--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.
This commit is contained in:
mfeemster 2016-05-02 16:54:56 -07:00
parent 1f0cc4bb4a
commit bbc5d0c783
15 changed files with 466 additions and 241 deletions

View File

@ -93,6 +93,7 @@ QDoubleSpinBox
QCheckBox
{
spacing: 5px;
outline: 0px;
}
QCheckBox::indicator,

View File

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

View File

@ -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:
/// <summary>
/// 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.
/// </summary>
/// <param name="ember">The ember to render</param>
/// <param name="colorResolution">The resolution of the test histogram. This value ^ 3 will be used for the total size. Common value is 10.</param>
/// <returns>The number of histogram cells that weren't black</returns>
/// <param name="colorResolution">The color resolution of the test histogram. This value ^ 3 will be used for the total size. Common value is 10.</param>
/// <returns>The percentage possible color values that were present in the final output image</returns>
T TryColors(Ember<T>& 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.
}
/// <summary>
@ -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;
}

View File

@ -21,7 +21,6 @@ template <typename T>
class EMBER_API VariationList: public Singleton<VariationList<T>>
{
public:
//~VariationList();
const Variation<T>* GetVariation(size_t index) const;
const Variation<T>* GetVariation(size_t index, eVariationType varType) const;
Variation<T>* GetVariationCopy(size_t index, T weight = 1) const;

View File

@ -184,7 +184,7 @@ public:
if (!m_ParentEmber && (typeid(T) == typeid(U)))
m_ParentEmber = reinterpret_cast<Ember<T>*>(xform.ParentEmber());
CopyCont(m_Xaos, xform.XaosVec());//<T, U> needed?//TODO
CopyCont(m_Xaos, xform.XaosVec());
CopyCont(m_Motion, xform.m_Motion);
m_Name = xform.m_Name;
return *this;

View File

@ -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<T> xform;
currentEmber.AddXform(xform);
}
//if (!Interpolater<T>::InterpMissingColors(currentEmber.m_Palette.m_Entries))
// AddToReport(string(loc) + " : Error interpolating missing palette colors");
currentEmber.CacheXforms();

View File

@ -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=<val> 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=<val> 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=<val> 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=<val> Depth to truncate <edit> tag structure when converting a flame to Xml. 0 prints all <edit> tags [default: 0].\n"));
INITUINTOPTION(JpegQuality, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG, _T("--jpeg"), 95, SO_REQ_SEP, "\t--jpeg=<val> 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=<val> 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=<val> 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=<val> 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=<val> Synonym for \"time\".\n"));
INITUINTOPTION(Dtime, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_DTIME, _T("--dtime"), 1, SO_REQ_SEP, "\t--dtime=<val> Time between frames [default: 1].\n"));
INITUINTOPTION(Frames, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_NFRAMES, _T("--nframes"), 20, SO_REQ_SEP, "\t--nframes=<val> 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=<val> 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=<val> 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=<val> 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=<val> Depth to truncate <edit> tag structure when converting a flame to Xml. 0 prints all <edit> tags [default: 0].\n"));
INITUINTOPTION(JpegQuality, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG, _T("--jpeg"), 95, SO_REQ_SEP, "\t--jpeg=<val> 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=<val> 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=<val> 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=<val> 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=<val> Synonym for \"time\".\n"));
INITUINTOPTION(Dtime, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_DTIME, _T("--dtime"), 1, SO_REQ_SEP, "\t--dtime=<val> Time between frames [default: 1].\n"));
INITUINTOPTION(Frames, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_NFRAMES, _T("--nframes"), 20, SO_REQ_SEP, "\t--nframes=<val> 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=<val> 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=<val> 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=<val> 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=<val> 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=<val> 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=<val> 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=<val> Interpolate the input file.\n"));
INITSTRINGOPTION(Rotate, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ROTATE, _T("--rotate"), "", SO_REQ_SEP, "\t--rotate=<val> Rotate the input file.\n"));
INITSTRINGOPTION(Strip, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_STRIP, _T("--strip"), "", SO_REQ_SEP, "\t--strip=<val> 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=<val> 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=<val> 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=<val> 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;

View File

@ -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<T> orig, save, selp0, selp1, parent0, parent1;
Ember<T> result, result1, result2, result3, interpolated;
Ember<T>* aselp0, *aselp1, *pTemplate = nullptr;
XmlToEmber<T> parser;
EmberToXml<T> 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<T> 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<T> 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<T> 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 << "<pick version=\"EMBER-" << EmberVersion() << "\">\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 << "<pick version=\"EMBER-" << EmberVersion() << "\">\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 << "</pick>\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;
}

View File

@ -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);

View File

@ -140,6 +140,16 @@
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QCheckBox" name="ApplyAllParamsCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Apply adjustments to all flames in the file&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Apply All</string>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="FlameTabScrollArea">
<property name="frameShape">
@ -157,7 +167,7 @@
<x>0</x>
<y>0</y>
<width>230</width>
<height>950</height>
<height>933</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
@ -176,7 +186,7 @@
<property name="spacing">
<number>0</number>
</property>
<item row="10" column="0">
<item row="12" column="0">
<widget class="TableWidget" name="IterationTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -346,7 +356,23 @@
</item>
</widget>
</item>
<item row="3" column="0">
<item row="18" column="0">
<spacer name="FlameTabVerticalSpacer5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QTableWidget" name="GeometryTableHeader">
<property name="enabled">
<bool>true</bool>
@ -427,7 +453,7 @@
</column>
</widget>
</item>
<item row="9" column="0">
<item row="11" column="0">
<widget class="QTableWidget" name="IterationTableHeader">
<property name="enabled">
<bool>true</bool>
@ -508,7 +534,7 @@
</column>
</widget>
</item>
<item row="0" column="0">
<item row="1" column="0">
<widget class="QTableWidget" name="ColorTableHeader">
<property name="enabled">
<bool>true</bool>
@ -595,7 +621,7 @@
</column>
</widget>
</item>
<item row="8" column="0">
<item row="10" column="0">
<spacer name="FlameTabVerticalSpacer3">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -611,7 +637,7 @@
</property>
</spacer>
</item>
<item row="6" column="0">
<item row="8" column="0">
<widget class="QTableWidget" name="FilterTableHeader">
<property name="enabled">
<bool>true</bool>
@ -692,7 +718,7 @@
</column>
</widget>
</item>
<item row="5" column="0">
<item row="7" column="0">
<spacer name="FlameTabVerticalSpacer2">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -708,7 +734,7 @@
</property>
</spacer>
</item>
<item row="2" column="0">
<item row="4" column="0">
<spacer name="FlameTabVerticalSpacer1">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -724,7 +750,7 @@
</property>
</spacer>
</item>
<item row="4" column="0">
<item row="6" column="0">
<widget class="TableWidget" name="GeometryTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1014,7 +1040,7 @@
</item>
</widget>
</item>
<item row="7" column="0">
<item row="9" column="0">
<widget class="TableWidget" name="FilterTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1199,7 +1225,7 @@
</item>
</widget>
</item>
<item row="1" column="0">
<item row="3" column="0">
<widget class="TableWidget" name="ColorTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1423,7 +1449,7 @@
</item>
</widget>
</item>
<item row="14" column="0">
<item row="16" column="0">
<widget class="QTableWidget" name="AnimationTableHeader">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1504,7 +1530,7 @@
</column>
</widget>
</item>
<item row="13" column="0">
<item row="15" column="0">
<spacer name="FlameTabVerticalSpacer4">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -1520,7 +1546,7 @@
</property>
</spacer>
</item>
<item row="15" column="0">
<item row="17" column="0">
<widget class="QTableWidget" name="AnimationTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1661,22 +1687,6 @@
</item>
</widget>
</item>
<item row="16" column="0">
<spacer name="FlameTabVerticalSpacer5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
@ -3217,7 +3227,7 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<widget class="TableWidget" name="XformColorValuesTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
@ -3403,7 +3413,37 @@
</item>
</widget>
</item>
<item row="4" column="0">
<item row="3" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="RandomColorIndicesButton">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set all xform color indices to random numbers between 0 and 1, inclusive&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Random Indices</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ToggleColorIndicesButton">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set all xform color indices to 0 or 1&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Toggle Indices</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="SoloXformCheckBox">
<property name="text">
<string>Solo</string>
@ -3473,8 +3513,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>118</width>
<height>618</height>
<width>263</width>
<height>700</height>
</rect>
</property>
<property name="autoFillBackground">
@ -5491,8 +5531,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>133</width>
<height>52</height>
<width>259</width>
<height>652</height>
</rect>
</property>
<property name="sizePolicy">
@ -6767,6 +6807,7 @@
<addaction name="ActionRedo"/>
<addaction name="separator"/>
<addaction name="ActionStartStopRenderer"/>
<addaction name="ActionRenderPreviews"/>
<addaction name="ActionStopRenderingPreviews"/>
<addaction name="ActionFinalRender"/>
<addaction name="separator"/>

View File

@ -200,7 +200,7 @@ void FractoriumEmberController<T>::SetEmber(size_t index, bool verbatim)
/// <param name="updateRender">True to update renderer, else false. Default: true.</param>
/// <param name="action">The action to add to the rendering queue. Default: eProcessAction::FULL_RENDER.</param>
template <typename T>
void FractoriumEmberController<T>::Update(std::function<void (void)> func, bool updateRender, eProcessAction action)
void FractoriumEmberController<T>::Update(std::function<void(void)> func, bool updateRender, eProcessAction action)
{
func();
@ -208,6 +208,27 @@ void FractoriumEmberController<T>::Update(std::function<void (void)> func, bool
UpdateRender(action);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="func">The function to call</param>
/// <param name="updateRender">True to update renderer, else false. Default: true.</param>
/// <param name="action">The action to add to the rendering queue. Default: eProcessAction::FULL_RENDER.</param>
/// <param name="applyAll">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.</param>
template <typename T>
void FractoriumEmberController<T>::UpdateAll(std::function<void(Ember<T>& 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);
}
/// <summary>
/// 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<T>::SetEmberPrivate(const Ember<U>& 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();

View File

@ -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<void (void)> func, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER);
void UpdateAll(std::function<void (Ember<T>&)> func, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER, bool applyAll = false);
bool SyncSizes();
//Templated members.

View File

@ -26,7 +26,7 @@ void Fractorium::InitParamsUI()
SetupSpinner<DoubleSpinBox, double>(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<DoubleSpinBox, double>(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<DoubleSpinBox, double>(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<DoubleSpinBox, double>(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<DoubleSpinBox, double>(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&)));
}
/// <summary>
/// Return whether the apply all checkbox is checked.
/// </summary>
/// <returns>True if checked, else false.</returns>
bool Fractorium::ApplyAll()
{
return ui.ApplyAllParamsCheckBox->isChecked();
}
/// <summary>
/// Color.
/// </summary>
@ -106,7 +115,13 @@ void Fractorium::InitParamsUI()
/// </summary>
/// <param name="d">The brightness</param>
template <typename T>
void FractoriumEmberController<T>::BrightnessChanged(double d) { Update([&] { m_Ember.m_Brightness = d; }, true, eProcessAction::FILTER_AND_ACCUM); }
void FractoriumEmberController<T>::BrightnessChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_Brightness = d;
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
}
void Fractorium::OnBrightnessChanged(double d) { m_Controller->BrightnessChanged(d); }
/// <summary>
@ -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.
/// </summary>
/// <param name="d">The gamma value</param>
template <typename T> void FractoriumEmberController<T>::GammaChanged(double d) { Update([&] { m_Ember.m_Gamma = d; }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }
template <typename T> void FractoriumEmberController<T>::GammaChanged(double d)
{
UpdateAll([&](Ember<T>& 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); }
/// <summary>
@ -125,7 +146,13 @@ void Fractorium::OnGammaChanged(double d) { m_Controller->GammaChanged(d); }
/// Resets the rendering process to the final accumulation stage.
/// </summary>
/// <param name="d">The gamma threshold</param>
template <typename T> void FractoriumEmberController<T>::GammaThresholdChanged(double d) { Update([&] { m_Ember.m_GammaThresh = d; }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }
template <typename T> void FractoriumEmberController<T>::GammaThresholdChanged(double d)
{
UpdateAll([&](Ember<T>& 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); }
/// <summary>
@ -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.
/// </summary>
/// <param name="d">The vibrancy</param>
template <typename T> void FractoriumEmberController<T>::VibrancyChanged(double d) { Update([&] { m_Ember.m_Vibrancy = d; }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }
template <typename T> void FractoriumEmberController<T>::VibrancyChanged(double d)
{
UpdateAll([&](Ember<T>& 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); }
/// <summary>
@ -143,7 +176,13 @@ void Fractorium::OnVibrancyChanged(double d) { m_Controller->VibrancyChanged(d);
/// Resets the rendering process to the final accumulation stage.
/// </summary>
/// <param name="d">The highlight power</param>
template <typename T> void FractoriumEmberController<T>::HighlightPowerChanged(double d) { Update([&] { m_Ember.m_HighlightPower = d; }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }
template <typename T> void FractoriumEmberController<T>::HighlightPowerChanged(double d)
{
UpdateAll([&](Ember<T>& 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); }
/// <summary>
@ -166,24 +205,21 @@ void Fractorium::OnBackgroundColorButtonClicked(bool checked)
template <typename T>
void FractoriumEmberController<T>::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<T>& 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.
/// </summary>
/// <param name="index">The index of the palette mode combo box</param>
template <typename T> void FractoriumEmberController<T>::PaletteModeChanged(uint i) { Update([&] { m_Ember.m_PaletteMode = i == 0 ? ePaletteMode::PALETTE_STEP : ePaletteMode::PALETTE_LINEAR; }); }
template <typename T> void FractoriumEmberController<T>::PaletteModeChanged(uint i)
{
UpdateAll([&](Ember<T>& 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); }
/// <summary>
@ -206,7 +248,13 @@ void Fractorium::OnPaletteModeComboCurrentIndexChanged(int index) { m_Controller
/// Dimensions are set automatically to match the dimensions of GLWidget.
/// </summary>
/// <param name="d">Ignored</param>
template <typename T> void FractoriumEmberController<T>::WidthChanged(uint i) { Update([&] { m_Ember.m_FinalRasW = i; }); }
template <typename T> void FractoriumEmberController<T>::WidthChanged(uint i)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_FinalRasW = i;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnWidthChanged(int i) { m_Controller->WidthChanged(i); }
/// <summary>
@ -214,7 +262,13 @@ void Fractorium::OnWidthChanged(int i) { m_Controller->WidthChanged(i); }
/// Dimensions are set automatically to match the dimensions of GLWidget.
/// </summary>
/// <param name="d">Ignored</param>
template <typename T> void FractoriumEmberController<T>::HeightChanged(uint i) { Update([&] { m_Ember.m_FinalRasH = i; }); }
template <typename T> void FractoriumEmberController<T>::HeightChanged(uint i)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_FinalRasH = i;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnHeightChanged(int i) { m_Controller->HeightChanged(i); }
/// <summary>
@ -222,7 +276,13 @@ void Fractorium::OnHeightChanged(int i) { m_Controller->HeightChanged(i); }
/// Resets the rendering process.
/// </summary>
/// <param name="d">The x offset value</param>
template <typename T> void FractoriumEmberController<T>::CenterXChanged(double d) { Update([&] { m_Ember.m_CenterX = d; }); }
template <typename T> void FractoriumEmberController<T>::CenterXChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_CenterX = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnCenterXChanged(double d) { m_Controller->CenterXChanged(d); }
/// <summary>
@ -230,7 +290,13 @@ void Fractorium::OnCenterXChanged(double d) { m_Controller->CenterXChanged(d); }
/// Resets the rendering process.
/// </summary>
/// <param name="d">The y offset value</param>
template <typename T> void FractoriumEmberController<T>::CenterYChanged(double d) { Update([&] { m_Ember.m_CenterY = m_Ember.m_RotCenterY = d; }); }
template <typename T> void FractoriumEmberController<T>::CenterYChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_CenterY = ember.m_RotCenterY = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnCenterYChanged(double d) { m_Controller->CenterYChanged(d); }
/// <summary>
@ -241,7 +307,13 @@ void Fractorium::OnCenterYChanged(double d) { m_Controller->CenterYChanged(d); }
/// Resets the rendering process.
/// </summary>
/// <param name="d">The scale value</param>
template <typename T> void FractoriumEmberController<T>::ScaleChanged(double d) { Update([&] { m_Ember.m_PixelsPerUnit = d; }); }
template <typename T> void FractoriumEmberController<T>::ScaleChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_PixelsPerUnit = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnScaleChanged(double d) { m_Controller->ScaleChanged(d); }
/// <summary>
@ -252,7 +324,13 @@ void Fractorium::OnScaleChanged(double d) { m_Controller->ScaleChanged(d); }
/// Resets the rendering process.
/// </summary>
/// <param name="d">The zoom value</param>
template <typename T> void FractoriumEmberController<T>::ZoomChanged(double d) { Update([&] { m_Ember.m_Zoom = d; }); }
template <typename T> void FractoriumEmberController<T>::ZoomChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_Zoom = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnZoomChanged(double d) { m_Controller->ZoomChanged(d); }
/// <summary>
@ -261,22 +339,58 @@ void Fractorium::OnZoomChanged(double d) { m_Controller->ZoomChanged(d); }
/// Resets the rendering process.
/// </summary>
/// <param name="d">The rotation in angles</param>
template <typename T> void FractoriumEmberController<T>::RotateChanged(double d) { Update([&] { m_Ember.m_Rotate = d; }); }
template <typename T> void FractoriumEmberController<T>::RotateChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_Rotate = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnRotateChanged(double d) { m_Controller->RotateChanged(d); }
template <typename T> void FractoriumEmberController<T>::ZPosChanged(double d) { Update([&] { m_Ember.m_CamZPos = d; }); }
template <typename T> void FractoriumEmberController<T>::ZPosChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_CamZPos = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnZPosChanged(double d) { m_Controller->ZPosChanged(d); }
template <typename T> void FractoriumEmberController<T>::PerspectiveChanged(double d) { Update([&] { m_Ember.m_CamPerspective = d; }); }
template <typename T> void FractoriumEmberController<T>::PerspectiveChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_CamPerspective = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnPerspectiveChanged(double d) { m_Controller->PerspectiveChanged(d); }
template <typename T> void FractoriumEmberController<T>::PitchChanged(double d) { Update([&] { m_Ember.m_CamPitch = d* DEG_2_RAD; }); }
template <typename T> void FractoriumEmberController<T>::PitchChanged(double d)
{
UpdateAll([&](Ember<T>& 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 <typename T> void FractoriumEmberController<T>::YawChanged(double d) { Update([&] { m_Ember.m_CamYaw = d* DEG_2_RAD; }); }
template <typename T> void FractoriumEmberController<T>::YawChanged(double d)
{
UpdateAll([&](Ember<T>& 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 <typename T> void FractoriumEmberController<T>::DepthBlurChanged(double d) { Update([&] { m_Ember.m_CamDepthBlur = d; }); }
template <typename T> void FractoriumEmberController<T>::DepthBlurChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_CamDepthBlur = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnDepthBlurChanged(double d) { m_Controller->DepthBlurChanged(d); }
/// <summary>
@ -291,10 +405,10 @@ void Fractorium::OnDepthBlurChanged(double d) { m_Controller->DepthBlurChanged(d
/// <param name="d">The spatial filter width</param>
template <typename T> void FractoriumEmberController<T>::SpatialFilterWidthChanged(double d)
{
Update([&]
UpdateAll([&](Ember<T>& 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
/// <param name="text">The spatial filter type</param>
template <typename T> void FractoriumEmberController<T>::SpatialFilterTypeChanged(const QString& text)
{
Update([&]
UpdateAll([&](Ember<T>& ember)
{
m_Ember.m_SpatialFilterType = SpatialFilterCreator<T>::FromString(text.toStdString());
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
ember.m_SpatialFilterType = SpatialFilterCreator<T>::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.
/// </summary>
/// <param name="d">The temporal filter width</param>
template <typename T> void FractoriumEmberController<T>::TemporalFilterWidthChanged(double d) { Update([&] { m_Ember.m_TemporalFilterWidth = d; }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
template <typename T> void FractoriumEmberController<T>::TemporalFilterWidthChanged(double d)
{
UpdateAll([&](Ember<T>& 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); }
/// <summary>
@ -332,7 +452,13 @@ void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->Temporal
/// In the future, when animation is implemented, this will have an effect.
/// </summary>
/// <param name="text">The name of the temporal filter</param>
template <typename T> void FractoriumEmberController<T>::TemporalFilterTypeChanged(const QString& text) { Update([&] { m_Ember.m_TemporalFilterType = TemporalFilterCreator<T>::FromString(text.toStdString()); }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
template <typename T> void FractoriumEmberController<T>::TemporalFilterTypeChanged(const QString& text)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_TemporalFilterType = TemporalFilterCreator<T>::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); }
/// <summary>
@ -349,10 +475,10 @@ void FractoriumEmberController<T>::DEFilterMinRadiusWidthChanged(double d)
return;
}
Update([&]
UpdateAll([&](Ember<T>& 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<T>::DEFilterMaxRadiusWidthChanged(double d)
return;
}
Update([&]
UpdateAll([&](Ember<T>& 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
/// <param name="d">The curve value</param>
template <typename T> void FractoriumEmberController<T>::DEFilterCurveWidthChanged(double d)
{
Update([&]
UpdateAll([&](Ember<T>& 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.
/// </summary>
/// <param name="d">The sub batch size value to set</param>
template <typename T> void FractoriumEmberController<T>::SbsChanged(int d) { Update([&] { m_Ember.m_SubBatchSize = d; }); }
template <typename T> void FractoriumEmberController<T>::SbsChanged(int d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_SubBatchSize = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnSbsChanged(int d) { m_Controller->SbsChanged(d); }
/// <summary>
@ -413,7 +545,13 @@ void Fractorium::OnSbsChanged(int d) { m_Controller->SbsChanged(d); }
/// Resets the rendering process.
/// </summary>
/// <param name="d">The fuse count value to set</param>
template <typename T> void FractoriumEmberController<T>::FuseChanged(int d) { Update([&] { m_Ember.m_FuseCount = d; }); }
template <typename T> void FractoriumEmberController<T>::FuseChanged(int d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_FuseCount = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
/// <summary>
@ -426,8 +564,8 @@ void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
/// the rendering process is continued, else it's reset.
/// </summary>
/// <param name="d">The quality in terms of iterations per pixel</param>
template <typename T> void FractoriumEmberController<T>::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 <typename T> void FractoriumEmberController<T>::QualityChanged(double d) { }
void Fractorium::OnQualityChanged(double d) { m_Controller->QualityChanged(d); }
/// <summary>
/// Set the supersample.
@ -440,7 +578,13 @@ void Fractorium::OnQualityChanged(double d) { /*m_Controller->QualityChanged(d);
/// Resets the rendering process.
/// </summary>
/// <param name="d">The supersample value to set</param>
template <typename T> void FractoriumEmberController<T>::SupersampleChanged(int d) { Update([&] { m_Ember.m_Supersample = d; }); }
template <typename T> void FractoriumEmberController<T>::SupersampleChanged(int d)
{
UpdateAll([&](Ember<T>& ember)
{
ember.m_Supersample = d;
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
}
void Fractorium::OnSupersampleChanged(int d) { m_Controller->SupersampleChanged(d); }
/// <summary>
@ -450,7 +594,13 @@ void Fractorium::OnSupersampleChanged(int d) { m_Controller->SupersampleChanged(
/// In the future, when animation is implemented, this will have an effect.
/// </summary>
/// <param name="d">The temporal samples value</param>
template <typename T> void FractoriumEmberController<T>::TemporalSamplesChanged(int i) { Update([&] { m_Ember.m_TemporalSamples = i; }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
template <typename T> void FractoriumEmberController<T>::TemporalSamplesChanged(int i)
{
UpdateAll([&](Ember<T>& 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); }
/// <summary>
@ -463,15 +613,15 @@ void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamples
template <typename T>
void FractoriumEmberController<T>::AffineInterpTypeChanged(int i)
{
Update([&]
UpdateAll([&](Ember<T>& 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 <typename T>
void FractoriumEmberController<T>::InterpTypeChanged(int i)
{
Update([&]
UpdateAll([&](Ember<T>& 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 <typename T>
void FractoriumEmberController<T>::SetCenter(double x, double y)
{
m_Ember.m_CenterX = x;
m_Ember.m_CenterY = m_Ember.m_RotCenterY = y;
UpdateAll([&](Ember<T>& 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.
}
/// <summary>

View File

@ -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<DoubleSpinBox, double>(ui.XformColorIndexTable, this, row, 1, m_XformColorIndexSpin, spinHeight, 0, 1, 0.01, SIGNAL(valueChanged(double)), SLOT(OnXformColorIndexChanged(double)), false, 0, 1, 0);
SetupSpinner<DoubleSpinBox, double>(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<DoubleSpinBox, double>(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);
}
/// <summary>
@ -70,6 +72,35 @@ void FractoriumEmberController<T>::XformScrollColorIndexChanged(int d)
void Fractorium::OnXformScrollColorIndexChanged(int d) { m_Controller->XformScrollColorIndexChanged(d); }
/// <summary>
/// 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.
/// </summary>
template <typename T>
void FractoriumEmberController<T>::RandomColorIndicesButtonClicked()
{
UpdateXform([&](Xform<T>* xform) { xform->m_ColorX = m_Rand.Frand01<T>(); }, 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(); }
/// <summary>
/// Resets the rendering process.
/// Set all xform color indices to either 0 and 1, sequentially toggling.
/// Called when the Toggle Indices button is clicked.
/// </summary>
template <typename T>
void FractoriumEmberController<T>::ToggleColorIndicesButtonClicked()
{
char ch = 1;
UpdateXform([&](Xform<T>* 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(); }
/// <summary>
/// Set the color speed of the selected xforms.
/// Called when xform color speed spinner is changed.

View File

@ -427,9 +427,7 @@ void GLEmberController<T>::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.