diff --git a/.gitignore b/.gitignore
index a0d164f..487619f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,4 +35,5 @@ Builds/MSVC/VS2010/Obj/EmberTester/x64/Debug/EmberTester_manifest.rc
Builds/MSVC/VS2010/Obj/EmberRender/x64/Debug/EmberRender_manifest.rc
Builds/MSVC/VS2010/Obj/EmberGenome/x64/Debug/EmberGenome_manifest.rc
Builds/MSVC/VS2010/Obj/EmberAnimate/x64/Debug/EmberAnimate_manifest.rc
-Builds/MSVC/VS2010/Obj/Ember/x64/Debug/Ember_manifest.rc
\ No newline at end of file
+Builds/MSVC/VS2010/Obj/Ember/x64/Debug/Ember_manifest.rc
+Bin/x64/Release/testallvarsout.flame
\ No newline at end of file
diff --git a/Builds/MSVC/VS2010/FractoriumInstaller/FractoriumInstaller.wixproj b/Builds/MSVC/VS2010/FractoriumInstaller/FractoriumInstaller.wixproj
index 9902321..9b094fe 100644
--- a/Builds/MSVC/VS2010/FractoriumInstaller/FractoriumInstaller.wixproj
+++ b/Builds/MSVC/VS2010/FractoriumInstaller/FractoriumInstaller.wixproj
@@ -6,7 +6,7 @@
3.7
{c8096c47-e358-438c-a520-146d46b0637d}
2.0
- Fractorium_Beta_0.4.0.8
+ Fractorium_Beta_0.4.0.9
Package
$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets
$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets
diff --git a/Builds/MSVC/VS2010/FractoriumInstaller/Product.wxs b/Builds/MSVC/VS2010/FractoriumInstaller/Product.wxs
index d44f184..138c913 100644
--- a/Builds/MSVC/VS2010/FractoriumInstaller/Product.wxs
+++ b/Builds/MSVC/VS2010/FractoriumInstaller/Product.wxs
@@ -1,6 +1,6 @@
-
+
@@ -13,7 +13,7 @@
-
+
= 0.
+ Ensure OpenCL platform and device combo boxes in the final render dialog expand as needed.
+
+--Code Changes
+ Make VariationTreeSpinbox take its parent VariationTreeWidgetItem as a constructor argument. This makes SetupVariationTree() and VariationSpinBoxValueChanged() more efficient.
+ Make Interference2 and ho use fabs().
+
0.4.0.8 Beta 07/26/2014
--Bug Fixes
Fix falloff, falloff2, falloff3.
diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h
index 6d4694b..14de05c 100644
--- a/Source/Ember/EmberDefines.h
+++ b/Source/Ember/EmberDefines.h
@@ -25,7 +25,7 @@ namespace EmberNs
extern void sincos(double x, double *s, double *c);
#endif
-#define EMBER_VERSION "0.4.0.8"
+#define EMBER_VERSION "0.4.0.9"
#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.
#define ISAAC_SIZE 4
diff --git a/Source/Ember/Variations01.h b/Source/Ember/Variations01.h
index 87c580d..14a6012 100644
--- a/Source/Ember/Variations01.h
+++ b/Source/Ember/Variations01.h
@@ -3473,7 +3473,7 @@ public:
{
T wx = m_Weight * T(1.3029400317411197908970256609023);//This precision came from the original.
T y2 = helper.In.y * 2;
- T r = wx * sqrt(fabs(helper.In.y * helper.In.x) / Zeps(helper.In.x * helper.In.x + y2 * y2));
+ T r = wx * sqrt(fabs(helper.In.y * helper.In.x) / Zeps(SQR(helper.In.x) + SQR(y2)));
helper.Out.x = r * helper.In.x;
helper.Out.y = r * y2;
@@ -3488,7 +3488,7 @@ public:
ss << "\t{\n"
<< "\t\treal_t wx = xform->m_VariationWeights[" << varIndex << "] * 1.3029400317411197908970256609023;\n"
<< "\t\treal_t y2 = vIn.y * 2.0;\n"
- << "\t\treal_t r = wx * sqrt(fabs(vIn.y * vIn.x) / Zeps(vIn.x * vIn.x + y2 * y2));\n"
+ << "\t\treal_t r = wx * sqrt(fabs(vIn.y * vIn.x) / Zeps(SQR(vIn.x) + SQR(y2)));\n"
<< "\n"
<< "\t\tvOut.x = r * vIn.x;\n"
<< "\t\tvOut.y = r * y2;\n"
diff --git a/Source/Ember/Variations03.h b/Source/Ember/Variations03.h
index ae0af14..0a68b6e 100644
--- a/Source/Ember/Variations03.h
+++ b/Source/Ember/Variations03.h
@@ -424,7 +424,7 @@ public:
void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand)
{
- T x, y, z, alpha = m_Radius / helper.m_PrecalcSqrtSumSquares;
+ T x, y, z;
if (helper.m_PrecalcSqrtSumSquares < m_Radius)//Object generation.
{
@@ -434,6 +434,8 @@ public:
}
else
{
+ T alpha = fabs(m_Radius / Zeps(helper.m_PrecalcSqrtSumSquares));//Original did not fabs().
+
if (rand.Frand01() > m_Contrast * pow(alpha, m_Pow))
{
x = helper.In.x;
@@ -479,7 +481,7 @@ public:
string y1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
- << "\t\treal_t x, y, z, alpha = " << radius << " / precalcSqrtSumSquares;\n"
+ << "\t\treal_t x, y, z;\n"
<< "\n"
<< "\t\tif (precalcSqrtSumSquares < " << radius << ")\n"
<< "\t\t{\n"
@@ -489,6 +491,8 @@ public:
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
+ << "\t\t real_t alpha = fabs(" << radius << " / Zeps(precalcSqrtSumSquares));\n"
+ << "\n"
<< "\t\t if (MwcNext01(mwc) > " << contrast << " * pow(alpha, " << pow << "))\n"
<< "\t\t {\n"
<< "\t\t x = vIn.x;\n"
@@ -602,7 +606,7 @@ public:
void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand)
{
- T x, y, alpha = m_Radius / helper.m_PrecalcSqrtSumSquares;
+ T x, y;
if (helper.m_PrecalcSqrtSumSquares < m_Radius)
{
@@ -612,6 +616,8 @@ public:
}
else
{
+ T alpha = fabs(m_Radius / Zeps(helper.m_PrecalcSqrtSumSquares));//Original did not fabs().
+
if (rand.Frand01() > m_Contrast * pow(alpha, m_Pow))
{
helper.Out.x = m_Weight * helper.In.x;
@@ -645,7 +651,7 @@ public:
string delta = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
- << "\t\treal_t x, y, alpha = " << radius << " / precalcSqrtSumSquares;\n"
+ << "\t\treal_t x, y;\n"
<< "\n"
<< "\t\tif (precalcSqrtSumSquares < " << radius << ")\n"
<< "\t\t{\n"
@@ -655,6 +661,8 @@ public:
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
+ << "\t\t real_t alpha = fabs(" << radius << " / Zeps(precalcSqrtSumSquares));\n"
+ << "\n"
<< "\t\t if (MwcNext01(mwc) > " << contrast << " * pow(alpha, " << pow << "))\n"
<< "\t\t {\n"
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
@@ -692,9 +700,9 @@ public:
virtual void Precalc()
{
m_Pow = fabs(m_Pow);
- m_Phi10 = M_2PI * m_Phi1;
- m_Phi20 = M_2PI * m_Phi2;
- m_Gamma = m_Thickness * (2 * m_Radius + m_Thickness) / (m_Radius + m_Thickness);
+ m_Phi10 = T(M_PI) * m_Phi1 / 180;
+ m_Phi20 = T(M_PI) * m_Phi2 / 180;
+ m_Gamma = m_Thickness * (2 * m_Radius + m_Thickness) / Zeps(m_Radius + m_Thickness);
m_Delta = m_Phi20 - m_Phi10;
}
@@ -756,7 +764,7 @@ public:
void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand)
{
- T x, y, alpha = m_Radius / helper.m_PrecalcSqrtSumSquares;
+ T x, y;
if (helper.m_PrecalcSqrtSumSquares < m_Radius1)
{
@@ -766,6 +774,8 @@ public:
}
else
{
+ T alpha = fabs(m_Radius / Zeps(helper.m_PrecalcSqrtSumSquares));//Original did not fabs().
+
if (rand.Frand01() > m_Contrast * pow(alpha, m_Pow))
{
helper.Out.x = m_Weight * helper.In.x;
@@ -797,7 +807,7 @@ public:
string gamma = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
- << "\t\treal_t x, y, alpha = " << radius << " / precalcSqrtSumSquares;\n"
+ << "\t\treal_t x, y;\n"
<< "\n"
<< "\t\tif (precalcSqrtSumSquares < " << radius1 << ")\n"
<< "\t\t{\n"
@@ -807,6 +817,8 @@ public:
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
+ << "\t\t real_t alpha = fabs(" << radius << " / Zeps(precalcSqrtSumSquares));\n"
+ << "\n"
<< "\t\t if (MwcNext01(mwc) > " << contrast << " * pow(alpha, " << pow << "))\n"
<< "\t\t {\n"
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
@@ -849,8 +861,8 @@ public:
virtual void Precalc()
{
m_Radius1 = m_Radius + m_Thickness;
- m_Radius2 = SQR(m_Radius) / m_Radius1;
- m_Gamma = m_Radius1 / (m_Radius1 + m_Radius2);
+ m_Radius2 = SQR(m_Radius) / Zeps(m_Radius1);
+ m_Gamma = m_Radius1 / Zeps(m_Radius1 + m_Radius2);
}
protected:
@@ -1045,18 +1057,13 @@ public:
return ss.str();
}
- virtual void Precalc()
- {
- ClampGte0Ref(m_Power);
- }
-
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
- m_Params.push_back(ParamWithName(&m_Power, prefix + "sineblur_power", 1));
+ m_Params.push_back(ParamWithName(&m_Power, prefix + "sineblur_power", 1, REAL, 0));
}
private:
diff --git a/Source/Ember/Variations04.h b/Source/Ember/Variations04.h
index 6d5b71a..5eaaff9 100644
--- a/Source/Ember/Variations04.h
+++ b/Source/Ember/Variations04.h
@@ -1231,7 +1231,7 @@ public:
{
T jun = Zeps(fabs(m_N));
- T a = (atan2(helper.In.y, pow(helper.In.x, m_Sep)) + M_2PI * Floor(rand.Frand01() * m_AbsN)) / jun;
+ T a = (atan2(helper.In.y, pow(fabs(helper.In.x), m_Sep)) + M_2PI * Floor(rand.Frand01() * m_AbsN)) / jun;
T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn * m_A);
helper.Out.x = r * cos(a) + m_B;
@@ -1255,7 +1255,7 @@ public:
ss << "\t{\n"
<< "\t\treal_t jun = Zeps(fabs(" << n << "));\n"
<< "\n"
- << "\t\treal_t a = (atan2(vIn.y, pow(vIn.x, " << sep << ")) + M_2PI * floor(MwcNext01(mwc) * " << absN << ")) / jun;\n"
+ << "\t\treal_t a = (atan2(vIn.y, pow(fabs(vIn.x), " << sep << ")) + M_2PI * floor(MwcNext01(mwc) * " << absN << ")) / jun;\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(precalcSumSquares, " << cn << " * " << a << ");\n"
<< "\n"
<< "\t\tvOut.x = r * cos(a) + " << b << ";\n"
@@ -1709,8 +1709,8 @@ public:
pr1 = m_An2_1 * pow(fabs(mcosr), m_N2_1) + m_Bn3_1 * pow(fabs(msinr), m_N3_1);
pr2 = m_An2_2 * pow(fabs(mcosp), m_N2_2) + m_Bn3_2 * pow(fabs(msinp), m_N3_2);
- r1 = pow(pr1, m_N1_1) + m_Spiral * rho1;
- r2 = pow(pr2, m_N1_2);
+ r1 = pow(fabs(pr1), m_N1_1) + m_Spiral * rho1;
+ r2 = pow(fabs(pr2), m_N1_2);
if ((int)m_Toroidmap == 1)
{
@@ -1784,8 +1784,8 @@ public:
<< "\n"
<< "\t\tpr1 = " << an2_1 << " * pow(fabs(mcosr), " << n2_1 << ") + " << bn3_1 << " * pow(fabs(msinr), " << n3_1 << ");\n"
<< "\t\tpr2 = " << an2_2 << " * pow(fabs(mcosp), " << n2_2 << ") + " << bn3_2 << " * pow(fabs(msinp), " << n3_2 << ");\n"
- << "\t\tr1 = pow(pr1, " << n1_1 << ") + " << spiral << " * rho1;\n"
- << "\t\tr2 = pow(pr2, " << n1_2 << ");\n"
+ << "\t\tr1 = pow(fabs(pr1), " << n1_1 << ") + " << spiral << " * rho1;\n"
+ << "\t\tr2 = pow(fabs(pr2), " << n1_2 << ");\n"
<< "\n"
<< "\t\tif ((int)" << toroid << " == 1)\n"
<< "\t\t{\n"
@@ -3083,12 +3083,12 @@ public:
return
"real_t Interference2Sine(real_t a, real_t b, real_t c, real_t p, real_t x)\n"
"{\n"
- " return a * pow(ClampGte(sin(b * x + c), EPS), p);\n"
+ " return a * pow(fabs(sin(b * x + c)), p);\n"
"}\n"
"\n"
"real_t Interference2Tri(real_t a, real_t b, real_t c, real_t p, real_t x)\n"
"{\n"
- " return a * 2 * pow(ClampGte(asin(cos(b * x + c - M_PI_2)), EPS) * M_1_PI, p);\n"
+ " return a * 2 * pow(fabs(asin(cos(b * x + c - M_PI_2))) * M_1_PI, p);\n"
"}\n"
"\n"
"real_t Interference2Squ(real_t a, real_t b, real_t c, real_t p, real_t x)\n"
@@ -3119,12 +3119,12 @@ protected:
private:
inline static T Sine(T a, T b, T c, T p, T x)
{
- return a * pow(ClampGte(sin(b * x + c), EPS), p);//Original did not clamp.
+ return a * pow(fabs(sin(b * x + c)), p);//Original did not fabs().
}
inline static T Tri(T a, T b, T c, T p, T x)
{
- return a * 2 * pow(ClampGte(asin(cos(b * x + c - T(M_PI_2))), EPS) * T(M_1_PI), p);//Original did not clamp.
+ return a * 2 * pow(fabs(asin(cos(b * x + c - T(M_PI_2)))) * T(M_1_PI), p);//Original did not fabs().
}
inline static T Squ(T a, T b, T c, T p, T x)
diff --git a/Source/Ember/Variations05.h b/Source/Ember/Variations05.h
index c4d84e1..c414fc0 100644
--- a/Source/Ember/Variations05.h
+++ b/Source/Ember/Variations05.h
@@ -1085,9 +1085,9 @@ public:
T cv = cos(helper.In.y);
T cucv = cu * cv;
T sucv = su * cv;
- T x = pow(ClampGte(cucv, EPS), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must clamp first argument to pow, because negative values will return NaN.
- T y = pow(ClampGte(sucv, EPS), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values.
- T z = pow(ClampGte(sv, EPS), m_ZPow) + sv * m_ZPow;
+ T x = pow(fabs(cucv), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must fabs first argument to pow, because negative values will return NaN.
+ T y = pow(fabs(sucv), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values.
+ T z = pow(fabs(sv), m_ZPow) + sv * m_ZPow;
helper.Out.x = m_Weight * x;
helper.Out.y = m_Weight * y;
@@ -1117,9 +1117,9 @@ public:
<< "\t\treal_t cv = cos(vIn.y);\n"
<< "\t\treal_t cucv = cu * cv;\n"
<< "\t\treal_t sucv = su * cv;\n"
- << "\t\treal_t x = pow(ClampGte(cucv, EPS), " << xpow << ") + (cucv * " << xpow << ") + (0.25 * atOmegaX);\n"
- << "\t\treal_t y = pow(ClampGte(sucv, EPS), " << ypow << ") + (sucv * " << ypow << ") + (0.25 * atOmegaY);\n"
- << "\t\treal_t z = pow(ClampGte(sv, EPS), " << zpow << ") + sv * " << zpow << ";\n"
+ << "\t\treal_t x = pow(fabs(cucv), " << xpow << ") + (cucv * " << xpow << ") + (0.25 * atOmegaX);\n"
+ << "\t\treal_t y = pow(fabs(sucv), " << ypow << ") + (sucv * " << ypow << ") + (0.25 * atOmegaY);\n"
+ << "\t\treal_t z = pow(fabs(sv), " << zpow << ") + sv * " << zpow << ";\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * x;\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * y;\n"
@@ -2151,8 +2151,8 @@ public:
case 2://Box.
scale = Clamp(rs, 0, T(0.9)) + T(0.1);
denom = 1 / scale;
- helper.Out.x = m_Weight * Lerp(helper.In.x, floor(helper.In.x * denom) + scale * ax, m_MulX * rs) + m_MulX * pow(ax, m_BoxPow) * rs * denom;
- helper.Out.y = m_Weight * Lerp(helper.In.y, floor(helper.In.y * denom) + scale * ay, m_MulY * rs) + m_MulY * pow(ay, m_BoxPow) * rs * denom;
+ helper.Out.x = m_Weight * Lerp(helper.In.x, floor(helper.In.x * denom) + scale * ax, m_MulX * rs) + m_MulX * pow(ax, m_BoxPow) * rs * denom;//m_BoxPow should be an integer value held in T,
+ helper.Out.y = m_Weight * Lerp(helper.In.y, floor(helper.In.y * denom) + scale * ay, m_MulY * rs) + m_MulY * pow(ay, m_BoxPow) * rs * denom;//so fabs() shouldn't be necessary.
helper.Out.z = m_Weight * Lerp(helper.In.z, floor(helper.In.z * denom) + scale * az, m_MulZ * rs) + m_MulZ * pow(az, m_BoxPow) * rs * denom;
break;
}
diff --git a/Source/EmberAnimate/EmberAnimate.rc b/Source/EmberAnimate/EmberAnimate.rc
index 59941e7..0c3c781 100644
--- a/Source/EmberAnimate/EmberAnimate.rc
+++ b/Source/EmberAnimate/EmberAnimate.rc
@@ -49,8 +49,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,4,0,8
- PRODUCTVERSION 0,4,0,8
+ FILEVERSION 0,4,0,9
+ PRODUCTVERSION 0,4,0,9
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as animations with motion blur"
- VALUE "FileVersion", "0.4.0.8"
+ VALUE "FileVersion", "0.4.0.9"
VALUE "InternalName", "EmberAnimate.rc"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3"
VALUE "OriginalFilename", "EmberAnimate.rc"
VALUE "ProductName", "Ember Animate"
- VALUE "ProductVersion", "0.4.0.8"
+ VALUE "ProductVersion", "0.4.0.9"
END
END
BLOCK "VarFileInfo"
diff --git a/Source/EmberGenome/EmberGenome.rc b/Source/EmberGenome/EmberGenome.rc
index df718e5..2e57adb 100644
--- a/Source/EmberGenome/EmberGenome.rc
+++ b/Source/EmberGenome/EmberGenome.rc
@@ -49,8 +49,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,4,0,8
- PRODUCTVERSION 0,4,0,8
+ FILEVERSION 0,4,0,9
+ PRODUCTVERSION 0,4,0,9
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Manipulates fractal flames parameter files"
- VALUE "FileVersion", "0.4.0.8"
+ VALUE "FileVersion", "0.4.0.9"
VALUE "InternalName", "EmberGenome.rc"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3"
VALUE "OriginalFilename", "EmberGenome.rc"
VALUE "ProductName", "Ember Genome"
- VALUE "ProductVersion", "0.4.0.8"
+ VALUE "ProductVersion", "0.4.0.9"
END
END
BLOCK "VarFileInfo"
diff --git a/Source/EmberRender/EmberRender.rc b/Source/EmberRender/EmberRender.rc
index c7936b7..f2747f5 100644
--- a/Source/EmberRender/EmberRender.rc
+++ b/Source/EmberRender/EmberRender.rc
@@ -49,8 +49,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,4,0,8
- PRODUCTVERSION 0,4,0,8
+ FILEVERSION 0,4,0,9
+ PRODUCTVERSION 0,4,0,9
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as single images"
- VALUE "FileVersion", "0.4.0.8"
+ VALUE "FileVersion", "0.4.0.9"
VALUE "InternalName", "EmberRender.rc"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3"
VALUE "OriginalFilename", "EmberRender.rc"
VALUE "ProductName", "Ember Render"
- VALUE "ProductVersion", "0.4.0.8"
+ VALUE "ProductVersion", "0.4.0.9"
END
END
BLOCK "VarFileInfo"
diff --git a/Source/Fractorium/AboutDialog.ui b/Source/Fractorium/AboutDialog.ui
index f18e669..1cccbdb 100644
--- a/Source/Fractorium/AboutDialog.ui
+++ b/Source/Fractorium/AboutDialog.ui
@@ -52,7 +52,7 @@
- <html><head/><body><p align="center"><br/><span style=" font-size:12pt;">Fractorium 0.4.0.8 Beta</span></p><p align="center"><span style=" font-size:10pt;"><br/>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"><span style=" font-size:10pt;">Matt Feemster</span></p></body></html>
+ <html><head/><body><p align="center"><br/><span style=" font-size:12pt;">Fractorium 0.4.0.9 Beta</span></p><p align="center"><span style=" font-size:10pt;"><br/>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"><span style=" font-size:10pt;">Matt Feemster</span></p></body></html>
Qt::RichText
diff --git a/Source/Fractorium/DoubleSpinBox.h b/Source/Fractorium/DoubleSpinBox.h
index 1f02cd0..de9b3c6 100644
--- a/Source/Fractorium/DoubleSpinBox.h
+++ b/Source/Fractorium/DoubleSpinBox.h
@@ -45,6 +45,12 @@ private:
double m_SmallStep;
};
+///
+/// VariationTreeWidgetItem and VariationTreeDoubleSpinBox need each other, but each can't include the other.
+/// So VariationTreeWidgetItem includes this file, and use a forward declaration here.
+///
+template class VariationTreeWidgetItem;
+
///
/// Derivation for the double spin boxes that are in the
/// variations tree.
@@ -57,13 +63,15 @@ public:
/// Constructor that passes agruments to the base and assigns the m_Param and m_Variation members.
///
/// The parent widget
+ /// The widget item this spinner is contained in
/// The variation this spinner is for
/// The name of the parameter this is for
/// The height of the spin box. Default: 16.
/// The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.
- explicit VariationTreeDoubleSpinBox(QWidget* parent, Variation* var, string param, int height = 16, double step = 0.05)
+ explicit VariationTreeDoubleSpinBox(QWidget* parent, VariationTreeWidgetItem* widgetItem, Variation* var, string param, int height = 16, double step = 0.05)
: DoubleSpinBox(parent, height, step)
{
+ m_WidgetItem = widgetItem;
m_Param = param;
m_Variation = var;
setDecimals(3);
@@ -73,8 +81,10 @@ public:
bool IsParam() { return !m_Param.empty(); }
string ParamName() { return m_Param; }
Variation* GetVariation() { return m_Variation; }
+ VariationTreeWidgetItem* WidgetItem() { return m_WidgetItem; }
private:
string m_Param;
Variation* m_Variation;
+ VariationTreeWidgetItem* m_WidgetItem;
};
diff --git a/Source/Fractorium/FinalRenderDialog.cpp b/Source/Fractorium/FinalRenderDialog.cpp
index bf0f4d9..f6095d0 100644
--- a/Source/Fractorium/FinalRenderDialog.cpp
+++ b/Source/Fractorium/FinalRenderDialog.cpp
@@ -119,6 +119,38 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
s.setHeight(min(s.height(), (int)((double)desktopHeight * 0.90)));
setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, qApp->desktop()->availableGeometry()));
+
+ QWidget* w = SetTabOrder(this, ui.FinalRenderEarlyClipCheckBox, ui.FinalRenderYAxisUpCheckBox);
+
+ w = SetTabOrder(this, w, ui.FinalRenderTransparencyCheckBox);
+ w = SetTabOrder(this, w, ui.FinalRenderOpenCLCheckBox);
+ w = SetTabOrder(this, w, ui.FinalRenderDoublePrecisionCheckBox);
+ w = SetTabOrder(this, w, ui.FinalRenderSaveXmlCheckBox);
+ w = SetTabOrder(this, w, ui.FinalRenderDoAllCheckBox);
+ w = SetTabOrder(this, w, ui.FinalRenderDoSequenceCheckBox);
+ w = SetTabOrder(this, w, ui.FinalRenderKeepAspectCheckBox);
+ w = SetTabOrder(this, w, ui.FinalRenderScaleNoneRadioButton);
+ w = SetTabOrder(this, w, ui.FinalRenderScaleWidthRadioButton);
+ w = SetTabOrder(this, w, ui.FinalRenderScaleHeightRadioButton);
+ w = SetTabOrder(this, w, ui.FinalRenderJpgRadioButton);
+ w = SetTabOrder(this, w, ui.FinalRenderPngRadioButton);
+ w = SetTabOrder(this, w, ui.FinalRenderPlatformCombo);
+ w = SetTabOrder(this, w, ui.FinalRenderDeviceCombo);
+ w = SetTabOrder(this, w, ui.FinalRenderThreadCountSpin);
+ w = SetTabOrder(this, w, m_WidthSpin);
+ w = SetTabOrder(this, w, m_HeightSpin);
+ w = SetTabOrder(this, w, m_QualitySpin);
+ w = SetTabOrder(this, w, m_TemporalSamplesSpin);
+ w = SetTabOrder(this, w, m_SupersampleSpin);
+ w = SetTabOrder(this, w, tbw);
+ w = SetTabOrder(this, w, tbw->m_Button1);
+ w = SetTabOrder(this, w, tbw->m_Button2);
+ w = SetTabOrder(this, w, m_PrefixEdit);
+ w = SetTabOrder(this, w, m_SuffixEdit);
+ w = SetTabOrder(this, w, ui.FinalRenderTextOutput);
+ w = SetTabOrder(this, w, ui.StartRenderButton);
+ w = SetTabOrder(this, w, ui.StopRenderButton);
+ w = SetTabOrder(this, w, ui.CloseButton);
}
///
diff --git a/Source/Fractorium/FinalRenderDialog.ui b/Source/Fractorium/FinalRenderDialog.ui
index db9da53..ee5c5ee 100644
--- a/Source/Fractorium/FinalRenderDialog.ui
+++ b/Source/Fractorium/FinalRenderDialog.ui
@@ -46,6 +46,9 @@
-
+
+ Qt::NoFocus
+
QFrame::NoFrame
@@ -352,44 +355,44 @@
-
-
+
-
+
0
0
- 320
+ 0
0
- 320
+ 16777215
16777215
-
-
+
-
+
0
0
- 320
+ 0
0
- 320
+ 16777215
16777215
@@ -476,6 +479,9 @@
Qt::SolidLine
+
+ false
+
false
@@ -828,7 +834,13 @@
- Qt::TabFocus
+ Qt::StrongFocus
+
+
+ true
+
+
+ Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
@@ -916,6 +928,30 @@
+
+ FinalRenderEarlyClipCheckBox
+ FinalRenderYAxisUpCheckBox
+ FinalRenderTransparencyCheckBox
+ FinalRenderOpenCLCheckBox
+ FinalRenderDoublePrecisionCheckBox
+ FinalRenderSaveXmlCheckBox
+ FinalRenderDoAllCheckBox
+ FinalRenderDoSequenceCheckBox
+ FinalRenderKeepAspectCheckBox
+ FinalRenderScaleNoneRadioButton
+ FinalRenderScaleWidthRadioButton
+ FinalRenderScaleHeightRadioButton
+ FinalRenderJpgRadioButton
+ FinalRenderPngRadioButton
+ FinalRenderPlatformCombo
+ FinalRenderDeviceCombo
+ FinalRenderThreadCountSpin
+ FinalRenderGeometryTable
+ FinalRenderTextOutput
+ StartRenderButton
+ StopRenderButton
+ CloseButton
+
diff --git a/Source/Fractorium/FinalRenderEmberController.cpp b/Source/Fractorium/FinalRenderEmberController.cpp
index 2ca9564..69c443b 100644
--- a/Source/Fractorium/FinalRenderEmberController.cpp
+++ b/Source/Fractorium/FinalRenderEmberController.cpp
@@ -201,6 +201,7 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD
for (i = 0; i < m_EmberFile.m_Embers.size() && m_Run; i++)
{
m_Renderer->Reset();//Have to manually set this since the ember is not set each time through.
+ m_PureIterTime = 0;
m_RenderTimer.Tic();//Toc() is called in the progress function.
if (m_Renderer->Run(m_FinalImage, i) != RENDER_OK)
@@ -223,6 +224,7 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD
for (i = 0; i < m_EmberFile.m_Embers.size() && m_Run; i++)
{
m_Renderer->SetEmber(m_EmberFile.m_Embers[i]);
+ m_PureIterTime = 0;
m_RenderTimer.Tic();//Toc() is called in the progress function.
if (m_Renderer->Run(m_FinalImage) != RENDER_OK)
@@ -240,6 +242,7 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD
ResetProgress();
m_Ember.m_TemporalSamples = 1;
m_Renderer->SetEmber(m_Ember);
+ m_PureIterTime = 0;
m_RenderTimer.Tic();//Toc() is called in the progress function.
if (m_Renderer->Run(m_FinalImage) != RENDER_OK)
@@ -288,22 +291,29 @@ template
int FinalRenderEmberController::ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs)
{
static int count = 0;
+ int intFract = (int)fraction;
if (stage == 0)
- QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(fraction)));
+ {
+ QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract));
+
+ if (intFract == 100)
+ m_PureIterTime = m_RenderTimer.Toc();
+ }
else if (stage == 1)
- QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(fraction)));
+ QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract));
else if (stage == 2)
- QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(fraction)));
+ QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract));
//Finished, so take special action.
- if (stage == 2 && (int)fraction == 100)
+ if (stage == 2 && intFract == 100)
{
string renderTimeString = m_RenderTimer.Format(m_RenderTimer.Toc()), totalTimeString;
QString status, filename = m_GuiState.m_Path;
QFileInfo original(filename);
EmberStats stats = m_Renderer->Stats();
QString iters = QLocale(QLocale::English).toString(stats.m_Iters);
+ QString itersPerSec = QLocale(QLocale::English).toString(int(stats.m_Iters / (m_PureIterTime / 1000.0)));
if (m_GuiState.m_DoAll && m_EmberFile.m_Embers.size() > 1)
filename = original.absolutePath() + QDir::separator() + m_GuiState.m_Prefix + QString::fromStdString(m_EmberFile.m_Embers[m_FinishedImageCount].m_Name) + m_GuiState.m_Suffix + "." + m_GuiState.m_DoAllExt;
@@ -348,9 +358,9 @@ int FinalRenderEmberController::ProgressFunc(Ember& ember, void* foo, doub
}
m_FinishedImageCount++;
- QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(100)));//Just to be safe.
- QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(100)));
- QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(100)));
+ QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100));//Just to be safe.
+ QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100));
+ QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100));
QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(((float)m_FinishedImageCount / (float)m_ImageCount) * 100)));
QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(QString, QString::number(m_FinishedImageCount) + " / " + QString::number(m_ImageCount)));
@@ -358,7 +368,7 @@ int FinalRenderEmberController::ProgressFunc(Ember& ember, void* foo, doub
QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(QString, status));
totalTimeString = m_TotalTimer.Format(m_TotalTimer.Toc());
- status = "Total render time: " + QString::fromStdString(totalTimeString) + "\nTotal iters: " + iters + "\n";
+ status = "Total render time: " + QString::fromStdString(totalTimeString) + "\nTotal iters: " + iters + "\nIters/second: " + itersPerSec + "\n";
QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(QString, status));
QMetaObject::invokeMethod(m_FinalRender, "MoveCursorToEnd", Qt::QueuedConnection);
diff --git a/Source/Fractorium/FinalRenderEmberController.h b/Source/Fractorium/FinalRenderEmberController.h
index 82ef798..5d59556 100644
--- a/Source/Fractorium/FinalRenderEmberController.h
+++ b/Source/Fractorium/FinalRenderEmberController.h
@@ -76,6 +76,7 @@ protected:
bool m_PreviewRun;
unsigned int m_ImageCount;
unsigned int m_FinishedImageCount;
+ double m_PureIterTime;
QFuture m_Result;
QFuture m_PreviewResult;
diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp
index 285bd4a..bcb77ff 100644
--- a/Source/Fractorium/Fractorium.cpp
+++ b/Source/Fractorium/Fractorium.cpp
@@ -144,6 +144,8 @@ Fractorium::Fractorium(QWidget* parent)
ui.GLDisplay->SetMainWindow(this);
SetCoordinateStatus(0, 0, 0, 0);
+ SetTabOrders();
+
//At this point, everything has been setup except the renderer. Shortly after
//this constructor exits, GLWidget::initializeGL() will create the initial flock and start the rendering timer
//which executes whenever the program is idle. Upon starting the timer, the renderer
@@ -527,6 +529,134 @@ QString Fractorium::SetupSaveFolderDialog()
return filename;
}
+///
+/// Explicitly set the tab orders for the entire program.
+/// Qt has a facility to do this, but it fails when using custom widgets in
+/// tables, so it must be done manually here.
+/// This list must be kept in sync with any UI changes.
+///
+void Fractorium::SetTabOrders()
+{
+ QWidget* w = SetTabOrder(this, ui.ColorTable, m_BrightnessSpin);//Flame.
+
+ w = SetTabOrder(this, w, m_GammaSpin);
+ w = SetTabOrder(this, w, m_GammaThresholdSpin);
+ w = SetTabOrder(this, w, m_VibrancySpin);
+ w = SetTabOrder(this, w, m_HighlightSpin);
+ w = SetTabOrder(this, w, m_BackgroundColorButton);
+ w = SetTabOrder(this, w, m_PaletteModeCombo);
+
+ w = SetTabOrder(this, w, m_CenterXSpin);
+ w = SetTabOrder(this, w, m_CenterYSpin);
+ w = SetTabOrder(this, w, m_ScaleSpin);
+ w = SetTabOrder(this, w, m_ZoomSpin);
+ w = SetTabOrder(this, w, m_RotateSpin);
+ w = SetTabOrder(this, w, m_ZPosSpin);
+ w = SetTabOrder(this, w, m_PerspectiveSpin);
+ w = SetTabOrder(this, w, m_PitchSpin);
+ w = SetTabOrder(this, w, m_YawSpin);
+ w = SetTabOrder(this, w, m_DepthBlurSpin);
+
+ w = SetTabOrder(this, w, m_SpatialFilterWidthSpin);
+ w = SetTabOrder(this, w, m_SpatialFilterTypeCombo);
+ w = SetTabOrder(this, w, m_TemporalFilterTypeCombo);
+ w = SetTabOrder(this, w, m_DEFilterMinRadiusSpin);
+ w = SetTabOrder(this, w, m_DEFilterMaxRadiusSpin);
+ w = SetTabOrder(this, w, m_DECurveSpin);
+
+ w = SetTabOrder(this, w, m_PassesSpin);
+ w = SetTabOrder(this, w, m_TemporalSamplesSpin);
+ w = SetTabOrder(this, w, m_QualitySpin);
+ w = SetTabOrder(this, w, m_SupersampleSpin);
+ w = SetTabOrder(this, w, m_AffineInterpTypeCombo);
+ w = SetTabOrder(this, w, m_InterpTypeCombo);
+
+ w = SetTabOrder(this, ui.CurrentXformCombo, ui.AddXformButton);//Xforms.
+ w = SetTabOrder(this, w, ui.DuplicateXformButton);
+ w = SetTabOrder(this, w, ui.ClearXformButton);
+ w = SetTabOrder(this, w, ui.DeleteXformButton);
+ w = SetTabOrder(this, w, ui.AddFinalXformButton);
+ w = SetTabOrder(this, w, m_XformWeightSpin);
+ w = SetTabOrder(this, w, m_XformWeightSpinnerButtonWidget->m_Button);
+
+ w = SetTabOrder(this, m_XformColorIndexSpin, ui.XformColorScroll);//Xforms color.
+ w = SetTabOrder(this, w, m_XformColorSpeedSpin);
+ w = SetTabOrder(this, w, m_XformOpacitySpin);
+ w = SetTabOrder(this, w, m_XformDirectColorSpin);
+ w = SetTabOrder(this, w, ui.SoloXformCheckBox);
+
+ w = SetTabOrder(this, ui.PreAffineGroupBox, m_PreX1Spin);//Xforms affine.
+ w = SetTabOrder(this, w, m_PreX2Spin);
+ w = SetTabOrder(this, w, m_PreY1Spin);
+ w = SetTabOrder(this, w, m_PreY2Spin);
+ w = SetTabOrder(this, w, m_PreO1Spin);
+ w = SetTabOrder(this, w, m_PreO2Spin);
+ w = SetTabOrder(this, w, ui.PreFlipVerticalButton);
+ w = SetTabOrder(this, w, ui.PreResetButton);
+ w = SetTabOrder(this, w, ui.PreFlipHorizontalButton);
+ w = SetTabOrder(this, w, ui.PreRotate90CcButton);
+ w = SetTabOrder(this, w, ui.PreRotateCcButton);
+ w = SetTabOrder(this, w, ui.PreRotateCombo);
+ w = SetTabOrder(this, w, ui.PreRotateCButton);
+ w = SetTabOrder(this, w, ui.PreRotate90CButton);
+ w = SetTabOrder(this, w, ui.PreMoveUpButton);
+ w = SetTabOrder(this, w, ui.PreMoveDownButton);
+ w = SetTabOrder(this, w, ui.PreMoveCombo);
+ w = SetTabOrder(this, w, ui.PreMoveLeftButton);
+ w = SetTabOrder(this, w, ui.PreMoveRightButton);
+ w = SetTabOrder(this, w, ui.PreScaleUpButton);
+ w = SetTabOrder(this, w, ui.PreScaleCombo);
+ w = SetTabOrder(this, w, ui.PreScaleDownButton);
+ w = SetTabOrder(this, w, ui.ShowPreAffineCurrentRadio);
+ w = SetTabOrder(this, w, ui.ShowPreAffineAllRadio);
+ w = SetTabOrder(this, w, ui.PostAffineGroupBox);
+ w = SetTabOrder(this, w, m_PostX1Spin);
+ w = SetTabOrder(this, w, m_PostX2Spin);
+ w = SetTabOrder(this, w, m_PostY1Spin);
+ w = SetTabOrder(this, w, m_PostY2Spin);
+ w = SetTabOrder(this, w, m_PostO1Spin);
+ w = SetTabOrder(this, w, m_PostO2Spin);
+ w = SetTabOrder(this, w, ui.PostFlipVerticalButton);
+ w = SetTabOrder(this, w, ui.PostResetButton);
+ w = SetTabOrder(this, w, ui.PostFlipHorizontalButton);
+ w = SetTabOrder(this, w, ui.PostRotate90CcButton);
+ w = SetTabOrder(this, w, ui.PostRotateCcButton);
+ w = SetTabOrder(this, w, ui.PostRotateCombo);
+ w = SetTabOrder(this, w, ui.PostRotateCButton);
+ w = SetTabOrder(this, w, ui.PostRotate90CButton);
+ w = SetTabOrder(this, w, ui.PostMoveUpButton);
+ w = SetTabOrder(this, w, ui.PostMoveDownButton);
+ w = SetTabOrder(this, w, ui.PostMoveCombo);
+ w = SetTabOrder(this, w, ui.PostMoveLeftButton);
+ w = SetTabOrder(this, w, ui.PostMoveRightButton);
+ w = SetTabOrder(this, w, ui.PostScaleUpButton);
+ w = SetTabOrder(this, w, ui.PostScaleCombo);
+ w = SetTabOrder(this, w, ui.PostScaleDownButton);
+ w = SetTabOrder(this, w, ui.ShowPostAffineCurrentRadio);
+ w = SetTabOrder(this, w, ui.ShowPostAffineAllRadio);
+ w = SetTabOrder(this, w, ui.LocalPivotRadio);
+ w = SetTabOrder(this, w, ui.WorldPivotRadio);
+
+ w = SetTabOrder(this, ui.VariationsFilterLineEdit, ui.VariationsFilterClearButton);//Xforms variation.
+ w = SetTabOrder(this, w, ui.VariationsTree);
+
+ //Xforms xaos is done dynamically every time.
+
+ w = SetTabOrder(this, m_PaletteHueSpin, m_PaletteContrastSpin);//Palette.
+ w = SetTabOrder(this, w, m_PaletteSaturationSpin);
+ w = SetTabOrder(this, w, m_PaletteBlurSpin);
+ w = SetTabOrder(this, w, m_PaletteBrightnessSpin);
+ w = SetTabOrder(this, w, m_PaletteFrequencySpin);
+ w = SetTabOrder(this, w, ui.PaletteListTable);
+
+ w = SetTabOrder(this, ui.InfoBoundsGroupBox, ui.InfoBoundsFrame);//Info.
+ w = SetTabOrder(this, w, ui.InfoBoundsTable);
+ w = SetTabOrder(this, w, ui.InfoFileOpeningGroupBox);
+ w = SetTabOrder(this, w, ui.InfoFileOpeningTextEdit);
+ w = SetTabOrder(this, w, ui.InfoRenderingGroupBox);
+ w = SetTabOrder(this, w, ui.InfoRenderingTextEdit);
+}
+
///
/// This is no longer needed and was used to compensate for a different bug
/// however the code is interesting, so keep it around for possible future use.
diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h
index c2dc2a8..5cbb6f5 100644
--- a/Source/Fractorium/Fractorium.h
+++ b/Source/Fractorium/Fractorium.h
@@ -260,6 +260,7 @@ private:
void InitXformsXaosUI();
void InitPaletteUI();
void InitLibraryUI();
+ void SetTabOrders();
//Embers.
bool HaveFinal();
@@ -446,5 +447,19 @@ static void SetupSpinner(QTableWidget* table, const QObject* receiver, int& row,
row++;
}
+///
+/// Wrapper around QWidget::setTabOrder() to return the second widget.
+/// This makes it easy to chain multiple calls without having to retype
+/// all of them if the order changes or if a new widget is inserted.
+///
+/// The parent widget that w1 and w2 belong to
+/// The widget to come first in the tab order
+/// The widget to come second in the tab order
+static QWidget* SetTabOrder(QWidget* parent, QWidget* w1, QWidget* w2)
+{
+ parent->setTabOrder(w1, w2);
+ return w2;
+}
+
//template void Fractorium::SetupSpinner (QTableWidget* table, const QObject* receiver, int& row, int col, SpinBox*& spinBox, int height, int min, int max, int step, const char* signal, const char* slot, bool incRow, int val, int doubleClickZero, int doubleClickNonZero);
//template void Fractorium::SetupSpinner(QTableWidget* table, const QObject* receiver, int& row, int col, DoubleSpinBox*& spinBox, int height, double min, double max, double step, const char* signal, const char* slot, bool incRow, double val, double doubleClickZero, double doubleClickNonZero);
diff --git a/Source/Fractorium/Fractorium.rc b/Source/Fractorium/Fractorium.rc
index 2e8866c..e8d6d0f 100644
Binary files a/Source/Fractorium/Fractorium.rc and b/Source/Fractorium/Fractorium.rc differ
diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui
index 8806d71..aa8406d 100644
--- a/Source/Fractorium/Fractorium.ui
+++ b/Source/Fractorium/Fractorium.ui
@@ -340,7 +340,7 @@
QTabWidget::Triangular
- 2
+ 0
true
@@ -403,6 +403,9 @@
-
+
+ Qt::StrongFocus
+
Qt::CustomContextMenu
@@ -525,6 +528,9 @@
22
+
+ Qt::NoFocus
+
QFrame::Panel
@@ -603,6 +609,9 @@
22
+
+ Qt::NoFocus
+
QFrame::Panel
@@ -688,7 +697,7 @@
Qt::NoFocus
- true
+ false
QFrame::Panel
@@ -705,6 +714,9 @@
QAbstractItemView::NoEditTriggers
+
+ false
+
false
@@ -923,6 +935,9 @@
QAbstractItemView::NoEditTriggers
+
+ false
+
false
@@ -1105,6 +1120,9 @@
22
+
+ Qt::NoFocus
+
QFrame::Panel
@@ -1183,6 +1201,9 @@
22
+
+ Qt::NoFocus
+
QFrame::Panel
@@ -1276,6 +1297,9 @@
QAbstractItemView::NoEditTriggers
+
+ false
+
false
@@ -1520,6 +1544,9 @@
QAbstractItemView::NoEditTriggers
+
+ false
+
false
@@ -1899,7 +1926,7 @@
- Qt::NoFocus
+ Qt::StrongFocus
false
@@ -1922,6 +1949,9 @@
QAbstractItemView::DoubleClicked|QAbstractItemView::SelectedClicked
+
+ false
+
QAbstractItemView::NoSelection
@@ -2312,6 +2342,9 @@ SpinBox
QAbstractItemView::NoEditTriggers
+
+ false
+
false
@@ -2498,6 +2531,9 @@ SpinBox
QAbstractItemView::NoEditTriggers
+
+ false
+
QAbstractItemView::NoSelection
@@ -2600,6 +2636,9 @@ SpinBox
QAbstractItemView::NoEditTriggers
+
+ false
+
QAbstractItemView::NoSelection
@@ -2674,6 +2713,9 @@ SpinBox
16
+
+ Qt::StrongFocus
+
255
@@ -2739,8 +2781,8 @@ SpinBox
0
0
- 118
- 597
+ 238
+ 752
@@ -2882,6 +2924,9 @@ SpinBox
QAbstractItemView::NoEditTriggers
+
+ false
+
QAbstractItemView::NoSelection
@@ -3483,6 +3528,9 @@ SpinBox
QAbstractItemView::NoEditTriggers
+
+ false
+
QAbstractItemView::NoSelection
@@ -4352,6 +4400,9 @@ SpinBox
QAbstractItemView::NoEditTriggers
+
+ false
+
false
@@ -4569,6 +4620,9 @@ SpinBox
QAbstractItemView::NoEditTriggers
+
+ false
+
QAbstractItemView::NoSelection
@@ -4661,7 +4715,7 @@ SpinBox
-
- Qt::NoFocus
+ Qt::StrongFocus
QFrame::Panel
@@ -4678,6 +4732,9 @@ SpinBox
QAbstractItemView::NoEditTriggers
+
+ false
+
QAbstractItemView::NoSelection
@@ -4944,6 +5001,9 @@ SpinBox
250
+
+ Qt::StrongFocus
+
false
@@ -5250,6 +5310,9 @@ SpinBox
0
+
+ Qt::StrongFocus
+
Rendering
@@ -5271,9 +5334,18 @@ SpinBox
-
+
+ Qt::StrongFocus
+
+
+ true
+
true
+
+ Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
@@ -5287,6 +5359,9 @@ SpinBox
0
+
+ Qt::StrongFocus
+
File Opening
@@ -5308,6 +5383,9 @@ SpinBox
-
+
+ Qt::StrongFocus
+
true
@@ -5644,6 +5722,86 @@ SpinBox
1
+
+ DockWidget
+ SaveCurrentAsXmlButton
+ SaveEntireFileAsXmlButton
+ SaveCurrentToOpenedFileButton
+ ParamsTabWidget
+ LibraryTree
+ scrollArea
+ CurrentXformCombo
+ AddXformButton
+ DuplicateXformButton
+ ClearXformButton
+ DeleteXformButton
+ AddFinalXformButton
+ XformWeightNameTable
+ XformsTabWidget
+ XformColorIndexTable
+ XformColorScroll
+ XformColorValuesTable
+ SoloXformCheckBox
+ scrollArea_3
+ PreAffineTable
+ PreFlipVerticalButton
+ PreResetButton
+ PreFlipHorizontalButton
+ PreRotate90CcButton
+ PreRotateCcButton
+ PreRotateCombo
+ PreRotateCButton
+ PreRotate90CButton
+ PreMoveUpButton
+ PreMoveDownButton
+ PreMoveCombo
+ PreMoveLeftButton
+ PreMoveRightButton
+ PreScaleUpButton
+ PreScaleCombo
+ PreScaleDownButton
+ ShowPreAffineCurrentRadio
+ ShowPreAffineAllRadio
+ PostAffineGroupBox
+ PostAffineTable
+ PostFlipVerticalButton
+ PostResetButton
+ PostFlipHorizontalButton
+ PostRotate90CcButton
+ PostRotateCcButton
+ PostRotateCombo
+ PostRotateCButton
+ PostRotate90CButton
+ PostMoveUpButton
+ PostMoveDownButton
+ PostMoveCombo
+ PostMoveLeftButton
+ PostMoveRightButton
+ PostScaleUpButton
+ PostScaleCombo
+ PostScaleDownButton
+ ShowPostAffineCurrentRadio
+ ShowPostAffineAllRadio
+ LocalPivotRadio
+ WorldPivotRadio
+ VariationsFilterLineEdit
+ VariationsFilterClearButton
+ VariationsTree
+ XaosTable
+ PaletteAdjustTable
+ PaletteListTable
+ scrollArea_5
+ InfoFileOpeningGroupBox
+ InfoFileOpeningTextEdit
+ InfoRenderingGroupBox
+ InfoRenderingTextEdit
+ PreAffineGroupBox
+ scrollArea_4
+ ClearXaosButton
+ InfoBoundsGroupBox
+ XaosFromRadio
+ XaosToRadio
+
diff --git a/Source/Fractorium/FractoriumXformsVariations.cpp b/Source/Fractorium/FractoriumXformsVariations.cpp
index 331ad52..7a8890e 100644
--- a/Source/Fractorium/FractoriumXformsVariations.cpp
+++ b/Source/Fractorium/FractoriumXformsVariations.cpp
@@ -44,8 +44,8 @@ void FractoriumEmberController::SetupVariationTree()
ParametricVariation* parVar = dynamic_cast*>(var);
//First add the variation, with a spinner for its weight.
- VariationTreeWidgetItem* item = new VariationTreeWidgetItem(tree);
- VariationTreeDoubleSpinBox* spinBox = new VariationTreeDoubleSpinBox(tree, parVar ? parVar : var, "");
+ VariationTreeWidgetItem* item = new VariationTreeWidgetItem(var->VariationId(), tree);
+ VariationTreeDoubleSpinBox* spinBox = new VariationTreeDoubleSpinBox(tree, item, parVar ? parVar : var, "");
item->setText(0, QString::fromStdString(var->Name()));
item->setSizeHint(0, hint0);
@@ -68,8 +68,8 @@ void FractoriumEmberController::SetupVariationTree()
{
if (!params[j].IsPrecalc())
{
- VariationTreeWidgetItem* paramWidget = new VariationTreeWidgetItem(item);
- VariationTreeDoubleSpinBox* varSpinBox = new VariationTreeDoubleSpinBox(tree, parVar, params[j].Name());
+ VariationTreeWidgetItem* paramWidget = new VariationTreeWidgetItem(var->VariationId(), item);
+ VariationTreeDoubleSpinBox* varSpinBox = new VariationTreeDoubleSpinBox(tree, paramWidget, parVar, params[j].Name());
paramWidget->setText(0, params[j].Name().c_str());
paramWidget->setSizeHint(0, hint0);
@@ -144,7 +144,7 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d)
Variation* var = sender->GetVariation();//The variation attached to the sender, for reference only.
ParametricVariation* parVar = dynamic_cast*>(var);//The parametric cast of that variation.
Variation* xformVar = xform->GetVariationById(var->VariationId());//The corresponding variation in the currently selected xform.
- QList items = tree->findItems(QString::fromStdString(var->Name()), Qt::MatchExactly);
+ VariationTreeWidgetItem* widgetItem = sender->WidgetItem();
bool isParam = parVar && sender->IsParam();
if (isParam)
@@ -167,7 +167,7 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d)
if (xformVar)
xform->DeleteVariationById(var->VariationId());
- items[0]->setBackgroundColor(0, QColor(255, 255, 255));//Ensure background is always white if weight goes to zero.
+ widgetItem->setBackgroundColor(0, QColor(255, 255, 255));//Ensure background is always white if weight goes to zero.
}
else
{
@@ -183,7 +183,7 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d)
newVar->m_Weight = d;
xform->AddVariation(newVar);
- items[0]->setBackgroundColor(0, QColor(200, 200, 200));//Set background to gray when a variation has non-zero weight in this xform.
+ widgetItem->setBackgroundColor(0, QColor(200, 200, 200));//Set background to gray when a variation has non-zero weight in this xform.
//If they've added a new parametric variation, then grab the values currently in the spinners
//for the child parameters and assign them to the newly added variation.
@@ -191,19 +191,16 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d)
{
ParametricVariation* newParVar = dynamic_cast*>(newVar);
- if (!items.empty())//Get the tree widget for the parent variation.
+ for (int i = 0; i < widgetItem->childCount(); i++)//Iterate through all of the children, which will be the params.
{
- for (int i = 0; i < items[0]->childCount(); i++)//Iterate through all of the children, which will be the params.
+ QTreeWidgetItem* childItem = widgetItem->child(i);//Get the child.
+ QWidget* itemWidget = tree->itemWidget(childItem, 1);//Get the widget for the child.
+
+ if (VariationTreeDoubleSpinBox* spinBox = dynamic_cast*>(itemWidget))//Cast the widget to the VariationTreeDoubleSpinBox type.
{
- QTreeWidgetItem* childItem = items[0]->child(i);//Get the child.
- QWidget* itemWidget = tree->itemWidget(childItem, 1);//Get the widget for the child.
+ string s = childItem->text(0).toStdString();//Use the name of the child, and the value of the spinner widget to assign the param.
- if (VariationTreeDoubleSpinBox* spinBox = dynamic_cast*>(itemWidget))//Cast the widget to the VariationTreeDoubleSpinBox type.
- {
- string s = childItem->text(0).toStdString();//Use the name of the child, and the value of the spinner widget to assign the param.
-
- newParVar->SetParamVal(s.c_str(), spinBox->value());
- }
+ newParVar->SetParamVal(s.c_str(), spinBox->value());
}
}
}
@@ -231,14 +228,12 @@ void FractoriumEmberController::FillVariationTreeWithXform(Xform* xform)
for (unsigned int i = 0; i < tree->topLevelItemCount(); i++)
{
- QTreeWidgetItem* item = tree->topLevelItem(i);
- string varName = item->text(0).toStdString();
- Variation* var = xform->GetVariationByName(varName);//See if this variation in the tree was contained in the xform.
+ VariationTreeWidgetItem* item = dynamic_cast*>(tree->topLevelItem(i));
+ Variation* var = xform->GetVariationById(item->Id());//See if this variation in the tree was contained in the xform.
ParametricVariation* parVar = dynamic_cast*>(var);//Attempt cast to parametric variation for later.
- ParametricVariation* origParVar = dynamic_cast*>(m_VariationList.GetVariation(varName));
- QWidget* itemWidget = tree->itemWidget(item, 1);//Get the widget for the item.
+ ParametricVariation* origParVar = dynamic_cast*>(m_VariationList.GetVariation(item->Id()));
- if (VariationTreeDoubleSpinBox* spinBox = dynamic_cast*>(itemWidget))//Cast the widget to the VariationTreeDoubleSpinBox type.
+ if (VariationTreeDoubleSpinBox* spinBox = dynamic_cast*>(tree->itemWidget(item, 1)))//Get the widget for the item, and cast the widget to the VariationTreeDoubleSpinBox type.
{
spinBox->SetValueStealth(var ? var->m_Weight : 0);//If the variation was present, set the spin box to its weight, else zero.
item->setBackgroundColor(0, var ? QColor(200, 200, 200) : QColor(255, 255, 255));//Ensure background is always white if the value goes to zero, else gray if var present.
diff --git a/Source/Fractorium/FractoriumXformsXaos.cpp b/Source/Fractorium/FractoriumXformsXaos.cpp
index 7489471..2b16402 100644
--- a/Source/Fractorium/FractoriumXformsXaos.cpp
+++ b/Source/Fractorium/FractoriumXformsXaos.cpp
@@ -136,7 +136,7 @@ void Fractorium::OnXaosFromToToggled(bool checked)
void Fractorium::FillXaosTable()
{
int spinHeight = 20;
-
+ QWidget* w;
ui.XaosTable->setRowCount(m_Controller->XformCount());//This will grow or shrink the number of rows and call the destructor for previous DoubleSpinBoxes.
for (int i = 0; i < m_Controller->XformCount(); i++)
@@ -150,7 +150,16 @@ void Fractorium::FillXaosTable()
ui.XaosTable->setItem(i, 0, xformNameItem);
ui.XaosTable->setCellWidget(i, 1, spinBox);
connect(spinBox, SIGNAL(valueChanged(double)), this, SLOT(OnXaosChanged(double)), Qt::QueuedConnection);
+
+ if (i > 0)
+ w = SetTabOrder(this, w, spinBox);
+ else
+ w = spinBox;
}
+
+ w = SetTabOrder(this, w, ui.XaosToRadio);
+ w = SetTabOrder(this, w, ui.XaosFromRadio);
+ w = SetTabOrder(this, w, ui.ClearXaosButton);
}
///
diff --git a/Source/Fractorium/GLWidget.cpp b/Source/Fractorium/GLWidget.cpp
index bad50bd..c71b005 100644
--- a/Source/Fractorium/GLWidget.cpp
+++ b/Source/Fractorium/GLWidget.cpp
@@ -477,12 +477,14 @@ void GLEmberController::MousePress(QMouseEvent* e)
//The user has selected an xform by clicking on it, so update the main GUI by selecting this xform in the combo box.
m_Fractorium->CurrentXform(xformIndex);
- //Update selected xform dot.
- bool pre = m_Fractorium->ui.PreAffineGroupBox->isChecked();
- bool post = m_Fractorium->ui.PostAffineGroupBox->isChecked();
-
- DrawAffines(pre, post);
- m_GL->update();
+ //Draw large yellow dot on select or drag.
+ m_GL->glPointSize(6.0f);
+ m_GL->glBegin(GL_POINTS);
+ m_GL->glColor4f(1.0f, 1.0f, 0.5f, 1.0f);
+ m_GL->glVertex2f(m_DragHandlePos.x, m_DragHandlePos.y);
+ m_GL->glEnd();
+ m_GL->glPointSize(1.0f);//Restore point size.
+ m_GL->repaint();
}
else//Nothing was selected.
{
diff --git a/Source/Fractorium/OptionsDialog.ui b/Source/Fractorium/OptionsDialog.ui
index d56b0df..6410e89 100644
--- a/Source/Fractorium/OptionsDialog.ui
+++ b/Source/Fractorium/OptionsDialog.ui
@@ -52,6 +52,9 @@
0
+
+ Qt::NoFocus
+
QTabWidget::Triangular
@@ -728,6 +731,26 @@ in interactive mode for each mouse movement
+
+ EarlyClipCheckBox
+ YAxisUpCheckBox
+ TransparencyCheckBox
+ OpenCLCheckBox
+ DoublePrecisionCheckBox
+ ShowAllXformsCheckBox
+ PlatformCombo
+ DeviceCombo
+ ThreadCountSpin
+ CpuSubBatchSpin
+ OpenCLSubBatchSpin
+ CpuFilteringLogRadioButton
+ CpuFilteringDERadioButton
+ OpenCLFilteringLogRadioButton
+ OpenCLFilteringDERadioButton
+ OptionsXmlSavingTable
+ OptionsIdentityTable
+ OptionsButtonBox
+
diff --git a/Source/Fractorium/VariationTreeWidgetItem.h b/Source/Fractorium/VariationTreeWidgetItem.h
index d051872..7c9c904 100644
--- a/Source/Fractorium/VariationTreeWidgetItem.h
+++ b/Source/Fractorium/VariationTreeWidgetItem.h
@@ -21,10 +21,12 @@ public:
/// Constructor that takes a pointer to a QTreeWidget as the parent
/// and passes it to the base.
///
+ /// The ID of the variation this widget will represent
/// The parent widget
- VariationTreeWidgetItem(QTreeWidget* parent = 0)
+ VariationTreeWidgetItem(eVariationId id, QTreeWidget* parent = 0)
: QTreeWidgetItem(parent)
{
+ m_Id = id;
}
///
@@ -32,13 +34,16 @@ public:
/// and passes it to the base.
/// This is used for making sub items for parametric variation parameters.
///
+ /// The ID of the variation this widget will represent
/// The parent widget
- VariationTreeWidgetItem(QTreeWidgetItem* parent = 0)
+ VariationTreeWidgetItem(eVariationId id, QTreeWidgetItem* parent = 0)
: QTreeWidgetItem(parent)
{
+ m_Id = id;
}
virtual ~VariationTreeWidgetItem() { }
+ eVariationId Id() { return m_Id; }
private:
///
@@ -86,4 +91,6 @@ private:
return false;
}
+
+ eVariationId m_Id;
};
\ No newline at end of file