diff --git a/Data/dark.qss b/Data/dark.qss
index 39bc746..b034dbe 100644
--- a/Data/dark.qss
+++ b/Data/dark.qss
@@ -93,6 +93,7 @@ QDoubleSpinBox
QCheckBox
{
spacing: 5px;
+ outline: 0px;
}
QCheckBox::indicator,
diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h
index cc94140..420a68f 100644
--- a/Source/Ember/Ember.h
+++ b/Source/Ember/Ember.h
@@ -1311,7 +1311,7 @@ public:
if (useDefaults)
{
//If defaults are on, set to reasonable values.
- m_HighlightPower = -1;
+ m_HighlightPower = 1;
m_Background.Reset();
m_FinalRasW = 100;
m_FinalRasH = 100;
@@ -1327,6 +1327,8 @@ public:
m_BlurCoef = 0;
m_CamMat = m3T(0);
m_Quality = 1;
+ m_SubBatchSize = 10240;
+ m_FuseCount = 15;
m_MaxRadDE = T(9.0);
m_MinRadDE = 0;
m_CurveDE = T(0.4);
@@ -1337,7 +1339,8 @@ public:
m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER;
m_TemporalFilterWidth = 1;
m_TemporalFilterExp = 0;
- m_PaletteMode = ePaletteMode::PALETTE_STEP;
+ m_PaletteMode = ePaletteMode::PALETTE_LINEAR;
+ m_Interp = eInterp::EMBER_INTERP_SMOOTH;
}
else
{
@@ -1358,6 +1361,8 @@ public:
m_BlurCoef = 999999;
m_CamMat = m3T(999999);
m_Quality = -1;
+ m_SubBatchSize = 0;
+ m_FuseCount = 0;
m_MaxRadDE = -1;
m_MinRadDE = -1;
m_CurveDE = -1;
@@ -1369,6 +1374,7 @@ public:
m_TemporalFilterWidth = -1;
m_TemporalFilterExp = -999;
m_PaletteMode = ePaletteMode::PALETTE_STEP;
+ m_Interp = eInterp::EMBER_INTERP_LINEAR;
}
m_Xforms.clear();
@@ -1573,7 +1579,7 @@ public:
//Value to control saturation of some pixels in gamma correction during final accumulation.
//Xml field: "highlight_power".
- T m_HighlightPower = -1;
+ T m_HighlightPower = 1;
//When animating a file full of many embers, this value is used to specify the time in the animation
//that this ember should be rendered. They must all be sequential and increase by a default value of 1.
diff --git a/Source/Ember/SheepTools.h b/Source/Ember/SheepTools.h
index cd6be0b..99e5e73 100644
--- a/Source/Ember/SheepTools.h
+++ b/Source/Ember/SheepTools.h
@@ -376,7 +376,7 @@ public:
else
{
ember.m_Palette.Clear(false);
- cout << "Failure getting random palette, palette set to white\n";
+ cerr << "Failure getting random palette, palette set to white\n";
}
}
}
@@ -538,7 +538,7 @@ public:
}
while ((i > 1) && !(got0 && got1));
- os << "cross alternate ";
+ os << " cross alternate ";
os << trystr;
}
@@ -799,7 +799,7 @@ public:
if (best < 0)
{
- cout << "Error in TryColors(), skipping ImproveColors()\n";
+ cerr << "Error in TryColors(), skipping ImproveColors()\n";
return;
}
@@ -810,7 +810,7 @@ public:
if (b < 0)
{
- cout << "Error in TryColors, aborting tries.\n";
+ cerr << "Error in TryColors, aborting tries.\n";
break;
}
@@ -826,10 +826,12 @@ public:
///
/// Run a test render to improve the colors.
+ /// This checks to see how much of the possible color space is actually used in the final output image.
+ /// Images which contain a small number or range of colors will return a lower value.
///
/// The ember to render
- /// The resolution of the test histogram. This value ^ 3 will be used for the total size. Common value is 10.
- /// The number of histogram cells that weren't black
+ /// The color resolution of the test histogram. This value ^ 3 will be used for the total size. Common value is 10.
+ /// The percentage possible color values that were present in the final output image
T TryColors(Ember& ember, size_t colorResolution)
{
byte* p;
@@ -848,37 +850,31 @@ public:
adjustedEmber.m_PixelsPerUnit *= scalar;
adjustedEmber.m_TemporalSamples = 1;
m_Renderer->SetEmber(adjustedEmber);
- m_Renderer->BytesPerChannel(1);
m_Renderer->EarlyClip(true);
- m_Renderer->PixelAspectRatio(1);
- m_Renderer->ThreadCount(Timing::ProcessorCount());
- m_Renderer->Callback(nullptr);
if (m_Renderer->Run(m_FinalImage) != eRenderStatus::RENDER_OK)
{
- cout << "Error rendering test image for TryColors(). Aborting.\n";
+ cerr << "Error rendering test image for TryColors(). Aborting.\n";
return -1;
}
m_Hist.resize(res3);
- memset(m_Hist.data(), 0, res3);
+ Memset(m_Hist);
p = m_FinalImage.data();
for (i = 0; i < m_Renderer->FinalDimensions(); i++)
{
m_Hist[(p[0] * res / 256) +
(p[1] * res / 256) * res +
- (p[2] * res / 256) * res * res]++;
- p += m_Renderer->NumChannels();
+ (p[2] * res / 256) * res * res]++;//A specific histogram index representing the sum of R,G,B values.
+ p += m_Renderer->PixelSize();//Advance the pointer by 1 pixel.
}
for (i = 0; i < res3; i++)
- {
- if (m_Hist[i])
+ if (m_Hist[i])//The greater range of RGB values used...
hits++;
- }
- return T(hits / res3);
+ return T(hits / res3);//...the higher this returned ratio will be.
}
///
@@ -897,7 +893,7 @@ public:
else
{
ember.m_Palette.Clear(false);
- cout << "Error retrieving random palette, setting to all white.\n";
+ cerr << "Error retrieving random palette, setting to all white.\n";
}
}
@@ -1115,7 +1111,7 @@ public:
if (templ.m_Background[i] >= 0)
ember.m_Background[i] = templ.m_Background[i];
- if (templ.m_Zoom < 999999998)
+ if (templ.m_Zoom < 999999)
ember.m_Zoom = templ.m_Zoom;
if (templ.m_Supersample > 0)
@@ -1127,6 +1123,12 @@ public:
if (templ.m_Quality > 0)
ember.m_Quality = templ.m_Quality;
+ if (templ.m_SubBatchSize > 0)
+ ember.m_SubBatchSize = templ.m_SubBatchSize;
+
+ if (templ.m_FuseCount > 0)
+ ember.m_FuseCount = templ.m_FuseCount;
+
if (templ.m_TemporalSamples > 0)
ember.m_TemporalSamples = templ.m_TemporalSamples;
@@ -1155,10 +1157,10 @@ public:
if (templ.m_SpatialFilterType > eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER)
ember.m_SpatialFilterType = templ.m_SpatialFilterType;
- if (templ.m_Interp >= eInterp::EMBER_INTERP_LINEAR)
+ if (templ.m_Interp != eInterp::EMBER_INTERP_SMOOTH)
ember.m_Interp = templ.m_Interp;
- if (templ.m_AffineInterp >= eAffineInterp::AFFINE_INTERP_LINEAR)
+ if (templ.m_AffineInterp != eAffineInterp::AFFINE_INTERP_LOG)
ember.m_AffineInterp = templ.m_AffineInterp;
if (templ.m_TemporalFilterType >= eTemporalFilterType::BOX_TEMPORAL_FILTER)
@@ -1167,13 +1169,13 @@ public:
if (templ.m_TemporalFilterWidth > 0)
ember.m_TemporalFilterWidth = templ.m_TemporalFilterWidth;
- if (templ.m_TemporalFilterExp > -900)
+ if (templ.m_TemporalFilterExp > -999)
ember.m_TemporalFilterExp = templ.m_TemporalFilterExp;
- if (templ.m_HighlightPower >= 0)
+ if (templ.m_HighlightPower != 1)
ember.m_HighlightPower = templ.m_HighlightPower;
- if (templ.m_PaletteMode >= ePaletteMode::PALETTE_STEP)
+ if (templ.m_PaletteMode != ePaletteMode::PALETTE_LINEAR)
ember.m_PaletteMode = templ.m_PaletteMode;
}
diff --git a/Source/Ember/VariationList.h b/Source/Ember/VariationList.h
index 09fb25d..168ac98 100644
--- a/Source/Ember/VariationList.h
+++ b/Source/Ember/VariationList.h
@@ -21,7 +21,6 @@ template
class EMBER_API VariationList: public Singleton>
{
public:
- //~VariationList();
const Variation* GetVariation(size_t index) const;
const Variation* GetVariation(size_t index, eVariationType varType) const;
Variation* GetVariationCopy(size_t index, T weight = 1) const;
diff --git a/Source/Ember/Xform.h b/Source/Ember/Xform.h
index 2911a51..31e121b 100644
--- a/Source/Ember/Xform.h
+++ b/Source/Ember/Xform.h
@@ -184,7 +184,7 @@ public:
if (!m_ParentEmber && (typeid(T) == typeid(U)))
m_ParentEmber = reinterpret_cast*>(xform.ParentEmber());
- CopyCont(m_Xaos, xform.XaosVec());// needed?//TODO
+ CopyCont(m_Xaos, xform.XaosVec());
CopyCont(m_Motion, xform.m_Motion);
m_Name = xform.m_Name;
return *this;
diff --git a/Source/Ember/XmlToEmber.h b/Source/Ember/XmlToEmber.h
index 9f65421..877c044 100644
--- a/Source/Ember/XmlToEmber.h
+++ b/Source/Ember/XmlToEmber.h
@@ -524,6 +524,12 @@ private:
AddToReport(string(loc) + " : Error assigning palette with index " + Itos(currentEmber.PaletteIndex()));
}
+ if (!currentEmber.XformCount())//Ensure there is always at least one xform or else the renderer will crash when trying to render.
+ {
+ Xform xform;
+ currentEmber.AddXform(xform);
+ }
+
//if (!Interpolater::InterpMissingColors(currentEmber.m_Palette.m_Entries))
// AddToReport(string(loc) + " : Error interpolating missing palette colors");
currentEmber.CacheXforms();
diff --git a/Source/EmberCommon/EmberOptions.h b/Source/EmberCommon/EmberOptions.h
index 439ffed..38cfd32 100644
--- a/Source/EmberCommon/EmberOptions.h
+++ b/Source/EmberCommon/EmberOptions.h
@@ -121,7 +121,6 @@ enum class eOptionIDs : et
OPT_METHOD,
OPT_INTER,
OPT_ROTATE,
- OPT_STRIP,
OPT_SEQUENCE,
OPT_USE_VARS,
OPT_DONT_USE_VARS,
@@ -303,9 +302,9 @@ public:
INITBOOLOPTION(Help, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_HELP, _T("--help"), false, SO_NONE, "\t--help Show this screen and exit.\n"));
INITBOOLOPTION(Version, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_VERSION, _T("--version"), false, SO_NONE, "\t--version Show version and exit.\n"));
INITBOOLOPTION(OpenCLInfo, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_DUMP_OPENCL_INFO, _T("--openclinfo"), false, SO_NONE, "\t--openclinfo Display platforms and devices for OpenCL and exit.\n"));
- INITBOOLOPTION(AllVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ALL_VARS, _T("--allvars"), false, SO_NONE, "\t--allvars Display the names of all supported variations and exit.\n"));
- INITBOOLOPTION(RegVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_REG_VARS, _T("--regvars"), false, SO_NONE, "\t--regvars Display the names of all supported regular variations and exit.\n"));
- INITBOOLOPTION(PreVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PRE_VARS, _T("--prevars"), false, SO_NONE, "\t--prevars Display the names of all supported pre variations and exit.\n"));
+ INITBOOLOPTION(AllVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ALL_VARS, _T("--allvars"), false, SO_NONE, "\t--allvars Display the names of all supported variations and exit.\n"));
+ INITBOOLOPTION(RegVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_REG_VARS, _T("--regvars"), false, SO_NONE, "\t--regvars Display the names of all supported regular variations and exit.\n"));
+ INITBOOLOPTION(PreVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PRE_VARS, _T("--prevars"), false, SO_NONE, "\t--prevars Display the names of all supported pre variations and exit.\n"));
INITBOOLOPTION(PostVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_POST_VARS, _T("--postvars"), false, SO_NONE, "\t--postvars Display the names of all supported post variations and exit.\n"));
//Diagnostic bools.
INITBOOLOPTION(Verbose, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_VERBOSE, _T("--verbose"), false, SO_NONE, "\t--verbose Verbose output [default: false].\n"));
@@ -344,17 +343,17 @@ public:
INITUINTOPTION(Strips, Eou(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_STRIPS, _T("--nstrips"), 1, SO_REQ_SEP, "\t--nstrips= The number of fractions to split a single render frame into. Useful for print size renders or low memory systems [default: 1].\n"));
INITUINTOPTION(Supersample, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUPERSAMPLE, _T("--supersample"), 0, SO_REQ_SEP, "\t--supersample= The supersample value used to override the one specified in the file [default: 0 (use value from file), Range: 0 - 4].\n"));
INITUINTOPTION(BitsPerChannel, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_BPC, _T("--bpc"), 8, SO_REQ_SEP, "\t--bpc= Bits per channel. 8 or 16 for PNG, 8 for all others, always 8 with OpenCL [default: 8].\n"));
- INITUINTOPTION(PrintEditDepth, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PRINT_EDIT_DEPTH, _T("--print_edit_depth"), 0, SO_REQ_SEP, "\t--print_edit_depth= Depth to truncate tag structure when converting a flame to Xml. 0 prints all tags [default: 0].\n"));
- INITUINTOPTION(JpegQuality, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG, _T("--jpeg"), 95, SO_REQ_SEP, "\t--jpeg= Jpeg quality 0-100 for compression [default: 95].\n"));
- INITUINTOPTION(FirstFrame, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_BEGIN, _T("--begin"), UINT_MAX, SO_REQ_SEP, "\t--begin= Time of first frame to render [default: first time specified in file].\n"));
- INITUINTOPTION(LastFrame, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_END, _T("--end"), UINT_MAX, SO_REQ_SEP, "\t--end= Time of last frame to render [default: last time specified in the input file].\n"));
- INITUINTOPTION(Time, Eou(eOptionUse::OPT_ANIM_GENOME, eOptionIDs::OPT_TIME, _T("--time"), 0, SO_REQ_SEP, "\t--time= Time of first and last frame (ie do one frame).\n"));
- INITUINTOPTION(Frame, Eou(eOptionUse::OPT_ANIM_GENOME, eOptionIDs::OPT_FRAME, _T("--frame"), 0, SO_REQ_SEP, "\t--frame= Synonym for \"time\".\n"));
- INITUINTOPTION(Dtime, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_DTIME, _T("--dtime"), 1, SO_REQ_SEP, "\t--dtime= Time between frames [default: 1].\n"));
- INITUINTOPTION(Frames, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_NFRAMES, _T("--nframes"), 20, SO_REQ_SEP, "\t--nframes= Number of frames per loop and per interpolation in the animation [default: 20].\n"));
- INITUINTOPTION(Repeat, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_REPEAT, _T("--repeat"), 1, SO_REQ_SEP, "\t--repeat= Number of new flames to create. Ignored if sequence, inter or rotate were specified [default: 1].\n"));
- INITUINTOPTION(Tries, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_TRIES, _T("--tries"), 10, SO_REQ_SEP, "\t--tries= Number times to try creating a flame that meets the specified constraints. Ignored if sequence, inter or rotate were specified [default: 10].\n"));
- INITUINTOPTION(MaxXforms, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_MAX_XFORMS, _T("--maxxforms"), UINT_MAX, SO_REQ_SEP, "\t--maxxforms= The maximum number of xforms allowed in the final output.\n"));
+ INITUINTOPTION(PrintEditDepth, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PRINT_EDIT_DEPTH, _T("--print_edit_depth"), 0, SO_REQ_SEP, "\t--print_edit_depth= Depth to truncate tag structure when converting a flame to Xml. 0 prints all tags [default: 0].\n"));
+ INITUINTOPTION(JpegQuality, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG, _T("--jpeg"), 95, SO_REQ_SEP, "\t--jpeg= Jpeg quality 0-100 for compression [default: 95].\n"));
+ INITUINTOPTION(FirstFrame, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_BEGIN, _T("--begin"), UINT_MAX, SO_REQ_SEP, "\t--begin= Time of first frame to render [default: first time specified in file].\n"));
+ INITUINTOPTION(LastFrame, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_END, _T("--end"), UINT_MAX, SO_REQ_SEP, "\t--end= Time of last frame to render [default: last time specified in the input file].\n"));
+ INITUINTOPTION(Time, Eou(eOptionUse::OPT_ANIM_GENOME, eOptionIDs::OPT_TIME, _T("--time"), 0, SO_REQ_SEP, "\t--time= Time of first and last frame (ie do one frame).\n"));
+ INITUINTOPTION(Frame, Eou(eOptionUse::OPT_ANIM_GENOME, eOptionIDs::OPT_FRAME, _T("--frame"), 0, SO_REQ_SEP, "\t--frame= Synonym for \"time\".\n"));
+ INITUINTOPTION(Dtime, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_DTIME, _T("--dtime"), 1, SO_REQ_SEP, "\t--dtime= Time between frames [default: 1].\n"));
+ INITUINTOPTION(Frames, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_NFRAMES, _T("--nframes"), 20, SO_REQ_SEP, "\t--nframes= Number of frames per loop and per interpolation in the animation [default: 20].\n"));
+ INITUINTOPTION(Repeat, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_REPEAT, _T("--repeat"), 1, SO_REQ_SEP, "\t--repeat= Number of new flames to create. Ignored if sequence, inter or rotate were specified [default: 1].\n"));
+ INITUINTOPTION(Tries, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_TRIES, _T("--tries"), 10, SO_REQ_SEP, "\t--tries= Number times to try creating a flame that meets the specified constraints. Ignored if sequence, inter or rotate were specified [default: 10].\n"));
+ INITUINTOPTION(MaxXforms, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_MAX_XFORMS, _T("--maxxforms"), UINT_MAX, SO_REQ_SEP, "\t--maxxforms= The maximum number of xforms allowed in the final output.\n"));
//Double.
INITDOUBLEOPTION(SizeScale, Eod(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SS, _T("--ss"), 1, SO_REQ_SEP, "\t--ss= Size scale. All dimensions are scaled by this amount [default: 1.0].\n"));
INITDOUBLEOPTION(QualityScale, Eod(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_QS, _T("--qs"), 1, SO_REQ_SEP, "\t--qs= Quality scale. All quality values are scaled by this amount [default: 1.0].\n"));
@@ -397,7 +396,6 @@ public:
INITSTRINGOPTION(Method, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_METHOD, _T("--method"), "", SO_REQ_SEP, "\t--method= Method used for genetic cross: alternate, interpolate, or union. For mutate: all_vars, one_xform, add_symmetry, post_xforms, color_palette, delete_xform, all_coefs [default: random].\n"));//Original ommitted this important documentation for mutate!
INITSTRINGOPTION(Inter, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_INTER, _T("--inter"), "", SO_REQ_SEP, "\t--inter= Interpolate the input file.\n"));
INITSTRINGOPTION(Rotate, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ROTATE, _T("--rotate"), "", SO_REQ_SEP, "\t--rotate= Rotate the input file.\n"));
- INITSTRINGOPTION(Strip, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_STRIP, _T("--strip"), "", SO_REQ_SEP, "\t--strip= Break strip out of each flame in the input file.\n"));
INITSTRINGOPTION(Sequence, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SEQUENCE, _T("--sequence"), "", SO_REQ_SEP, "\t--sequence= 360 degree rotation 'loops' times of each control point in the input file plus rotating transitions.\n"));
INITSTRINGOPTION(UseVars, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_USE_VARS, _T("--use_vars"), "", SO_REQ_SEP, "\t--use_vars= Comma separated list of variation #'s to use when generating a random flame.\n"));
INITSTRINGOPTION(DontUseVars, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_DONT_USE_VARS, _T("--dont_use_vars"), "", SO_REQ_SEP, "\t--dont_use_vars= Comma separated list of variation #'s to NOT use when generating a random flame.\n"));
@@ -526,7 +524,6 @@ public:
PARSESTRINGOPTION(eOptionIDs::OPT_METHOD, Method);
PARSESTRINGOPTION(eOptionIDs::OPT_INTER, Inter);
PARSESTRINGOPTION(eOptionIDs::OPT_ROTATE, Rotate);
- PARSESTRINGOPTION(eOptionIDs::OPT_STRIP, Strip);
PARSESTRINGOPTION(eOptionIDs::OPT_SEQUENCE, Sequence);
PARSESTRINGOPTION(eOptionIDs::OPT_USE_VARS, UseVars);
PARSESTRINGOPTION(eOptionIDs::OPT_DONT_USE_VARS, DontUseVars);
@@ -804,7 +801,6 @@ public:
Eos Method;
Eos Inter;
Eos Rotate;
- Eos Strip;
Eos Sequence;
Eos UseVars;
Eos DontUseVars;
diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp
index 2e5c09d..b20632f 100644
--- a/Source/EmberGenome/EmberGenome.cpp
+++ b/Source/EmberGenome/EmberGenome.cpp
@@ -74,8 +74,6 @@ bool EmberGenome(EmberOptions& opt)
for (auto& v : vars)
cout << v->Name() << "\n";
-
- return true;
}
else
{
@@ -100,8 +98,8 @@ bool EmberGenome(EmberOptions& opt)
VerbosePrint("Using " << (sizeof(T) == sizeof(float) ? "single" : "double") << " precision.");
//Regular variables.
Timing t;
- bool exactTimeMatch, randomMode, didColor, seqFlag;
- size_t i, j, i0, i1, rep, val, frame, frameCount, count = 0;
+ bool exactTimeMatch, randomMode, didColor, seqFlag, random = false;
+ size_t i, i0, i1, rep, val, frame, frameCount, count = 0;
size_t ftime, firstFrame, lastFrame;
size_t n, tot, totb, totw;
T avgPix, fractionBlack, fractionWhite, blend, spread, mix0, mix1;
@@ -113,7 +111,6 @@ bool EmberGenome(EmberOptions& opt)
eCrossMode crossMeth;
eMutateMode mutMeth;
Ember orig, save, selp0, selp1, parent0, parent1;
- Ember result, result1, result2, result3, interpolated;
Ember* aselp0, *aselp1, *pTemplate = nullptr;
XmlToEmber parser;
EmberToXml emberToXml;
@@ -193,18 +190,10 @@ bool EmberGenome(EmberOptions& opt)
noVars.push_back(eVariationId::VAR_SPLIT);
noVars.push_back(eVariationId::VAR_SPLITS);
- //Loop over the novars and set ivars to the complement.
+ //Set ivars to the complement of novars.
for (i = 0; i < varList->Size(); i++)
- {
- for (j = 0; j < noVars.size(); j++)
- {
- if (noVars[j] == varList->GetVariation(i)->VariationId())
- break;
- }
-
- if (j == noVars.size())
+ if (!Contains(noVars, varList->GetVariation(i)->VariationId()))
vars.push_back(varList->GetVariation(i)->VariationId());
- }
}
else
{
@@ -234,18 +223,10 @@ bool EmberGenome(EmberOptions& opt)
}
}
- //Loop over the novars and set ivars to the complement.
+ //Set ivars to the complement of novars.
for (i = 0; i < varList->Size(); i++)
- {
- for (j = 0; j < noVars.size(); j++)
- {
- if (noVars[j] == varList->GetVariation(i)->VariationId())
- break;
- }
-
- if (j == noVars.size())
+ if (!Contains(noVars, varList->GetVariation(i)->VariationId()))
vars.push_back(varList->GetVariation(i)->VariationId());
- }
}
}
@@ -253,19 +234,17 @@ bool EmberGenome(EmberOptions& opt)
bool doInter = opt.Inter() != "";
bool doRotate = opt.Rotate() != "";
bool doClone = opt.Clone() != "";
- bool doStrip = opt.Strip() != "";
bool doCross0 = opt.Cross0() != "";
bool doCross1 = opt.Cross1() != "";
count += (doMutate ? 1 : 0);
count += (doInter ? 1 : 0);
count += (doRotate ? 1 : 0);
count += (doClone ? 1 : 0);
- count += (doStrip ? 1 : 0);
count += ((doCross0 || doCross1) ? 1 : 0);
if (count > 1)
{
- cerr << "Can only specify one of mutate, clone, cross, rotate, strip, or inter. Returning without executing.\n";
+ cerr << "Can only specify one of mutate, clone, cross, rotate, or inter. Returning without executing.\n";
return false;
}
@@ -297,24 +276,26 @@ bool EmberGenome(EmberOptions& opt)
else if (doInter) filename = opt.Inter();
else if (doRotate) filename = opt.Rotate();
else if (doClone) filename = opt.Clone();
- else if (doStrip) filename = opt.Strip();
else if (doCross0) filename = opt.Cross0();
else if (opt.CloneAll() != "") filename = opt.CloneAll();
else if (opt.Animate() != "") filename = opt.Animate();
else if (opt.Sequence() != "") filename = opt.Sequence();
else if (opt.Inter() != "") filename = opt.Inter();
else if (opt.Rotate() != "") filename = opt.Rotate();
- else if (opt.Strip() != "") filename = opt.Strip();
else if (opt.Clone() != "") filename = opt.Clone();
else if (opt.Mutate() != "") filename = opt.Mutate();
+ else random = true;
- if (!ParseEmberFile(parser, filename, embers))
- return false;
-
- if (doCross1)
+ if (!random)
{
- if (!ParseEmberFile(parser, opt.Cross1(), embers2))
+ if (!ParseEmberFile(parser, filename, embers))
return false;
+
+ if (doCross1)
+ {
+ if (!ParseEmberFile(parser, opt.Cross1(), embers2))
+ return false;
+ }
}
if (opt.CloneAll() != "")
@@ -336,6 +317,8 @@ bool EmberGenome(EmberOptions& opt)
if (opt.Animate() != "")
{
+ Ember interpolated;
+
for (i = 0; i < embers.size(); i++)
{
if (i > 0 && embers[i].m_Time <= embers[i - 1].m_Time)
@@ -398,6 +381,8 @@ bool EmberGenome(EmberOptions& opt)
if (opt.Sequence() != "")
{
+ Ember result;
+
if (opt.Frames() == 0)
{
cerr << "nframes must be positive and non-zero, not " << opt.Frames() << ".\n";
@@ -465,7 +450,7 @@ bool EmberGenome(EmberOptions& opt)
if (doInter || doRotate)
{
- frame = std::max(opt.Frame(), opt.Time());
+ Ember result, result1, result2, result3;
if (opt.Frames() == 0)
{
@@ -473,8 +458,9 @@ bool EmberGenome(EmberOptions& opt)
return false;
}
- blend = frame / T(opt.Frames());
- spread = 1 / T(opt.Frames());
+ frame = opt.Frame();
+ blend = frame / T(opt.Frames());//Percentage between first and second flame to treat as the center flame.
+ spread = 1 / T(opt.Frames());//Amount to move backward and forward from the center flame.
if (opt.Enclosed())
cout << "\n";
@@ -487,10 +473,14 @@ bool EmberGenome(EmberOptions& opt)
return false;
}
- tools.Spin(embers[0], pTemplate, result1, frame - 1, blend - spread);
+ if (frame)//Cannot spin backward below frame zero.
+ {
+ tools.Spin(embers[0], pTemplate, result1, frame - 1, blend - spread);
+ cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
+ }
+
tools.Spin(embers[0], pTemplate, result2, frame , blend );
tools.Spin(embers[0], pTemplate, result3, frame + 1, blend + spread);
- cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
cout << emberToXml.ToString(result2, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
cout << emberToXml.ToString(result3, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
}
@@ -502,10 +492,14 @@ bool EmberGenome(EmberOptions& opt)
return false;
}
- tools.SpinInter(embers.data(), pTemplate, result1, frame - 1, 0, blend - spread);
- tools.SpinInter(embers.data(), pTemplate, result2, frame , 0, blend );
- tools.SpinInter(embers.data(), pTemplate, result3, frame + 1, 0, blend + spread);
- cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
+ if (frame)//Cannot interpolate backward below frame zero.
+ {
+ tools.SpinInter(embers.data(), pTemplate, result1, frame - 1, false, blend - spread);
+ cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
+ }
+
+ tools.SpinInter(embers.data(), pTemplate, result2, frame , false, blend );
+ tools.SpinInter(embers.data(), pTemplate, result3, frame + 1, false, blend + spread);
cout << emberToXml.ToString(result2, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
cout << emberToXml.ToString(result3, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
}
@@ -516,36 +510,6 @@ bool EmberGenome(EmberOptions& opt)
return true;
}
- if (doStrip)
- {
- if (opt.Enclosed())
- cout << "\n";
-
- for (i = 0; i < embers.size(); i++)
- {
- T oldX, oldY;
- embers[i].DeleteMotionElements();
- oldX = embers[i].m_CenterX;
- oldY = embers[i].m_CenterY;
- embers[i].m_FinalRasH = size_t(T(embers[i].m_FinalRasH) / T(opt.Frames()));
- embers[i].m_CenterY = embers[i].m_CenterY - ((opt.Frames() - 1) * embers[i].m_FinalRasH) /
- (2 * embers[i].m_PixelsPerUnit * std::pow(T(2.0), embers[i].m_Zoom));
- embers[i].m_CenterY += embers[i].m_FinalRasH * opt.Frame() / (embers[i].m_PixelsPerUnit * std::pow(T(2.0), embers[i].m_Zoom));
- tools.RotateOldCenterBy(embers[i].m_CenterX, embers[i].m_CenterY, oldX, oldY, embers[i].m_Rotate);
-
- if (pTemplate)
- tools.ApplyTemplate(embers[i], *pTemplate);
-
- tools.Offset(embers[i], T(opt.OffsetX()), T(opt.OffsetY()));
- cout << emberToXml.ToString(embers[i], opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
- }
-
- if (opt.Enclosed())
- cout << "\n";
-
- return true;
- }
-
//Repeat.
renderer->EarlyClip(opt.EarlyClip());
renderer->YAxisUp(opt.YAxisUp());
@@ -567,7 +531,7 @@ bool EmberGenome(EmberOptions& opt)
count = 0;
os.str("");
save.Clear();
- VerbosePrint("Flame = " << rep + 1 << "/" << opt.Repeat() << "..");
+ VerbosePrint("Flame = " << rep + 1 << "/" << opt.Repeat() << "...");
if (opt.Clone() != "")
{
@@ -657,7 +621,7 @@ bool EmberGenome(EmberOptions& opt)
crossMeth = eCrossMode::CROSS_NOT_SPECIFIED;
}
- tools.Cross(embers[i0], embers2[i1], orig, crossMeth);
+ os << tools.Cross(embers[i0], embers2[i1], orig, crossMeth);
if (embers[i0].m_Name != "" || embers2[i1].m_Name != "")
{
@@ -671,6 +635,8 @@ bool EmberGenome(EmberOptions& opt)
os << "random";
randomMode = true;
tools.Random(orig, vars, opt.Symmetry(), 0, MAX_CL_VARS);
+ orig.m_FinalRasW = 1920;
+ orig.m_FinalRasH = 1080;
aselp0 = nullptr;
aselp1 = nullptr;
}
diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h
index db361b4..5cc3856 100644
--- a/Source/Fractorium/Fractorium.h
+++ b/Source/Fractorium/Fractorium.h
@@ -87,6 +87,7 @@ public:
~Fractorium();
//Geometry.
+ bool ApplyAll();
void SetCenter(float x, float y);
void SetRotation(double rot, bool stealth);
void SetScale(double scale);
@@ -241,6 +242,8 @@ public slots:
void OnXformColorIndexChanged(double d);
void OnXformColorIndexChanged(double d, bool updateRender);
void OnXformScrollColorIndexChanged(int d);
+ void OnRandomColorIndicesButtonClicked(bool b);
+ void OnToggleColorIndicesButtonClicked(bool b);
void OnXformColorSpeedChanged(double d);
void OnXformOpacityChanged(double d);
void OnXformDirectColorChanged(double d);
diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui
index e6bd161..5001c57 100644
--- a/Source/Fractorium/Fractorium.ui
+++ b/Source/Fractorium/Fractorium.ui
@@ -140,6 +140,16 @@
4
+ -
+
+
+ <html><head/><body><p>Apply adjustments to all flames in the file</p></body></html>
+
+
+ Apply All
+
+
+
-
@@ -157,7 +167,7 @@
0
0
230
- 950
+ 933
@@ -176,7 +186,7 @@
0
-
-
+
-
@@ -346,7 +356,23 @@
- -
+
-
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Expanding
+
+
+
+ 20
+ 20
+
+
+
+
+ -
true
@@ -427,7 +453,7 @@
- -
+
-
true
@@ -508,7 +534,7 @@
- -
+
-
true
@@ -595,7 +621,7 @@
- -
+
-
Qt::Vertical
@@ -611,7 +637,7 @@
- -
+
-
true
@@ -692,7 +718,7 @@
- -
+
-
Qt::Vertical
@@ -708,7 +734,7 @@
- -
+
-
Qt::Vertical
@@ -724,7 +750,7 @@
- -
+
-
@@ -1014,7 +1040,7 @@
- -
+
-
@@ -1199,7 +1225,7 @@
- -
+
-
@@ -1423,7 +1449,7 @@
- -
+
-
@@ -1504,7 +1530,7 @@
- -
+
-
Qt::Vertical
@@ -1520,7 +1546,7 @@
- -
+
-
@@ -1661,22 +1687,6 @@
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Expanding
-
-
-
- 20
- 20
-
-
-
-
@@ -3217,7 +3227,7 @@
- -
+
-
@@ -3403,7 +3413,37 @@
- -
+
-
+
+
+ 4
+
+
+ 0
+
+
-
+
+
+ <html><head/><body><p>Set all xform color indices to random numbers between 0 and 1, inclusive</p></body></html>
+
+
+ Random Indices
+
+
+
+ -
+
+
+ <html><head/><body><p>Set all xform color indices to 0 or 1</p></body></html>
+
+
+ Toggle Indices
+
+
+
+
+
+ -
Solo
@@ -3473,8 +3513,8 @@
0
0
- 118
- 618
+ 263
+ 700
@@ -5491,8 +5531,8 @@
0
0
- 133
- 52
+ 259
+ 652
@@ -6767,6 +6807,7 @@
+
diff --git a/Source/Fractorium/FractoriumEmberController.cpp b/Source/Fractorium/FractoriumEmberController.cpp
index 4a8a8a4..6435215 100644
--- a/Source/Fractorium/FractoriumEmberController.cpp
+++ b/Source/Fractorium/FractoriumEmberController.cpp
@@ -200,7 +200,7 @@ void FractoriumEmberController::SetEmber(size_t index, bool verbatim)
/// True to update renderer, else false. Default: true.
/// The action to add to the rendering queue. Default: eProcessAction::FULL_RENDER.
template
-void FractoriumEmberController::Update(std::function func, bool updateRender, eProcessAction action)
+void FractoriumEmberController::Update(std::function func, bool updateRender, eProcessAction action)
{
func();
@@ -208,6 +208,27 @@ void FractoriumEmberController::Update(std::function func, bool
UpdateRender(action);
}
+///
+/// Wrapper to call a function on the current ember and optionally all other embers in the file.
+/// Then optionally add the requested action to the rendering queue.
+///
+/// The function to call
+/// True to update renderer, else false. Default: true.
+/// The action to add to the rendering queue. Default: eProcessAction::FULL_RENDER.
+/// True to apply the action to all embers in the file in addition to the curent one, false to apply the action only to the current one.
+template
+void FractoriumEmberController::UpdateAll(std::function& ember)> func, bool updateRender, eProcessAction action, bool applyAll)
+{
+ func(m_Ember);
+
+ if (applyAll)
+ for (auto& it : m_EmberFile.m_Embers)
+ func(it);
+
+ if (updateRender)
+ UpdateRender(action);
+}
+
///
/// Wrapper to call a function on the specified xforms, then optionally add the requested action to the rendering queue.
/// If no xforms are selected via the checkboxes, and the update type is UPDATE_SELECTED, then the function will be called only on the currently selected xform.
@@ -352,7 +373,7 @@ void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool v
string filename = QDir::homePath().toStdString() + "/.config/fractorium/last.flame";
#endif
- writer.Save(filename.c_str(), m_Ember, 0, true, false, true);
+ writer.Save(filename.c_str(), m_Ember, 0, true, true, false, true, true);
m_GLController->ResetMouseState();
FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo.
FillParamTablesAndPalette();
diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h
index 6e6eaf6..312f668 100644
--- a/Source/Fractorium/FractoriumEmberController.h
+++ b/Source/Fractorium/FractoriumEmberController.h
@@ -186,6 +186,8 @@ public:
//Xforms Color.
virtual void XformColorIndexChanged(double d, bool updateRender) { }
virtual void XformScrollColorIndexChanged(int d) { }
+ virtual void RandomColorIndicesButtonClicked() { }
+ virtual void ToggleColorIndicesButtonClicked() { }
virtual void XformColorSpeedChanged(double d) { }
virtual void XformOpacityChanged(double d) { }
virtual void XformDirectColorChanged(double d) { }
@@ -431,6 +433,8 @@ public:
//Xforms Color.
virtual void XformColorIndexChanged(double d, bool updateRender) override;
virtual void XformScrollColorIndexChanged(int d) override;
+ virtual void RandomColorIndicesButtonClicked() override;
+ virtual void ToggleColorIndicesButtonClicked() override;
virtual void XformColorSpeedChanged(double d) override;
virtual void XformOpacityChanged(double d) override;
virtual void XformDirectColorChanged(double d) override;
@@ -494,6 +498,7 @@ private:
//Rendering/progress.
void Update(std::function func, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER);
+ void UpdateAll(std::function&)> func, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER, bool applyAll = false);
bool SyncSizes();
//Templated members.
diff --git a/Source/Fractorium/FractoriumParams.cpp b/Source/Fractorium/FractoriumParams.cpp
index 3107f31..e17a924 100644
--- a/Source/Fractorium/FractoriumParams.cpp
+++ b/Source/Fractorium/FractoriumParams.cpp
@@ -26,7 +26,7 @@ void Fractorium::InitParamsUI()
SetupSpinner(table, this, row, 1, m_GammaSpin, spinHeight, 1, 9999, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0);
SetupSpinner(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
SetupSpinner(table, this, row, 1, m_VibrancySpin, spinHeight, 0, 30, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0);
- SetupSpinner(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, -1.0, -1.0, -1.0);
+ SetupSpinner(table, this, row, 1, m_HighlightSpin, spinHeight, 1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, -1.0, -1.0, -1.0);
m_GammaThresholdSpin->setDecimals(4);
m_BackgroundColorButton = new QPushButton("...", table);
m_BackgroundColorButton->setMinimumWidth(21);
@@ -95,6 +95,15 @@ void Fractorium::InitParamsUI()
SetupCombo( table, this, row, 1, m_TemporalFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnTemporalFilterTypeComboCurrentIndexChanged(const QString&)));
}
+///
+/// Return whether the apply all checkbox is checked.
+///
+/// True if checked, else false.
+bool Fractorium::ApplyAll()
+{
+ return ui.ApplyAllParamsCheckBox->isChecked();
+}
+
///
/// Color.
///
@@ -106,7 +115,13 @@ void Fractorium::InitParamsUI()
///
/// The brightness
template
-void FractoriumEmberController::BrightnessChanged(double d) { Update([&] { m_Ember.m_Brightness = d; }, true, eProcessAction::FILTER_AND_ACCUM); }
+void FractoriumEmberController::BrightnessChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_Brightness = d;
+ }, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
+}
void Fractorium::OnBrightnessChanged(double d) { m_Controller->BrightnessChanged(d); }
///
@@ -116,7 +131,13 @@ void Fractorium::OnBrightnessChanged(double d) { m_Controller->BrightnessChanged
/// else if early clip is true, filter and accum, else final accum only.
///
/// The gamma value
-template void FractoriumEmberController::GammaChanged(double d) { Update([&] { m_Ember.m_Gamma = d; }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }
+template void FractoriumEmberController::GammaChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_Gamma = d;
+ }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
+}
void Fractorium::OnGammaChanged(double d) { m_Controller->GammaChanged(d); }
///
@@ -125,7 +146,13 @@ void Fractorium::OnGammaChanged(double d) { m_Controller->GammaChanged(d); }
/// Resets the rendering process to the final accumulation stage.
///
/// The gamma threshold
-template void FractoriumEmberController::GammaThresholdChanged(double d) { Update([&] { m_Ember.m_GammaThresh = d; }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }
+template void FractoriumEmberController::GammaThresholdChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_GammaThresh = d;
+ }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
+}
void Fractorium::OnGammaThresholdChanged(double d) { m_Controller->GammaThresholdChanged(d); }
///
@@ -134,7 +161,13 @@ void Fractorium::OnGammaThresholdChanged(double d) { m_Controller->GammaThreshol
/// Resets the rendering process to the final accumulation stage if temporal samples is 1, else full reset.
///
/// The vibrancy
-template void FractoriumEmberController::VibrancyChanged(double d) { Update([&] { m_Ember.m_Vibrancy = d; }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }
+template void FractoriumEmberController::VibrancyChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_Vibrancy = d;
+ }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
+}
void Fractorium::OnVibrancyChanged(double d) { m_Controller->VibrancyChanged(d); }
///
@@ -143,7 +176,13 @@ void Fractorium::OnVibrancyChanged(double d) { m_Controller->VibrancyChanged(d);
/// Resets the rendering process to the final accumulation stage.
///
/// The highlight power
-template void FractoriumEmberController::HighlightPowerChanged(double d) { Update([&] { m_Ember.m_HighlightPower = d; }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }
+template void FractoriumEmberController::HighlightPowerChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_HighlightPower = d;
+ }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
+}
void Fractorium::OnHighlightPowerChanged(double d) { m_Controller->HighlightPowerChanged(d); }
///
@@ -166,24 +205,21 @@ void Fractorium::OnBackgroundColorButtonClicked(bool checked)
template
void FractoriumEmberController::BackgroundChanged(const QColor& color)
{
- Update([&]
+ int itemRow = 5;
+ auto colorTable = m_Fractorium->ui.ColorTable;
+ colorTable->item(itemRow, 1)->setBackgroundColor(color);
+ auto r = ToString(color.red());
+ auto g = ToString(color.green());
+ auto b = ToString(color.blue());
+ colorTable->item(itemRow, 1)->setTextColor(VisibleColor(color));
+ colorTable->item(itemRow, 1)->setText("rgb(" + r + ", " + g + ", " + b + ")");
+ UpdateAll([&](Ember& ember)
{
- int itemRow = 5;
- auto colorTable = m_Fractorium->ui.ColorTable;
- colorTable->item(itemRow, 1)->setBackgroundColor(color);
-
- auto r = ToString(color.red());
- auto g = ToString(color.green());
- auto b = ToString(color.blue());
-
- colorTable->item(itemRow, 1)->setTextColor(VisibleColor(color));
- colorTable->item(itemRow, 1)->setText("rgb(" + r + ", " + g + ", " + b + ")");
-
//Color is 0-255, normalize to 0-1.
- m_Ember.m_Background.r = color.red() / 255.0;
- m_Ember.m_Background.g = color.green() / 255.0;
- m_Ember.m_Background.b = color.blue() / 255.0;
- });
+ ember.m_Background.r = color.red() / 255.0;
+ ember.m_Background.g = color.green() / 255.0;
+ ember.m_Background.b = color.blue() / 255.0;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnColorSelected(const QColor& color) { m_Controller->BackgroundChanged(color); }
@@ -194,7 +230,13 @@ void Fractorium::OnColorSelected(const QColor& color) { m_Controller->Background
/// Resets the rendering process.
///
/// The index of the palette mode combo box
-template void FractoriumEmberController::PaletteModeChanged(uint i) { Update([&] { m_Ember.m_PaletteMode = i == 0 ? ePaletteMode::PALETTE_STEP : ePaletteMode::PALETTE_LINEAR; }); }
+template void FractoriumEmberController::PaletteModeChanged(uint i)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_PaletteMode = i == 0 ? ePaletteMode::PALETTE_STEP : ePaletteMode::PALETTE_LINEAR;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnPaletteModeComboCurrentIndexChanged(int index) { m_Controller->PaletteModeChanged(index); }
///
@@ -206,7 +248,13 @@ void Fractorium::OnPaletteModeComboCurrentIndexChanged(int index) { m_Controller
/// Dimensions are set automatically to match the dimensions of GLWidget.
///
/// Ignored
-template void FractoriumEmberController::WidthChanged(uint i) { Update([&] { m_Ember.m_FinalRasW = i; }); }
+template void FractoriumEmberController::WidthChanged(uint i)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_FinalRasW = i;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnWidthChanged(int i) { m_Controller->WidthChanged(i); }
///
@@ -214,7 +262,13 @@ void Fractorium::OnWidthChanged(int i) { m_Controller->WidthChanged(i); }
/// Dimensions are set automatically to match the dimensions of GLWidget.
///
/// Ignored
-template void FractoriumEmberController::HeightChanged(uint i) { Update([&] { m_Ember.m_FinalRasH = i; }); }
+template void FractoriumEmberController::HeightChanged(uint i)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_FinalRasH = i;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnHeightChanged(int i) { m_Controller->HeightChanged(i); }
///
@@ -222,7 +276,13 @@ void Fractorium::OnHeightChanged(int i) { m_Controller->HeightChanged(i); }
/// Resets the rendering process.
///
/// The x offset value
-template void FractoriumEmberController::CenterXChanged(double d) { Update([&] { m_Ember.m_CenterX = d; }); }
+template void FractoriumEmberController::CenterXChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_CenterX = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnCenterXChanged(double d) { m_Controller->CenterXChanged(d); }
///
@@ -230,7 +290,13 @@ void Fractorium::OnCenterXChanged(double d) { m_Controller->CenterXChanged(d); }
/// Resets the rendering process.
///
/// The y offset value
-template void FractoriumEmberController::CenterYChanged(double d) { Update([&] { m_Ember.m_CenterY = m_Ember.m_RotCenterY = d; }); }
+template void FractoriumEmberController::CenterYChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_CenterY = ember.m_RotCenterY = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnCenterYChanged(double d) { m_Controller->CenterYChanged(d); }
///
@@ -241,7 +307,13 @@ void Fractorium::OnCenterYChanged(double d) { m_Controller->CenterYChanged(d); }
/// Resets the rendering process.
///
/// The scale value
-template void FractoriumEmberController::ScaleChanged(double d) { Update([&] { m_Ember.m_PixelsPerUnit = d; }); }
+template void FractoriumEmberController::ScaleChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_PixelsPerUnit = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnScaleChanged(double d) { m_Controller->ScaleChanged(d); }
///
@@ -252,7 +324,13 @@ void Fractorium::OnScaleChanged(double d) { m_Controller->ScaleChanged(d); }
/// Resets the rendering process.
///
/// The zoom value
-template void FractoriumEmberController::ZoomChanged(double d) { Update([&] { m_Ember.m_Zoom = d; }); }
+template void FractoriumEmberController::ZoomChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_Zoom = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnZoomChanged(double d) { m_Controller->ZoomChanged(d); }
///
@@ -261,22 +339,58 @@ void Fractorium::OnZoomChanged(double d) { m_Controller->ZoomChanged(d); }
/// Resets the rendering process.
///
/// The rotation in angles
-template void FractoriumEmberController::RotateChanged(double d) { Update([&] { m_Ember.m_Rotate = d; }); }
+template void FractoriumEmberController::RotateChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_Rotate = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnRotateChanged(double d) { m_Controller->RotateChanged(d); }
-template void FractoriumEmberController::ZPosChanged(double d) { Update([&] { m_Ember.m_CamZPos = d; }); }
+template void FractoriumEmberController::ZPosChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_CamZPos = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnZPosChanged(double d) { m_Controller->ZPosChanged(d); }
-template void FractoriumEmberController::PerspectiveChanged(double d) { Update([&] { m_Ember.m_CamPerspective = d; }); }
+template void FractoriumEmberController::PerspectiveChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_CamPerspective = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnPerspectiveChanged(double d) { m_Controller->PerspectiveChanged(d); }
-template void FractoriumEmberController::PitchChanged(double d) { Update([&] { m_Ember.m_CamPitch = d* DEG_2_RAD; }); }
+template void FractoriumEmberController::PitchChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_CamPitch = d * DEG_2_RAD;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnPitchChanged(double d) { m_Controller->PitchChanged(d); }
-template void FractoriumEmberController::YawChanged(double d) { Update([&] { m_Ember.m_CamYaw = d* DEG_2_RAD; }); }
+template void FractoriumEmberController::YawChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_CamYaw = d * DEG_2_RAD;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnYawChanged(double d) { m_Controller->YawChanged(d); }
-template void FractoriumEmberController::DepthBlurChanged(double d) { Update([&] { m_Ember.m_CamDepthBlur = d; }); }
+template void FractoriumEmberController::DepthBlurChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_CamDepthBlur = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnDepthBlurChanged(double d) { m_Controller->DepthBlurChanged(d); }
///
@@ -291,10 +405,10 @@ void Fractorium::OnDepthBlurChanged(double d) { m_Controller->DepthBlurChanged(d
/// The spatial filter width
template void FractoriumEmberController::SpatialFilterWidthChanged(double d)
{
- Update([&]
+ UpdateAll([&](Ember& ember)
{
- m_Ember.m_SpatialFilterRadius = d;
- }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
+ ember.m_SpatialFilterRadius = d;
+ }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
}
void Fractorium::OnSpatialFilterWidthChanged(double d) { m_Controller->SpatialFilterWidthChanged(d); }
@@ -307,10 +421,10 @@ void Fractorium::OnSpatialFilterWidthChanged(double d) { m_Controller->SpatialFi
/// The spatial filter type
template void FractoriumEmberController::SpatialFilterTypeChanged(const QString& text)
{
- Update([&]
+ UpdateAll([&](Ember& ember)
{
- m_Ember.m_SpatialFilterType = SpatialFilterCreator::FromString(text.toStdString());
- }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
+ ember.m_SpatialFilterType = SpatialFilterCreator::FromString(text.toStdString());
+ }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
}
void Fractorium::OnSpatialFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->SpatialFilterTypeChanged(text); }
@@ -322,7 +436,13 @@ void Fractorium::OnSpatialFilterTypeComboCurrentIndexChanged(const QString& text
/// In the future, when animation is implemented, this will have an effect.
///
/// The temporal filter width
-template void FractoriumEmberController::TemporalFilterWidthChanged(double d) { Update([&] { m_Ember.m_TemporalFilterWidth = d; }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
+template void FractoriumEmberController::TemporalFilterWidthChanged(double d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_TemporalFilterWidth = d;
+ }, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
+}
void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->TemporalFilterWidthChanged(d); }
///
@@ -332,7 +452,13 @@ void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->Temporal
/// In the future, when animation is implemented, this will have an effect.
///
/// The name of the temporal filter
-template void FractoriumEmberController::TemporalFilterTypeChanged(const QString& text) { Update([&] { m_Ember.m_TemporalFilterType = TemporalFilterCreator::FromString(text.toStdString()); }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
+template void FractoriumEmberController::TemporalFilterTypeChanged(const QString& text)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_TemporalFilterType = TemporalFilterCreator::FromString(text.toStdString());
+ }, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
+}
void Fractorium::OnTemporalFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->TemporalFilterTypeChanged(text); }
///
@@ -349,10 +475,10 @@ void FractoriumEmberController::DEFilterMinRadiusWidthChanged(double d)
return;
}
- Update([&]
+ UpdateAll([&](Ember& ember)
{
- m_Ember.m_MinRadDE = d;
- }, true, eProcessAction::FILTER_AND_ACCUM);
+ ember.m_MinRadDE = d;
+ }, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
}
void Fractorium::OnDEFilterMinRadiusWidthChanged(double d) { m_Controller->DEFilterMinRadiusWidthChanged(d); }
@@ -371,10 +497,10 @@ void FractoriumEmberController::DEFilterMaxRadiusWidthChanged(double d)
return;
}
- Update([&]
+ UpdateAll([&](Ember& ember)
{
- m_Ember.m_MaxRadDE = d;
- }, true, eProcessAction::FILTER_AND_ACCUM);
+ ember.m_MaxRadDE = d;
+ }, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
}
void Fractorium::OnDEFilterMaxRadiusWidthChanged(double d) { m_Controller->DEFilterMaxRadiusWidthChanged(d); }
@@ -386,10 +512,10 @@ void Fractorium::OnDEFilterMaxRadiusWidthChanged(double d) { m_Controller->DEFil
/// The curve value
template void FractoriumEmberController::DEFilterCurveWidthChanged(double d)
{
- Update([&]
+ UpdateAll([&](Ember& ember)
{
- m_Ember.m_CurveDE = d;
- }, true, eProcessAction::FILTER_AND_ACCUM);
+ ember.m_CurveDE = d;
+ }, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
}
void Fractorium::OnDEFilterCurveWidthChanged(double d) { m_Controller->DEFilterCurveWidthChanged(d); }
@@ -404,7 +530,13 @@ void Fractorium::OnDEFilterCurveWidthChanged(double d) { m_Controller->DEFilterC
/// Resets the rendering process.
///
/// The sub batch size value to set
-template void FractoriumEmberController::SbsChanged(int d) { Update([&] { m_Ember.m_SubBatchSize = d; }); }
+template void FractoriumEmberController::SbsChanged(int d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_SubBatchSize = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnSbsChanged(int d) { m_Controller->SbsChanged(d); }
///
@@ -413,7 +545,13 @@ void Fractorium::OnSbsChanged(int d) { m_Controller->SbsChanged(d); }
/// Resets the rendering process.
///
/// The fuse count value to set
-template void FractoriumEmberController::FuseChanged(int d) { Update([&] { m_Ember.m_FuseCount = d; }); }
+template void FractoriumEmberController::FuseChanged(int d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_FuseCount = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
///
@@ -426,8 +564,8 @@ void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
/// the rendering process is continued, else it's reset.
///
/// The quality in terms of iterations per pixel
-template void FractoriumEmberController::QualityChanged(double d) { /*Update([&] { m_Ember.m_Quality = d; }, true, d > m_Ember.m_Quality ? KEEP_ITERATING : eProcessAction::FULL_RENDER);*/ }
-void Fractorium::OnQualityChanged(double d) { /*m_Controller->QualityChanged(d);*/ }
+template void FractoriumEmberController::QualityChanged(double d) { }
+void Fractorium::OnQualityChanged(double d) { m_Controller->QualityChanged(d); }
///
/// Set the supersample.
@@ -440,7 +578,13 @@ void Fractorium::OnQualityChanged(double d) { /*m_Controller->QualityChanged(d);
/// Resets the rendering process.
///
/// The supersample value to set
-template void FractoriumEmberController::SupersampleChanged(int d) { Update([&] { m_Ember.m_Supersample = d; }); }
+template void FractoriumEmberController::SupersampleChanged(int d)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_Supersample = d;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
+}
void Fractorium::OnSupersampleChanged(int d) { m_Controller->SupersampleChanged(d); }
///
@@ -450,7 +594,13 @@ void Fractorium::OnSupersampleChanged(int d) { m_Controller->SupersampleChanged(
/// In the future, when animation is implemented, this will have an effect.
///
/// The temporal samples value
-template void FractoriumEmberController::TemporalSamplesChanged(int i) { Update([&] { m_Ember.m_TemporalSamples = i; }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
+template void FractoriumEmberController::TemporalSamplesChanged(int i)
+{
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_TemporalSamples = i;
+ }, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
+}
void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamplesChanged(d); }
///
@@ -463,15 +613,15 @@ void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamples
template
void FractoriumEmberController::AffineInterpTypeChanged(int i)
{
- Update([&]
+ UpdateAll([&](Ember& ember)
{
if (i == 0)
- m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
+ ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
else if (i == 1)
- m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
+ ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
else
- m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
- }, true, eProcessAction::NOTHING);
+ ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
+ }, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
}
void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Controller->AffineInterpTypeChanged(index); }
@@ -486,15 +636,15 @@ void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Contr
template
void FractoriumEmberController::InterpTypeChanged(int i)
{
- Update([&]
+ UpdateAll([&](Ember& ember)
{
if (i == 0)
- m_Ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
+ ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
else if (i == 1)
- m_Ember.m_Interp = eInterp::EMBER_INTERP_SMOOTH;
+ ember.m_Interp = eInterp::EMBER_INTERP_SMOOTH;
else
- m_Ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
- }, true, eProcessAction::NOTHING);
+ ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
+ }, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
}
void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller->InterpTypeChanged(index); }
@@ -509,13 +659,13 @@ void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller-
template
void FractoriumEmberController::SetCenter(double x, double y)
{
- m_Ember.m_CenterX = x;
- m_Ember.m_CenterY = m_Ember.m_RotCenterY = y;
+ UpdateAll([&](Ember& ember)
+ {
+ ember.m_CenterX = x;
+ ember.m_CenterY = ember.m_RotCenterY = y;
+ }, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
m_Fractorium->m_CenterXSpin->SetValueStealth(x);//Don't trigger a redraw twice.
m_Fractorium->m_CenterYSpin->SetValueStealth(y);
-
- if (m_Renderer.get())//On startup, this will be null at first because a resize takes place before the rendering thread is started.
- CenterXChanged(m_Ember.m_CenterX);//Trigger update using both new values.
}
///
diff --git a/Source/Fractorium/FractoriumXformsColor.cpp b/Source/Fractorium/FractoriumXformsColor.cpp
index 53f0a50..7b62af7 100644
--- a/Source/Fractorium/FractoriumXformsColor.cpp
+++ b/Source/Fractorium/FractoriumXformsColor.cpp
@@ -13,6 +13,8 @@ void Fractorium::InitXformsColorUI()
ui.XformPaletteRefTable->setItem(0, 0, m_PaletteRefItem);
ui.XformPaletteRefTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
connect(ui.XformPaletteRefTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this, SLOT(OnXformRefPaletteResized(int, int, int)), Qt::QueuedConnection);
+ connect(ui.RandomColorIndicesButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomColorIndicesButtonClicked(bool)), Qt::QueuedConnection);
+ connect(ui.ToggleColorIndicesButton, SIGNAL(clicked(bool)), this, SLOT(OnToggleColorIndicesButtonClicked(bool)), Qt::QueuedConnection);
SetupSpinner(ui.XformColorIndexTable, this, row, 1, m_XformColorIndexSpin, spinHeight, 0, 1, 0.01, SIGNAL(valueChanged(double)), SLOT(OnXformColorIndexChanged(double)), false, 0, 1, 0);
SetupSpinner(ui.XformColorValuesTable, this, row, 1, m_XformColorSpeedSpin, spinHeight, -1, 1, 0.1, SIGNAL(valueChanged(double)), SLOT(OnXformColorSpeedChanged(double)), true, 0.5, 0.5, 0.5);
SetupSpinner(ui.XformColorValuesTable, this, row, 1, m_XformOpacitySpin, spinHeight, 0, 1, 0.1, SIGNAL(valueChanged(double)), SLOT(OnXformOpacityChanged(double)), true, 1, 1, 0);
@@ -21,8 +23,8 @@ void Fractorium::InitXformsColorUI()
m_XformColorSpeedSpin->setDecimals(3);
m_XformOpacitySpin->setDecimals(3);
m_XformDirectColorSpin->setDecimals(3);
- connect(ui.XformColorScroll, SIGNAL(valueChanged(int)), this, SLOT(OnXformScrollColorIndexChanged(int)), Qt::QueuedConnection);
- connect(ui.SoloXformCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSoloXformCheckBoxStateChanged(int)), Qt::QueuedConnection);
+ connect(ui.XformColorScroll, SIGNAL(valueChanged(int)), this, SLOT(OnXformScrollColorIndexChanged(int)), Qt::QueuedConnection);
+ connect(ui.SoloXformCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSoloXformCheckBoxStateChanged(int)), Qt::QueuedConnection);
}
///
@@ -70,6 +72,35 @@ void FractoriumEmberController::XformScrollColorIndexChanged(int d)
void Fractorium::OnXformScrollColorIndexChanged(int d) { m_Controller->XformScrollColorIndexChanged(d); }
+///
+/// Set all xform color indices to a random value between 0 and 1, inclusive.
+/// Called when the Random Indices button is clicked.
+/// Resets the rendering process.
+///
+template
+void FractoriumEmberController::RandomColorIndicesButtonClicked()
+{
+ UpdateXform([&](Xform* xform) { xform->m_ColorX = m_Rand.Frand01(); }, eXformUpdate::UPDATE_ALL);
+ m_Fractorium->m_XformColorIndexSpin->SetValueStealth(CurrentXform()->m_ColorX);
+ m_Fractorium->OnXformColorIndexChanged(CurrentXform()->m_ColorX, false);//Update GUI, no need to update renderer because UpdateXform() did it.
+}
+void Fractorium::OnRandomColorIndicesButtonClicked(bool b) { m_Controller->RandomColorIndicesButtonClicked(); }
+
+///
+/// Resets the rendering process.
+/// Set all xform color indices to either 0 and 1, sequentially toggling.
+/// Called when the Toggle Indices button is clicked.
+///
+template
+void FractoriumEmberController::ToggleColorIndicesButtonClicked()
+{
+ char ch = 1;
+ UpdateXform([&](Xform* xform) { xform->m_ColorX = T(ch ^= 1); }, eXformUpdate::UPDATE_ALL);
+ m_Fractorium->m_XformColorIndexSpin->SetValueStealth(CurrentXform()->m_ColorX);
+ m_Fractorium->OnXformColorIndexChanged(CurrentXform()->m_ColorX, false);//Update GUI, no need to update renderer because UpdateXform() did it.
+}
+void Fractorium::OnToggleColorIndicesButtonClicked(bool b) { m_Controller->ToggleColorIndicesButtonClicked(); }
+
///
/// Set the color speed of the selected xforms.
/// Called when xform color speed spinner is changed.
diff --git a/Source/Fractorium/GLWidget.cpp b/Source/Fractorium/GLWidget.cpp
index d3ed1c7..9edac48 100644
--- a/Source/Fractorium/GLWidget.cpp
+++ b/Source/Fractorium/GLWidget.cpp
@@ -427,9 +427,7 @@ void GLEmberController::MousePress(QMouseEvent* e)
if (mod.testFlag(Qt::ShiftModifier))
SetShift();
- //if (mod.testFlag(Qt::ControlModifier))// || mod.testFlag(Qt::Key_C))
- // m_DragModifier |= DragModControl;
- if (mod.testFlag(Qt::AltModifier))// || mod.testFlag(Qt::Key_A))
+ if (mod.testFlag(Qt::AltModifier))
SetAlt();
if (m_DragState == eDragState::DragNone)//Only take action if the user wasn't already dragging.