--User changes

-Entering xaos cells will always select the entire cell to make editing easier.
 -Add radio buttons on the xaos tab to specify how pasting or duplicating xforms should preserve xaos.

--Bug fixes
 -The left header column in the xaos visualization table had somehow disappeared.

--Code changes
 -DoubleSpinBox now has a boolean which specifies whether it clears its selection on enter. Default true.
 -Make AddXformsWithXaos() be a static member of FractoriumEmberController for quicker build times.
 -Add new exmaple flames to package_linux.sh
This commit is contained in:
Person 2020-03-11 06:49:29 -07:00
parent 61dd5e6eeb
commit 18809e65aa
10 changed files with 221 additions and 83 deletions

View File

@ -10,6 +10,8 @@
namespace EmberCommon namespace EmberCommon
{ {
enum class eXaosPasteStyle : int { NONE, ZERO_TO_ONE, ZERO_TO_VALS, ONE_TO_VALS, VALS_TO_ONE };
/// <summary> /// <summary>
/// Derivation of the RenderCallback class to do custom printing action /// Derivation of the RenderCallback class to do custom printing action
/// whenever the progress function is internally called inside of Ember /// whenever the progress function is internally called inside of Ember
@ -869,43 +871,6 @@ static vector<const Variation<T>*> FindVarsWithout(const vector<const Variation<
return vec; return vec;
} }
/// <summary>
/// Add a vector of xforms to the passed in ember, and optionally preserve the xaos based on position.
/// </summary>
/// <param name="ember">The ember to add xforms to</param>
/// <param name="xforms">The vector of xforms to add</param>
/// <param name="preserveXaos">True to preserve xaos else false.</param>
template <typename T>
static void AddXformsWithXaos(Ember<T>& ember, std::vector<std::pair<Xform<T>, size_t>>& xforms, bool preserveXaos)
{
auto origXformCount = ember.XformCount();
for (auto& it : xforms)
ember.AddXform(it.first);
for (auto i = 0; i < ember.XformCount(); i++)
{
auto xf = ember.GetXform(i);
if (i < origXformCount)
{
for (auto j = 0; j < ember.XformCount(); j++)
if (j >= origXformCount)
xf->SetXaos(j, 0);
}
else
{
for (auto j = 0; j < ember.XformCount(); j++)
if (j < origXformCount)
xf->SetXaos(j, 0);
else if (!preserveXaos)
xf->SetXaos(j, 1);
else if (i - origXformCount < xforms.size())//Should never be out of bounds, but just to be safe.
xf->SetXaos(j, xforms[i - origXformCount].first.Xaos(j - origXformCount));
}
}
}
} }
/// <summary> /// <summary>

View File

@ -12,10 +12,11 @@ QTimer DoubleSpinBox::s_Timer;
/// <param name="p">The parent widget. Default: nullptr.</param> /// <param name="p">The parent widget. Default: nullptr.</param>
/// <param name="height">The height of the spin box. Default: 16.</param> /// <param name="height">The height of the spin box. Default: 16.</param>
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.</param> /// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.</param>
DoubleSpinBox::DoubleSpinBox(QWidget* p, int h, double step) DoubleSpinBox::DoubleSpinBox(QWidget* p, int h, double step, bool clearSel)
: QDoubleSpinBox(p) : QDoubleSpinBox(p)
{ {
m_DoubleClick = false; m_DoubleClick = false;
m_ClearSel = clearSel;
m_DoubleClickLowVal = 0; m_DoubleClickLowVal = 0;
m_DoubleClickNonZero = 0; m_DoubleClickNonZero = 0;
m_DoubleClickZero = 1; m_DoubleClickZero = 1;
@ -135,7 +136,8 @@ QLineEdit* DoubleSpinBox::lineEdit()
/// </summary> /// </summary>
void DoubleSpinBox::OnSpinBoxValueChanged(double) void DoubleSpinBox::OnSpinBoxValueChanged(double)
{ {
lineEdit()->deselect();//Gets rid of nasty "feature" that always has text selected. if (m_ClearSel)
lineEdit()->deselect();//Gets rid of nasty "feature" that always has text selected.
} }
/// <summary> /// <summary>

View File

@ -19,7 +19,7 @@ class DoubleSpinBox : public QDoubleSpinBox
Q_OBJECT Q_OBJECT
public: public:
explicit DoubleSpinBox(QWidget* parent = nullptr, int height = 16, double step = 0.05); explicit DoubleSpinBox(QWidget* parent = nullptr, int height = 16, double step = 0.05, bool clearsel = true);
virtual ~DoubleSpinBox() { } virtual ~DoubleSpinBox() { }
void SetValueStealth(double d); void SetValueStealth(double d);
void DoubleClick(bool b); void DoubleClick(bool b);
@ -45,6 +45,7 @@ protected:
virtual void leaveEvent(QEvent* e) override; virtual void leaveEvent(QEvent* e) override;
bool m_DoubleClick; bool m_DoubleClick;
bool m_ClearSel;
shared_ptr<FractoriumSettings> m_Settings; shared_ptr<FractoriumSettings> m_Settings;
private: private:

View File

@ -129,6 +129,9 @@ public:
bool DrawAllPost(); bool DrawAllPost();
bool LocalPivot(); bool LocalPivot();
//Xaos.
eXaosPasteStyle GetXaosPasteStyleType();
//Info. //Info.
void ReorderVariations(QTreeWidgetItem* item); void ReorderVariations(QTreeWidgetItem* item);
@ -144,7 +147,7 @@ public slots:
void OnActionCopyFlameInCurrentFile(bool checked); void OnActionCopyFlameInCurrentFile(bool checked);
void OnActionCreateReferenceFile(bool checked); void OnActionCreateReferenceFile(bool checked);
void OnActionOpen(bool checked); void OnActionOpen(bool checked);
void OnActionOpenExamples(bool checked); void OnActionOpenExamples(bool checked);
void OnActionSaveCurrentAsXml(bool checked); void OnActionSaveCurrentAsXml(bool checked);
void OnActionSaveEntireFileAsXml(bool checked); void OnActionSaveEntireFileAsXml(bool checked);
void OnActionSaveCurrentScreen(bool checked); void OnActionSaveCurrentScreen(bool checked);
@ -470,7 +473,7 @@ private:
void EnableRenderControls(bool enable); void EnableRenderControls(bool enable);
//Dialogs. //Dialogs.
QStringList SetupOpenXmlDialog(bool openExamples = false); QStringList SetupOpenXmlDialog(bool openExamples = false);
QString SetupSaveXmlDialog(const QString& defaultFilename); QString SetupSaveXmlDialog(const QString& defaultFilename);
QString SetupSaveImageDialog(const QString& defaultFilename); QString SetupSaveImageDialog(const QString& defaultFilename);
QString SetupSaveFolderDialog(); QString SetupSaveFolderDialog();

View File

@ -1867,7 +1867,7 @@
<rect> <rect>
<x>550</x> <x>550</x>
<y>0</y> <y>0</y>
<width>252</width> <width>310</width>
<height>881</height> <height>881</height>
</rect> </rect>
</property> </property>
@ -1879,8 +1879,8 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>252</width> <width>310</width>
<height>409</height> <height>428</height>
</size> </size>
</property> </property>
<property name="floating"> <property name="floating">
@ -1902,9 +1902,9 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0,0,0"> <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0,0,0,0">
<property name="spacing"> <property name="spacing">
<number>4</number> <number>1</number>
</property> </property>
<property name="leftMargin"> <property name="leftMargin">
<number>4</number> <number>4</number>
@ -2002,6 +2002,86 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QGroupBox" name="XaosPasteGroupBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="title">
<string>Paste Style</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QRadioButton" name="XaosPasteNoneRadio">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;All values in the new xaos rows and columns will be 1&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="XaosPaste0to1Radio">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;All values in the new xaos rows and columns before the bottom right square will be 0, and those in the square will be 1&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>0-&gt;1</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="XaosPaste0toValsRadio">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;All values in the new xaos rows and columns before the bottom right square will be 0, and those in the square will be the original xaos values starting from the top of the new xforms&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>0-&gt;Vals</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="XaosPaste1toValsRadio">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;All values in the new xaos rows and columns before the bottom right square will be 1, and those in the square will be the original xaos values starting from the top of the new xforms&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>1-&gt;Vals</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="XaosPasteValsTo1Radio">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;All values in the new xaos rows and columns before the bottom right square will be the original xaos values starting from the top of the new xforms, and those in the square will be 1&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Vals-&gt;1</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QTableView" name="XaosTableView"> <widget class="QTableView" name="XaosTableView">
<property name="sizePolicy"> <property name="sizePolicy">
@ -2226,7 +2306,7 @@
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>
<attribute name="verticalHeaderVisible"> <attribute name="verticalHeaderVisible">
<bool>false</bool> <bool>true</bool>
</attribute> </attribute>
<attribute name="verticalHeaderCascadingSectionResizes"> <attribute name="verticalHeaderCascadingSectionResizes">
<bool>false</bool> <bool>false</bool>
@ -2316,7 +2396,7 @@
<widget class="QDockWidget" name="PaletteDockWidget"> <widget class="QDockWidget" name="PaletteDockWidget">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>800</x> <x>860</x>
<y>10</y> <y>10</y>
<width>295</width> <width>295</width>
<height>700</height> <height>700</height>

View File

@ -489,6 +489,7 @@ public:
void FillWithXform(Xform<T>* xform); void FillWithXform(Xform<T>* xform);
Xform<T>* CurrentXform(); Xform<T>* CurrentXform();
void UpdateXform(std::function<void(Xform<T>*, size_t, size_t)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER, size_t index = 0); void UpdateXform(std::function<void(Xform<T>*, size_t, size_t)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER, size_t index = 0);
static void AddXformsWithXaos(Ember<T>& ember, std::vector<std::pair<Xform<T>, size_t>>& xforms, bool preserveXaos, eXaosPasteStyle pastestyle);
//Xforms Affine. //Xforms Affine.
virtual void AffineSetHelper(double d, int index, bool pre) override; virtual void AffineSetHelper(double d, int index, bool pre) override;

View File

@ -812,7 +812,7 @@ void FractoriumEmberController<T>::PasteSelectedXforms()
{ {
Update([&]() Update([&]()
{ {
AddXformsWithXaos(m_Ember, m_CopiedXforms, true); AddXformsWithXaos(m_Ember, m_CopiedXforms, true, m_Fractorium->GetXaosPasteStyleType());
if (!m_CopiedFinalXform.Empty()) if (!m_CopiedFinalXform.Empty())
m_Ember.SetFinalXform(m_CopiedFinalXform); m_Ember.SetFinalXform(m_CopiedFinalXform);

View File

@ -11,7 +11,7 @@ void Fractorium::InitXaosUI()
int spinHeight = 20; int spinHeight = 20;
ui.XaosTableView->verticalHeader()->setSectionsClickable(true); ui.XaosTableView->verticalHeader()->setSectionsClickable(true);
ui.XaosTableView->horizontalHeader()->setSectionsClickable(true); ui.XaosTableView->horizontalHeader()->setSectionsClickable(true);
m_XaosSpinBox = new DoubleSpinBox(nullptr, spinHeight, 0.1); m_XaosSpinBox = new DoubleSpinBox(nullptr, spinHeight, 0.1, false);
m_XaosSpinBox->DoubleClick(true); m_XaosSpinBox->DoubleClick(true);
m_XaosSpinBox->DoubleClickZero(1); m_XaosSpinBox->DoubleClickZero(1);
m_XaosSpinBox->DoubleClickNonZero(0); m_XaosSpinBox->DoubleClickNonZero(0);
@ -265,7 +265,7 @@ void FractoriumEmberController<T>::AddLayer(int xforms)
Update([&] Update([&]
{ {
std::vector<std::pair<Xform<T>, size_t>> vec(xforms); std::vector<std::pair<Xform<T>, size_t>> vec(xforms);
AddXformsWithXaos(m_Ember, vec, false); AddXformsWithXaos(m_Ember, vec, false, eXaosPasteStyle::ZERO_TO_ONE);
}); });
FillXforms(); FillXforms();
@ -371,6 +371,26 @@ void Fractorium::OnXaosVScrollValueChanged(int value)
ui.XaosAppliedTableView->verticalScrollBar()->setValue(value); ui.XaosAppliedTableView->verticalScrollBar()->setValue(value);
} }
/// <summary>
/// Get an enum value corresponding to the currently selected xaos pasting mode.
/// </summary>
/// <returns>The xaos pasting mode enum</returns>
eXaosPasteStyle Fractorium::GetXaosPasteStyleType()
{
if (ui.XaosPasteNoneRadio->isChecked())
return eXaosPasteStyle::NONE;
else if (ui.XaosPaste0to1Radio->isChecked())
return eXaosPasteStyle::ZERO_TO_ONE;
else if (ui.XaosPaste0toValsRadio->isChecked())
return eXaosPasteStyle::ZERO_TO_VALS;
else if (ui.XaosPaste1toValsRadio->isChecked())
return eXaosPasteStyle::ONE_TO_VALS;
else if (ui.XaosPasteValsTo1Radio->isChecked())
return eXaosPasteStyle::VALS_TO_ONE;
else
return eXaosPasteStyle::NONE;
}
template class FractoriumEmberController<float>; template class FractoriumEmberController<float>;
#ifdef DO_DOUBLE #ifdef DO_DOUBLE

View File

@ -206,6 +206,94 @@ void FractoriumEmberController<T>::AddLinkedXform()
void Fractorium::OnAddLinkedXformButtonClicked(bool checked) { m_Controller->AddLinkedXform(); } void Fractorium::OnAddLinkedXformButtonClicked(bool checked) { m_Controller->AddLinkedXform(); }
/// <summary>
/// Add a vector of xforms to the passed in ember, and optionally preserve the xaos based on position.
/// </summary>
/// <param name="ember">The ember to add xforms to</param>
/// <param name="xforms">The vector of xforms to add</param>
/// <param name="preserveXaos">True to preserve xaos else false.</param>
/// <param name="eXaosPasteStyle">The method which governs how the copying of xaos values is handles</param>
template <typename T>
void FractoriumEmberController<T>::AddXformsWithXaos(Ember<T>& ember, std::vector<std::pair<Xform<T>, size_t>>& xforms, bool preserveXaos, eXaosPasteStyle pastestyle)
{
if (ember.XaosPresent())
{
auto oldxfcount = ember.XformCount();
for (auto& it : xforms)
{
ember.AddXform(it.first);
auto newxfcount = ember.XformCount() - 1;
auto* newxform = ember.GetXform(newxfcount);
for (size_t i = 0; i < oldxfcount; i++)
{
if (auto xform = ember.GetXform(i))
{
switch (pastestyle)
{
case EmberCommon::eXaosPasteStyle::NONE:
newxform->SetXaos(i, 1);
xform->SetXaos(newxfcount, 1);
break;
case EmberCommon::eXaosPasteStyle::ZERO_TO_ONE:
case EmberCommon::eXaosPasteStyle::ZERO_TO_VALS:
newxform->SetXaos(i, 0);
xform->SetXaos(newxfcount, 0);
break;
case EmberCommon::eXaosPasteStyle::ONE_TO_VALS:
newxform->SetXaos(i, 1);
xform->SetXaos(newxfcount, 1);
break;
case EmberCommon::eXaosPasteStyle::VALS_TO_ONE:
newxform->SetXaos(i, it.first.Xaos(i));
xform->SetXaos(newxfcount, xform->Xaos(it.second));
break;
default:
break;
}
}
}
}
for (size_t i = oldxfcount; i < ember.XformCount(); i++)
{
if (auto xform = ember.GetXform(i))
{
for (size_t j = oldxfcount; j < ember.XformCount(); j++)
{
switch (pastestyle)
{
case EmberCommon::eXaosPasteStyle::NONE:
case EmberCommon::eXaosPasteStyle::ZERO_TO_ONE:
xform->SetXaos(j, 1);
break;
case EmberCommon::eXaosPasteStyle::ZERO_TO_VALS:
case EmberCommon::eXaosPasteStyle::ONE_TO_VALS:
xform->SetXaos(j, xforms[i - oldxfcount].first.Xaos(j - oldxfcount));
break;
case EmberCommon::eXaosPasteStyle::VALS_TO_ONE:
xform->SetXaos(j, 1);
break;
default:
break;
}
}
}
}
}
else
for (auto& it : xforms)
ember.AddXform(it.first);
}
/// <summary> /// <summary>
/// Duplicate the specified xforms in the current ember, and set the last one as the current xform. /// Duplicate the specified xforms in the current ember, and set the last one as the current xform.
/// If xaos is present in the ember, the duplicated xforms will be added with xaos preserved, else they'll just be added normally. /// If xaos is present in the ember, the duplicated xforms will be added with xaos preserved, else they'll just be added normally.
@ -227,37 +315,7 @@ void FractoriumEmberController<T>::DuplicateXform()
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL, false); }, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL, false);
Update([&]() Update([&]()
{ {
if (m_Ember.XaosPresent()) AddXformsWithXaos(m_Ember, vec, true, m_Fractorium->GetXaosPasteStyleType());
{
if (!ctrl)
{
auto oldxfcount = m_Ember.XformCount();
for (auto& it : vec)
{
m_Ember.AddXform(it.first);
auto newxfcount = m_Ember.XformCount() - 1;
auto* newxform = m_Ember.GetXform(newxfcount);
for (size_t i = 0; i < oldxfcount; i++)
{
if (auto xform = m_Ember.GetXform(i))
{
newxform->SetXaos(i, it.first.Xaos(i));
xform->SetXaos(newxfcount, xform->Xaos(it.second));
}
}
}
}
else
{
AddXformsWithXaos(m_Ember, vec, true);
}
}
else
for (auto& it : vec)
m_Ember.AddXform(it.first);
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 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. FillXforms(index);//Handles xaos.
}); });

View File

@ -123,6 +123,14 @@ tar --exclude='package-linux.sh' \
./Data/dark_linux.qss \ ./Data/dark_linux.qss \
./Data/lightdark.qss \ ./Data/lightdark.qss \
./Data/uranium.qss \ ./Data/uranium.qss \
./Data/examples/b33rheart_examples.flame \
./Data/examples/b33rheart_sierpinski.flame \
./Data/examples/pillemaster_hexagonal_tilings.flame \
./Data/examples/plangkye_examples.flame \
./Data/examples/tatasz_examples.flame \
./Data/examples/tatasz_substitution.flame \
./Data/examples/triptychaos_examples \
./Data/examples/tyrantwave_base_forms.flame \
. .
[ $? -ne 0 ] && echo "Tar command failed." && exit 2 [ $? -ne 0 ] && echo "Tar command failed." && exit 2