mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-02-01 10:30:08 -05:00
Bug fixes:
--Fix bug where clearing the final xform, but leaving it present, then editing it would crash the program.
This commit is contained in:
parent
706c0b60ad
commit
a81b93d94a
@ -215,6 +215,27 @@ public:
|
||||
AddXforms(xformPad - XformCount());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace the xforms vector with the one passed in.
|
||||
/// </summary>
|
||||
/// <param name="xforms">The xforms to replace with</param>
|
||||
/// <param name="xformPad">True to move, false to copy. Default: true.</param>
|
||||
/// <returns>True if replaced, else false.</returns>
|
||||
bool ReplaceXforms(vector<Xform<T>>& xforms, bool move = true)
|
||||
{
|
||||
if (!xforms.empty())
|
||||
{
|
||||
if (move)
|
||||
m_Xforms = std::move(xforms);
|
||||
else
|
||||
m_Xforms = xforms;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy this ember with optional padding xforms added.
|
||||
/// </summary>
|
||||
@ -280,12 +301,13 @@ public:
|
||||
/// Delete the xform at the specified index, including the final one.
|
||||
/// </summary>
|
||||
/// <param name="i">The index to delete</param>
|
||||
/// <param name="forceFinal">If true, delete the final xform when its index is passed in even if one is not present. Default: false.</param>
|
||||
/// <returns>True if success, else false.</returns>
|
||||
bool DeleteTotalXform(size_t i)
|
||||
bool DeleteTotalXform(size_t i, bool forceFinal = false)
|
||||
{
|
||||
if (DeleteXform(i))
|
||||
{ }
|
||||
else if (i == XformCount() && UseFinalXform())
|
||||
else if (i == XformCount() && (forceFinal || UseFinalXform()))
|
||||
m_FinalXform.Clear();
|
||||
else
|
||||
return false;
|
||||
@ -310,13 +332,13 @@ public:
|
||||
/// Get a pointer to the xform at the specified index, including the final one.
|
||||
/// </summary>
|
||||
/// <param name="i">The index to get</param>
|
||||
/// <param name="forceFinal">If true, return the final xform when its index is requested even if one is not present</param>
|
||||
/// <param name="forceFinal">If true, return the final xform when its index is requested even if one is not present. Default: false.</param>
|
||||
/// <returns>A pointer to the xform at the index if successful, else nullptr.</returns>
|
||||
Xform<T>* GetTotalXform(size_t i, bool forceFinal = false) const
|
||||
{
|
||||
if (i < XformCount())
|
||||
return const_cast<Xform<T>*>(&m_Xforms[i]);
|
||||
else if (forceFinal || (i == XformCount() && UseFinalXform()))
|
||||
else if (i == XformCount() && (forceFinal || UseFinalXform()))
|
||||
return const_cast<Xform<T>*>(&m_FinalXform);
|
||||
else
|
||||
return nullptr;
|
||||
@ -342,13 +364,14 @@ public:
|
||||
/// Search the xforms, including final, to find which one's address matches the address of the specified xform.
|
||||
/// </summary>
|
||||
/// <param name="xform">A pointer to the xform to find</param>
|
||||
/// <param name="forceFinal">If true, return the index of the final xform when its pointer is passed, even if a final is not present. Default: false.</param>
|
||||
/// <returns>The index of the matched xform if found, else -1.</returns>
|
||||
intmax_t GetTotalXformIndex(Xform<T>* xform) const
|
||||
intmax_t GetTotalXformIndex(Xform<T>* xform, bool forceFinal = false) const
|
||||
{
|
||||
size_t totalXformCount = TotalXformCount();
|
||||
size_t totalXformCount = TotalXformCount(forceFinal);
|
||||
|
||||
for (size_t i = 0; i < totalXformCount; i++)
|
||||
if (GetTotalXform(i) == xform)
|
||||
if (GetTotalXform(i, forceFinal) == xform)
|
||||
return intmax_t(i);
|
||||
|
||||
return -1;
|
||||
@ -1468,7 +1491,7 @@ public:
|
||||
inline const Xform<T>* FinalXform() const { return &m_FinalXform; }
|
||||
inline Xform<T>* NonConstFinalXform() { return &m_FinalXform; }
|
||||
inline bool UseFinalXform() const { return !m_FinalXform.Empty(); }
|
||||
inline size_t TotalXformCount() const { return XformCount() + (UseFinalXform() ? 1 : 0); }
|
||||
inline size_t TotalXformCount(bool forceFinal = false) const { return XformCount() + ((forceFinal || UseFinalXform()) ? 1 : 0); }
|
||||
inline int PaletteIndex() const { return m_Palette.m_Index; }
|
||||
inline T BlurCoef() { return m_BlurCoef; }
|
||||
inline eScaleType ScaleType() const { return m_ScaleType; }
|
||||
|
@ -264,6 +264,8 @@ void FractoriumEmberController<T>::ApplyXmlSavingTemplate(Ember<T>& ember)
|
||||
|
||||
/// <summary>
|
||||
/// Return whether the current ember contains a final xform and the GUI is aware of it.
|
||||
/// Note this can be true even if the final is empty, as long as they've added one and have
|
||||
/// not explicitly deleted it.
|
||||
/// </summary>
|
||||
/// <returns>True if the current ember contains a final xform, else false.</returns>
|
||||
bool Fractorium::HaveFinal()
|
||||
|
@ -405,7 +405,7 @@ private:
|
||||
|
||||
//Xforms Selection.
|
||||
void ClearXformsSelections();
|
||||
void ForEachXformCheckbox(std::function<void(int, QCheckBox*)> func);
|
||||
void ForEachXformCheckbox(std::function<void(int, QCheckBox*, bool)> func);
|
||||
|
||||
//Xaos.
|
||||
void FillXaosTable();
|
||||
|
@ -3423,7 +3423,7 @@
|
||||
<string><html><head/><body><p>Set all xform color speed values to random numbers between 0 and 1, inclusive</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Random Color Speed</string>
|
||||
<string>Random Color Speeds</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -208,31 +208,32 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType, bool updateRender, eProcessAction action, size_t index)
|
||||
{
|
||||
int i = 0;
|
||||
bool isCurrentFinal = m_Ember.IsFinalXform(CurrentXform());
|
||||
auto current = CurrentXform();
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
bool isCurrentFinal = m_Ember.IsFinalXform(current);
|
||||
bool doFinal = updateType != eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL && updateType != eXformUpdate::UPDATE_ALL_EXCEPT_FINAL;
|
||||
|
||||
switch (updateType)
|
||||
{
|
||||
case eXformUpdate::UPDATE_SPECIFIC:
|
||||
{
|
||||
if (auto xform = m_Ember.GetTotalXform(index))
|
||||
if (auto xform = m_Ember.GetTotalXform(index, forceFinal))
|
||||
func(xform);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_CURRENT:
|
||||
{
|
||||
if (auto xform = CurrentXform())
|
||||
func(xform);
|
||||
if (current)
|
||||
func(current);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_CURRENT_AND_SELECTED:
|
||||
{
|
||||
bool currentDone = false;
|
||||
auto current = CurrentXform();
|
||||
|
||||
while (auto xform = m_Ember.GetTotalXform(i))
|
||||
while (auto xform = m_Ember.GetTotalXform(i, forceFinal))
|
||||
{
|
||||
if (i < m_Fractorium->m_XformSelections.size())
|
||||
{
|
||||
@ -261,7 +262,7 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
{
|
||||
bool anyUpdated = false;
|
||||
|
||||
while (auto xform = (doFinal ? m_Ember.GetTotalXform(i) : m_Ember.GetXform(i)))
|
||||
while (auto xform = (doFinal ? m_Ember.GetTotalXform(i, forceFinal) : m_Ember.GetXform(i)))
|
||||
{
|
||||
if (i < m_Fractorium->m_XformSelections.size())
|
||||
{
|
||||
@ -280,14 +281,14 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
|
||||
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 (auto xform = CurrentXform())
|
||||
func(xform);
|
||||
if (current)
|
||||
func(current);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_ALL:
|
||||
{
|
||||
while (auto xform = m_Ember.GetTotalXform(i++))
|
||||
while (auto xform = m_Ember.GetTotalXform(i++, forceFinal))
|
||||
func(xform);
|
||||
}
|
||||
break;
|
||||
|
@ -69,7 +69,8 @@ void FractoriumEmberController<T>::FillSummary()
|
||||
int vp = 4;
|
||||
int vlen = 7;
|
||||
char pc = 'f';
|
||||
size_t x = 0, total = m_Ember.TotalXformCount();
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
size_t x = 0, total = m_Ember.TotalXformCount(forceFinal);
|
||||
Xform<T>* xform = nullptr;
|
||||
QColor color;
|
||||
auto table = m_Fractorium->ui.SummaryTable;
|
||||
@ -85,7 +86,7 @@ void FractoriumEmberController<T>::FillSummary()
|
||||
QSize size(table->columnWidth(0), table->rowHeight(1) + 1);
|
||||
m_Fractorium->m_InfoPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
|
||||
for (x = 0; x < total && (xform = m_Ember.GetTotalXform(x)); x++)
|
||||
for (x = 0; x < total && (xform = m_Ember.GetTotalXform(x, forceFinal)); x++)
|
||||
{
|
||||
size_t i = 0;
|
||||
QString as = "Pre";
|
||||
@ -233,5 +234,5 @@ void Fractorium::ErrorReportToQTextEdit(const vector<string>& errors, QTextEdit*
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -428,7 +428,9 @@ void FractoriumEmberController<T>::Undo()
|
||||
{
|
||||
if (m_UndoList.size() > 1 && m_UndoIndex > 0)
|
||||
{
|
||||
int index = m_Ember.GetTotalXformIndex(CurrentXform());
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
auto current = CurrentXform();
|
||||
int index = m_Ember.GetTotalXformIndex(current, forceFinal);
|
||||
m_LastEditWasUndoRedo = true;
|
||||
m_UndoIndex = std::max<size_t>(0u, m_UndoIndex - 1u);
|
||||
SetEmber(m_UndoList[m_UndoIndex], true, false);//Don't update pointer because it's coming from the undo list...
|
||||
@ -452,7 +454,9 @@ void FractoriumEmberController<T>::Redo()
|
||||
{
|
||||
if (m_UndoList.size() > 1 && m_UndoIndex < m_UndoList.size() - 1)
|
||||
{
|
||||
int index = m_Ember.GetTotalXformIndex(CurrentXform());
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
auto current = CurrentXform();
|
||||
int index = m_Ember.GetTotalXformIndex(current, forceFinal);
|
||||
m_LastEditWasUndoRedo = true;
|
||||
m_UndoIndex = std::min<size_t>(m_UndoIndex + 1, m_UndoList.size() - 1);
|
||||
SetEmber(m_UndoList[m_UndoIndex], true, false);
|
||||
@ -740,10 +744,11 @@ void Fractorium::OnActionResetScale(bool checked)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddReflectiveSymmetry()
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(-1, m_Rand);
|
||||
auto index = m_Ember.TotalXformCount() - (m_Ember.UseFinalXform() ? 2 : 1);//Set index to the last item before final.
|
||||
auto index = m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1);//Set index to the last item before final.
|
||||
FillXforms(int(index));
|
||||
});
|
||||
}
|
||||
@ -757,10 +762,11 @@ void Fractorium::OnActionAddReflectiveSymmetry(bool checked) { m_Controller->Add
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddRotationalSymmetry()
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(2, m_Rand);
|
||||
auto index = m_Ember.TotalXformCount() - (m_Ember.UseFinalXform() ? 2 : 1);//Set index to the last item before final.
|
||||
auto index = m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1);//Set index to the last item before final.
|
||||
FillXforms(int(index));
|
||||
});
|
||||
}
|
||||
@ -774,10 +780,11 @@ void Fractorium::OnActionAddRotationalSymmetry(bool checked) { m_Controller->Add
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddBothSymmetry()
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(-2, m_Rand);
|
||||
auto index = m_Ember.TotalXformCount() - (m_Ember.UseFinalXform() ? 2 : 1);//Set index to the last item before final.
|
||||
auto index = m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1);//Set index to the last item before final.
|
||||
FillXforms(int(index));
|
||||
});
|
||||
}
|
||||
|
@ -323,8 +323,9 @@ void FractoriumEmberController<T>::PaletteEditorButtonClicked()
|
||||
Palette<float> prevPal = m_TempPalette;
|
||||
ed->SetPalette(m_TempPalette);
|
||||
map<size_t, float> colorIndices;
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
|
||||
while (auto xform = m_Ember.GetTotalXform(i))
|
||||
while (auto xform = m_Ember.GetTotalXform(i, forceFinal))
|
||||
colorIndices[i++] = xform->m_ColorX;
|
||||
|
||||
ed->SetColorIndices(colorIndices);
|
||||
|
@ -341,10 +341,11 @@ bool FractoriumEmberController<T>::Render()
|
||||
{
|
||||
size_t i = 0;
|
||||
int solo = m_Fractorium->ui.CurrentXformCombo->property("soloxform").toInt();
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
|
||||
if (solo != -1)
|
||||
{
|
||||
m_TempOpacities.resize(m_Ember.TotalXformCount());
|
||||
m_TempOpacities.resize(m_Ember.TotalXformCount(forceFinal));
|
||||
|
||||
while (auto xform = m_Ember.GetTotalXform(i))
|
||||
{
|
||||
@ -357,7 +358,7 @@ bool FractoriumEmberController<T>::Render()
|
||||
m_Renderer->SetEmber(m_Ember, action);
|
||||
|
||||
if (solo != -1)
|
||||
while (auto xform = m_Ember.GetTotalXform(i))
|
||||
while (auto xform = m_Ember.GetTotalXform(i, forceFinal))
|
||||
xform->m_Opacity = m_TempOpacities[i++];
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ void Fractorium::InitXformsUI()
|
||||
template <typename T>
|
||||
Xform<T>* FractoriumEmberController<T>::CurrentXform()
|
||||
{
|
||||
return m_Ember.GetTotalXform(m_Fractorium->ui.CurrentXformCombo->currentIndex());
|
||||
bool hasFinal = m_Fractorium->HaveFinal();
|
||||
return m_Ember.GetTotalXform(m_Fractorium->ui.CurrentXformCombo->currentIndex(), hasFinal);//Need to force final for the special case they created a final, then cleared it, but did not delete it.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -67,7 +68,9 @@ void Fractorium::CurrentXform(uint i)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::CurrentXformComboChanged(int index)
|
||||
{
|
||||
if (auto xform = m_Ember.GetTotalXform(index))
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
|
||||
if (auto xform = m_Ember.GetTotalXform(index, forceFinal))
|
||||
{
|
||||
FillWithXform(xform);
|
||||
m_GLController->SetSelectedXform(xform);
|
||||
@ -95,13 +98,14 @@ void Fractorium::OnCurrentXformComboChanged(int index) { m_Controller->CurrentXf
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddXform()
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
Update([&]()
|
||||
{
|
||||
Xform<T> newXform;
|
||||
newXform.m_Weight = 0.25;
|
||||
newXform.m_ColorX = m_Rand.Frand01<T>();
|
||||
m_Ember.AddXform(newXform);
|
||||
int index = int(m_Ember.TotalXformCount() - (m_Ember.UseFinalXform() ? 2 : 1));//Set index to the last item before final.
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);
|
||||
});
|
||||
}
|
||||
@ -119,6 +123,7 @@ void Fractorium::OnAddXformButtonClicked(bool checked) { m_Controller->AddXform(
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddLinkedXform()
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
{
|
||||
size_t i, count = m_Ember.XformCount();
|
||||
@ -148,7 +153,7 @@ void FractoriumEmberController<T>::AddLinkedXform()
|
||||
|
||||
xform->SetXaos(count - 1, 1);//Set the xaos value for the previous xform pointing to the new one to one.
|
||||
xform->m_Opacity = 0;//Clear the opacity of the previous xform.
|
||||
int index = int(m_Ember.TotalXformCount() - (m_Ember.UseFinalXform() ? 2 : 1));//Set index to the last item before final.
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);
|
||||
FillXaos();
|
||||
}, eXformUpdate::UPDATE_CURRENT);
|
||||
@ -165,6 +170,7 @@ void Fractorium::OnAddLinkedXformButtonClicked(bool checked) { m_Controller->Add
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::DuplicateXform()
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
vector<Xform<T>> vec;
|
||||
vec.reserve(m_Ember.XformCount());
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
@ -176,7 +182,7 @@ void FractoriumEmberController<T>::DuplicateXform()
|
||||
for (auto& it : vec)
|
||||
m_Ember.AddXform(it);
|
||||
|
||||
int index = int(m_Ember.TotalXformCount() - (m_Ember.UseFinalXform() ? 2 : 1));//Set index to the last item before final.
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);//Handles xaos.
|
||||
});
|
||||
}
|
||||
@ -211,49 +217,60 @@ void Fractorium::OnClearXformButtonClicked(bool checked) { m_Controller->ClearXf
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::DeleteXforms()
|
||||
{
|
||||
int offset = 0, current = 0, checked = 0;
|
||||
bool haveFinal = false;
|
||||
size_t count;
|
||||
bool removed = false;
|
||||
bool haveFinal = m_Fractorium->HaveFinal();
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
Xform<T>* finalXform = nullptr;
|
||||
vector<Xform<T>> xforms;
|
||||
xforms.reserve(m_Ember.TotalXformCount());
|
||||
//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)
|
||||
//Rather than go through and delete, it's easier to just make a list of what we want to keep.
|
||||
m_Fractorium->ForEachXformCheckbox([&](int i, QCheckBox * w, bool isFinal)
|
||||
{
|
||||
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 && !(i - offset))
|
||||
return;
|
||||
|
||||
if (!haveFinal && count == 1)
|
||||
return;
|
||||
|
||||
if (w->isChecked())
|
||||
if (!w->isChecked())//Keep if not checked.
|
||||
{
|
||||
m_Ember.DeleteTotalXform(i - offset);//Subtract offset to account for previously deleted xforms.
|
||||
offset++;
|
||||
if (isFinal)
|
||||
finalXform = m_Ember.NonConstFinalXform();
|
||||
else if (auto xform = m_Ember.GetXform(i))
|
||||
xforms.push_back(*xform);
|
||||
}
|
||||
});
|
||||
current = combo->currentIndex();
|
||||
count = m_Ember.TotalXformCount();
|
||||
haveFinal = m_Ember.UseFinalXform();//Requery again.
|
||||
//They might not have selected any checkboxes, in which case just delete the current.
|
||||
auto current = combo->currentIndex();
|
||||
auto count = m_Ember.TotalXformCount();
|
||||
bool anySelected = xforms.size() < m_Ember.XformCount();
|
||||
bool finalSelected = !finalXform && haveFinal;
|
||||
|
||||
//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))
|
||||
if (!anySelected && !finalSelected)
|
||||
{
|
||||
m_Ember.DeleteTotalXform(current);
|
||||
offset++;
|
||||
//Disallow deleting the only remaining non-final xform.
|
||||
if (!(haveFinal && count <= 2 && current == 0) &&//One non-final, one final, disallow deleting non-final.
|
||||
!(!haveFinal && count == 1))//One non-final, no final, disallow deleting.
|
||||
{
|
||||
m_Ember.DeleteTotalXform(current, haveFinal);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!xforms.empty() && (xforms.size() != m_Ember.XformCount()))//Remove if they requested to do so, but ensure it's not removing all.
|
||||
{
|
||||
removed = true;
|
||||
m_Ember.ReplaceXforms(xforms);
|
||||
}
|
||||
|
||||
if (offset)
|
||||
if (finalSelected)
|
||||
{
|
||||
removed = true;
|
||||
m_Ember.NonConstFinalXform()->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (removed)
|
||||
{
|
||||
int index = int(m_Ember.TotalXformCount() - (m_Ember.UseFinalXform() ? 2 : 1));//Set index to the last item before final. Note final is requeried one last time.
|
||||
FillXforms(index);
|
||||
@ -262,7 +279,6 @@ void FractoriumEmberController<T>::DeleteXforms()
|
||||
}
|
||||
|
||||
void Fractorium::OnDeleteXformButtonClicked(bool checked) { m_Controller->DeleteXforms(); }
|
||||
|
||||
/// <summary>
|
||||
/// Add a final xform to the ember and set it as the current xform.
|
||||
/// Will only take action if a final xform is not already present.
|
||||
@ -286,9 +302,7 @@ void FractoriumEmberController<T>::AddFinalXform()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnAddFinalXformButtonClicked(bool checked) { m_Controller->AddFinalXform(); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the weight of the selected xforms.
|
||||
/// Called when weight spinner changes.
|
||||
@ -304,9 +318,7 @@ void FractoriumEmberController<T>::XformWeightChanged(double d)
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL);
|
||||
SetNormalizedWeightText(CurrentXform());
|
||||
}
|
||||
|
||||
void Fractorium::OnXformWeightChanged(double d) { m_Controller->XformWeightChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Equalize the weights of all xforms in the ember.
|
||||
/// </summary>
|
||||
@ -319,9 +331,7 @@ void FractoriumEmberController<T>::EqualizeWeights()
|
||||
m_Fractorium->m_XformWeightSpin->setValue(xform->m_Weight);//Will trigger an update, so pass false to updateRender below.
|
||||
}, 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.
|
||||
@ -332,17 +342,16 @@ void Fractorium::OnEqualWeightButtonClicked(bool checked) { m_Controller->Equali
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformNameChanged(int row, int col)
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
int index = m_Ember.GetTotalXformIndex(xform);
|
||||
int index = m_Ember.GetTotalXformIndex(xform, forceFinal);
|
||||
xform->m_Name = m_Fractorium->ui.XformWeightNameTable->item(row, col)->text().toStdString();
|
||||
XformCheckboxAt(index, [&](QCheckBox * checkbox) { checkbox->setText(MakeXformCaption(index)); });
|
||||
}, eXformUpdate::UPDATE_CURRENT, false);
|
||||
FillSummary();//Manually update because this does not trigger a render, which is where this would normally be called.
|
||||
}
|
||||
|
||||
void Fractorium::OnXformNameChanged(int row, int col) { m_Controller->XformNameChanged(row, col); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the animate field of the selected xforms.
|
||||
/// This has no effect on interactive rendering, it only sets a value
|
||||
@ -373,9 +382,7 @@ void FractoriumEmberController<T>::XformAnimateChanged(int state)
|
||||
}
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
void Fractorium::OnXformAnimateCheckBoxStateChanged(int state) { m_Controller->XformAnimateChanged(state); }
|
||||
|
||||
/// <summary>
|
||||
/// Fill all GUI widgets with values from the passed in xform.
|
||||
/// </summary>
|
||||
@ -399,7 +406,6 @@ void FractoriumEmberController<T>::FillWithXform(Xform<T>* xform)//Need to see w
|
||||
FillAffineWithXform(xform, true);
|
||||
FillAffineWithXform(xform, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the normalized weight of the current xform as the suffix text of the weight spinner.
|
||||
/// </summary>
|
||||
@ -416,7 +422,6 @@ void FractoriumEmberController<T>::SetNormalizedWeightText(Xform<T>* xform)
|
||||
m_Fractorium->m_XformWeightSpin->setSuffix(QString(" (") + QLocale::system().toString(double(m_NormalizedWeights[index]), 'g', 3) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether the specified xform is the final xform in the ember.
|
||||
/// </summary>
|
||||
@ -427,7 +432,6 @@ bool FractoriumEmberController<T>::IsFinal(Xform<T>* xform)
|
||||
{
|
||||
return (m_Fractorium->HaveFinal() && (xform == m_Ember.FinalXform()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill the xforms combo box with the xforms in the current ember.
|
||||
/// Select the index passed in and fill all widgets with its values.
|
||||
@ -498,9 +502,7 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
m_Fractorium->OnSoloXformCheckBoxStateChanged(Qt::Unchecked);
|
||||
m_Fractorium->OnCurrentXformComboChanged(index);//Make sure the event gets called, because it won't if the zero index is already selected.
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
@ -16,13 +16,13 @@ void Fractorium::InitXformsSelectUI()
|
||||
/// 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); }); }
|
||||
void Fractorium::OnXformsSelectAllButtonClicked(bool checked) { ForEachXformCheckbox([&](int i, QCheckBox * w, bool isFinal) { 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); }); }
|
||||
void Fractorium::OnXformsSelectNoneButtonClicked(bool checked) { ForEachXformCheckbox([&](int i, QCheckBox * w, bool isFinal) { w->setChecked(false); }); }
|
||||
|
||||
/// <summary>
|
||||
/// Return whether the checkbox at the specified index is checked.
|
||||
@ -67,10 +67,11 @@ void Fractorium::ClearXformsSelections()
|
||||
template <typename T>
|
||||
QString FractoriumEmberController<T>::MakeXformCaption(size_t i)
|
||||
{
|
||||
bool isFinal = m_Ember.FinalXform() == m_Ember.GetTotalXform(i);
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
bool isFinal = m_Ember.FinalXform() == m_Ember.GetTotalXform(i, forceFinal);
|
||||
QString caption = isFinal ? "Final" : QString::number(i + 1);
|
||||
|
||||
if (auto xform = m_Ember.GetTotalXform(i))
|
||||
if (auto xform = m_Ember.GetTotalXform(i, forceFinal))
|
||||
if (!xform->m_Name.empty())
|
||||
caption += " (" + QString::fromStdString(xform->m_Name) + ")";
|
||||
|
||||
@ -81,12 +82,13 @@ QString FractoriumEmberController<T>::MakeXformCaption(size_t i)
|
||||
/// 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)
|
||||
void Fractorium::ForEachXformCheckbox(std::function<void(int, QCheckBox*, bool)> func)
|
||||
{
|
||||
int i = 0;
|
||||
bool haveFinal = HaveFinal();
|
||||
|
||||
for (auto& cb : m_XformSelections)
|
||||
func(i++, cb);
|
||||
func(i++, cb, haveFinal && cb == m_XformSelections.back());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -120,7 +122,8 @@ bool FractoriumEmberController<T>::XformCheckboxAt(int i, std::function<void(QCh
|
||||
template <typename T>
|
||||
bool FractoriumEmberController<T>::XformCheckboxAt(Xform<T>* xform, std::function<void(QCheckBox*)> func)
|
||||
{
|
||||
return XformCheckboxAt(m_Ember.GetTotalXformIndex(xform), func);
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
return XformCheckboxAt(m_Ember.GetTotalXformIndex(xform, forceFinal), func);
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
|
@ -215,7 +215,7 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
|
||||
if (isParam)
|
||||
{
|
||||
//Do not take action if the xform doesn't contain the variation which this param is part of.
|
||||
if (ParametricVariation<T>* xformParVar = dynamic_cast<ParametricVariation<T>*>(xformVar))//The parametric cast of the xform's variation.
|
||||
if (auto xformParVar = dynamic_cast<ParametricVariation<T>*>(xformVar))//The parametric cast of the xform's variation.
|
||||
if (xformParVar->SetParamVal(sender->ParamName().c_str(), d))
|
||||
update = true;
|
||||
}
|
||||
|
@ -290,6 +290,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
bool dragging = m_DragState == eDragState::DragDragging;
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
|
||||
//Draw grid if control key is pressed.
|
||||
if ((m_GL->hasFocus() && GetControl()) || m_Fractorium->DrawGrid())
|
||||
@ -307,7 +308,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
while (auto xform = ember->GetTotalXform(i))
|
||||
while (auto xform = ember->GetTotalXform(i, forceFinal))
|
||||
{
|
||||
bool selected = m_Fractorium->IsXformSelected(i++) || (dragging ? (m_SelectedXform == xform) : (m_HoverXform == xform));
|
||||
DrawAffine(xform, true, selected);
|
||||
@ -322,7 +323,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
while (auto xform = ember->GetTotalXform(i))
|
||||
while (auto xform = ember->GetTotalXform(i, forceFinal))
|
||||
{
|
||||
bool selected = m_Fractorium->IsXformSelected(i++) || (dragging ? (m_SelectedXform == xform) : (m_HoverXform == xform));
|
||||
DrawAffine(xform, false, selected);
|
||||
@ -1035,6 +1036,8 @@ int GLEmberController<T>::UpdateHover(v3T& glCoords)
|
||||
|
||||
if (m_Fractorium->DrawXforms())//Don't bother checking anything if the user wants to see no xforms.
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
|
||||
//If there's a selected/current xform, check it first so it gets precedence over the others.
|
||||
if (m_SelectedXform)
|
||||
{
|
||||
@ -1047,12 +1050,13 @@ int GLEmberController<T>::UpdateHover(v3T& glCoords)
|
||||
if (CheckXformHover(m_SelectedXform, glCoords, bestDist, checkSelPre, checkSelPost))
|
||||
{
|
||||
m_HoverXform = m_SelectedXform;
|
||||
bestIndex = int(ember->GetTotalXformIndex(m_SelectedXform));
|
||||
bestIndex = int(ember->GetTotalXformIndex(m_SelectedXform, forceFinal));
|
||||
}
|
||||
}
|
||||
|
||||
//Check all xforms.
|
||||
while (auto xform = ember->GetTotalXform(i))
|
||||
|
||||
while (auto xform = ember->GetTotalXform(i, forceFinal))
|
||||
{
|
||||
if (preAll || (pre && m_HoverXform == xform))//Only check pre affine if they are shown.
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user