From bbc5d0c783e805cbe7a00360842d1a13e1038871 Mon Sep 17 00:00:00 2001 From: mfeemster Date: Mon, 2 May 2016 16:54:56 -0700 Subject: [PATCH] --User changes -Highlight power is now on by default. -Allow for adjustments on the Flame tab to apply to all open flames in the file. -Add two new buttons to the color tab to randomize and toggle the xform color indices. -Remove the --strip option from EmberGenome. It was useless and was likely just a carry over from flam3 during its early debugging stages when testing strips. -Make randoms in EmberGenome have default dimensions of 1920 x 1080. -Prevent --inter and --rotate in EmberGenome from rotating backward before the first flame since it doesn't really make sense. -Ensure every loaded flame has at least one xform in it. -Change dark.qss to hide dotted selection outline around checkboxes. Users must reload it to take effect. --Bug fixes -The saving of last.flame during editing was appending the file when it should have been replacing. -It was impossible for EmberGenome to create a random flame. It can now be done by specifying no arguments: EmberGenome.exe -Crossing in EmberGenome was not logging the performed actions to the edit Xml tag. -Apply sub batch size and fuse count to template files used on the command line. -Use new default filter types with template files. --Code changes -Use cerr in SheepTools instead of cout. -Set m_SubBatchSize and m_FuseCount to default values in Ember::Clear(). -Clean up some command line options text formatting. --- Data/dark.qss | 1 + Source/Ember/Ember.h | 12 +- Source/Ember/SheepTools.h | 52 +-- Source/Ember/VariationList.h | 1 - Source/Ember/Xform.h | 2 +- Source/Ember/XmlToEmber.h | 6 + Source/EmberCommon/EmberOptions.h | 32 +- Source/EmberGenome/EmberGenome.cpp | 118 +++---- Source/Fractorium/Fractorium.h | 3 + Source/Fractorium/Fractorium.ui | 115 ++++--- .../Fractorium/FractoriumEmberController.cpp | 25 +- Source/Fractorium/FractoriumEmberController.h | 5 + Source/Fractorium/FractoriumParams.cpp | 296 +++++++++++++----- Source/Fractorium/FractoriumXformsColor.cpp | 35 ++- Source/Fractorium/GLWidget.cpp | 4 +- 15 files changed, 466 insertions(+), 241 deletions(-) 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.