From c0a1395a2b5c909411d5360d6182d887209973d5 Mon Sep 17 00:00:00 2001 From: Person Date: Tue, 14 Jul 2020 17:45:07 -0700 Subject: [PATCH] --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. --- Builds/MSVC/Installer/Product.wxs | 10 +- Source/Ember/Variations07.h | 4 +- Source/Ember/XmlToEmber.cpp | 10 +- Source/Fractorium/Fractorium.cpp | 20 ++-- Source/Fractorium/FractoriumLibrary.cpp | 132 ++++++++++++------------ 5 files changed, 91 insertions(+), 85 deletions(-) diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs index 804d710..9aceebb 100644 --- a/Builds/MSVC/Installer/Product.wxs +++ b/Builds/MSVC/Installer/Product.wxs @@ -168,19 +168,19 @@ - + - + - + - + - + diff --git a/Source/Ember/Variations07.h b/Source/Ember/Variations07.h index ad7810d..708be70 100644 --- a/Source/Ember/Variations07.h +++ b/Source/Ember/Variations07.h @@ -2395,8 +2395,8 @@ public: { 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); - m_PrecalcC = std::cos(a) * m_R * std::cos(a) / m_Divisor; - m_PrecalcD = std::cos(a) * m_R * std::sin(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) / Zeps(m_Divisor); m_HalfC = m_PrecalcC / 2; m_HalfD = m_PrecalcD / 2; m_Coeff = m_PrecalcD == 0 ? 0 : T(-0.095) * m_Spread / m_PrecalcD; diff --git a/Source/Ember/XmlToEmber.cpp b/Source/Ember/XmlToEmber.cpp index eba3c40..fc68e12 100644 --- a/Source/Ember/XmlToEmber.cpp +++ b/Source/Ember/XmlToEmber.cpp @@ -1198,7 +1198,15 @@ bool XmlToEmber::ParseEmberElementFromChaos(xmlNode* emberNode, Ember& cur std::string periterweights; 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")) { diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index a669e0e..9d7dddc 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -382,8 +382,8 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e) { auto combo = ui.CurrentXformCombo; bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); - int times = 3; - int ftimes = 2; + const int times = 3; + const int ftimes = 2; 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) { - int val = ke->key() - (int)Qt::Key_F1; + const int val = ke->key() - (int)Qt::Key_F1; if (val < combo->count()) combo->setCurrentIndex(val); @@ -417,10 +417,10 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e) } else if (o == this) { - auto focusedctrlEdit = dynamic_cast(this->focusWidget()); - auto focusedctrlSpin = dynamic_cast(this->focusWidget()); - auto focusedctrlDblSpin = dynamic_cast(this->focusWidget()); - auto focusedctrlCombo = dynamic_cast(this->focusWidget()); + const auto focusedctrlEdit = dynamic_cast(this->focusWidget()); + const auto focusedctrlSpin = dynamic_cast(this->focusWidget()); + const auto focusedctrlDblSpin = dynamic_cast(this->focusWidget()); + const auto focusedctrlCombo = dynamic_cast(this->focusWidget()); if (!focusedctrlEdit && !focusedctrlSpin && @@ -434,11 +434,11 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e) double zoom = 1; double rot = 1; double grow = 0.01; - bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); - bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier); + const bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); + const bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier); 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(); vdist = std::abs(r->UpperRightY() - r->LowerLeftY()) * 0.01 * m_Controller->AffineScaleLockedToCurrent(); diff --git a/Source/Fractorium/FractoriumLibrary.cpp b/Source/Fractorium/FractoriumLibrary.cpp index 2db506e..e2be177 100644 --- a/Source/Fractorium/FractoriumLibrary.cpp +++ b/Source/Fractorium/FractoriumLibrary.cpp @@ -7,10 +7,11 @@ void Fractorium::InitLibraryUI() { 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(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.SequenceStopPreviewsButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceStopPreviewsButtonClicked(bool)), Qt::QueuedConnection); connect(ui.SequenceAllButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceAllButtonClicked(bool)), Qt::QueuedConnection); @@ -68,7 +69,7 @@ void Fractorium::InitLibraryUI() /// The 0-based index of the item in the library tree to select 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++) { @@ -89,10 +90,10 @@ vector> Fractorium::GetCurrentEmberIndex() { int index = 0; QTreeWidgetItem* item = nullptr; - auto tree = ui.LibraryTree; + const auto tree = ui.LibraryTree; vector> 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. { @@ -117,7 +118,7 @@ vector> Fractorium::GetCurrentEmberIndex() /// The height of the bitmap 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()); item->SetImage(m_PreviewVec, w, h); } @@ -131,9 +132,9 @@ template void FractoriumEmberController::SyncLibrary(eLibraryUpdate update) { 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. { @@ -166,11 +167,10 @@ void FractoriumEmberController::FillLibraryTree(int selectIndex) { uint size = 64; uint i = 0; - auto tree = m_Fractorium->ui.LibraryTree; + const auto tree = m_Fractorium->ui.LibraryTree; vector v(size * size * 4); StopAllPreviewRenderers(); tree->clear(); - QCoreApplication::processEvents(); auto fileItem = new QTreeWidgetItem(tree); QFileInfo info(m_EmberFile.m_Filename); fileItem->setText(0, info.fileName()); @@ -205,13 +205,13 @@ void FractoriumEmberController::FillLibraryTree(int selectIndex) template void FractoriumEmberController::UpdateLibraryTree() { - uint size = 64; + const uint size = 64; vector v(size * size * 4); - auto tree = m_Fractorium->ui.LibraryTree; + const auto tree = m_Fractorium->ui.LibraryTree; if (auto top = tree->topLevelItem(0)) { - int origChildCount = top->childCount(); + const int origChildCount = top->childCount(); int i = origChildCount; for (auto it = Advance(m_EmberFile.m_Embers.begin(), i); it != m_EmberFile.m_Embers.end(); ++it) @@ -249,25 +249,24 @@ void FractoriumEmberController::EmberTreeItemChanged(QTreeWidgetItem* item, i { try { - auto tree = m_Fractorium->ui.LibraryTree; + const auto tree = m_Fractorium->ui.LibraryTree; if (auto emberItem = dynamic_cast*>(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; - if (emberItem->text(0).isEmpty())//Prevent empty string. + if (newName.empty())//Prevent empty string. { emberItem->UpdateEditText(); 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. 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. @@ -281,7 +280,7 @@ void FractoriumEmberController::EmberTreeItemChanged(QTreeWidgetItem* item, i } else if (auto parentItem = dynamic_cast(item)) { - QString text = parentItem->text(0); + auto text = parentItem->text(0); if (text != "") { @@ -298,7 +297,7 @@ void FractoriumEmberController::EmberTreeItemChanged(QTreeWidgetItem* item, i 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); } @@ -334,9 +333,9 @@ template void FractoriumEmberController::MoveLibraryItems(const QModelIndexList& items, int destRow) { int i = 0; - auto startRow = items[0].row(); - auto tree = m_Fractorium->ui.LibraryTree; - auto top = tree->topLevelItem(0); + const auto startRow = items[0].row(); + const auto tree = m_Fractorium->ui.LibraryTree; + const auto top = tree->topLevelItem(0); list names; for (auto& item : items) @@ -344,7 +343,7 @@ void FractoriumEmberController::MoveLibraryItems(const QModelIndexList& items names.push_back(temp->m_Name); auto b = m_EmberFile.m_Embers.begin(); - auto result = Gather(b, m_EmberFile.m_Embers.end(), Advance(b, destRow), [&](const Ember& ember) + const auto result = Gather(b, m_EmberFile.m_Embers.end(), Advance(b, destRow), [&](const Ember& ember) { auto position = std::find(names.begin(), names.end(), ember.m_Name); @@ -387,7 +386,7 @@ void FractoriumEmberController::Delete(const vectorui.LibraryTree->topLevelItem(0)) + if (const auto top = m_Fractorium->ui.LibraryTree->topLevelItem(0)) { last = std::min(top->childCount() - 1, last); @@ -421,9 +420,9 @@ void FractoriumEmberController::RenderPreviews(QTreeWidget* tree, TreePreview 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 emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 4); for (int i = 0; i < childCount; i++) @@ -469,13 +468,12 @@ void FractoriumEmberController::StopAllPreviewRenderers() template void FractoriumEmberController::FillSequenceTree() { - uint size = 64; + const uint size = 64; uint i = 0; - auto tree = m_Fractorium->ui.SequenceTree; + const auto tree = m_Fractorium->ui.SequenceTree; vector v(size * size * 4); m_SequencePreviewRenderer->Stop(); 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); QFileInfo info(m_SequenceFile.m_Filename); fileItem->setText(0, info.fileName()); @@ -512,7 +510,7 @@ void FractoriumEmberController::SequenceTreeItemChanged(QTreeWidgetItem* item { if (item == m_Fractorium->ui.SequenceTree->topLevelItem(0)) { - QString text = item->text(0); + auto text = item->text(0); if (text != "") m_SequenceFile.m_Filename = text; @@ -521,7 +519,7 @@ void FractoriumEmberController::SequenceTreeItemChanged(QTreeWidgetItem* item void Fractorium::OnSequenceTreeItemChanged(QTreeWidgetItem* item, int col) { - if (ui.SequenceTree->topLevelItemCount()) + if (item && ui.SequenceTree->topLevelItemCount()) m_Controller->SequenceTreeItemChanged(item, col); } @@ -549,9 +547,9 @@ void Fractorium::OnSequenceStopPreviewsButtonClicked(bool checked) { m_Controlle /// 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.SequenceStartFlameSpinBox->setMinimum(0); ui.SequenceStartFlameSpinBox->setMaximum(count); @@ -581,33 +579,33 @@ void FractoriumEmberController::SequenceGenerateButtonClicked() auto& ui = m_Fractorium->ui; auto s = m_Fractorium->m_Settings; //Bools for determining whether to use hard coded vs. random values. - bool randStagger = ui.SequenceRandomizeStaggerCheckBox->isChecked(); - bool randFramesRot = ui.SequenceRandomizeFramesPerRotCheckBox->isChecked(); - bool randRot = ui.SequenceRandomizeRotationsCheckBox->isChecked(); - bool randBlend = ui.SequenceRandomizeBlendFramesCheckBox->isChecked(); - bool randBlendRot = ui.SequenceRandomizeRotationsPerBlendCheckBox->isChecked(); + const bool randStagger = ui.SequenceRandomizeStaggerCheckBox->isChecked(); + const bool randFramesRot = ui.SequenceRandomizeFramesPerRotCheckBox->isChecked(); + const bool randRot = ui.SequenceRandomizeRotationsCheckBox->isChecked(); + const bool randBlend = ui.SequenceRandomizeBlendFramesCheckBox->isChecked(); + const bool randBlendRot = ui.SequenceRandomizeRotationsPerBlendCheckBox->isChecked(); //The direction to rotate the loops. - bool loopsCw = ui.SequenceRotationsCWCheckBox->isChecked(); - bool loopsBlendCw = ui.SequenceRotationsPerBlendCWCheckBox->isChecked(); + const bool loopsCw = ui.SequenceRotationsCWCheckBox->isChecked(); + const bool loopsBlendCw = ui.SequenceRotationsPerBlendCWCheckBox->isChecked(); //Whether to stagger, default is 1 which means no stagger. - double stagger = ui.SequenceStaggerSpinBox->value(); - double staggerMax = ui.SequenceRandomStaggerMaxSpinBox->value(); + const double stagger = ui.SequenceStaggerSpinBox->value(); + const double staggerMax = ui.SequenceRandomStaggerMaxSpinBox->value(); //Rotations on keyframes. - double rots = ui.SequenceRotationsSpinBox->value(); - double rotsMax = ui.SequenceRandomRotationsMaxSpinBox->value(); + const double rots = ui.SequenceRotationsSpinBox->value(); + const double rotsMax = ui.SequenceRandomRotationsMaxSpinBox->value(); //Number of frames it takes to rotate a keyframe. - int framesPerRot = ui.SequenceFramesPerRotSpinBox->value(); - int framesPerRotMax = ui.SequenceRandomFramesPerRotMaxSpinBox->value(); + const int framesPerRot = ui.SequenceFramesPerRotSpinBox->value(); + const int framesPerRotMax = ui.SequenceRandomFramesPerRotMaxSpinBox->value(); //Number of frames it takes to interpolate. - int framesBlend = ui.SequenceBlendFramesSpinBox->value(); - int framesBlendMax = ui.SequenceRandomBlendMaxFramesSpinBox->value(); + const int framesBlend = ui.SequenceBlendFramesSpinBox->value(); + const int framesBlendMax = ui.SequenceRandomBlendMaxFramesSpinBox->value(); //Number of rotations performed during interpolation. - int rotsPerBlend = ui.SequenceRotationsPerBlendSpinBox->value(); - int rotsPerBlendMax = ui.SequenceRotationsPerBlendMaxSpinBox->value(); - size_t start = ui.SequenceStartFlameSpinBox->value(); - size_t stop = ui.SequenceStopFlameSpinBox->value(); - size_t startCount = ui.SequenceStartCountSpinBox->value(); - size_t keyFrames = (stop - start) + 1; + const int rotsPerBlend = ui.SequenceRotationsPerBlendSpinBox->value(); + const int rotsPerBlendMax = ui.SequenceRotationsPerBlendMaxSpinBox->value(); + const size_t start = ui.SequenceStartFlameSpinBox->value(); + const size_t stop = ui.SequenceStopFlameSpinBox->value(); + const size_t startCount = ui.SequenceStartCountSpinBox->value(); + const size_t keyFrames = (stop - start) + 1; size_t frameCount = 0; double frames = 0; vector> devices;//Dummy. @@ -674,18 +672,18 @@ void FractoriumEmberController::SequenceGenerateButtonClicked() double blend; size_t frame; Ember 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); for (size_t i = start; i <= stop && it != m_EmberFile.m_Embers.end(); i++, ++it) { - double rotations = randRot ? m_Rand.Frand(rots, rotsMax) : rots; + const auto rotations = randRot ? m_Rand.Frand(rots, rotsMax) : rots; embers[0] = *it; if (rotations > 0) { - double rotFrames = randFramesRot ? m_Rand.Frand(framesPerRot, framesPerRotMax) : framesPerRot; - size_t roundFrames = size_t(std::round(rotFrames * rotations)); + const auto rotFrames = randFramesRot ? m_Rand.Frand(framesPerRot, framesPerRotMax) : framesPerRot; + const auto roundFrames = size_t(std::round(rotFrames * rotations)); for (frame = 0; frame < roundFrames; frame++) { @@ -711,9 +709,9 @@ void FractoriumEmberController::SequenceGenerateButtonClicked() 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. - size_t blendFrames = randBlend ? m_Rand.Frand(framesBlend, framesBlendMax) : framesBlend; - double d = randBlendRot ? m_Rand.Frand(rotsPerBlend, rotsPerBlendMax) : double(rotsPerBlend); - size_t rpb = size_t(std::round(d)); + const auto blendFrames = randBlend ? m_Rand.Frand(framesBlend, framesBlendMax) : framesBlend; + const auto d = randBlendRot ? m_Rand.Frand(rotsPerBlend, rotsPerBlendMax) : double(rotsPerBlend); + const auto rpb = size_t(std::round(d)); if (randStagger) tools.Stagger(m_Rand.Frand(stagger, staggerMax)); @@ -722,7 +720,7 @@ void FractoriumEmberController::SequenceGenerateButtonClicked() { //if (frame == 43) // cout << frame << endl; - bool seqFlag = frame == 0 || (frame == blendFrames - 1); + const auto seqFlag = frame == 0 || (frame == blendFrames - 1); blend = frame / double(blendFrames); result.Clear(); tools.SpinInter(&embers[0], nullptr, result, startCount + frameCount++, seqFlag, blend, rpb, loopsBlendCw);