mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-02-01 10:30:08 -05:00
Add option to display affines in polar coords.
This commit is contained in:
parent
b1d5db261b
commit
c01f444d52
@ -71,6 +71,14 @@ void DoubleSpinBox::DoubleClickNonZero(double val)
|
||||
m_DoubleClickNonZero = val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default step used when the user scrolls.
|
||||
/// </summary>
|
||||
double DoubleSpinBox::Step()
|
||||
{
|
||||
return m_Step;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the default step to be used when the user scrolls.
|
||||
/// </summary>
|
||||
@ -80,6 +88,14 @@ void DoubleSpinBox::Step(double step)
|
||||
m_Step = step;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the small step to be used when the user holds down shift while scrolling.
|
||||
/// </summary>
|
||||
double DoubleSpinBox::SmallStep()
|
||||
{
|
||||
return m_SmallStep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the small step to be used when the user holds down shift while scrolling.
|
||||
/// The default is step / 10, so use this if something else is needed.
|
||||
|
@ -22,7 +22,9 @@ public:
|
||||
void DoubleClick(bool b);
|
||||
void DoubleClickZero(double val);
|
||||
void DoubleClickNonZero(double val);
|
||||
double Step();
|
||||
void Step(double step);
|
||||
double SmallStep();
|
||||
void SmallStep(double step);
|
||||
QLineEdit* lineEdit();
|
||||
|
||||
|
@ -211,6 +211,7 @@ public slots:
|
||||
|
||||
void OnAffineGroupBoxToggled(bool on);
|
||||
void OnAffineDrawAllCurrentRadioButtonToggled(bool checked);
|
||||
void OnPolarAffineCheckBoxStateChanged(int state);
|
||||
|
||||
//Xforms Color.
|
||||
void OnXformColorIndexChanged(double d);
|
||||
@ -384,6 +385,9 @@ private:
|
||||
DoubleSpinBox* m_PostY2Spin;
|
||||
DoubleSpinBox* m_PostO1Spin;
|
||||
DoubleSpinBox* m_PostO2Spin;
|
||||
|
||||
DoubleSpinBox* m_PreSpins[6];
|
||||
DoubleSpinBox* m_PostSpins[6];
|
||||
|
||||
//Palette.
|
||||
SpinBox* m_PaletteHueSpin;
|
||||
|
@ -353,7 +353,7 @@
|
||||
<enum>QTabWidget::Triangular</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="usesScrollButtons">
|
||||
<bool>true</bool>
|
||||
@ -504,8 +504,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>259</width>
|
||||
<height>852</height>
|
||||
<width>73</width>
|
||||
<height>837</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
@ -2285,7 +2285,7 @@ SpinBox
|
||||
<enum>QTabWidget::Triangular</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="ColorTab">
|
||||
<property name="sizePolicy">
|
||||
@ -2825,8 +2825,8 @@ SpinBox
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>118</width>
|
||||
<height>597</height>
|
||||
<width>245</width>
|
||||
<height>747</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
@ -4065,6 +4065,13 @@ SpinBox
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="PolarAffineCheckBox">
|
||||
<property name="text">
|
||||
<string>Polar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="PivotGroupBox">
|
||||
<property name="autoFillBackground">
|
||||
@ -5041,8 +5048,8 @@ SpinBox
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>259</width>
|
||||
<height>853</height>
|
||||
<width>73</width>
|
||||
<height>454</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -148,6 +148,7 @@ public:
|
||||
virtual void MoveCurrentXform(double x, double y, bool pre) { }
|
||||
virtual void ScaleCurrentXform(double scale, bool pre) { }
|
||||
virtual void ResetCurrentXformAffine(bool pre) { }
|
||||
virtual void FillBothAffines() { }
|
||||
|
||||
//Xforms Color.
|
||||
virtual void XformColorIndexChanged(double d, bool updateRender) { }
|
||||
@ -368,6 +369,7 @@ public:
|
||||
virtual void MoveCurrentXform(double x, double y, bool pre) override;
|
||||
virtual void ScaleCurrentXform(double scale, bool pre) override;
|
||||
virtual void ResetCurrentXformAffine(bool pre) override;
|
||||
virtual void FillBothAffines() override;
|
||||
void FillAffineWithXform(Xform<T>* xform, bool pre);
|
||||
|
||||
//Xforms Color.
|
||||
|
@ -97,48 +97,64 @@ void Fractorium::InitXformsAffineUI()
|
||||
connect(ui.ShowPostAffineAllRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ShowPostAffineCurrentRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
|
||||
connect(ui.PolarAffineCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnPolarAffineCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
|
||||
#ifndef WIN32
|
||||
//For some reason linux makes these 24x24, even though the designer explicitly says 16x16.
|
||||
//Also, in order to get 4 pixels of spacing between elements in the grid layout, 0 must be specified.
|
||||
ui.PreFlipHorizontalButton->setIconSize(QSize(16, 16));
|
||||
ui.PreFlipVerticalButton->setIconSize(QSize(16, 16));
|
||||
ui.PreRotate90CButton->setIconSize(QSize(16, 16));
|
||||
ui.PreRotate90CcButton->setIconSize(QSize(16, 16));
|
||||
ui.PreRotateCButton->setIconSize(QSize(16, 16));
|
||||
ui.PreRotateCcButton->setIconSize(QSize(16, 16));
|
||||
ui.PreMoveUpButton->setIconSize(QSize(16, 16));
|
||||
ui.PreMoveDownButton->setIconSize(QSize(16, 16));
|
||||
ui.PreMoveLeftButton->setIconSize(QSize(16, 16));
|
||||
ui.PreMoveRightButton->setIconSize(QSize(16, 16));
|
||||
ui.PreScaleDownButton->setIconSize(QSize(16, 16));
|
||||
ui.PreScaleUpButton->setIconSize(QSize(16, 16));
|
||||
ui.PreResetButton->setIconSize(QSize(16, 16));
|
||||
ui.PreAffineGridLayout->setHorizontalSpacing(0);
|
||||
ui.PreAffineGridLayout->setVerticalSpacing(0);
|
||||
|
||||
ui.PostFlipHorizontalButton->setIconSize(QSize(16, 16));
|
||||
ui.PostFlipVerticalButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotate90CButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotate90CcButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotateCButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotateCcButton->setIconSize(QSize(16, 16));
|
||||
ui.PostMoveUpButton->setIconSize(QSize(16, 16));
|
||||
ui.PostMoveDownButton->setIconSize(QSize(16, 16));
|
||||
ui.PostMoveLeftButton->setIconSize(QSize(16, 16));
|
||||
ui.PostMoveRightButton->setIconSize(QSize(16, 16));
|
||||
ui.PostScaleDownButton->setIconSize(QSize(16, 16));
|
||||
ui.PostScaleUpButton->setIconSize(QSize(16, 16));
|
||||
ui.PostResetButton->setIconSize(QSize(16, 16));
|
||||
ui.PostAffineGridLayout->setHorizontalSpacing(0);
|
||||
ui.PostAffineGridLayout->setVerticalSpacing(0);
|
||||
|
||||
//Further, the size of the dock widget won't be properly adjusted until the xforms tab is shown.
|
||||
//So show it here and it will be switched back in Fractorium's constructor.
|
||||
ui.ParamsTabWidget->setCurrentIndex(2);
|
||||
ui.DockWidget->update();
|
||||
//For some reason linux makes these 24x24, even though the designer explicitly says 16x16.
|
||||
//Also, in order to get 4 pixels of spacing between elements in the grid layout, 0 must be specified.
|
||||
ui.PreFlipHorizontalButton->setIconSize(QSize(16, 16));
|
||||
ui.PreFlipVerticalButton->setIconSize(QSize(16, 16));
|
||||
ui.PreRotate90CButton->setIconSize(QSize(16, 16));
|
||||
ui.PreRotate90CcButton->setIconSize(QSize(16, 16));
|
||||
ui.PreRotateCButton->setIconSize(QSize(16, 16));
|
||||
ui.PreRotateCcButton->setIconSize(QSize(16, 16));
|
||||
ui.PreMoveUpButton->setIconSize(QSize(16, 16));
|
||||
ui.PreMoveDownButton->setIconSize(QSize(16, 16));
|
||||
ui.PreMoveLeftButton->setIconSize(QSize(16, 16));
|
||||
ui.PreMoveRightButton->setIconSize(QSize(16, 16));
|
||||
ui.PreScaleDownButton->setIconSize(QSize(16, 16));
|
||||
ui.PreScaleUpButton->setIconSize(QSize(16, 16));
|
||||
ui.PreResetButton->setIconSize(QSize(16, 16));
|
||||
ui.PreAffineGridLayout->setHorizontalSpacing(0);
|
||||
ui.PreAffineGridLayout->setVerticalSpacing(0);
|
||||
|
||||
ui.PostFlipHorizontalButton->setIconSize(QSize(16, 16));
|
||||
ui.PostFlipVerticalButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotate90CButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotate90CcButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotateCButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotateCcButton->setIconSize(QSize(16, 16));
|
||||
ui.PostMoveUpButton->setIconSize(QSize(16, 16));
|
||||
ui.PostMoveDownButton->setIconSize(QSize(16, 16));
|
||||
ui.PostMoveLeftButton->setIconSize(QSize(16, 16));
|
||||
ui.PostMoveRightButton->setIconSize(QSize(16, 16));
|
||||
ui.PostScaleDownButton->setIconSize(QSize(16, 16));
|
||||
ui.PostScaleUpButton->setIconSize(QSize(16, 16));
|
||||
ui.PostResetButton->setIconSize(QSize(16, 16));
|
||||
ui.PostAffineGridLayout->setHorizontalSpacing(0);
|
||||
ui.PostAffineGridLayout->setVerticalSpacing(0);
|
||||
|
||||
//Further, the size of the dock widget won't be properly adjusted until the xforms tab is shown.
|
||||
//So show it here and it will be switched back in Fractorium's constructor.
|
||||
ui.ParamsTabWidget->setCurrentIndex(2);
|
||||
ui.DockWidget->update();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//Placing pointers to the spin boxes in arrays makes them easier to access in various places.
|
||||
m_PreSpins[0] = m_PreX1Spin;//A
|
||||
m_PreSpins[1] = m_PreY1Spin;//B
|
||||
m_PreSpins[2] = m_PreO1Spin;//C
|
||||
m_PreSpins[3] = m_PreX2Spin;//D
|
||||
m_PreSpins[4] = m_PreY2Spin;//E
|
||||
m_PreSpins[5] = m_PreO2Spin;//F
|
||||
|
||||
m_PostSpins[0] = m_PostX1Spin;
|
||||
m_PostSpins[1] = m_PostY1Spin;
|
||||
m_PostSpins[2] = m_PostO1Spin;
|
||||
m_PostSpins[3] = m_PostX2Spin;
|
||||
m_PostSpins[4] = m_PostY2Spin;
|
||||
m_PostSpins[5] = m_PostO2Spin;
|
||||
|
||||
ui.PostAffineGroupBox->setChecked(true);//Flip it once to force the disabling of the group box.
|
||||
ui.PostAffineGroupBox->setChecked(false);
|
||||
}
|
||||
@ -155,32 +171,52 @@ void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
{
|
||||
QObject* objSender = m_Fractorium->sender();
|
||||
DoubleSpinBox* spinBox = dynamic_cast<DoubleSpinBox*>(objSender);
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
|
||||
if (spinBox)
|
||||
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
affine->A(spinBox->value());
|
||||
case 3:
|
||||
affine->A(cos(spinners[0]->value() * DEG_2_RAD) * spinners[3]->value());
|
||||
affine->D(sin(spinners[0]->value() * DEG_2_RAD) * spinners[3]->value());
|
||||
break;
|
||||
case 1:
|
||||
affine->B(spinBox->value());
|
||||
case 4:
|
||||
affine->B(cos(spinners[1]->value() * DEG_2_RAD) * spinners[4]->value());
|
||||
affine->E(sin(spinners[1]->value() * DEG_2_RAD) * spinners[4]->value());
|
||||
break;
|
||||
case 2:
|
||||
affine->C(spinBox->value());
|
||||
case 5:
|
||||
default:
|
||||
affine->C(cos(spinners[2]->value() * DEG_2_RAD) * spinners[5]->value());
|
||||
affine->F(sin(spinners[2]->value() * DEG_2_RAD) * spinners[5]->value());
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
affine->A(d);
|
||||
break;
|
||||
case 1:
|
||||
affine->B(d);
|
||||
break;
|
||||
case 2:
|
||||
affine->C(d);
|
||||
break;
|
||||
case 3:
|
||||
affine->D(spinBox->value());
|
||||
affine->D(d);
|
||||
break;
|
||||
case 4:
|
||||
affine->E(spinBox->value());
|
||||
affine->E(d);
|
||||
break;
|
||||
case 5:
|
||||
affine->F(spinBox->value());
|
||||
affine->F(d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -465,6 +501,16 @@ void FractoriumEmberController<T>::ResetCurrentXformAffine(bool pre)
|
||||
/// </summary>
|
||||
void Fractorium::OnResetAffineButtonClicked(bool checked) { m_Controller->ResetCurrentXformAffine(sender() == ui.PreResetButton); }
|
||||
|
||||
/// <summary>
|
||||
/// Fill the GUI with the pre and post affine xform values.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillBothAffines()
|
||||
{
|
||||
FillAffineWithXform(CurrentXform(), true);
|
||||
FillAffineWithXform(CurrentXform(), false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill the GUI with the pre/post affine xform values.
|
||||
/// </summary>
|
||||
@ -473,23 +519,26 @@ void Fractorium::OnResetAffineButtonClicked(bool checked) { m_Controller->ResetC
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillAffineWithXform(Xform<T>* xform, bool pre)
|
||||
{
|
||||
if (pre)
|
||||
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
const Affine2D<T>& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
|
||||
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
|
||||
{
|
||||
m_Fractorium->m_PreX1Spin->SetValueStealth(xform->m_Affine.A());
|
||||
m_Fractorium->m_PreY1Spin->SetValueStealth(xform->m_Affine.B());
|
||||
m_Fractorium->m_PreO1Spin->SetValueStealth(xform->m_Affine.C());
|
||||
m_Fractorium->m_PreX2Spin->SetValueStealth(xform->m_Affine.D());
|
||||
m_Fractorium->m_PreY2Spin->SetValueStealth(xform->m_Affine.E());
|
||||
m_Fractorium->m_PreO2Spin->SetValueStealth(xform->m_Affine.F());
|
||||
spinners[0]->SetValueStealth(RAD_2_DEG * atan2(affine.D(), affine.A()));
|
||||
spinners[1]->SetValueStealth(RAD_2_DEG * atan2(affine.E(), affine.B()));
|
||||
spinners[2]->SetValueStealth(RAD_2_DEG * atan2(affine.F(), affine.C()));
|
||||
spinners[3]->SetValueStealth(Hypot(affine.D(), affine.A()));
|
||||
spinners[4]->SetValueStealth(Hypot(affine.E(), affine.B()));
|
||||
spinners[5]->SetValueStealth(Hypot(affine.F(), affine.C()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Fractorium->m_PostX1Spin->SetValueStealth(xform->m_Post.A());
|
||||
m_Fractorium->m_PostY1Spin->SetValueStealth(xform->m_Post.B());
|
||||
m_Fractorium->m_PostO1Spin->SetValueStealth(xform->m_Post.C());
|
||||
m_Fractorium->m_PostX2Spin->SetValueStealth(xform->m_Post.D());
|
||||
m_Fractorium->m_PostY2Spin->SetValueStealth(xform->m_Post.E());
|
||||
m_Fractorium->m_PostO2Spin->SetValueStealth(xform->m_Post.F());
|
||||
spinners[0]->SetValueStealth(affine.A());
|
||||
spinners[1]->SetValueStealth(affine.B());
|
||||
spinners[2]->SetValueStealth(affine.C());
|
||||
spinners[3]->SetValueStealth(affine.D());
|
||||
spinners[4]->SetValueStealth(affine.E());
|
||||
spinners[5]->SetValueStealth(affine.F());
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,6 +565,31 @@ void Fractorium::OnAffineDrawAllCurrentRadioButtonToggled(bool checked)
|
||||
ui.GLDisplay->update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to display affine values in polar vs. rectangular coordinates.
|
||||
/// Updates the current affine display.
|
||||
/// </summary>
|
||||
/// <param name="state">The state of the checkbox</param>
|
||||
void Fractorium::OnPolarAffineCheckBoxStateChanged(int state)
|
||||
{
|
||||
double mult = state ? 100 : 0.01;
|
||||
double step = m_PreX1Spin->Step() * mult;
|
||||
double small = m_PreX1Spin->SmallStep() * mult;
|
||||
double click = state ? 90 : 1;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
m_PreSpins[i]->Step(step);
|
||||
m_PreSpins[i]->SmallStep(small);
|
||||
m_PostSpins[i]->Step(step);
|
||||
m_PostSpins[i]->SmallStep(small);
|
||||
m_PreSpins[i]->DoubleClickZero(click);
|
||||
m_PostSpins[i]->DoubleClickZero(click);
|
||||
}
|
||||
|
||||
m_Controller->FillBothAffines();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup a spinner to be placed in a table cell.
|
||||
/// Special setup function for affine spinners which differs slightly from the regular
|
||||
|
Loading…
Reference in New Issue
Block a user