Merge branch 'main' into modernize-type-check
This commit is contained in:
@@ -319,6 +319,7 @@ SET(Gui_UIC_SRCS
|
||||
PreferencePages/DlgSettingsEditor.ui
|
||||
PreferencePages/DlgSettingsGeneral.ui
|
||||
DlgSettingsImage.ui
|
||||
PreferencePages/DlgSettingsLightSources.ui
|
||||
PreferencePages/DlgSettingsMacro.ui
|
||||
PreferencePages/DlgSettingsNavigation.ui
|
||||
PreferencePages/DlgSettingsNotificationArea.ui
|
||||
@@ -565,6 +566,7 @@ SET(Dialog_Settings_CPP_SRCS
|
||||
PreferencePages/DlgSettingsEditor.cpp
|
||||
PreferencePages/DlgSettingsGeneral.cpp
|
||||
DlgSettingsImageImp.cpp
|
||||
PreferencePages/DlgSettingsLightSources.cpp
|
||||
PreferencePages/DlgSettingsMacroImp.cpp
|
||||
PreferencePages/DlgSettingsNavigation.cpp
|
||||
PreferencePages/DlgSettingsNotificationArea.cpp
|
||||
@@ -586,6 +588,7 @@ SET(Dialog_Settings_HPP_SRCS
|
||||
PreferencePages/DlgSettingsEditor.h
|
||||
PreferencePages/DlgSettingsGeneral.h
|
||||
DlgSettingsImageImp.h
|
||||
PreferencePages/DlgSettingsLightSources.h
|
||||
PreferencePages/DlgSettingsMacroImp.h
|
||||
PreferencePages/DlgSettingsNavigation.h
|
||||
PreferencePages/DlgSettingsNotificationArea.h
|
||||
@@ -609,6 +612,7 @@ SET(Dialog_Settings_SRCS
|
||||
PreferencePages/DlgSettingsEditor.ui
|
||||
PreferencePages/DlgSettingsGeneral.ui
|
||||
DlgSettingsImage.ui
|
||||
PreferencePages/DlgSettingsLightSources.ui
|
||||
PreferencePages/DlgSettingsMacro.ui
|
||||
PreferencePages/DlgSettingsNavigation.ui
|
||||
PreferencePages/DlgSettingsNotificationArea.ui
|
||||
@@ -835,6 +839,8 @@ SET(View3D_CPP_SRCS
|
||||
View3DPy.cpp
|
||||
View3DViewerPy.cpp
|
||||
NaviCube.cpp
|
||||
NavigationAnimator.cpp
|
||||
NavigationAnimation.cpp
|
||||
)
|
||||
SET(View3D_SRCS
|
||||
${View3D_CPP_SRCS}
|
||||
@@ -857,6 +863,8 @@ SET(View3D_SRCS
|
||||
CoinRiftWidget.h
|
||||
View3DViewerPy.h
|
||||
NaviCube.h
|
||||
NavigationAnimator.h
|
||||
NavigationAnimation.h
|
||||
)
|
||||
SOURCE_GROUP("View3D" FILES ${View3D_SRCS})
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ void DemoMode::reset()
|
||||
view->getViewer()->stopAnimating();
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/View");
|
||||
hGrp->Notify("UseAutoRotation");
|
||||
hGrp->Notify("UseNavigationAnimations");
|
||||
}
|
||||
|
||||
void DemoMode::accept()
|
||||
@@ -150,7 +150,7 @@ Gui::View3DInventor* DemoMode::activeView() const
|
||||
|
||||
float DemoMode::getSpeed(int v) const
|
||||
{
|
||||
float speed = (static_cast<float>(v)) / 50.0f; // let 2.0 be the maximum speed
|
||||
float speed = (static_cast<float>(v)) / 10.0f; // let 10.0 be the maximum speed
|
||||
return speed;
|
||||
}
|
||||
|
||||
@@ -273,8 +273,9 @@ void DemoMode::startAnimation(Gui::View3DInventor* view)
|
||||
{
|
||||
if (!view->getViewer()->isAnimationEnabled())
|
||||
view->getViewer()->setAnimationEnabled(true);
|
||||
view->getViewer()->startAnimating(getDirection(view),
|
||||
getSpeed(ui->speedSlider->value()));
|
||||
|
||||
view->getViewer()->startSpinningAnimation(getDirection(view),
|
||||
getSpeed(ui->speedSlider->value()));
|
||||
}
|
||||
|
||||
void DemoMode::onTimerCheckToggled(bool on)
|
||||
|
||||
@@ -1821,7 +1821,6 @@ MDIView *Document::createView(const Base::Type& typeId)
|
||||
|
||||
view3D->setWindowTitle(title);
|
||||
view3D->setWindowModified(this->isModified());
|
||||
view3D->setWindowIcon(QApplication::windowIcon());
|
||||
view3D->resize(400, 300);
|
||||
|
||||
if (!cameraSettings.empty()) {
|
||||
|
||||
@@ -51,6 +51,7 @@ EditableDatumLabel::EditableDatumLabel(View3DInventorViewer* view,
|
||||
: isSet(false)
|
||||
, autoDistance(autoDistance)
|
||||
, autoDistanceReverse(false)
|
||||
, value(0.0)
|
||||
, viewer(view)
|
||||
, spinBox(nullptr)
|
||||
, cameraSensor(nullptr)
|
||||
@@ -94,7 +95,7 @@ EditableDatumLabel::~EditableDatumLabel()
|
||||
|
||||
void EditableDatumLabel::activate()
|
||||
{
|
||||
if (!viewer) {
|
||||
if (!viewer || isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -130,8 +131,12 @@ void EditableDatumLabel::deactivate()
|
||||
}
|
||||
}
|
||||
|
||||
void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj)
|
||||
void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj, bool visibleToMouse)
|
||||
{
|
||||
if (isInEdit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget* mdi = viewer->parentWidget();
|
||||
|
||||
label->string = " ";
|
||||
@@ -147,6 +152,10 @@ void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj)
|
||||
spinBox->installEventFilter(eventFilteringObj);
|
||||
}
|
||||
|
||||
if (!visibleToMouse) {
|
||||
setSpinboxVisibleToMouse(visibleToMouse);
|
||||
}
|
||||
|
||||
spinBox->show();
|
||||
setSpinboxValue(val);
|
||||
//Note: adjustSize apparently uses the Min/Max values to set the size. So if we don't set them to INT_MAX, the spinbox are much too big.
|
||||
@@ -156,6 +165,7 @@ void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj)
|
||||
connect(spinBox, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, [this](double value) {
|
||||
this->isSet = true;
|
||||
this->value = value;
|
||||
Q_EMIT this->valueChanged(value);
|
||||
});
|
||||
}
|
||||
@@ -163,20 +173,35 @@ void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj)
|
||||
void EditableDatumLabel::stopEdit()
|
||||
{
|
||||
if (spinBox) {
|
||||
// write the spinbox value in the label.
|
||||
Base::Quantity quantity = spinBox->value();
|
||||
|
||||
double factor{};
|
||||
QString unitStr;
|
||||
QString valueStr;
|
||||
valueStr = quantity.getUserString(factor, unitStr);
|
||||
label->string = SbString(valueStr.toUtf8().constData());
|
||||
|
||||
spinBox->deleteLater();
|
||||
spinBox = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool EditableDatumLabel::isInEdit()
|
||||
bool EditableDatumLabel::isActive() const
|
||||
{
|
||||
return spinBox;
|
||||
return cameraSensor != nullptr;
|
||||
}
|
||||
|
||||
bool EditableDatumLabel::isInEdit() const
|
||||
{
|
||||
return spinBox != nullptr;
|
||||
}
|
||||
|
||||
|
||||
double EditableDatumLabel::getValue()
|
||||
double EditableDatumLabel::getValue() const
|
||||
{
|
||||
return spinBox->rawValue();
|
||||
// We use value rather than spinBox->rawValue() in case edit stopped.
|
||||
return value;
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setSpinboxValue(double val, const Base::Unit& unit)
|
||||
@@ -188,6 +213,7 @@ void EditableDatumLabel::setSpinboxValue(double val, const Base::Unit& unit)
|
||||
|
||||
QSignalBlocker block(spinBox);
|
||||
spinBox->setValue(Base::Quantity(val, unit));
|
||||
value = val;
|
||||
positionSpinbox();
|
||||
|
||||
if (spinBox->hasFocus()) {
|
||||
@@ -311,11 +337,13 @@ void EditableDatumLabel::setLabelDistance(double val)
|
||||
label->param1 = float(val);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
void EditableDatumLabel::setLabelStartAngle(double val)
|
||||
{
|
||||
label->param2 = float(val);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
void EditableDatumLabel::setLabelRange(double val)
|
||||
{
|
||||
label->param3 = float(val);
|
||||
@@ -340,9 +368,9 @@ void EditableDatumLabel::setLabelAutoDistanceReverse(bool val)
|
||||
autoDistanceReverse = val;
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setSpinboxInvisibleToMouse(bool val)
|
||||
void EditableDatumLabel::setSpinboxVisibleToMouse(bool val)
|
||||
{
|
||||
spinBox->setAttribute(Qt::WA_TransparentForMouseEvents, val);
|
||||
spinBox->setAttribute(Qt::WA_TransparentForMouseEvents, !val);
|
||||
}
|
||||
|
||||
#include "moc_EditableDatumLabel.cpp"
|
||||
|
||||
@@ -51,10 +51,11 @@ public:
|
||||
void activate();
|
||||
void deactivate();
|
||||
|
||||
void startEdit(double val, QObject* eventFilteringObj = nullptr);
|
||||
void startEdit(double val, QObject* eventFilteringObj = nullptr, bool visibleToMouse = false);
|
||||
void stopEdit();
|
||||
bool isInEdit();
|
||||
double getValue();
|
||||
bool isActive() const;
|
||||
bool isInEdit() const;
|
||||
double getValue() const;
|
||||
void setSpinboxValue(double val, const Base::Unit& unit = Base::Unit::Length);
|
||||
void setPlacement(const Base::Placement& plc);
|
||||
void setColor(SbColor color);
|
||||
@@ -68,13 +69,14 @@ public:
|
||||
void setLabelRange(double val);
|
||||
void setLabelRecommendedDistance();
|
||||
void setLabelAutoDistanceReverse(bool val);
|
||||
void setSpinboxInvisibleToMouse(bool val);
|
||||
void setSpinboxVisibleToMouse(bool val);
|
||||
|
||||
// NOLINTBEGIN
|
||||
SoDatumLabel* label;
|
||||
bool isSet;
|
||||
bool autoDistance;
|
||||
bool autoDistanceReverse;
|
||||
double value;
|
||||
// NOLINTEND
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
#include <Inventor/details/SoPointDetail.h>
|
||||
|
||||
#include <Inventor/draggers/SoCenterballDragger.h>
|
||||
#include <Inventor/draggers/SoDirectionalLightDragger.h>
|
||||
#include <Inventor/draggers/SoDragger.h>
|
||||
#include <Inventor/draggers/SoTrackballDragger.h>
|
||||
#include <Inventor/draggers/SoTransformerDragger.h>
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2023 Bas Ruigrok (Rexbas) <[email protected]> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include "NavigationAnimation.h"
|
||||
#include <Inventor/nodes/SoCamera.h>
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
NavigationAnimation::NavigationAnimation(NavigationStyle* navigation)
|
||||
: navigation(navigation)
|
||||
{}
|
||||
|
||||
void NavigationAnimation::updateCurrentValue(const QVariant& value)
|
||||
{
|
||||
if (state() == QAbstractAnimation::State::Stopped) {
|
||||
return;
|
||||
}
|
||||
update(value);
|
||||
}
|
||||
|
||||
void NavigationAnimation::onStop([[maybe_unused]] bool finished)
|
||||
{}
|
||||
|
||||
FixedTimeAnimation::FixedTimeAnimation(NavigationStyle* navigation, const SbRotation& orientation,
|
||||
const SbVec3f& rotationCenter, const SbVec3f& translation,
|
||||
int duration)
|
||||
: NavigationAnimation(navigation)
|
||||
, targetOrientation(orientation)
|
||||
, targetTranslation(translation)
|
||||
, rotationCenter(rotationCenter)
|
||||
{
|
||||
setDuration(duration);
|
||||
setStartValue(0.0);
|
||||
setEndValue(duration * 1.0);
|
||||
}
|
||||
|
||||
void FixedTimeAnimation::initialize()
|
||||
{
|
||||
prevAngle = 0;
|
||||
prevTranslation = SbVec3f(0, 0, 0);
|
||||
|
||||
// Find an axis and angle to rotate from the camera orientation to the target orientation using post-multiplication
|
||||
SbVec3f rotationAxisPost;
|
||||
float angle;
|
||||
SbRotation(navigation->getCamera()->orientation.getValue().inverse() * targetOrientation).getValue(rotationAxisPost, angle);
|
||||
if (angle > M_PI) {
|
||||
angle -= 2 * M_PI;
|
||||
}
|
||||
|
||||
// Convert post-multiplication axis to a pre-multiplication axis
|
||||
navigation->getCamera()->orientation.getValue().inverse().multVec(rotationAxisPost, rotationAxis);
|
||||
|
||||
angularVelocity = angle / duration();
|
||||
linearVelocity = targetTranslation / duration();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The elapsed time
|
||||
*/
|
||||
void FixedTimeAnimation::update(const QVariant& value)
|
||||
{
|
||||
SoCamera* camera = navigation->getCamera();
|
||||
if (!camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
float angle = value.toFloat() * angularVelocity;
|
||||
SbVec3f translation = value.toFloat() * linearVelocity;
|
||||
|
||||
SbRotation rotation(rotationAxis, angle - prevAngle);
|
||||
|
||||
camera->position = camera->position.getValue() - prevTranslation;
|
||||
navigation->reorientCamera(camera, rotation, rotationCenter);
|
||||
camera->position = camera->position.getValue() + translation;
|
||||
|
||||
prevAngle = angle;
|
||||
prevTranslation = translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param finished True when the animation is finished, false when interrupted
|
||||
*/
|
||||
void FixedTimeAnimation::onStop(bool finished)
|
||||
{
|
||||
if (finished) {
|
||||
SoCamera* camera = navigation->getCamera();
|
||||
if (!camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set exact target orientation
|
||||
camera->orientation = targetOrientation;
|
||||
camera->position = camera->position.getValue() + targetTranslation - prevTranslation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param navigation The navigation style
|
||||
* @param axis The rotation axis in screen coordinates
|
||||
* @param velocity The angular velocity in radians per second
|
||||
*/
|
||||
SpinningAnimation::SpinningAnimation(NavigationStyle* navigation, const SbVec3f& axis,
|
||||
float velocity)
|
||||
: NavigationAnimation(navigation)
|
||||
, rotationAxis(axis)
|
||||
{
|
||||
setDuration((2 * M_PI / velocity) * 1000.0);
|
||||
setStartValue(0.0);
|
||||
setEndValue(2 * M_PI);
|
||||
setLoopCount(-1);
|
||||
}
|
||||
|
||||
void SpinningAnimation::initialize()
|
||||
{
|
||||
prevAngle = 0;
|
||||
|
||||
navigation->setViewing(true);
|
||||
navigation->setViewingMode(NavigationStyle::SPINNING);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The angle in radians
|
||||
*/
|
||||
void SpinningAnimation::update(const QVariant& value)
|
||||
{
|
||||
SoCamera* camera = navigation->getCamera();
|
||||
if (!camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
SbRotation deltaRotation = SbRotation(rotationAxis, value.toFloat() - prevAngle);
|
||||
navigation->reorientCamera(camera, deltaRotation);
|
||||
|
||||
prevAngle = value.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param finished True when the animation is finished, false when interrupted
|
||||
*/
|
||||
void SpinningAnimation::onStop([[maybe_unused]] bool finished)
|
||||
{
|
||||
if (navigation->getViewingMode() != NavigationStyle::SPINNING) {
|
||||
return;
|
||||
}
|
||||
navigation->setViewingMode(navigation->isViewing() ? NavigationStyle::IDLE : NavigationStyle::INTERACT);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2023 Bas Ruigrok (Rexbas) <[email protected]> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GUI_NAVIGATIONANIMATION_H
|
||||
#define GUI_NAVIGATIONANIMATION_H
|
||||
|
||||
#include "NavigationStyle.h"
|
||||
#include <Inventor/SbRotation.h>
|
||||
#include <Inventor/SbVec3f.h>
|
||||
#include <QVariantAnimation>
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
|
||||
class GuiExport NavigationAnimation : protected QVariantAnimation
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NavigationAnimation(NavigationStyle* navigation);
|
||||
|
||||
Q_SIGNALS:
|
||||
void interrupted();
|
||||
|
||||
protected:
|
||||
NavigationStyle* navigation;
|
||||
|
||||
virtual void initialize() = 0;
|
||||
virtual void update(const QVariant& value) = 0;
|
||||
virtual void onStop(bool finished);
|
||||
|
||||
private:
|
||||
void updateCurrentValue(const QVariant& value) override;
|
||||
|
||||
friend class NavigationAnimator;
|
||||
friend class QObject;
|
||||
};
|
||||
|
||||
class GuiExport FixedTimeAnimation : public NavigationAnimation
|
||||
{
|
||||
public:
|
||||
explicit FixedTimeAnimation(NavigationStyle* navigation, const SbRotation& orientation,
|
||||
const SbVec3f& rotationCenter, const SbVec3f& translation,
|
||||
int duration);
|
||||
|
||||
private:
|
||||
float angularVelocity; // [rad/ms]
|
||||
SbVec3f linearVelocity; // [/ms]
|
||||
|
||||
SbRotation targetOrientation;
|
||||
SbVec3f targetTranslation;
|
||||
|
||||
float prevAngle;
|
||||
SbVec3f prevTranslation;
|
||||
|
||||
SbVec3f rotationCenter;
|
||||
SbVec3f rotationAxis;
|
||||
|
||||
void initialize() override;
|
||||
void update(const QVariant& value) override;
|
||||
void onStop(bool finished) override;
|
||||
};
|
||||
|
||||
class GuiExport SpinningAnimation : public NavigationAnimation
|
||||
{
|
||||
public:
|
||||
explicit SpinningAnimation(NavigationStyle* navigation, const SbVec3f& axis, float velocity);
|
||||
|
||||
private:
|
||||
SbVec3f rotationAxis;
|
||||
float prevAngle;
|
||||
|
||||
void initialize() override;
|
||||
void update(const QVariant& value) override;
|
||||
void onStop(bool finished) override;
|
||||
};
|
||||
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_NAVIGATIONANIMATION_H
|
||||
@@ -0,0 +1,92 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2023 Bas Ruigrok (Rexbas) <[email protected]> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include "NavigationAnimator.h"
|
||||
#include "NavigationAnimation.h"
|
||||
#include <QEventLoop>
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
NavigationAnimator::NavigationAnimator()
|
||||
: activeAnimation(nullptr)
|
||||
{}
|
||||
|
||||
NavigationAnimator::~NavigationAnimator()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start an animation
|
||||
*
|
||||
* @param animation The animation to start
|
||||
*/
|
||||
void NavigationAnimator::start(const std::shared_ptr<NavigationAnimation>& animation)
|
||||
{
|
||||
stop();
|
||||
activeAnimation = animation;
|
||||
activeAnimation->initialize();
|
||||
|
||||
connect(activeAnimation.get(), &NavigationAnimation::finished, this, [this]() {
|
||||
activeAnimation->onStop(true);
|
||||
activeAnimation.reset();
|
||||
});
|
||||
|
||||
activeAnimation->start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start an animation and wait for it to finish
|
||||
*
|
||||
* @param animation The animation to start
|
||||
* @return True if the animation finished, false if interrupted
|
||||
*/
|
||||
bool NavigationAnimator::startAndWait(const std::shared_ptr<NavigationAnimation>& animation)
|
||||
{
|
||||
stop();
|
||||
bool finished = true;
|
||||
QEventLoop loop;
|
||||
connect(animation.get(), &NavigationAnimation::finished, &loop, &QEventLoop::quit);
|
||||
connect(animation.get(), &NavigationAnimation::interrupted, &loop, [&finished, &loop]() {
|
||||
finished = false;
|
||||
loop.quit();
|
||||
});
|
||||
start(animation);
|
||||
loop.exec();
|
||||
return finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an active animation and releases shared ownership of the animation
|
||||
*/
|
||||
void NavigationAnimator::stop()
|
||||
{
|
||||
if (activeAnimation && activeAnimation->state() != QAbstractAnimation::State::Stopped) {
|
||||
disconnect(activeAnimation.get(), &NavigationAnimation::finished, 0, 0);
|
||||
Q_EMIT activeAnimation->interrupted();
|
||||
activeAnimation->stop();
|
||||
activeAnimation->onStop(false);
|
||||
activeAnimation.reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2023 Bas Ruigrok (Rexbas) <[email protected]> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GUI_NAVIGATIONANIMATOR_H
|
||||
#define GUI_NAVIGATIONANIMATOR_H
|
||||
|
||||
#include "NavigationStyle.h"
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
|
||||
class NavigationAnimation;
|
||||
|
||||
class GuiExport NavigationAnimator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NavigationAnimator();
|
||||
~NavigationAnimator();
|
||||
void start(const std::shared_ptr<NavigationAnimation>& animation);
|
||||
bool startAndWait(const std::shared_ptr<NavigationAnimation>& animation);
|
||||
void stop();
|
||||
|
||||
private:
|
||||
std::shared_ptr<NavigationAnimation> activeAnimation;
|
||||
};
|
||||
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_NAVIGATIONANIMATOR_H
|
||||
+120
-253
@@ -45,40 +45,13 @@
|
||||
#include "Application.h"
|
||||
#include "MenuManager.h"
|
||||
#include "MouseSelection.h"
|
||||
#include "NavigationAnimator.h"
|
||||
#include "NavigationAnimation.h"
|
||||
#include "SoMouseWheelEvent.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
namespace Gui {
|
||||
struct NavigationStyleP {
|
||||
int animationsteps;
|
||||
int animationdelta;
|
||||
SbVec3f focal1, focal2;
|
||||
SbVec3f rotationCenter;
|
||||
SbBool rotationCenterFound;
|
||||
NavigationStyle::RotationCenterModes rotationCenterMode;
|
||||
SbRotation endRotation;
|
||||
SoTimerSensor * animsensor;
|
||||
float sensitivity;
|
||||
SbBool resetcursorpos;
|
||||
|
||||
NavigationStyleP()
|
||||
{
|
||||
this->animationsteps = 0;
|
||||
this->animationdelta = 0;
|
||||
this->animsensor = nullptr;
|
||||
this->sensitivity = 2.0f;
|
||||
this->resetcursorpos = false;
|
||||
this->rotationCenterFound = false;
|
||||
this->rotationCenterMode = NavigationStyle::RotationCenterMode::ScenePointAtCursor |
|
||||
NavigationStyle::RotationCenterMode::FocalPointAtCursor;
|
||||
}
|
||||
static void viewAnimationCB(void * data, SoSensor * sensor);
|
||||
};
|
||||
}
|
||||
|
||||
class FCSphereSheetProjector : public SbSphereSheetProjector {
|
||||
using inherited = SbSphereSheetProjector;
|
||||
|
||||
@@ -184,25 +157,19 @@ const Base::Type& NavigationStyleEvent::style() const
|
||||
return t;
|
||||
}
|
||||
|
||||
#define PRIVATE(ptr) (ptr->pimpl)
|
||||
#define PUBLIC(ptr) (ptr->pub)
|
||||
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Gui::NavigationStyle,Base::BaseClass)
|
||||
|
||||
NavigationStyle::NavigationStyle() : viewer(nullptr), mouseSelection(nullptr)
|
||||
{
|
||||
PRIVATE(this) = new NavigationStyleP();
|
||||
PRIVATE(this)->animsensor = new SoTimerSensor(NavigationStyleP::viewAnimationCB, this);
|
||||
this->rotationCenterMode = NavigationStyle::RotationCenterMode::ScenePointAtCursor
|
||||
| NavigationStyle::RotationCenterMode::FocalPointAtCursor;
|
||||
initialize();
|
||||
}
|
||||
|
||||
NavigationStyle::~NavigationStyle()
|
||||
{
|
||||
finalize();
|
||||
if (PRIVATE(this)->animsensor->isScheduled())
|
||||
PRIVATE(this)->animsensor->unschedule();
|
||||
delete PRIVATE(this)->animsensor;
|
||||
delete PRIVATE(this);
|
||||
delete this->animator;
|
||||
}
|
||||
|
||||
NavigationStyle& NavigationStyle::operator = (const NavigationStyle& ns)
|
||||
@@ -222,12 +189,15 @@ void NavigationStyle::setViewer(View3DInventorViewer* view)
|
||||
|
||||
void NavigationStyle::initialize()
|
||||
{
|
||||
this->animator = new NavigationAnimator();
|
||||
|
||||
this->sensitivity = 2.0f;
|
||||
this->resetcursorpos = false;
|
||||
this->currentmode = NavigationStyle::IDLE;
|
||||
this->prevRedrawTime = SbTime::getTimeOfDay();
|
||||
this->spinanimatingallowed = true;
|
||||
this->spinsamplecounter = 0;
|
||||
this->spinincrement = SbRotation::identity();
|
||||
this->spinRotation.setValue(SbVec3f(0, 0, -1), 0);
|
||||
this->rotationCenterFound = false;
|
||||
|
||||
// FIXME: use a smaller sphere than the default one to have a larger
|
||||
// area close to the borders that gives us "z-axis rotation"?
|
||||
@@ -357,167 +327,72 @@ SbBool NavigationStyle::lookAtPoint(const SbVec2s screenpos)
|
||||
return true;
|
||||
}
|
||||
|
||||
void NavigationStyle::lookAtPoint(const SbVec3f& pos)
|
||||
void NavigationStyle::lookAtPoint(const SbVec3f& position)
|
||||
{
|
||||
SoCamera* cam = viewer->getSoRenderManager()->getCamera();
|
||||
if (!cam)
|
||||
return;
|
||||
PRIVATE(this)->rotationCenterFound = false;
|
||||
|
||||
// Find global coordinates of focal point.
|
||||
SbVec3f direction;
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
PRIVATE(this)->focal1 = cam->position.getValue() +
|
||||
cam->focalDistance.getValue() * direction;
|
||||
PRIVATE(this)->focal2 = pos;
|
||||
|
||||
// avoid to interfere with spinning (fixes #3101462)
|
||||
if (this->isAnimating())
|
||||
this->stopAnimating();
|
||||
|
||||
if (PRIVATE(this)->animsensor->isScheduled()) {
|
||||
PRIVATE(this)->animsensor->unschedule();
|
||||
this->interactiveCountDec();
|
||||
}
|
||||
|
||||
if (isAnimationEnabled()) {
|
||||
SbRotation cam_rot = cam->orientation.getValue();
|
||||
// get the amount of movement
|
||||
SbVec3f dir1 = direction, dir2;
|
||||
dir2 = pos - cam->position.getValue();
|
||||
dir2.normalize();
|
||||
SbRotation rot(dir1, dir2);
|
||||
float val = 0.5f*(1.0f + dir1.dot(dir2)); // value in range [0,1]
|
||||
int div = (int)(val * 20.0f);
|
||||
int steps = 20-div; // do it with max. 20 steps
|
||||
|
||||
// check whether a movement is required
|
||||
if (steps > 0) {
|
||||
PRIVATE(this)->endRotation = cam_rot;
|
||||
this->spinRotation = cam_rot;
|
||||
PRIVATE(this)->animationsteps = 5;
|
||||
PRIVATE(this)->animationdelta = std::max<int>(100/steps, 5);
|
||||
PRIVATE(this)->animsensor->setBaseTime(SbTime::getTimeOfDay());
|
||||
PRIVATE(this)->animsensor->schedule();
|
||||
this->interactiveCountInc();
|
||||
}
|
||||
else {
|
||||
// set to the given position
|
||||
SbVec3f direction;
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
cam->position = pos - cam->focalDistance.getValue() * direction;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set to the given position
|
||||
SbVec3f direction;
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
cam->position = pos - cam->focalDistance.getValue() * direction;
|
||||
}
|
||||
this->rotationCenterFound = false;
|
||||
translateCamera(position - getFocalPoint());
|
||||
}
|
||||
|
||||
void NavigationStyle::setCameraOrientation(const SbRotation& rot, SbBool moveToCenter)
|
||||
SoCamera* NavigationStyle::getCamera() const
|
||||
{
|
||||
SoCamera* cam = viewer->getSoRenderManager()->getCamera();
|
||||
if (!cam)
|
||||
return this->viewer->getCamera();
|
||||
}
|
||||
|
||||
void NavigationStyle::setCameraOrientation(const SbRotation& orientation, SbBool moveToCenter)
|
||||
{
|
||||
SoCamera* camera = getCamera();
|
||||
if (!camera)
|
||||
return;
|
||||
|
||||
// Find global coordinates of focal point.
|
||||
SbVec3f direction;
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
PRIVATE(this)->focal1 = cam->position.getValue() +
|
||||
cam->focalDistance.getValue() * direction;
|
||||
PRIVATE(this)->focal2 = PRIVATE(this)->focal1;
|
||||
animator->stop();
|
||||
|
||||
SbVec3f focalPoint = getFocalPoint();
|
||||
SbVec3f translation(0, 0, 0);
|
||||
|
||||
if (moveToCenter) {
|
||||
SoGetBoundingBoxAction action(viewer->getSoRenderManager()->getViewportRegion());
|
||||
action.apply(viewer->getSceneGraph());
|
||||
SbBox3f box = action.getBoundingBox();
|
||||
if (!box.isEmpty()) {
|
||||
rot.multVec(SbVec3f(0, 0, -1), direction);
|
||||
//float s = (this->focal1 - box.getCenter()).dot(direction);
|
||||
//this->focal2 = box.getCenter() + s * direction;
|
||||
// setting the center of the overall bounding box as the future focal point
|
||||
// seems to be a satisfactory solution
|
||||
PRIVATE(this)->focal2 = box.getCenter();
|
||||
translation = box.getCenter() - focalPoint;
|
||||
}
|
||||
}
|
||||
|
||||
// avoid to interfere with spinning (fixes #3101462)
|
||||
if (this->isAnimating())
|
||||
this->stopAnimating();
|
||||
|
||||
if (PRIVATE(this)->animsensor->isScheduled()) {
|
||||
PRIVATE(this)->animsensor->unschedule();
|
||||
this->interactiveCountDec();
|
||||
}
|
||||
|
||||
// Start an animation or set the pose directly
|
||||
if (isAnimationEnabled()) {
|
||||
// get the amount of movement
|
||||
SbVec3f dir1, dir2;
|
||||
SbRotation cam_rot = cam->orientation.getValue();
|
||||
cam_rot.multVec(SbVec3f(0, 0, -1), dir1);
|
||||
rot.multVec(SbVec3f(0, 0, -1), dir2);
|
||||
float val = 0.5f*(1.0f + dir1.dot(dir2)); // value in range [0,1]
|
||||
int div = (int)(val * 20.0f);
|
||||
int steps = 20-div; // do it with max. 20 steps
|
||||
|
||||
// check whether a movement is required
|
||||
if (steps > 0) {
|
||||
PRIVATE(this)->endRotation = rot; // this is the final camera orientation
|
||||
this->spinRotation = cam_rot;
|
||||
PRIVATE(this)->animationsteps = 5;
|
||||
PRIVATE(this)->animationdelta = std::max<int>(100/steps, 5);
|
||||
PRIVATE(this)->animsensor->setBaseTime(SbTime::getTimeOfDay());
|
||||
PRIVATE(this)->animsensor->schedule();
|
||||
this->interactiveCountInc();
|
||||
}
|
||||
else {
|
||||
// due to possible round-off errors make sure that the
|
||||
// exact orientation is set
|
||||
cam->orientation.setValue(rot);
|
||||
cam->position = PRIVATE(this)->focal2 - cam->focalDistance.getValue() * direction;
|
||||
}
|
||||
viewer->startAnimation(orientation, focalPoint, translation);
|
||||
}
|
||||
else {
|
||||
// set to the given rotation
|
||||
cam->orientation.setValue(rot);
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
cam->position = PRIVATE(this)->focal2 - cam->focalDistance.getValue() * direction;
|
||||
// Distance from rotation center to camera position in camera coordinate system
|
||||
SbVec3f rotationCenterDistanceCam = camera->focalDistance.getValue() * SbVec3f(0, 0, 1);
|
||||
|
||||
// Set to the given orientation
|
||||
camera->orientation = orientation;
|
||||
|
||||
// Distance from rotation center to new camera position in global coordinate system
|
||||
SbVec3f newRotationCenterDistance;
|
||||
camera->orientation.getValue().multVec(rotationCenterDistanceCam, newRotationCenterDistance);
|
||||
|
||||
// Reposition camera so the rotation center stays in the same place
|
||||
// Optionally add translation to move to center
|
||||
camera->position = focalPoint + newRotationCenterDistance + translation;
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationStyleP::viewAnimationCB(void * data, SoSensor * sensor)
|
||||
void NavigationStyle::translateCamera(const SbVec3f& translation)
|
||||
{
|
||||
Q_UNUSED(sensor);
|
||||
auto that = static_cast<NavigationStyle*>(data);
|
||||
if (PRIVATE(that)->animationsteps > 0) {
|
||||
// here the camera rotates from the current rotation to a given
|
||||
// rotation (e.g. the standard views). To get this movement animated
|
||||
// we calculate an interpolated rotation and update the view after
|
||||
// each step
|
||||
float step = std::min<float>((float)PRIVATE(that)->animationsteps/100.0f, 1.0f);
|
||||
SbRotation slerp = SbRotation::slerp(that->spinRotation, PRIVATE(that)->endRotation, step);
|
||||
SbVec3f focalpoint = (1.0f-step)*PRIVATE(that)->focal1 + step*PRIVATE(that)->focal2;
|
||||
SoCamera* cam = that->viewer->getSoRenderManager()->getCamera();
|
||||
if (!cam) // no camera
|
||||
return;
|
||||
SoCamera* camera = getCamera();
|
||||
if (!camera)
|
||||
return;
|
||||
|
||||
SbVec3f direction;
|
||||
cam->orientation.setValue(slerp);
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
cam->position = focalpoint - cam->focalDistance.getValue() * direction;
|
||||
animator->stop();
|
||||
|
||||
PRIVATE(that)->animationsteps += PRIVATE(that)->animationdelta;
|
||||
if (PRIVATE(that)->animationsteps > 100) {
|
||||
// now we have reached the end of the movement
|
||||
PRIVATE(that)->animationsteps=0;
|
||||
PRIVATE(that)->animsensor->unschedule();
|
||||
that->interactiveCountDec();
|
||||
// set to the actual given rotation
|
||||
cam->orientation.setValue(PRIVATE(that)->endRotation);
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
cam->position = PRIVATE(that)->focal2 - cam->focalDistance.getValue() * direction;
|
||||
}
|
||||
// Start an animation or set the pose directly
|
||||
if (isAnimationEnabled()) {
|
||||
viewer->startAnimation(camera->orientation.getValue(), SbVec3f(0, 0, 0), translation);
|
||||
}
|
||||
else {
|
||||
camera->position = camera->position.getValue() + translation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,29 +479,41 @@ void NavigationStyle::viewAll()
|
||||
}
|
||||
}
|
||||
|
||||
/** Rotate the camera by the given amount, then reposition it so we're
|
||||
* still pointing at the same focal point.
|
||||
/** Rotate the camera by the given amount, then reposition it so we're still pointing at the same
|
||||
* focal point
|
||||
*/
|
||||
void NavigationStyle::reorientCamera(SoCamera * cam, const SbRotation & rot)
|
||||
void NavigationStyle::reorientCamera(SoCamera* camera, const SbRotation& rotation)
|
||||
{
|
||||
if (!cam)
|
||||
reorientCamera(camera, rotation, getFocalPoint());
|
||||
}
|
||||
|
||||
/** Rotate the camera by the given amount, then reposition it so the rotation center stays in the
|
||||
* same place
|
||||
*/
|
||||
void NavigationStyle::reorientCamera(SoCamera* camera, const SbRotation& rotation, const SbVec3f& rotationCenter)
|
||||
{
|
||||
if (!camera) {
|
||||
return;
|
||||
|
||||
// Find global coordinates of focal point.
|
||||
SbVec3f direction;
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
SbVec3f focalpoint = cam->position.getValue() +
|
||||
cam->focalDistance.getValue() * direction;
|
||||
|
||||
// Set new orientation value by accumulating the new rotation.
|
||||
cam->orientation = rot * cam->orientation.getValue();
|
||||
// Fix issue with near clipping in orthogonal view
|
||||
if (cam->getTypeId().isDerivedFrom(SoOrthographicCamera::getClassTypeId())) {
|
||||
cam->focalDistance = static_cast<SoOrthographicCamera*>(cam)->height;
|
||||
}
|
||||
// Reposition camera so we are still pointing at the same old focal point.
|
||||
cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
|
||||
cam->position = focalpoint - cam->focalDistance.getValue() * direction;
|
||||
|
||||
// Distance from rotation center to camera position in camera coordinate system
|
||||
SbVec3f rotationCenterDistanceCam;
|
||||
camera->orientation.getValue().inverse().multVec(camera->position.getValue() - rotationCenter, rotationCenterDistanceCam);
|
||||
|
||||
// Set new orientation value by accumulating the new rotation
|
||||
camera->orientation = rotation * camera->orientation.getValue();
|
||||
|
||||
// Fix issue with near clipping in orthogonal view
|
||||
if (camera->getTypeId().isDerivedFrom(SoOrthographicCamera::getClassTypeId())) {
|
||||
camera->focalDistance = static_cast<SoOrthographicCamera*>(camera)->height;
|
||||
}
|
||||
|
||||
// Distance from rotation center to new camera position in global coordinate system
|
||||
SbVec3f newRotationCenterDistance;
|
||||
camera->orientation.getValue().multVec(rotationCenterDistanceCam, newRotationCenterDistance);
|
||||
|
||||
// Reposition camera so the rotation center stays in the same place
|
||||
camera->position = rotationCenter + newRotationCenterDistance;
|
||||
}
|
||||
|
||||
void NavigationStyle::panCamera(SoCamera * cam, float aspectratio, const SbPlane & panplane,
|
||||
@@ -684,7 +571,7 @@ void NavigationStyle::panToCenter(const SbPlane & pplane, const SbVec2f & currpo
|
||||
const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
|
||||
float ratio = vp.getViewportAspectRatio();
|
||||
panCamera(viewer->getSoRenderManager()->getCamera(), ratio, pplane, SbVec2f(0.5,0.5), currpos);
|
||||
PRIVATE(this)->rotationCenterFound = false;
|
||||
this->rotationCenterFound = false;
|
||||
}
|
||||
|
||||
/** Dependent on the camera type this will either shrink or expand the
|
||||
@@ -695,6 +582,9 @@ void NavigationStyle::zoom(SoCamera * cam, float diffvalue)
|
||||
{
|
||||
if (!cam) // can happen for empty scenegraph
|
||||
return;
|
||||
|
||||
animator->stop();
|
||||
|
||||
SoType t = cam->getTypeId();
|
||||
SbName tname = t.getName();
|
||||
|
||||
@@ -862,14 +752,14 @@ void NavigationStyle::doRotate(SoCamera * camera, float angle, const SbVec2f& po
|
||||
|
||||
SbVec3f NavigationStyle::getRotationCenter(SbBool& found) const
|
||||
{
|
||||
found = PRIVATE(this)->rotationCenterFound;
|
||||
return PRIVATE(this)->rotationCenter;
|
||||
found = this->rotationCenterFound;
|
||||
return this->rotationCenter;
|
||||
}
|
||||
|
||||
void NavigationStyle::setRotationCenter(const SbVec3f& cnt)
|
||||
{
|
||||
PRIVATE(this)->rotationCenter = cnt;
|
||||
PRIVATE(this)->rotationCenterFound = true;
|
||||
this->rotationCenter = cnt;
|
||||
this->rotationCenterFound = true;
|
||||
}
|
||||
|
||||
SbVec3f NavigationStyle::getFocalPoint() const
|
||||
@@ -901,8 +791,8 @@ void NavigationStyle::spin(const SbVec2f & pointerpos)
|
||||
lastpos[0] = float(this->log.position[1][0]) / float(std::max((int)(glsize[0]-1), 1));
|
||||
lastpos[1] = float(this->log.position[1][1]) / float(std::max((int)(glsize[1]-1), 1));
|
||||
|
||||
if (PRIVATE(this)->rotationCenterMode && PRIVATE(this)->rotationCenterFound) {
|
||||
SbVec3f hitpoint = PRIVATE(this)->rotationCenter;
|
||||
if (this->rotationCenterMode && this->rotationCenterFound) {
|
||||
SbVec3f hitpoint = this->rotationCenter;
|
||||
|
||||
// set to the given position
|
||||
SbVec3f direction;
|
||||
@@ -929,7 +819,7 @@ void NavigationStyle::spin(const SbVec2f & pointerpos)
|
||||
r.invert();
|
||||
this->reorientCamera(viewer->getSoRenderManager()->getCamera(), r);
|
||||
|
||||
if (PRIVATE(this)->rotationCenterMode && PRIVATE(this)->rotationCenterFound) {
|
||||
if (this->rotationCenterMode && this->rotationCenterFound) {
|
||||
float ratio = vp.getViewportAspectRatio();
|
||||
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(vp.getViewportAspectRatio());
|
||||
SbPlane panplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
|
||||
@@ -1015,7 +905,7 @@ SbBool NavigationStyle::doSpin()
|
||||
float radians;
|
||||
rot.getValue(axis, radians);
|
||||
if ((radians > 0.01f) && (deltatime < 0.300)) {
|
||||
this->spinRotation = rot;
|
||||
viewer->startSpinningAnimation(axis, radians * 5);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1030,14 +920,14 @@ void NavigationStyle::saveCursorPosition(const SoEvent * const ev)
|
||||
this->localPos = ev->getPosition();
|
||||
|
||||
// mode is WindowCenter
|
||||
if (!PRIVATE(this)->rotationCenterMode) {
|
||||
if (!this->rotationCenterMode) {
|
||||
setRotationCenter(getFocalPoint());
|
||||
}
|
||||
|
||||
//Option to get point on model (slow) or always on focal plane (fast)
|
||||
//
|
||||
// mode is ScenePointAtCursor to get exact point if possible
|
||||
if (PRIVATE(this)->rotationCenterMode & NavigationStyle::RotationCenterMode::ScenePointAtCursor) {
|
||||
if (this->rotationCenterMode & NavigationStyle::RotationCenterMode::ScenePointAtCursor) {
|
||||
SoRayPickAction rpaction(viewer->getSoRenderManager()->getViewportRegion());
|
||||
rpaction.setPoint(this->localPos);
|
||||
rpaction.setRadius(viewer->getPickRadius());
|
||||
@@ -1051,7 +941,7 @@ void NavigationStyle::saveCursorPosition(const SoEvent * const ev)
|
||||
}
|
||||
|
||||
// mode is FocalPointAtCursor or a ScenePointAtCursor failed
|
||||
if (PRIVATE(this)->rotationCenterMode & NavigationStyle::RotationCenterMode::FocalPointAtCursor) {
|
||||
if (this->rotationCenterMode & NavigationStyle::RotationCenterMode::FocalPointAtCursor) {
|
||||
// get the intersection point of the ray and the focal plane
|
||||
const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
|
||||
float ratio = vp.getViewportAspectRatio();
|
||||
@@ -1072,7 +962,7 @@ void NavigationStyle::saveCursorPosition(const SoEvent * const ev)
|
||||
}
|
||||
|
||||
// mode is BoundingBoxCenter or a ScenePointAtCursor failed
|
||||
if (PRIVATE(this)->rotationCenterMode & NavigationStyle::RotationCenterMode::BoundingBoxCenter) {
|
||||
if (this->rotationCenterMode & NavigationStyle::RotationCenterMode::BoundingBoxCenter) {
|
||||
const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
|
||||
float ratio = vp.getViewportAspectRatio();
|
||||
|
||||
@@ -1128,20 +1018,6 @@ void NavigationStyle::moveCursorPosition()
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationStyle::updateAnimation()
|
||||
{
|
||||
SbTime now = SbTime::getTimeOfDay();
|
||||
double secs = now.getValue() - prevRedrawTime.getValue();
|
||||
this->prevRedrawTime = now;
|
||||
|
||||
if (this->isAnimating()) {
|
||||
// here the camera rotates around a fix axis
|
||||
SbRotation deltaRotation = this->spinRotation;
|
||||
deltaRotation.scaleAngle(secs * 5.0);
|
||||
this->reorientCamera(viewer->getSoRenderManager()->getCamera(), deltaRotation);
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationStyle::redraw()
|
||||
{
|
||||
if (mouseSelection)
|
||||
@@ -1168,7 +1044,7 @@ void
|
||||
NavigationStyle::setAnimationEnabled(const SbBool enable)
|
||||
{
|
||||
this->spinanimatingallowed = enable;
|
||||
if (!enable && this->isAnimating()) { this->stopAnimating(); }
|
||||
if (!enable && this->isAnimating()) { animator->stop(); }
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1191,52 +1067,39 @@ SbBool NavigationStyle::isAnimating() const
|
||||
return this->currentmode == NavigationStyle::SPINNING;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Starts programmatically the viewer in animation mode. The given axis direction
|
||||
* is always in screen coordinates, not in world coordinates.
|
||||
*/
|
||||
void NavigationStyle::startAnimating(const SbVec3f& axis, float velocity)
|
||||
void NavigationStyle::startAnimating(const std::shared_ptr<NavigationAnimation>& animation, bool wait) const
|
||||
{
|
||||
if (!isAnimationEnabled())
|
||||
return;
|
||||
|
||||
this->prevRedrawTime = SbTime::getTimeOfDay();
|
||||
this->spinincrement = SbRotation::identity();
|
||||
SbRotation rot;
|
||||
rot.setValue(axis, velocity);
|
||||
|
||||
this->setViewing(true);
|
||||
this->setViewingMode(NavigationStyle::SPINNING);
|
||||
this->spinRotation = rot;
|
||||
if (wait) {
|
||||
animator->startAndWait(animation);
|
||||
}
|
||||
else {
|
||||
animator->start(animation);
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationStyle::stopAnimating()
|
||||
void NavigationStyle::stopAnimating() const
|
||||
{
|
||||
if (this->currentmode != NavigationStyle::SPINNING) {
|
||||
return;
|
||||
}
|
||||
this->setViewingMode(this->isViewing() ?
|
||||
NavigationStyle::IDLE : NavigationStyle::INTERACT);
|
||||
animator->stop();
|
||||
}
|
||||
|
||||
void NavigationStyle::setSensitivity(float val)
|
||||
{
|
||||
PRIVATE(this)->sensitivity = val;
|
||||
this->sensitivity = val;
|
||||
}
|
||||
|
||||
float NavigationStyle::getSensitivity() const
|
||||
{
|
||||
return PRIVATE(this)->sensitivity;
|
||||
return this->sensitivity;
|
||||
}
|
||||
|
||||
void NavigationStyle::setResetCursorPosition(SbBool on)
|
||||
{
|
||||
PRIVATE(this)->resetcursorpos = on;
|
||||
this->resetcursorpos = on;
|
||||
}
|
||||
|
||||
SbBool NavigationStyle::isResetCursorPosition() const
|
||||
{
|
||||
return PRIVATE(this)->resetcursorpos;
|
||||
return this->resetcursorpos;
|
||||
}
|
||||
|
||||
void NavigationStyle::setZoomInverted(SbBool on)
|
||||
@@ -1266,12 +1129,12 @@ SbBool NavigationStyle::isZoomAtCursor() const
|
||||
|
||||
void NavigationStyle::setRotationCenterMode(NavigationStyle::RotationCenterModes mode)
|
||||
{
|
||||
PRIVATE(this)->rotationCenterMode = mode;
|
||||
this->rotationCenterMode = mode;
|
||||
}
|
||||
|
||||
NavigationStyle::RotationCenterModes NavigationStyle::getRotationCenterMode() const
|
||||
{
|
||||
return PRIVATE(this)->rotationCenterMode;
|
||||
return this->rotationCenterMode;
|
||||
}
|
||||
|
||||
void NavigationStyle::startSelection(AbstractMouseSelection* mouse)
|
||||
@@ -1415,6 +1278,7 @@ void NavigationStyle::setViewingMode(const ViewerMode newmode)
|
||||
case DRAGGING:
|
||||
// Set up initial projection point for the projector object when
|
||||
// first starting a drag operation.
|
||||
animator->stop();
|
||||
viewer->showRotationCenter(true);
|
||||
this->spinprojector->project(this->lastmouseposition);
|
||||
this->interactiveCountInc();
|
||||
@@ -1428,15 +1292,18 @@ void NavigationStyle::setViewingMode(const ViewerMode newmode)
|
||||
break;
|
||||
|
||||
case PANNING:
|
||||
animator->stop();
|
||||
pan(viewer->getSoRenderManager()->getCamera());
|
||||
this->interactiveCountInc();
|
||||
break;
|
||||
|
||||
case ZOOMING:
|
||||
animator->stop();
|
||||
this->interactiveCountInc();
|
||||
break;
|
||||
|
||||
case BOXZOOM:
|
||||
animator->stop();
|
||||
this->interactiveCountInc();
|
||||
break;
|
||||
|
||||
|
||||
+23
-13
@@ -38,7 +38,7 @@
|
||||
#include <Base/BaseClass.h>
|
||||
#include <Gui/Namespace.h>
|
||||
#include <FCGlobal.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
// forward declarations
|
||||
class SoEvent;
|
||||
@@ -52,7 +52,9 @@ class SbSphereSheetProjector;
|
||||
namespace Gui {
|
||||
|
||||
class View3DInventorViewer;
|
||||
class NavigationAnimator;
|
||||
class AbstractMouseSelection;
|
||||
class NavigationAnimation;
|
||||
|
||||
/**
|
||||
* @author Werner Mayer
|
||||
@@ -122,9 +124,9 @@ public:
|
||||
void setAnimationEnabled(const SbBool enable);
|
||||
SbBool isAnimationEnabled() const;
|
||||
|
||||
void startAnimating(const SbVec3f& axis, float velocity);
|
||||
void stopAnimating();
|
||||
SbBool isAnimating() const;
|
||||
void startAnimating(const std::shared_ptr<NavigationAnimation>& animation, bool wait = false) const;
|
||||
void stopAnimating() const;
|
||||
|
||||
void setSensitivity(float);
|
||||
float getSensitivity() const;
|
||||
@@ -144,11 +146,14 @@ public:
|
||||
void setRotationCenter(const SbVec3f& cnt);
|
||||
SbVec3f getFocalPoint() const;
|
||||
|
||||
void updateAnimation();
|
||||
void redraw();
|
||||
|
||||
void setCameraOrientation(const SbRotation& rot, SbBool moveTocenter=false);
|
||||
void lookAtPoint(const SbVec3f&);
|
||||
SoCamera* getCamera() const;
|
||||
void setCameraOrientation(const SbRotation& orientation, SbBool moveToCenter = false);
|
||||
void translateCamera(const SbVec3f& translation);
|
||||
void reorientCamera(SoCamera* camera, const SbRotation& rotation);
|
||||
void reorientCamera(SoCamera* camera, const SbRotation& rotation, const SbVec3f& rotationCenter);
|
||||
|
||||
void boxZoom(const SbBox2s& box);
|
||||
virtual void viewAll();
|
||||
|
||||
@@ -173,6 +178,9 @@ public:
|
||||
void setOrbitStyle(OrbitStyle style);
|
||||
OrbitStyle getOrbitStyle() const;
|
||||
|
||||
SbBool isViewing() const;
|
||||
void setViewing(SbBool);
|
||||
|
||||
SbVec3f getRotationCenter(SbBool&) const;
|
||||
|
||||
protected:
|
||||
@@ -183,15 +191,13 @@ protected:
|
||||
void interactiveCountDec();
|
||||
int getInteractiveCount() const;
|
||||
|
||||
SbBool isViewing() const;
|
||||
void setViewing(SbBool);
|
||||
SbBool isSeekMode() const;
|
||||
void setSeekMode(SbBool enable);
|
||||
SbBool seekToPoint(const SbVec2s screenpos);
|
||||
void seekToPoint(const SbVec3f& scenepos);
|
||||
SbBool lookAtPoint(const SbVec2s screenpos);
|
||||
void lookAtPoint(const SbVec3f& position);
|
||||
|
||||
void reorientCamera(SoCamera * camera, const SbRotation & rot);
|
||||
void panCamera(SoCamera * camera,
|
||||
float vpaspect,
|
||||
const SbPlane & panplane,
|
||||
@@ -233,13 +239,13 @@ protected:
|
||||
} log;
|
||||
|
||||
View3DInventorViewer* viewer{nullptr};
|
||||
NavigationAnimator* animator;
|
||||
ViewerMode currentmode;
|
||||
SoMouseButtonEvent mouseDownConsumedEvent;
|
||||
SbVec2f lastmouseposition;
|
||||
SbVec2s globalPos;
|
||||
SbVec2s localPos;
|
||||
SbPlane panningplane;
|
||||
SbTime prevRedrawTime;
|
||||
SbTime centerTime;
|
||||
SbBool lockrecenter;
|
||||
SbBool menuenabled;
|
||||
@@ -261,13 +267,17 @@ protected:
|
||||
SbBool spinanimatingallowed;
|
||||
int spinsamplecounter;
|
||||
SbRotation spinincrement;
|
||||
SbRotation spinRotation;
|
||||
SbSphereSheetProjector * spinprojector;
|
||||
//@}
|
||||
|
||||
private:
|
||||
struct NavigationStyleP* pimpl;
|
||||
friend struct NavigationStyleP;
|
||||
friend class NavigationAnimator;
|
||||
|
||||
SbVec3f rotationCenter;
|
||||
SbBool rotationCenterFound;
|
||||
NavigationStyle::RotationCenterModes rotationCenterMode;
|
||||
float sensitivity;
|
||||
SbBool resetcursorpos;
|
||||
};
|
||||
|
||||
/** Sub-classes of this class appear in the preference dialog where users can
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
<FCBool Name="ShowFPS" Value="0"/>
|
||||
<FCBool Name="ShowNaviCube" Value="1"/>
|
||||
<FCBool Name="ShowSelectionBoundingBox" Value="0"/>
|
||||
<FCBool Name="UseAutoRotation" Value="0"/>
|
||||
<FCBool Name="UseNavigationAnimations" Value="1"/>
|
||||
<FCFloat Name="AnimationDuration" Value="0.25"/>
|
||||
<FCBool Name="UseVBO" Value="0"/>
|
||||
<FCFloat Name="ViewScalingFactor" Value="1.0"/>
|
||||
<FCBool Name="ZoomAtCursor" Value="1"/>
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <QColor>
|
||||
#include <QEvent>
|
||||
#include <QGridLayout>
|
||||
#include <Inventor/draggers/SoDirectionalLightDragger.h>
|
||||
#include <Inventor/nodes/SoDirectionalLight.h>
|
||||
#include <Inventor/nodes/SoOrthographicCamera.h>
|
||||
#include <Inventor/nodes/SoPickStyle.h>
|
||||
#include <Inventor/nodes/SoSeparator.h>
|
||||
#endif
|
||||
|
||||
#include "DlgSettingsLightSources.h"
|
||||
#include "ui_DlgSettingsLightSources.h"
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
|
||||
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::DlgSettingsLightSources */
|
||||
|
||||
DlgSettingsLightSources::DlgSettingsLightSources(QWidget* parent)
|
||||
: PreferencePage(parent)
|
||||
, ui(new Ui_DlgSettingsLightSources)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setupConnection();
|
||||
}
|
||||
|
||||
DlgSettingsLightSources::~DlgSettingsLightSources()
|
||||
{
|
||||
delete view;
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::setupConnection()
|
||||
{
|
||||
connect(ui->checkBoxLight1, &QCheckBox::toggled,
|
||||
this, &DlgSettingsLightSources::toggleLight);
|
||||
connect(ui->sliderIntensity1, &QSlider::valueChanged,
|
||||
this, &DlgSettingsLightSources::lightIntensity);
|
||||
connect(ui->light1Color, &Gui::ColorButton::changed,
|
||||
this, &DlgSettingsLightSources::lightColor);
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::showEvent(QShowEvent* event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
if (!view) {
|
||||
QGroupBox* box = ui->groupBoxLight;
|
||||
QWidget* widget = createViewer(box);
|
||||
auto grid = new QGridLayout(box);
|
||||
grid->addWidget(widget);
|
||||
box->setLayout(grid);
|
||||
|
||||
loadDirection();
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::dragMotionCallback(void *data, SoDragger *drag)
|
||||
{
|
||||
auto lightdrag = static_cast<SoDirectionalLightDragger*>(drag); // NOLINT
|
||||
auto self = static_cast<DlgSettingsLightSources*>(data);
|
||||
SbRotation rotation = lightdrag->rotation.getValue();
|
||||
SbVec3f dir(0, 0, -1);
|
||||
rotation.multVec(dir, dir);
|
||||
self->view->getHeadlight()->direction = dir;
|
||||
}
|
||||
|
||||
QWidget* DlgSettingsLightSources::createViewer(QWidget* parent)
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
view = new Gui::View3DInventorViewer(parent);
|
||||
view->setRedirectToSceneGraph(true);
|
||||
view->setViewing(true);
|
||||
view->setPopupMenuEnabled(false);
|
||||
|
||||
view->setBackgroundColor(QColor(255, 255, 255));
|
||||
view->setGradientBackground(Gui::View3DInventorViewer::NoGradient);
|
||||
view->setEnabledNaviCube(false);
|
||||
|
||||
auto root = static_cast<SoSeparator*>(view->getSceneGraph());
|
||||
root->addChild(createDragger());
|
||||
|
||||
view->setCameraType(SoOrthographicCamera::getClassTypeId());
|
||||
view->setViewDirection(SbVec3f(1, 1, -5));
|
||||
view->viewAll();
|
||||
// NOLINTEND
|
||||
|
||||
const int size = 250;
|
||||
view->resize(size, size);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
SoDirectionalLightDragger* DlgSettingsLightSources::createDragger()
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
lightDragger = new SoDirectionalLightDragger();
|
||||
if (SoDragger* translator = dynamic_cast<SoDragger *>(lightDragger->getPart("translator", false))) {
|
||||
translator->setPartAsDefault("xTranslator.translatorActive", nullptr);
|
||||
translator->setPartAsDefault("yTranslator.translatorActive", nullptr);
|
||||
translator->setPartAsDefault("zTranslator.translatorActive", nullptr);
|
||||
translator->setPartAsDefault("xTranslator.translator", nullptr);
|
||||
translator->setPartAsDefault("yTranslator.translator", nullptr);
|
||||
translator->setPartAsDefault("zTranslator.translator", nullptr);
|
||||
SoNode* node = translator->getPart("yzTranslator.translator", false);
|
||||
if (node && node->isOfType(SoGroup::getClassTypeId())) {
|
||||
auto ps = new SoPickStyle();
|
||||
ps->style = SoPickStyle::UNPICKABLE;
|
||||
static_cast<SoGroup*>(node)->insertChild(ps, 0);
|
||||
}
|
||||
}
|
||||
|
||||
lightDragger->addMotionCallback(dragMotionCallback, this);
|
||||
return lightDragger;
|
||||
// NOLINTEND
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::saveSettings()
|
||||
{
|
||||
ui->checkBoxLight1->onSave();
|
||||
ui->light1Color->onSave();
|
||||
ui->sliderIntensity1->onSave();
|
||||
saveDirection();
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::loadSettings()
|
||||
{
|
||||
ui->checkBoxLight1->onRestore();
|
||||
ui->light1Color->onRestore();
|
||||
ui->sliderIntensity1->onRestore();
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::saveDirection()
|
||||
{
|
||||
if (lightDragger) {
|
||||
ParameterGrp::handle grp = ui->sliderIntensity1->getWindowParameter();
|
||||
SbRotation rotation = lightDragger->rotation.getValue();
|
||||
grp->SetFloat("HeadlightRotationX", rotation[0]);
|
||||
grp->SetFloat("HeadlightRotationY", rotation[1]);
|
||||
grp->SetFloat("HeadlightRotationZ", rotation[2]);
|
||||
grp->SetFloat("HeadlightRotationW", rotation[3]);
|
||||
|
||||
SbVec3f dir(0, 0, -1);
|
||||
rotation.multVec(dir, dir);
|
||||
|
||||
QString headlightDir = QString::fromLatin1("(%1,%2,%3)").arg(dir[0]).arg(dir[1]).arg(dir[2]);
|
||||
grp->SetASCII("HeadlightDirection", headlightDir.toLatin1());
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::loadDirection()
|
||||
{
|
||||
ParameterGrp::handle grp = ui->sliderIntensity1->getWindowParameter();
|
||||
SbRotation rotation = lightDragger->rotation.getValue();
|
||||
// NOLINTBEGIN
|
||||
float q1 = float(grp->GetFloat("HeadlightRotationX", rotation[0]));
|
||||
float q2 = float(grp->GetFloat("HeadlightRotationY", rotation[1]));
|
||||
float q3 = float(grp->GetFloat("HeadlightRotationZ", rotation[2]));
|
||||
float q4 = float(grp->GetFloat("HeadlightRotationW", rotation[3]));
|
||||
// NOLINTEND
|
||||
rotation.setValue(q1, q2, q3, q4);
|
||||
lightDragger->rotation.setValue(rotation);
|
||||
|
||||
SbVec3f direction(0, 0, -1);
|
||||
rotation.multVec(direction, direction);
|
||||
view->getHeadlight()->direction = direction;
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::toggleLight(bool on)
|
||||
{
|
||||
if (view) {
|
||||
view->setHeadlightEnabled(on);
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::lightIntensity(int value)
|
||||
{
|
||||
if (view) {
|
||||
float intensity = float(value) / 100.0F;
|
||||
view->getHeadlight()->intensity = intensity;
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::lightColor()
|
||||
{
|
||||
if (view) {
|
||||
QColor color = ui->light1Color->color();
|
||||
float red = float(color.redF());
|
||||
float green = float(color.greenF());
|
||||
float blue = float(color.blueF());
|
||||
view->getHeadlight()->color = SbColor(red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::changeEvent(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
PreferencePage::changeEvent(event);
|
||||
}
|
||||
|
||||
|
||||
#include "moc_DlgSettingsLightSources.cpp"
|
||||
@@ -0,0 +1,79 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_DIALOG_DLGSETTINGSLIGHTSOURCES_H
|
||||
#define GUI_DIALOG_DLGSETTINGSLIGHTSOURCES_H
|
||||
|
||||
#include <Gui/PropertyPage.h>
|
||||
#include <memory>
|
||||
|
||||
class SoDragger;
|
||||
class SoDirectionalLightDragger;
|
||||
|
||||
namespace Gui {
|
||||
class View3DInventorViewer;
|
||||
namespace Dialog {
|
||||
class Ui_DlgSettingsLightSources;
|
||||
|
||||
/**
|
||||
* The DlgSettingsLightSources class implements a preference page to change settings
|
||||
* for the light sources of a 3D view.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
class DlgSettingsLightSources : public PreferencePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DlgSettingsLightSources(QWidget* parent = nullptr);
|
||||
~DlgSettingsLightSources() override;
|
||||
|
||||
void saveSettings() override;
|
||||
void loadSettings() override;
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent* event) override;
|
||||
void showEvent(QShowEvent* event) override;
|
||||
|
||||
private:
|
||||
void setupConnection();
|
||||
void toggleLight(bool on);
|
||||
void lightIntensity(int value);
|
||||
void lightColor();
|
||||
void saveDirection();
|
||||
void loadDirection();
|
||||
QWidget* createViewer(QWidget* parent);
|
||||
SoDirectionalLightDragger* createDragger();
|
||||
static void dragMotionCallback(void *data, SoDragger *drag);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_DlgSettingsLightSources> ui;
|
||||
View3DInventorViewer* view = nullptr;
|
||||
SoDirectionalLightDragger* lightDragger = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Dialog
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_DIALOG_DLGSETTINGSLIGHTSOURCES_H
|
||||
@@ -0,0 +1,199 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui::Dialog::DlgSettingsLightSources</class>
|
||||
<widget class="QWidget" name="Gui::Dialog::DlgSettingsLightSources">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>484</width>
|
||||
<height>515</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Light Sources</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Light sources</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="checkBoxLight1">
|
||||
<property name="text">
|
||||
<string>Light source</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>EnableHeadlight</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="light1Color">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>HeadlightColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>115</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="light1Label">
|
||||
<property name="text">
|
||||
<string>Intensity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="Gui::PrefSlider" name="sliderIntensity1">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>HeadlightIntensity</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBoxLight">
|
||||
<property name="title">
|
||||
<string>Lights</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>428</width>
|
||||
<height>376</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::ColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Gui/Widgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefColorButton</class>
|
||||
<extends>Gui::ColorButton</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefSlider</class>
|
||||
<extends>QSlider</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>checkBoxLight1</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>light1Color</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>73</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>150</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkBoxLight1</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>light1Label</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>73</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>284</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkBoxLight1</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>sliderIntensity1</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>73</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>357</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -88,7 +88,8 @@ void DlgSettingsNavigation::saveSettings()
|
||||
ui->rotationCenterSize->onSave();
|
||||
ui->rotationCenterColor->onSave();
|
||||
ui->spinBoxZoomStep->onSave();
|
||||
ui->checkBoxUseAutoRotation->onSave();
|
||||
ui->checkBoxNavigationAnimations->onSave();
|
||||
ui->spinBoxAnimationDuration->onSave();
|
||||
ui->qspinNewDocScale->onSave();
|
||||
ui->prefStepByTurn->onSave();
|
||||
ui->naviCubeCorner->onSave();
|
||||
@@ -115,7 +116,7 @@ void DlgSettingsNavigation::saveSettings()
|
||||
hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/NaviCube");
|
||||
if (ui->naviCubeFontName->currentIndex()) {
|
||||
hGrp->SetASCII("FontString", ui->naviCubeFontName->currentText().toLatin1());
|
||||
hGrp->SetASCII("FontString", ui->naviCubeFontName->currentText().toLatin1());
|
||||
} else {
|
||||
hGrp->RemoveASCII("FontString");
|
||||
}
|
||||
@@ -129,7 +130,8 @@ void DlgSettingsNavigation::loadSettings()
|
||||
ui->rotationCenterSize->onRestore();
|
||||
ui->rotationCenterColor->onRestore();
|
||||
ui->spinBoxZoomStep->onRestore();
|
||||
ui->checkBoxUseAutoRotation->onRestore();
|
||||
ui->checkBoxNavigationAnimations->onRestore();
|
||||
ui->spinBoxAnimationDuration->onRestore();
|
||||
ui->qspinNewDocScale->onRestore();
|
||||
ui->prefStepByTurn->onRestore();
|
||||
ui->naviCubeCorner->onRestore();
|
||||
@@ -191,7 +193,7 @@ void DlgSettingsNavigation::loadSettings()
|
||||
QStringList familyNames = QFontDatabase::families(QFontDatabase::Any);
|
||||
#endif
|
||||
ui->naviCubeFontName->addItems(familyNames);
|
||||
|
||||
|
||||
hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/NaviCube");
|
||||
int indexFamilyNames = familyNames.indexOf(
|
||||
|
||||
@@ -566,27 +566,91 @@ The value is the diameter of the sphere to fit on the screen.</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="checkBoxUseAutoRotation">
|
||||
<widget class="Gui::PrefCheckBox" name="checkBoxNavigationAnimations">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enable animated rotations</string>
|
||||
<string>Enable navigation animations</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable animation</string>
|
||||
<string>Enable navigation animations</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>UseAutoRotation</cstring>
|
||||
<cstring>UseNavigationAnimations</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="navigationAnimationsLabel">
|
||||
<property name="toolTip">
|
||||
<string>Duration of navigation animations that have a fixed duration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Animation duration</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="Gui::PrefSpinBox" name="spinBoxAnimationDuration">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The duration of navigation animations in milliseconds</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>AnimationDuration</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="checkBoxZoomAtCursor">
|
||||
<property name="toolTip">
|
||||
@@ -609,7 +673,7 @@ The value is the diameter of the sphere to fit on the screen.</string>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string> Zoom step</string>
|
||||
<string>Zoom step</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
|
||||
#include "SoQTQuarterAdaptor.h"
|
||||
|
||||
|
||||
// NOLINTBEGIN
|
||||
// clang-format off
|
||||
static unsigned char fps2dfont[][12] = {
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, //
|
||||
{ 0, 0, 12, 12, 0, 8, 12, 12, 12, 12, 12, 0 }, // !
|
||||
@@ -140,21 +141,37 @@ static unsigned char fps2dfont[][12] = {
|
||||
{ 0, 48, 8, 8, 8, 16, 12, 16, 8, 8, 8, 48 }, // }
|
||||
{ 0, 0, 0, 0, 0, 0, 78, 57, 0, 0, 0, 0 } // ~
|
||||
};
|
||||
// clang-format on
|
||||
// NOLINTEND
|
||||
|
||||
SIM::Coin3D::Quarter::SoQTQuarterAdaptor::SoQTQuarterAdaptor(QWidget* parent, const QtGLWidget* sharewidget, Qt::WindowFlags f)
|
||||
: QuarterWidget(parent, sharewidget, f), matrixaction(SbViewportRegion(100,100))
|
||||
constexpr const int defaultSize = 100;
|
||||
|
||||
// NOLINTBEGIN(readability-implicit-bool-conversion)
|
||||
SIM::Coin3D::Quarter::SoQTQuarterAdaptor::SoQTQuarterAdaptor(QWidget* parent,
|
||||
const QtGLWidget* sharewidget,
|
||||
Qt::WindowFlags flags)
|
||||
: QuarterWidget(parent, sharewidget, flags)
|
||||
, matrixaction(SbViewportRegion(defaultSize, defaultSize))
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
SIM::Coin3D::Quarter::SoQTQuarterAdaptor::SoQTQuarterAdaptor(const QtGLFormat& format, QWidget* parent, const QtGLWidget* shareWidget, Qt::WindowFlags f)
|
||||
: QuarterWidget(format, parent, shareWidget, f), matrixaction(SbViewportRegion(100,100))
|
||||
SIM::Coin3D::Quarter::SoQTQuarterAdaptor::SoQTQuarterAdaptor(const QtGLFormat& format,
|
||||
QWidget* parent,
|
||||
const QtGLWidget* shareWidget,
|
||||
Qt::WindowFlags flags)
|
||||
: QuarterWidget(format, parent, shareWidget, flags)
|
||||
, matrixaction(SbViewportRegion(defaultSize, defaultSize))
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
SIM::Coin3D::Quarter::SoQTQuarterAdaptor::SoQTQuarterAdaptor(QtGLContext* context, QWidget* parent, const QtGLWidget* sharewidget, Qt::WindowFlags f)
|
||||
: QuarterWidget(context, parent, sharewidget, f), matrixaction(SbViewportRegion(100,100))
|
||||
SIM::Coin3D::Quarter::SoQTQuarterAdaptor::SoQTQuarterAdaptor(QtGLContext* context,
|
||||
QWidget* parent,
|
||||
const QtGLWidget* sharewidget,
|
||||
Qt::WindowFlags flags)
|
||||
: QuarterWidget(context, parent, sharewidget, flags)
|
||||
, matrixaction(SbViewportRegion(defaultSize, defaultSize))
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -166,10 +183,11 @@ SIM::Coin3D::Quarter::SoQTQuarterAdaptor::~SoQTQuarterAdaptor()
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::init()
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
m_interactionnesting = 0;
|
||||
m_seekdistance = 50.0f;
|
||||
m_seekdistance = 50.0F;
|
||||
m_seekdistanceabs = false;
|
||||
m_seekperiod = 2.0f;
|
||||
m_seekperiod = 2.0F;
|
||||
m_inseekmode = false;
|
||||
m_storedcamera = nullptr;
|
||||
m_viewingflag = false;
|
||||
@@ -179,6 +197,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::init()
|
||||
getSoEventManager()->setNavigationState(SoEventManager::NO_NAVIGATION);
|
||||
|
||||
resetFrameCounter();
|
||||
// NOLINTEND
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +217,7 @@ QWidget* SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getWidget() const
|
||||
{
|
||||
//we keep the function from SoQt as we want to introduce the QGraphicsView and then the GLWidget
|
||||
//is separated from the Widget used in layouts again
|
||||
return const_cast<SoQTQuarterAdaptor*>(this);
|
||||
return const_cast<SoQTQuarterAdaptor*>(this); // NOLINT
|
||||
}
|
||||
|
||||
QWidget* SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getGLWidget() const
|
||||
@@ -221,38 +240,39 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setCameraType(SoType type)
|
||||
SbBool oldisperspective = cam ? cam->getTypeId().isDerivedFrom(perspectivetype) : false;
|
||||
SbBool newisperspective = type.isDerivedFrom(perspectivetype);
|
||||
|
||||
if (oldisperspective == newisperspective) // Same old, same old..
|
||||
// Same old, same old..
|
||||
if (oldisperspective == newisperspective) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
SoCamera* currentcam = getSoRenderManager()->getCamera();
|
||||
SoCamera* newcamera = (SoCamera*)type.createInstance();
|
||||
SoCamera* newcamera = static_cast<SoCamera*>(type.createInstance()); // NOLINT
|
||||
|
||||
// Transfer and convert values from one camera type to the other.
|
||||
if(newisperspective) {
|
||||
convertOrtho2Perspective((SoOrthographicCamera*)currentcam,
|
||||
(SoPerspectiveCamera*)newcamera);
|
||||
convertOrtho2Perspective(dynamic_cast<SoOrthographicCamera*>(currentcam),
|
||||
dynamic_cast<SoPerspectiveCamera*>(newcamera));
|
||||
}
|
||||
else {
|
||||
convertPerspective2Ortho((SoPerspectiveCamera*)currentcam,
|
||||
(SoOrthographicCamera*)newcamera);
|
||||
convertPerspective2Ortho(dynamic_cast<SoPerspectiveCamera*>(currentcam),
|
||||
dynamic_cast<SoOrthographicCamera*>(newcamera));
|
||||
}
|
||||
|
||||
getSoRenderManager()->setCamera(newcamera);
|
||||
getSoEventManager()->setCamera(newcamera);
|
||||
|
||||
//if the superscene has a camera we need to replace it too
|
||||
SoSeparator* superscene = (SoSeparator*) getSoRenderManager()->getSceneGraph();
|
||||
auto superscene = dynamic_cast<SoSeparator*>(getSoRenderManager()->getSceneGraph());
|
||||
SoSearchAction sa;
|
||||
sa.setInterest(SoSearchAction::FIRST);
|
||||
sa.setType(SoCamera::getClassTypeId());
|
||||
sa.apply(superscene);
|
||||
|
||||
if(sa.getPath()) {
|
||||
if (sa.getPath()) {
|
||||
SoNode* node = sa.getPath()->getTail();
|
||||
SoGroup* parent = (SoGroup*) sa.getPath()->getNodeFromTail(1);
|
||||
SoGroup* parent = static_cast<SoGroup*>(sa.getPath()->getNodeFromTail(1)); // NOLINT
|
||||
|
||||
if(node && node->isOfType(SoCamera::getClassTypeId())) {
|
||||
if (node && node->isOfType(SoCamera::getClassTypeId())) {
|
||||
parent->replaceChild(node, newcamera);
|
||||
}
|
||||
}
|
||||
@@ -274,7 +294,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::convertOrtho2Perspective(const So
|
||||
|
||||
SbRotation camrot = in->orientation.getValue();
|
||||
|
||||
float focaldist = in->height.getValue() / (2.0*tan(M_PI / 8.0));
|
||||
float focaldist = float(in->height.getValue() / (2.0*tan(M_PI / 8.0))); // NOLINT
|
||||
|
||||
SbVec3f offset(0,0,focaldist-in->focalDistance.getValue());
|
||||
|
||||
@@ -284,7 +304,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::convertOrtho2Perspective(const So
|
||||
out->focalDistance.setValue(focaldist);
|
||||
|
||||
// 45° is the default value of this field in SoPerspectiveCamera.
|
||||
out->heightAngle = (float)(M_PI / 4.0);
|
||||
out->heightAngle = (float)(M_PI / 4.0); // NOLINT
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::convertPerspective2Ortho(const SoPerspectiveCamera* in,
|
||||
@@ -298,7 +318,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::convertPerspective2Ortho(const So
|
||||
|
||||
float focaldist = in->focalDistance.getValue();
|
||||
|
||||
out->height = 2.0f * focaldist * (float)tan(in->heightAngle.getValue() / 2.0);
|
||||
out->height = 2.0F * focaldist * (float)tan(in->heightAngle.getValue() / 2.0); // NOLINT
|
||||
}
|
||||
|
||||
SoCamera* SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getCamera() const
|
||||
@@ -311,9 +331,8 @@ const SbViewportRegion & SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getViewportRe
|
||||
return getSoRenderManager()->getViewportRegion();
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setViewing(SbBool enable)
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setViewing(bool enable)
|
||||
{
|
||||
|
||||
m_viewingflag = enable;
|
||||
|
||||
// Turn off the selection indicators when we go back from picking
|
||||
@@ -321,12 +340,13 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setViewing(SbBool enable)
|
||||
if (m_viewingflag) {
|
||||
SoGLRenderAction* action = getSoRenderManager()->getGLRenderAction();
|
||||
|
||||
if (action)
|
||||
if (action) {
|
||||
SoLocateHighlight::turnOffCurrentHighlight(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isViewing() const
|
||||
bool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isViewing() const
|
||||
{
|
||||
return m_viewingflag;
|
||||
}
|
||||
@@ -336,14 +356,14 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::interactiveCountInc()
|
||||
// Catch problems with missing interactiveCountDec() calls.
|
||||
assert(m_interactionnesting < 100);
|
||||
|
||||
if(++m_interactionnesting == 1) {
|
||||
if (++m_interactionnesting == 1) {
|
||||
m_interactionStartCallback.invokeCallbacks(this);
|
||||
}
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::interactiveCountDec()
|
||||
{
|
||||
if(--m_interactionnesting <= 0) {
|
||||
if (--m_interactionnesting <= 0) {
|
||||
m_interactionEndCallback.invokeCallbacks(this);
|
||||
m_interactionnesting = 0;
|
||||
}
|
||||
@@ -354,26 +374,27 @@ int SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getInteractiveCount() const
|
||||
return m_interactionnesting;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::addStartCallback(SIM::Coin3D::Quarter::SoQTQuarterAdaptorCB* func, void* data)
|
||||
{
|
||||
m_interactionStartCallback.addCallback((SoCallbackListCB*)func, data);
|
||||
m_interactionStartCallback.addCallback((SoCallbackListCB*)func, data); // NOLINT
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::removeStartCallback(SIM::Coin3D::Quarter::SoQTQuarterAdaptorCB* func, void* data)
|
||||
{
|
||||
m_interactionStartCallback.removeCallback((SoCallbackListCB*)func, data);
|
||||
m_interactionStartCallback.removeCallback((SoCallbackListCB*)func, data); // NOLINT
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::addFinishCallback(SIM::Coin3D::Quarter::SoQTQuarterAdaptorCB* func, void* data)
|
||||
{
|
||||
m_interactionEndCallback.addCallback((SoCallbackListCB*)func, data);
|
||||
m_interactionEndCallback.addCallback((SoCallbackListCB*)func, data); // NOLINT
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::removeFinishCallback(SIM::Coin3D::Quarter::SoQTQuarterAdaptorCB* func, void* data)
|
||||
{
|
||||
m_interactionEndCallback.removeCallback((SoCallbackListCB*)func, data);
|
||||
m_interactionEndCallback.removeCallback((SoCallbackListCB*)func, data); // NOLINT
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
float SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getSeekDistance() const
|
||||
{
|
||||
@@ -385,14 +406,14 @@ float SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getSeekTime() const
|
||||
return m_seekperiod;
|
||||
}
|
||||
|
||||
SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isSeekMode() const
|
||||
bool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isSeekMode() const
|
||||
{
|
||||
return m_inseekmode;
|
||||
}
|
||||
|
||||
SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isSeekValuePercentage() const
|
||||
bool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isSeekValuePercentage() const
|
||||
{
|
||||
return m_seekdistanceabs ? false : true;
|
||||
return !m_seekdistanceabs;
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setPickRadius(float pickRadius)
|
||||
@@ -400,14 +421,14 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setPickRadius(float pickRadius)
|
||||
this->pickRadius = pickRadius;
|
||||
SoEventManager* evm = this->getSoEventManager();
|
||||
if (evm){
|
||||
SoHandleEventAction* a = evm->getHandleEventAction();
|
||||
if (a){
|
||||
a->setPickRadius(pickRadius);
|
||||
SoHandleEventAction* hea = evm->getHandleEventAction();
|
||||
if (hea){
|
||||
hea->setPickRadius(pickRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seekToPoint(const SbVec2s screenpos)
|
||||
bool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seekToPoint(const SbVec2s& screenpos)
|
||||
{
|
||||
|
||||
SoRayPickAction rpaction(getSoRenderManager()->getViewportRegion());
|
||||
@@ -417,7 +438,7 @@ SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seekToPoint(const SbVec2s scree
|
||||
|
||||
SoPickedPoint* picked = rpaction.getPickedPoint();
|
||||
|
||||
if(!picked) {
|
||||
if (!picked) {
|
||||
this->interactiveCountInc(); // decremented in setSeekMode(false)
|
||||
this->setSeekMode(false);
|
||||
return false;
|
||||
@@ -439,7 +460,8 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seekToPoint(const SbVec3f& scenep
|
||||
|
||||
// move point to the camera coordinate system, consider
|
||||
// transformations before camera in the scene graph
|
||||
SbMatrix cameramatrix, camerainverse;
|
||||
SbMatrix cameramatrix;
|
||||
SbMatrix camerainverse;
|
||||
getCameraCoordinateSystem(getSoRenderManager()->getCamera(),
|
||||
getSceneGraph(),
|
||||
cameramatrix,
|
||||
@@ -448,8 +470,9 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seekToPoint(const SbVec3f& scenep
|
||||
|
||||
float fd = m_seekdistance;
|
||||
|
||||
if(!m_seekdistanceabs)
|
||||
fd *= (hitpoint - getSoRenderManager()->getCamera()->position.getValue()).length()/100.0f;
|
||||
if(!m_seekdistanceabs) {
|
||||
fd *= (hitpoint - getSoRenderManager()->getCamera()->position.getValue()).length()/100.0F;
|
||||
}
|
||||
|
||||
getSoRenderManager()->getCamera()->focalDistance = fd;
|
||||
|
||||
@@ -479,7 +502,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setSeekDistance(const float dista
|
||||
m_seekdistance = distance;
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setSeekMode(SbBool enable)
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setSeekMode(bool enable)
|
||||
{
|
||||
if(!enable && m_seeksensor->isScheduled()) {
|
||||
m_seeksensor->unschedule();
|
||||
@@ -494,12 +517,15 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setSeekTime(const float seconds)
|
||||
m_seekperiod = seconds;
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setSeekValueAsPercentage(const SbBool on)
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setSeekValueAsPercentage(bool on)
|
||||
{
|
||||
m_seekdistanceabs = on ? false : true;
|
||||
m_seekdistanceabs = !on;
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getCameraCoordinateSystem(SoCamera* camera, SoNode* root, SbMatrix& matrix, SbMatrix& inverse)
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getCameraCoordinateSystem(SoCamera* camera,
|
||||
SoNode* root,
|
||||
SbMatrix& matrix,
|
||||
SbMatrix& inverse)
|
||||
{
|
||||
searchaction.reset();
|
||||
searchaction.setSearchingAll(true);
|
||||
@@ -518,30 +544,33 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getCameraCoordinateSystem(SoCamer
|
||||
searchaction.reset();
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seeksensorCB(void* data, SoSensor* s)
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seeksensorCB(void* data, SoSensor* sensor)
|
||||
{
|
||||
SoQTQuarterAdaptor* thisp = (SoQTQuarterAdaptor*) data;
|
||||
SoQTQuarterAdaptor* thisp = static_cast<SoQTQuarterAdaptor*>(data); // NOLINT
|
||||
SbTime currenttime = SbTime::getTimeOfDay();
|
||||
|
||||
SoTimerSensor* sensor = (SoTimerSensor*)s;
|
||||
SoTimerSensor* timer = static_cast<SoTimerSensor*>(sensor); // NOLINT
|
||||
|
||||
float t =
|
||||
float((currenttime - sensor->getBaseTime()).getValue()) / thisp->m_seekperiod;
|
||||
float par = float((currenttime - timer->getBaseTime()).getValue()) / thisp->m_seekperiod;
|
||||
|
||||
if((t > 1.0f) || (t + sensor->getInterval().getValue() > 1.0f)) t = 1.0f;
|
||||
if ((par > 1.0F) || (par + timer->getInterval().getValue() > 1.0F)) {
|
||||
par = 1.0F;
|
||||
}
|
||||
|
||||
SbBool end = (t == 1.0f);
|
||||
bool end = (par == 1.0F);
|
||||
|
||||
t = (float)((1.0 - cos(M_PI*t)) * 0.5);
|
||||
par = (float)((1.0 - cos(M_PI * par)) * 0.5); // NOLINT
|
||||
|
||||
thisp->getSoRenderManager()->getCamera()->position = thisp->m_camerastartposition +
|
||||
(thisp->m_cameraendposition - thisp->m_camerastartposition) * t;
|
||||
(thisp->m_cameraendposition - thisp->m_camerastartposition) * par;
|
||||
thisp->getSoRenderManager()->getCamera()->orientation =
|
||||
SbRotation::slerp(thisp->m_camerastartorient,
|
||||
thisp->m_cameraendorient,
|
||||
t);
|
||||
par);
|
||||
|
||||
if(end) thisp->setSeekMode(false);
|
||||
if (end) {
|
||||
thisp->setSeekMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::saveHomePosition()
|
||||
@@ -551,15 +580,15 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::saveHomePosition()
|
||||
return;
|
||||
}
|
||||
|
||||
SoType t = cam->getTypeId();
|
||||
assert(t.isDerivedFrom(SoNode::getClassTypeId()));
|
||||
assert(t.canCreateInstance());
|
||||
SoType type = cam->getTypeId();
|
||||
assert(type.isDerivedFrom(SoNode::getClassTypeId()));
|
||||
assert(type.canCreateInstance());
|
||||
|
||||
if(m_storedcamera) {
|
||||
m_storedcamera->unref();
|
||||
}
|
||||
|
||||
m_storedcamera = (SoNode*)t.createInstance();
|
||||
m_storedcamera = static_cast<SoNode*>(type.createInstance()); // NOLINT
|
||||
m_storedcamera->ref();
|
||||
|
||||
m_storedcamera->copyFieldValues(getSoRenderManager()->getCamera());
|
||||
@@ -576,27 +605,27 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetToHomePosition()
|
||||
return;
|
||||
}
|
||||
|
||||
SoType t = getSoRenderManager()->getCamera()->getTypeId();
|
||||
SoType s = m_storedcamera->getTypeId();
|
||||
SoType ttype = getSoRenderManager()->getCamera()->getTypeId();
|
||||
SoType stype = m_storedcamera->getTypeId();
|
||||
|
||||
// most common case
|
||||
if(t == s) {
|
||||
if (ttype == stype) {
|
||||
// We copy the field data directly, instead of using
|
||||
// SoFieldContainer::copyContents(), for the reason described in
|
||||
// detail in So@Gui@Viewer::saveHomePosition().
|
||||
getSoRenderManager()->getCamera()->copyFieldValues(m_storedcamera);
|
||||
}
|
||||
// handle common case #1
|
||||
else if(t == SoOrthographicCamera::getClassTypeId() &&
|
||||
s == SoPerspectiveCamera::getClassTypeId()) {
|
||||
convertPerspective2Ortho((SoPerspectiveCamera*)m_storedcamera,
|
||||
(SoOrthographicCamera*)getSoRenderManager()->getCamera());
|
||||
else if(ttype == SoOrthographicCamera::getClassTypeId() &&
|
||||
stype == SoPerspectiveCamera::getClassTypeId()) {
|
||||
convertPerspective2Ortho(dynamic_cast<SoPerspectiveCamera*>(m_storedcamera),
|
||||
dynamic_cast<SoOrthographicCamera*>(getSoRenderManager()->getCamera()));
|
||||
}
|
||||
// handle common case #2
|
||||
else if(t == SoPerspectiveCamera::getClassTypeId() &&
|
||||
s == SoOrthographicCamera::getClassTypeId()) {
|
||||
convertOrtho2Perspective((SoOrthographicCamera*)m_storedcamera,
|
||||
(SoPerspectiveCamera*)getSoRenderManager()->getCamera());
|
||||
else if(ttype == SoPerspectiveCamera::getClassTypeId() &&
|
||||
stype == SoOrthographicCamera::getClassTypeId()) {
|
||||
convertOrtho2Perspective(dynamic_cast<SoOrthographicCamera*>(m_storedcamera),
|
||||
dynamic_cast<SoPerspectiveCamera*>(getSoRenderManager()->getCamera()));
|
||||
}
|
||||
|
||||
// otherwise, cameras have changed in ways we don't understand since
|
||||
@@ -606,7 +635,9 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetToHomePosition()
|
||||
|
||||
|
||||
void
|
||||
SIM::Coin3D::Quarter::SoQTQuarterAdaptor::draw2DString(const char* str, SbVec2s glsize, SbVec2f position)
|
||||
SIM::Coin3D::Quarter::SoQTQuarterAdaptor::draw2DString(const char* str,
|
||||
SbVec2s glsize,
|
||||
SbVec2f position)
|
||||
{
|
||||
// Store GL state.
|
||||
glPushAttrib(GL_ENABLE_BIT|GL_CURRENT_BIT);
|
||||
@@ -651,17 +682,19 @@ SIM::Coin3D::Quarter::SoQTQuarterAdaptor::draw2DString(const char* str, SbVec2s
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::printString(const char* s)
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::printString(const char* str)
|
||||
{
|
||||
int i,n;
|
||||
n = strlen(s);
|
||||
// NOLINTBEGIN
|
||||
std::size_t len = strlen(str);
|
||||
|
||||
for(i = 0; i < n; i++)
|
||||
glBitmap(8, 12, 0.0, 2.0, 10.0, 0.0, fps2dfont[s[i] - 32]);
|
||||
for(std::size_t i = 0; i < len; i++) {
|
||||
glBitmap(8, 12, 0.0, 2.0, 10.0, 0.0, fps2dfont[str[i] - 32]);
|
||||
}
|
||||
// NOLINTEND
|
||||
}
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::moveCameraScreen(const SbVec2f& screenpos) {
|
||||
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::moveCameraScreen(const SbVec2f& screenpos)
|
||||
{
|
||||
SoCamera* cam = getSoRenderManager()->getCamera();
|
||||
assert(cam);
|
||||
|
||||
@@ -669,11 +702,12 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::moveCameraScreen(const SbVec2f& s
|
||||
SbViewVolume vv = cam->getViewVolume(getGLWidget()->width() / getGLWidget()->height());
|
||||
SbPlane panplane = vv.getPlane(cam->focalDistance.getValue());
|
||||
|
||||
constexpr const float mid = 0.5F;
|
||||
SbLine line;
|
||||
vv.projectPointToLine(screenpos + SbVec2f(0.5, 0.5f), line);
|
||||
vv.projectPointToLine(screenpos + SbVec2f(mid, mid), line);
|
||||
SbVec3f current_planept;
|
||||
panplane.intersect(line, current_planept);
|
||||
vv.projectPointToLine(SbVec2f(0.5f, 0.5f), line);
|
||||
vv.projectPointToLine(SbVec2f(mid, mid), line);
|
||||
SbVec3f old_planept;
|
||||
panplane.intersect(line, old_planept);
|
||||
|
||||
@@ -682,30 +716,31 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::moveCameraScreen(const SbVec2f& s
|
||||
cam->position = cam->position.getValue() - (current_planept - old_planept);
|
||||
}
|
||||
|
||||
bool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::processSoEvent(const SoEvent* event) {
|
||||
|
||||
bool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::processSoEvent(const SoEvent* event)
|
||||
{
|
||||
const SoType type(event->getTypeId());
|
||||
|
||||
constexpr const float delta = 0.1F;
|
||||
if(type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
|
||||
const SoKeyboardEvent* keyevent = static_cast<const SoKeyboardEvent*>(event);
|
||||
const SoKeyboardEvent* keyevent = static_cast<const SoKeyboardEvent*>(event); // NOLINT
|
||||
|
||||
if(keyevent->getState() == SoButtonEvent::DOWN) {
|
||||
switch(keyevent->getKey()) {
|
||||
|
||||
case SoKeyboardEvent::LEFT_ARROW:
|
||||
moveCameraScreen(SbVec2f(-0.1f, 0.0f));
|
||||
moveCameraScreen(SbVec2f(-delta, 0.0F));
|
||||
return true;
|
||||
|
||||
case SoKeyboardEvent::UP_ARROW:
|
||||
moveCameraScreen(SbVec2f(0.0f, 0.1f));
|
||||
moveCameraScreen(SbVec2f(0.0F, delta));
|
||||
return true;
|
||||
|
||||
case SoKeyboardEvent::RIGHT_ARROW:
|
||||
moveCameraScreen(SbVec2f(0.1f, 0.0f));
|
||||
moveCameraScreen(SbVec2f(delta, 0.0F));
|
||||
return true;
|
||||
|
||||
case SoKeyboardEvent::DOWN_ARROW:
|
||||
moveCameraScreen(SbVec2f(0.0f, -0.1f));
|
||||
moveCameraScreen(SbVec2f(0.0F, -delta));
|
||||
return true;
|
||||
|
||||
default:
|
||||
@@ -730,31 +765,35 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::paintEvent(QPaintEvent* event)
|
||||
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetFrameCounter()
|
||||
{
|
||||
this->framecount = 0;
|
||||
this->frametime = 0.0f;
|
||||
this->drawtime = 0.0f;
|
||||
this->frametime = 0.0F;
|
||||
this->drawtime = 0.0F;
|
||||
this->starttime = SbTime::getTimeOfDay().getValue();
|
||||
this->framesPerSecond = SbVec2f(0, 0);
|
||||
}
|
||||
|
||||
SbVec2f SIM::Coin3D::Quarter::SoQTQuarterAdaptor::addFrametime(double starttime)
|
||||
{
|
||||
constexpr const double FPS_FACTOR = 0.7;
|
||||
constexpr const double FIVE_SECS = 5000.0;
|
||||
constexpr const float ONE_SEC = 1000.0F;
|
||||
|
||||
this->framecount++;
|
||||
|
||||
double timeofday = SbTime::getTimeOfDay().getValue();
|
||||
|
||||
// draw time is the actual time spent on rendering
|
||||
double drawtime = timeofday - starttime;
|
||||
#define FPS_FACTOR 0.7
|
||||
this->drawtime = (drawtime*FPS_FACTOR) + this->drawtime*(1.0-FPS_FACTOR);
|
||||
this->drawtime = (drawtime*FPS_FACTOR) + this->drawtime*(1.0 - FPS_FACTOR);
|
||||
|
||||
// frame time is the time spent since the last frame. There could an
|
||||
// indefinite pause between the last frame because the scene is not
|
||||
// changing. So we limit the skew to 5 second.
|
||||
double frametime = std::min(timeofday-this->starttime, std::max(drawtime,5000.0));
|
||||
this->frametime = (frametime*FPS_FACTOR) + this->frametime*(1.0-FPS_FACTOR);
|
||||
double frametime = std::min(timeofday-this->starttime, std::max(drawtime, FIVE_SECS));
|
||||
this->frametime = (frametime*FPS_FACTOR) + this->frametime*(1.0 - FPS_FACTOR);
|
||||
|
||||
this->starttime = timeofday;
|
||||
return {1000 * float(this->drawtime), 1.0F / float(this->frametime)};
|
||||
return {ONE_SEC * float(this->drawtime), 1.0F / float(this->frametime)};
|
||||
}
|
||||
// NOLINTEND(readability-implicit-bool-conversion)
|
||||
|
||||
#include "moc_SoQTQuarterAdaptor.cpp"
|
||||
|
||||
@@ -47,9 +47,17 @@ class QUARTER_DLL_API SoQTQuarterAdaptor : public QuarterWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SoQTQuarterAdaptor(QWidget* parent = nullptr, const QtGLWidget* sharewidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
explicit SoQTQuarterAdaptor(const QtGLFormat& format, QWidget* parent = nullptr, const QtGLWidget* shareWidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
explicit SoQTQuarterAdaptor(QtGLContext* context, QWidget* parent = nullptr, const QtGLWidget* sharewidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
explicit SoQTQuarterAdaptor(QWidget* parent = nullptr,
|
||||
const QtGLWidget* sharewidget = nullptr,
|
||||
Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
explicit SoQTQuarterAdaptor(const QtGLFormat& format,
|
||||
QWidget* parent = nullptr,
|
||||
const QtGLWidget* shareWidget = nullptr,
|
||||
Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
explicit SoQTQuarterAdaptor(QtGLContext* context,
|
||||
QWidget* parent = nullptr,
|
||||
const QtGLWidget* sharewidget = nullptr,
|
||||
Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
~SoQTQuarterAdaptor() override;
|
||||
|
||||
//the functions available in soqtviewer but missing in quarter
|
||||
@@ -63,8 +71,8 @@ public:
|
||||
|
||||
const SbViewportRegion & getViewportRegion() const;
|
||||
|
||||
virtual void setViewing(SbBool enable);
|
||||
SbBool isViewing() const;
|
||||
virtual void setViewing(bool enable);
|
||||
bool isViewing() const;
|
||||
|
||||
void interactiveCountInc();
|
||||
void interactiveCountDec();
|
||||
@@ -75,72 +83,76 @@ public:
|
||||
void removeStartCallback(SoQTQuarterAdaptorCB* func, void* data = nullptr);
|
||||
void removeFinishCallback(SoQTQuarterAdaptorCB* func, void* data = nullptr);
|
||||
|
||||
virtual void setSeekMode(SbBool enable);
|
||||
SbBool isSeekMode() const;
|
||||
SbBool seekToPoint(const SbVec2s screenpos);
|
||||
virtual void setSeekMode(bool enable);
|
||||
bool isSeekMode() const;
|
||||
bool seekToPoint(const SbVec2s& screenpos);
|
||||
void seekToPoint(const SbVec3f& scenepos);
|
||||
void setSeekTime(const float seconds);
|
||||
void setSeekTime(float seconds);
|
||||
float getSeekTime() const;
|
||||
void setSeekDistance(const float distance);
|
||||
void setSeekDistance(float distance);
|
||||
float getSeekDistance() const;
|
||||
void setSeekValueAsPercentage(const SbBool on);
|
||||
SbBool isSeekValuePercentage() const;
|
||||
void setSeekValueAsPercentage(bool on);
|
||||
bool isSeekValuePercentage() const;
|
||||
|
||||
virtual float getPickRadius() const {return this->pickRadius;}
|
||||
virtual void setPickRadius(float pickRadius);
|
||||
|
||||
virtual void saveHomePosition();
|
||||
virtual void resetToHomePosition();
|
||||
virtual bool hasHomePosition() const {return m_storedcamera;}
|
||||
virtual bool hasHomePosition() const
|
||||
{
|
||||
return m_storedcamera != nullptr;
|
||||
}
|
||||
|
||||
void setSceneGraph(SoNode* root) override {
|
||||
void setSceneGraph(SoNode* root) override
|
||||
{
|
||||
QuarterWidget::setSceneGraph(root);
|
||||
}
|
||||
|
||||
bool processSoEvent(const SoEvent* event) override;
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
//this functions still need to be ported
|
||||
virtual void afterRealizeHook() {} //enables spacenav and joystick in soqt, dunno if this is needed
|
||||
|
||||
private:
|
||||
void init();
|
||||
void convertPerspective2Ortho(const SoPerspectiveCamera* in, SoOrthographicCamera* out);
|
||||
void convertOrtho2Perspective(const SoOrthographicCamera* in, SoPerspectiveCamera* out);
|
||||
static void convertPerspective2Ortho(const SoPerspectiveCamera* in, SoOrthographicCamera* out);
|
||||
static void convertOrtho2Perspective(const SoOrthographicCamera* in, SoPerspectiveCamera* out);
|
||||
void getCameraCoordinateSystem(SoCamera * camera, SoNode * root, SbMatrix & matrix, SbMatrix & inverse);
|
||||
static void seeksensorCB(void * data, SoSensor * s);
|
||||
static void seeksensorCB(void * data, SoSensor * sensor);
|
||||
void moveCameraScreen(const SbVec2f & screenpos);
|
||||
void resetFrameCounter();
|
||||
SbVec2f addFrametime(double ft);
|
||||
|
||||
bool m_viewingflag;
|
||||
int m_interactionnesting;
|
||||
bool m_viewingflag = false;
|
||||
int m_interactionnesting = 0;
|
||||
SoCallbackList m_interactionStartCallback;
|
||||
SoCallbackList m_interactionEndCallback;
|
||||
|
||||
double frametime;
|
||||
double drawtime;
|
||||
double starttime;
|
||||
int framecount;
|
||||
double frametime = 0.0;
|
||||
double drawtime = 0.0;
|
||||
double starttime = 0.0;
|
||||
int framecount = 0.0;
|
||||
|
||||
// Seek functionality
|
||||
SoTimerSensor* m_seeksensor;
|
||||
float m_seekperiod;
|
||||
SbBool m_inseekmode;
|
||||
SoTimerSensor* m_seeksensor = nullptr;
|
||||
float m_seekperiod = 0.0F;
|
||||
bool m_inseekmode = false;
|
||||
SbVec3f m_camerastartposition, m_cameraendposition;
|
||||
SbRotation m_camerastartorient, m_cameraendorient;
|
||||
float m_seekdistance;
|
||||
SbBool m_seekdistanceabs;
|
||||
float m_seekdistance = 0.0F;
|
||||
bool m_seekdistanceabs = false;
|
||||
SoSearchAction searchaction;
|
||||
SoGetMatrixAction matrixaction;
|
||||
float pickRadius;
|
||||
float pickRadius = 0.0F;
|
||||
// Home position storage.
|
||||
SoNode * m_storedcamera;
|
||||
|
||||
SoNode * m_storedcamera = nullptr;
|
||||
|
||||
protected:
|
||||
void draw2DString(const char * str, SbVec2s glsize, SbVec2f position);
|
||||
void printString(const char * s);
|
||||
SbVec2f framesPerSecond;
|
||||
static void draw2DString(const char * str, SbVec2s glsize, SbVec2f position);
|
||||
static void printString(const char * str);
|
||||
SbVec2f framesPerSecond; // NOLINT
|
||||
};
|
||||
|
||||
} //Quarter
|
||||
|
||||
@@ -529,7 +529,7 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d)
|
||||
|
||||
midPoint = (points[0] + points[1]) / 2;
|
||||
|
||||
measureLabel->startEdit(getDistance(points[1]), this);
|
||||
measureLabel->startEdit(getDistance(points[1]), this, true);
|
||||
|
||||
Q_EMIT enableApplyBtn();
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "View3DInventor.h"
|
||||
#include "View3DSettings.h"
|
||||
#include "Application.h"
|
||||
#include "BitmapFactory.h"
|
||||
#include "Camera.h"
|
||||
#include "Document.h"
|
||||
#include "FileDialog.h"
|
||||
@@ -134,6 +135,8 @@ View3DInventor::View3DInventor(Gui::Document* pcDocument, QWidget* parent,
|
||||
|
||||
stopSpinTimer = new QTimer(this);
|
||||
connect(stopSpinTimer, &QTimer::timeout, this, &View3DInventor::stopAnimating);
|
||||
|
||||
setWindowIcon(Gui::BitmapFactory().pixmap("Document"));
|
||||
}
|
||||
|
||||
View3DInventor::~View3DInventor()
|
||||
|
||||
+632
-456
File diff suppressed because it is too large
Load Diff
@@ -54,11 +54,11 @@ class SoShapeHints;
|
||||
class SoMaterial;
|
||||
class SoRotationXYZ;
|
||||
class SbSphereSheetProjector;
|
||||
class SoEventCallback;
|
||||
class SoEventCallback; // NOLINT
|
||||
class SbBox2s;
|
||||
class SoVectorizeAction;
|
||||
class QImage;
|
||||
class SoGroup;
|
||||
class SoGroup; // NOLINT
|
||||
class SoPickStyle;
|
||||
class NaviCube;
|
||||
class SoClipPlane;
|
||||
@@ -153,38 +153,40 @@ public:
|
||||
void onSelectionChanged(const SelectionChanges &Reason) override;
|
||||
|
||||
SoDirectionalLight* getBacklight() const;
|
||||
void setBacklight(SbBool on);
|
||||
SbBool isBacklight() const;
|
||||
void setBacklightEnabled(bool on);
|
||||
bool isBacklightEnabled() const;
|
||||
void setSceneGraph (SoNode *root) override;
|
||||
SbBool searchNode(SoNode*) const;
|
||||
bool searchNode(SoNode*) const;
|
||||
|
||||
void setAnimationEnabled(const SbBool enable);
|
||||
SbBool isAnimationEnabled() const;
|
||||
void setAnimationEnabled(bool enable);
|
||||
bool isAnimationEnabled() const;
|
||||
|
||||
void setPopupMenuEnabled(const SbBool on);
|
||||
SbBool isPopupMenuEnabled() const;
|
||||
void setPopupMenuEnabled(bool on);
|
||||
bool isPopupMenuEnabled() const;
|
||||
|
||||
void startAnimating(const SbVec3f& axis, float velocity);
|
||||
void startAnimation(const SbRotation& orientation, const SbVec3f& rotationCenter,
|
||||
const SbVec3f& translation, int duration = -1, bool wait = false);
|
||||
void startSpinningAnimation(const SbVec3f& axis, float velocity);
|
||||
void stopAnimating();
|
||||
SbBool isAnimating() const;
|
||||
bool isAnimating() const;
|
||||
|
||||
void setFeedbackVisibility(const SbBool enable);
|
||||
SbBool isFeedbackVisible() const;
|
||||
void setFeedbackVisibility(bool enable);
|
||||
bool isFeedbackVisible() const;
|
||||
|
||||
void setFeedbackSize(const int size);
|
||||
void setFeedbackSize(int size);
|
||||
int getFeedbackSize() const;
|
||||
|
||||
/// Get the preferred samples from the user settings
|
||||
static int getNumSamples();
|
||||
void setRenderType(const RenderType type);
|
||||
void setRenderType(RenderType type);
|
||||
RenderType getRenderType() const;
|
||||
void renderToFramebuffer(QtGLFramebufferObject*);
|
||||
QImage grabFramebuffer();
|
||||
void imageFromFramebuffer(int width, int height, int samples,
|
||||
const QColor& bgcolor, QImage& img);
|
||||
|
||||
void setViewing(SbBool enable) override;
|
||||
virtual void setCursorEnabled(SbBool enable);
|
||||
void setViewing(bool enable) override;
|
||||
virtual void setCursorEnabled(bool enable);
|
||||
|
||||
void addGraphicsItem(GLGraphicsItem*);
|
||||
void removeGraphicsItem(GLGraphicsItem*);
|
||||
@@ -195,11 +197,11 @@ public:
|
||||
/** @name Handling of view providers */
|
||||
//@{
|
||||
/// Checks if the view provider is a top-level object of the scene
|
||||
SbBool hasViewProvider(ViewProvider*) const;
|
||||
bool hasViewProvider(ViewProvider*) const;
|
||||
/// Checks if the view provider is part of the scene.
|
||||
/// In contrast to hasViewProvider() this method also checks if the view
|
||||
/// provider is a child of another view provider
|
||||
SbBool containsViewProvider(const ViewProvider*) const;
|
||||
bool containsViewProvider(const ViewProvider*) const;
|
||||
/// adds an ViewProvider to the view, e.g. from a feature
|
||||
void addViewProvider(ViewProvider*);
|
||||
/// remove a ViewProvider
|
||||
@@ -210,9 +212,9 @@ public:
|
||||
/// get all view providers of given type
|
||||
std::vector<ViewProvider*> getViewProvidersOfType(const Base::Type& typeId) const;
|
||||
/// set the ViewProvider in special edit mode
|
||||
void setEditingViewProvider(Gui::ViewProvider* p, int ModNum);
|
||||
void setEditingViewProvider(Gui::ViewProvider* vp, int ModNum);
|
||||
/// return whether a view provider is edited
|
||||
SbBool isEditingViewProvider() const;
|
||||
bool isEditingViewProvider() const;
|
||||
/// reset from edit mode
|
||||
void resetEditingViewProvider();
|
||||
void setupEditingRoot(SoNode *node=nullptr, const Base::Matrix4D *mat=nullptr);
|
||||
@@ -235,10 +237,10 @@ public:
|
||||
/** @name Making pictures */
|
||||
//@{
|
||||
/**
|
||||
* Creates an image with width \a w and height \a h of the current scene graph
|
||||
* using a multi-sampling of \a s and exports the rendered scenegraph to an image.
|
||||
* Creates an image with width \a width and height \a height of the current scene graph
|
||||
* using a multi-sampling of \a sample and exports the rendered scenegraph to an image.
|
||||
*/
|
||||
void savePicture(int w, int h, int s, const QColor&, QImage&) const;
|
||||
void savePicture(int width, int height, int sample, const QColor& bg, QImage& img) const;
|
||||
void saveGraphic(int pagesize, const QColor&, SoVectorizeAction* va) const;
|
||||
//@}
|
||||
/**
|
||||
@@ -255,8 +257,8 @@ public:
|
||||
std::vector<SbVec2f> getGLPolygon(SelectionRole* role=nullptr) const;
|
||||
std::vector<SbVec2f> getGLPolygon(const std::vector<SbVec2s>&) const;
|
||||
const std::vector<SbVec2s>& getPolygon(SelectionRole* role=nullptr) const;
|
||||
void setSelectionEnabled(const SbBool enable);
|
||||
SbBool isSelectionEnabled() const;
|
||||
void setSelectionEnabled(bool enable);
|
||||
bool isSelectionEnabled() const;
|
||||
//@}
|
||||
|
||||
/// Returns the screen coordinates of the origin of the path's tail object
|
||||
@@ -265,14 +267,14 @@ public:
|
||||
|
||||
/** @name Edit methods */
|
||||
//@{
|
||||
void setEditing(SbBool edit);
|
||||
SbBool isEditing() const { return this->editing; }
|
||||
void setEditing(bool edit);
|
||||
bool isEditing() const { return this->editing; }
|
||||
void setEditingCursor (const QCursor& cursor);
|
||||
void setComponentCursor(const QCursor& cursor);
|
||||
void setRedirectToSceneGraph(SbBool redirect) { this->redirected = redirect; }
|
||||
SbBool isRedirectedToSceneGraph() const { return this->redirected; }
|
||||
void setRedirectToSceneGraphEnabled(SbBool enable) { this->allowredir = enable; }
|
||||
SbBool isRedirectToSceneGraphEnabled() const { return this->allowredir; }
|
||||
void setRedirectToSceneGraph(bool redirect) { this->redirected = redirect; }
|
||||
bool isRedirectedToSceneGraph() const { return this->redirected; }
|
||||
void setRedirectToSceneGraphEnabled(bool enable) { this->allowredir = enable; }
|
||||
bool isRedirectToSceneGraphEnabled() const { return this->allowredir; }
|
||||
//@}
|
||||
|
||||
/** @name Pick actions */
|
||||
@@ -281,7 +283,7 @@ public:
|
||||
bool pickPoint(const SbVec2s& pos,SbVec3f &point,SbVec3f &norm) const;
|
||||
SoPickedPoint* pickPoint(const SbVec2s& pos) const;
|
||||
const SoPickedPoint* getPickedPoint(SoEventCallback * n) const;
|
||||
SbBool pubSeekToPoint(const SbVec2s& pos);
|
||||
bool pubSeekToPoint(const SbVec2s& pos);
|
||||
void pubSeekToPoint(const SbVec3f& pos);
|
||||
//@}
|
||||
|
||||
@@ -373,9 +375,9 @@ public:
|
||||
* \a true the reorientation is animated, otherwise its directly
|
||||
* set.
|
||||
*/
|
||||
void setCameraOrientation(const SbRotation& rot, SbBool moveTocenter=false);
|
||||
void setCameraType(SoType t) override;
|
||||
void moveCameraTo(const SbRotation& rot, const SbVec3f& pos, int steps, int ms);
|
||||
void setCameraOrientation(const SbRotation& orientation, bool moveToCenter = false);
|
||||
void setCameraType(SoType type) override;
|
||||
void moveCameraTo(const SbRotation& orientation, const SbVec3f& position, int duration = -1);
|
||||
/**
|
||||
* Zooms the viewport to the size of the bounding box.
|
||||
*/
|
||||
@@ -410,17 +412,17 @@ public:
|
||||
const SbColor& midColor);
|
||||
void setNavigationType(Base::Type);
|
||||
|
||||
void setAxisCross(bool b);
|
||||
void setAxisCross(bool on);
|
||||
bool hasAxisCross();
|
||||
|
||||
void showRotationCenter(bool show);
|
||||
|
||||
void setEnabledFPSCounter(bool b);
|
||||
void setEnabledNaviCube(bool b);
|
||||
void setEnabledFPSCounter(bool on);
|
||||
void setEnabledNaviCube(bool on);
|
||||
bool isEnabledNaviCube() const;
|
||||
void setNaviCubeCorner(int);
|
||||
NaviCube* getNaviCube() const;
|
||||
void setEnabledVBO(bool b);
|
||||
void setEnabledVBO(bool on);
|
||||
bool isEnabledVBO() const;
|
||||
void setRenderCache(int);
|
||||
|
||||
@@ -436,21 +438,21 @@ public:
|
||||
virtual PyObject *getPyObject();
|
||||
|
||||
protected:
|
||||
GLenum getInternalTextureFormat() const;
|
||||
static GLenum getInternalTextureFormat();
|
||||
void renderScene();
|
||||
void renderFramebuffer();
|
||||
void renderGLImage();
|
||||
void animatedViewAll(int steps, int ms);
|
||||
void actualRedraw() override;
|
||||
void setSeekMode(SbBool enable) override;
|
||||
void setSeekMode(bool on) override;
|
||||
void afterRealizeHook() override;
|
||||
bool processSoEvent(const SoEvent * ev) override;
|
||||
void dropEvent (QDropEvent * e) override;
|
||||
void dragEnterEvent (QDragEnterEvent * e) override;
|
||||
void dragMoveEvent(QDragMoveEvent *e) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *e) override;
|
||||
SbBool processSoEventBase(const SoEvent * const ev);
|
||||
void printDimension();
|
||||
void dropEvent (QDropEvent * ev) override;
|
||||
void dragEnterEvent (QDragEnterEvent * ev) override;
|
||||
void dragMoveEvent(QDragMoveEvent* ev) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent* ev) override;
|
||||
bool processSoEventBase(const SoEvent * const ev);
|
||||
void printDimension() const;
|
||||
void selectAll();
|
||||
|
||||
private:
|
||||
@@ -463,13 +465,13 @@ private:
|
||||
static void interactionLoggerCB(void * ud, SoAction* action);
|
||||
|
||||
private:
|
||||
static void selectCB(void * closure, SoPath * p);
|
||||
static void deselectCB(void * closure, SoPath * p);
|
||||
static SoPath * pickFilterCB(void * data, const SoPickedPoint * pick);
|
||||
static void selectCB(void * viewer, SoPath * path);
|
||||
static void deselectCB(void * viewer, SoPath * path);
|
||||
static SoPath * pickFilterCB(void * viewer, const SoPickedPoint * pp);
|
||||
void initialize();
|
||||
void drawAxisCross();
|
||||
static void drawArrow();
|
||||
void drawSingleBackground(const QColor&);
|
||||
static void drawSingleBackground(const QColor&);
|
||||
void setCursorRepresentation(int mode);
|
||||
void aboutToDestroyGLContext() override;
|
||||
void createStandardCursors(double);
|
||||
@@ -504,11 +506,11 @@ private:
|
||||
RenderType renderType;
|
||||
QtGLFramebufferObject* framebuffer;
|
||||
QImage glImage;
|
||||
SbBool shading;
|
||||
bool shading;
|
||||
SoSwitch *dimensionRoot;
|
||||
|
||||
// small axis cross in the corner
|
||||
SbBool axiscrossEnabled;
|
||||
bool axiscrossEnabled;
|
||||
int axiscrossSize;
|
||||
// big one in the middle
|
||||
SoShapeScale* axisCross;
|
||||
@@ -519,12 +521,12 @@ private:
|
||||
//stuff needed to draw the fps counter
|
||||
bool fpsEnabled;
|
||||
bool vboEnabled;
|
||||
SbBool naviCubeEnabled;
|
||||
bool naviCubeEnabled;
|
||||
|
||||
SbBool editing;
|
||||
bool editing;
|
||||
QCursor editCursor, zoomCursor, panCursor, spinCursor;
|
||||
SbBool redirected;
|
||||
SbBool allowredir;
|
||||
bool redirected;
|
||||
bool allowredir;
|
||||
|
||||
std::string overrideMode;
|
||||
Gui::Document* guiDocument = nullptr;
|
||||
|
||||
@@ -777,10 +777,10 @@ Py::Object View3DInventorPy::getCameraOrientation()
|
||||
|
||||
Py::Object View3DInventorPy::viewPosition(const Py::Tuple& args)
|
||||
{
|
||||
PyObject* p=nullptr;
|
||||
int steps = 20;
|
||||
int ms = 30;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "|O!ii",&Base::PlacementPy::Type,&p,&steps,&ms))
|
||||
PyObject* p = nullptr;
|
||||
int steps; // Unused but kept as parameter to not break the Python interface
|
||||
int duration = -1; // Duration in ms, will be replaced with User parameter:BaseApp/Preferences/View/AnimationDuration when not explicitly provided
|
||||
if (!PyArg_ParseTuple(args.ptr(), "|O!ii", &Base::PlacementPy::Type, &p, &steps, &duration))
|
||||
throw Py::Exception();
|
||||
|
||||
if (p) {
|
||||
@@ -791,7 +791,7 @@ Py::Object View3DInventorPy::viewPosition(const Py::Tuple& args)
|
||||
rot.getValue(q0,q1,q2,q3);
|
||||
getView3DIventorPtr()->getViewer()->moveCameraTo(
|
||||
SbRotation((float)q0, (float)q1, (float)q2, (float)q3),
|
||||
SbVec3f((float)pos.x, (float)pos.y, (float)pos.z), steps, ms);
|
||||
SbVec3f((float)pos.x, (float)pos.y, (float)pos.z), duration);
|
||||
}
|
||||
|
||||
SoCamera* cam = getView3DIventorPtr()->getViewer()->getSoRenderManager()->getCamera();
|
||||
@@ -810,11 +810,11 @@ Py::Object View3DInventorPy::viewPosition(const Py::Tuple& args)
|
||||
|
||||
Py::Object View3DInventorPy::startAnimating(const Py::Tuple& args)
|
||||
{
|
||||
float x,y,z;
|
||||
float x, y, z;
|
||||
float velocity;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "ffff", &x,&y,&z,&velocity))
|
||||
if (!PyArg_ParseTuple(args.ptr(), "ffff", &x, &y, &z, &velocity))
|
||||
throw Py::Exception();
|
||||
getView3DIventorPtr()->getViewer()->startAnimating(SbVec3f(x,y,z),velocity);
|
||||
getView3DIventorPtr()->getViewer()->startSpinningAnimation(SbVec3f(x, y, z), velocity);
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ void View3DSettings::applySettings()
|
||||
OnChange(*hGrp,"CornerCoordSystem");
|
||||
OnChange(*hGrp,"CornerCoordSystemSize");
|
||||
OnChange(*hGrp,"ShowAxisCross");
|
||||
OnChange(*hGrp,"UseAutoRotation");
|
||||
OnChange(*hGrp,"UseNavigationAnimations");
|
||||
OnChange(*hGrp,"Gradient");
|
||||
OnChange(*hGrp,"RadialGradient");
|
||||
OnChange(*hGrp,"BackgroundColor");
|
||||
@@ -87,6 +87,7 @@ void View3DSettings::applySettings()
|
||||
OnChange(*hGrp,"UseVBO");
|
||||
OnChange(*hGrp,"RenderCache");
|
||||
OnChange(*hGrp,"Orthographic");
|
||||
OnChange(*hGrp,"EnableHeadlight");
|
||||
OnChange(*hGrp,"HeadlightColor");
|
||||
OnChange(*hGrp,"HeadlightDirection");
|
||||
OnChange(*hGrp,"HeadlightIntensity");
|
||||
@@ -108,7 +109,13 @@ void View3DSettings::applySettings()
|
||||
void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason)
|
||||
{
|
||||
const ParameterGrp& rGrp = static_cast<ParameterGrp&>(rCaller);
|
||||
if (strcmp(Reason,"HeadlightColor") == 0) {
|
||||
if (strcmp(Reason,"EnableHeadlight") == 0) {
|
||||
bool enable = rGrp.GetBool("EnableHeadlight", true);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->setHeadlightEnabled(enable);
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"HeadlightColor") == 0) {
|
||||
unsigned long headlight = rGrp.GetUnsigned("HeadlightColor",ULONG_MAX); // default color (white)
|
||||
float transparency;
|
||||
SbColor headlightColor;
|
||||
@@ -137,7 +144,7 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
||||
}
|
||||
else if (strcmp(Reason,"EnableBacklight") == 0) {
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->setBacklight(rGrp.GetBool("EnableBacklight", false));
|
||||
_viewer->setBacklightEnabled(rGrp.GetBool("EnableBacklight", false));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"BacklightColor") == 0) {
|
||||
@@ -287,9 +294,9 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
||||
_viewer->setAxisCross(rGrp.GetBool("ShowAxisCross", false));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"UseAutoRotation") == 0) {
|
||||
else if (strcmp(Reason,"UseNavigationAnimations") == 0) {
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->setAnimationEnabled(rGrp.GetBool("UseAutoRotation", false));
|
||||
_viewer->setAnimationEnabled(rGrp.GetBool("UseNavigationAnimations", true));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"Gradient") == 0 || strcmp(Reason,"RadialGradient") == 0) {
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "PreferencePages/DlgSettingsEditor.h"
|
||||
#include "PreferencePages/DlgSettingsGeneral.h"
|
||||
#include "PreferencePages/DlgSettingsMacroImp.h"
|
||||
#include "PreferencePages/DlgSettingsLightSources.h"
|
||||
#include "PreferencePages/DlgSettingsNavigation.h"
|
||||
#include "PreferencePages/DlgSettingsNotificationArea.h"
|
||||
#include "PreferencePages/DlgSettingsPythonConsole.h"
|
||||
@@ -58,6 +59,7 @@
|
||||
using namespace Gui;
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* Registers all preference pages or widgets to create them dynamically at any later time.
|
||||
*/
|
||||
@@ -74,6 +76,7 @@ WidgetFactorySupplier::WidgetFactorySupplier()
|
||||
new PrefPageProducer<DlgSettingsNotificationArea> ( QT_TRANSLATE_NOOP("QObject","General") );
|
||||
new PrefPageProducer<DlgSettingsReportView> ( QT_TRANSLATE_NOOP("QObject","General") );
|
||||
new PrefPageProducer<DlgSettings3DViewImp> ( QT_TRANSLATE_NOOP("QObject","Display") );
|
||||
new PrefPageProducer<DlgSettingsLightSources> ( QT_TRANSLATE_NOOP("QObject","Display") );
|
||||
new PrefPageProducer<DlgSettingsUI> ( QT_TRANSLATE_NOOP("QObject","Display") );
|
||||
new PrefPageProducer<DlgSettingsNavigation> ( QT_TRANSLATE_NOOP("QObject","Display") );
|
||||
new PrefPageProducer<DlgSettingsViewColor> ( QT_TRANSLATE_NOOP("QObject","Display") );
|
||||
@@ -122,3 +125,4 @@ WidgetFactorySupplier::WidgetFactorySupplier()
|
||||
new WidgetProducer<Gui::DoubleSpinBox>;
|
||||
new WidgetProducer<Gui::QuantitySpinBox>;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -301,9 +301,10 @@ class CommandBuildingPart:
|
||||
ss += "]"
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create BuildingPart"))
|
||||
FreeCADGui.addModule("Arch")
|
||||
FreeCADGui.doCommand("obj = Arch.makeBuildingPart("+ss+")")
|
||||
FreeCADGui.addModule("Draft")
|
||||
FreeCADGui.doCommand("obj.Placement = FreeCAD.DraftWorkingPlane.getPlacement()")
|
||||
FreeCADGui.addModule("WorkingPlane")
|
||||
FreeCADGui.doCommand("obj = Arch.makeBuildingPart("+ss+")")
|
||||
FreeCADGui.doCommand("obj.Placement = WorkingPlane.get_working_plane().get_placement()")
|
||||
FreeCADGui.doCommand("Draft.autogroup(obj)")
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
@@ -963,30 +964,22 @@ class ViewProviderBuildingPart:
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
|
||||
def setWorkingPlane(self,restore=False):
|
||||
vobj = self.Object.ViewObject
|
||||
|
||||
if hasattr(self,"Object") and hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
import FreeCADGui
|
||||
autoclip = False
|
||||
if hasattr(self.Object.ViewObject,"AutoCutView"):
|
||||
autoclip = self.Object.ViewObject.AutoCutView
|
||||
if restore:
|
||||
FreeCAD.DraftWorkingPlane.restore()
|
||||
if autoclip:
|
||||
self.Object.ViewObject.CutView = False
|
||||
else:
|
||||
FreeCAD.DraftWorkingPlane.save()
|
||||
FreeCADGui.runCommand("Draft_SelectPlane")
|
||||
if autoclip:
|
||||
self.Object.ViewObject.CutView = True
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
FreeCADGui.Snapper.setGrid()
|
||||
if hasattr(FreeCADGui,"draftToolBar"):
|
||||
if restore and hasattr(self,"wptext"):
|
||||
FreeCADGui.draftToolBar.wplabel.setText(self.wptext)
|
||||
else:
|
||||
self.wptext = FreeCADGui.draftToolBar.wplabel.text()
|
||||
FreeCADGui.draftToolBar.wplabel.setText(self.Object.Label)
|
||||
FreeCAD.DraftWorkingPlane.lastBuildingPart = self.Object.Name
|
||||
import WorkingPlane
|
||||
wp = WorkingPlane.get_working_plane(update=False)
|
||||
autoclip = False
|
||||
if hasattr(vobj,"AutoCutView"):
|
||||
autoclip = vobj.AutoCutView
|
||||
if restore:
|
||||
if wp.label.rstrip("*") == self.Object.Label:
|
||||
wp._previous()
|
||||
if autoclip:
|
||||
vobj.CutView = False
|
||||
else:
|
||||
wp.align_to_selection()
|
||||
if autoclip:
|
||||
vobj.CutView = True
|
||||
|
||||
def writeCamera(self):
|
||||
|
||||
|
||||
@@ -124,8 +124,8 @@ class CommandArchCurtainWall:
|
||||
else:
|
||||
# interactive line drawing
|
||||
self.points = []
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
FreeCAD.DraftWorkingPlane.setup()
|
||||
import WorkingPlane
|
||||
WorkingPlane.get_working_plane()
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint)
|
||||
|
||||
|
||||
@@ -46,8 +46,9 @@ __url__ = "http://www.freecad.org"
|
||||
def getPlanWithLine(line):
|
||||
"""Function to make a plane along Normal plan"""
|
||||
import Part
|
||||
plan = FreeCAD.DraftWorkingPlane
|
||||
w = plan.getNormal()
|
||||
import WorkingPlane
|
||||
plan = WorkingPlane.get_working_plane()
|
||||
w = plan.axis
|
||||
part = Part.Shape(line)
|
||||
out = part.extrude(w)
|
||||
return out
|
||||
|
||||
@@ -583,8 +583,8 @@ class Nester:
|
||||
|
||||
# flatten the polygon on the XY plane
|
||||
|
||||
wp = WorkingPlane.plane()
|
||||
wp.alignToPointAndAxis(face.CenterOfMass,face.normalAt(0,0))
|
||||
wp = WorkingPlane.PlaneBase()
|
||||
wp.align_to_point_and_axis(face.CenterOfMass,face.normalAt(0,0))
|
||||
pverts = []
|
||||
for v in verts:
|
||||
vx = DraftVecUtils.project(v,wp.u)
|
||||
|
||||
@@ -165,9 +165,9 @@ class CommandPanel:
|
||||
return
|
||||
|
||||
# interactive mode
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
FreeCAD.DraftWorkingPlane.setup()
|
||||
|
||||
import WorkingPlane
|
||||
WorkingPlane.get_working_plane()
|
||||
|
||||
self.points = []
|
||||
self.tracker = DraftTrackers.boxTracker()
|
||||
self.tracker.width(self.Width)
|
||||
@@ -434,8 +434,6 @@ class _Panel(ArchComponent.Component):
|
||||
if self.clone(obj):
|
||||
return
|
||||
|
||||
import Part #, DraftGeomUtils
|
||||
|
||||
layers = []
|
||||
length = 0
|
||||
width = 0
|
||||
|
||||
@@ -74,7 +74,8 @@ def makeSectionPlane(objectslist=None,name=None):
|
||||
for o in Draft.get_group_contents(objectslist):
|
||||
if hasattr(o,"Shape") and hasattr(o.Shape,"BoundBox"):
|
||||
bb.add(o.Shape.BoundBox)
|
||||
obj.Placement = FreeCAD.DraftWorkingPlane.getPlacement()
|
||||
import WorkingPlane
|
||||
obj.Placement = WorkingPlane.get_working_plane().get_placement()
|
||||
obj.Placement.Base = bb.Center
|
||||
if FreeCAD.GuiUp:
|
||||
margin = bb.XLength*0.1
|
||||
@@ -391,13 +392,13 @@ def getSVG(source,
|
||||
svgcache = ''
|
||||
# render using the Arch Vector Renderer
|
||||
import ArchVRM, WorkingPlane
|
||||
wp = WorkingPlane.plane()
|
||||
wp = WorkingPlane.PlaneBase()
|
||||
pl = FreeCAD.Placement(source.Placement)
|
||||
if source.ViewObject and hasattr(source.ViewObject,"CutMargin"):
|
||||
mv = pl.multVec(FreeCAD.Vector(0,0,1))
|
||||
mv.multiply(source.ViewObject.CutMargin)
|
||||
pl.move(mv)
|
||||
wp.setFromPlacement(pl)
|
||||
wp.align_to_placement(pl)
|
||||
#wp.inverse()
|
||||
render = ArchVRM.Renderer()
|
||||
render.setWorkingPlane(wp)
|
||||
@@ -748,9 +749,9 @@ def getCoinSVG(cutplane,objs,cameradata=None,linewidth=0.2,singleface=False,face
|
||||
factor = None
|
||||
trans = None
|
||||
import WorkingPlane
|
||||
wp = WorkingPlane.plane()
|
||||
wp.alignToPointAndAxis_SVG(Vector(0,0,0),cutplane.normalAt(0,0),0)
|
||||
p = wp.getLocalCoords(markervec)
|
||||
wp = WorkingPlane.PlaneBase()
|
||||
wp.align_to_point_and_axis_svg(Vector(0,0,0),cutplane.normalAt(0,0),0)
|
||||
p = wp.get_local_coords(markervec)
|
||||
orlength = FreeCAD.Vector(p.x,p.y,0).Length
|
||||
marker = re.findall("<line x1=.*?stroke=\"\#ffffff\".*?\/>",svg)
|
||||
if marker:
|
||||
@@ -763,7 +764,7 @@ def getCoinSVG(cutplane,objs,cameradata=None,linewidth=0.2,singleface=False,face
|
||||
p2 = FreeCAD.Vector(x2,y2,0)
|
||||
factor = orlength/p2.sub(p1).Length
|
||||
if factor:
|
||||
orig = wp.getLocalCoords(FreeCAD.Vector(boundbox.XMin,boundbox.YMin,boundbox.ZMin))
|
||||
orig = wp.get_local_coords(FreeCAD.Vector(boundbox.XMin,boundbox.YMin,boundbox.ZMin))
|
||||
orig = FreeCAD.Vector(orig.x,-orig.y,0)
|
||||
scaledp1 = FreeCAD.Vector(p1.x*factor,p1.y*factor,0)
|
||||
trans = orig.sub(scaledp1)
|
||||
|
||||
@@ -170,9 +170,8 @@ def placeAlongEdge(p1,p2,horizontal=False):
|
||||
|
||||
pl = FreeCAD.Placement()
|
||||
pl.Base = p1
|
||||
up = FreeCAD.Vector(0,0,1)
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
up = FreeCAD.DraftWorkingPlane.axis
|
||||
import WorkingPlane
|
||||
up = WorkingPlane.get_working_plane(update=False).axis
|
||||
zaxis = p2.sub(p1)
|
||||
yaxis = up.cross(zaxis)
|
||||
if yaxis.Length > 0:
|
||||
@@ -290,6 +289,7 @@ class _CommandStructure:
|
||||
self.bpoint = None
|
||||
self.bmode = False
|
||||
self.precastvalues = None
|
||||
self.wp = None
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if sel:
|
||||
st = Draft.getObjectsOfType(sel,"Structure")
|
||||
@@ -309,15 +309,15 @@ class _CommandStructure:
|
||||
return
|
||||
|
||||
# interactive mode
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
FreeCAD.DraftWorkingPlane.setup()
|
||||
import WorkingPlane
|
||||
self.wp = WorkingPlane.get_working_plane()
|
||||
|
||||
self.points = []
|
||||
self.tracker = DraftTrackers.boxTracker()
|
||||
self.tracker.width(self.Width)
|
||||
self.tracker.height(self.Height)
|
||||
self.tracker.length(self.Length)
|
||||
self.tracker.setRotation(FreeCAD.DraftWorkingPlane.getRotation().Rotation)
|
||||
self.tracker.setRotation(self.wp.get_placement().Rotation)
|
||||
self.tracker.on()
|
||||
self.precast = ArchPrecast._PrecastTaskPanel()
|
||||
self.dents = ArchPrecast._DentsTaskPanel()
|
||||
@@ -344,6 +344,7 @@ class _CommandStructure:
|
||||
horiz = True # determines the type of rotation to apply to the final object
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Structure"))
|
||||
FreeCADGui.addModule("Arch")
|
||||
FreeCADGui.addModule("WorkingPlane")
|
||||
if self.Profile is not None:
|
||||
try: # try to update latest precast values - fails if dialog has been destroyed already
|
||||
self.precastvalues = self.precast.getValues()
|
||||
@@ -361,8 +362,7 @@ class _CommandStructure:
|
||||
delta = FreeCAD.Vector(0,0-self.Width/2,0)
|
||||
else:
|
||||
delta = FreeCAD.Vector(-self.Length/2,-self.Width/2,0)
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
delta = FreeCAD.DraftWorkingPlane.getRotation().multVec(delta)
|
||||
delta = self.wp.get_global_coords(delta,as_vector=True)
|
||||
point = point.add(delta)
|
||||
if self.bpoint:
|
||||
self.bpoint = self.bpoint.add(delta)
|
||||
@@ -396,7 +396,8 @@ class _CommandStructure:
|
||||
FreeCADGui.doCommand('s.Placement = Arch.placeAlongEdge('+DraftVecUtils.toString(self.bpoint)+","+DraftVecUtils.toString(point)+","+str(horiz)+")")
|
||||
else:
|
||||
FreeCADGui.doCommand('s.Placement.Base = '+DraftVecUtils.toString(point))
|
||||
FreeCADGui.doCommand('s.Placement.Rotation = s.Placement.Rotation.multiply(FreeCAD.DraftWorkingPlane.getRotation().Rotation)')
|
||||
FreeCADGui.doCommand('wp = WorkingPlane.get_working_plane()')
|
||||
FreeCADGui.doCommand('s.Placement.Rotation = s.Placement.Rotation.multiply(wp.get_placement().Rotation)')
|
||||
|
||||
FreeCADGui.addModule("Draft")
|
||||
FreeCADGui.doCommand("Draft.autogroup(s)")
|
||||
@@ -543,16 +544,14 @@ class _CommandStructure:
|
||||
delta = Vector(0,0,self.Height/2)
|
||||
else:
|
||||
delta = Vector(self.Length/2,0,0)
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
delta = FreeCAD.DraftWorkingPlane.getRotation().multVec(delta)
|
||||
delta = self.wp.get_global_coords(delta,as_vector=True)
|
||||
if self.modec.isChecked():
|
||||
self.tracker.pos(point.add(delta))
|
||||
self.tracker.on()
|
||||
else:
|
||||
if self.bpoint:
|
||||
delta = Vector(0,0,-self.Height/2)
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
delta = FreeCAD.DraftWorkingPlane.getRotation().multVec(delta)
|
||||
delta = self.wp.get_global_coords(delta,as_vector=True)
|
||||
self.tracker.update([self.bpoint.add(delta),point.add(delta)])
|
||||
self.tracker.on()
|
||||
l = (point.sub(self.bpoint)).Length
|
||||
|
||||
@@ -105,8 +105,8 @@ class CommandArchTruss:
|
||||
else:
|
||||
# interactive line drawing
|
||||
self.points = []
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
FreeCAD.DraftWorkingPlane.setup()
|
||||
import WorkingPlane
|
||||
WorkingPlane.get_working_plane()
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint)
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class Renderer:
|
||||
self.wp = wp
|
||||
else:
|
||||
import WorkingPlane
|
||||
self.wp = WorkingPlane.plane()
|
||||
self.wp = WorkingPlane.PlaneBase()
|
||||
|
||||
if DEBUG: print("Renderer initialized on " + str(self.wp))
|
||||
|
||||
@@ -92,7 +92,7 @@ class Renderer:
|
||||
def setWorkingPlane(self,wp):
|
||||
"sets a Draft WorkingPlane or Placement for this renderer"
|
||||
if isinstance(wp,FreeCAD.Placement):
|
||||
self.wp.setFromPlacement(wp)
|
||||
self.wp.align_to_placement(wp)
|
||||
else:
|
||||
self.wp = wp
|
||||
if DEBUG: print("Renderer set on " + str(self.wp))
|
||||
@@ -198,7 +198,7 @@ class Renderer:
|
||||
for e in edges:
|
||||
v = e.Vertexes[0].Point
|
||||
#print(v)
|
||||
v = self.wp.getLocalCoords(v)
|
||||
v = self.wp.get_local_coords(v)
|
||||
verts.append(v)
|
||||
verts.append(verts[0])
|
||||
if len(verts) > 2:
|
||||
@@ -211,7 +211,7 @@ class Renderer:
|
||||
return None
|
||||
else:
|
||||
# restoring flipped normals
|
||||
vnorm = self.wp.getLocalCoords(norm)
|
||||
vnorm = self.wp.get_local_coords(norm)
|
||||
if vnorm.getAngle(sh.normalAt(0,0)) > 1:
|
||||
sh.reverse()
|
||||
#print("VRM: projectFace end: ",len(sh.Vertexes)," verts")
|
||||
@@ -220,8 +220,8 @@ class Renderer:
|
||||
def projectEdge(self,edge):
|
||||
"projects a single edge on the WP"
|
||||
if len(edge.Vertexes) > 1:
|
||||
v1 = self.wp.getLocalCoords(edge.Vertexes[0].Point)
|
||||
v2 = self.wp.getLocalCoords(edge.Vertexes[-1].Point)
|
||||
v1 = self.wp.get_local_coords(edge.Vertexes[0].Point)
|
||||
v2 = self.wp.get_local_coords(edge.Vertexes[-1].Point)
|
||||
return Part.LineSegment(v1,v2).toShape()
|
||||
return edge
|
||||
|
||||
@@ -293,7 +293,7 @@ class Renderer:
|
||||
|
||||
# http://paulbourke.net/geometry/insidepoly/
|
||||
count = 0
|
||||
p = self.wp.getLocalCoords(vert.Point)
|
||||
p = self.wp.get_local_coords(vert.Point)
|
||||
for e in face[0].Edges:
|
||||
p1 = e.Vertexes[0].Point
|
||||
p2 = e.Vertexes[-1].Point
|
||||
|
||||
@@ -316,6 +316,7 @@ class _CommandWall:
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
done = False
|
||||
self.existing = []
|
||||
self.wp = None
|
||||
|
||||
if sel:
|
||||
# automatic mode
|
||||
@@ -345,9 +346,9 @@ class _CommandWall:
|
||||
# interactive mode
|
||||
|
||||
self.points = []
|
||||
import WorkingPlane
|
||||
self.wp = WorkingPlane.get_working_plane()
|
||||
self.tracker = DraftTrackers.boxTracker()
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
FreeCAD.DraftWorkingPlane.setup()
|
||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint,
|
||||
extradlg=self.taskbox(),
|
||||
title=translate("Arch","First point of wall")+":")
|
||||
@@ -386,8 +387,8 @@ class _CommandWall:
|
||||
|
||||
elif len(self.points) == 2:
|
||||
import Part
|
||||
l = Part.LineSegment(FreeCAD.DraftWorkingPlane.getLocalCoords(self.points[0]),
|
||||
FreeCAD.DraftWorkingPlane.getLocalCoords(self.points[1]))
|
||||
l = Part.LineSegment(self.wp.get_local_coords(self.points[0]),
|
||||
self.wp.get_local_coords(self.points[1]))
|
||||
self.tracker.finalize()
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Wall"))
|
||||
FreeCADGui.addModule("Arch")
|
||||
@@ -431,6 +432,8 @@ class _CommandWall:
|
||||
"""
|
||||
|
||||
FreeCADGui.addModule("Draft")
|
||||
FreeCADGui.addModule("WorkingPlane")
|
||||
FreeCADGui.doCommand("wp = WorkingPlane.get_working_plane()")
|
||||
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("WallSketches",True):
|
||||
# Use ArchSketch if SketchArch add-on is present
|
||||
try:
|
||||
@@ -439,13 +442,13 @@ class _CommandWall:
|
||||
FreeCADGui.doCommand('base=ArchSketchObject.makeArchSketch()')
|
||||
except:
|
||||
FreeCADGui.doCommand('base=FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace")')
|
||||
FreeCADGui.doCommand('base.Placement = FreeCAD.DraftWorkingPlane.getPlacement()')
|
||||
FreeCADGui.doCommand('base.Placement = wp.get_placement()')
|
||||
FreeCADGui.doCommand('base.addGeometry(trace)')
|
||||
else:
|
||||
FreeCADGui.doCommand('base=Draft.makeLine(trace)')
|
||||
FreeCADGui.doCommand('FreeCAD.ActiveDocument.recompute()')
|
||||
FreeCADGui.doCommand('wall = Arch.makeWall(base,width='+str(self.Width)+',height='+str(self.Height)+',align="'+str(self.Align)+'")')
|
||||
FreeCADGui.doCommand('wall.Normal = FreeCAD.DraftWorkingPlane.getNormal()')
|
||||
FreeCADGui.doCommand('wall.Normal = wp.axis')
|
||||
if self.MultiMat:
|
||||
FreeCADGui.doCommand("wall.Material = FreeCAD.ActiveDocument."+self.MultiMat.Name)
|
||||
FreeCADGui.doCommand("Draft.autogroup(wall)")
|
||||
@@ -467,7 +470,7 @@ class _CommandWall:
|
||||
|
||||
if FreeCADGui.Control.activeDialog():
|
||||
b = self.points[0]
|
||||
n = FreeCAD.DraftWorkingPlane.axis
|
||||
n = self.wp.axis
|
||||
bv = point.sub(b)
|
||||
dv = bv.cross(n)
|
||||
dv = DraftVecUtils.scaleTo(dv,self.Width/2)
|
||||
|
||||
@@ -186,6 +186,7 @@ class _CommandWindow:
|
||||
self.Include = True
|
||||
self.baseFace = None
|
||||
self.wparams = ["Width","Height","H1","H2","H3","W1","W2","O1","O2"]
|
||||
self.wp = None
|
||||
|
||||
# autobuild mode
|
||||
if FreeCADGui.Selection.getSelectionEx():
|
||||
@@ -235,8 +236,8 @@ class _CommandWindow:
|
||||
return
|
||||
|
||||
# interactive mode
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
FreeCAD.DraftWorkingPlane.setup()
|
||||
import WorkingPlane
|
||||
self.wp = WorkingPlane.get_working_plane()
|
||||
|
||||
self.tracker = DraftTrackers.boxTracker()
|
||||
self.tracker.length(self.Width)
|
||||
@@ -274,8 +275,8 @@ class _CommandWindow:
|
||||
point = point.add(FreeCAD.Vector(0,0,self.Sill))
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Window"))
|
||||
|
||||
FreeCADGui.doCommand("import math, FreeCAD, Arch, DraftGeomUtils")
|
||||
FreeCADGui.doCommand("wp = FreeCAD.DraftWorkingPlane")
|
||||
FreeCADGui.doCommand("import math, FreeCAD, Arch, DraftGeomUtils, WorkingPlane")
|
||||
FreeCADGui.doCommand("wp = WorkingPlane.get_working_plane()")
|
||||
|
||||
if self.baseFace is not None:
|
||||
FreeCADGui.doCommand("face = FreeCAD.ActiveDocument." + self.baseFace[0].Name + ".Shape.Faces[" + str(self.baseFace[1]) + "]")
|
||||
@@ -342,9 +343,8 @@ class _CommandWindow:
|
||||
delta = FreeCAD.Vector(self.Width/2,self.Thickness/2,self.Height/2)
|
||||
delta = delta.add(FreeCAD.Vector(0,0,self.Sill))
|
||||
|
||||
wp = FreeCAD.DraftWorkingPlane
|
||||
if self.baseFace is None:
|
||||
rot = FreeCAD.Rotation(wp.u,wp.v,-wp.axis,"XZY")
|
||||
rot = FreeCAD.Rotation(self.wp.u,self.wp.v,-self.wp.axis,"XZY")
|
||||
self.tracker.setRotation(rot)
|
||||
if info:
|
||||
if "Face" in info['Component']:
|
||||
@@ -353,7 +353,7 @@ class _CommandWindow:
|
||||
self.baseFace = [o,int(info['Component'][4:])-1]
|
||||
#print("switching to ",o.Label," face ",self.baseFace[1])
|
||||
f = o.Shape.Faces[self.baseFace[1]]
|
||||
p = DraftGeomUtils.placement_from_face(f,vec_z=wp.axis,rotated=True)
|
||||
p = DraftGeomUtils.placement_from_face(f,vec_z=self.wp.axis,rotated=True)
|
||||
rot = p.Rotation
|
||||
self.tracker.setRotation(rot)
|
||||
r = self.tracker.trans.rotation.getValue().getValue()
|
||||
|
||||
@@ -714,9 +714,7 @@ def getRotation(entity):
|
||||
w = FreeCAD.Vector(entity.Axis3.DirectionRatios)
|
||||
except AttributeError:
|
||||
return FreeCAD.Rotation()
|
||||
import WorkingPlane
|
||||
p = WorkingPlane.plane(u=u, v=v, w=w)
|
||||
return p.getRotation().Rotation
|
||||
return FreeCAD.Rotation(u, v, w, "ZYX")
|
||||
|
||||
|
||||
def getPlacement(entity,scaling=1000):
|
||||
|
||||
@@ -73,6 +73,7 @@ class Draft_SelectPlane:
|
||||
App.activeDraftCommand.finish()
|
||||
|
||||
App.activeDraftCommand = self
|
||||
self.call = None
|
||||
|
||||
# Set variables
|
||||
self.wp = WorkingPlane.get_working_plane()
|
||||
@@ -134,6 +135,7 @@ class Draft_SelectPlane:
|
||||
if Gui.Selection.hasSelection():
|
||||
if self.wp.align_to_selection(self.offset):
|
||||
Gui.Selection.clearSelection()
|
||||
self.finish()
|
||||
return
|
||||
|
||||
# Execute the actual task panel delayed to catch possible active Draft command
|
||||
|
||||
@@ -77,6 +77,7 @@ class Facebinder(DraftObject):
|
||||
if "Face" in sub:
|
||||
try:
|
||||
face = Part.getShape(sel[0], sub, needSubElement=True, retType=0)
|
||||
area += face.Area
|
||||
if offs_val:
|
||||
if face.Surface.isPlanar():
|
||||
norm = face.normalAt(0, 0)
|
||||
@@ -86,14 +87,14 @@ class Facebinder(DraftObject):
|
||||
else:
|
||||
offs = face.makeOffsetShape(offs_val, 1e-7)
|
||||
faces.extend(offs.Faces)
|
||||
area += face.Area
|
||||
else:
|
||||
faces.append(face)
|
||||
except Part.OCCError:
|
||||
print("Draft: error building facebinder")
|
||||
return
|
||||
if not faces:
|
||||
return
|
||||
try:
|
||||
sh = None
|
||||
if extr_val:
|
||||
extrs = []
|
||||
for face in faces:
|
||||
@@ -103,23 +104,26 @@ class Facebinder(DraftObject):
|
||||
else:
|
||||
extr = face.makeOffsetShape(extr_val, 1e-7, fill=True)
|
||||
extrs.extend(extr.Solids)
|
||||
sh = extrs.pop()
|
||||
sh = sh.multiFuse(extrs)
|
||||
shp = Part.Shape() # create empty shape to ensure default Placement
|
||||
shp = shp.fuse(extrs.pop()) # add 1st shape, multiFuse does not work otherwise
|
||||
if extrs:
|
||||
shp = shp.multiFuse(extrs) # multiFuse is more reliable than serial fuse
|
||||
else:
|
||||
shp = Part.Shape()
|
||||
shp = shp.fuse(faces.pop())
|
||||
if faces:
|
||||
shp = shp.multiFuse(faces)
|
||||
if len(faces) > 1:
|
||||
if not sh:
|
||||
sh = faces.pop()
|
||||
sh = sh.multiFuse(faces)
|
||||
if hasattr(obj, "Sew") and obj.Sew:
|
||||
sh.sewShape()
|
||||
shp.sewShape()
|
||||
if not hasattr(obj, "RemoveSplitter"):
|
||||
sh = sh.removeSplitter()
|
||||
shp = shp.removeSplitter()
|
||||
elif obj.RemoveSplitter:
|
||||
sh = sh.removeSplitter()
|
||||
shp = shp.removeSplitter()
|
||||
except Part.OCCError:
|
||||
print("Draft: error building facebinder")
|
||||
return
|
||||
obj.Shape = sh
|
||||
obj.Placement = pl
|
||||
obj.Shape = shp
|
||||
obj.Area = area
|
||||
self.props_changed_clear()
|
||||
|
||||
|
||||
@@ -66,24 +66,28 @@ TaskFemConstraintTemperature::TaskFemConstraintTemperature(
|
||||
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
|
||||
|
||||
// Fill data into dialog elements
|
||||
ui->if_temperature->setMinimum(0);
|
||||
ui->if_temperature->setMaximum(FLOAT_MAX);
|
||||
ui->qsb_temperature->setMinimum(0);
|
||||
ui->qsb_temperature->setMaximum(FLOAT_MAX);
|
||||
ui->qsb_cflux->setMinimum(-FLOAT_MAX);
|
||||
ui->qsb_cflux->setMaximum(FLOAT_MAX);
|
||||
|
||||
std::string constraint_type = pcConstraint->ConstraintType.getValueAsString();
|
||||
if (constraint_type == "Temperature") {
|
||||
ui->rb_temperature->setChecked(true);
|
||||
ui->if_temperature->setValue(pcConstraint->Temperature.getQuantityValue());
|
||||
App::PropertyEnumeration* constrType = &pcConstraint->ConstraintType;
|
||||
QStringList qTypeList;
|
||||
for (auto item : constrType->getEnumVector()) {
|
||||
qTypeList << QString::fromUtf8(item.c_str());
|
||||
}
|
||||
|
||||
ui->if_temperature->bind(pcConstraint->Temperature);
|
||||
ui->if_temperature->setUnit(pcConstraint->Temperature.getUnit());
|
||||
}
|
||||
else if (constraint_type == "CFlux") {
|
||||
ui->rb_cflux->setChecked(true);
|
||||
std::string str = "Concentrated heat flux";
|
||||
ui->if_temperature->setValue(pcConstraint->CFlux.getQuantityValue());
|
||||
ui->if_temperature->bind(pcConstraint->CFlux);
|
||||
ui->if_temperature->setUnit(pcConstraint->CFlux.getUnit());
|
||||
}
|
||||
ui->cb_constr_type->addItems(qTypeList);
|
||||
ui->cb_constr_type->setCurrentIndex(constrType->getValue());
|
||||
onConstrTypeChanged(constrType->getValue());
|
||||
|
||||
ui->qsb_temperature->setValue(pcConstraint->Temperature.getQuantityValue());
|
||||
ui->qsb_temperature->bind(pcConstraint->Temperature);
|
||||
ui->qsb_temperature->setUnit(pcConstraint->Temperature.getUnit());
|
||||
|
||||
ui->qsb_cflux->setValue(pcConstraint->CFlux.getQuantityValue());
|
||||
ui->qsb_cflux->bind(pcConstraint->CFlux);
|
||||
ui->qsb_cflux->setUnit(pcConstraint->CFlux.getUnit());
|
||||
|
||||
ui->lw_references->clear();
|
||||
for (std::size_t i = 0; i < Objects.size(); i++) {
|
||||
@@ -108,12 +112,22 @@ TaskFemConstraintTemperature::TaskFemConstraintTemperature(
|
||||
&QListWidget::itemClicked,
|
||||
this,
|
||||
&TaskFemConstraintTemperature::setSelection);
|
||||
connect(ui->rb_temperature, &QRadioButton::clicked, this, &TaskFemConstraintTemperature::Temp);
|
||||
connect(ui->rb_cflux, &QRadioButton::clicked, this, &TaskFemConstraintTemperature::Flux);
|
||||
connect(ui->cb_constr_type,
|
||||
qOverload<int>(&QComboBox::activated),
|
||||
this,
|
||||
&TaskFemConstraintTemperature::onConstrTypeChanged);
|
||||
connect(ui->qsb_temperature,
|
||||
qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
|
||||
this,
|
||||
&TaskFemConstraintTemperature::onTempChanged);
|
||||
connect(ui->qsb_cflux,
|
||||
qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
|
||||
this,
|
||||
&TaskFemConstraintTemperature::onCFluxChanged);
|
||||
|
||||
// Selection buttons
|
||||
buttonGroup->addButton(ui->btnAdd, (int)SelectionChangeModes::refAdd);
|
||||
buttonGroup->addButton(ui->btnRemove, (int)SelectionChangeModes::refRemove);
|
||||
buttonGroup->addButton(ui->btnAdd, static_cast<int>(SelectionChangeModes::refAdd));
|
||||
buttonGroup->addButton(ui->btnRemove, static_cast<int>(SelectionChangeModes::refRemove));
|
||||
|
||||
updateUI();
|
||||
}
|
||||
@@ -129,20 +143,41 @@ void TaskFemConstraintTemperature::updateUI()
|
||||
}
|
||||
}
|
||||
|
||||
void TaskFemConstraintTemperature::Temp()
|
||||
void TaskFemConstraintTemperature::onTempChanged(double)
|
||||
{
|
||||
Fem::ConstraintTemperature* pcConstraint =
|
||||
static_cast<Fem::ConstraintTemperature*>(ConstraintView->getObject());
|
||||
ui->if_temperature->setUnit(pcConstraint->Temperature.getUnit());
|
||||
ui->if_temperature->setValue(pcConstraint->Temperature.getQuantityValue());
|
||||
std::string name = ConstraintView->getObject()->getNameInDocument();
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"App.ActiveDocument.%s.Temperature = \"%s\"",
|
||||
name.c_str(),
|
||||
get_temperature().c_str());
|
||||
}
|
||||
|
||||
void TaskFemConstraintTemperature::Flux()
|
||||
void TaskFemConstraintTemperature::onCFluxChanged(double)
|
||||
{
|
||||
Fem::ConstraintTemperature* pcConstraint =
|
||||
static_cast<Fem::ConstraintTemperature*>(ConstraintView->getObject());
|
||||
ui->if_temperature->setUnit(pcConstraint->CFlux.getUnit());
|
||||
ui->if_temperature->setValue(pcConstraint->CFlux.getQuantityValue());
|
||||
std::string name = ConstraintView->getObject()->getNameInDocument();
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"App.ActiveDocument.%s.CFlux = \"%s\"",
|
||||
name.c_str(),
|
||||
get_cflux().c_str());
|
||||
}
|
||||
|
||||
void TaskFemConstraintTemperature::onConstrTypeChanged(int item)
|
||||
{
|
||||
auto obj = static_cast<Fem::ConstraintTemperature*>(ConstraintView->getObject());
|
||||
obj->ConstraintType.setValue(item);
|
||||
const char* type = obj->ConstraintType.getValueAsString();
|
||||
if (strcmp(type, "Temperature") == 0) {
|
||||
ui->qsb_temperature->setVisible(true);
|
||||
ui->qsb_cflux->setVisible(false);
|
||||
ui->lbl_temperature->setVisible(true);
|
||||
ui->lbl_cflux->setVisible(false);
|
||||
}
|
||||
else if (strcmp(type, "CFlux") == 0) {
|
||||
ui->qsb_cflux->setVisible(true);
|
||||
ui->qsb_temperature->setVisible(false);
|
||||
ui->lbl_cflux->setVisible(true);
|
||||
ui->lbl_temperature->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskFemConstraintTemperature::addToSelection()
|
||||
@@ -270,25 +305,17 @@ const std::string TaskFemConstraintTemperature::getReferences() const
|
||||
|
||||
std::string TaskFemConstraintTemperature::get_temperature() const
|
||||
{
|
||||
return ui->if_temperature->value().getSafeUserString().toStdString();
|
||||
return ui->qsb_temperature->value().getSafeUserString().toStdString();
|
||||
}
|
||||
|
||||
std::string TaskFemConstraintTemperature::get_cflux() const
|
||||
{
|
||||
return ui->if_temperature->value().getSafeUserString().toStdString();
|
||||
return ui->qsb_cflux->value().getSafeUserString().toStdString();
|
||||
}
|
||||
|
||||
std::string TaskFemConstraintTemperature::get_constraint_type() const
|
||||
{
|
||||
std::string type;
|
||||
|
||||
if (ui->rb_temperature->isChecked()) {
|
||||
type = "\"Temperature\"";
|
||||
}
|
||||
else if (ui->rb_cflux->isChecked()) {
|
||||
type = "\"CFlux\"";
|
||||
}
|
||||
return type;
|
||||
return ui->cb_constr_type->currentText().toStdString();
|
||||
}
|
||||
|
||||
bool TaskFemConstraintTemperature::event(QEvent* e)
|
||||
@@ -357,7 +384,7 @@ bool TaskDlgFemConstraintTemperature::accept()
|
||||
|
||||
try {
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"App.ActiveDocument.%s.ConstraintType = %s",
|
||||
"App.ActiveDocument.%s.ConstraintType = \"%s\"",
|
||||
name.c_str(),
|
||||
parameterTemperature->get_constraint_type().c_str());
|
||||
if (type == "Temperature") {
|
||||
|
||||
@@ -55,8 +55,9 @@ public:
|
||||
|
||||
private Q_SLOTS:
|
||||
void onReferenceDeleted();
|
||||
void Temp();
|
||||
void Flux();
|
||||
void onConstrTypeChanged(int item);
|
||||
void onCFluxChanged(double);
|
||||
void onTempChanged(double);
|
||||
void addToSelection() override;
|
||||
void removeFromSelection() override;
|
||||
|
||||
|
||||
@@ -49,42 +49,45 @@
|
||||
<widget class="QListWidget" name="lw_references"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rb_temperature">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbl_constr_type">
|
||||
<property name="text">
|
||||
<string>Temperature</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
<string>Constraint type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rb_cflux">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cb_constr_type"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lbl_temperature">
|
||||
<property name="text">
|
||||
<string>Temperature</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="qsb_temperature">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">K</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lbl_cflux">
|
||||
<property name="text">
|
||||
<string>Concentrated heat flux</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="layoutTemperature">
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_type">
|
||||
<property name="text">
|
||||
<string>Temperature</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="if_temperature">
|
||||
<item row="2" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="qsb_cflux">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">K</string>
|
||||
<string notr="true">mW</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
|
||||
@@ -6,16 +6,22 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>264</width>
|
||||
<height>142</height>
|
||||
<width>344</width>
|
||||
<height>160</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Sprocket parameter</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Number of teeth:</string>
|
||||
</property>
|
||||
@@ -23,6 +29,12 @@
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NumberOfTeeth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>3</number>
|
||||
</property>
|
||||
@@ -43,6 +55,12 @@
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBox_SprocketReference">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ANSI 25</string>
|
||||
@@ -205,7 +223,7 @@
|
||||
<item row="2" column="1">
|
||||
<widget class="Gui::InputField" name="Quantity_Pitch">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@@ -245,14 +263,14 @@
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Roller Diameter:</string>
|
||||
<string>Chain Roller Diameter:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="Gui::InputField" name="Quantity_RollerDiameter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@@ -289,14 +307,14 @@
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Thickness:</string>
|
||||
<string>Tooth Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="Gui::InputField" name="Quantity_Thickness">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
|
||||
@@ -346,21 +346,25 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
# Note that emitting preambles between moves breaks some dressups and prevents path optimization on some controllers
|
||||
pathParams["preamble"] = False
|
||||
|
||||
if self.endVector is None:
|
||||
verts = hWire.Wires[0].Vertexes
|
||||
idx = 0
|
||||
if obj.Direction == "CCW":
|
||||
idx = len(verts) - 1
|
||||
x = verts[idx].X
|
||||
y = verts[idx].Y
|
||||
# Zero start value adjustments for Path.fromShapes() bug
|
||||
if Path.Geom.isRoughly(x, 0.0):
|
||||
x = 0.00001
|
||||
if Path.Geom.isRoughly(y, 0.0):
|
||||
y = 0.00001
|
||||
pathParams["start"] = FreeCAD.Vector(x, y, verts[0].Z)
|
||||
else:
|
||||
pathParams["start"] = self.endVector
|
||||
# Always manually setting pathParams["start"] to the first or
|
||||
# last vertex of the wire (depending on obj.Direction) ensures
|
||||
# the edge is always milled in the correct direction. Using
|
||||
# self.endVector would allow Path.fromShapes to reverse the
|
||||
# direction if that would shorten the travel move and thus cause
|
||||
# the edges being milled in seemingly random directions.
|
||||
|
||||
verts = hWire.Wires[0].Vertexes
|
||||
idx = 0
|
||||
if obj.Direction == "CCW":
|
||||
idx = len(verts) - 1
|
||||
x = verts[idx].X
|
||||
y = verts[idx].Y
|
||||
# Zero start value adjustments for Path.fromShapes() bug
|
||||
if Path.Geom.isRoughly(x, 0.0):
|
||||
x = 0.00001
|
||||
if Path.Geom.isRoughly(y, 0.0):
|
||||
y = 0.00001
|
||||
pathParams["start"] = FreeCAD.Vector(x, y, verts[0].Z)
|
||||
|
||||
obj.PathParams = str(
|
||||
{key: value for key, value in pathParams.items() if key != "shapes"}
|
||||
|
||||
@@ -394,7 +394,7 @@ void SketcherToolDefaultWidget::setParameterLabel(int parameterindex, const QStr
|
||||
void SketcherToolDefaultWidget::setParameter(int parameterindex, double val)
|
||||
{
|
||||
if (parameterindex < nParameters) {
|
||||
getParameterSpinBox(parameterindex)->setValue(Base::Quantity(val, Base::Unit::Length));
|
||||
getParameterSpinBox(parameterindex)->setValue(val);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -424,6 +424,45 @@ void SketcherToolDefaultWidget::configureParameterUnit(int parameterindex, const
|
||||
QT_TRANSLATE_NOOP("Exceptions", "ToolWidget parameter index out of range"));
|
||||
}
|
||||
|
||||
void SketcherToolDefaultWidget::configureParameterDecimals(int parameterindex, int val)
|
||||
{
|
||||
Base::StateLocker lock(blockParameterSlots, true);
|
||||
if (parameterindex < nParameters) {
|
||||
getParameterSpinBox(parameterindex)->setDecimals(val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
THROWM(Base::IndexError,
|
||||
QT_TRANSLATE_NOOP("Exceptions", "ToolWidget parameter index out of range"));
|
||||
}
|
||||
|
||||
void SketcherToolDefaultWidget::configureParameterMin(int parameterindex, double val)
|
||||
{
|
||||
Base::StateLocker lock(blockParameterSlots, true);
|
||||
if (parameterindex < nParameters) {
|
||||
getParameterSpinBox(parameterindex)->setMinimum(val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
THROWM(Base::IndexError,
|
||||
QT_TRANSLATE_NOOP("Exceptions", "ToolWidget parameter index out of range"));
|
||||
}
|
||||
|
||||
void SketcherToolDefaultWidget::configureParameterMax(int parameterindex, double val)
|
||||
{
|
||||
Base::StateLocker lock(blockParameterSlots, true);
|
||||
if (parameterindex < nParameters) {
|
||||
getParameterSpinBox(parameterindex)->setMaximum(val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
THROWM(Base::IndexError,
|
||||
QT_TRANSLATE_NOOP("Exceptions", "ToolWidget parameter index out of range"));
|
||||
}
|
||||
|
||||
void SketcherToolDefaultWidget::setParameterEnabled(int parameterindex, bool active)
|
||||
{
|
||||
if (parameterindex < nParameters) {
|
||||
@@ -714,6 +753,20 @@ void SketcherToolDefaultWidget::restoreCheckBoxPref(int checkboxindex)
|
||||
}
|
||||
}
|
||||
|
||||
void SketcherToolDefaultWidget::setCheckboxIcon(int checkboxindex, QIcon icon)
|
||||
{
|
||||
if (checkboxindex < nCheckbox) {
|
||||
getCheckBox(checkboxindex)->setIcon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
void SketcherToolDefaultWidget::setComboboxItemIcon(int comboboxindex, int index, QIcon icon)
|
||||
{
|
||||
if (comboboxindex < nCombobox) {
|
||||
getComboBox(comboboxindex)->setItemIcon(index, icon);
|
||||
}
|
||||
}
|
||||
|
||||
void SketcherToolDefaultWidget::setComboboxPrefEntry(int comboboxindex,
|
||||
const std::string& prefEntry)
|
||||
{
|
||||
|
||||
@@ -146,6 +146,9 @@ public:
|
||||
void setParameter(int parameterindex, double val);
|
||||
void configureParameterInitialValue(int parameterindex, double value);
|
||||
void configureParameterUnit(int parameterindex, const Base::Unit& unit);
|
||||
void configureParameterDecimals(int parameterindex, int val);
|
||||
void configureParameterMax(int parameterindex, double val);
|
||||
void configureParameterMin(int parameterindex, double val);
|
||||
double getParameter(int parameterindex);
|
||||
bool isParameterSet(int parameterindex);
|
||||
void
|
||||
@@ -172,6 +175,7 @@ public:
|
||||
void setCheckboxToolTip(int checkboxindex, const QString& string);
|
||||
bool getCheckboxChecked(int checkboxindex);
|
||||
void setCheckboxPrefEntry(int checkboxindex, const std::string& prefEntry);
|
||||
void setCheckboxIcon(int checkboxindex, QIcon icon);
|
||||
void restoreCheckBoxPref(int checkboxindex);
|
||||
|
||||
void initNComboboxes(int ncombobox);
|
||||
@@ -180,6 +184,7 @@ public:
|
||||
void setComboboxLabel(int comboboxindex, const QString& string);
|
||||
int getComboboxIndex(int comboboxindex);
|
||||
void setComboboxElements(int comboboxindex, const QStringList& names);
|
||||
void setComboboxItemIcon(int comboboxindex, int index, QIcon icon);
|
||||
void setComboboxPrefEntry(int comboboxindex, const std::string& prefEntry);
|
||||
void restoreComboboxPref(int comboboxindex);
|
||||
|
||||
|
||||
@@ -1066,11 +1066,12 @@ void execLine2Points(Gui::Command* cmd)
|
||||
//check if editing existing edge
|
||||
if (!edgeNames.empty() && (edgeNames.size() == 1)) {
|
||||
TechDraw::CosmeticEdge* ce = baseFeat->getCosmeticEdgeBySelection(edgeNames.front());
|
||||
if (!ce) {
|
||||
if (!ce || ce->m_geometry->getGeomType() != TechDraw::GeomType::GENERIC) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong Selection"),
|
||||
QObject::tr("Selection is not a Cosmetic Line."));
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::Control().showDialog(new TaskDlgCosmeticLine(baseFeat,
|
||||
edgeNames.front()));
|
||||
return;
|
||||
@@ -1208,11 +1209,14 @@ void execCosmeticCircle(Gui::Command* cmd)
|
||||
//check if editing existing edge
|
||||
if (!edgeNames.empty() && (edgeNames.size() == 1)) {
|
||||
TechDraw::CosmeticEdge* ce = baseFeat->getCosmeticEdgeBySelection(edgeNames.front());
|
||||
if (!ce) {
|
||||
if (!ce
|
||||
|| !(ce->m_geometry->getGeomType() == TechDraw::GeomType::CIRCLE
|
||||
|| ce->m_geometry->getGeomType() == TechDraw::GeomType::ARCOFCIRCLE)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong Selection"),
|
||||
QObject::tr("Selection is not a Cosmetic edge."));
|
||||
QObject::tr("Selection is not a Cosmetic Circle or a Cosmetic Arc of Circle."));
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::Control().showDialog(new TaskDlgCosmeticCircle(baseFeat,
|
||||
edgeNames.front()));
|
||||
return;
|
||||
|
||||
@@ -289,6 +289,8 @@ void QGIViewPart::drawAllEdges()
|
||||
item->setNormalColor(PreferencesGui::getAccessibleQColor(PreferencesGui::normalQColor()));
|
||||
item->setStyle(Qt::SolidLine);
|
||||
if ((*itGeom)->getCosmetic()) {
|
||||
item->setCosmetic(true);
|
||||
|
||||
// cosmetic edge - format appropriately
|
||||
int source = (*itGeom)->source();
|
||||
if (source == COSMETICEDGE) {
|
||||
|
||||
Reference in New Issue
Block a user