mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-02-01 10:30:08 -05:00
--User changes
Add the ability to apply operations to a selection of xforms, rather than just the current one. Update tool tips accordingly. --Bug fixes Fix NAN in equalized weight calculation when all weights are set to 0. --Code changes Clean up strange nested usage of Update([&]()) calls when changing xform color index via either the spinner or scroll bar. Made no sense. Make ISAAC RandBit() use RandByte() to be slightly more efficient. Put FillXforms() in the controller where it belongs, rather than the main window class. Add UpdateXform() function to the controller to handle applying operations to multiple xforms. Remove the word "Current" out of most xform related functions because they now operate on whatever is selected. Properly use Update() for various xform operations whereas before it was manually calling UpdateRender(). Also properly use Update() in places where it was erroneously using UpdateXform() for things that did not involve xforms. Block signals in FillXaosTable(). Add new file named FractoriumXformsSelect.cpp to handle new xform selection code.
This commit is contained in:
parent
e8bbfdd2d4
commit
be8e9a5e02
@ -326,6 +326,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"</
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\FractoriumXforms.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\FractoriumXformsAffine.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\FractoriumXformsColor.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\FractoriumXformsSelect.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\FractoriumXformsVariations.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\FractoriumXaos.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\GLEmberController.cpp" />
|
||||
|
@ -244,6 +244,9 @@
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\FractoriumXaos.cpp">
|
||||
<Filter>MainWindows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\Source\Fractorium\FractoriumXformsSelect.cpp">
|
||||
<Filter>MainWindows</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="GeneratedFiles\ui_Fractorium.h">
|
||||
|
@ -621,7 +621,7 @@ public:
|
||||
normalizedWeights.resize(m_Xforms.size());
|
||||
|
||||
ForEach(m_Xforms, [&](Xform<T>& xform) { norm += xform.m_Weight; });
|
||||
ForEach(normalizedWeights, [&](T& weight) { weight = m_Xforms[i].m_Weight / norm; i++; });
|
||||
ForEach(normalizedWeights, [&](T& weight) { weight = (norm == T(0) ? T(0) : m_Xforms[i].m_Weight / norm); i++; });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -199,7 +199,7 @@ public:
|
||||
/// <returns>A random 0 or 1</returns>
|
||||
inline uint RandBit()
|
||||
{
|
||||
return Rand() & 1;
|
||||
return RandByte() & 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -76,7 +76,8 @@ Fractorium::Fractorium(QWidget* p)
|
||||
InitXformsColorUI();
|
||||
InitXformsAffineUI();
|
||||
InitXformsVariationsUI();
|
||||
InitXformsXaosUI();
|
||||
InitXformsSelectUI();
|
||||
InitXaosUI();
|
||||
InitPaletteUI();
|
||||
InitLibraryUI();
|
||||
InitMenusUI();
|
||||
|
@ -241,7 +241,11 @@ public slots:
|
||||
void OnVariationsFilterLineEditTextChanged(const QString& text);
|
||||
void OnVariationsFilterClearButtonClicked(bool checked);
|
||||
|
||||
//Xforms Xaos.
|
||||
//Xforms Selection.
|
||||
void OnXformsSelectAllButtonClicked(bool checked);
|
||||
void OnXformsSelectNoneButtonClicked(bool checked);
|
||||
|
||||
//Xaos.
|
||||
void OnXaosChanged(double d);
|
||||
void OnClearXaosButtonClicked(bool checked);
|
||||
void OnRandomXaosButtonClicked(bool checked);
|
||||
@ -287,7 +291,8 @@ private:
|
||||
void InitXformsColorUI();
|
||||
void InitXformsAffineUI();
|
||||
void InitXformsVariationsUI();
|
||||
void InitXformsXaosUI();
|
||||
void InitXformsSelectUI();
|
||||
void InitXaosUI();
|
||||
void InitPaletteUI();
|
||||
void InitLibraryUI();
|
||||
void SetTabOrders();
|
||||
@ -301,7 +306,6 @@ private:
|
||||
//Params.
|
||||
|
||||
//Xforms.
|
||||
void FillXforms();
|
||||
|
||||
//Xforms Color.
|
||||
|
||||
@ -309,7 +313,11 @@ private:
|
||||
|
||||
//Xforms Variations.
|
||||
|
||||
//Xforms Xaos.
|
||||
//Xforms Selection.
|
||||
void ClearXformsSelections();
|
||||
void ForEachXformCheckbox(std::function<void(int, QCheckBox*)> func);
|
||||
|
||||
//Xaos.
|
||||
void FillXaosTable();
|
||||
|
||||
//Palette.
|
||||
@ -371,6 +379,8 @@ private:
|
||||
//Xforms.
|
||||
DoubleSpinBox* m_XformWeightSpin;
|
||||
SpinnerButtonWidget* m_XformWeightSpinnerButtonWidget;
|
||||
QFormLayout* m_XformsSelectionLayout;
|
||||
QVector<QCheckBox*> m_XformSelections;
|
||||
|
||||
//Xforms Color.
|
||||
QTableWidgetItem* m_XformColorValueItem;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -224,21 +224,79 @@ void FractoriumEmberController<T>::Update(std::function<void (void)> func, bool
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper to call a function on the current xform, then optionally add the requested action to the rendering queue.
|
||||
/// Wrapper to call a function on the specified xforms, then optionally add the requested action to the rendering queue.
|
||||
/// If no xforms are selected via the checkboxes, and the update type is UPDATE_SELECTED, then the function will be called only on the currently selected xform.
|
||||
/// </summary>
|
||||
/// <param name="func">The function to call</param>
|
||||
/// <param name="updateType">Whether to apply this update operation on the current, all or selected xforms. Default: UPDATE_CURRENT.</param>
|
||||
/// <param name="updateRender">True to update renderer, else false. Default: true.</param>
|
||||
/// <param name="action">The action to add to the rendering queue. Default: FULL_RENDER.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::UpdateCurrentXform(std::function<void (Xform<T>*)> func, bool updateRender, eProcessAction action)
|
||||
void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType, bool updateRender, eProcessAction action)
|
||||
{
|
||||
if (Xform<T>* xform = CurrentXform())
|
||||
{
|
||||
func(xform);
|
||||
size_t i = 0;
|
||||
bool isCurrentFinal = m_Ember.IsFinalXform(CurrentXform());
|
||||
bool doFinal = updateType != eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL && updateType != eXformUpdate::UPDATE_ALL_EXCEPT_FINAL;
|
||||
|
||||
if (updateRender)
|
||||
UpdateRender(action);
|
||||
switch (updateType)
|
||||
{
|
||||
case eXformUpdate::UPDATE_CURRENT:
|
||||
{
|
||||
if (Xform<T>* xform = CurrentXform())
|
||||
func(xform);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_SELECTED:
|
||||
case eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL:
|
||||
{
|
||||
bool anyUpdated = false;
|
||||
|
||||
while (Xform<T>* xform = (doFinal ? m_Ember.GetTotalXform(i) : m_Ember.GetXform(i)))
|
||||
{
|
||||
if (QLayoutItem* child = m_Fractorium->m_XformsSelectionLayout->itemAt(i))
|
||||
{
|
||||
if (auto* w = dynamic_cast<QCheckBox*>(child->widget()))
|
||||
{
|
||||
if (w->isChecked())
|
||||
{
|
||||
func(xform);
|
||||
anyUpdated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!anyUpdated)//None were selected, so just apply to the current.
|
||||
if (doFinal || !isCurrentFinal)//If do final, call func regardless. If not, only call if current is not final.
|
||||
if (Xform<T>* xform = CurrentXform())
|
||||
func(xform);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_ALL:
|
||||
{
|
||||
while (Xform<T>* xform = m_Ember.GetTotalXform(i++))
|
||||
func(xform);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_ALL_EXCEPT_FINAL:
|
||||
default:
|
||||
{
|
||||
while (Xform<T>* xform = m_Ember.GetXform(i++))
|
||||
func(xform);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (updateRender)
|
||||
UpdateRender(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -276,7 +334,7 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
|
||||
#endif
|
||||
|
||||
m_GLController->ResetMouseState();
|
||||
m_Fractorium->FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo.
|
||||
FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo.
|
||||
FillParamTablesAndPalette();
|
||||
|
||||
//If a resize happened, this won't do anything because the new size is not reflected in the scroll area yet.
|
||||
|
@ -11,7 +11,12 @@
|
||||
/// <summary>
|
||||
/// An enum representing the type of edit being done.
|
||||
/// </summary>
|
||||
enum eEditUndoState : uint { REGULAR_EDIT = 0, UNDO_REDO = 1, EDIT_UNDO = 2 };
|
||||
enum eEditUndoState : uint { REGULAR_EDIT, UNDO_REDO, EDIT_UNDO };
|
||||
|
||||
/// <summary>
|
||||
/// An enum representing which xforms an update should be applied to.
|
||||
/// </summary>
|
||||
enum eXformUpdate : uint { UPDATE_CURRENT, UPDATE_SELECTED, UPDATE_SELECTED_EXCEPT_FINAL, UPDATE_ALL, UPDATE_ALL_EXCEPT_FINAL };
|
||||
|
||||
/// <summary>
|
||||
/// FractoriumEmberController and Fractorium need each other, but each can't include the other.
|
||||
@ -58,8 +63,8 @@ public:
|
||||
//virtual void Clear() { }
|
||||
virtual void AddXform() { }
|
||||
virtual void DuplicateXform() { }
|
||||
virtual void ClearCurrentXform() { }
|
||||
virtual void DeleteCurrentXform() { }
|
||||
virtual void ClearXform() { }
|
||||
virtual void DeleteXforms() { }
|
||||
virtual void AddFinalXform() { }
|
||||
virtual bool UseFinalXform() { return false; }
|
||||
virtual size_t XformCount() const { return 0; }
|
||||
@ -145,20 +150,23 @@ public:
|
||||
virtual void AffineInterpTypeChanged(int i) { }
|
||||
virtual void InterpTypeChanged(int i) { }
|
||||
virtual void BackgroundChanged(const QColor& color) { }
|
||||
|
||||
virtual void ClearColorCurves() { }
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) { }
|
||||
|
||||
//Xforms.
|
||||
virtual void CurrentXformComboChanged(int index) { }
|
||||
virtual void XformWeightChanged(double d) { }
|
||||
virtual void EqualizeWeights() { }
|
||||
virtual void XformNameChanged(int row, int col) { }
|
||||
virtual void FillXforms() { }
|
||||
|
||||
//Xforms Affine.
|
||||
virtual void AffineSetHelper(double d, int index, bool pre) { }
|
||||
virtual void FlipCurrentXform(bool horizontal, bool vertical, bool pre) { }
|
||||
virtual void RotateCurrentXformByAngle(double angle, bool pre) { }
|
||||
virtual void MoveCurrentXform(double x, double y, bool pre) { }
|
||||
virtual void ScaleCurrentXform(double scale, bool pre) { }
|
||||
virtual void ResetCurrentXformAffine(bool pre) { }
|
||||
virtual void FlipXforms(bool horizontal, bool vertical, bool pre) { }
|
||||
virtual void RotateXformsByAngle(double angle, bool pre) { }
|
||||
virtual void MoveXforms(double x, double y, bool pre) { }
|
||||
virtual void ScaleXforms(double scale, bool pre) { }
|
||||
virtual void ResetXformsAffine(bool pre) { }
|
||||
virtual void FillBothAffines() { }
|
||||
|
||||
//Xforms Color.
|
||||
@ -167,8 +175,6 @@ public:
|
||||
virtual void XformColorSpeedChanged(double d) { }
|
||||
virtual void XformOpacityChanged(double d) { }
|
||||
virtual void XformDirectColorChanged(double d) { }
|
||||
virtual void ClearColorCurves() { }
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) { }//need to put this in a different section because it's not xform specific.//TODO
|
||||
void SetPaletteRefTable(QPixmap* pixmap);
|
||||
|
||||
//Xforms Variations.
|
||||
@ -176,7 +182,9 @@ public:
|
||||
virtual void ClearVariationsTree() { }
|
||||
virtual void VariationSpinBoxValueChanged(double d) { }
|
||||
|
||||
//Xforms Xaos.
|
||||
//Xforms Selection.
|
||||
|
||||
//Xaos.
|
||||
virtual void FillXaos() { }
|
||||
virtual QString MakeXaosNameString(uint i) { return ""; }
|
||||
virtual void XaosChanged(DoubleSpinBox* sender) { }
|
||||
@ -281,8 +289,8 @@ public:
|
||||
//virtual void Clear() override { }
|
||||
virtual void AddXform() override;
|
||||
virtual void DuplicateXform() override;
|
||||
virtual void ClearCurrentXform() override;
|
||||
virtual void DeleteCurrentXform() override;
|
||||
virtual void ClearXform() override;
|
||||
virtual void DeleteXforms() override;
|
||||
virtual void AddFinalXform() override;
|
||||
virtual bool UseFinalXform() override { return m_Ember.UseFinalXform(); }
|
||||
//virtual bool IsFinal(uint i) { return false; }
|
||||
@ -371,22 +379,25 @@ public:
|
||||
virtual void AffineInterpTypeChanged(int index) override;
|
||||
virtual void InterpTypeChanged(int index) override;
|
||||
virtual void BackgroundChanged(const QColor& col) override;
|
||||
virtual void ClearColorCurves() override;
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) override;
|
||||
|
||||
//Xforms.
|
||||
virtual void CurrentXformComboChanged(int index) override;
|
||||
virtual void XformWeightChanged(double d) override;
|
||||
virtual void EqualizeWeights() override;
|
||||
virtual void XformNameChanged(int row, int col) override;
|
||||
virtual void FillXforms() override;
|
||||
void FillWithXform(Xform<T>* xform);
|
||||
Xform<T>* CurrentXform();
|
||||
|
||||
//Xforms Affine.
|
||||
virtual void AffineSetHelper(double d, int index, bool pre) override;
|
||||
virtual void FlipCurrentXform(bool horizontal, bool vertical, bool pre) override;
|
||||
virtual void RotateCurrentXformByAngle(double angle, bool pre) override;
|
||||
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 FlipXforms(bool horizontal, bool vertical, bool pre) override;
|
||||
virtual void RotateXformsByAngle(double angle, bool pre) override;
|
||||
virtual void MoveXforms(double x, double y, bool pre) override;
|
||||
virtual void ScaleXforms(double scale, bool pre) override;
|
||||
virtual void ResetXformsAffine(bool pre) override;
|
||||
virtual void FillBothAffines() override;
|
||||
void FillAffineWithXform(Xform<T>* xform, bool pre);
|
||||
|
||||
@ -396,8 +407,6 @@ public:
|
||||
virtual void XformColorSpeedChanged(double d) override;
|
||||
virtual void XformOpacityChanged(double d) override;
|
||||
virtual void XformDirectColorChanged(double d) override;
|
||||
virtual void ClearColorCurves() override;
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) override;
|
||||
void FillColorWithXform(Xform<T>* xform);
|
||||
|
||||
//Xforms Variations.
|
||||
@ -444,15 +453,20 @@ private:
|
||||
bool IsFinal(Xform<T>* xform);
|
||||
|
||||
//Xforms Color.
|
||||
void SetCurrentXformColorIndex(double d);
|
||||
void SetCurrentXformColorIndex(double d, bool updateRender);
|
||||
void FillCurvesControl();
|
||||
|
||||
//Xforms Selection.
|
||||
QString MakeXformCaption(size_t i);
|
||||
bool XformCheckboxAt(int i, std::function<void(QCheckBox*)> func);
|
||||
bool XformCheckboxAt(Xform<T>* xform, std::function<void(QCheckBox*)> func);
|
||||
void UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = FULL_RENDER);
|
||||
|
||||
//Palette.
|
||||
void UpdateAdjustedPaletteGUI(Palette<T>& palette);
|
||||
|
||||
//Rendering/progress.
|
||||
void Update(std::function<void (void)> func, bool updateRender = true, eProcessAction action = FULL_RENDER);
|
||||
void UpdateCurrentXform(std::function<void (Xform<T>*)> func, bool updateRender = true, eProcessAction action = FULL_RENDER);
|
||||
bool SyncSizes();
|
||||
|
||||
//Templated members.
|
||||
|
@ -618,10 +618,12 @@ void FractoriumEmberController<T>::AddReflectiveSymmetry()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
m_Ember.AddSymmetry(-1, m_Rand);
|
||||
m_Fractorium->FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
UpdateRender();
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(-1, m_Rand);
|
||||
FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
});
|
||||
}
|
||||
|
||||
void Fractorium::OnActionAddReflectiveSymmetry(bool checked) { m_Controller->AddReflectiveSymmetry(); }
|
||||
@ -635,10 +637,12 @@ void FractoriumEmberController<T>::AddRotationalSymmetry()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
m_Ember.AddSymmetry(2, m_Rand);
|
||||
m_Fractorium->FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
UpdateRender();
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(2, m_Rand);
|
||||
FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
});
|
||||
}
|
||||
|
||||
void Fractorium::OnActionAddRotationalSymmetry(bool checked) { m_Controller->AddRotationalSymmetry(); }
|
||||
@ -652,10 +656,12 @@ void FractoriumEmberController<T>::AddBothSymmetry()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
m_Ember.AddSymmetry(-2, m_Rand);
|
||||
m_Fractorium->FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
UpdateRender();
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(-2, m_Rand);
|
||||
FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
});
|
||||
}
|
||||
|
||||
void Fractorium::OnActionAddBothSymmetry(bool checked) { m_Controller->AddBothSymmetry(); }
|
||||
@ -665,7 +671,7 @@ void Fractorium::OnActionAddBothSymmetry(bool checked) { m_Controller->AddBothSy
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::Flatten() { UpdateCurrentXform([&] (Xform<T>* xform) { m_Ember.Flatten(XmlToEmber<T>::m_FlattenNames); FillVariationTreeWithXform(xform); }); }
|
||||
void FractoriumEmberController<T>::Flatten() { UpdateXform([&] (Xform<T>* xform) { m_Ember.Flatten(XmlToEmber<T>::m_FlattenNames); FillVariationTreeWithXform(xform); }); }
|
||||
void Fractorium::OnActionFlatten(bool checked) { m_Controller->Flatten(); }
|
||||
|
||||
/// <summary>
|
||||
@ -673,7 +679,7 @@ void Fractorium::OnActionFlatten(bool checked) { m_Controller->Flatten(); }
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::Unflatten() { UpdateCurrentXform([&] (Xform<T>* xform) { m_Ember.Unflatten(); FillVariationTreeWithXform(xform); }); }
|
||||
void FractoriumEmberController<T>::Unflatten() { UpdateXform([&] (Xform<T>* xform) { m_Ember.Unflatten(); FillVariationTreeWithXform(xform); }); }
|
||||
void Fractorium::OnActionUnflatten(bool checked) { m_Controller->Unflatten(); }
|
||||
|
||||
/// <summary>
|
||||
@ -684,21 +690,23 @@ void Fractorium::OnActionUnflatten(bool checked) { m_Controller->Unflatten(); }
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ClearFlame()
|
||||
{
|
||||
while (m_Ember.TotalXformCount() > 1)
|
||||
m_Ember.DeleteTotalXform(m_Ember.TotalXformCount() - 1);
|
||||
|
||||
if (m_Ember.XformCount() == 1)
|
||||
Update([&]()
|
||||
{
|
||||
if (Xform<T>* xform = m_Ember.GetXform(0))
|
||||
{
|
||||
xform->Clear();
|
||||
xform->ParentEmber(&m_Ember);
|
||||
}
|
||||
}
|
||||
while (m_Ember.TotalXformCount() > 1)
|
||||
m_Ember.DeleteTotalXform(m_Ember.TotalXformCount() - 1);
|
||||
|
||||
m_Fractorium->FillXforms();
|
||||
m_Fractorium->ui.CurrentXformCombo->setCurrentIndex(0);
|
||||
UpdateRender();
|
||||
if (m_Ember.XformCount() == 1)
|
||||
{
|
||||
if (Xform<T>* xform = m_Ember.GetXform(0))
|
||||
{
|
||||
xform->Clear();
|
||||
xform->ParentEmber(&m_Ember);
|
||||
}
|
||||
}
|
||||
|
||||
FillXforms();
|
||||
m_Fractorium->ui.CurrentXformCombo->setCurrentIndex(0);
|
||||
});
|
||||
}
|
||||
|
||||
void Fractorium::OnActionClearFlame(bool checked) { m_Controller->ClearFlame(); }
|
||||
|
@ -202,7 +202,7 @@ void FractoriumEmberController<T>::UpdateAdjustedPaletteGUI(Palette<T>& palette)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::PaletteAdjust()
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
Update([&]()
|
||||
{
|
||||
ApplyPaletteToEmber();
|
||||
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);
|
||||
|
@ -4,7 +4,7 @@
|
||||
/// <summary>
|
||||
/// Initialize the xforms xaos UI.
|
||||
/// </summary>
|
||||
void Fractorium::InitXformsXaosUI()
|
||||
void Fractorium::InitXaosUI()
|
||||
{
|
||||
connect(ui.ClearXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnClearXaosButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.RandomXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomXaosButtonClicked(bool)), Qt::QueuedConnection);
|
||||
@ -88,6 +88,7 @@ void Fractorium::FillXaosTable()
|
||||
QWidget* w = nullptr;
|
||||
QString lbl("lbl");
|
||||
|
||||
ui.XaosTable->blockSignals(true);
|
||||
ui.XaosTable->setRowCount(count);//This will grow or shrink the number of rows and call the destructor for previous DoubleSpinBoxes.
|
||||
ui.XaosTable->setColumnCount(count);
|
||||
|
||||
@ -137,6 +138,7 @@ void Fractorium::FillXaosTable()
|
||||
|
||||
w = SetTabOrder(this, w, ui.ClearXaosButton);
|
||||
w = SetTabOrder(this, w, ui.RandomXaosButton);
|
||||
ui.XaosTable->blockSignals(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -30,7 +30,7 @@ void Fractorium::InitXformsUI()
|
||||
connect(ui.XformWeightNameTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnXformNameChanged(int, int)), Qt::QueuedConnection);
|
||||
|
||||
ui.CurrentXformCombo->setProperty("soloxform", -1);
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
//For some reason linux makes these 24x24, even though the designer explicitly says 16x16.
|
||||
ui.AddXformButton->setIconSize(QSize(16, 16));
|
||||
@ -101,7 +101,7 @@ void Fractorium::OnCurrentXformComboChanged(int index) { m_Controller->CurrentXf
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddXform()
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
Update([&]()
|
||||
{
|
||||
Xform<T> newXform;
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
@ -109,7 +109,7 @@ void FractoriumEmberController<T>::AddXform()
|
||||
newXform.m_Weight = 0.25;
|
||||
newXform.m_ColorX = m_Rand.Frand01<T>();
|
||||
m_Ember.AddXform(newXform);
|
||||
m_Fractorium->FillXforms();
|
||||
FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
});
|
||||
}
|
||||
@ -117,7 +117,7 @@ void FractoriumEmberController<T>::AddXform()
|
||||
void Fractorium::OnAddXformButtonClicked(bool checked) { m_Controller->AddXform(); }
|
||||
|
||||
/// <summary>
|
||||
/// Duplicate the current xform in the current ember, and set it as the current xform.
|
||||
/// Duplicate the specified xforms in the current ember, and set the last one as the current xform.
|
||||
/// Called when the duplicate xform button is clicked.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
@ -125,71 +125,112 @@ void Fractorium::OnAddXformButtonClicked(bool checked) { m_Controller->AddXform(
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::DuplicateXform()
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
vector<Xform<T>> vec;
|
||||
|
||||
vec.reserve(m_Ember.XformCount());
|
||||
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
vec.push_back(*xform);
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL, false);
|
||||
|
||||
Update([&]()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
if (xform && !IsFinal(xform))
|
||||
{
|
||||
m_Ember.AddXform(*xform);
|
||||
m_Fractorium->FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
}
|
||||
for (auto& it : vec)
|
||||
m_Ember.AddXform(it);
|
||||
|
||||
FillXforms();//Handles xaos.
|
||||
combo->setCurrentIndex(combo->count() - (m_Fractorium->HaveFinal() ? 2 : 1));//Set index to the last item before final.
|
||||
});
|
||||
}
|
||||
|
||||
void Fractorium::OnDuplicateXformButtonClicked(bool checked) { m_Controller->DuplicateXform(); }
|
||||
|
||||
/// <summary>
|
||||
/// Clear all variations from the current xform, affine, palette and xaos are left untouched.
|
||||
/// Clear all variations from the selected xforms. Affine, palette and xaos are left untouched.
|
||||
/// Called when the clear xform button is clicked.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="checked">Ignored</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ClearCurrentXform()
|
||||
void FractoriumEmberController<T>::ClearXform()
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
xform->ClearAndDeleteVariations();
|
||||
//Note xaos is left alone.
|
||||
FillVariationTreeWithXform(xform);
|
||||
});
|
||||
xform->ClearAndDeleteVariations();//Note xaos is left alone.
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillVariationTreeWithXform(CurrentXform());
|
||||
}
|
||||
|
||||
void Fractorium::OnClearXformButtonClicked(bool checked) { m_Controller->ClearCurrentXform(); }
|
||||
void Fractorium::OnClearXformButtonClicked(bool checked) { m_Controller->ClearXform(); }
|
||||
|
||||
/// <summary>
|
||||
/// Delete the current xform.
|
||||
/// Delete the selected xforms.
|
||||
/// Will not delete the last remaining non-final xform.
|
||||
/// Called when the delete xform button is clicked.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="checked">Ignored</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::DeleteCurrentXform()
|
||||
void FractoriumEmberController<T>::DeleteXforms()
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
int i = 0, offset = 0, current = 0, checked = 0;
|
||||
bool haveFinal = false;
|
||||
size_t count;
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
//Iterating over the checkboxes must be done instead of using UpdateXform() to iterate over xforms
|
||||
//because xforms are being deleted inside the loop.
|
||||
//Also manually calling UpdateRender() rather than using the usual Update() call because
|
||||
//it should only be called if an xform has actually been deleted.
|
||||
m_Fractorium->ForEachXformCheckbox([&](int i, QCheckBox* w)
|
||||
{
|
||||
bool haveFinal = m_Fractorium->HaveFinal();
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
int count = combo->count();
|
||||
int index = combo->currentIndex();
|
||||
count = m_Ember.TotalXformCount();
|
||||
haveFinal = m_Ember.UseFinalXform();//Requery every time.
|
||||
|
||||
if (w->isChecked())
|
||||
checked++;
|
||||
|
||||
//Do not allow deleting the only remaining non-final xform.
|
||||
if (haveFinal && count <= 2 && index == 0)
|
||||
if (haveFinal && count <= 2 && i == 0)
|
||||
return;
|
||||
|
||||
if (!haveFinal && count == 1)
|
||||
return;
|
||||
|
||||
m_Ember.DeleteTotalXform(index);
|
||||
m_Fractorium->FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (haveFinal ? 2 : 1));//Set index to the last item before final.
|
||||
if (w->isChecked())
|
||||
{
|
||||
//qDebug() << "Deleting " << w->text();
|
||||
m_Ember.DeleteTotalXform(i - offset);//Subtract offset to account for previously deleted xforms.
|
||||
offset++;
|
||||
}
|
||||
});
|
||||
|
||||
current = combo->currentIndex();
|
||||
count = m_Ember.TotalXformCount();
|
||||
haveFinal = m_Ember.UseFinalXform();//Requery again.
|
||||
|
||||
//Nothing was selected, so just delete current.
|
||||
if (!checked &&
|
||||
!(haveFinal && count <= 2 && current == 0) &&//Again disallow deleting the only remaining non-final xform.
|
||||
!(!haveFinal && count == 1))
|
||||
{
|
||||
m_Ember.DeleteTotalXform(current);
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (offset)
|
||||
{
|
||||
FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - (m_Ember.UseFinalXform() ? 2 : 1));//Set index to the last item before final. Note final is requeried one last time.
|
||||
UpdateRender();
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnDeleteXformButtonClicked(bool checked) { m_Controller->DeleteCurrentXform(); }
|
||||
void Fractorium::OnDeleteXformButtonClicked(bool checked) { m_Controller->DeleteXforms(); }
|
||||
|
||||
/// <summary>
|
||||
/// Add a final xform to the ember and set it as the current xform.
|
||||
@ -201,26 +242,26 @@ void Fractorium::OnDeleteXformButtonClicked(bool checked) { m_Controller->Delete
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddFinalXform()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
//Check to see if a final xform is already present.
|
||||
if (!m_Fractorium->HaveFinal())
|
||||
{
|
||||
Xform<T> xform;
|
||||
Update([&]()
|
||||
{
|
||||
Xform<T> final;
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
xform.AddVariation(new LinearVariation<T>());//Just a placeholder so other parts of the code don't see it as being empty.
|
||||
m_Ember.SetFinalXform(xform);
|
||||
combo->addItem("Final");
|
||||
combo->setItemIcon(combo->count() - 1, m_Fractorium->m_FinalXformComboIcon);
|
||||
combo->setCurrentIndex(combo->count() - 1);//Set index to the last item.
|
||||
UpdateRender();
|
||||
final.AddVariation(new LinearVariation<T>());//Just a placeholder so other parts of the code don't see it as being empty.
|
||||
m_Ember.SetFinalXform(final);
|
||||
FillXforms();
|
||||
combo->setCurrentIndex(combo->count() - 1);//Set index to the last item.
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnAddFinalXformButtonClicked(bool checked) { m_Controller->AddFinalXform(); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the weight of the current xform.
|
||||
/// Set the weight of the selected xforms.
|
||||
/// Called when weight spinner changes.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
@ -228,11 +269,12 @@ void Fractorium::OnAddFinalXformButtonClicked(bool checked) { m_Controller->AddF
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformWeightChanged(double d)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
xform->m_Weight = d;
|
||||
SetNormalizedWeightText(xform);
|
||||
});
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL);
|
||||
|
||||
SetNormalizedWeightText(CurrentXform());
|
||||
}
|
||||
|
||||
void Fractorium::OnXformWeightChanged(double d) { m_Controller->XformWeightChanged(d); }
|
||||
@ -243,17 +285,18 @@ void Fractorium::OnXformWeightChanged(double d) { m_Controller->XformWeightChang
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::EqualizeWeights()
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
m_Ember.EqualizeWeights();
|
||||
m_Fractorium->m_XformWeightSpin->setValue(xform->m_Weight);//Will trigger an update, so pass false to updateRender below.
|
||||
}, false);
|
||||
}, eXformUpdate::UPDATE_CURRENT, false);
|
||||
}
|
||||
|
||||
void Fractorium::OnEqualWeightButtonClicked(bool checked) { m_Controller->EqualizeWeights(); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the current xform.
|
||||
/// Update the corresponding xform checkbox text with the name.
|
||||
/// Called when the user types in the name cell of the table.
|
||||
/// </summary>
|
||||
/// <param name="row">The row of the cell</param>
|
||||
@ -261,18 +304,18 @@ void Fractorium::OnEqualWeightButtonClicked(bool checked) { m_Controller->Equali
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformNameChanged(int row, int col)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
int index = m_Ember.GetXformIndex(xform);
|
||||
int index = m_Ember.GetTotalXformIndex(xform);
|
||||
|
||||
xform->m_Name = m_Fractorium->ui.XformWeightNameTable->item(row, col)->text().toStdString();
|
||||
|
||||
XformCheckboxAt(index, [&](QCheckBox* checkbox) { checkbox->setText(MakeXformCaption(index)); });
|
||||
//if (index != -1)
|
||||
//{
|
||||
// if (QTableWidgetItem* xformNameItem = m_Fractorium->ui.XaosTable->item(index, 0))
|
||||
// xformNameItem->setText(MakeXaosNameString(index));
|
||||
//}
|
||||
}, false);
|
||||
}, eXformUpdate::UPDATE_CURRENT, false);
|
||||
}
|
||||
|
||||
void Fractorium::OnXformNameChanged(int row, int col) { m_Controller->XformNameChanged(row, col); }
|
||||
@ -282,7 +325,7 @@ void Fractorium::OnXformNameChanged(int row, int col) { m_Controller->XformNameC
|
||||
/// </summary>
|
||||
/// <param name="xform">The xform whose values will be used to populate the widgets</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillWithXform(Xform<T>* xform)
|
||||
void FractoriumEmberController<T>::FillWithXform(Xform<T>* xform)//Need to see where all this is called from and sync with FillXform(). Maybe rename the latter.
|
||||
{
|
||||
m_Fractorium->m_XformWeightSpin->SetValueStealth(xform->m_Weight);
|
||||
SetNormalizedWeightText(xform);
|
||||
@ -332,32 +375,71 @@ bool FractoriumEmberController<T>::IsFinal(Xform<T>* xform)
|
||||
/// <summary>
|
||||
/// Fill the xforms combo box with the xforms in the current ember.
|
||||
/// Select the first one and fill all widgets with its values.
|
||||
/// Also dynamically generate a checkbox for each xform which will allow the user
|
||||
/// to select which xforms to apply operations to.
|
||||
/// </summary>
|
||||
void Fractorium::FillXforms()
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillXforms()
|
||||
{
|
||||
int i = 0, spinHeight = 20;
|
||||
QComboBox* combo = ui.CurrentXformCombo;
|
||||
int i = 0, count = int(XformCount());
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
combo->blockSignals(true);
|
||||
combo->clear();
|
||||
|
||||
for (i = 0; i < int(m_Controller->XformCount()); i++)
|
||||
//First clear all dynamically created checkboxes.
|
||||
m_Fractorium->ClearXformsSelections();
|
||||
m_Fractorium->m_XformsSelectionLayout->blockSignals(true);
|
||||
|
||||
//Fill combo box and create new checkboxes.
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
combo->addItem(ToString(i + 1));
|
||||
combo->setItemIcon(i, m_XformComboIcons[i % XFORM_COLOR_COUNT]);
|
||||
combo->setItemIcon(i, m_Fractorium->m_XformComboIcons[i % XFORM_COLOR_COUNT]);
|
||||
}
|
||||
|
||||
if (m_Controller->UseFinalXform())
|
||||
i = 0;
|
||||
while (i < count)
|
||||
{
|
||||
combo->addItem("Final");
|
||||
combo->setItemIcon(i, m_FinalXformComboIcon);
|
||||
if (i < count - 1)
|
||||
{
|
||||
auto cb1 = new QCheckBox(MakeXformCaption(i), m_Fractorium);
|
||||
auto cb2 = new QCheckBox(MakeXformCaption(i + 1), m_Fractorium);
|
||||
|
||||
m_Fractorium->m_XformSelections.push_back(cb1);
|
||||
m_Fractorium->m_XformSelections.push_back(cb2);
|
||||
m_Fractorium->m_XformsSelectionLayout->addRow(cb1, cb2);
|
||||
i += 2;
|
||||
}
|
||||
else if (i < count)
|
||||
{
|
||||
auto cb = new QCheckBox(MakeXformCaption(i), m_Fractorium);
|
||||
|
||||
m_Fractorium->m_XformSelections.push_back(cb);
|
||||
m_Fractorium->m_XformsSelectionLayout->addRow(cb, new QWidget(m_Fractorium));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Special case for final xform.
|
||||
if (UseFinalXform())
|
||||
{
|
||||
auto cb = new QCheckBox(MakeXformCaption(i), m_Fractorium);
|
||||
|
||||
m_Fractorium->m_XformSelections.push_back(cb);
|
||||
m_Fractorium->m_XformsSelectionLayout->addRow(cb, new QWidget(m_Fractorium));
|
||||
|
||||
combo->addItem("Final");
|
||||
combo->setItemIcon(i, m_Fractorium->m_FinalXformComboIcon);
|
||||
}
|
||||
|
||||
m_Fractorium->m_XformsSelectionLayout->blockSignals(false);
|
||||
combo->blockSignals(false);
|
||||
combo->setCurrentIndex(0);
|
||||
FillXaosTable();
|
||||
OnSoloXformCheckBoxStateChanged(Qt::Unchecked);
|
||||
OnCurrentXformComboChanged(0);//Make sure the event gets called, because it won't if the zero index is already selected.
|
||||
|
||||
m_Fractorium->FillXaosTable();
|
||||
m_Fractorium->OnSoloXformCheckBoxStateChanged(Qt::Unchecked);
|
||||
m_Fractorium->OnCurrentXformComboChanged(0);//Make sure the event gets called, because it won't if the zero index is already selected.
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
|
@ -169,7 +169,7 @@ void Fractorium::InitXformsAffineUI()
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
@ -220,7 +220,7 @@ void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -235,16 +235,16 @@ void Fractorium::OnO1Changed(double d) { m_Controller->AffineSetHelper(d, 2, sen
|
||||
void Fractorium::OnO2Changed(double d) { m_Controller->AffineSetHelper(d, 5, sender() == m_PreO2Spin); }
|
||||
|
||||
/// <summary>
|
||||
/// Flip the current pre/post affine vertically and/or horizontally.
|
||||
/// Flip the selected pre/post affines vertically and/or horizontally.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="horizontal">True to flip horizontally</param>
|
||||
/// <param name="vertical">True to flip vertically</param>
|
||||
/// <param name="pre">True if pre affine, else post affine.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FlipCurrentXform(bool horizontal, bool vertical, bool pre)
|
||||
void FractoriumEmberController<T>::FlipXforms(bool horizontal, bool vertical, bool pre)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
@ -266,29 +266,31 @@ void FractoriumEmberController<T>::FlipCurrentXform(bool horizontal, bool vertic
|
||||
affine->F(-affine->F());
|
||||
}
|
||||
|
||||
FillAffineWithXform(xform, pre);
|
||||
});
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
void Fractorium::OnFlipHorizontalButtonClicked(bool checked) { m_Controller->FlipCurrentXform(true, false, sender() == ui.PreFlipHorizontalButton); }
|
||||
void Fractorium::OnFlipVerticalButtonClicked(bool checked) { m_Controller->FlipCurrentXform(false, true, sender() == ui.PreFlipVerticalButton); }
|
||||
void Fractorium::OnFlipHorizontalButtonClicked(bool checked) { m_Controller->FlipXforms(true, false, sender() == ui.PreFlipHorizontalButton); }
|
||||
void Fractorium::OnFlipVerticalButtonClicked(bool checked) { m_Controller->FlipXforms(false, true, sender() == ui.PreFlipVerticalButton); }
|
||||
|
||||
/// <summary>
|
||||
/// Rotate the current pre/post affine transform x degrees.
|
||||
/// Rotate the selected pre/post affines transform x degrees.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="angle">The angle to rotate by</param>
|
||||
/// <param name="pre">True if pre affine, else post affine.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::RotateCurrentXformByAngle(double angle, bool pre)
|
||||
void FractoriumEmberController<T>::RotateXformsByAngle(double angle, bool pre)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
affine->Rotate(angle);
|
||||
FillAffineWithXform(xform, pre);
|
||||
});
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -297,8 +299,8 @@ void FractoriumEmberController<T>::RotateCurrentXformByAngle(double angle, bool
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="checked">Ignored</param>
|
||||
void Fractorium::OnRotate90CButtonClicked(bool checked) { m_Controller->RotateCurrentXformByAngle(90, sender() == ui.PreRotate90CButton); }
|
||||
void Fractorium::OnRotate90CcButtonClicked(bool checked) { m_Controller->RotateCurrentXformByAngle(-90, sender() == ui.PreRotate90CcButton); }
|
||||
void Fractorium::OnRotate90CButtonClicked(bool checked) { m_Controller->RotateXformsByAngle(90, sender() == ui.PreRotate90CButton); }
|
||||
void Fractorium::OnRotate90CcButtonClicked(bool checked) { m_Controller->RotateXformsByAngle(-90, sender() == ui.PreRotate90CcButton); }
|
||||
|
||||
/// <summary>
|
||||
/// Rotate the selected pre/post affine transform x degrees clockwise.
|
||||
@ -314,7 +316,7 @@ void Fractorium::OnRotateCButtonClicked(bool checked)
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
m_Controller->RotateCurrentXformByAngle(d, pre);
|
||||
m_Controller->RotateXformsByAngle(d, pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -331,27 +333,28 @@ void Fractorium::OnRotateCcButtonClicked(bool checked)
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
m_Controller->RotateCurrentXformByAngle(-d, pre);
|
||||
m_Controller->RotateXformsByAngle(-d, pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the current pre/post affine in the x and y directions by the specified amount.
|
||||
/// Move the selected pre/post affines in the x and y directions by the specified amount.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="x">The x direction to move</param>
|
||||
/// <param name="y">The y direction to move</param>
|
||||
/// <param name="pre">True if pre affine, else post affine.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::MoveCurrentXform(double x, double y, bool pre)
|
||||
void FractoriumEmberController<T>::MoveXforms(double x, double y, bool pre)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
affine->C(affine->C() + x);
|
||||
affine->F(affine->F() + y);
|
||||
FillAffineWithXform(xform, pre);
|
||||
});
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -368,7 +371,7 @@ void Fractorium::OnMoveUpButtonClicked(bool checked)
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
m_Controller->MoveCurrentXform(0, d, pre);
|
||||
m_Controller->MoveXforms(0, d, pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -385,7 +388,7 @@ void Fractorium::OnMoveDownButtonClicked(bool checked)
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
m_Controller->MoveCurrentXform(0, -d, pre);
|
||||
m_Controller->MoveXforms(0, -d, pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -402,7 +405,7 @@ void Fractorium::OnMoveLeftButtonClicked(bool checked)
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
m_Controller->MoveCurrentXform(-d, 0, pre);
|
||||
m_Controller->MoveXforms(-d, 0, pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -419,19 +422,19 @@ void Fractorium::OnMoveRightButtonClicked(bool checked)
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
m_Controller->MoveCurrentXform(d, 0, pre);
|
||||
m_Controller->MoveXforms(d, 0, pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale the current pre/post affine by the specified amount.
|
||||
/// Scale the selected pre/post affines by the specified amount.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="scale">The scale value</param>
|
||||
/// <param name="pre">True if pre affine, else post affine.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ScaleCurrentXform(double scale, bool pre)
|
||||
void FractoriumEmberController<T>::ScaleXforms(double scale, bool pre)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
@ -439,8 +442,9 @@ void FractoriumEmberController<T>::ScaleCurrentXform(double scale, bool pre)
|
||||
affine->B(affine->B() * scale);
|
||||
affine->D(affine->D() * scale);
|
||||
affine->E(affine->E() * scale);
|
||||
FillAffineWithXform(xform, pre);
|
||||
});
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -457,7 +461,7 @@ void Fractorium::OnScaleDownButtonClicked(bool checked)
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
m_Controller->ScaleCurrentXform(1.0 / (d / 100.0), pre);
|
||||
m_Controller->ScaleXforms(1.0 / (d / 100.0), pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -474,24 +478,25 @@ void Fractorium::OnScaleUpButtonClicked(bool checked)
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
m_Controller->ScaleCurrentXform(d / 100.0, pre);
|
||||
m_Controller->ScaleXforms(d / 100.0, pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset pre/post affine to the identity matrix.
|
||||
/// Reset selected pre/post affines to the identity matrix.
|
||||
/// Called when reset pre/post affine buttons are clicked.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ResetCurrentXformAffine(bool pre)
|
||||
void FractoriumEmberController<T>::ResetXformsAffine(bool pre)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
affine->MakeID();
|
||||
FillAffineWithXform(xform, pre);
|
||||
});
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -499,7 +504,7 @@ void FractoriumEmberController<T>::ResetCurrentXformAffine(bool pre)
|
||||
/// Called when reset pre/post affine buttons are clicked.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
void Fractorium::OnResetAffineButtonClicked(bool checked) { m_Controller->ResetCurrentXformAffine(sender() == ui.PreResetButton); }
|
||||
void Fractorium::OnResetAffineButtonClicked(bool checked) { m_Controller->ResetXformsAffine(sender() == ui.PreResetButton); }
|
||||
|
||||
/// <summary>
|
||||
/// Fill the GUI with the pre and post affine xform values.
|
||||
|
@ -37,7 +37,7 @@ void Fractorium::InitXformsColorUI()
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the color index of the current xform.
|
||||
/// Set the color index of the selected xforms.
|
||||
/// Update the color index scrollbar to match.
|
||||
/// Called when spinner in the color index cell in the palette ref table is changed.
|
||||
/// Optionally resets the rendering process.
|
||||
@ -47,17 +47,14 @@ void Fractorium::InitXformsColorUI()
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformColorIndexChanged(double d, bool updateRender)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
{
|
||||
QScrollBar* scroll = m_Fractorium->ui.XformColorScroll;
|
||||
int scrollVal = d * scroll->maximum();
|
||||
auto scroll = m_Fractorium->ui.XformColorScroll;
|
||||
int scrollVal = d * scroll->maximum();
|
||||
|
||||
scroll->blockSignals(true);
|
||||
scroll->setValue(scrollVal);
|
||||
scroll->blockSignals(false);
|
||||
scroll->blockSignals(true);
|
||||
scroll->setValue(scrollVal);
|
||||
scroll->blockSignals(false);
|
||||
|
||||
SetCurrentXformColorIndex(d);
|
||||
}, updateRender);
|
||||
SetCurrentXformColorIndex(d, updateRender);
|
||||
}
|
||||
|
||||
void Fractorium::OnXformColorIndexChanged(double d) { OnXformColorIndexChanged(d, true); }
|
||||
@ -65,7 +62,7 @@ void Fractorium::OnXformColorIndexChanged(double d, bool updateRender) { m_Contr
|
||||
|
||||
/// <summary>
|
||||
/// Set the color index of the current xform.
|
||||
/// Update the color index cell in the palette ref table to match.
|
||||
/// Will trigger an update which will cause the color index cell in the palette ref table to match.
|
||||
/// Called when color index scrollbar is changed.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
@ -73,43 +70,40 @@ void Fractorium::OnXformColorIndexChanged(double d, bool updateRender) { m_Contr
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformScrollColorIndexChanged(int d)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
{
|
||||
m_Fractorium->m_XformColorIndexSpin->setValue(d / double(m_Fractorium->ui.XformColorScroll->maximum()));//Will trigger an update.
|
||||
}, false);
|
||||
m_Fractorium->m_XformColorIndexSpin->setValue(d / double(m_Fractorium->ui.XformColorScroll->maximum()));//Will trigger an update.
|
||||
}
|
||||
|
||||
void Fractorium::OnXformScrollColorIndexChanged(int d) { m_Controller->XformScrollColorIndexChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the color speed of the current xform.
|
||||
/// Set the color speed of the selected xforms.
|
||||
/// Called when xform color speed spinner is changed.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="d">The color speed, -1-1.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformColorSpeedChanged(double d) { UpdateCurrentXform([&] (Xform<T>* xform) { xform->m_ColorSpeed = d; }); }
|
||||
void FractoriumEmberController<T>::XformColorSpeedChanged(double d) { UpdateXform([&] (Xform<T>* xform) { xform->m_ColorSpeed = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void Fractorium::OnXformColorSpeedChanged(double d) { m_Controller->XformColorSpeedChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the opacity of the current xform.
|
||||
/// Set the opacity of the selected xforms.
|
||||
/// Called when xform opacity spinner is changed.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="d">The opacity, 0-1.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformOpacityChanged(double d) { UpdateCurrentXform([&] (Xform<T>* xform) { xform->m_Opacity = d; }); }
|
||||
void FractoriumEmberController<T>::XformOpacityChanged(double d) { UpdateXform([&] (Xform<T>* xform) { xform->m_Opacity = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void Fractorium::OnXformOpacityChanged(double d) { m_Controller->XformOpacityChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the direct color percentage of the current xform.
|
||||
/// Set the direct color percentage of the selected xforms.
|
||||
/// Called when xform direct color spinner is changed.
|
||||
/// Note this only affects xforms that include a dc_ variation.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="d">The direct color percentage, 0-1.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformDirectColorChanged(double d) { UpdateCurrentXform([&] (Xform<T>* xform) { xform->m_DirectColor = d; }); }
|
||||
void FractoriumEmberController<T>::XformDirectColorChanged(double d) { UpdateXform([&] (Xform<T>* xform) { xform->m_DirectColor = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void Fractorium::OnXformDirectColorChanged(double d) { m_Controller->XformDirectColorChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
@ -201,27 +195,27 @@ void Fractorium::OnCurvesGreenRadioButtonToggled(bool checked) { if (checked) ui
|
||||
void Fractorium::OnCurvesBlueRadioButtonToggled(bool checked) { if (checked) ui.CurvesView->SetTop(CurveIndex::BLUE); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the current xform color index spinner to the current xform's color index.
|
||||
/// Set the selected xforms color index to the passed in value.
|
||||
/// Set the color cell in the palette ref table.
|
||||
/// </summary>
|
||||
/// <param name="d">The index value to set, 0-1.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SetCurrentXformColorIndex(double d)
|
||||
void FractoriumEmberController<T>::SetCurrentXformColorIndex(double d, bool updateRender)
|
||||
{
|
||||
UpdateCurrentXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
xform->m_ColorX = Clamp<T>(d, 0, 1);
|
||||
|
||||
|
||||
//Grab the current color from the index and assign it to the first cell of the first table.
|
||||
v4T entry = m_Ember.m_Palette[Clamp<int>(d * COLORMAP_LENGTH_MINUS_1, 0, m_Ember.m_Palette.Size())];
|
||||
|
||||
entry.r *= 255;
|
||||
entry.g *= 255;
|
||||
entry.b *= 255;
|
||||
|
||||
|
||||
QRgb rgb = uint(entry.r) << 16 | uint(entry.g) << 8 | uint(entry.b);
|
||||
m_Fractorium->ui.XformColorIndexTable->item(0, 0)->setBackgroundColor(QColor::fromRgb(rgb));
|
||||
}, false);
|
||||
}, eXformUpdate::UPDATE_SELECTED, updateRender);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -247,7 +241,7 @@ void FractoriumEmberController<T>::FillCurvesControl()
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the color index, speed and opacity spinners with the values of the current xform.
|
||||
/// Set the color index, speed and opacity spinners with the values of the passed in xform.
|
||||
/// Set the cells of the palette ref table as well.
|
||||
/// </summary>
|
||||
/// <param name="xform">The xform whose values will be copied to the GUI</param>
|
||||
|
127
Source/Fractorium/FractoriumXformsSelect.cpp
Normal file
127
Source/Fractorium/FractoriumXformsSelect.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include "FractoriumPch.h"
|
||||
#include "Fractorium.h"
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the xforms selection UI.
|
||||
/// </summary>
|
||||
void Fractorium::InitXformsSelectUI()
|
||||
{
|
||||
m_XformsSelectionLayout = (QFormLayout*)ui.XformsSelectGroupBoxScrollAreaWidget->layout();
|
||||
connect(ui.XformsSelectAllButton, SIGNAL(clicked(bool)), this, SLOT(OnXformsSelectAllButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.XformsSelectNoneButton, SIGNAL(clicked(bool)), this, SLOT(OnXformsSelectNoneButtonClicked(bool)), Qt::QueuedConnection);
|
||||
|
||||
ClearXformsSelections();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check all of the xform selection checkboxes.
|
||||
/// </summary>
|
||||
/// <param name="checked">Ignored</param>
|
||||
void Fractorium::OnXformsSelectAllButtonClicked(bool checked) { ForEachXformCheckbox([&](int i, QCheckBox* w) { w->setChecked(true); }); }
|
||||
|
||||
/// <summary>
|
||||
/// Uncheck all of the xform selection checkboxes.
|
||||
/// </summary>
|
||||
/// <param name="checked">Ignored</param>
|
||||
void Fractorium::OnXformsSelectNoneButtonClicked(bool checked) { ForEachXformCheckbox([&](int i, QCheckBox* w) { w->setChecked(false); }); }
|
||||
|
||||
/// <summary>
|
||||
/// Clear all of the dynamically created xform checkboxes.
|
||||
/// </summary>
|
||||
void Fractorium::ClearXformsSelections()
|
||||
{
|
||||
QLayoutItem* child = nullptr;
|
||||
|
||||
m_XformSelections.clear();
|
||||
m_XformsSelectionLayout->blockSignals(true);
|
||||
|
||||
while (m_XformsSelectionLayout->count() && (child = m_XformsSelectionLayout->takeAt(0)))
|
||||
{
|
||||
auto* w = child->widget();
|
||||
delete child;
|
||||
delete w;
|
||||
}
|
||||
|
||||
m_XformsSelectionLayout->blockSignals(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a caption from an xform.
|
||||
/// The caption will be the xform count + 1, optionally followed by the xform's name.
|
||||
/// For final xforms, the string "Final" will be used in place of the count.
|
||||
/// </summary>
|
||||
/// <param name="i">The index of xform to make a caption for</param>
|
||||
/// <returns>The caption string</returns>
|
||||
template <typename T>
|
||||
QString FractoriumEmberController<T>::MakeXformCaption(size_t i)
|
||||
{
|
||||
bool isFinal = m_Ember.FinalXform() == m_Ember.GetTotalXform(i);
|
||||
QString caption = isFinal ? "Final" : QString::number(i + 1);
|
||||
|
||||
if (Xform<T>* xform = m_Ember.GetTotalXform(i))
|
||||
{
|
||||
if (!xform->m_Name.empty())
|
||||
caption += " (" + QString::fromStdString(xform->m_Name) + ")";
|
||||
}
|
||||
|
||||
return caption;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function to perform the specified operation on every dynamically created xform selection checkbox.
|
||||
/// </summary>
|
||||
/// <param name="func">The operation to perform</param>
|
||||
void Fractorium::ForEachXformCheckbox(std::function<void(int, QCheckBox*)> func)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (QLayoutItem* child = m_XformsSelectionLayout->itemAt(i))
|
||||
{
|
||||
if (auto* w = dynamic_cast<QCheckBox*>(child->widget()))
|
||||
{
|
||||
func(i, w);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function to perform the specified operation on one dynamically created xform selection checkbox.
|
||||
/// </summary>
|
||||
/// <param name="i">The index of the checkbox</param>
|
||||
/// <param name="func">The operation to perform</param>
|
||||
/// <returns>True if the checkbox was found, else false.</returns>
|
||||
template <typename T>
|
||||
bool FractoriumEmberController<T>::XformCheckboxAt(int i, std::function<void(QCheckBox*)> func)
|
||||
{
|
||||
if (QLayoutItem* child = m_Fractorium->m_XformsSelectionLayout->itemAt(i))
|
||||
{
|
||||
if (auto* w = dynamic_cast<QCheckBox*>(child->widget()))
|
||||
{
|
||||
func(w);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function to perform the specified operation on one dynamically created xform selection checkbox.
|
||||
/// The checkbox is specified by the xform it corresponds to, rather than its index.
|
||||
/// </summary>
|
||||
/// <param name="xform">The xform that corresponds to the checkbox</param>
|
||||
/// <param name="func">The operation to perform</param>
|
||||
/// <returns>True if the checkbox was found, else false.</returns>
|
||||
template <typename T>
|
||||
bool FractoriumEmberController<T>::XformCheckboxAt(Xform<T>* xform, std::function<void(QCheckBox*)> func)
|
||||
{
|
||||
return XformCheckboxAt(m_Ember.GetTotalXformIndex(xform), func);
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
@ -129,7 +129,7 @@ void FractoriumEmberController<T>::ClearVariationsTree()
|
||||
/// </summary>
|
||||
/// <param name="d">The spinner value</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)
|
||||
void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would be awesome to make this work for all.//TODO
|
||||
{
|
||||
QObject* objSender = m_Fractorium->sender();
|
||||
QTreeWidget* tree = m_Fractorium->ui.VariationsTree;
|
||||
|
Loading…
Reference in New Issue
Block a user