Merge pull request #19397 from kadet1090/three-point-lighting
Add three-point lighting
This commit is contained in:
@@ -31,19 +31,7 @@
|
||||
#include "Application.h"
|
||||
#include "Material.h"
|
||||
|
||||
// Helper functions to consistently convert between float and long
|
||||
namespace
|
||||
{
|
||||
float fromPercent(long value)
|
||||
{
|
||||
return std::roundf(value) / 100.0F;
|
||||
}
|
||||
|
||||
long toPercent(float value)
|
||||
{
|
||||
return std::lround(100.0 * value);
|
||||
}
|
||||
} // namespace
|
||||
#include <Base/Tools.h>
|
||||
|
||||
using namespace App;
|
||||
|
||||
@@ -351,9 +339,9 @@ App::Material Material::getDefaultAppearance()
|
||||
};
|
||||
|
||||
App::Material mat(App::Material::DEFAULT);
|
||||
mat.transparency = fromPercent(hGrp->GetInt("DefaultShapeTransparency", 0));
|
||||
long shininess = toPercent(mat.shininess);
|
||||
mat.shininess = fromPercent(hGrp->GetInt("DefaultShapeShininess", shininess));
|
||||
mat.transparency = Base::fromPercent(hGrp->GetInt("DefaultShapeTransparency", 0));
|
||||
long shininess = Base::toPercent(mat.shininess);
|
||||
mat.shininess = Base::fromPercent(hGrp->GetInt("DefaultShapeShininess", shininess));
|
||||
|
||||
// This is handled in the material code when using the object appearance
|
||||
bool randomColor = hGrp->GetBool("RandomColor", false);
|
||||
|
||||
@@ -1253,7 +1253,7 @@ bool InventorLoader::isValid() const
|
||||
|
||||
namespace Base
|
||||
{
|
||||
BaseExport Vector3f to_vector(std::string str)
|
||||
BaseExport Vector3f stringToVector(std::string str)
|
||||
{
|
||||
std::string_view view = str;
|
||||
if (!boost::starts_with(view, "(") || !boost::ends_with(str, ")")) {
|
||||
@@ -1282,4 +1282,9 @@ BaseExport Vector3f to_vector(std::string str)
|
||||
return vec;
|
||||
}
|
||||
|
||||
BaseExport std::string vectorToString(Vector3f vec)
|
||||
{
|
||||
return fmt::format("({},{},{})", vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
} // namespace Base
|
||||
|
||||
@@ -845,7 +845,14 @@ private:
|
||||
* If it fails then a std::exception is thrown.
|
||||
* Supported type names are float or double
|
||||
*/
|
||||
BaseExport Base::Vector3f to_vector(std::string);
|
||||
BaseExport Base::Vector3f stringToVector(std::string);
|
||||
|
||||
/*!
|
||||
* Expects a string of the form "(x,y,z)" and creates a vector from it.
|
||||
* If it fails then a std::exception is thrown.
|
||||
* Supported type names are float or double
|
||||
*/
|
||||
BaseExport std::string vectorToString(Vector3f);
|
||||
|
||||
} // namespace Base
|
||||
|
||||
|
||||
@@ -143,6 +143,16 @@ inline T toDegrees(T r)
|
||||
return static_cast<T>((r / M_PI) * 180.0);
|
||||
}
|
||||
|
||||
inline float fromPercent(const long value)
|
||||
{
|
||||
return std::roundf(value) / 100.0F;
|
||||
}
|
||||
|
||||
inline long toPercent(float value)
|
||||
{
|
||||
return std::lround(100.0 * value);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T fmod(T numerator, T denominator)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "ui_DlgMaterialProperties.h"
|
||||
#include "ViewProvider.h"
|
||||
|
||||
#include <Base/Tools.h>
|
||||
|
||||
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
@@ -129,7 +131,7 @@ void DlgMaterialPropertiesImp::onSpecularColorChanged()
|
||||
*/
|
||||
void DlgMaterialPropertiesImp::onShininessValueChanged(int sh)
|
||||
{
|
||||
customMaterial.shininess = (float)sh / 100.0F;
|
||||
customMaterial.shininess = Base::fromPercent(sh);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +139,7 @@ void DlgMaterialPropertiesImp::onShininessValueChanged(int sh)
|
||||
*/
|
||||
void DlgMaterialPropertiesImp::onTransparencyValueChanged(int sh)
|
||||
{
|
||||
customMaterial.transparency = (float)sh / 100.0F;
|
||||
customMaterial.transparency = Base::fromPercent(sh);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>499</width>
|
||||
<height>520</height>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -48,11 +48,12 @@ lower right corner within opened files</string>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacerCoord">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -63,7 +64,7 @@ lower right corner within opened files</string>
|
||||
<string>Relative size:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -73,6 +74,9 @@ lower right corner within opened files</string>
|
||||
<string>Size of main coordinate system representation
|
||||
in the corner -- in % of height/width of viewport</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string notr="true">%</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
@@ -82,9 +86,6 @@ in the corner -- in % of height/width of viewport</string>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string notr="true">%</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>CornerCoordSystemSize</cstring>
|
||||
</property>
|
||||
@@ -105,7 +106,7 @@ in the corner -- in % of height/width of viewport</string>
|
||||
<property name="toolTip">
|
||||
<string>Axis letter and FPS counter color</string>
|
||||
</property>
|
||||
<property name="color" stdset="0">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
@@ -324,14 +325,76 @@ report this setting as enabled when seeking support on the FreeCAD forums</strin
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="renderCacheLabel">
|
||||
<property name="text">
|
||||
<string>Render cache</string>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboAliasing">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>What kind of multisample anti-aliasing is used</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="markerSizeLabel">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Marker size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="aliasingLAbel">
|
||||
<property name="text">
|
||||
<string>Anti-Aliasing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="transparentRenderLabel">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transparent objects:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Gui::PrefComboBox" name="comboTransparentRender">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Render types of transparent objects</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>TransparentObjectRenderType</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>One pass</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Backface pass</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="renderCache">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@@ -368,76 +431,21 @@ but slower response to any scene changes.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="aliasingLAbel">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="renderCacheLabel">
|
||||
<property name="text">
|
||||
<string>Anti-Aliasing</string>
|
||||
<string>Render cache</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QComboBox" name="comboAliasing">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>What kind of multisample anti-aliasing is used</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="transparentRenderLabel">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="textLabel1">
|
||||
<property name="text">
|
||||
<string>Transparent objects:</string>
|
||||
<string>Eye to eye distance for stereo modes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="Gui::PrefComboBox" name="comboTransparentRender">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Render types of transparent objects</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>TransparentObjectRenderType</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>One pass</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Backface pass</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="markerSizeLabel">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Marker size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="boxMarkerSize">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@@ -450,14 +458,7 @@ but slower response to any scene changes.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="textLabel1">
|
||||
<property name="text">
|
||||
<string>Eye to eye distance for stereo modes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<item row="4" column="1">
|
||||
<widget class="Gui::PrefDoubleSpinBox" name="FloatSpinBox_EyeDistance">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@@ -493,120 +494,6 @@ bounding box size of the 3D object that is currently displayed.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="checkBoxBacklight">
|
||||
<property name="toolTip">
|
||||
<string>Backlight is enabled with the defined color</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Backlight color</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>EnableBacklight</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="backlightColor">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Backlight color</string>
|
||||
</property>
|
||||
<property name="color" stdset="0">
|
||||
<color>
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>BacklightColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QLabel" name="backlightLabel">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Intensity</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="Gui::PrefSlider" name="sliderIntensity">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Intensity of the backlight</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</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>BacklightIntensity</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -674,7 +561,7 @@ bounding box size of the 3D object that is currently displayed.</string>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -694,18 +581,8 @@ bounding box size of the 3D object that is currently displayed.</string>
|
||||
<header>Gui/Widgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefRadioButton</class>
|
||||
<extends>QRadioButton</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<class>Gui::PrefSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
@@ -714,8 +591,18 @@ bounding box size of the 3D object that is currently displayed.</string>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefSlider</class>
|
||||
<extends>QSlider</extends>
|
||||
<class>Gui::PrefRadioButton</class>
|
||||
<extends>QRadioButton</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
@@ -723,73 +610,40 @@ bounding box size of the 3D object that is currently displayed.</string>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>checkBoxBacklight</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>backlightColor</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>161</x>
|
||||
<y>227</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>290</x>
|
||||
<y>224</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkBoxBacklight</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>sliderIntensity</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>92</x>
|
||||
<y>235</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>293</x>
|
||||
<y>256</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkBoxBacklight</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>backlightLabel</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>82</x>
|
||||
<y>507</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>316</x>
|
||||
<y>507</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>CheckBox_CornerCoordSystem</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>SpinBox_CornerCoordSystemSize</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>CheckBox_CornerCoordSystem</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>axisLetterColor</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
||||
@@ -69,10 +69,7 @@ void DlgSettings3DViewImp::saveSettings()
|
||||
ui->CheckBox_use_SW_OpenGL->onSave();
|
||||
ui->CheckBox_useVBO->onSave();
|
||||
ui->FloatSpinBox_EyeDistance->onSave();
|
||||
ui->checkBoxBacklight->onSave();
|
||||
ui->backlightColor->onSave();
|
||||
ui->axisLetterColor->onSave();
|
||||
ui->sliderIntensity->onSave();
|
||||
ui->radioPerspective->onSave();
|
||||
ui->radioOrthographic->onSave();
|
||||
ui->xAxisColor->onSave();
|
||||
@@ -89,10 +86,7 @@ void DlgSettings3DViewImp::loadSettings()
|
||||
ui->CheckBox_use_SW_OpenGL->onRestore();
|
||||
ui->CheckBox_useVBO->onRestore();
|
||||
ui->FloatSpinBox_EyeDistance->onRestore();
|
||||
ui->checkBoxBacklight->onRestore();
|
||||
ui->backlightColor->onRestore();
|
||||
ui->axisLetterColor->onRestore();
|
||||
ui->sliderIntensity->onRestore();
|
||||
ui->radioPerspective->onRestore();
|
||||
ui->radioOrthographic->onRestore();
|
||||
ui->comboTransparentRender->onRestore();
|
||||
|
||||
@@ -24,12 +24,11 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <Inventor/draggers/SoDirectionalLightDragger.h>
|
||||
#include <Inventor/events/SoEvent.h>
|
||||
#include <Inventor/nodes/SoDirectionalLight.h>
|
||||
#include <Inventor/nodes/SoEventCallback.h>
|
||||
#include <Inventor/nodes/SoOrthographicCamera.h>
|
||||
#include <Inventor/nodes/SoPickStyle.h>
|
||||
#include <Inventor/nodes/SoComplexity.h>
|
||||
#include <Inventor/nodes/SoSeparator.h>
|
||||
#include <Inventor/nodes/SoMaterial.h>
|
||||
#include <Inventor/nodes/SoSphere.h>
|
||||
@@ -37,7 +36,10 @@
|
||||
|
||||
#include "DlgSettingsLightSources.h"
|
||||
#include "ui_DlgSettingsLightSources.h"
|
||||
#include <App/Application.h>
|
||||
|
||||
#include <Utilities.h>
|
||||
#include <Base/Builder3D.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
#include <Gui/View3DSettings.h>
|
||||
|
||||
@@ -46,273 +48,305 @@ using namespace Gui::Dialog;
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::DlgSettingsLightSources */
|
||||
|
||||
DlgSettingsLightSources::DlgSettingsLightSources(QWidget* parent)
|
||||
: PreferencePage(parent)
|
||||
, ui(new Ui_DlgSettingsLightSources)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
view = ui->viewer;
|
||||
createViewer();
|
||||
}
|
||||
|
||||
static inline
|
||||
SbVec3f getDirectionVector(const SbRotation &rotation)
|
||||
static inline SbVec3f getDirectionVector(const SbRotation& rotation)
|
||||
{
|
||||
SbVec3f dir {0.0f, 0.0f, -1.0f};
|
||||
rotation.multVec(dir, dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
static inline
|
||||
void setLightDirection(const SbRotation &rotation, Gui::View3DInventorViewer *viewer)
|
||||
DlgSettingsLightSources::DlgSettingsLightSources(QWidget* parent)
|
||||
: PreferencePage(parent)
|
||||
, ui(new Ui_DlgSettingsLightSources)
|
||||
{
|
||||
viewer->getHeadlight()->direction = getDirectionVector(rotation);
|
||||
ui->setupUi(this);
|
||||
|
||||
view = ui->viewer;
|
||||
|
||||
configureViewer();
|
||||
|
||||
const auto connectLightEvents = [&](QuantitySpinBox* horizontalAngleSpinBox,
|
||||
QuantitySpinBox* verticalAngleSpinBox,
|
||||
QSpinBox* intensitySpinBox,
|
||||
ColorButton* colorButton,
|
||||
QCheckBox* enabledCheckbox,
|
||||
auto updateLightFunction) {
|
||||
connect(horizontalAngleSpinBox,
|
||||
qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this,
|
||||
updateLightFunction);
|
||||
connect(verticalAngleSpinBox,
|
||||
qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this,
|
||||
updateLightFunction);
|
||||
connect(intensitySpinBox,
|
||||
qOverload<int>(&QSpinBox::valueChanged),
|
||||
this,
|
||||
updateLightFunction);
|
||||
connect(colorButton, &ColorButton::changed, this, updateLightFunction);
|
||||
connect(enabledCheckbox, &QCheckBox::stateChanged, this, updateLightFunction);
|
||||
};
|
||||
|
||||
const auto updateLight = [&](SoDirectionalLight* light,
|
||||
QuantitySpinBox* horizontalAngleSpinBox,
|
||||
QuantitySpinBox* verticalAngleSpinBox,
|
||||
QSpinBox* intensitySpinBox,
|
||||
ColorButton* colorButton,
|
||||
QCheckBox* enabledCheckbox,
|
||||
std::function<void(bool)> setLightEnabled) {
|
||||
light->color = Base::convertTo<SbColor>(colorButton->color());
|
||||
light->intensity = Base::fromPercent(intensitySpinBox->value());
|
||||
light->direction =
|
||||
Base::convertTo<SbVec3f>(azimuthElevationToDirection(horizontalAngleSpinBox->rawValue(),
|
||||
verticalAngleSpinBox->rawValue()));
|
||||
setLightEnabled(enabledCheckbox->isChecked());
|
||||
};
|
||||
|
||||
const auto updateHeadLight = [&] {
|
||||
updateLight(view->getHeadlight(),
|
||||
ui->mainLightHorizontalAngle,
|
||||
ui->mainLightVerticalAngle,
|
||||
ui->mainLightIntensitySpinBox,
|
||||
ui->mainLightColor,
|
||||
ui->mainLightEnable,
|
||||
[&](bool enabled) {
|
||||
view->setHeadlightEnabled(enabled);
|
||||
});
|
||||
};
|
||||
|
||||
const auto updateFillLight = [&] {
|
||||
updateLight(view->getFillLight(),
|
||||
ui->fillLightHorizontalAngle,
|
||||
ui->fillLightVerticalAngle,
|
||||
ui->fillLightIntensitySpinBox,
|
||||
ui->fillLightColor,
|
||||
ui->fillLightEnable,
|
||||
[&](bool enabled) {
|
||||
view->setFillLightEnabled(enabled);
|
||||
});
|
||||
};
|
||||
|
||||
const auto updateBackLight = [&] {
|
||||
updateLight(view->getBacklight(),
|
||||
ui->backLightHorizontalAngle,
|
||||
ui->backLightVerticalAngle,
|
||||
ui->backLightIntensitySpinBox,
|
||||
ui->backLightColor,
|
||||
ui->backLightEnable,
|
||||
[&](bool enabled) {
|
||||
view->setBacklightEnabled(enabled);
|
||||
});
|
||||
};
|
||||
|
||||
connectLightEvents(ui->mainLightHorizontalAngle,
|
||||
ui->mainLightVerticalAngle,
|
||||
ui->mainLightIntensitySpinBox,
|
||||
ui->mainLightColor,
|
||||
ui->mainLightEnable,
|
||||
updateHeadLight);
|
||||
connectLightEvents(ui->backLightHorizontalAngle,
|
||||
ui->backLightVerticalAngle,
|
||||
ui->backLightIntensitySpinBox,
|
||||
ui->backLightColor,
|
||||
ui->backLightEnable,
|
||||
updateBackLight);
|
||||
connectLightEvents(ui->fillLightHorizontalAngle,
|
||||
ui->fillLightVerticalAngle,
|
||||
ui->fillLightIntensitySpinBox,
|
||||
ui->fillLightColor,
|
||||
ui->fillLightEnable,
|
||||
updateFillLight);
|
||||
|
||||
const auto updateAmbientLight = [&] {
|
||||
view->getEnvironment()->ambientColor =
|
||||
Base::convertTo<SbColor>(ui->ambientLightColor->color());
|
||||
view->getEnvironment()->ambientIntensity =
|
||||
Base::fromPercent(ui->ambientLightIntensitySpinBox->value());
|
||||
};
|
||||
|
||||
connect(ui->ambientLightIntensitySpinBox,
|
||||
qOverload<int>(&QSpinBox::valueChanged),
|
||||
this,
|
||||
updateAmbientLight);
|
||||
connect(ui->ambientLightColor, &ColorButton::changed, this, updateAmbientLight);
|
||||
|
||||
connect(ui->zoomInButton, &QToolButton::clicked, this, &DlgSettingsLightSources::zoomIn);
|
||||
connect(ui->zoomOutButton, &QToolButton::clicked, this, &DlgSettingsLightSources::zoomOut);
|
||||
|
||||
DlgSettingsLightSources::loadSettings();
|
||||
}
|
||||
|
||||
static inline
|
||||
void setLightDraggerDirection(const SbRotation &rotation, SoDirectionalLightDragger *light_dragger)
|
||||
static inline SoMaterial* createMaterial(void)
|
||||
{
|
||||
light_dragger->rotation = rotation;
|
||||
}
|
||||
const QColor ambientColor {0xff333333}, diffuseColor {0xffd2d2ff}, emissiveColor {0xff000000},
|
||||
specularColor {0xffcccccc};
|
||||
|
||||
static inline
|
||||
void setValueSilently(QDoubleSpinBox *spn, const float val)
|
||||
{
|
||||
Q_ASSERT_X(spn, "setValueSilently", "QDoubleSpinBox has been deleted");
|
||||
auto material = new SoMaterial();
|
||||
|
||||
spn->blockSignals(true);
|
||||
spn->setValue(val);
|
||||
spn->blockSignals(false);
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::dragMotionCallback(void *data, SoDragger *drag)
|
||||
{
|
||||
auto lightdrag = dynamic_cast <SoDirectionalLightDragger *> (drag);
|
||||
auto self = static_cast<DlgSettingsLightSources*>(data);
|
||||
|
||||
const SbRotation rotation = lightdrag->rotation.getValue();
|
||||
|
||||
setLightDirection(rotation, self->view);
|
||||
|
||||
setValueSilently(self->ui->q0_spnBox, rotation[0]);
|
||||
setValueSilently(self->ui->q1_spnBox, rotation[1]);
|
||||
setValueSilently(self->ui->q2_spnBox, rotation[2]);
|
||||
setValueSilently(self->ui->q3_spnBox, rotation[3]);
|
||||
|
||||
const SbVec3f dir = getDirectionVector(rotation);
|
||||
|
||||
setValueSilently(self->ui->x_spnBox, dir[0]);
|
||||
setValueSilently(self->ui->y_spnBox, dir[1]);
|
||||
setValueSilently(self->ui->z_spnBox, dir[2]);
|
||||
}
|
||||
|
||||
static inline
|
||||
SoMaterial *createMaterial(void)
|
||||
{
|
||||
const QColor ambientColor {0xff333333},
|
||||
diffuseColor {0xffd2d2ff},
|
||||
emissiveColor {0xff000000},
|
||||
specularColor {0xffcccccc};
|
||||
|
||||
auto material = new SoMaterial ();
|
||||
material->ambientColor.setValue (ambientColor.redF(), ambientColor.greenF(), ambientColor.blueF());
|
||||
material->diffuseColor.setValue (diffuseColor.redF(), diffuseColor.greenF(), diffuseColor.blueF());
|
||||
material->emissiveColor.setValue(emissiveColor.redF(), emissiveColor.greenF(), emissiveColor.blueF());
|
||||
material->specularColor.setValue(specularColor.redF(), specularColor.greenF(), specularColor.blueF());
|
||||
material->ambientColor.setValue(Base::convertTo<SbColor>(ambientColor));
|
||||
material->diffuseColor.setValue(Base::convertTo<SbColor>(diffuseColor));
|
||||
material->emissiveColor.setValue(Base::convertTo<SbColor>(emissiveColor));
|
||||
material->specularColor.setValue(Base::convertTo<SbColor>(specularColor));
|
||||
|
||||
material->shininess = 0.9f;
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
static inline
|
||||
SoSphere *createSphere(void)
|
||||
static inline SoSphere* createSphere(void)
|
||||
{
|
||||
auto sphere = new SoSphere();
|
||||
sphere->radius = 2;
|
||||
sphere->radius = 3;
|
||||
|
||||
return sphere;
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::createViewer()
|
||||
static inline SoComplexity* createGoodComplexity()
|
||||
{
|
||||
const QColor default_bg_color {180, 180, 180};
|
||||
const SbVec3f default_view_direction {1.0f, 1.0f, -5.0f};
|
||||
auto complexity = new SoComplexity();
|
||||
complexity->value = 1.0;
|
||||
|
||||
return complexity;
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::configureViewer()
|
||||
{
|
||||
const SbVec3f defaultViewDirection {0.0f, 1.0f, 0.3f};
|
||||
|
||||
View3DSettings(hGrp, view).applySettings();
|
||||
|
||||
// NOLINTBEGIN
|
||||
view->setRedirectToSceneGraph(true);
|
||||
view->setViewing(true);
|
||||
view->setPopupMenuEnabled(false);
|
||||
|
||||
view->setBackgroundColor(default_bg_color);
|
||||
view->setGradientBackground(Gui::View3DInventorViewer::NoGradient);
|
||||
view->setEnabledNaviCube(false);
|
||||
|
||||
auto root = static_cast<SoSeparator*>(view->getSceneGraph());
|
||||
root->addChild(createDragger());
|
||||
const auto root = static_cast<SoSeparator*>(view->getSceneGraph());
|
||||
root->addChild(createGoodComplexity());
|
||||
root->addChild(createMaterial());
|
||||
root->addChild(createSphere());
|
||||
|
||||
auto callback = new SoEventCallback();
|
||||
const auto callback = new SoEventCallback();
|
||||
root->addChild(callback);
|
||||
callback->addEventCallback(SoEvent::getClassTypeId(),
|
||||
[] (void* ud, SoEventCallback* cb) {
|
||||
Q_UNUSED(ud)
|
||||
cb->setHandled();
|
||||
});
|
||||
[]([[maybe_unused]] void* ud, SoEventCallback* cb) {
|
||||
cb->setHandled();
|
||||
});
|
||||
|
||||
view->setCameraType(SoOrthographicCamera::getClassTypeId());
|
||||
view->setViewDirection(default_view_direction);
|
||||
view->setViewDirection(defaultViewDirection);
|
||||
view->viewAll();
|
||||
|
||||
camera = dynamic_cast <SoOrthographicCamera *> (view->getCamera());
|
||||
const float camera_height = camera->height.getValue() * 2.0f;
|
||||
camera->height = camera_height;
|
||||
cam_step = camera_height / 14.0f;
|
||||
// NOLINTEND
|
||||
camera = dynamic_cast<SoOrthographicCamera*>(view->getCamera());
|
||||
const float cameraHeight = camera->height.getValue() * 2.0f;
|
||||
camera->height = cameraHeight;
|
||||
zoomStep = cameraHeight / 14.0f;
|
||||
}
|
||||
|
||||
SoDirectionalLightDragger* DlgSettingsLightSources::createDragger()
|
||||
Base::Vector3d DlgSettingsLightSources::azimuthElevationToDirection(double azimuth,
|
||||
double elevation)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
azimuth = Base::toRadians(azimuth);
|
||||
elevation = Base::toRadians(elevation);
|
||||
|
||||
lightDragger->addMotionCallback(dragMotionCallback, this);
|
||||
return lightDragger;
|
||||
// NOLINTEND
|
||||
auto direction = Base::Vector3d {std::sin(azimuth) * std::cos(elevation),
|
||||
std::cos(azimuth) * std::cos(elevation),
|
||||
std::sin(elevation)};
|
||||
|
||||
direction.Normalize();
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
std::pair<double, double>
|
||||
DlgSettingsLightSources::directionToAzimuthElevation(Base::Vector3d direction)
|
||||
{
|
||||
const auto azimuth = std::atan2(direction[0], direction[1]);
|
||||
const auto elevation =
|
||||
std::atan2(direction[2],
|
||||
std::sqrt(direction[1] * direction[1] + direction[0] * direction[0]));
|
||||
|
||||
return {Base::toDegrees(azimuth), Base::toDegrees(elevation)};
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::saveSettings()
|
||||
{
|
||||
ui->checkBoxLight1->onSave();
|
||||
ui->light1Color->onSave();
|
||||
ui->sliderIntensity1->onSave();
|
||||
saveDirection();
|
||||
for (const auto& widget : findChildren<QWidget*>()) {
|
||||
if (const auto pref = dynamic_cast<PrefWidget*>(widget)) {
|
||||
pref->onSave();
|
||||
}
|
||||
}
|
||||
|
||||
const auto saveAngles = [&](QuantitySpinBox* horizontalAngleSpinBox,
|
||||
QuantitySpinBox* verticalAngleSpinBox,
|
||||
const char* parameter) {
|
||||
try {
|
||||
const auto direction = azimuthElevationToDirection(horizontalAngleSpinBox->rawValue(),
|
||||
verticalAngleSpinBox->rawValue());
|
||||
|
||||
hGrp->SetASCII(parameter,
|
||||
Base::vectorToString(Base::convertTo<Base::Vector3f>(direction)));
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
};
|
||||
|
||||
saveAngles(ui->mainLightHorizontalAngle, ui->mainLightVerticalAngle, "HeadlightDirection");
|
||||
saveAngles(ui->backLightHorizontalAngle, ui->backLightVerticalAngle, "BacklightDirection");
|
||||
saveAngles(ui->fillLightHorizontalAngle, ui->fillLightVerticalAngle, "FillLightDirection");
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::loadSettings()
|
||||
{
|
||||
ui->checkBoxLight1->onRestore();
|
||||
ui->light1Color->onRestore();
|
||||
ui->sliderIntensity1->onRestore();
|
||||
loadDirection();
|
||||
lightColor();
|
||||
for (const auto& widget : findChildren<QWidget*>()) {
|
||||
if (const auto pref = dynamic_cast<PrefWidget*>(widget)) {
|
||||
pref->onRestore();
|
||||
}
|
||||
}
|
||||
|
||||
const auto loadAngles = [&](QuantitySpinBox* horizontalAngleSpinBox,
|
||||
QuantitySpinBox* verticalAngleSpinBox,
|
||||
const char* parameter) {
|
||||
try {
|
||||
const auto direction = Base::stringToVector(hGrp->GetASCII(parameter));
|
||||
const auto [azimuth, elevation] =
|
||||
directionToAzimuthElevation(Base::convertTo<Base::Vector3d>(direction));
|
||||
|
||||
horizontalAngleSpinBox->setValue(azimuth);
|
||||
verticalAngleSpinBox->setValue(elevation);
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
};
|
||||
|
||||
loadAngles(ui->mainLightHorizontalAngle, ui->mainLightVerticalAngle, "HeadlightDirection");
|
||||
loadAngles(ui->backLightHorizontalAngle, ui->backLightVerticalAngle, "BacklightDirection");
|
||||
loadAngles(ui->fillLightHorizontalAngle, ui->fillLightVerticalAngle, "FillLightDirection");
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::resetSettingsToDefaults()
|
||||
{
|
||||
ParameterGrp::handle grp = ui->sliderIntensity1->getWindowParameter();
|
||||
|
||||
grp->SetFloat("HeadlightRotationX", 0.0);
|
||||
grp->SetFloat("HeadlightRotationY", 0.0);
|
||||
grp->SetFloat("HeadlightRotationZ", 0.0);
|
||||
grp->SetFloat("HeadlightRotationW", 1.0);
|
||||
|
||||
grp->SetASCII("HeadlightDirection", "(0.0,0.0,-1.0)");
|
||||
|
||||
PreferencePage::resetSettingsToDefaults();
|
||||
|
||||
loadSettings();
|
||||
configureViewer();
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::saveDirection()
|
||||
void DlgSettingsLightSources::zoomIn() const
|
||||
{
|
||||
if (lightDragger) {
|
||||
const SbRotation rotation = lightDragger->rotation.getValue();
|
||||
const SbVec3f dir = getDirectionVector(rotation);
|
||||
const QString headlightDir = QStringLiteral("(%1,%2,%3)").arg(dir[0]).arg(dir[1]).arg(dir[2]);
|
||||
|
||||
ParameterGrp::handle grp = ui->sliderIntensity1->getWindowParameter();
|
||||
|
||||
grp->SetFloat("HeadlightRotationX", rotation[0]);
|
||||
grp->SetFloat("HeadlightRotationY", rotation[1]);
|
||||
grp->SetFloat("HeadlightRotationZ", rotation[2]);
|
||||
grp->SetFloat("HeadlightRotationW", rotation[3]);
|
||||
|
||||
grp->SetASCII("HeadlightDirection", qPrintable(headlightDir));
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::loadDirection()
|
||||
{
|
||||
ParameterGrp::handle grp = ui->sliderIntensity1->getWindowParameter();
|
||||
SbRotation rotation = lightDragger->rotation.getValue();
|
||||
|
||||
auto get_q = [&grp](const char *name, const float def){return static_cast <float> (grp->GetFloat(name, def));};
|
||||
|
||||
const float q0 = get_q("HeadlightRotationX", rotation[0]),
|
||||
q1 = get_q("HeadlightRotationY", rotation[1]),
|
||||
q2 = get_q("HeadlightRotationZ", rotation[2]),
|
||||
q3 = get_q("HeadlightRotationW", rotation[3]);
|
||||
|
||||
rotation.setValue(q0, q1, q2, q3);
|
||||
|
||||
setLightDirection(rotation, ui->viewer);
|
||||
setLightDraggerDirection(rotation, lightDragger);
|
||||
|
||||
setValueSilently(ui->q0_spnBox, rotation[0]);
|
||||
setValueSilently(ui->q1_spnBox, rotation[1]);
|
||||
setValueSilently(ui->q2_spnBox, rotation[2]);
|
||||
setValueSilently(ui->q3_spnBox, rotation[3]);
|
||||
|
||||
const SbVec3f dir = getDirectionVector(rotation);
|
||||
|
||||
setValueSilently(ui->x_spnBox, dir[0]);
|
||||
setValueSilently(ui->y_spnBox, dir[1]);
|
||||
setValueSilently(ui->z_spnBox, dir[2]);
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::toggleLight(bool on)
|
||||
{
|
||||
if (view) {
|
||||
view->setHeadlightEnabled(on);
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::lightIntensity(int value)
|
||||
{
|
||||
if (view) {
|
||||
view->getHeadlight()->intensity = static_cast <float> (value) / 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::lightColor()
|
||||
{
|
||||
if (view) {
|
||||
const QColor color = ui->light1Color->color();
|
||||
view->getHeadlight()->color.setValue(color.redF(),
|
||||
color.greenF(),
|
||||
color.blueF());
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::pushIn(void)
|
||||
{
|
||||
if (camera == nullptr)
|
||||
if (camera == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
camera->height = camera->height.getValue() - cam_step;
|
||||
camera->height = camera->height.getValue() - zoomStep;
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::pullOut(void)
|
||||
void DlgSettingsLightSources::zoomOut() const
|
||||
{
|
||||
if (camera == nullptr)
|
||||
if (camera == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
camera->height = camera->height.getValue() + cam_step;
|
||||
camera->height = camera->height.getValue() + zoomStep;
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::changeEvent(QEvent* event)
|
||||
@@ -323,41 +357,4 @@ void DlgSettingsLightSources::changeEvent(QEvent* event)
|
||||
PreferencePage::changeEvent(event);
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::updateDraggerQS()
|
||||
{
|
||||
const float q0 = ui->q0_spnBox->value(),
|
||||
q1 = ui->q1_spnBox->value(),
|
||||
q2 = ui->q2_spnBox->value(),
|
||||
q3 = ui->q3_spnBox->value();
|
||||
|
||||
const SbRotation rotation {q0, q1, q2, q3};
|
||||
|
||||
setLightDirection(rotation, view);
|
||||
setLightDraggerDirection(rotation, lightDragger);
|
||||
|
||||
const SbVec3f dir = getDirectionVector(rotation);
|
||||
|
||||
setValueSilently(ui->x_spnBox, dir[0]);
|
||||
setValueSilently(ui->y_spnBox, dir[1]);
|
||||
setValueSilently(ui->z_spnBox, dir[2]);
|
||||
}
|
||||
|
||||
void DlgSettingsLightSources::updateDraggerXYZ()
|
||||
{
|
||||
const float x = ui->x_spnBox->value(),
|
||||
y = ui->y_spnBox->value(),
|
||||
z = ui->z_spnBox->value();
|
||||
|
||||
const SbRotation rotation {SbVec3f{0.0f, 0.0f, -1.0f}, SbVec3f{x, y, z}};
|
||||
|
||||
setLightDirection(rotation, view);
|
||||
setLightDraggerDirection(rotation, lightDragger);
|
||||
|
||||
setValueSilently(ui->q0_spnBox, rotation[0]);
|
||||
setValueSilently(ui->q1_spnBox, rotation[1]);
|
||||
setValueSilently(ui->q2_spnBox, rotation[2]);
|
||||
setValueSilently(ui->q3_spnBox, rotation[3]);
|
||||
}
|
||||
|
||||
|
||||
#include "moc_DlgSettingsLightSources.cpp"
|
||||
|
||||
@@ -28,8 +28,12 @@
|
||||
#include <Gui/PropertyPage.h>
|
||||
#include <memory>
|
||||
#include <QPointer>
|
||||
#include <App/Application.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
class SoDragger;
|
||||
class SbRotation;
|
||||
class SoDirectionalLightDragger;
|
||||
class SoOrthographicCamera;
|
||||
|
||||
@@ -56,32 +60,26 @@ public:
|
||||
void resetSettingsToDefaults() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateDraggerQS ();
|
||||
void updateDraggerXYZ();
|
||||
void toggleLight(bool on);
|
||||
void lightIntensity(int value);
|
||||
void lightColor();
|
||||
|
||||
void pushIn (void);
|
||||
void pullOut(void);
|
||||
void zoomIn() const;
|
||||
void zoomOut() const;
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent* event) override;
|
||||
|
||||
private:
|
||||
void saveDirection();
|
||||
void loadDirection();
|
||||
void createViewer();
|
||||
SoDirectionalLightDragger* createDragger();
|
||||
static void dragMotionCallback(void *data, SoDragger *drag);
|
||||
void configureViewer();
|
||||
|
||||
Base::Vector3d azimuthElevationToDirection(double azimuth, double elevation);
|
||||
std::pair<double, double> directionToAzimuthElevation(Base::Vector3d direction);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_DlgSettingsLightSources> ui;
|
||||
QPointer <View3DInventorViewer> view;
|
||||
SoDirectionalLightDragger* lightDragger = nullptr;
|
||||
SoOrthographicCamera *camera = nullptr;
|
||||
|
||||
float cam_step = 3.0f;
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
|
||||
float zoomStep = 3.0f;
|
||||
};
|
||||
|
||||
} // namespace Dialog
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>484</width>
|
||||
<width>743</width>
|
||||
<height>515</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -26,141 +26,10 @@
|
||||
<string>Adjust the orientation of the directional light source by dragging the handle with the mouse or use the spin boxes for fine tuning.</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Direction</string>
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="z_spnBox">
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="y_spnBox">
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="z_label">
|
||||
<property name="text">
|
||||
<string notr="true">z</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="x_label">
|
||||
<property name="text">
|
||||
<string notr="true">x</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QDoubleSpinBox" name="q1_spnBox">
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QDoubleSpinBox" name="q2_spnBox">
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QDoubleSpinBox" name="q0_spnBox">
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="y_label">
|
||||
<property name="text">
|
||||
<string notr="true">y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="q2_label">
|
||||
<property name="text">
|
||||
<string notr="true">q2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="q0_label">
|
||||
<property name="text">
|
||||
<string notr="true">q0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QDoubleSpinBox" name="q3_spnBox">
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="q1_label">
|
||||
<property name="text">
|
||||
<string notr="true">q1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="q3_label">
|
||||
<property name="text">
|
||||
<string notr="true">q3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="x_spnBox">
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="5">
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="Gui::View3DInventorViewer" name="viewer" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
@@ -169,7 +38,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
@@ -183,7 +52,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -194,9 +63,9 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="pushInTB">
|
||||
<widget class="QToolButton" name="zoomInButton">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Push In</string>
|
||||
@@ -214,9 +83,9 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="pullOutTB">
|
||||
<widget class="QToolButton" name="zoomOutButton">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Pull Out</string>
|
||||
@@ -238,7 +107,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -254,16 +123,72 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<spacer name="bottomSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<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">
|
||||
<item row="0" column="4">
|
||||
<widget class="QLabel" name="light1Label">
|
||||
<property name="text">
|
||||
<string>Light source</string>
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="6">
|
||||
<widget class="Gui::PrefSpinBox" name="ambientLightIntensitySpinBox">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>AmbientLightIntensity</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="Gui::PrefColorButton" name="backLightColor">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>245</red>
|
||||
<green>245</green>
|
||||
<blue>238</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>BacklightColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="mainLightEnable">
|
||||
<property name="text">
|
||||
<string>Main Light</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
@@ -276,9 +201,226 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="light1Color">
|
||||
<property name="color" stdset="0">
|
||||
<item row="2" column="2">
|
||||
<widget class="Gui::QuantitySpinBox" name="backLightHorizontalAngle">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>-130.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="Gui::QuantitySpinBox" name="backLightVerticalAngle">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>-10.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="backLightEnable">
|
||||
<property name="text">
|
||||
<string>Back Light</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>EnableBacklight</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="Gui::QuantitySpinBox" name="fillLightHorizontalAngle">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>-40.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="light1Label_2">
|
||||
<property name="text">
|
||||
<string>Vertical Angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="Gui::PrefColorButton" name="ambientLightColor">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>AmbientLightColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="light1Label_3">
|
||||
<property name="text">
|
||||
<string>Horizontal Angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6">
|
||||
<widget class="Gui::PrefSpinBox" name="mainLightIntensitySpinBox">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>90</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>HeadlightIntensity</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="Gui::QuantitySpinBox" name="mainLightHorizontalAngle">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="Gui::QuantitySpinBox" name="fillLightVerticalAngle">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="6">
|
||||
<widget class="Gui::PrefSpinBox" name="backLightIntensitySpinBox">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>BacklightIntensity</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="fillLightEnable">
|
||||
<property name="text">
|
||||
<string>Fill Light</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>EnableFillLight</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="6">
|
||||
<widget class="Gui::PrefSpinBox" name="fillLightIntensitySpinBox">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>40</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>FillLightIntensity</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QLabel" name="light1Label_4">
|
||||
<property name="text">
|
||||
<string>Intensity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="Gui::PrefColorButton" name="fillLightColor">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>230</red>
|
||||
<green>250</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>FillLightColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="Gui::QuantitySpinBox" name="mainLightVerticalAngle">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>-46.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="Gui::PrefColorButton" name="mainLightColor">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
@@ -293,83 +435,37 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer1">
|
||||
<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">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<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>
|
||||
<string>Ambient Light</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<spacer name="bottomSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::QuantitySpinBox</class>
|
||||
<extends>QAbstractSpinBox</extends>
|
||||
<header>Gui/QuantitySpinBox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::ColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Gui/Widgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefColorButton</class>
|
||||
<extends>Gui::ColorButton</extends>
|
||||
<class>Gui::PrefSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefSlider</class>
|
||||
<extends>QSlider</extends>
|
||||
<class>Gui::PrefColorButton</class>
|
||||
<extends>Gui::ColorButton</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
@@ -384,262 +480,28 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>checkBoxLight1</tabstop>
|
||||
<tabstop>light1Color</tabstop>
|
||||
<tabstop>sliderIntensity1</tabstop>
|
||||
<tabstop>x_spnBox</tabstop>
|
||||
<tabstop>y_spnBox</tabstop>
|
||||
<tabstop>z_spnBox</tabstop>
|
||||
<tabstop>q0_spnBox</tabstop>
|
||||
<tabstop>q1_spnBox</tabstop>
|
||||
<tabstop>q2_spnBox</tabstop>
|
||||
<tabstop>q3_spnBox</tabstop>
|
||||
<tabstop>mainLightEnable</tabstop>
|
||||
<tabstop>mainLightHorizontalAngle</tabstop>
|
||||
<tabstop>mainLightVerticalAngle</tabstop>
|
||||
<tabstop>mainLightColor</tabstop>
|
||||
<tabstop>mainLightIntensitySpinBox</tabstop>
|
||||
<tabstop>backLightEnable</tabstop>
|
||||
<tabstop>backLightHorizontalAngle</tabstop>
|
||||
<tabstop>backLightVerticalAngle</tabstop>
|
||||
<tabstop>backLightColor</tabstop>
|
||||
<tabstop>backLightIntensitySpinBox</tabstop>
|
||||
<tabstop>fillLightEnable</tabstop>
|
||||
<tabstop>fillLightHorizontalAngle</tabstop>
|
||||
<tabstop>fillLightVerticalAngle</tabstop>
|
||||
<tabstop>fillLightColor</tabstop>
|
||||
<tabstop>fillLightIntensitySpinBox</tabstop>
|
||||
<tabstop>ambientLightColor</tabstop>
|
||||
<tabstop>ambientLightIntensitySpinBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../Icons/resource.qrc"/>
|
||||
</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>339</x>
|
||||
<y>65</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>
|
||||
<connection>
|
||||
<sender>q1_spnBox</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>updateDraggerQS(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>399</x>
|
||||
<y>168</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>q2_spnBox</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>updateDraggerQS(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>399</x>
|
||||
<y>200</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>q3_spnBox</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>updateDraggerQS(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>399</x>
|
||||
<y>232</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>q0_spnBox</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>updateDraggerQS(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>422</x>
|
||||
<y>128</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkBoxLight1</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>toggleLight(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>68</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>sliderIntensity1</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>lightIntensity(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>404</x>
|
||||
<y>52</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>light1Color</sender>
|
||||
<signal>changed(void)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>lightColor(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>140</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>x_spnBox</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>updateDraggerXYZ(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>186</x>
|
||||
<y>141</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>y_spnBox</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>updateDraggerXYZ(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>186</x>
|
||||
<y>173</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>z_spnBox</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>updateDraggerXYZ(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>186</x>
|
||||
<y>205</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>pushInTB</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>pushIn(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>126</x>
|
||||
<y>224</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>pullOutTB</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Gui::Dialog::DlgSettingsLightSources</receiver>
|
||||
<slot>pullOut(void)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>126</x>
|
||||
<y>255</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>257</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
<slots>
|
||||
<slot>updateDraggerQS(void)</slot>
|
||||
<slot>updateDraggerXYZ(void)</slot>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define GUI_UTILITIES_H
|
||||
|
||||
#include <vector>
|
||||
#include <QColor>
|
||||
#include <App/Material.h>
|
||||
#include <Base/Converter.h>
|
||||
#include <Base/ViewProj.h>
|
||||
@@ -33,7 +34,6 @@
|
||||
#include <Inventor/SbVec2f.h>
|
||||
#include <Inventor/SbViewVolume.h>
|
||||
|
||||
|
||||
class SbViewVolume;
|
||||
class QAbstractItemView;
|
||||
|
||||
@@ -105,6 +105,18 @@ private:
|
||||
const vec_type& v;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vec_traits<QColor> {
|
||||
using vec_type = QColor;
|
||||
using float_type = float;
|
||||
explicit vec_traits(const vec_type& v) : v(v){}
|
||||
inline std::tuple<float_type,float_type,float_type> get() const {
|
||||
return std::make_tuple(v.redF(), v.greenF(), v.blueF());
|
||||
}
|
||||
private:
|
||||
const vec_type& v;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline SbMatrix convertTo<SbMatrix, Base::Matrix4D>(const Base::Matrix4D& vec2)
|
||||
{
|
||||
|
||||
@@ -130,6 +130,8 @@
|
||||
#include "Navigation/NavigationAnimation.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
#include <Inventor/nodes/SoRotation.h>
|
||||
#include <Inventor/nodes/SoTransformSeparator.h>
|
||||
#include <Inventor/So3DAnnotation.h>
|
||||
|
||||
|
||||
@@ -435,12 +437,25 @@ void View3DInventorViewer::init()
|
||||
|
||||
// setup light sources
|
||||
SoDirectionalLight* hl = this->getHeadlight();
|
||||
|
||||
environment = new SoEnvironment();
|
||||
environment->ref();
|
||||
environment->setName("environment");
|
||||
|
||||
backlight = new SoDirectionalLight();
|
||||
backlight->ref();
|
||||
backlight->setName("backlight");
|
||||
backlight->direction.setValue(-hl->direction.getValue());
|
||||
backlight->on.setValue(false); // by default off
|
||||
|
||||
fillLight = new SoDirectionalLight();
|
||||
fillLight->ref();
|
||||
fillLight->setName("filllight");
|
||||
fillLight->direction.setValue(-0.60, -0.35, -0.79);
|
||||
fillLight->intensity.setValue(0.6);
|
||||
fillLight->color.setValue(0.95, 0.95, 1.0);
|
||||
fillLight->on.setValue(false); // by default off
|
||||
|
||||
// Set up background scenegraph with image in it.
|
||||
backgroundroot = new SoSeparator;
|
||||
backgroundroot->ref();
|
||||
@@ -470,10 +485,20 @@ void View3DInventorViewer::init()
|
||||
cam->farDistance = 10;
|
||||
// NOLINTEND
|
||||
|
||||
lightRotation = new SoRotation;
|
||||
lightRotation->ref();
|
||||
lightRotation->rotation.connectFrom(&cam->orientation);
|
||||
|
||||
this->foregroundroot->addChild(cam);
|
||||
this->foregroundroot->addChild(lm);
|
||||
this->foregroundroot->addChild(bc);
|
||||
|
||||
auto threePointLightingSeparator = new SoTransformSeparator;
|
||||
threePointLightingSeparator->addChild(lightRotation);
|
||||
threePointLightingSeparator->addChild(this->fillLight);
|
||||
|
||||
this->foregroundroot->addChild(cam);
|
||||
|
||||
// NOTE: For every mouse click event the SoFCUnifiedSelection searches for the picked
|
||||
// point which causes a certain slow-down because for all objects the primitives
|
||||
// must be created. Using an SoSeparator avoids this drawback.
|
||||
@@ -482,6 +507,8 @@ void View3DInventorViewer::init()
|
||||
|
||||
// set the ViewProvider root node
|
||||
pcViewProviderRoot = selectionRoot;
|
||||
pcViewProviderRoot->addChild(threePointLightingSeparator);
|
||||
pcViewProviderRoot->addChild(environment);
|
||||
|
||||
// increase refcount before passing it to setScenegraph(), to avoid
|
||||
// premature destruction
|
||||
@@ -633,6 +660,10 @@ View3DInventorViewer::~View3DInventorViewer()
|
||||
this->objectGroup = nullptr;
|
||||
this->backlight->unref();
|
||||
this->backlight = nullptr;
|
||||
this->fillLight->unref();
|
||||
this->fillLight = nullptr;
|
||||
this->environment->unref();
|
||||
this->environment = nullptr;
|
||||
|
||||
inventorSelection.reset(nullptr);
|
||||
|
||||
@@ -1545,6 +1576,25 @@ bool View3DInventorViewer::isBacklightEnabled() const
|
||||
return this->backlight->on.getValue();
|
||||
}
|
||||
|
||||
SoDirectionalLight* View3DInventorViewer::getFillLight() const
|
||||
{
|
||||
return this->fillLight;
|
||||
}
|
||||
|
||||
void View3DInventorViewer::setFillLightEnabled(bool on)
|
||||
{
|
||||
this->fillLight->on = on;
|
||||
}
|
||||
|
||||
bool View3DInventorViewer::isFillLightEnabled() const
|
||||
{
|
||||
return this->fillLight->on.getValue();
|
||||
}
|
||||
SoEnvironment* View3DInventorViewer::getEnvironment() const
|
||||
{
|
||||
return this->environment;
|
||||
}
|
||||
|
||||
void View3DInventorViewer::setSceneGraph(SoNode* root)
|
||||
{
|
||||
inherited::setSceneGraph(root);
|
||||
@@ -3175,18 +3225,22 @@ void View3DInventorViewer::setCameraType(SoType type)
|
||||
{
|
||||
inherited::setCameraType(type);
|
||||
|
||||
SoCamera* cam = this->getSoRenderManager()->getCamera();
|
||||
|
||||
if (!cam) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type.isDerivedFrom(SoPerspectiveCamera::getClassTypeId())) {
|
||||
// When doing a viewAll() for an orthographic camera and switching
|
||||
// to perspective the scene looks completely strange because of the
|
||||
// heightAngle. Setting it to 45 deg also causes an issue with a too
|
||||
// close camera but we don't have this other ugly effect.
|
||||
SoCamera* cam = this->getSoRenderManager()->getCamera();
|
||||
if (!cam) {
|
||||
return;
|
||||
}
|
||||
|
||||
static_cast<SoPerspectiveCamera*>(cam)->heightAngle = (float)(M_PI / 4.0); // NOLINT
|
||||
}
|
||||
|
||||
lightRotation->rotation.connectFrom(&cam->orientation);
|
||||
}
|
||||
|
||||
void View3DInventorViewer::moveCameraTo(const SbRotation& orientation, const SbVec3f& position, int duration)
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
#include "View3DInventorSelection.h"
|
||||
#include "Quarter/SoQTQuarterAdaptor.h"
|
||||
|
||||
#include <Inventor/nodes/SoEnvironment.h>
|
||||
#include <Inventor/nodes/SoRotation.h>
|
||||
|
||||
|
||||
class SoTranslation;
|
||||
class SoTransform;
|
||||
@@ -146,6 +149,13 @@ public:
|
||||
SoDirectionalLight* getBacklight() const;
|
||||
void setBacklightEnabled(bool on);
|
||||
bool isBacklightEnabled() const;
|
||||
|
||||
SoDirectionalLight* getFillLight() const;
|
||||
void setFillLightEnabled(bool on);
|
||||
bool isFillLightEnabled() const;
|
||||
|
||||
SoEnvironment* getEnvironment() const;
|
||||
|
||||
void setSceneGraph (SoNode *root) override;
|
||||
bool searchNode(SoNode*) const;
|
||||
|
||||
@@ -496,7 +506,12 @@ private:
|
||||
SoFCBackgroundGradient *pcBackGround;
|
||||
SoSeparator * backgroundroot;
|
||||
SoSeparator * foregroundroot;
|
||||
|
||||
SoDirectionalLight* backlight;
|
||||
SoDirectionalLight* fillLight;
|
||||
SoEnvironment* environment;
|
||||
|
||||
SoRotation* lightRotation;
|
||||
|
||||
// Scene graph root
|
||||
SoSeparator * pcViewProviderRoot;
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "View3DSettings.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
|
||||
#include <Base/Tools.h>
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
View3DSettings::View3DSettings(ParameterGrp::handle hGrp,
|
||||
@@ -100,6 +102,12 @@ void View3DSettings::applySettings()
|
||||
OnChange(*hGrp,"BacklightColor");
|
||||
OnChange(*hGrp,"BacklightDirection");
|
||||
OnChange(*hGrp,"BacklightIntensity");
|
||||
OnChange(*hGrp,"EnableFillLight");
|
||||
OnChange(*hGrp,"FillLightColor");
|
||||
OnChange(*hGrp,"FillLightDirection");
|
||||
OnChange(*hGrp,"FillLightIntensity");
|
||||
OnChange(*hGrp,"AmbientLightColor");
|
||||
OnChange(*hGrp,"AmbientLightIntensity");
|
||||
OnChange(*hGrp,"NavigationStyle");
|
||||
OnChange(*hGrp,"OrbitStyle");
|
||||
OnChange(*hGrp,"Sensitivity");
|
||||
@@ -121,7 +129,7 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"HeadlightColor") == 0) {
|
||||
unsigned long headlight = rGrp.GetUnsigned("HeadlightColor",ULONG_MAX); // default color (white)
|
||||
unsigned long headlight = rGrp.GetUnsigned("HeadlightColor", 0xFFFFFFFF); // default color (white)
|
||||
float transparency;
|
||||
SbColor headlightColor;
|
||||
headlightColor.setPackedValue((uint32_t)headlight, transparency);
|
||||
@@ -131,9 +139,9 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
||||
}
|
||||
else if (strcmp(Reason,"HeadlightDirection") == 0) {
|
||||
try {
|
||||
std::string pos = rGrp.GetASCII("HeadlightDirection");
|
||||
std::string pos = rGrp.GetASCII("HeadlightDirection", defaultHeadLightDirection);
|
||||
if (!pos.empty()) {
|
||||
Base::Vector3f dir = Base::to_vector(pos);
|
||||
Base::Vector3f dir = Base::stringToVector(pos);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getHeadlight()->direction.setValue(dir.x, dir.y, dir.z);
|
||||
}
|
||||
@@ -144,18 +152,18 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"HeadlightIntensity") == 0) {
|
||||
long value = rGrp.GetInt("HeadlightIntensity", 100);
|
||||
long value = rGrp.GetInt("HeadlightIntensity", 90);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getHeadlight()->intensity.setValue((float)value/100.0f);
|
||||
_viewer->getHeadlight()->intensity.setValue(Base::fromPercent(value));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"EnableBacklight") == 0) {
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->setBacklightEnabled(rGrp.GetBool("EnableBacklight", false));
|
||||
_viewer->setBacklightEnabled(rGrp.GetBool("EnableBacklight", true));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"BacklightColor") == 0) {
|
||||
unsigned long backlight = rGrp.GetUnsigned("BacklightColor",ULONG_MAX); // default color (white)
|
||||
unsigned long backlight = rGrp.GetUnsigned("BacklightColor", 0xF5F5EEFF);
|
||||
float transparency;
|
||||
SbColor backlightColor;
|
||||
backlightColor.setPackedValue((uint32_t)backlight, transparency);
|
||||
@@ -165,9 +173,9 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
||||
}
|
||||
else if (strcmp(Reason,"BacklightDirection") == 0) {
|
||||
try {
|
||||
std::string pos = rGrp.GetASCII("BacklightDirection");
|
||||
std::string pos = rGrp.GetASCII("BacklightDirection", defaultBackLightDirection);
|
||||
if (!pos.empty()) {
|
||||
Base::Vector3f dir = Base::to_vector(pos);
|
||||
Base::Vector3f dir = Base::stringToVector(pos);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getBacklight()->direction.setValue(dir.x, dir.y, dir.z);
|
||||
}
|
||||
@@ -178,9 +186,58 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"BacklightIntensity") == 0) {
|
||||
long value = rGrp.GetInt("BacklightIntensity", 100);
|
||||
long value = rGrp.GetInt("BacklightIntensity", 60);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getBacklight()->intensity.setValue((float)value/100.0f);
|
||||
_viewer->getBacklight()->intensity.setValue(Base::fromPercent(value));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"EnableFillLight") == 0) {
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->setFillLightEnabled(rGrp.GetBool("EnableFillLight", true));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"FillLightColor") == 0) {
|
||||
unsigned long backlight = rGrp.GetUnsigned("FillLightColor", 0xE6FAFFFF); // default color (white)
|
||||
float transparency;
|
||||
SbColor backlightColor;
|
||||
backlightColor.setPackedValue((uint32_t)backlight, transparency);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getFillLight()->color.setValue(backlightColor);
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"FillLightDirection") == 0) {
|
||||
try {
|
||||
std::string pos = rGrp.GetASCII("FillLightDirection", defaultFillLightDirection);
|
||||
if (!pos.empty()) {
|
||||
Base::Vector3f dir = Base::stringToVector(pos);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getFillLight()->direction.setValue(dir.x, dir.y, dir.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
// ignore exception
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"FillLightIntensity") == 0) {
|
||||
long value = rGrp.GetInt("FillLightIntensity", 40);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getFillLight()->intensity.setValue(Base::fromPercent(value));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"AmbientLightColor") == 0) {
|
||||
unsigned long color = rGrp.GetUnsigned("AmbientLightColor", 0xFFFFFFFF);
|
||||
float transparency;
|
||||
SbColor backlightColor;
|
||||
backlightColor.setPackedValue((uint32_t)color, transparency);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getEnvironment()->ambientColor.setValue(backlightColor);
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"AmbientLightIntensity") == 0) {
|
||||
long value = rGrp.GetInt("AmbientLightIntensity", 20);
|
||||
for (auto _viewer : _viewers) {
|
||||
_viewer->getEnvironment()->ambientIntensity.setValue(Base::fromPercent(value));
|
||||
}
|
||||
}
|
||||
else if (strcmp(Reason,"EnablePreselection") == 0) {
|
||||
|
||||
@@ -33,6 +33,10 @@ class View3DInventorViewer;
|
||||
class GuiExport View3DSettings: public ParameterGrp::ObserverType
|
||||
{
|
||||
public:
|
||||
static constexpr auto defaultHeadLightDirection = "(0.6841049,-0.12062616,-0.7193398)";
|
||||
static constexpr auto defaultFillLightDirection = "(-0.6403416,0.7631294,0.087155744)";
|
||||
static constexpr auto defaultBackLightDirection = "(-0.7544065,-0.63302225,-0.17364818)";
|
||||
|
||||
View3DSettings(ParameterGrp::handle hGrp, View3DInventorViewer*);
|
||||
View3DSettings(ParameterGrp::handle hGrp, const std::vector<View3DInventorViewer*>&);
|
||||
~View3DSettings() override;
|
||||
|
||||
@@ -49,21 +49,10 @@
|
||||
#include "ViewProviderGeometryObject.h"
|
||||
#include "ViewProviderGeometryObjectPy.h"
|
||||
|
||||
#include <Base/Tools.h>
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
// Helper functions to consistently convert between float and long
|
||||
namespace {
|
||||
float fromPercent(long value)
|
||||
{
|
||||
return std::roundf(value) / 100.0F;
|
||||
}
|
||||
|
||||
long toPercent(float value)
|
||||
{
|
||||
return std::lround(100.0 * value);
|
||||
}
|
||||
}
|
||||
|
||||
PROPERTY_SOURCE(Gui::ViewProviderGeometryObject, Gui::ViewProviderDragger)
|
||||
|
||||
const App::PropertyIntegerConstraint::Constraints intPercent = {0, 100, 5};
|
||||
@@ -71,7 +60,8 @@ const App::PropertyIntegerConstraint::Constraints intPercent = {0, 100, 5};
|
||||
ViewProviderGeometryObject::ViewProviderGeometryObject()
|
||||
{
|
||||
App::Material mat = App::Material::getDefaultAppearance();
|
||||
long initialTransparency = toPercent(mat.transparency);
|
||||
|
||||
long initialTransparency = Base::toPercent(mat.transparency);
|
||||
|
||||
static const char* dogroup = "Display Options";
|
||||
static const char* sgroup = "Selection";
|
||||
@@ -140,8 +130,8 @@ void ViewProviderGeometryObject::onChanged(const App::Property* prop)
|
||||
setSelectable(Sel);
|
||||
}
|
||||
else if (prop == &Transparency) {
|
||||
long value = toPercent(ShapeAppearance.getTransparency());
|
||||
float trans = fromPercent(Transparency.getValue());
|
||||
long value = Base::toPercent(ShapeAppearance.getTransparency());
|
||||
float trans = Base::fromPercent(Transparency.getValue());
|
||||
if (value != Transparency.getValue()) {
|
||||
ShapeAppearance.setTransparency(trans);
|
||||
}
|
||||
@@ -152,7 +142,7 @@ void ViewProviderGeometryObject::onChanged(const App::Property* prop)
|
||||
if (getObject() && getObject()->testStatus(App::ObjectStatus::TouchOnColorChange)) {
|
||||
getObject()->touch(true);
|
||||
}
|
||||
long value = toPercent(ShapeAppearance.getTransparency());
|
||||
long value = Base::toPercent(ShapeAppearance.getTransparency());
|
||||
if (value != Transparency.getValue()) {
|
||||
Transparency.setValue(value);
|
||||
}
|
||||
|
||||
@@ -71,17 +71,6 @@ namespace
|
||||
{
|
||||
constexpr const int lowPrec = 2;
|
||||
constexpr const int highPrec = 16;
|
||||
|
||||
int toPercent(float value)
|
||||
{
|
||||
return static_cast<int>(100 * value); // NOLINT
|
||||
}
|
||||
|
||||
float fromPercent(int value)
|
||||
{
|
||||
return static_cast<float>(value) / 100.0F; // NOLINT
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PropertyItemFactory& PropertyItemFactory::instance()
|
||||
@@ -3658,7 +3647,7 @@ int PropertyMaterialItem::getShininess() const
|
||||
}
|
||||
|
||||
auto val = value.value<Material>();
|
||||
return toPercent(val.shininess);
|
||||
return Base::toPercent(val.shininess);
|
||||
}
|
||||
|
||||
void PropertyMaterialItem::setShininess(int s)
|
||||
@@ -3669,7 +3658,7 @@ void PropertyMaterialItem::setShininess(int s)
|
||||
}
|
||||
|
||||
auto mat = value.value<Material>();
|
||||
mat.shininess = fromPercent(s);
|
||||
mat.shininess = Base::fromPercent(s);
|
||||
setValue(QVariant::fromValue<Material>(mat));
|
||||
}
|
||||
|
||||
@@ -3681,7 +3670,7 @@ int PropertyMaterialItem::getTransparency() const
|
||||
}
|
||||
|
||||
auto val = value.value<Material>();
|
||||
return toPercent(val.transparency);
|
||||
return Base::toPercent(val.transparency);
|
||||
}
|
||||
|
||||
void PropertyMaterialItem::setTransparency(int t)
|
||||
@@ -3692,7 +3681,7 @@ void PropertyMaterialItem::setTransparency(int t)
|
||||
}
|
||||
|
||||
auto mat = value.value<Material>();
|
||||
mat.transparency = fromPercent(t);
|
||||
mat.transparency = Base::fromPercent(t);
|
||||
setValue(QVariant::fromValue<Material>(mat));
|
||||
}
|
||||
|
||||
@@ -3747,8 +3736,8 @@ QVariant PropertyMaterialItem::toolTip(const App::Property* prop) const
|
||||
.arg(ec.red())
|
||||
.arg(ec.green())
|
||||
.arg(ec.blue())
|
||||
.arg(toPercent(value.shininess))
|
||||
.arg(toPercent(value.transparency));
|
||||
.arg(Base::toPercent(value.shininess))
|
||||
.arg(Base::toPercent(value.transparency));
|
||||
|
||||
return {data};
|
||||
}
|
||||
@@ -4085,7 +4074,7 @@ int PropertyMaterialListItem::getShininess() const
|
||||
}
|
||||
|
||||
auto mat = list[0].value<Material>();
|
||||
return toPercent(mat.shininess);
|
||||
return Base::toPercent(mat.shininess);
|
||||
}
|
||||
|
||||
void PropertyMaterialListItem::setShininess(int s)
|
||||
@@ -4105,7 +4094,7 @@ void PropertyMaterialListItem::setShininess(int s)
|
||||
}
|
||||
|
||||
auto mat = list[0].value<Material>();
|
||||
mat.shininess = fromPercent(s);
|
||||
mat.shininess = Base::fromPercent(s);
|
||||
list[0] = QVariant::fromValue<Material>(mat);
|
||||
setValue(list);
|
||||
}
|
||||
@@ -4127,7 +4116,7 @@ int PropertyMaterialListItem::getTransparency() const
|
||||
}
|
||||
|
||||
auto mat = list[0].value<Material>();
|
||||
return toPercent(mat.transparency);
|
||||
return Base::toPercent(mat.transparency);
|
||||
}
|
||||
|
||||
void PropertyMaterialListItem::setTransparency(int t)
|
||||
@@ -4147,7 +4136,7 @@ void PropertyMaterialListItem::setTransparency(int t)
|
||||
}
|
||||
|
||||
auto mat = list[0].value<Material>();
|
||||
mat.transparency = fromPercent(t);
|
||||
mat.transparency = Base::fromPercent(t);
|
||||
list[0] = QVariant::fromValue<Material>(mat);
|
||||
setValue(list);
|
||||
}
|
||||
@@ -4235,8 +4224,8 @@ QVariant PropertyMaterialListItem::toolTip(const App::Property* prop) const
|
||||
.arg(ec.red())
|
||||
.arg(ec.green())
|
||||
.arg(ec.blue())
|
||||
.arg(toPercent(value.shininess))
|
||||
.arg(toPercent(value.transparency));
|
||||
.arg(Base::toPercent(value.shininess))
|
||||
.arg(Base::toPercent(value.transparency));
|
||||
|
||||
return {data};
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
#include "ViewProviderAnalysis.h"
|
||||
#include "ViewProviderFemPostObject.h"
|
||||
|
||||
#include <Base/Tools.h>
|
||||
|
||||
|
||||
using namespace FemGui;
|
||||
namespace sp = std::placeholders;
|
||||
@@ -659,7 +661,7 @@ void ViewProviderFemPostObject::WriteColorData(bool ResetColorBarRange)
|
||||
|
||||
if (Field.getEnumVector().empty() || Field.getValue() == 0) {
|
||||
m_material->diffuseColor.setValue(SbColor(0.8, 0.8, 0.8));
|
||||
float trans = float(Transparency.getValue()) / 100.0;
|
||||
float trans = Base::fromPercent(Transparency.getValue());
|
||||
m_material->transparency.setValue(trans);
|
||||
m_materialBinding->value = SoMaterialBinding::OVERALL;
|
||||
m_materialBinding->touch();
|
||||
@@ -696,7 +698,7 @@ void ViewProviderFemPostObject::WriteColorData(bool ResetColorBarRange)
|
||||
SbColor* diffcol = m_material->diffuseColor.startEditing();
|
||||
SbColor* edgeDiffcol = m_matPlainEdges->diffuseColor.startEditing();
|
||||
|
||||
float overallTransp = Transparency.getValue() / 100.0f;
|
||||
float overallTransp = Base::fromPercent(Transparency.getValue());
|
||||
m_material->transparency.setNum(numPts);
|
||||
m_matPlainEdges->transparency.setNum(numPts);
|
||||
float* transp = m_material->transparency.startEditing();
|
||||
@@ -737,7 +739,7 @@ void ViewProviderFemPostObject::WriteColorData(bool ResetColorBarRange)
|
||||
|
||||
void ViewProviderFemPostObject::WriteTransparency()
|
||||
{
|
||||
float trans = static_cast<float>(Transparency.getValue()) / 100.0;
|
||||
float trans = Base::fromPercent(Transparency.getValue());
|
||||
float* value = m_material->transparency.startEditing();
|
||||
float* edgeValue = m_matPlainEdges->transparency.startEditing();
|
||||
// m_material and m_matPlainEdges field containers have same size
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "ModelManager.h"
|
||||
#include "ModelUuids.h"
|
||||
|
||||
#include <Base/Tools.h>
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
@@ -174,8 +176,8 @@ std::shared_ptr<App::Material> MaterialManager::defaultAppearance()
|
||||
|
||||
long initialTransparency = hGrp->GetInt("DefaultShapeTransparency", 0);
|
||||
long initialShininess = hGrp->GetInt("DefaultShapeShininess", 90);
|
||||
mat.shininess = ((float)initialShininess / 100.0F);
|
||||
mat.transparency = ((float)initialTransparency / 100.0F);
|
||||
mat.shininess = Base::fromPercent(initialShininess);
|
||||
mat.transparency = Base::fromPercent(initialTransparency);
|
||||
|
||||
return std::make_shared<App::Material>(mat);
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ void ViewProviderMesh::onChanged(const App::Property* prop)
|
||||
pcMatBinding->value = SoMaterialBinding::OVERALL;
|
||||
}
|
||||
if (prop == &LineTransparency) {
|
||||
float trans = LineTransparency.getValue() / 100.0F;
|
||||
float trans = Base::fromPercent(LineTransparency.getValue());
|
||||
pLineColor->transparency = trans;
|
||||
}
|
||||
else if (prop == &LineWidth) {
|
||||
@@ -590,7 +590,7 @@ void ViewProviderMesh::tryColorPerVertexOrFace(bool on)
|
||||
pcMatBinding->value = SoMaterialBinding::OVERALL;
|
||||
const App::Color& c = ShapeAppearance.getDiffuseColor();
|
||||
pcShapeMaterial->diffuseColor.setValue(c.r, c.g, c.b);
|
||||
pcShapeMaterial->transparency.setValue(Transparency.getValue() / 100.0F);
|
||||
pcShapeMaterial->transparency.setValue(Base::fromPercent(Transparency.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "ViewProvider.h"
|
||||
|
||||
#include <Base/Tools.h>
|
||||
|
||||
|
||||
using namespace PartGui;
|
||||
|
||||
@@ -88,7 +90,7 @@ void ViewProviderPart::applyTransparency(float transparency, std::vector<App::Co
|
||||
for (auto& j : colors) {
|
||||
// transparency hasn't been set for this face
|
||||
if (j.a == 0.0) {
|
||||
j.setTransparency(transparency/100.0F); // transparency comes in percent
|
||||
j.setTransparency(Base::fromPercent(transparency)); // transparency comes in percent
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,7 +103,7 @@ void ViewProviderPart::applyTransparency(float transparency, std::vector<App::Ma
|
||||
for (auto& j : colors) {
|
||||
// transparency hasn't been set for this face
|
||||
if (j.transparency == 0.0) {
|
||||
j.transparency = transparency / 100.0F; // transparency comes in percent
|
||||
j.transparency = Base::fromPercent(transparency); // transparency comes in percent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,19 +97,6 @@ FC_LOG_LEVEL_INIT("Part", true, true)
|
||||
|
||||
using namespace PartGui;
|
||||
|
||||
// Helper functions to consistently convert between float and long
|
||||
namespace {
|
||||
float fromPercent(long value)
|
||||
{
|
||||
return std::roundf(value) / 100.0F;
|
||||
}
|
||||
|
||||
long toPercent(float value)
|
||||
{
|
||||
return std::lround(100.0 * value);
|
||||
}
|
||||
}
|
||||
|
||||
PROPERTY_SOURCE(PartGui::ViewProviderPartExt, Gui::ViewProviderGeometryObject)
|
||||
|
||||
|
||||
@@ -364,9 +351,9 @@ void ViewProviderPartExt::onChanged(const App::Property* prop)
|
||||
}
|
||||
else if (prop == &Transparency) {
|
||||
const App::Material& Mat = ShapeAppearance[0];
|
||||
long value = toPercent(Mat.transparency);
|
||||
long value = Base::toPercent(Mat.transparency);
|
||||
if (value != Transparency.getValue()) {
|
||||
float trans = fromPercent(Transparency.getValue());
|
||||
float trans = Base::fromPercent(Transparency.getValue());
|
||||
ShapeAppearance.setTransparency(trans);
|
||||
}
|
||||
}
|
||||
@@ -676,7 +663,7 @@ std::map<std::string,App::Color> ViewProviderPartExt::getElementColors(const cha
|
||||
|
||||
if(!element || !element[0]) {
|
||||
auto color = ShapeAppearance.getDiffuseColor();
|
||||
color.setTransparency(Transparency.getValue()/100.0F);
|
||||
color.setTransparency(Base::fromPercent(Transparency.getValue()));
|
||||
ret["Face"] = color;
|
||||
ret["Edge"] = LineColor.getValue();
|
||||
ret["Vertex"] = PointColor.getValue();
|
||||
@@ -687,7 +674,7 @@ std::map<std::string,App::Color> ViewProviderPartExt::getElementColors(const cha
|
||||
auto size = ShapeAppearance.getSize();
|
||||
if(element[4]=='*') {
|
||||
auto color = ShapeAppearance.getDiffuseColor();
|
||||
color.setTransparency(Transparency.getValue()/100.0F);
|
||||
color.setTransparency(Base::fromPercent(Transparency.getValue()));
|
||||
bool singleColor = true;
|
||||
for(int i=0;i<size;++i) {
|
||||
if (ShapeAppearance.getDiffuseColor(i) != color) {
|
||||
@@ -699,7 +686,7 @@ std::map<std::string,App::Color> ViewProviderPartExt::getElementColors(const cha
|
||||
}
|
||||
if(size && singleColor) {
|
||||
color = ShapeAppearance.getDiffuseColor(0);
|
||||
color.setTransparency(Transparency.getValue()/100.0F);
|
||||
color.setTransparency(Base::fromPercent(100.0F));
|
||||
ret.clear();
|
||||
}
|
||||
ret["Face"] = color;
|
||||
@@ -710,7 +697,7 @@ std::map<std::string,App::Color> ViewProviderPartExt::getElementColors(const cha
|
||||
else
|
||||
ret[element] = ShapeAppearance.getDiffuseColor();
|
||||
if(size==1)
|
||||
ret[element].setTransparency(Transparency.getValue()/100.0F);
|
||||
ret[element].setTransparency(Base::fromPercent(Transparency.getValue()));
|
||||
}
|
||||
} else if (boost::starts_with(element,"Edge")) {
|
||||
auto size = LineColorArray.getSize();
|
||||
|
||||
@@ -3303,7 +3303,7 @@ void ViewProviderSketch::unsetEdit(int ModNum)
|
||||
// Resets the override draw style mode when leaving the sketch edit mode.
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Sketcher/General");
|
||||
auto disableShadedView = hGrp->GetBool("DisableShadedView", true);
|
||||
auto disableShadedView = hGrp->GetBool("DisableShadedView", false);
|
||||
if (disableShadedView) {
|
||||
Gui::View3DInventorViewer* viewer =
|
||||
static_cast<Gui::View3DInventor*>(mdi)->getViewer();
|
||||
@@ -3400,7 +3400,7 @@ void ViewProviderSketch::setEditViewer(Gui::View3DInventorViewer* viewer, int Mo
|
||||
// Sets the view mode to no shading to prevent visibility issues against parallel surfaces with shininess when entering the sketch mode.
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Sketcher/General");
|
||||
auto disableShadedView = hGrp->GetBool("DisableShadedView", true);
|
||||
auto disableShadedView = hGrp->GetBool("DisableShadedView", false);
|
||||
|
||||
hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Sketcher/General");
|
||||
|
||||
Reference in New Issue
Block a user