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 @@
TableWidget.h
+ + 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
TableWidget.h
+ + 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