diff --git a/Builds/MSVC/Installer/FractoriumInstaller.wixproj b/Builds/MSVC/Installer/FractoriumInstaller.wixproj
index 1036aa8..fb456da 100644
--- a/Builds/MSVC/Installer/FractoriumInstaller.wixproj
+++ b/Builds/MSVC/Installer/FractoriumInstaller.wixproj
@@ -6,7 +6,7 @@
3.7
{c8096c47-e358-438c-a520-146d46b0637d}
2.0
- Fractorium_1.0.0.20
+ Fractorium_1.0.0.21
Package
$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets
$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets
diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs
index 804d710..f8693f9 100644
--- a/Builds/MSVC/Installer/Product.wxs
+++ b/Builds/MSVC/Installer/Product.wxs
@@ -1,6 +1,6 @@
-
+
@@ -13,7 +13,7 @@
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/Builds/MSVC/VS2019/Ember.rc b/Builds/MSVC/VS2019/Ember.rc
index cecb063..b85ab00 100644
Binary files a/Builds/MSVC/VS2019/Ember.rc and b/Builds/MSVC/VS2019/Ember.rc differ
diff --git a/Builds/MSVC/VS2019/EmberAnimate.rc b/Builds/MSVC/VS2019/EmberAnimate.rc
index 9873293..8d4bbfd 100644
--- a/Builds/MSVC/VS2019/EmberAnimate.rc
+++ b/Builds/MSVC/VS2019/EmberAnimate.rc
@@ -49,8 +49,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1, 0, 0, 20
- PRODUCTVERSION 1, 0, 0, 20
+ FILEVERSION 1, 0, 0, 21
+ PRODUCTVERSION 1, 0, 0, 21
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as animations with motion blur"
- VALUE "FileVersion", "1, 0, 0, 20"
+ VALUE "FileVersion", "1, 0, 0, 21"
VALUE "InternalName", "EmberAnimate.exe"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2020, GPL v3"
VALUE "OriginalFilename", "EmberAnimate.exe"
VALUE "ProductName", "Ember Animate"
- VALUE "ProductVersion", "1, 0, 0, 20"
+ VALUE "ProductVersion", "1, 0, 0, 21"
END
END
BLOCK "VarFileInfo"
diff --git a/Builds/MSVC/VS2019/EmberCL.rc b/Builds/MSVC/VS2019/EmberCL.rc
index ec61563..0021d94 100644
Binary files a/Builds/MSVC/VS2019/EmberCL.rc and b/Builds/MSVC/VS2019/EmberCL.rc differ
diff --git a/Builds/MSVC/VS2019/EmberGenome.rc b/Builds/MSVC/VS2019/EmberGenome.rc
index 500bc09..9b0cd11 100644
--- a/Builds/MSVC/VS2019/EmberGenome.rc
+++ b/Builds/MSVC/VS2019/EmberGenome.rc
@@ -49,8 +49,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1, 0, 0, 20
- PRODUCTVERSION 1, 0, 0, 20
+ FILEVERSION 1, 0, 0, 21
+ PRODUCTVERSION 1, 0, 0, 21
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Manipulates fractal flame parameter files"
- VALUE "FileVersion", "1, 0, 0, 20"
+ VALUE "FileVersion", "1, 0, 0, 21"
VALUE "InternalName", "EmberGenome.exe"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2020, GPL v3"
VALUE "OriginalFilename", "EmberGenome.exe"
VALUE "ProductName", "Ember Genome"
- VALUE "ProductVersion", "1, 0, 0, 20"
+ VALUE "ProductVersion", "1, 0, 0, 21"
END
END
BLOCK "VarFileInfo"
diff --git a/Builds/MSVC/VS2019/EmberRender.rc b/Builds/MSVC/VS2019/EmberRender.rc
index 895d5cf..76fb3d3 100644
--- a/Builds/MSVC/VS2019/EmberRender.rc
+++ b/Builds/MSVC/VS2019/EmberRender.rc
@@ -49,8 +49,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1, 0, 0, 20
- PRODUCTVERSION 1, 0, 0, 20
+ FILEVERSION 1, 0, 0, 21
+ PRODUCTVERSION 1, 0, 0, 21
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as single images"
- VALUE "FileVersion", "1, 0, 0, 20"
+ VALUE "FileVersion", "1, 0, 0, 21"
VALUE "InternalName", "EmberRender.exe"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2020, GPL v3"
VALUE "OriginalFilename", "EmberRender.exe"
VALUE "ProductName", "Ember Render"
- VALUE "ProductVersion", "1, 0, 0, 20"
+ VALUE "ProductVersion", "1, 0, 0, 21"
END
END
BLOCK "VarFileInfo"
diff --git a/Builds/MSVC/VS2019/Fractorium.rc b/Builds/MSVC/VS2019/Fractorium.rc
index c14f115..01f200b 100644
Binary files a/Builds/MSVC/VS2019/Fractorium.rc and b/Builds/MSVC/VS2019/Fractorium.rc differ
diff --git a/Data/Version History.txt b/Data/Version History.txt
index 6172a3f..0fab215 100644
--- a/Data/Version History.txt
+++ b/Data/Version History.txt
@@ -1,4 +1,4 @@
-1.0.0.20 4/11/2020
+1.0.0.21 4/11/2020
--Bug fixes
-ETA time was wrong with incremental final renders after waiting for a period of time.
-Fix possible OpenCL bugs in cubic3D, cubicLattice_3D, dc_cube, falloff, falloff2, falloff3, waffle.
diff --git a/Source/Ember/Ember.cpp b/Source/Ember/Ember.cpp
index 6e22e18..41beacf 100644
--- a/Source/Ember/Ember.cpp
+++ b/Source/Ember/Ember.cpp
@@ -496,6 +496,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Gnarly, T) \
EXPORTPREPOSTREGVAR(Inkdrop, T) \
EXPORTPREPOSTREGVAR(HexModulus, T) \
+ EXPORTPREPOSTREGVAR(Vignette, T) \
template EMBER_API class VariationList; \
template EMBER_API class SpatialFilter; \
template EMBER_API class GaussianFilter; \
diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h
index 13544cd..e50087c 100644
--- a/Source/Ember/EmberDefines.h
+++ b/Source/Ember/EmberDefines.h
@@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
namespace EmberNs
{
-#define EMBER_VERSION "1.0.0.20"
+#define EMBER_VERSION "1.0.0.21"
//#define FLAM3_COMPAT 1//Uncomment this if you want full compatibility with flam3 regarding some of the trig-based variations in Variations01.h
#define EPS6 T(1e-6)
#define EPS std::numeric_limits::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
diff --git a/Source/Ember/Variation.h b/Source/Ember/Variation.h
index 5c1e4c0..aeae69a 100644
--- a/Source/Ember/Variation.h
+++ b/Source/Ember/Variation.h
@@ -433,6 +433,7 @@ enum class eVariationId : glm::uint
VAR_UNPOLAR ,
VAR_VIBRATION,
VAR_VIBRATION2,
+ VAR_VIGNETTE,
VAR_VORON,
VAR_W ,
VAR_WAFFLE,
@@ -849,6 +850,7 @@ enum class eVariationId : glm::uint
VAR_PRE_UNPOLAR,
VAR_PRE_VIBRATION,
VAR_PRE_VIBRATION2,
+ VAR_PRE_VIGNETTE,
VAR_PRE_VORON,
VAR_PRE_W,
VAR_PRE_WAFFLE,
@@ -1265,6 +1267,7 @@ enum class eVariationId : glm::uint
VAR_POST_UNPOLAR,
VAR_POST_VIBRATION,
VAR_POST_VIBRATION2,
+ VAR_POST_VIGNETTE,
VAR_POST_VORON,
VAR_POST_W,
VAR_POST_WAFFLE,
diff --git a/Source/Ember/VariationList.cpp b/Source/Ember/VariationList.cpp
index 18dfd34..5a0067f 100644
--- a/Source/Ember/VariationList.cpp
+++ b/Source/Ember/VariationList.cpp
@@ -439,6 +439,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Gnarly)
ADDPREPOSTREGVAR(Inkdrop)
ADDPREPOSTREGVAR(HexModulus)
+ ADDPREPOSTREGVAR(Vignette)
//ADDPREPOSTREGVAR(LinearXZ)
//ADDPREPOSTREGVAR(LinearYZ)
//DC are special.
diff --git a/Source/Ember/Variations07.h b/Source/Ember/Variations07.h
index ad7810d..b94b311 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;
@@ -7564,6 +7564,199 @@ private:
T m_Yfact001;//Precalc.
};
+///
+/// vignette by Bezo97.
+///
+template
+class VignetteVariation : public ParametricVariation
+{
+public:
+ VignetteVariation(T weight = 1.0) : ParametricVariation("vignette", eVariationId::VAR_VIGNETTE, weight)
+ {
+ Init();
+ }
+
+ PARVARCOPY(VignetteVariation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T px = helper.In.x;
+ T py = helper.In.y;
+ T dist = std::sqrt((px - m_Posx) * (px - m_Posx) + (py - m_Posy) * (py - m_Posy));
+ helper.Out.z = DefaultZ(helper);
+
+ if (dist < m_InnerabsPrecalc)
+ {
+ //middle part
+ if (m_Innerradius < 0.0)
+ {
+ helper.Out.x = 0;
+ helper.Out.y = 0;
+ return;
+ }
+
+ helper.Out.x = px * m_Weight;
+ helper.Out.y = py * m_Weight;
+ return;
+ }
+
+ //map to 0-1
+ dist = (dist - m_InnerabsPrecalc) / m_FadeabsPrecalc;
+ T fade = T(1.0) - std::pow(rand.Frand01(), m_PowerhelperPrecalc);
+ T blur_r = m_Blur * std::pow(dist * rand.Frand01(), T(2.0));
+ T blur_a = rand.Frand01() * M_2PI;
+
+ if (m_Faderadius > 0)
+ {
+ //vignette
+ if (fade < dist)
+ {
+ px = 0;
+ py = 0;
+ }
+ else
+ {
+ px += blur_r * std::cos(blur_a);
+ py += blur_r * std::sin(blur_a);
+ }
+ }
+ else
+ {
+ //inverse vignette
+ if (1 - fade > dist)
+ {
+ px = 0;
+ py = 0;
+ }
+ else
+ {
+ px += blur_r * std::cos(blur_a);
+ py += blur_r * std::sin(blur_a);
+ }
+ }
+
+ helper.Out.x = px * m_Weight;
+ helper.Out.y = py * m_Weight;
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string posx = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string posy = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string innerradius = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string faderadius = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string blur = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string innerabsprecalc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string fadeabsprecalc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string powerhelperprecalc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\treal_t px = vIn.x;\n"
+ << "\t\treal_t py = vIn.y;\n"
+ << "\t\treal_t dist = sqrt((px - " << posx << ") * (px - " << posx << ") + (py - " << posy << ") * (py - " << posy << "));\n"
+ << "\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\n"
+ << "\t\tif (dist < " << innerabsprecalc << ")\n"
+ << "\t\t{\n"
+ << "\t\t\tif (" << innerradius << " < (real_t)(0.0))\n"
+ << "\t\t\t{\n"
+ << "\t\t\t\tvOut.x = (real_t)(0.0);\n"
+ << "\t\t\t\tvOut.y = (real_t)(0.0);\n"
+ << "\t\t\t}\n"
+ << "\t\t\telse\n"
+ << "\t\t\t{\n"
+ << "\t\t\t\tvOut.x = px * " << weight << ";\n"
+ << "\t\t\t\tvOut.y = py * " << weight << ";\n"
+ << "\t\t\t}\n"
+ << "\t\t}\n"
+ << "\t\telse\n"
+ << "\t\t{\n"
+ << "\t\t\tdist = (dist - " << innerabsprecalc << ") / " << fadeabsprecalc << ";\n"
+ << "\n"
+ << "\t\t\treal_t fade = (real_t)(1.0) - pow(MwcNext01(mwc), " << powerhelperprecalc << ");\n"
+ << "\t\t\treal_t blur_r = " << blur << " * pow(dist * MwcNext01(mwc), (real_t)(2.0));\n"
+ << "\t\t\treal_t blur_a = MwcNext01(mwc) * M_2PI;\n"
+ << "\n"
+ << "\t\t\tif (" << faderadius << " > 0.0)\n"
+ << "\t\t\t{\n"
+ << "\t\t\t\tif (fade < dist)\n"
+ << "\t\t\t\t{\n"
+ << "\t\t\t\t\tpx = (real_t)(0.0);\n"
+ << "\t\t\t\t\tpy = (real_t)(0.0);\n"
+ << "\t\t\t\t}\n"
+ << "\t\t\t\telse\n"
+ << "\t\t\t\t{\n"
+ << "\t\t\t\t\tpx += blur_r * cos(blur_a);\n"
+ << "\t\t\t\t\tpy += blur_r * sin(blur_a);\n"
+ << "\t\t\t\t}\n"
+ << "\t\t\t}\n"
+ << "\t\t\telse\n"
+ << "\t\t\t{\n"
+ << "\t\t\t\tif (1 - fade > dist)\n"
+ << "\t\t\t\t{\n"
+ << "\t\t\t\t\tpx = (real_t)(0.0);\n"
+ << "\t\t\t\t\tpy = (real_t)(0.0);\n"
+ << "\t\t\t\t}\n"
+ << "\t\t\t\telse\n"
+ << "\t\t\t\t{\n"
+ << "\t\t\t\t\tpx += blur_r * cos(blur_a);\n"
+ << "\t\t\t\t\tpy += blur_r * sin(blur_a);\n"
+ << "\t\t\t\t}\n"
+ << "\t\t\t}\n"
+ << "\n"
+ << "\t\t\tvOut.x = px * " << weight << ";\n"
+ << "\t\t\tvOut.y = py * " << weight << ";\n"
+ << "\t\t}\n"
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual void Precalc() override
+ {
+ m_InnerabsPrecalc = std::abs(m_Innerradius);
+ m_FadeabsPrecalc = std::abs(m_Faderadius);
+ m_PowerhelperPrecalc = T(1.0) / std::abs(m_Power);
+ }
+
+ virtual vector OpenCLGlobalFuncNames() const override
+ {
+ return vector { "Zeps" };
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_Posx, prefix + "vignette_posx"));
+ m_Params.push_back(ParamWithName(&m_Posy, prefix + "vignette_posy"));
+ m_Params.push_back(ParamWithName(&m_Innerradius, prefix + "vignette_inner_radius", T(0.5)));
+ m_Params.push_back(ParamWithName(&m_Faderadius, prefix + "vignette_fade_radius", T(0.5), eParamType::REAL_NONZERO));
+ m_Params.push_back(ParamWithName(&m_Power, prefix + "vignette_power", T(4.0), eParamType::REAL_NONZERO));
+ m_Params.push_back(ParamWithName(&m_Blur, prefix + "vignette_blur", T(1.0)));
+ m_Params.push_back(ParamWithName(true, &m_InnerabsPrecalc, prefix + "vignette_inner_abs_precalc"));//Precalc.
+ m_Params.push_back(ParamWithName(true, &m_FadeabsPrecalc, prefix + "vignette_fade_abs_precalc"));
+ m_Params.push_back(ParamWithName(true, &m_PowerhelperPrecalc, prefix + "vignette_power_helper_precalc"));
+ }
+
+private:
+ T m_Posx;
+ T m_Posy;
+ T m_Innerradius;
+ T m_Faderadius;
+ T m_Power;
+ T m_Blur;
+ T m_InnerabsPrecalc;//Precalc.
+ T m_FadeabsPrecalc;
+ T m_PowerhelperPrecalc;
+};
+
MAKEPREPOSTPARVAR(Splits3D, splits3D, SPLITS3D)
MAKEPREPOSTPARVAR(Waves2B, waves2b, WAVES2B)
MAKEPREPOSTPARVAR(JacCn, jac_cn, JAC_CN)
@@ -7634,4 +7827,5 @@ MAKEPREPOSTPARVAR(Waves23, waves23, WAVES23)
MAKEPREPOSTPARVAR(Waves42, waves42, WAVES42)
MAKEPREPOSTPARVAR(Waves3, waves3, WAVES3)
MAKEPREPOSTPARVAR(Waves4, waves4, WAVES4)
+MAKEPREPOSTPARVAR(Vignette, vignette, VIGNETTE)
}
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/AboutDialog.ui b/Source/Fractorium/AboutDialog.ui
index 1c40021..3bf07b0 100644
--- a/Source/Fractorium/AboutDialog.ui
+++ b/Source/Fractorium/AboutDialog.ui
@@ -58,7 +58,7 @@
QFrame::NoFrame
- <html><head/><body><p align="center"><span style=" font-size:10pt;">Fractorium 1.0.0.20</span></p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">fractorium.com</span></a></p></body></html>
+ <html><head/><body><p align="center"><span style=" font-size:10pt;">Fractorium 1.0.0.21</span></p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">fractorium.com</span></a></p></body></html>
Qt::RichText
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/Fractorium.ui b/Source/Fractorium/Fractorium.ui
index 21d82c9..4c35769 100644
--- a/Source/Fractorium/Fractorium.ui
+++ b/Source/Fractorium/Fractorium.ui
@@ -8745,7 +8745,7 @@
Pre
- Show/Hide Pre Affines
+ Show/Hide Pre Affines (P)
@@ -8756,7 +8756,7 @@
All
- Show All Pre Affines
+ Show All Pre Affines (L)
@@ -8767,7 +8767,7 @@
Post
- Show/Hide Post Affines
+ Show/Hide Post Affines (Shift + P)
@@ -8778,7 +8778,7 @@
All
- Show All Post Affines
+ Show All Post Affines (Shift + L)
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);