--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 QCheckBox
{ {
spacing: 5px; spacing: 5px;
outline: 0px;
} }
QCheckBox::indicator, QCheckBox::indicator,

View File

@ -1311,7 +1311,7 @@ public:
if (useDefaults) if (useDefaults)
{ {
//If defaults are on, set to reasonable values. //If defaults are on, set to reasonable values.
m_HighlightPower = -1; m_HighlightPower = 1;
m_Background.Reset(); m_Background.Reset();
m_FinalRasW = 100; m_FinalRasW = 100;
m_FinalRasH = 100; m_FinalRasH = 100;
@ -1327,6 +1327,8 @@ public:
m_BlurCoef = 0; m_BlurCoef = 0;
m_CamMat = m3T(0); m_CamMat = m3T(0);
m_Quality = 1; m_Quality = 1;
m_SubBatchSize = 10240;
m_FuseCount = 15;
m_MaxRadDE = T(9.0); m_MaxRadDE = T(9.0);
m_MinRadDE = 0; m_MinRadDE = 0;
m_CurveDE = T(0.4); m_CurveDE = T(0.4);
@ -1337,7 +1339,8 @@ public:
m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER; m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER;
m_TemporalFilterWidth = 1; m_TemporalFilterWidth = 1;
m_TemporalFilterExp = 0; m_TemporalFilterExp = 0;
m_PaletteMode = ePaletteMode::PALETTE_STEP; m_PaletteMode = ePaletteMode::PALETTE_LINEAR;
m_Interp = eInterp::EMBER_INTERP_SMOOTH;
} }
else else
{ {
@ -1358,6 +1361,8 @@ public:
m_BlurCoef = 999999; m_BlurCoef = 999999;
m_CamMat = m3T(999999); m_CamMat = m3T(999999);
m_Quality = -1; m_Quality = -1;
m_SubBatchSize = 0;
m_FuseCount = 0;
m_MaxRadDE = -1; m_MaxRadDE = -1;
m_MinRadDE = -1; m_MinRadDE = -1;
m_CurveDE = -1; m_CurveDE = -1;
@ -1369,6 +1374,7 @@ public:
m_TemporalFilterWidth = -1; m_TemporalFilterWidth = -1;
m_TemporalFilterExp = -999; m_TemporalFilterExp = -999;
m_PaletteMode = ePaletteMode::PALETTE_STEP; m_PaletteMode = ePaletteMode::PALETTE_STEP;
m_Interp = eInterp::EMBER_INTERP_LINEAR;
} }
m_Xforms.clear(); m_Xforms.clear();
@ -1573,7 +1579,7 @@ public:
//Value to control saturation of some pixels in gamma correction during final accumulation. //Value to control saturation of some pixels in gamma correction during final accumulation.
//Xml field: "highlight_power". //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 //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. //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 else
{ {
ember.m_Palette.Clear(false); 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";
} }
} }
} }
@ -799,7 +799,7 @@ public:
if (best < 0) if (best < 0)
{ {
cout << "Error in TryColors(), skipping ImproveColors()\n"; cerr << "Error in TryColors(), skipping ImproveColors()\n";
return; return;
} }
@ -810,7 +810,7 @@ public:
if (b < 0) if (b < 0)
{ {
cout << "Error in TryColors, aborting tries.\n"; cerr << "Error in TryColors, aborting tries.\n";
break; break;
} }
@ -826,10 +826,12 @@ public:
/// <summary> /// <summary>
/// Run a test render to improve the colors. /// 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> /// </summary>
/// <param name="ember">The ember to render</param> /// <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> /// <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 number of histogram cells that weren't black</returns> /// <returns>The percentage possible color values that were present in the final output image</returns>
T TryColors(Ember<T>& ember, size_t colorResolution) T TryColors(Ember<T>& ember, size_t colorResolution)
{ {
byte* p; byte* p;
@ -848,37 +850,31 @@ public:
adjustedEmber.m_PixelsPerUnit *= scalar; adjustedEmber.m_PixelsPerUnit *= scalar;
adjustedEmber.m_TemporalSamples = 1; adjustedEmber.m_TemporalSamples = 1;
m_Renderer->SetEmber(adjustedEmber); m_Renderer->SetEmber(adjustedEmber);
m_Renderer->BytesPerChannel(1);
m_Renderer->EarlyClip(true); 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) 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; return -1;
} }
m_Hist.resize(res3); m_Hist.resize(res3);
memset(m_Hist.data(), 0, res3); Memset(m_Hist);
p = m_FinalImage.data(); p = m_FinalImage.data();
for (i = 0; i < m_Renderer->FinalDimensions(); i++) for (i = 0; i < m_Renderer->FinalDimensions(); i++)
{ {
m_Hist[(p[0] * res / 256) + m_Hist[(p[0] * res / 256) +
(p[1] * res / 256) * res + (p[1] * res / 256) * res +
(p[2] * res / 256) * res * res]++; (p[2] * res / 256) * res * res]++;//A specific histogram index representing the sum of R,G,B values.
p += m_Renderer->NumChannels(); p += m_Renderer->PixelSize();//Advance the pointer by 1 pixel.
} }
for (i = 0; i < res3; i++) for (i = 0; i < res3; i++)
{ if (m_Hist[i])//The greater range of RGB values used...
if (m_Hist[i])
hits++; hits++;
}
return T(hits / res3); return T(hits / res3);//...the higher this returned ratio will be.
} }
/// <summary> /// <summary>
@ -897,7 +893,7 @@ public:
else else
{ {
ember.m_Palette.Clear(false); 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) if (templ.m_Background[i] >= 0)
ember.m_Background[i] = templ.m_Background[i]; ember.m_Background[i] = templ.m_Background[i];
if (templ.m_Zoom < 999999998) if (templ.m_Zoom < 999999)
ember.m_Zoom = templ.m_Zoom; ember.m_Zoom = templ.m_Zoom;
if (templ.m_Supersample > 0) if (templ.m_Supersample > 0)
@ -1127,6 +1123,12 @@ public:
if (templ.m_Quality > 0) if (templ.m_Quality > 0)
ember.m_Quality = templ.m_Quality; 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) if (templ.m_TemporalSamples > 0)
ember.m_TemporalSamples = templ.m_TemporalSamples; ember.m_TemporalSamples = templ.m_TemporalSamples;
@ -1155,10 +1157,10 @@ public:
if (templ.m_SpatialFilterType > eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER) if (templ.m_SpatialFilterType > eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER)
ember.m_SpatialFilterType = templ.m_SpatialFilterType; 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; 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; ember.m_AffineInterp = templ.m_AffineInterp;
if (templ.m_TemporalFilterType >= eTemporalFilterType::BOX_TEMPORAL_FILTER) if (templ.m_TemporalFilterType >= eTemporalFilterType::BOX_TEMPORAL_FILTER)
@ -1167,13 +1169,13 @@ public:
if (templ.m_TemporalFilterWidth > 0) if (templ.m_TemporalFilterWidth > 0)
ember.m_TemporalFilterWidth = templ.m_TemporalFilterWidth; ember.m_TemporalFilterWidth = templ.m_TemporalFilterWidth;
if (templ.m_TemporalFilterExp > -900) if (templ.m_TemporalFilterExp > -999)
ember.m_TemporalFilterExp = templ.m_TemporalFilterExp; ember.m_TemporalFilterExp = templ.m_TemporalFilterExp;
if (templ.m_HighlightPower >= 0) if (templ.m_HighlightPower != 1)
ember.m_HighlightPower = templ.m_HighlightPower; 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; ember.m_PaletteMode = templ.m_PaletteMode;
} }

View File

@ -21,7 +21,6 @@ template <typename T>
class EMBER_API VariationList: public Singleton<VariationList<T>> class EMBER_API VariationList: public Singleton<VariationList<T>>
{ {
public: public:
//~VariationList();
const Variation<T>* GetVariation(size_t index) const; const Variation<T>* GetVariation(size_t index) const;
const Variation<T>* GetVariation(size_t index, eVariationType varType) const; const Variation<T>* GetVariation(size_t index, eVariationType varType) const;
Variation<T>* GetVariationCopy(size_t index, T weight = 1) 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))) if (!m_ParentEmber && (typeid(T) == typeid(U)))
m_ParentEmber = reinterpret_cast<Ember<T>*>(xform.ParentEmber()); 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); CopyCont(m_Motion, xform.m_Motion);
m_Name = xform.m_Name; m_Name = xform.m_Name;
return *this; return *this;

View File

@ -524,6 +524,12 @@ private:
AddToReport(string(loc) + " : Error assigning palette with index " + Itos(currentEmber.PaletteIndex())); 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)) //if (!Interpolater<T>::InterpMissingColors(currentEmber.m_Palette.m_Entries))
// AddToReport(string(loc) + " : Error interpolating missing palette colors"); // AddToReport(string(loc) + " : Error interpolating missing palette colors");
currentEmber.CacheXforms(); currentEmber.CacheXforms();

View File

@ -121,7 +121,6 @@ enum class eOptionIDs : et
OPT_METHOD, OPT_METHOD,
OPT_INTER, OPT_INTER,
OPT_ROTATE, OPT_ROTATE,
OPT_STRIP,
OPT_SEQUENCE, OPT_SEQUENCE,
OPT_USE_VARS, OPT_USE_VARS,
OPT_DONT_USE_VARS, OPT_DONT_USE_VARS,
@ -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(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(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(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(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(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")); 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_METHOD, Method);
PARSESTRINGOPTION(eOptionIDs::OPT_INTER, Inter); PARSESTRINGOPTION(eOptionIDs::OPT_INTER, Inter);
PARSESTRINGOPTION(eOptionIDs::OPT_ROTATE, Rotate); PARSESTRINGOPTION(eOptionIDs::OPT_ROTATE, Rotate);
PARSESTRINGOPTION(eOptionIDs::OPT_STRIP, Strip);
PARSESTRINGOPTION(eOptionIDs::OPT_SEQUENCE, Sequence); PARSESTRINGOPTION(eOptionIDs::OPT_SEQUENCE, Sequence);
PARSESTRINGOPTION(eOptionIDs::OPT_USE_VARS, UseVars); PARSESTRINGOPTION(eOptionIDs::OPT_USE_VARS, UseVars);
PARSESTRINGOPTION(eOptionIDs::OPT_DONT_USE_VARS, DontUseVars); PARSESTRINGOPTION(eOptionIDs::OPT_DONT_USE_VARS, DontUseVars);
@ -804,7 +801,6 @@ public:
Eos Method; Eos Method;
Eos Inter; Eos Inter;
Eos Rotate; Eos Rotate;
Eos Strip;
Eos Sequence; Eos Sequence;
Eos UseVars; Eos UseVars;
Eos DontUseVars; Eos DontUseVars;

View File

@ -74,8 +74,6 @@ bool EmberGenome(EmberOptions& opt)
for (auto& v : vars) for (auto& v : vars)
cout << v->Name() << "\n"; cout << v->Name() << "\n";
return true;
} }
else else
{ {
@ -100,8 +98,8 @@ bool EmberGenome(EmberOptions& opt)
VerbosePrint("Using " << (sizeof(T) == sizeof(float) ? "single" : "double") << " precision."); VerbosePrint("Using " << (sizeof(T) == sizeof(float) ? "single" : "double") << " precision.");
//Regular variables. //Regular variables.
Timing t; Timing t;
bool exactTimeMatch, randomMode, didColor, seqFlag; bool exactTimeMatch, randomMode, didColor, seqFlag, random = false;
size_t i, j, i0, i1, rep, val, frame, frameCount, count = 0; size_t i, i0, i1, rep, val, frame, frameCount, count = 0;
size_t ftime, firstFrame, lastFrame; size_t ftime, firstFrame, lastFrame;
size_t n, tot, totb, totw; size_t n, tot, totb, totw;
T avgPix, fractionBlack, fractionWhite, blend, spread, mix0, mix1; T avgPix, fractionBlack, fractionWhite, blend, spread, mix0, mix1;
@ -113,7 +111,6 @@ bool EmberGenome(EmberOptions& opt)
eCrossMode crossMeth; eCrossMode crossMeth;
eMutateMode mutMeth; eMutateMode mutMeth;
Ember<T> orig, save, selp0, selp1, parent0, parent1; Ember<T> orig, save, selp0, selp1, parent0, parent1;
Ember<T> result, result1, result2, result3, interpolated;
Ember<T>* aselp0, *aselp1, *pTemplate = nullptr; Ember<T>* aselp0, *aselp1, *pTemplate = nullptr;
XmlToEmber<T> parser; XmlToEmber<T> parser;
EmberToXml<T> emberToXml; EmberToXml<T> emberToXml;
@ -193,19 +190,11 @@ bool EmberGenome(EmberOptions& opt)
noVars.push_back(eVariationId::VAR_SPLIT); noVars.push_back(eVariationId::VAR_SPLIT);
noVars.push_back(eVariationId::VAR_SPLITS); 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 (i = 0; i < varList->Size(); i++)
{ if (!Contains(noVars, varList->GetVariation(i)->VariationId()))
for (j = 0; j < noVars.size(); j++)
{
if (noVars[j] == varList->GetVariation(i)->VariationId())
break;
}
if (j == noVars.size())
vars.push_back(varList->GetVariation(i)->VariationId()); vars.push_back(varList->GetVariation(i)->VariationId());
} }
}
else else
{ {
if (opt.UseVars() != "")//Parse comma-separated list of variations to use. if (opt.UseVars() != "")//Parse comma-separated list of variations to use.
@ -234,38 +223,28 @@ 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 (i = 0; i < varList->Size(); i++)
{ if (!Contains(noVars, varList->GetVariation(i)->VariationId()))
for (j = 0; j < noVars.size(); j++)
{
if (noVars[j] == varList->GetVariation(i)->VariationId())
break;
}
if (j == noVars.size())
vars.push_back(varList->GetVariation(i)->VariationId()); vars.push_back(varList->GetVariation(i)->VariationId());
} }
} }
}
bool doMutate = opt.Mutate() != ""; bool doMutate = opt.Mutate() != "";
bool doInter = opt.Inter() != ""; bool doInter = opt.Inter() != "";
bool doRotate = opt.Rotate() != ""; bool doRotate = opt.Rotate() != "";
bool doClone = opt.Clone() != ""; bool doClone = opt.Clone() != "";
bool doStrip = opt.Strip() != "";
bool doCross0 = opt.Cross0() != ""; bool doCross0 = opt.Cross0() != "";
bool doCross1 = opt.Cross1() != ""; bool doCross1 = opt.Cross1() != "";
count += (doMutate ? 1 : 0); count += (doMutate ? 1 : 0);
count += (doInter ? 1 : 0); count += (doInter ? 1 : 0);
count += (doRotate ? 1 : 0); count += (doRotate ? 1 : 0);
count += (doClone ? 1 : 0); count += (doClone ? 1 : 0);
count += (doStrip ? 1 : 0);
count += ((doCross0 || doCross1) ? 1 : 0); count += ((doCross0 || doCross1) ? 1 : 0);
if (count > 1) 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; return false;
} }
@ -297,17 +276,18 @@ bool EmberGenome(EmberOptions& opt)
else if (doInter) filename = opt.Inter(); else if (doInter) filename = opt.Inter();
else if (doRotate) filename = opt.Rotate(); else if (doRotate) filename = opt.Rotate();
else if (doClone) filename = opt.Clone(); else if (doClone) filename = opt.Clone();
else if (doStrip) filename = opt.Strip();
else if (doCross0) filename = opt.Cross0(); else if (doCross0) filename = opt.Cross0();
else if (opt.CloneAll() != "") filename = opt.CloneAll(); else if (opt.CloneAll() != "") filename = opt.CloneAll();
else if (opt.Animate() != "") filename = opt.Animate(); else if (opt.Animate() != "") filename = opt.Animate();
else if (opt.Sequence() != "") filename = opt.Sequence(); else if (opt.Sequence() != "") filename = opt.Sequence();
else if (opt.Inter() != "") filename = opt.Inter(); else if (opt.Inter() != "") filename = opt.Inter();
else if (opt.Rotate() != "") filename = opt.Rotate(); else if (opt.Rotate() != "") filename = opt.Rotate();
else if (opt.Strip() != "") filename = opt.Strip();
else if (opt.Clone() != "") filename = opt.Clone(); else if (opt.Clone() != "") filename = opt.Clone();
else if (opt.Mutate() != "") filename = opt.Mutate(); else if (opt.Mutate() != "") filename = opt.Mutate();
else random = true;
if (!random)
{
if (!ParseEmberFile(parser, filename, embers)) if (!ParseEmberFile(parser, filename, embers))
return false; return false;
@ -316,6 +296,7 @@ bool EmberGenome(EmberOptions& opt)
if (!ParseEmberFile(parser, opt.Cross1(), embers2)) if (!ParseEmberFile(parser, opt.Cross1(), embers2))
return false; return false;
} }
}
if (opt.CloneAll() != "") if (opt.CloneAll() != "")
{ {
@ -336,6 +317,8 @@ bool EmberGenome(EmberOptions& opt)
if (opt.Animate() != "") if (opt.Animate() != "")
{ {
Ember<T> interpolated;
for (i = 0; i < embers.size(); i++) for (i = 0; i < embers.size(); i++)
{ {
if (i > 0 && embers[i].m_Time <= embers[i - 1].m_Time) if (i > 0 && embers[i].m_Time <= embers[i - 1].m_Time)
@ -398,6 +381,8 @@ bool EmberGenome(EmberOptions& opt)
if (opt.Sequence() != "") if (opt.Sequence() != "")
{ {
Ember<T> result;
if (opt.Frames() == 0) if (opt.Frames() == 0)
{ {
cerr << "nframes must be positive and non-zero, not " << opt.Frames() << ".\n"; cerr << "nframes must be positive and non-zero, not " << opt.Frames() << ".\n";
@ -465,7 +450,7 @@ bool EmberGenome(EmberOptions& opt)
if (doInter || doRotate) if (doInter || doRotate)
{ {
frame = std::max(opt.Frame(), opt.Time()); Ember<T> result, result1, result2, result3;
if (opt.Frames() == 0) if (opt.Frames() == 0)
{ {
@ -473,8 +458,9 @@ bool EmberGenome(EmberOptions& opt)
return false; return false;
} }
blend = frame / T(opt.Frames()); frame = opt.Frame();
spread = 1 / T(opt.Frames()); 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()) if (opt.Enclosed())
cout << "<pick version=\"EMBER-" << EmberVersion() << "\">\n"; cout << "<pick version=\"EMBER-" << EmberVersion() << "\">\n";
@ -487,10 +473,14 @@ bool EmberGenome(EmberOptions& opt)
return false; return false;
} }
if (frame)//Cannot spin backward below frame zero.
{
tools.Spin(embers[0], pTemplate, result1, frame - 1, blend - spread); 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, result2, frame , blend );
tools.Spin(embers[0], pTemplate, result3, frame + 1, blend + spread); 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(result2, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
cout << emberToXml.ToString(result3, 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; return false;
} }
tools.SpinInter(embers.data(), pTemplate, result1, frame - 1, 0, blend - spread); if (frame)//Cannot interpolate backward below frame zero.
tools.SpinInter(embers.data(), pTemplate, result2, frame , 0, blend ); {
tools.SpinInter(embers.data(), pTemplate, result3, frame + 1, 0, blend + spread); tools.SpinInter(embers.data(), pTemplate, result1, frame - 1, false, blend - spread);
cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); 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(result2, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
cout << emberToXml.ToString(result3, 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; 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. //Repeat.
renderer->EarlyClip(opt.EarlyClip()); renderer->EarlyClip(opt.EarlyClip());
renderer->YAxisUp(opt.YAxisUp()); renderer->YAxisUp(opt.YAxisUp());
@ -567,7 +531,7 @@ bool EmberGenome(EmberOptions& opt)
count = 0; count = 0;
os.str(""); os.str("");
save.Clear(); save.Clear();
VerbosePrint("Flame = " << rep + 1 << "/" << opt.Repeat() << ".."); VerbosePrint("Flame = " << rep + 1 << "/" << opt.Repeat() << "...");
if (opt.Clone() != "") if (opt.Clone() != "")
{ {
@ -657,7 +621,7 @@ bool EmberGenome(EmberOptions& opt)
crossMeth = eCrossMode::CROSS_NOT_SPECIFIED; 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 != "") if (embers[i0].m_Name != "" || embers2[i1].m_Name != "")
{ {
@ -671,6 +635,8 @@ bool EmberGenome(EmberOptions& opt)
os << "random"; os << "random";
randomMode = true; randomMode = true;
tools.Random(orig, vars, opt.Symmetry(), 0, MAX_CL_VARS); tools.Random(orig, vars, opt.Symmetry(), 0, MAX_CL_VARS);
orig.m_FinalRasW = 1920;
orig.m_FinalRasH = 1080;
aselp0 = nullptr; aselp0 = nullptr;
aselp1 = nullptr; aselp1 = nullptr;
} }

View File

@ -87,6 +87,7 @@ public:
~Fractorium(); ~Fractorium();
//Geometry. //Geometry.
bool ApplyAll();
void SetCenter(float x, float y); void SetCenter(float x, float y);
void SetRotation(double rot, bool stealth); void SetRotation(double rot, bool stealth);
void SetScale(double scale); void SetScale(double scale);
@ -241,6 +242,8 @@ public slots:
void OnXformColorIndexChanged(double d); void OnXformColorIndexChanged(double d);
void OnXformColorIndexChanged(double d, bool updateRender); void OnXformColorIndexChanged(double d, bool updateRender);
void OnXformScrollColorIndexChanged(int d); void OnXformScrollColorIndexChanged(int d);
void OnRandomColorIndicesButtonClicked(bool b);
void OnToggleColorIndicesButtonClicked(bool b);
void OnXformColorSpeedChanged(double d); void OnXformColorSpeedChanged(double d);
void OnXformOpacityChanged(double d); void OnXformOpacityChanged(double d);
void OnXformDirectColorChanged(double d); void OnXformDirectColorChanged(double d);

View File

@ -140,6 +140,16 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>4</number> <number>4</number>
</property> </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> <item>
<widget class="QScrollArea" name="FlameTabScrollArea"> <widget class="QScrollArea" name="FlameTabScrollArea">
<property name="frameShape"> <property name="frameShape">
@ -157,7 +167,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>230</width> <width>230</width>
<height>950</height> <height>933</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
@ -176,7 +186,7 @@
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
<item row="10" column="0"> <item row="12" column="0">
<widget class="TableWidget" name="IterationTable"> <widget class="TableWidget" name="IterationTable">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -346,7 +356,23 @@
</item> </item>
</widget> </widget>
</item> </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"> <widget class="QTableWidget" name="GeometryTableHeader">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
@ -427,7 +453,7 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="9" column="0"> <item row="11" column="0">
<widget class="QTableWidget" name="IterationTableHeader"> <widget class="QTableWidget" name="IterationTableHeader">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
@ -508,7 +534,7 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="1" column="0">
<widget class="QTableWidget" name="ColorTableHeader"> <widget class="QTableWidget" name="ColorTableHeader">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
@ -595,7 +621,7 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="8" column="0"> <item row="10" column="0">
<spacer name="FlameTabVerticalSpacer3"> <spacer name="FlameTabVerticalSpacer3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -611,7 +637,7 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="6" column="0"> <item row="8" column="0">
<widget class="QTableWidget" name="FilterTableHeader"> <widget class="QTableWidget" name="FilterTableHeader">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
@ -692,7 +718,7 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="7" column="0">
<spacer name="FlameTabVerticalSpacer2"> <spacer name="FlameTabVerticalSpacer2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -708,7 +734,7 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="2" column="0"> <item row="4" column="0">
<spacer name="FlameTabVerticalSpacer1"> <spacer name="FlameTabVerticalSpacer1">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -724,7 +750,7 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="4" column="0"> <item row="6" column="0">
<widget class="TableWidget" name="GeometryTable"> <widget class="TableWidget" name="GeometryTable">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1014,7 +1040,7 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="7" column="0"> <item row="9" column="0">
<widget class="TableWidget" name="FilterTable"> <widget class="TableWidget" name="FilterTable">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1199,7 +1225,7 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="3" column="0">
<widget class="TableWidget" name="ColorTable"> <widget class="TableWidget" name="ColorTable">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1423,7 +1449,7 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="14" column="0"> <item row="16" column="0">
<widget class="QTableWidget" name="AnimationTableHeader"> <widget class="QTableWidget" name="AnimationTableHeader">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1504,7 +1530,7 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="13" column="0"> <item row="15" column="0">
<spacer name="FlameTabVerticalSpacer4"> <spacer name="FlameTabVerticalSpacer4">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -1520,7 +1546,7 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="15" column="0"> <item row="17" column="0">
<widget class="QTableWidget" name="AnimationTable"> <widget class="QTableWidget" name="AnimationTable">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1661,22 +1687,6 @@
</item> </item>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
</widget> </widget>
@ -3217,7 +3227,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2"> <item row="4" column="0" colspan="2">
<widget class="TableWidget" name="XformColorValuesTable"> <widget class="TableWidget" name="XformColorValuesTable">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum"> <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
@ -3403,7 +3413,37 @@
</item> </item>
</widget> </widget>
</item> </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"> <widget class="QCheckBox" name="SoloXformCheckBox">
<property name="text"> <property name="text">
<string>Solo</string> <string>Solo</string>
@ -3473,8 +3513,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>118</width> <width>263</width>
<height>618</height> <height>700</height>
</rect> </rect>
</property> </property>
<property name="autoFillBackground"> <property name="autoFillBackground">
@ -5491,8 +5531,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>133</width> <width>259</width>
<height>52</height> <height>652</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -6767,6 +6807,7 @@
<addaction name="ActionRedo"/> <addaction name="ActionRedo"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="ActionStartStopRenderer"/> <addaction name="ActionStartStopRenderer"/>
<addaction name="ActionRenderPreviews"/>
<addaction name="ActionStopRenderingPreviews"/> <addaction name="ActionStopRenderingPreviews"/>
<addaction name="ActionFinalRender"/> <addaction name="ActionFinalRender"/>
<addaction name="separator"/> <addaction name="separator"/>

View File

@ -208,6 +208,27 @@ void FractoriumEmberController<T>::Update(std::function<void (void)> func, bool
UpdateRender(action); 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> /// <summary>
/// Wrapper to call a function on the specified xforms, then optionally add the requested action to the rendering queue. /// 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. /// 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"; string filename = QDir::homePath().toStdString() + "/.config/fractorium/last.flame";
#endif #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(); m_GLController->ResetMouseState();
FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo. FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo.
FillParamTablesAndPalette(); FillParamTablesAndPalette();

View File

@ -186,6 +186,8 @@ public:
//Xforms Color. //Xforms Color.
virtual void XformColorIndexChanged(double d, bool updateRender) { } virtual void XformColorIndexChanged(double d, bool updateRender) { }
virtual void XformScrollColorIndexChanged(int d) { } virtual void XformScrollColorIndexChanged(int d) { }
virtual void RandomColorIndicesButtonClicked() { }
virtual void ToggleColorIndicesButtonClicked() { }
virtual void XformColorSpeedChanged(double d) { } virtual void XformColorSpeedChanged(double d) { }
virtual void XformOpacityChanged(double d) { } virtual void XformOpacityChanged(double d) { }
virtual void XformDirectColorChanged(double d) { } virtual void XformDirectColorChanged(double d) { }
@ -431,6 +433,8 @@ public:
//Xforms Color. //Xforms Color.
virtual void XformColorIndexChanged(double d, bool updateRender) override; virtual void XformColorIndexChanged(double d, bool updateRender) override;
virtual void XformScrollColorIndexChanged(int d) override; virtual void XformScrollColorIndexChanged(int d) override;
virtual void RandomColorIndicesButtonClicked() override;
virtual void ToggleColorIndicesButtonClicked() override;
virtual void XformColorSpeedChanged(double d) override; virtual void XformColorSpeedChanged(double d) override;
virtual void XformOpacityChanged(double d) override; virtual void XformOpacityChanged(double d) override;
virtual void XformDirectColorChanged(double d) override; virtual void XformDirectColorChanged(double d) override;
@ -494,6 +498,7 @@ private:
//Rendering/progress. //Rendering/progress.
void Update(std::function<void (void)> func, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER); 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(); bool SyncSizes();
//Templated members. //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_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_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_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_GammaThresholdSpin->setDecimals(4);
m_BackgroundColorButton = new QPushButton("...", table); m_BackgroundColorButton = new QPushButton("...", table);
m_BackgroundColorButton->setMinimumWidth(21); 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&))); 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> /// <summary>
/// Color. /// Color.
/// </summary> /// </summary>
@ -106,7 +115,13 @@ void Fractorium::InitParamsUI()
/// </summary> /// </summary>
/// <param name="d">The brightness</param> /// <param name="d">The brightness</param>
template <typename T> 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); } void Fractorium::OnBrightnessChanged(double d) { m_Controller->BrightnessChanged(d); }
/// <summary> /// <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. /// else if early clip is true, filter and accum, else final accum only.
/// </summary> /// </summary>
/// <param name="d">The gamma value</param> /// <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); } void Fractorium::OnGammaChanged(double d) { m_Controller->GammaChanged(d); }
/// <summary> /// <summary>
@ -125,7 +146,13 @@ void Fractorium::OnGammaChanged(double d) { m_Controller->GammaChanged(d); }
/// Resets the rendering process to the final accumulation stage. /// Resets the rendering process to the final accumulation stage.
/// </summary> /// </summary>
/// <param name="d">The gamma threshold</param> /// <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); } void Fractorium::OnGammaThresholdChanged(double d) { m_Controller->GammaThresholdChanged(d); }
/// <summary> /// <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. /// Resets the rendering process to the final accumulation stage if temporal samples is 1, else full reset.
/// </summary> /// </summary>
/// <param name="d">The vibrancy</param> /// <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); } void Fractorium::OnVibrancyChanged(double d) { m_Controller->VibrancyChanged(d); }
/// <summary> /// <summary>
@ -143,7 +176,13 @@ void Fractorium::OnVibrancyChanged(double d) { m_Controller->VibrancyChanged(d);
/// Resets the rendering process to the final accumulation stage. /// Resets the rendering process to the final accumulation stage.
/// </summary> /// </summary>
/// <param name="d">The highlight power</param> /// <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); } void Fractorium::OnHighlightPowerChanged(double d) { m_Controller->HighlightPowerChanged(d); }
/// <summary> /// <summary>
@ -165,25 +204,22 @@ void Fractorium::OnBackgroundColorButtonClicked(bool checked)
/// <param name="color">The color to set, RGB in the 0-255 range</param> /// <param name="color">The color to set, RGB in the 0-255 range</param>
template <typename T> template <typename T>
void FractoriumEmberController<T>::BackgroundChanged(const QColor& color) void FractoriumEmberController<T>::BackgroundChanged(const QColor& color)
{
Update([&]
{ {
int itemRow = 5; int itemRow = 5;
auto colorTable = m_Fractorium->ui.ColorTable; auto colorTable = m_Fractorium->ui.ColorTable;
colorTable->item(itemRow, 1)->setBackgroundColor(color); colorTable->item(itemRow, 1)->setBackgroundColor(color);
auto r = ToString(color.red()); auto r = ToString(color.red());
auto g = ToString(color.green()); auto g = ToString(color.green());
auto b = ToString(color.blue()); auto b = ToString(color.blue());
colorTable->item(itemRow, 1)->setTextColor(VisibleColor(color)); colorTable->item(itemRow, 1)->setTextColor(VisibleColor(color));
colorTable->item(itemRow, 1)->setText("rgb(" + r + ", " + g + ", " + b + ")"); colorTable->item(itemRow, 1)->setText("rgb(" + r + ", " + g + ", " + b + ")");
UpdateAll([&](Ember<T>& ember)
{
//Color is 0-255, normalize to 0-1. //Color is 0-255, normalize to 0-1.
m_Ember.m_Background.r = color.red() / 255.0; ember.m_Background.r = color.red() / 255.0;
m_Ember.m_Background.g = color.green() / 255.0; ember.m_Background.g = color.green() / 255.0;
m_Ember.m_Background.b = color.blue() / 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); } 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. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="index">The index of the palette mode combo box</param> /// <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); } void Fractorium::OnPaletteModeComboCurrentIndexChanged(int index) { m_Controller->PaletteModeChanged(index); }
/// <summary> /// <summary>
@ -206,7 +248,13 @@ void Fractorium::OnPaletteModeComboCurrentIndexChanged(int index) { m_Controller
/// Dimensions are set automatically to match the dimensions of GLWidget. /// Dimensions are set automatically to match the dimensions of GLWidget.
/// </summary> /// </summary>
/// <param name="d">Ignored</param> /// <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); } void Fractorium::OnWidthChanged(int i) { m_Controller->WidthChanged(i); }
/// <summary> /// <summary>
@ -214,7 +262,13 @@ void Fractorium::OnWidthChanged(int i) { m_Controller->WidthChanged(i); }
/// Dimensions are set automatically to match the dimensions of GLWidget. /// Dimensions are set automatically to match the dimensions of GLWidget.
/// </summary> /// </summary>
/// <param name="d">Ignored</param> /// <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); } void Fractorium::OnHeightChanged(int i) { m_Controller->HeightChanged(i); }
/// <summary> /// <summary>
@ -222,7 +276,13 @@ void Fractorium::OnHeightChanged(int i) { m_Controller->HeightChanged(i); }
/// Resets the rendering process. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="d">The x offset value</param> /// <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); } void Fractorium::OnCenterXChanged(double d) { m_Controller->CenterXChanged(d); }
/// <summary> /// <summary>
@ -230,7 +290,13 @@ void Fractorium::OnCenterXChanged(double d) { m_Controller->CenterXChanged(d); }
/// Resets the rendering process. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="d">The y offset value</param> /// <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); } void Fractorium::OnCenterYChanged(double d) { m_Controller->CenterYChanged(d); }
/// <summary> /// <summary>
@ -241,7 +307,13 @@ void Fractorium::OnCenterYChanged(double d) { m_Controller->CenterYChanged(d); }
/// Resets the rendering process. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="d">The scale value</param> /// <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); } void Fractorium::OnScaleChanged(double d) { m_Controller->ScaleChanged(d); }
/// <summary> /// <summary>
@ -252,7 +324,13 @@ void Fractorium::OnScaleChanged(double d) { m_Controller->ScaleChanged(d); }
/// Resets the rendering process. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="d">The zoom value</param> /// <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); } void Fractorium::OnZoomChanged(double d) { m_Controller->ZoomChanged(d); }
/// <summary> /// <summary>
@ -261,22 +339,58 @@ void Fractorium::OnZoomChanged(double d) { m_Controller->ZoomChanged(d); }
/// Resets the rendering process. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="d">The rotation in angles</param> /// <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); } 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); } 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); } 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); } 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); } 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); } void Fractorium::OnDepthBlurChanged(double d) { m_Controller->DepthBlurChanged(d); }
/// <summary> /// <summary>
@ -291,10 +405,10 @@ void Fractorium::OnDepthBlurChanged(double d) { m_Controller->DepthBlurChanged(d
/// <param name="d">The spatial filter width</param> /// <param name="d">The spatial filter width</param>
template <typename T> void FractoriumEmberController<T>::SpatialFilterWidthChanged(double d) template <typename T> void FractoriumEmberController<T>::SpatialFilterWidthChanged(double d)
{ {
Update([&] UpdateAll([&](Ember<T>& ember)
{ {
m_Ember.m_SpatialFilterRadius = d; ember.m_SpatialFilterRadius = d;
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
} }
void Fractorium::OnSpatialFilterWidthChanged(double d) { m_Controller->SpatialFilterWidthChanged(d); } 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> /// <param name="text">The spatial filter type</param>
template <typename T> void FractoriumEmberController<T>::SpatialFilterTypeChanged(const QString& text) template <typename T> void FractoriumEmberController<T>::SpatialFilterTypeChanged(const QString& text)
{ {
Update([&] UpdateAll([&](Ember<T>& ember)
{ {
m_Ember.m_SpatialFilterType = SpatialFilterCreator<T>::FromString(text.toStdString()); ember.m_SpatialFilterType = SpatialFilterCreator<T>::FromString(text.toStdString());
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); }, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
} }
void Fractorium::OnSpatialFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->SpatialFilterTypeChanged(text); } 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. /// In the future, when animation is implemented, this will have an effect.
/// </summary> /// </summary>
/// <param name="d">The temporal filter width</param> /// <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); } void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->TemporalFilterWidthChanged(d); }
/// <summary> /// <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. /// In the future, when animation is implemented, this will have an effect.
/// </summary> /// </summary>
/// <param name="text">The name of the temporal filter</param> /// <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); } void Fractorium::OnTemporalFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->TemporalFilterTypeChanged(text); }
/// <summary> /// <summary>
@ -349,10 +475,10 @@ void FractoriumEmberController<T>::DEFilterMinRadiusWidthChanged(double d)
return; return;
} }
Update([&] UpdateAll([&](Ember<T>& ember)
{ {
m_Ember.m_MinRadDE = d; ember.m_MinRadDE = d;
}, true, eProcessAction::FILTER_AND_ACCUM); }, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
} }
void Fractorium::OnDEFilterMinRadiusWidthChanged(double d) { m_Controller->DEFilterMinRadiusWidthChanged(d); } void Fractorium::OnDEFilterMinRadiusWidthChanged(double d) { m_Controller->DEFilterMinRadiusWidthChanged(d); }
@ -371,10 +497,10 @@ void FractoriumEmberController<T>::DEFilterMaxRadiusWidthChanged(double d)
return; return;
} }
Update([&] UpdateAll([&](Ember<T>& ember)
{ {
m_Ember.m_MaxRadDE = d; ember.m_MaxRadDE = d;
}, true, eProcessAction::FILTER_AND_ACCUM); }, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
} }
void Fractorium::OnDEFilterMaxRadiusWidthChanged(double d) { m_Controller->DEFilterMaxRadiusWidthChanged(d); } 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> /// <param name="d">The curve value</param>
template <typename T> void FractoriumEmberController<T>::DEFilterCurveWidthChanged(double d) template <typename T> void FractoriumEmberController<T>::DEFilterCurveWidthChanged(double d)
{ {
Update([&] UpdateAll([&](Ember<T>& ember)
{ {
m_Ember.m_CurveDE = d; ember.m_CurveDE = d;
}, true, eProcessAction::FILTER_AND_ACCUM); }, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
} }
void Fractorium::OnDEFilterCurveWidthChanged(double d) { m_Controller->DEFilterCurveWidthChanged(d); } 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. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="d">The sub batch size value to set</param> /// <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); } void Fractorium::OnSbsChanged(int d) { m_Controller->SbsChanged(d); }
/// <summary> /// <summary>
@ -413,7 +545,13 @@ void Fractorium::OnSbsChanged(int d) { m_Controller->SbsChanged(d); }
/// Resets the rendering process. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="d">The fuse count value to set</param> /// <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); } void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
/// <summary> /// <summary>
@ -426,8 +564,8 @@ void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
/// the rendering process is continued, else it's reset. /// the rendering process is continued, else it's reset.
/// </summary> /// </summary>
/// <param name="d">The quality in terms of iterations per pixel</param> /// <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);*/ } template <typename T> void FractoriumEmberController<T>::QualityChanged(double d) { }
void Fractorium::OnQualityChanged(double d) { /*m_Controller->QualityChanged(d);*/ } void Fractorium::OnQualityChanged(double d) { m_Controller->QualityChanged(d); }
/// <summary> /// <summary>
/// Set the supersample. /// Set the supersample.
@ -440,7 +578,13 @@ void Fractorium::OnQualityChanged(double d) { /*m_Controller->QualityChanged(d);
/// Resets the rendering process. /// Resets the rendering process.
/// </summary> /// </summary>
/// <param name="d">The supersample value to set</param> /// <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); } void Fractorium::OnSupersampleChanged(int d) { m_Controller->SupersampleChanged(d); }
/// <summary> /// <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. /// In the future, when animation is implemented, this will have an effect.
/// </summary> /// </summary>
/// <param name="d">The temporal samples value</param> /// <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); } void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamplesChanged(d); }
/// <summary> /// <summary>
@ -463,15 +613,15 @@ void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamples
template <typename T> template <typename T>
void FractoriumEmberController<T>::AffineInterpTypeChanged(int i) void FractoriumEmberController<T>::AffineInterpTypeChanged(int i)
{ {
Update([&] UpdateAll([&](Ember<T>& ember)
{ {
if (i == 0) if (i == 0)
m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR; ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
else if (i == 1) else if (i == 1)
m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG; ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
else else
m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR; ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
}, true, eProcessAction::NOTHING); }, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
} }
void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Controller->AffineInterpTypeChanged(index); } void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Controller->AffineInterpTypeChanged(index); }
@ -486,15 +636,15 @@ void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Contr
template <typename T> template <typename T>
void FractoriumEmberController<T>::InterpTypeChanged(int i) void FractoriumEmberController<T>::InterpTypeChanged(int i)
{ {
Update([&] UpdateAll([&](Ember<T>& ember)
{ {
if (i == 0) if (i == 0)
m_Ember.m_Interp = eInterp::EMBER_INTERP_LINEAR; ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
else if (i == 1) else if (i == 1)
m_Ember.m_Interp = eInterp::EMBER_INTERP_SMOOTH; ember.m_Interp = eInterp::EMBER_INTERP_SMOOTH;
else else
m_Ember.m_Interp = eInterp::EMBER_INTERP_LINEAR; ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
}, true, eProcessAction::NOTHING); }, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
} }
void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller->InterpTypeChanged(index); } void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller->InterpTypeChanged(index); }
@ -509,13 +659,13 @@ void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller-
template <typename T> template <typename T>
void FractoriumEmberController<T>::SetCenter(double x, double y) void FractoriumEmberController<T>::SetCenter(double x, double y)
{ {
m_Ember.m_CenterX = x; UpdateAll([&](Ember<T>& ember)
m_Ember.m_CenterY = m_Ember.m_RotCenterY = y; {
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_CenterXSpin->SetValueStealth(x);//Don't trigger a redraw twice.
m_Fractorium->m_CenterYSpin->SetValueStealth(y); 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> /// <summary>

View File

@ -13,6 +13,8 @@ void Fractorium::InitXformsColorUI()
ui.XformPaletteRefTable->setItem(0, 0, m_PaletteRefItem); ui.XformPaletteRefTable->setItem(0, 0, m_PaletteRefItem);
ui.XformPaletteRefTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); 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.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.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_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); 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);
@ -70,6 +72,35 @@ void FractoriumEmberController<T>::XformScrollColorIndexChanged(int d)
void Fractorium::OnXformScrollColorIndexChanged(int d) { m_Controller->XformScrollColorIndexChanged(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> /// <summary>
/// Set the color speed of the selected xforms. /// Set the color speed of the selected xforms.
/// Called when xform color speed spinner is changed. /// 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)) if (mod.testFlag(Qt::ShiftModifier))
SetShift(); SetShift();
//if (mod.testFlag(Qt::ControlModifier))// || mod.testFlag(Qt::Key_C)) if (mod.testFlag(Qt::AltModifier))
// m_DragModifier |= DragModControl;
if (mod.testFlag(Qt::AltModifier))// || mod.testFlag(Qt::Key_A))
SetAlt(); SetAlt();
if (m_DragState == eDragState::DragNone)//Only take action if the user wasn't already dragging. if (m_DragState == eDragState::DragNone)//Only take action if the user wasn't already dragging.