0.4.0.9 Beta 07/27/2014

0.4.0.9 Beta 07/27/2014
--User Changes
Properly set tab order on all controls.
Calculate and report iters/second in the final render dialog.
Immediately draw yellow dot on xform mouse down on previously unselected
xform.

--Bug Fixes
Fix GlynnSim1, GlynnSim2, GlynnSim3 and juliaNab by ensuring the first
argument to pow() is >= 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().
This commit is contained in:
mfeemster 2014-07-27 22:25:38 -07:00
parent a5d69c75a2
commit 88a325a5cd
28 changed files with 561 additions and 111 deletions

3
.gitignore vendored
View File

@ -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
Builds/MSVC/VS2010/Obj/Ember/x64/Debug/Ember_manifest.rc
Bin/x64/Release/testallvarsout.flame

View File

@ -6,7 +6,7 @@
<ProductVersion>3.7</ProductVersion>
<ProjectGuid>{c8096c47-e358-438c-a520-146d46b0637d}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>Fractorium_Beta_0.4.0.8</OutputName>
<OutputName>Fractorium_Beta_0.4.0.9</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ProductVersion="0.4.0.8" ?>
<?define ProductVersion="0.4.0.9" ?>
<?define ProductName="Fractorium Beta $(var.ProductVersion) ($(var.GpuType))" ?>
<?define UpgradeCode="{4714cd15-bfba-44f6-8059-9e1466ebfa6e}"?>
<?define Manufacturer="Fractorium"?>
@ -13,7 +13,7 @@
<!--
Change this for every release.
-->
<?define ProductCode="{567692F8-C869-4EEA-98C4-5D69982F9F76}"?>
<?define ProductCode="{FCD71232-4553-4224-9328-A1B039A5A773}"?>
<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package

BIN
Data/Bench.xlsx Normal file

Binary file not shown.

View File

@ -1,3 +1,17 @@
0.4.0.9 Beta 07/27/2014
--User Changes
Properly set tab order on all controls.
Calculate and report iters/second in the final render dialog.
Immediately draw yellow dot on xform mouse down on previously unselected xform.
--Bug Fixes
Fix GlynnSim1, GlynnSim2, GlynnSim3 and juliaNab by ensuring the first argument to pow() is >= 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.

View File

@ -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<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
#define ISAAC_SIZE 4

View File

@ -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"

View File

@ -424,7 +424,7 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& 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<T>() > 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<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& 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<T>() > 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<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& 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<T>() > 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<T>(m_Power);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "sineblur_power", 1));
m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "sineblur_power", 1, REAL, 0));
}
private:

View File

@ -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<T>(rand.Frand01<T>() * m_AbsN)) / jun;
T a = (atan2(helper.In.y, pow(fabs(helper.In.x), m_Sep)) + M_2PI * Floor<T>(rand.Frand01<T>() * 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<T>(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<T>(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)

View File

@ -1085,9 +1085,9 @@ public:
T cv = cos(helper.In.y);
T cucv = cu * cv;
T sucv = su * cv;
T x = pow(ClampGte<T>(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<T>(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<T>(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<T>(rs, 0, T(0.9)) + T(0.1);
denom = 1 / scale;
helper.Out.x = m_Weight * Lerp<T>(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<T>(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<T>(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<T>(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<T>(helper.In.z, floor(helper.In.z * denom) + scale * az, m_MulZ * rs) + m_MulZ * pow(az, m_BoxPow) * rs * denom;
break;
}

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -52,7 +52,7 @@
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fractorium 0.4.0.8 Beta&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;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.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Matt Feemster&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fractorium 0.4.0.9 Beta&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;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.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Matt Feemster&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>

View File

@ -45,6 +45,12 @@ private:
double m_SmallStep;
};
/// <summary>
/// VariationTreeWidgetItem and VariationTreeDoubleSpinBox need each other, but each can't include the other.
/// So VariationTreeWidgetItem includes this file, and use a forward declaration here.
/// </summary>
template <typename T> class VariationTreeWidgetItem;
/// <summary>
/// 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.
/// </summary>
/// <param name="parent">The parent widget</param>
/// <param name="widgetItem">The widget item this spinner is contained in</param>
/// <param name="var">The variation this spinner is for</param>
/// <param name="param">The name of the parameter this is for</param>
/// <param name="height">The height of the spin box. Default: 16.</param>
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.</param>
explicit VariationTreeDoubleSpinBox(QWidget* parent, Variation<T>* var, string param, int height = 16, double step = 0.05)
explicit VariationTreeDoubleSpinBox(QWidget* parent, VariationTreeWidgetItem<T>* widgetItem, Variation<T>* 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<T>* GetVariation() { return m_Variation; }
VariationTreeWidgetItem<T>* WidgetItem() { return m_WidgetItem; }
private:
string m_Param;
Variation<T>* m_Variation;
VariationTreeWidgetItem<T>* m_WidgetItem;
};

View File

@ -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);
}
/// <summary>

View File

@ -46,6 +46,9 @@
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
@ -352,44 +355,44 @@
</widget>
</item>
<item>
<widget class="QComboBox" name="FinalRenderDeviceCombo">
<widget class="QComboBox" name="FinalRenderPlatformCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="FinalRenderPlatformCombo">
<widget class="QComboBox" name="FinalRenderDeviceCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
@ -476,6 +479,9 @@
<property name="gridStyle">
<enum>Qt::SolidLine</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
@ -828,7 +834,13 @@
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
<enum>Qt::StrongFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
@ -916,6 +928,30 @@
<header>TableWidget.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>FinalRenderEarlyClipCheckBox</tabstop>
<tabstop>FinalRenderYAxisUpCheckBox</tabstop>
<tabstop>FinalRenderTransparencyCheckBox</tabstop>
<tabstop>FinalRenderOpenCLCheckBox</tabstop>
<tabstop>FinalRenderDoublePrecisionCheckBox</tabstop>
<tabstop>FinalRenderSaveXmlCheckBox</tabstop>
<tabstop>FinalRenderDoAllCheckBox</tabstop>
<tabstop>FinalRenderDoSequenceCheckBox</tabstop>
<tabstop>FinalRenderKeepAspectCheckBox</tabstop>
<tabstop>FinalRenderScaleNoneRadioButton</tabstop>
<tabstop>FinalRenderScaleWidthRadioButton</tabstop>
<tabstop>FinalRenderScaleHeightRadioButton</tabstop>
<tabstop>FinalRenderJpgRadioButton</tabstop>
<tabstop>FinalRenderPngRadioButton</tabstop>
<tabstop>FinalRenderPlatformCombo</tabstop>
<tabstop>FinalRenderDeviceCombo</tabstop>
<tabstop>FinalRenderThreadCountSpin</tabstop>
<tabstop>FinalRenderGeometryTable</tabstop>
<tabstop>FinalRenderTextOutput</tabstop>
<tabstop>StartRenderButton</tabstop>
<tabstop>StopRenderButton</tabstop>
<tabstop>CloseButton</tabstop>
</tabstops>
<resources/>
<connections>
<connection>

View File

@ -201,6 +201,7 @@ FinalRenderEmberController<T>::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<T>::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<T>::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 <typename T>
int FinalRenderEmberController<T>::ProgressFunc(Ember<T>& 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<T>::ProgressFunc(Ember<T>& 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<T>::ProgressFunc(Ember<T>& 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);

View File

@ -76,6 +76,7 @@ protected:
bool m_PreviewRun;
unsigned int m_ImageCount;
unsigned int m_FinishedImageCount;
double m_PureIterTime;
QFuture<void> m_Result;
QFuture<void> m_PreviewResult;

View File

@ -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;
}
/// <summary>
/// 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.
/// </summary>
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);
}
/// <summary>
/// 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.

View File

@ -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++;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="parent">The parent widget that w1 and w2 belong to</param>
/// <param name="w1">The widget to come first in the tab order</param>
/// <param name="w2">The widget to come second in the tab order</param>
static QWidget* SetTabOrder(QWidget* parent, QWidget* w1, QWidget* w2)
{
parent->setTabOrder(w1, w2);
return w2;
}
//template void Fractorium::SetupSpinner<SpinBox, int> (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<DoubleSpinBox, double>(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);

Binary file not shown.

View File

@ -340,7 +340,7 @@
<enum>QTabWidget::Triangular</enum>
</property>
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
@ -403,6 +403,9 @@
</property>
<item row="1" column="0">
<widget class="QTreeWidget" name="LibraryTree">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
@ -525,6 +528,9 @@
<height>22</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
@ -603,6 +609,9 @@
<height>22</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
@ -688,7 +697,7 @@
<enum>Qt::NoFocus</enum>
</property>
<property name="acceptDrops">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
@ -705,6 +714,9 @@
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
@ -923,6 +935,9 @@
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
@ -1105,6 +1120,9 @@
<height>22</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
@ -1183,6 +1201,9 @@
<height>22</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
@ -1276,6 +1297,9 @@
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
@ -1520,6 +1544,9 @@
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
@ -1899,7 +1926,7 @@
</font>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
<enum>Qt::StrongFocus</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
@ -1922,6 +1949,9 @@
<property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::SelectedClicked</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
@ -2312,6 +2342,9 @@ SpinBox
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
@ -2498,6 +2531,9 @@ SpinBox
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
@ -2600,6 +2636,9 @@ SpinBox
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
@ -2674,6 +2713,9 @@ SpinBox
<height>16</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
@ -2739,8 +2781,8 @@ SpinBox
<rect>
<x>0</x>
<y>0</y>
<width>118</width>
<height>597</height>
<width>238</width>
<height>752</height>
</rect>
</property>
<property name="palette">
@ -2882,6 +2924,9 @@ SpinBox
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
@ -3483,6 +3528,9 @@ SpinBox
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
@ -4352,6 +4400,9 @@ SpinBox
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
@ -4569,6 +4620,9 @@ SpinBox
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
@ -4661,7 +4715,7 @@ SpinBox
<item row="2" column="0">
<widget class="QTableWidget" name="PaletteListTable">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
<enum>Qt::StrongFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
@ -4678,6 +4732,9 @@ SpinBox
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
@ -4944,6 +5001,9 @@ SpinBox
<height>250</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
@ -5250,6 +5310,9 @@ SpinBox
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="title">
<string>Rendering</string>
</property>
@ -5271,9 +5334,18 @@ SpinBox
</property>
<item>
<widget class="QTextEdit" name="InfoRenderingTextEdit">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="tabChangesFocus">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
@ -5287,6 +5359,9 @@ SpinBox
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="title">
<string>File Opening</string>
</property>
@ -5308,6 +5383,9 @@ SpinBox
</property>
<item>
<widget class="QTextEdit" name="InfoFileOpeningTextEdit">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
@ -5644,6 +5722,86 @@ SpinBox
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>DockWidget</tabstop>
<tabstop>SaveCurrentAsXmlButton</tabstop>
<tabstop>SaveEntireFileAsXmlButton</tabstop>
<tabstop>SaveCurrentToOpenedFileButton</tabstop>
<tabstop>ParamsTabWidget</tabstop>
<tabstop>LibraryTree</tabstop>
<tabstop>scrollArea</tabstop>
<tabstop>CurrentXformCombo</tabstop>
<tabstop>AddXformButton</tabstop>
<tabstop>DuplicateXformButton</tabstop>
<tabstop>ClearXformButton</tabstop>
<tabstop>DeleteXformButton</tabstop>
<tabstop>AddFinalXformButton</tabstop>
<tabstop>XformWeightNameTable</tabstop>
<tabstop>XformsTabWidget</tabstop>
<tabstop>XformColorIndexTable</tabstop>
<tabstop>XformColorScroll</tabstop>
<tabstop>XformColorValuesTable</tabstop>
<tabstop>SoloXformCheckBox</tabstop>
<tabstop>scrollArea_3</tabstop>
<tabstop>PreAffineTable</tabstop>
<tabstop>PreFlipVerticalButton</tabstop>
<tabstop>PreResetButton</tabstop>
<tabstop>PreFlipHorizontalButton</tabstop>
<tabstop>PreRotate90CcButton</tabstop>
<tabstop>PreRotateCcButton</tabstop>
<tabstop>PreRotateCombo</tabstop>
<tabstop>PreRotateCButton</tabstop>
<tabstop>PreRotate90CButton</tabstop>
<tabstop>PreMoveUpButton</tabstop>
<tabstop>PreMoveDownButton</tabstop>
<tabstop>PreMoveCombo</tabstop>
<tabstop>PreMoveLeftButton</tabstop>
<tabstop>PreMoveRightButton</tabstop>
<tabstop>PreScaleUpButton</tabstop>
<tabstop>PreScaleCombo</tabstop>
<tabstop>PreScaleDownButton</tabstop>
<tabstop>ShowPreAffineCurrentRadio</tabstop>
<tabstop>ShowPreAffineAllRadio</tabstop>
<tabstop>PostAffineGroupBox</tabstop>
<tabstop>PostAffineTable</tabstop>
<tabstop>PostFlipVerticalButton</tabstop>
<tabstop>PostResetButton</tabstop>
<tabstop>PostFlipHorizontalButton</tabstop>
<tabstop>PostRotate90CcButton</tabstop>
<tabstop>PostRotateCcButton</tabstop>
<tabstop>PostRotateCombo</tabstop>
<tabstop>PostRotateCButton</tabstop>
<tabstop>PostRotate90CButton</tabstop>
<tabstop>PostMoveUpButton</tabstop>
<tabstop>PostMoveDownButton</tabstop>
<tabstop>PostMoveCombo</tabstop>
<tabstop>PostMoveLeftButton</tabstop>
<tabstop>PostMoveRightButton</tabstop>
<tabstop>PostScaleUpButton</tabstop>
<tabstop>PostScaleCombo</tabstop>
<tabstop>PostScaleDownButton</tabstop>
<tabstop>ShowPostAffineCurrentRadio</tabstop>
<tabstop>ShowPostAffineAllRadio</tabstop>
<tabstop>LocalPivotRadio</tabstop>
<tabstop>WorldPivotRadio</tabstop>
<tabstop>VariationsFilterLineEdit</tabstop>
<tabstop>VariationsFilterClearButton</tabstop>
<tabstop>VariationsTree</tabstop>
<tabstop>XaosTable</tabstop>
<tabstop>PaletteAdjustTable</tabstop>
<tabstop>PaletteListTable</tabstop>
<tabstop>scrollArea_5</tabstop>
<tabstop>InfoFileOpeningGroupBox</tabstop>
<tabstop>InfoFileOpeningTextEdit</tabstop>
<tabstop>InfoRenderingGroupBox</tabstop>
<tabstop>InfoRenderingTextEdit</tabstop>
<tabstop>PreAffineGroupBox</tabstop>
<tabstop>scrollArea_4</tabstop>
<tabstop>ClearXaosButton</tabstop>
<tabstop>InfoBoundsGroupBox</tabstop>
<tabstop>XaosFromRadio</tabstop>
<tabstop>XaosToRadio</tabstop>
</tabstops>
<resources>
<include location="Fractorium.qrc"/>
</resources>

View File

@ -44,8 +44,8 @@ void FractoriumEmberController<T>::SetupVariationTree()
ParametricVariation<T>* parVar = dynamic_cast<ParametricVariation<T>*>(var);
//First add the variation, with a spinner for its weight.
VariationTreeWidgetItem<T>* item = new VariationTreeWidgetItem<T>(tree);
VariationTreeDoubleSpinBox<T>* spinBox = new VariationTreeDoubleSpinBox<T>(tree, parVar ? parVar : var, "");
VariationTreeWidgetItem<T>* item = new VariationTreeWidgetItem<T>(var->VariationId(), tree);
VariationTreeDoubleSpinBox<T>* spinBox = new VariationTreeDoubleSpinBox<T>(tree, item, parVar ? parVar : var, "");
item->setText(0, QString::fromStdString(var->Name()));
item->setSizeHint(0, hint0);
@ -68,8 +68,8 @@ void FractoriumEmberController<T>::SetupVariationTree()
{
if (!params[j].IsPrecalc())
{
VariationTreeWidgetItem<T>* paramWidget = new VariationTreeWidgetItem<T>(item);
VariationTreeDoubleSpinBox<T>* varSpinBox = new VariationTreeDoubleSpinBox<T>(tree, parVar, params[j].Name());
VariationTreeWidgetItem<T>* paramWidget = new VariationTreeWidgetItem<T>(var->VariationId(), item);
VariationTreeDoubleSpinBox<T>* varSpinBox = new VariationTreeDoubleSpinBox<T>(tree, paramWidget, parVar, params[j].Name());
paramWidget->setText(0, params[j].Name().c_str());
paramWidget->setSizeHint(0, hint0);
@ -144,7 +144,7 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)
Variation<T>* var = sender->GetVariation();//The variation attached to the sender, for reference only.
ParametricVariation<T>* parVar = dynamic_cast<ParametricVariation<T>*>(var);//The parametric cast of that variation.
Variation<T>* xformVar = xform->GetVariationById(var->VariationId());//The corresponding variation in the currently selected xform.
QList<QTreeWidgetItem*> items = tree->findItems(QString::fromStdString(var->Name()), Qt::MatchExactly);
VariationTreeWidgetItem<T>* widgetItem = sender->WidgetItem();
bool isParam = parVar && sender->IsParam();
if (isParam)
@ -167,7 +167,7 @@ void FractoriumEmberController<T>::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<T>::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<T>::VariationSpinBoxValueChanged(double d)
{
ParametricVariation<T>* newParVar = dynamic_cast<ParametricVariation<T>*>(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<T>* spinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(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<T>* spinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(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<T>::FillVariationTreeWithXform(Xform<T>* xform)
for (unsigned int i = 0; i < tree->topLevelItemCount(); i++)
{
QTreeWidgetItem* item = tree->topLevelItem(i);
string varName = item->text(0).toStdString();
Variation<T>* var = xform->GetVariationByName(varName);//See if this variation in the tree was contained in the xform.
VariationTreeWidgetItem<T>* item = dynamic_cast<VariationTreeWidgetItem<T>*>(tree->topLevelItem(i));
Variation<T>* var = xform->GetVariationById(item->Id());//See if this variation in the tree was contained in the xform.
ParametricVariation<T>* parVar = dynamic_cast<ParametricVariation<T>*>(var);//Attempt cast to parametric variation for later.
ParametricVariation<T>* origParVar = dynamic_cast<ParametricVariation<T>*>(m_VariationList.GetVariation(varName));
QWidget* itemWidget = tree->itemWidget(item, 1);//Get the widget for the item.
ParametricVariation<T>* origParVar = dynamic_cast<ParametricVariation<T>*>(m_VariationList.GetVariation(item->Id()));
if (VariationTreeDoubleSpinBox<T>* spinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(itemWidget))//Cast the widget to the VariationTreeDoubleSpinBox type.
if (VariationTreeDoubleSpinBox<T>* spinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(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.

View File

@ -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);
}
/// <summary>

View File

@ -477,12 +477,14 @@ void GLEmberController<T>::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.
{

View File

@ -52,6 +52,9 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Triangular</enum>
</property>
@ -728,6 +731,26 @@ in interactive mode for each mouse movement</string>
<header>TableWidget.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>EarlyClipCheckBox</tabstop>
<tabstop>YAxisUpCheckBox</tabstop>
<tabstop>TransparencyCheckBox</tabstop>
<tabstop>OpenCLCheckBox</tabstop>
<tabstop>DoublePrecisionCheckBox</tabstop>
<tabstop>ShowAllXformsCheckBox</tabstop>
<tabstop>PlatformCombo</tabstop>
<tabstop>DeviceCombo</tabstop>
<tabstop>ThreadCountSpin</tabstop>
<tabstop>CpuSubBatchSpin</tabstop>
<tabstop>OpenCLSubBatchSpin</tabstop>
<tabstop>CpuFilteringLogRadioButton</tabstop>
<tabstop>CpuFilteringDERadioButton</tabstop>
<tabstop>OpenCLFilteringLogRadioButton</tabstop>
<tabstop>OpenCLFilteringDERadioButton</tabstop>
<tabstop>OptionsXmlSavingTable</tabstop>
<tabstop>OptionsIdentityTable</tabstop>
<tabstop>OptionsButtonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>

View File

@ -21,10 +21,12 @@ public:
/// Constructor that takes a pointer to a QTreeWidget as the parent
/// and passes it to the base.
/// </summary>
/// <param name="id">The ID of the variation this widget will represent</param>
/// <param name="parent">The parent widget</param>
VariationTreeWidgetItem(QTreeWidget* parent = 0)
VariationTreeWidgetItem(eVariationId id, QTreeWidget* parent = 0)
: QTreeWidgetItem(parent)
{
m_Id = id;
}
/// <summary>
@ -32,13 +34,16 @@ public:
/// and passes it to the base.
/// This is used for making sub items for parametric variation parameters.
/// </summary>
/// <param name="id">The ID of the variation this widget will represent</param>
/// <param name="parent">The parent widget</param>
VariationTreeWidgetItem(QTreeWidgetItem* parent = 0)
VariationTreeWidgetItem(eVariationId id, QTreeWidgetItem* parent = 0)
: QTreeWidgetItem(parent)
{
m_Id = id;
}
virtual ~VariationTreeWidgetItem() { }
eVariationId Id() { return m_Id; }
private:
/// <summary>
@ -86,4 +91,6 @@ private:
return false;
}
eVariationId m_Id;
};