--Bug fixes

-Add support for Chaotica files which specify xform weight as "Base weight" instead of "base_weight".
 -Fix bug where Fractorium would crash when a new file was dragged in while previews were still rendering.
  --This was done by changing the TreeItemChanged() events in the library tab use a direct connection rather than a queued connection.
  --This obviated the need for QCoreApplication::processEvents() calls in the library tree code.
 -Fix bug where renaming a flame within a file, then tabbing away did not commit the name change.

--Code changes
 -Clean up some warnings about const variables in the latest version of Visual Studio 2019.
 -Upgrade installer to latest update of Visual Studio 2019.
This commit is contained in:
Person 2020-07-14 17:45:07 -07:00
parent a07955d12e
commit c0a1395a2b
5 changed files with 91 additions and 85 deletions

View File

@ -168,19 +168,19 @@
<File Id="tbb.dll" Source="$(var.SolutionDir)..\..\..\Bin\$(var.Platform)\Release\tbb.dll" KeyPath="yes" Checksum="yes" ProcessorArchitecture="x64" ReadOnly="yes"/> <File Id="tbb.dll" Source="$(var.SolutionDir)..\..\..\Bin\$(var.Platform)\Release\tbb.dll" KeyPath="yes" Checksum="yes" ProcessorArchitecture="x64" ReadOnly="yes"/>
</Component> </Component>
<Component Id="msvcp140.dll" Guid="8f1ffde7-c1bd-45fb-8bc8-26dde552eafd"> <Component Id="msvcp140.dll" Guid="8f1ffde7-c1bd-45fb-8bc8-26dde552eafd">
<File Id="msvcp140.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.25.28508\x64\Microsoft.VC142.CRT\msvcp140.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/> <File Id="msvcp140.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.26.28720\x64\Microsoft.VC142.CRT\msvcp140.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/>
</Component> </Component>
<Component Id="vcruntime140.dll" Guid="50c9bc27-c547-4a03-9f6c-cd416f449dd8"> <Component Id="vcruntime140.dll" Guid="50c9bc27-c547-4a03-9f6c-cd416f449dd8">
<File Id="vcruntime140.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.25.28508\x64\Microsoft.VC142.CRT\vcruntime140.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/> <File Id="vcruntime140.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.26.28720\x64\Microsoft.VC142.CRT\vcruntime140.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/>
</Component> </Component>
<Component Id="vcruntime140_1.dll" Guid="a02507f8-326b-45b2-b734-e5091921559f"> <Component Id="vcruntime140_1.dll" Guid="a02507f8-326b-45b2-b734-e5091921559f">
<File Id="vcruntime140_1.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.25.28508\x64\Microsoft.VC142.CRT\vcruntime140_1.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/> <File Id="vcruntime140_1.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.26.28720\x64\Microsoft.VC142.CRT\vcruntime140_1.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/>
</Component> </Component>
<Component Id="vccorlib140.dll" Guid="affe33e7-1e64-4bb0-a062-2b56f77459b4"> <Component Id="vccorlib140.dll" Guid="affe33e7-1e64-4bb0-a062-2b56f77459b4">
<File Id="vccorlib140.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.25.28508\x64\Microsoft.VC142.CRT\vccorlib140.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/> <File Id="vccorlib140.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.26.28720\x64\Microsoft.VC142.CRT\vccorlib140.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/>
</Component> </Component>
<Component Id="concrt140.dll" Guid="7fb716a1-1b4f-42fb-89c7-4d216ebd6e2e"> <Component Id="concrt140.dll" Guid="7fb716a1-1b4f-42fb-89c7-4d216ebd6e2e">
<File Id="concrt140.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.25.28508\x64\Microsoft.VC142.CRT\concrt140.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/> <File Id="concrt140.dll" Source="$(var.DevEnvDir)..\..\VC\Redist\MSVC\14.26.28720\x64\Microsoft.VC142.CRT\concrt140.dll" KeyPath="yes" Checksum="yes" ReadOnly="yes"/>
</Component> </Component>
<Component Id="flam3palettes.xml" Guid="d3adb0bb-14ef-4923-99d9-a5784b7ef04e"> <Component Id="flam3palettes.xml" Guid="d3adb0bb-14ef-4923-99d9-a5784b7ef04e">
<File Id="flam3palettes.xml" Source="$(var.SolutionDir)..\..\..\Data\flam3-palettes.xml" KeyPath="yes" Checksum="yes" ReadOnly="yes"/> <File Id="flam3palettes.xml" Source="$(var.SolutionDir)..\..\..\Data\flam3-palettes.xml" KeyPath="yes" Checksum="yes" ReadOnly="yes"/>

View File

@ -2395,8 +2395,8 @@ public:
{ {
m_Ang = M_2PI / Zeps(m_Divisor); m_Ang = M_2PI / Zeps(m_Divisor);
T a = std::atan2((m_D < 0 ? -std::log(-m_D) : std::log(m_D)) * m_R, M_2PI); T a = std::atan2((m_D < 0 ? -std::log(-m_D) : std::log(m_D)) * m_R, M_2PI);
m_PrecalcC = std::cos(a) * m_R * std::cos(a) / m_Divisor; m_PrecalcC = std::cos(a) * m_R * std::cos(a) / Zeps(m_Divisor);
m_PrecalcD = std::cos(a) * m_R * std::sin(a) / m_Divisor; m_PrecalcD = std::cos(a) * m_R * std::sin(a) / Zeps(m_Divisor);
m_HalfC = m_PrecalcC / 2; m_HalfC = m_PrecalcC / 2;
m_HalfD = m_PrecalcD / 2; m_HalfD = m_PrecalcD / 2;
m_Coeff = m_PrecalcD == 0 ? 0 : T(-0.095) * m_Spread / m_PrecalcD; m_Coeff = m_PrecalcD == 0 ? 0 : T(-0.095) * m_Spread / m_PrecalcD;

View File

@ -1198,7 +1198,15 @@ bool XmlToEmber<T>::ParseEmberElementFromChaos(xmlNode* emberNode, Ember<T>& cur
std::string periterweights; std::string periterweights;
if (auto baseWeightChildNode = GetChildNode(weightsChildNode, "base_weight")) if (auto baseWeightChildNode = GetChildNode(weightsChildNode, "base_weight"))
if (ParseAndAssignContent(baseWeightChildNode, "name", "base_weight", weight)) { xf.m_Weight = weight; } {
if (ParseAndAssignContent(baseWeightChildNode, "name", "base_weight", weight))
xf.m_Weight = weight;
}
else if (auto baseWeightChildNode = GetChildNode(weightsChildNode, "Base weight"))
{
if (ParseAndAssignContent(baseWeightChildNode, "name", "Base weight", weight))
xf.m_Weight = weight;
}
if (auto periterweightsChildNode = GetChildNode(weightsChildNode, "per_iterator_weights")) if (auto periterweightsChildNode = GetChildNode(weightsChildNode, "per_iterator_weights"))
{ {

View File

@ -382,8 +382,8 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
{ {
auto combo = ui.CurrentXformCombo; auto combo = ui.CurrentXformCombo;
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
int times = 3; const int times = 3;
int ftimes = 2; const int ftimes = 2;
if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F32) if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F32)
{ {
@ -391,7 +391,7 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
if (fcount >= ftimes) if (fcount >= ftimes)
{ {
int val = ke->key() - (int)Qt::Key_F1; const int val = ke->key() - (int)Qt::Key_F1;
if (val < combo->count()) if (val < combo->count())
combo->setCurrentIndex(val); combo->setCurrentIndex(val);
@ -417,10 +417,10 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
} }
else if (o == this) else if (o == this)
{ {
auto focusedctrlEdit = dynamic_cast<QLineEdit*>(this->focusWidget()); const auto focusedctrlEdit = dynamic_cast<QLineEdit*>(this->focusWidget());
auto focusedctrlSpin = dynamic_cast<QSpinBox*>(this->focusWidget()); const auto focusedctrlSpin = dynamic_cast<QSpinBox*>(this->focusWidget());
auto focusedctrlDblSpin = dynamic_cast<QDoubleSpinBox*>(this->focusWidget()); const auto focusedctrlDblSpin = dynamic_cast<QDoubleSpinBox*>(this->focusWidget());
auto focusedctrlCombo = dynamic_cast<QComboBox*>(this->focusWidget()); const auto focusedctrlCombo = dynamic_cast<QComboBox*>(this->focusWidget());
if (!focusedctrlEdit && if (!focusedctrlEdit &&
!focusedctrlSpin && !focusedctrlSpin &&
@ -434,11 +434,11 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
double zoom = 1; double zoom = 1;
double rot = 1; double rot = 1;
double grow = 0.01; double grow = 0.01;
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); const bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier); const bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
bool pre = true; bool pre = true;
if (auto r = m_Controller->Renderer()) if (const auto r = m_Controller->Renderer())
{ {
hdist = std::abs(r->UpperRightX() - r->LowerLeftX()) * 0.01 * m_Controller->AffineScaleLockedToCurrent(); hdist = std::abs(r->UpperRightX() - r->LowerLeftX()) * 0.01 * m_Controller->AffineScaleLockedToCurrent();
vdist = std::abs(r->UpperRightY() - r->LowerLeftY()) * 0.01 * m_Controller->AffineScaleLockedToCurrent(); vdist = std::abs(r->UpperRightY() - r->LowerLeftY()) * 0.01 * m_Controller->AffineScaleLockedToCurrent();

View File

@ -7,10 +7,11 @@
void Fractorium::InitLibraryUI() void Fractorium::InitLibraryUI()
{ {
ui.LibraryTree->SetMainWindow(this); ui.LibraryTree->SetMainWindow(this);
connect(ui.LibraryTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemChanged(QTreeWidgetItem*, int)), Qt::QueuedConnection); //Making the TreeItemChanged() events use a direct connection is absolutely critical.
connect(ui.LibraryTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemChanged(QTreeWidgetItem*, int)), Qt::DirectConnection);
connect(ui.LibraryTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection); connect(ui.LibraryTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection);
connect(ui.LibraryTree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection); connect(ui.LibraryTree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection);
connect(ui.SequenceTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnSequenceTreeItemChanged(QTreeWidgetItem*, int)), Qt::QueuedConnection); connect(ui.SequenceTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnSequenceTreeItemChanged(QTreeWidgetItem*, int)), Qt::DirectConnection);
connect(ui.SequenceStartPreviewsButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceStartPreviewsButtonClicked(bool)), Qt::QueuedConnection); connect(ui.SequenceStartPreviewsButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceStartPreviewsButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.SequenceStopPreviewsButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceStopPreviewsButtonClicked(bool)), Qt::QueuedConnection); connect(ui.SequenceStopPreviewsButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceStopPreviewsButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.SequenceAllButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceAllButtonClicked(bool)), Qt::QueuedConnection); connect(ui.SequenceAllButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceAllButtonClicked(bool)), Qt::QueuedConnection);
@ -68,7 +69,7 @@ void Fractorium::InitLibraryUI()
/// <param name="index">The 0-based index of the item in the library tree to select</param> /// <param name="index">The 0-based index of the item in the library tree to select</param>
void Fractorium::SelectLibraryItem(size_t index) void Fractorium::SelectLibraryItem(size_t index)
{ {
if (auto top = ui.LibraryTree->topLevelItem(0)) if (const auto top = ui.LibraryTree->topLevelItem(0))
{ {
for (int i = 0; i < top->childCount(); i++) for (int i = 0; i < top->childCount(); i++)
{ {
@ -89,10 +90,10 @@ vector<pair<size_t, QTreeWidgetItem*>> Fractorium::GetCurrentEmberIndex()
{ {
int index = 0; int index = 0;
QTreeWidgetItem* item = nullptr; QTreeWidgetItem* item = nullptr;
auto tree = ui.LibraryTree; const auto tree = ui.LibraryTree;
vector<pair<size_t, QTreeWidgetItem*>> v; vector<pair<size_t, QTreeWidgetItem*>> v;
if (auto top = tree->topLevelItem(0)) if (const auto top = tree->topLevelItem(0))
{ {
for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers. for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers.
{ {
@ -117,7 +118,7 @@ vector<pair<size_t, QTreeWidgetItem*>> Fractorium::GetCurrentEmberIndex()
/// <param name="h">The height of the bitmap</param> /// <param name="h">The height of the bitmap</param>
void Fractorium::SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vv4F& v, uint w, uint h) void Fractorium::SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vv4F& v, uint w, uint h)
{ {
m_PreviewVec.resize(w * h * 4); m_PreviewVec.resize(size_t(w) * size_t(h) * 4);
Rgba32ToRgba8(v.data(), m_PreviewVec.data(), w, h, m_Settings->Transparency()); Rgba32ToRgba8(v.data(), m_PreviewVec.data(), w, h, m_Settings->Transparency());
item->SetImage(m_PreviewVec, w, h); item->SetImage(m_PreviewVec, w, h);
} }
@ -131,9 +132,9 @@ template <typename T>
void FractoriumEmberController<T>::SyncLibrary(eLibraryUpdate update) void FractoriumEmberController<T>::SyncLibrary(eLibraryUpdate update)
{ {
auto it = m_EmberFile.m_Embers.begin(); auto it = m_EmberFile.m_Embers.begin();
auto tree = m_Fractorium->ui.LibraryTree; const auto tree = m_Fractorium->ui.LibraryTree;
if (auto top = tree->topLevelItem(0)) if (const auto top = tree->topLevelItem(0))
{ {
for (int i = 0; i < top->childCount() && it != m_EmberFile.m_Embers.end(); ++i, ++it)//Iterate through all of the children, which will represent the open embers. for (int i = 0; i < top->childCount() && it != m_EmberFile.m_Embers.end(); ++i, ++it)//Iterate through all of the children, which will represent the open embers.
{ {
@ -166,11 +167,10 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
{ {
uint size = 64; uint size = 64;
uint i = 0; uint i = 0;
auto tree = m_Fractorium->ui.LibraryTree; const auto tree = m_Fractorium->ui.LibraryTree;
vector<byte> v(size * size * 4); vector<byte> v(size * size * 4);
StopAllPreviewRenderers(); StopAllPreviewRenderers();
tree->clear(); tree->clear();
QCoreApplication::processEvents();
auto fileItem = new QTreeWidgetItem(tree); auto fileItem = new QTreeWidgetItem(tree);
QFileInfo info(m_EmberFile.m_Filename); QFileInfo info(m_EmberFile.m_Filename);
fileItem->setText(0, info.fileName()); fileItem->setText(0, info.fileName());
@ -205,13 +205,13 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
template <typename T> template <typename T>
void FractoriumEmberController<T>::UpdateLibraryTree() void FractoriumEmberController<T>::UpdateLibraryTree()
{ {
uint size = 64; const uint size = 64;
vector<byte> v(size * size * 4); vector<byte> v(size * size * 4);
auto tree = m_Fractorium->ui.LibraryTree; const auto tree = m_Fractorium->ui.LibraryTree;
if (auto top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
{ {
int origChildCount = top->childCount(); const int origChildCount = top->childCount();
int i = origChildCount; int i = origChildCount;
for (auto it = Advance(m_EmberFile.m_Embers.begin(), i); it != m_EmberFile.m_Embers.end(); ++it) for (auto it = Advance(m_EmberFile.m_Embers.begin(), i); it != m_EmberFile.m_Embers.end(); ++it)
@ -249,25 +249,24 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
{ {
try try
{ {
auto tree = m_Fractorium->ui.LibraryTree; const auto tree = m_Fractorium->ui.LibraryTree;
if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item)) if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item))
{ {
if (!emberItem->isSelected())//Checking/unchecking other items shouldn't perform the processing below. auto oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name.
auto newName = emberItem->text(0).toStdString();
//Checking/unchecking other items shouldn't perform the processing below.
//If nothing changed, nothing to do.
if (!emberItem->isSelected() && newName == oldName)
return; return;
if (emberItem->text(0).isEmpty())//Prevent empty string. if (newName.empty())//Prevent empty string.
{ {
emberItem->UpdateEditText(); emberItem->UpdateEditText();
return; return;
} }
string oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name.
string newName = emberItem->text(0).toStdString();
if (oldName == newName)//If nothing changed, nothing to do.
return;
emberItem->UpdateEmberName();//Copy edit text to the ember's name variable. emberItem->UpdateEmberName();//Copy edit text to the ember's name variable.
m_EmberFile.MakeNamesUnique();//Ensure all names remain unique. m_EmberFile.MakeNamesUnique();//Ensure all names remain unique.
SyncLibrary(eLibraryUpdate::NAME);//Copy all ember names to the tree items since some might have changed to be made unique. SyncLibrary(eLibraryUpdate::NAME);//Copy all ember names to the tree items since some might have changed to be made unique.
@ -281,7 +280,7 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
} }
else if (auto parentItem = dynamic_cast<QTreeWidgetItem*>(item)) else if (auto parentItem = dynamic_cast<QTreeWidgetItem*>(item))
{ {
QString text = parentItem->text(0); auto text = parentItem->text(0);
if (text != "") if (text != "")
{ {
@ -298,7 +297,7 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
void Fractorium::OnEmberTreeItemChanged(QTreeWidgetItem* item, int col) void Fractorium::OnEmberTreeItemChanged(QTreeWidgetItem* item, int col)
{ {
if (ui.LibraryTree->topLevelItemCount())//This can sometimes be spurriously called even when the tree is empty. if (item && ui.LibraryTree->topLevelItemCount())//This can sometimes be spurriously called even when the tree is empty.
m_Controller->EmberTreeItemChanged(item, col); m_Controller->EmberTreeItemChanged(item, col);
} }
@ -334,9 +333,9 @@ template <typename T>
void FractoriumEmberController<T>::MoveLibraryItems(const QModelIndexList& items, int destRow) void FractoriumEmberController<T>::MoveLibraryItems(const QModelIndexList& items, int destRow)
{ {
int i = 0; int i = 0;
auto startRow = items[0].row(); const auto startRow = items[0].row();
auto tree = m_Fractorium->ui.LibraryTree; const auto tree = m_Fractorium->ui.LibraryTree;
auto top = tree->topLevelItem(0); const auto top = tree->topLevelItem(0);
list<string> names; list<string> names;
for (auto& item : items) for (auto& item : items)
@ -344,7 +343,7 @@ void FractoriumEmberController<T>::MoveLibraryItems(const QModelIndexList& items
names.push_back(temp->m_Name); names.push_back(temp->m_Name);
auto b = m_EmberFile.m_Embers.begin(); auto b = m_EmberFile.m_Embers.begin();
auto result = Gather(b, m_EmberFile.m_Embers.end(), Advance(b, destRow), [&](const Ember<T>& ember) const auto result = Gather(b, m_EmberFile.m_Embers.end(), Advance(b, destRow), [&](const Ember<T>& ember)
{ {
auto position = std::find(names.begin(), names.end(), ember.m_Name); auto position = std::find(names.begin(), names.end(), ember.m_Name);
@ -387,7 +386,7 @@ void FractoriumEmberController<T>::Delete(const vector<pair<size_t, QTreeWidgetI
} }
//Select the next item in the tree closest to the last one that was deleted. //Select the next item in the tree closest to the last one that was deleted.
if (auto top = m_Fractorium->ui.LibraryTree->topLevelItem(0)) if (const auto top = m_Fractorium->ui.LibraryTree->topLevelItem(0))
{ {
last = std::min<uint>(top->childCount() - 1, last); last = std::min<uint>(top->childCount() - 1, last);
@ -421,9 +420,9 @@ void FractoriumEmberController<T>::RenderPreviews(QTreeWidget* tree, TreePreview
if (start == UINT_MAX && end == UINT_MAX) if (start == UINT_MAX && end == UINT_MAX)
{ {
if (auto top = tree->topLevelItem(0)) if (const auto top = tree->topLevelItem(0))
{ {
int childCount = top->childCount(); const auto childCount = top->childCount();
vector<byte> emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 4); vector<byte> emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 4);
for (int i = 0; i < childCount; i++) for (int i = 0; i < childCount; i++)
@ -469,13 +468,12 @@ void FractoriumEmberController<T>::StopAllPreviewRenderers()
template <typename T> template <typename T>
void FractoriumEmberController<T>::FillSequenceTree() void FractoriumEmberController<T>::FillSequenceTree()
{ {
uint size = 64; const uint size = 64;
uint i = 0; uint i = 0;
auto tree = m_Fractorium->ui.SequenceTree; const auto tree = m_Fractorium->ui.SequenceTree;
vector<byte> v(size * size * 4); vector<byte> v(size * size * 4);
m_SequencePreviewRenderer->Stop(); m_SequencePreviewRenderer->Stop();
tree->clear(); tree->clear();
QCoreApplication::processEvents();//Having to flush events is usually a sign of poor design. However, in this case, it's critical to have this here, else rapid button clicks will crash.
auto fileItem = new QTreeWidgetItem(tree); auto fileItem = new QTreeWidgetItem(tree);
QFileInfo info(m_SequenceFile.m_Filename); QFileInfo info(m_SequenceFile.m_Filename);
fileItem->setText(0, info.fileName()); fileItem->setText(0, info.fileName());
@ -512,7 +510,7 @@ void FractoriumEmberController<T>::SequenceTreeItemChanged(QTreeWidgetItem* item
{ {
if (item == m_Fractorium->ui.SequenceTree->topLevelItem(0)) if (item == m_Fractorium->ui.SequenceTree->topLevelItem(0))
{ {
QString text = item->text(0); auto text = item->text(0);
if (text != "") if (text != "")
m_SequenceFile.m_Filename = text; m_SequenceFile.m_Filename = text;
@ -521,7 +519,7 @@ void FractoriumEmberController<T>::SequenceTreeItemChanged(QTreeWidgetItem* item
void Fractorium::OnSequenceTreeItemChanged(QTreeWidgetItem* item, int col) void Fractorium::OnSequenceTreeItemChanged(QTreeWidgetItem* item, int col)
{ {
if (ui.SequenceTree->topLevelItemCount()) if (item && ui.SequenceTree->topLevelItemCount())
m_Controller->SequenceTreeItemChanged(item, col); m_Controller->SequenceTreeItemChanged(item, col);
} }
@ -549,9 +547,9 @@ void Fractorium::OnSequenceStopPreviewsButtonClicked(bool checked) { m_Controlle
/// </summary> /// </summary>
void Fractorium::SyncFileCountToSequenceCount() void Fractorium::SyncFileCountToSequenceCount()
{ {
if (auto top = ui.LibraryTree->topLevelItem(0)) if (const auto top = ui.LibraryTree->topLevelItem(0))
{ {
int count = top->childCount() - 1; const int count = top->childCount() - 1;
ui.LibraryTree->headerItem()->setText(0, "Current Flame File (" + QString::number(top->childCount()) + ")"); ui.LibraryTree->headerItem()->setText(0, "Current Flame File (" + QString::number(top->childCount()) + ")");
ui.SequenceStartFlameSpinBox->setMinimum(0); ui.SequenceStartFlameSpinBox->setMinimum(0);
ui.SequenceStartFlameSpinBox->setMaximum(count); ui.SequenceStartFlameSpinBox->setMaximum(count);
@ -581,33 +579,33 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked()
auto& ui = m_Fractorium->ui; auto& ui = m_Fractorium->ui;
auto s = m_Fractorium->m_Settings; auto s = m_Fractorium->m_Settings;
//Bools for determining whether to use hard coded vs. random values. //Bools for determining whether to use hard coded vs. random values.
bool randStagger = ui.SequenceRandomizeStaggerCheckBox->isChecked(); const bool randStagger = ui.SequenceRandomizeStaggerCheckBox->isChecked();
bool randFramesRot = ui.SequenceRandomizeFramesPerRotCheckBox->isChecked(); const bool randFramesRot = ui.SequenceRandomizeFramesPerRotCheckBox->isChecked();
bool randRot = ui.SequenceRandomizeRotationsCheckBox->isChecked(); const bool randRot = ui.SequenceRandomizeRotationsCheckBox->isChecked();
bool randBlend = ui.SequenceRandomizeBlendFramesCheckBox->isChecked(); const bool randBlend = ui.SequenceRandomizeBlendFramesCheckBox->isChecked();
bool randBlendRot = ui.SequenceRandomizeRotationsPerBlendCheckBox->isChecked(); const bool randBlendRot = ui.SequenceRandomizeRotationsPerBlendCheckBox->isChecked();
//The direction to rotate the loops. //The direction to rotate the loops.
bool loopsCw = ui.SequenceRotationsCWCheckBox->isChecked(); const bool loopsCw = ui.SequenceRotationsCWCheckBox->isChecked();
bool loopsBlendCw = ui.SequenceRotationsPerBlendCWCheckBox->isChecked(); const bool loopsBlendCw = ui.SequenceRotationsPerBlendCWCheckBox->isChecked();
//Whether to stagger, default is 1 which means no stagger. //Whether to stagger, default is 1 which means no stagger.
double stagger = ui.SequenceStaggerSpinBox->value(); const double stagger = ui.SequenceStaggerSpinBox->value();
double staggerMax = ui.SequenceRandomStaggerMaxSpinBox->value(); const double staggerMax = ui.SequenceRandomStaggerMaxSpinBox->value();
//Rotations on keyframes. //Rotations on keyframes.
double rots = ui.SequenceRotationsSpinBox->value(); const double rots = ui.SequenceRotationsSpinBox->value();
double rotsMax = ui.SequenceRandomRotationsMaxSpinBox->value(); const double rotsMax = ui.SequenceRandomRotationsMaxSpinBox->value();
//Number of frames it takes to rotate a keyframe. //Number of frames it takes to rotate a keyframe.
int framesPerRot = ui.SequenceFramesPerRotSpinBox->value(); const int framesPerRot = ui.SequenceFramesPerRotSpinBox->value();
int framesPerRotMax = ui.SequenceRandomFramesPerRotMaxSpinBox->value(); const int framesPerRotMax = ui.SequenceRandomFramesPerRotMaxSpinBox->value();
//Number of frames it takes to interpolate. //Number of frames it takes to interpolate.
int framesBlend = ui.SequenceBlendFramesSpinBox->value(); const int framesBlend = ui.SequenceBlendFramesSpinBox->value();
int framesBlendMax = ui.SequenceRandomBlendMaxFramesSpinBox->value(); const int framesBlendMax = ui.SequenceRandomBlendMaxFramesSpinBox->value();
//Number of rotations performed during interpolation. //Number of rotations performed during interpolation.
int rotsPerBlend = ui.SequenceRotationsPerBlendSpinBox->value(); const int rotsPerBlend = ui.SequenceRotationsPerBlendSpinBox->value();
int rotsPerBlendMax = ui.SequenceRotationsPerBlendMaxSpinBox->value(); const int rotsPerBlendMax = ui.SequenceRotationsPerBlendMaxSpinBox->value();
size_t start = ui.SequenceStartFlameSpinBox->value(); const size_t start = ui.SequenceStartFlameSpinBox->value();
size_t stop = ui.SequenceStopFlameSpinBox->value(); const size_t stop = ui.SequenceStopFlameSpinBox->value();
size_t startCount = ui.SequenceStartCountSpinBox->value(); const size_t startCount = ui.SequenceStartCountSpinBox->value();
size_t keyFrames = (stop - start) + 1; const size_t keyFrames = (stop - start) + 1;
size_t frameCount = 0; size_t frameCount = 0;
double frames = 0; double frames = 0;
vector<pair<size_t, size_t>> devices;//Dummy. vector<pair<size_t, size_t>> devices;//Dummy.
@ -674,18 +672,18 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked()
double blend; double blend;
size_t frame; size_t frame;
Ember<T> embers[2];//Spin needs contiguous array below, and this will also get modified, so a copy is needed to avoid modifying the embers in the original file. Ember<T> embers[2];//Spin needs contiguous array below, and this will also get modified, so a copy is needed to avoid modifying the embers in the original file.
auto padding = streamsize(std::log10(frames)) + 1; const auto padding = streamsize(std::log10(frames)) + 1;
auto it = Advance(m_EmberFile.m_Embers.begin(), start); auto it = Advance(m_EmberFile.m_Embers.begin(), start);
for (size_t i = start; i <= stop && it != m_EmberFile.m_Embers.end(); i++, ++it) for (size_t i = start; i <= stop && it != m_EmberFile.m_Embers.end(); i++, ++it)
{ {
double rotations = randRot ? m_Rand.Frand<double>(rots, rotsMax) : rots; const auto rotations = randRot ? m_Rand.Frand<double>(rots, rotsMax) : rots;
embers[0] = *it; embers[0] = *it;
if (rotations > 0) if (rotations > 0)
{ {
double rotFrames = randFramesRot ? m_Rand.Frand<double>(framesPerRot, framesPerRotMax) : framesPerRot; const auto rotFrames = randFramesRot ? m_Rand.Frand<double>(framesPerRot, framesPerRotMax) : framesPerRot;
size_t roundFrames = size_t(std::round(rotFrames * rotations)); const auto roundFrames = size_t(std::round(rotFrames * rotations));
for (frame = 0; frame < roundFrames; frame++) for (frame = 0; frame < roundFrames; frame++)
{ {
@ -711,9 +709,9 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked()
auto it2 = it;//Need a quick temporary to avoid modifying it which is used in the loop. auto it2 = it;//Need a quick temporary to avoid modifying it which is used in the loop.
embers[1] = *(++it2);//Get the next ember to be used with blending below. embers[1] = *(++it2);//Get the next ember to be used with blending below.
size_t blendFrames = randBlend ? m_Rand.Frand<double>(framesBlend, framesBlendMax) : framesBlend; const auto blendFrames = randBlend ? m_Rand.Frand<double>(framesBlend, framesBlendMax) : framesBlend;
double d = randBlendRot ? m_Rand.Frand<double>(rotsPerBlend, rotsPerBlendMax) : double(rotsPerBlend); const auto d = randBlendRot ? m_Rand.Frand<double>(rotsPerBlend, rotsPerBlendMax) : double(rotsPerBlend);
size_t rpb = size_t(std::round(d)); const auto rpb = size_t(std::round(d));
if (randStagger) if (randStagger)
tools.Stagger(m_Rand.Frand<double>(stagger, staggerMax)); tools.Stagger(m_Rand.Frand<double>(stagger, staggerMax));
@ -722,7 +720,7 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked()
{ {
//if (frame == 43) //if (frame == 43)
// cout << frame << endl; // cout << frame << endl;
bool seqFlag = frame == 0 || (frame == blendFrames - 1); const auto seqFlag = frame == 0 || (frame == blendFrames - 1);
blend = frame / double(blendFrames); blend = frame / double(blendFrames);
result.Clear(); result.Clear();
tools.SpinInter(&embers[0], nullptr, result, startCount + frameCount++, seqFlag, blend, rpb, loopsBlendCw); tools.SpinInter(&embers[0], nullptr, result, startCount + frameCount++, seqFlag, blend, rpb, loopsBlendCw);