mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 13:10:04 -05:00
--User changes
-Add animation sequence creation to Fractorium. -Add two new options to EmberGenome which are used when generating an animation sequence.: --startcount: Add this number to the filename of each flame. --padding: Override the automatically calculated amount of padding zeroes added to each filename. --Bug fixes -Prevent filenames in command line programs from using scientific notation when rendering a large number of frames. -Fix tab orders to match newer GUI items which were overlooked in previous releases. -Re-render previews if transparency value in the options dialog was changed. Re-rendering was previously only done if early clip or y axis up was changed. -Use transparency when rendering thumbnail previews. --Code changes -Wrap EmberCommon.h in a namespace called EmberCommon. -Move FormatName() from EmberGenome to EmberCommon.h/cpp -Add a prefix parameter to EmberFile::DefaultFilename() to allow for creating a default filename for sequences. -When showing the final render dialog, allow specifying where it came from: the toolbar or the render sequence button. -Refactor all preview rendering code out into its own class hierarchy with overrides for the main window and the final render dialog. -Remove all preview render cancelling functions, they are now built into the new class hierarchy and a new render will not start until the previous one is stopped. -Add two new function ConstrainLow() and ConstrainHigh() which wrap constraining two min/max spinboxes to each others' values. -Add a bool to FractoriumEmberControllerBase::CopyEmberFile() to specify whether to copy the main file or the sequence file. This is somewhat of a hack and was done in a rush. -Add a bool to FractoriumEmberControllerBase::SetEmberFile() to specify whether to move the file rather than copy. This is used in FinalRenderEmberController and improves efficiency. -Add wrapper functions for variations filter dialog settings.
This commit is contained in:
parent
51c1cc7a83
commit
c91171d392
@ -1323,6 +1323,16 @@ public:
|
||||
m_Comment = comment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set stagger value.
|
||||
/// Greater than 0 means interpolate xforms one at a time, else interpolate all at once.
|
||||
/// </summary>
|
||||
/// <param name="stagger">The stagger value to set.</param>
|
||||
void Stagger(T stagger)
|
||||
{
|
||||
m_Stagger = stagger;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_Smooth = true;
|
||||
intmax_t m_SheepGen = -1;
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include "EmberAnimate.h"
|
||||
#include "JpegUtils.h"
|
||||
|
||||
using namespace EmberCommon;
|
||||
|
||||
/// <summary>
|
||||
/// The core of the EmberAnimate.exe program.
|
||||
/// Template argument expected to be float or double.
|
||||
@ -368,7 +370,7 @@ bool EmberAnimate(EmberOptions& opt)
|
||||
break;
|
||||
}
|
||||
|
||||
fnstream << inputPath << opt.Prefix() << setfill('0') << setw(padding) << ftime << opt.Suffix() << "." << opt.Format();
|
||||
fnstream << inputPath << opt.Prefix() << setfill('0') << setprecision(0) << fixed << setw(padding) << ftime << opt.Suffix() << "." << opt.Format();
|
||||
filename = fnstream.str();
|
||||
fnstream.str("");
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
/// Ember and its derivatives.
|
||||
/// </summary>
|
||||
|
||||
namespace EmberCommon
|
||||
{
|
||||
/// <summary>
|
||||
/// Derivation of the RenderCallback class to do custom printing action
|
||||
/// whenever the progress function is internally called inside of Ember
|
||||
@ -147,6 +149,20 @@ static bool InitPaletteList(const string& filename)
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a filename with digits using the passed in amount of 0 padding.
|
||||
/// </summary>
|
||||
/// <param name="result">The ember whose name will be set</param>
|
||||
/// <param name="os">The ostringstream which will be used to format</param>
|
||||
/// <param name="padding">The amount of padding to use</param>
|
||||
template <typename T>
|
||||
void FormatName(Ember<T>& result, ostringstream& os, streamsize padding)
|
||||
{
|
||||
os << std::setw(padding) << result.m_Time;
|
||||
result.m_Name = os.str();
|
||||
os.str("");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA buffer to an RGB buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
@ -162,7 +178,7 @@ static void RgbaToRgb(vector<byte>& rgba, vector<byte>& rgb, size_t width, size_
|
||||
|
||||
for (size_t i = 0, j = 0; i < (width * height * 4); i += 4, j += 3)
|
||||
{
|
||||
rgb[j] = rgba[i];
|
||||
rgb[j] = rgba[i];
|
||||
rgb[j + 1] = rgba[i + 1];
|
||||
rgb[j + 2] = rgba[i + 2];
|
||||
}
|
||||
@ -371,7 +387,7 @@ static vector<unique_ptr<Renderer<T, float>>> CreateRenderers(eRendererType rend
|
||||
else
|
||||
{
|
||||
s = "CPU";
|
||||
v.push_back(std::move(unique_ptr<Renderer<T, float>>(::CreateRenderer<T>(eRendererType::CPU_RENDERER, devices, shared, texId, errorReport))));
|
||||
v.push_back(std::move(unique_ptr<Renderer<T, float>>(EmberCommon::CreateRenderer<T>(eRendererType::CPU_RENDERER, devices, shared, texId, errorReport))));
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
@ -388,7 +404,7 @@ static vector<unique_ptr<Renderer<T, float>>> CreateRenderers(eRendererType rend
|
||||
try
|
||||
{
|
||||
s = "CPU";
|
||||
v.push_back(std::move(unique_ptr<Renderer<T, float>>(::CreateRenderer<T>(eRendererType::CPU_RENDERER, devices, shared, texId, errorReport))));
|
||||
v.push_back(std::move(unique_ptr<Renderer<T, float>>(EmberCommon::CreateRenderer<T>(eRendererType::CPU_RENDERER, devices, shared, texId, errorReport))));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@ -628,6 +644,7 @@ static vector<const Variation<T>*> FindVarsWithout(const vector<const Variation<
|
||||
|
||||
return vec;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple macro to print a string if the --verbose options has been specified.
|
||||
|
@ -87,6 +87,8 @@ enum class eOptionIDs : et
|
||||
OPT_REPEAT,
|
||||
OPT_TRIES,
|
||||
OPT_MAX_XFORMS,
|
||||
OPT_START_COUNT,
|
||||
OPT_PADDING,
|
||||
OPT_PRIORITY,
|
||||
|
||||
OPT_SS,//Float value args.
|
||||
@ -307,52 +309,52 @@ public:
|
||||
m_DoubleArgs.reserve(size);
|
||||
m_StringArgs.reserve(size);
|
||||
//Informational bools.
|
||||
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(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"));
|
||||
INITBOOLOPTION(SumVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SUM_VARS, _T("--sumvars"), false, SO_NONE, "\t--sumvars Display the names of all regular variations which have the standard behavior of summing their output, and exit.\n"));
|
||||
INITBOOLOPTION(AssignVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ASSIGN_VARS, _T("--assignvars"), false, SO_NONE, "\t--assignvars Display the names of all regular variations which have the non-standard behavior of assigning their output, and exit.\n"));
|
||||
INITBOOLOPTION(PpSumVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PPSUM_VARS, _T("--ppsumvars"), false, SO_NONE, "\t--ppsumvars Display the names of all pre/post variations which have the non-standard behavior of summing their output, and exit.\n"));
|
||||
INITBOOLOPTION(PpAssignVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PPASSIGN_VARS, _T("--ppassignvars"), false, SO_NONE, "\t--ppassignvars Display the names of all pre/post variations which have the standard behavior of assigning their output, and exit.\n"));
|
||||
INITBOOLOPTION(DcVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_DC_VARS, _T("--dcvars"), false, SO_NONE, "\t--dcvars Display the names of all variations which alter the color index and exit.\n"));
|
||||
INITBOOLOPTION(StateVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_STATE_VARS, _T("--statevars"), false, SO_NONE, "\t--statevars Display the names of all variations which alter their state on each iteration and exit.\n"));
|
||||
INITBOOLOPTION(ParVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PAR_VARS, _T("--parvars"), false, SO_NONE, "\t--parvars Display the names of all variations which have parameters and exit.\n"));
|
||||
INITBOOLOPTION(NonParVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_NON_PAR_VARS, _T("--nonparvars"), false, SO_NONE, "\t--nonparvars Display the names of all variations which do not have parameters (weight only) and exit.\n"));
|
||||
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(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"));
|
||||
INITBOOLOPTION(SumVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SUM_VARS, _T("--sumvars"), false, SO_NONE, "\t--sumvars Display the names of all regular variations which have the standard behavior of summing their output, and exit.\n"));
|
||||
INITBOOLOPTION(AssignVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ASSIGN_VARS, _T("--assignvars"), false, SO_NONE, "\t--assignvars Display the names of all regular variations which have the non-standard behavior of assigning their output, and exit.\n"));
|
||||
INITBOOLOPTION(PpSumVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PPSUM_VARS, _T("--ppsumvars"), false, SO_NONE, "\t--ppsumvars Display the names of all pre/post variations which have the non-standard behavior of summing their output, and exit.\n"));
|
||||
INITBOOLOPTION(PpAssignVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PPASSIGN_VARS, _T("--ppassignvars"), false, SO_NONE, "\t--ppassignvars Display the names of all pre/post variations which have the standard behavior of assigning their output, and exit.\n"));
|
||||
INITBOOLOPTION(DcVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_DC_VARS, _T("--dcvars"), false, SO_NONE, "\t--dcvars Display the names of all variations which alter the color index and exit.\n"));
|
||||
INITBOOLOPTION(StateVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_STATE_VARS, _T("--statevars"), false, SO_NONE, "\t--statevars Display the names of all variations which alter their state on each iteration and exit.\n"));
|
||||
INITBOOLOPTION(ParVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PAR_VARS, _T("--parvars"), false, SO_NONE, "\t--parvars Display the names of all variations which have parameters and exit.\n"));
|
||||
INITBOOLOPTION(NonParVars, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_NON_PAR_VARS, _T("--nonparvars"), false, SO_NONE, "\t--nonparvars Display the names of all variations which do not have parameters (weight only) 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"));
|
||||
INITBOOLOPTION(Debug, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_DEBUG, _T("--debug"), false, SO_NONE, "\t--debug Debug output [default: false].\n"));
|
||||
INITBOOLOPTION(DumpArgs, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_DUMP_ARGS, _T("--dumpargs"), false, SO_NONE, "\t--dumpargs Print all arguments entered from either the command line or environment variables [default: false].\n"));
|
||||
INITBOOLOPTION(DoProgress, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PROGRESS, _T("--progress"), false, SO_NONE, "\t--progress Display progress. This will slow down processing by about 10% [default: false].\n"));
|
||||
INITBOOLOPTION(Verbose, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_VERBOSE, _T("--verbose"), false, SO_NONE, "\t--verbose Verbose output [default: false].\n"));
|
||||
INITBOOLOPTION(Debug, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_DEBUG, _T("--debug"), false, SO_NONE, "\t--debug Debug output [default: false].\n"));
|
||||
INITBOOLOPTION(DumpArgs, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_DUMP_ARGS, _T("--dumpargs"), false, SO_NONE, "\t--dumpargs Print all arguments entered from either the command line or environment variables [default: false].\n"));
|
||||
INITBOOLOPTION(DoProgress, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PROGRESS, _T("--progress"), false, SO_NONE, "\t--progress Display progress. This will slow down processing by about 10% [default: false].\n"));
|
||||
//Execution bools.
|
||||
INITBOOLOPTION(EmberCL, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_OPENCL, _T("--opencl"), false, SO_NONE, "\t--opencl Use OpenCL renderer (EmberCL) for rendering [default: false].\n"));
|
||||
INITBOOLOPTION(Sp, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_SP, _T("--sp"), false, SO_NONE, "\t--sp Use single precision for rendering instead of double precision [default: false].\n"));
|
||||
INITBOOLOPTION(EarlyClip, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_EARLYCLIP, _T("--earlyclip"), false, SO_NONE, "\t--earlyclip Perform clipping of RGB values before spatial filtering for better antialiasing and resizing [default: false].\n"));
|
||||
INITBOOLOPTION(YAxisUp, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_POS_Y_UP, _T("--yaxisup"), false, SO_NONE, "\t--yaxisup Orient the image with the positive y axis pointing up [default: false].\n"));
|
||||
INITBOOLOPTION(Transparency, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_TRANSPARENCY, _T("--transparency"), false, SO_NONE, "\t--transparency Include alpha channel in final output [default: false except for PNG].\n"));
|
||||
INITBOOLOPTION(NameEnable, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_NAME_ENABLE, _T("--name_enable"), false, SO_NONE, "\t--name_enable Use the name attribute contained in the Xml as the output filename [default: false].\n"));
|
||||
INITBOOLOPTION(HexPalette, Eob(eOptionUse::OPT_ANIM_GENOME, eOptionIDs::OPT_HEX_PALETTE, _T("--hex_palette"), true, SO_OPT, "\t--hex_palette Force palette RGB values to be hex when saving to Xml [default: true].\n"));
|
||||
INITBOOLOPTION(InsertPalette, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_INSERT_PALETTE, _T("--insert_palette"), false, SO_NONE, "\t--insert_palette Insert the palette into the image for debugging purposes. Disabled when running with OpenCL [default: false].\n"));
|
||||
INITBOOLOPTION(JpegComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG_COMMENTS, _T("--enable_jpg_comments"), false, SO_NONE, "\t--enable_jpg_comments Enables embedding the flame parameters and user identifying information in the jpeg header [default: false].\n"));
|
||||
INITBOOLOPTION(PngComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PNG_COMMENTS, _T("--enable_png_comments"), false, SO_NONE, "\t--enable_png_comments Enables embedding the flame parameters and user identifying information in the png header [default: false].\n"));
|
||||
INITBOOLOPTION(WriteGenome, Eob(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_WRITE_GENOME, _T("--write_genome"), false, SO_NONE, "\t--write_genome Write out flame associated with center of motion blur window [default: false].\n"));
|
||||
INITBOOLOPTION(ThreadedWrite, Eob(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_THREADED_WRITE, _T("--threaded_write"), true, SO_OPT, "\t--threaded_write Use a separate thread to write images to disk. This gives better performance, but doubles the memory required for the final output buffer. [default: true].\n"));
|
||||
INITBOOLOPTION(Enclosed, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ENCLOSED, _T("--enclosed"), true, SO_OPT, "\t--enclosed Use enclosing Xml tags [default: true].\n"));
|
||||
INITBOOLOPTION(NoEdits, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_NO_EDITS, _T("--noedits"), false, SO_NONE, "\t--noedits Exclude edit tags when writing Xml [default: false].\n"));
|
||||
INITBOOLOPTION(UnsmoothEdge, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_UNSMOOTH_EDGE, _T("--unsmoother"), false, SO_NONE, "\t--unsmoother Do not use smooth blending for sheep edges [default: false].\n"));
|
||||
INITBOOLOPTION(LockAccum, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_LOCK_ACCUM, _T("--lock_accum"), false, SO_NONE, "\t--lock_accum Lock threads when accumulating to the histogram using the CPU. This will drop performance to that of single threading [default: false].\n"));
|
||||
INITBOOLOPTION(DumpKernel, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_DUMP_KERNEL, _T("--dump_kernel"), false, SO_NONE, "\t--dump_kernel Print the iteration kernel string when using OpenCL (ignored for CPU) [default: false].\n"));
|
||||
INITBOOLOPTION(EmberCL, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_OPENCL, _T("--opencl"), false, SO_NONE, "\t--opencl Use OpenCL renderer (EmberCL) for rendering [default: false].\n"));
|
||||
INITBOOLOPTION(Sp, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_SP, _T("--sp"), false, SO_NONE, "\t--sp Use single precision for rendering instead of double precision [default: false].\n"));
|
||||
INITBOOLOPTION(EarlyClip, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_EARLYCLIP, _T("--earlyclip"), false, SO_NONE, "\t--earlyclip Perform clipping of RGB values before spatial filtering for better antialiasing and resizing [default: false].\n"));
|
||||
INITBOOLOPTION(YAxisUp, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_POS_Y_UP, _T("--yaxisup"), false, SO_NONE, "\t--yaxisup Orient the image with the positive y axis pointing up [default: false].\n"));
|
||||
INITBOOLOPTION(Transparency, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_TRANSPARENCY, _T("--transparency"), false, SO_NONE, "\t--transparency Include alpha channel in final output [default: false except for PNG].\n"));
|
||||
INITBOOLOPTION(NameEnable, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_NAME_ENABLE, _T("--name_enable"), false, SO_NONE, "\t--name_enable Use the name attribute contained in the Xml as the output filename [default: false].\n"));
|
||||
INITBOOLOPTION(HexPalette, Eob(eOptionUse::OPT_ANIM_GENOME, eOptionIDs::OPT_HEX_PALETTE, _T("--hex_palette"), true, SO_OPT, "\t--hex_palette Force palette RGB values to be hex when saving to Xml [default: true].\n"));
|
||||
INITBOOLOPTION(InsertPalette, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_INSERT_PALETTE, _T("--insert_palette"), false, SO_NONE, "\t--insert_palette Insert the palette into the image for debugging purposes. Disabled when running with OpenCL [default: false].\n"));
|
||||
INITBOOLOPTION(JpegComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG_COMMENTS, _T("--enable_jpg_comments"), false, SO_NONE, "\t--enable_jpg_comments Enables embedding the flame parameters and user identifying information in the jpeg header [default: false].\n"));
|
||||
INITBOOLOPTION(PngComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PNG_COMMENTS, _T("--enable_png_comments"), false, SO_NONE, "\t--enable_png_comments Enables embedding the flame parameters and user identifying information in the png header [default: false].\n"));
|
||||
INITBOOLOPTION(WriteGenome, Eob(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_WRITE_GENOME, _T("--write_genome"), false, SO_NONE, "\t--write_genome Write out flame associated with center of motion blur window [default: false].\n"));
|
||||
INITBOOLOPTION(ThreadedWrite, Eob(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_THREADED_WRITE, _T("--threaded_write"), true, SO_OPT, "\t--threaded_write Use a separate thread to write images to disk. This gives better performance, but doubles the memory required for the final output buffer. [default: true].\n"));
|
||||
INITBOOLOPTION(Enclosed, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ENCLOSED, _T("--enclosed"), true, SO_OPT, "\t--enclosed Use enclosing Xml tags [default: true].\n"));
|
||||
INITBOOLOPTION(NoEdits, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_NO_EDITS, _T("--noedits"), false, SO_NONE, "\t--noedits Exclude edit tags when writing Xml [default: false].\n"));
|
||||
INITBOOLOPTION(UnsmoothEdge, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_UNSMOOTH_EDGE, _T("--unsmoother"), false, SO_NONE, "\t--unsmoother Do not use smooth blending for sheep edges [default: false].\n"));
|
||||
INITBOOLOPTION(LockAccum, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_LOCK_ACCUM, _T("--lock_accum"), false, SO_NONE, "\t--lock_accum Lock threads when accumulating to the histogram using the CPU. This will drop performance to that of single threading [default: false].\n"));
|
||||
INITBOOLOPTION(DumpKernel, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_DUMP_KERNEL, _T("--dump_kernel"), false, SO_NONE, "\t--dump_kernel Print the iteration kernel string when using OpenCL (ignored for CPU) [default: false].\n"));
|
||||
//Int.
|
||||
INITINTOPTION(Symmetry, Eoi(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SYMMETRY, _T("--symmetry"), 0, SO_REQ_SEP, "\t--symmetry=<val> Set symmetry of result [default: 0].\n"));
|
||||
INITINTOPTION(SheepGen, Eoi(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SHEEP_GEN, _T("--sheep_gen"), -1, SO_REQ_SEP, "\t--sheep_gen=<val> Sheep generation of this flame [default: -1].\n"));
|
||||
INITINTOPTION(SheepId, Eoi(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SHEEP_ID, _T("--sheep_id"), -1, SO_REQ_SEP, "\t--sheep_id=<val> Sheep ID of this flame [default: -1].\n"));
|
||||
INITINTOPTION(Symmetry, Eoi(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SYMMETRY, _T("--symmetry"), 0, SO_REQ_SEP, "\t--symmetry=<val> Set symmetry of result [default: 0].\n"));
|
||||
INITINTOPTION(SheepGen, Eoi(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SHEEP_GEN, _T("--sheep_gen"), -1, SO_REQ_SEP, "\t--sheep_gen=<val> Sheep generation of this flame [default: -1].\n"));
|
||||
INITINTOPTION(SheepId, Eoi(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SHEEP_ID, _T("--sheep_id"), -1, SO_REQ_SEP, "\t--sheep_id=<val> Sheep ID of this flame [default: -1].\n"));
|
||||
#ifdef _WIN32
|
||||
INITINTOPTION(Priority, Eoi(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PRIORITY, _T("--priority"), int(eThreadPriority::NORMAL), SO_REQ_SEP, "\t--priority=<val> The priority of the CPU rendering threads from -2 - 2. This does not apply to OpenCL rendering.\n"));
|
||||
INITINTOPTION(Priority, Eoi(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PRIORITY, _T("--priority"), int(eThreadPriority::NORMAL), SO_REQ_SEP, "\t--priority=<val> The priority of the CPU rendering threads from -2 - 2. This does not apply to OpenCL rendering.\n"));
|
||||
#else
|
||||
INITINTOPTION(Priority, Eoi(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PRIORITY, _T("--priority"), int(eThreadPriority::NORMAL), SO_REQ_SEP, "\t--priority=<val> The priority of the CPU rendering threads, 1, 25, 50, 75, 99. This does not apply to OpenCL rendering.\n"));
|
||||
INITINTOPTION(Priority, Eoi(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PRIORITY, _T("--priority"), int(eThreadPriority::NORMAL), SO_REQ_SEP, "\t--priority=<val> The priority of the CPU rendering threads, 1, 25, 50, 75, 99. This does not apply to OpenCL rendering.\n"));
|
||||
#endif
|
||||
//Uint.
|
||||
INITUINTOPTION(ThreadCount, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_NTHREADS, _T("--nthreads"), 0, SO_REQ_SEP, "\t--nthreads=<val> The number of threads to use [default: use all available cores].\n"));
|
||||
@ -370,52 +372,54 @@ public:
|
||||
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(StartCount, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_START_COUNT, _T("--startcount"), 0, SO_REQ_SEP, "\t--startcount=<val> The number to add to each flame name when generating a sequence. Useful for programs like ffmpeg which require numerically increasing filenames [default: 0].\n"));
|
||||
INITUINTOPTION(Padding, Eou(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_PADDING, _T("--padding"), 0, SO_REQ_SEP, "\t--padding=<val> Override the amount of zero padding added to each flame name when generating a sequence. Useful for programs like ffmpeg which require fixed width filenames [default: 0 (auto calculate padding)].\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"));
|
||||
INITDOUBLEOPTION(Quality, Eod(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_QUALITY, _T("--quality"), 0, SO_REQ_SEP, "\t--quality=<val> Override the quality of the flame if not 0 [default: 0].\n"));
|
||||
INITDOUBLEOPTION(DeMin, Eod(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_DE_MIN, _T("--demin"), -1, SO_REQ_SEP, "\t--demin=<val> Override the minimum size of the density estimator filter radius if not -1 [default: -1].\n"));
|
||||
INITDOUBLEOPTION(DeMax, Eod(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_DE_MAX, _T("--demax"), -1, SO_REQ_SEP, "\t--demax=<val> Override the maximum size of the density estimator filter radius if not -1 [default: -1].\n"));
|
||||
INITDOUBLEOPTION(AspectRatio, Eod(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PIXEL_ASPECT, _T("--pixel_aspect"), 1, SO_REQ_SEP, "\t--pixel_aspect=<val> Aspect ratio of pixels (width over height), eg. 0.90909 for NTSC [default: 1.0].\n"));
|
||||
INITDOUBLEOPTION(Stagger, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_STAGGER, _T("--stagger"), 0, SO_REQ_SEP, "\t--stagger=<val> Affects simultaneity of xform interpolation during flame interpolation.\n"
|
||||
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"));
|
||||
INITDOUBLEOPTION(Quality, Eod(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_QUALITY, _T("--quality"), 0, SO_REQ_SEP, "\t--quality=<val> Override the quality of the flame if not 0 [default: 0].\n"));
|
||||
INITDOUBLEOPTION(DeMin, Eod(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_DE_MIN, _T("--demin"), -1, SO_REQ_SEP, "\t--demin=<val> Override the minimum size of the density estimator filter radius if not -1 [default: -1].\n"));
|
||||
INITDOUBLEOPTION(DeMax, Eod(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_DE_MAX, _T("--demax"), -1, SO_REQ_SEP, "\t--demax=<val> Override the maximum size of the density estimator filter radius if not -1 [default: -1].\n"));
|
||||
INITDOUBLEOPTION(AspectRatio, Eod(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PIXEL_ASPECT, _T("--pixel_aspect"), 1, SO_REQ_SEP, "\t--pixel_aspect=<val> Aspect ratio of pixels (width over height), eg. 0.90909 for NTSC [default: 1.0].\n"));
|
||||
INITDOUBLEOPTION(Stagger, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_STAGGER, _T("--stagger"), 0, SO_REQ_SEP, "\t--stagger=<val> Affects simultaneity of xform interpolation during flame interpolation.\n"
|
||||
"\t Represents how 'separate' the xforms are interpolated. Set to 1 for each\n"
|
||||
"\t xform to be interpolated individually, fractions control interpolation overlap [default: 0].\n"));
|
||||
INITDOUBLEOPTION(AvgThresh, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_AVG_THRESH, _T("--avg"), 20.0, SO_REQ_SEP, "\t--avg=<val> Minimum average pixel channel sum (r + g + b) threshold from 0 - 765. Ignored if sequence, inter or rotate were specified [default: 20].\n"));
|
||||
INITDOUBLEOPTION(BlackThresh, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_BLACK_THRESH, _T("--black"), 0.01, SO_REQ_SEP, "\t--black=<val> Minimum number of allowed black pixels as a percentage from 0 - 1. Ignored if sequence, inter or rotate were specified [default: 0.01].\n"));
|
||||
INITDOUBLEOPTION(WhiteLimit, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_WHITE_LIMIT, _T("--white"), 0.05, SO_REQ_SEP, "\t--white=<val> Maximum number of allowed white pixels as a percentage from 0 - 1. Ignored if sequence, inter or rotate were specified [default: 0.05].\n"));
|
||||
INITDOUBLEOPTION(Speed, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SPEED, _T("--speed"), 0.1, SO_REQ_SEP, "\t--speed=<val> Speed as a percentage from 0 - 1 that the affine transform of an existing flame mutates with the new flame. Ignored if sequence, inter or rotate were specified [default: 0.1].\n"));
|
||||
INITDOUBLEOPTION(OffsetX, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_OFFSETX, _T("--offsetx"), 0.0, SO_REQ_SEP, "\t--offsetx=<val> Amount to jitter each flame horizontally when applying genome tools [default: 0].\n"));
|
||||
INITDOUBLEOPTION(OffsetY, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_OFFSETY, _T("--offsety"), 0.0, SO_REQ_SEP, "\t--offsety=<val> Amount to jitter each flame vertically when applying genome tools [default: 0].\n"));
|
||||
INITDOUBLEOPTION(UseMem, Eod(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_USEMEM, _T("--use_mem"), 0.0, SO_REQ_SEP, "\t--use_mem=<val> Number of bytes of memory to use [default: max system memory].\n"));
|
||||
INITDOUBLEOPTION(Loops, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_LOOPS, _T("--loops"), 1.0, SO_REQ_SEP, "\t--loops=<val> Number of times to rotate each control point in sequence [default: 1].\n"));
|
||||
INITDOUBLEOPTION(AvgThresh, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_AVG_THRESH, _T("--avg"), 20.0, SO_REQ_SEP, "\t--avg=<val> Minimum average pixel channel sum (r + g + b) threshold from 0 - 765. Ignored if sequence, inter or rotate were specified [default: 20].\n"));
|
||||
INITDOUBLEOPTION(BlackThresh, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_BLACK_THRESH, _T("--black"), 0.01, SO_REQ_SEP, "\t--black=<val> Minimum number of allowed black pixels as a percentage from 0 - 1. Ignored if sequence, inter or rotate were specified [default: 0.01].\n"));
|
||||
INITDOUBLEOPTION(WhiteLimit, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_WHITE_LIMIT, _T("--white"), 0.05, SO_REQ_SEP, "\t--white=<val> Maximum number of allowed white pixels as a percentage from 0 - 1. Ignored if sequence, inter or rotate were specified [default: 0.05].\n"));
|
||||
INITDOUBLEOPTION(Speed, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SPEED, _T("--speed"), 0.1, SO_REQ_SEP, "\t--speed=<val> Speed as a percentage from 0 - 1 that the affine transform of an existing flame mutates with the new flame. Ignored if sequence, inter or rotate were specified [default: 0.1].\n"));
|
||||
INITDOUBLEOPTION(OffsetX, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_OFFSETX, _T("--offsetx"), 0.0, SO_REQ_SEP, "\t--offsetx=<val> Amount to jitter each flame horizontally when applying genome tools [default: 0].\n"));
|
||||
INITDOUBLEOPTION(OffsetY, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_OFFSETY, _T("--offsety"), 0.0, SO_REQ_SEP, "\t--offsety=<val> Amount to jitter each flame vertically when applying genome tools [default: 0].\n"));
|
||||
INITDOUBLEOPTION(UseMem, Eod(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_USEMEM, _T("--use_mem"), 0.0, SO_REQ_SEP, "\t--use_mem=<val> Number of bytes of memory to use [default: max system memory].\n"));
|
||||
INITDOUBLEOPTION(Loops, Eod(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_LOOPS, _T("--loops"), 1.0, SO_REQ_SEP, "\t--loops=<val> Number of times to rotate each control point in sequence [default: 1].\n"));
|
||||
//String.
|
||||
INITSTRINGOPTION(Device, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_OPENCL_DEVICE, _T("--device"), "0", SO_REQ_SEP, "\t--device The comma-separated OpenCL device indices to use. Single device: 0 Multi device: 0,1,3,4 [default: 0].\n"));
|
||||
INITSTRINGOPTION(IsaacSeed, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_ISAAC_SEED, _T("--isaac_seed"), "", SO_REQ_SEP, "\t--isaac_seed=<val> Character-based seed for the random number generator [default: random].\n"));
|
||||
INITSTRINGOPTION(Input, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_IN, _T("--in"), "", SO_REQ_SEP, "\t--in=<val> Name of the input file.\n"));
|
||||
INITSTRINGOPTION(Out, Eos(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_OUT, _T("--out"), "", SO_REQ_SEP, "\t--out=<val> Name of a single output file. Not recommended when rendering more than one image.\n"));
|
||||
INITSTRINGOPTION(Prefix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PREFIX, _T("--prefix"), "", SO_REQ_SEP, "\t--prefix=<val> Prefix to prepend to all output files.\n"));
|
||||
INITSTRINGOPTION(Suffix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUFFIX, _T("--suffix"), "", SO_REQ_SEP, "\t--suffix=<val> Suffix to append to all output files.\n"));
|
||||
INITSTRINGOPTION(Format, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, "\t--format=<val> Format of the output file. Valid values are: bmp, jpg, png, ppm [default: png].\n"));
|
||||
INITSTRINGOPTION(PalettePath, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PALETTE_FILE, _T("--flam3_palettes"), "flam3-palettes.xml", SO_REQ_SEP, "\t--flam3_palettes=<val> Path and name of the palette file [default: flam3-palettes.xml].\n"));
|
||||
INITSTRINGOPTION(Id, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_ID, _T("--id"), "", SO_REQ_SEP, "\t--id=<val> ID to use in <edit> tags / image comments.\n"));
|
||||
INITSTRINGOPTION(Url, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_URL, _T("--url"), "", SO_REQ_SEP, "\t--url=<val> URL to use in <edit> tags / image comments.\n"));
|
||||
INITSTRINGOPTION(Nick, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_NICK, _T("--nick"), "", SO_REQ_SEP, "\t--nick=<val> Nickname to use in <edit> tags / image comments.\n"));
|
||||
INITSTRINGOPTION(Comment, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_COMMENT, _T("--comment"), "", SO_REQ_SEP, "\t--comment=<val> Comment to use in <edit> tags.\n"));
|
||||
INITSTRINGOPTION(TemplateFile, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_TEMPLATE, _T("--template"), "", SO_REQ_SEP, "\t--template=<val> Apply defaults based on this flame.\n"));
|
||||
INITSTRINGOPTION(Clone, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CLONE, _T("--clone"), "", SO_REQ_SEP, "\t--clone=<val> Clone random flame in input.\n"));
|
||||
INITSTRINGOPTION(CloneAll, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CLONE_ALL, _T("--clone_all"), "", SO_REQ_SEP, "\t--clone_all=<val> Clones all flames in the input file. Useful for applying template to all flames.\n"));
|
||||
INITSTRINGOPTION(CloneAction, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CLONE_ACTION, _T("--clone_action"), "", SO_REQ_SEP, "\t--clone_action=<val> A description of the clone action taking place.\n"));
|
||||
INITSTRINGOPTION(Animate, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ANIMATE, _T("--animate"), "", SO_REQ_SEP, "\t--animate=<val> Interpolates between all flames in the input file, using times specified in file.\n"));
|
||||
INITSTRINGOPTION(Mutate, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_MUTATE, _T("--mutate"), "", SO_REQ_SEP, "\t--mutate=<val> Randomly mutate a random flame from the input file.\n"));
|
||||
INITSTRINGOPTION(Cross0, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CROSS0, _T("--cross0"), "", SO_REQ_SEP, "\t--cross0=<val> Randomly select one flame from the input file to genetically cross...\n"));
|
||||
INITSTRINGOPTION(Cross1, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CROSS1, _T("--cross1"), "", SO_REQ_SEP, "\t--cross1=<val> ...with one flame from this file.\n"));
|
||||
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(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"));
|
||||
INITSTRINGOPTION(Extras, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_EXTRAS, _T("--extras"), "", SO_REQ_SEP, "\t--extras=<val> Extra attributes to place in the flame section of the Xml.\n"));
|
||||
INITSTRINGOPTION(Device, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_OPENCL_DEVICE, _T("--device"), "0", SO_REQ_SEP, "\t--device The comma-separated OpenCL device indices to use. Single device: 0 Multi device: 0,1,3,4 [default: 0].\n"));
|
||||
INITSTRINGOPTION(IsaacSeed, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_ISAAC_SEED, _T("--isaac_seed"), "", SO_REQ_SEP, "\t--isaac_seed=<val> Character-based seed for the random number generator [default: random].\n"));
|
||||
INITSTRINGOPTION(Input, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_IN, _T("--in"), "", SO_REQ_SEP, "\t--in=<val> Name of the input file.\n"));
|
||||
INITSTRINGOPTION(Out, Eos(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_OUT, _T("--out"), "", SO_REQ_SEP, "\t--out=<val> Name of a single output file. Not recommended when rendering more than one image.\n"));
|
||||
INITSTRINGOPTION(Prefix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PREFIX, _T("--prefix"), "", SO_REQ_SEP, "\t--prefix=<val> Prefix to prepend to all output files.\n"));
|
||||
INITSTRINGOPTION(Suffix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUFFIX, _T("--suffix"), "", SO_REQ_SEP, "\t--suffix=<val> Suffix to append to all output files.\n"));
|
||||
INITSTRINGOPTION(Format, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, "\t--format=<val> Format of the output file. Valid values are: bmp, jpg, png, ppm [default: png].\n"));
|
||||
INITSTRINGOPTION(PalettePath, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PALETTE_FILE, _T("--flam3_palettes"), "flam3-palettes.xml", SO_REQ_SEP, "\t--flam3_palettes=<val> Path and name of the palette file [default: flam3-palettes.xml].\n"));
|
||||
INITSTRINGOPTION(Id, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_ID, _T("--id"), "", SO_REQ_SEP, "\t--id=<val> ID to use in <edit> tags / image comments.\n"));
|
||||
INITSTRINGOPTION(Url, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_URL, _T("--url"), "", SO_REQ_SEP, "\t--url=<val> URL to use in <edit> tags / image comments.\n"));
|
||||
INITSTRINGOPTION(Nick, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_NICK, _T("--nick"), "", SO_REQ_SEP, "\t--nick=<val> Nickname to use in <edit> tags / image comments.\n"));
|
||||
INITSTRINGOPTION(Comment, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_COMMENT, _T("--comment"), "", SO_REQ_SEP, "\t--comment=<val> Comment to use in <edit> tags.\n"));
|
||||
INITSTRINGOPTION(TemplateFile, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_TEMPLATE, _T("--template"), "", SO_REQ_SEP, "\t--template=<val> Apply defaults based on this flame.\n"));
|
||||
INITSTRINGOPTION(Clone, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CLONE, _T("--clone"), "", SO_REQ_SEP, "\t--clone=<val> Clone random flame in input.\n"));
|
||||
INITSTRINGOPTION(CloneAll, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CLONE_ALL, _T("--clone_all"), "", SO_REQ_SEP, "\t--clone_all=<val> Clones all flames in the input file. Useful for applying template to all flames.\n"));
|
||||
INITSTRINGOPTION(CloneAction, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CLONE_ACTION, _T("--clone_action"), "", SO_REQ_SEP, "\t--clone_action=<val> A description of the clone action taking place.\n"));
|
||||
INITSTRINGOPTION(Animate, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ANIMATE, _T("--animate"), "", SO_REQ_SEP, "\t--animate=<val> Interpolates between all flames in the input file, using times specified in file.\n"));
|
||||
INITSTRINGOPTION(Mutate, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_MUTATE, _T("--mutate"), "", SO_REQ_SEP, "\t--mutate=<val> Randomly mutate a random flame from the input file.\n"));
|
||||
INITSTRINGOPTION(Cross0, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CROSS0, _T("--cross0"), "", SO_REQ_SEP, "\t--cross0=<val> Randomly select one flame from the input file to genetically cross...\n"));
|
||||
INITSTRINGOPTION(Cross1, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CROSS1, _T("--cross1"), "", SO_REQ_SEP, "\t--cross1=<val> ...with one flame from this file.\n"));
|
||||
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(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"));
|
||||
INITSTRINGOPTION(Extras, Eos(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_EXTRAS, _T("--extras"), "", SO_REQ_SEP, "\t--extras=<val> Extra attributes to place in the flame section of the Xml.\n"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -509,6 +513,8 @@ public:
|
||||
PARSEUINTOPTION(eOptionIDs::OPT_REPEAT, Repeat);
|
||||
PARSEUINTOPTION(eOptionIDs::OPT_TRIES, Tries);
|
||||
PARSEUINTOPTION(eOptionIDs::OPT_MAX_XFORMS, MaxXforms);
|
||||
PARSEUINTOPTION(eOptionIDs::OPT_START_COUNT, StartCount);
|
||||
PARSEUINTOPTION(eOptionIDs::OPT_PADDING, Padding);
|
||||
PARSEDOUBLEOPTION(eOptionIDs::OPT_SS, SizeScale);//Float args.
|
||||
PARSEDOUBLEOPTION(eOptionIDs::OPT_QS, QualityScale);
|
||||
PARSEDOUBLEOPTION(eOptionIDs::OPT_QUALITY, Quality);
|
||||
@ -792,6 +798,8 @@ public:
|
||||
Eou Repeat;
|
||||
Eou Tries;
|
||||
Eou MaxXforms;
|
||||
Eou StartCount;
|
||||
Eou Padding;
|
||||
|
||||
Eod SizeScale;//Value double.
|
||||
Eod QualityScale;
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "EmberGenome.h"
|
||||
#include "JpegUtils.h"
|
||||
|
||||
using namespace EmberCommon;
|
||||
|
||||
/// <summary>
|
||||
/// Set various default test values on the passed in ember.
|
||||
/// </summary>
|
||||
@ -34,14 +36,6 @@ void SetDefaultTestValues(Ember<T>& ember)
|
||||
ember.m_CurveDE = T(0.6);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void FormatName(Ember<T>& result, ostringstream& os, streamsize padding)
|
||||
{
|
||||
os << std::setw(padding) << result.m_Time;
|
||||
result.m_Name = os.str();
|
||||
os.str("");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The core of the EmberGenome.exe program.
|
||||
/// Template argument expected to be float or double.
|
||||
@ -470,18 +464,20 @@ bool EmberGenome(EmberOptions& opt)
|
||||
|
||||
frameCount = 0;
|
||||
os.str("");
|
||||
os << setfill('0');
|
||||
auto padding = streamsize(std::log10(((opt.Frames() * opt.Loops()) + opt.Frames()) * embers.size())) + 1;
|
||||
os << setfill('0') << setprecision(0) << fixed;
|
||||
auto padding = opt.Padding() ? streamsize(opt.Padding()) : (streamsize(std::log10(opt.StartCount() + (((opt.Frames() * opt.Loops()) + opt.Frames()) * embers.size()))) + 1);
|
||||
t.Tic();
|
||||
|
||||
for (i = 0; i < embers.size(); i++)
|
||||
{
|
||||
if (opt.Loops() > 0)
|
||||
{
|
||||
for (frame = 0; frame < std::round(opt.Frames() * opt.Loops()); frame++)
|
||||
size_t roundFrames = size_t(std::round(opt.Frames() * opt.Loops()));
|
||||
|
||||
for (frame = 0; frame < roundFrames; frame++)
|
||||
{
|
||||
blend = T(frame) / T(opt.Frames());
|
||||
tools.Spin(embers[i], pTemplate, result, frameCount++, blend);//Result is cleared and reassigned each time inside of Spin().
|
||||
tools.Spin(embers[i], pTemplate, result, opt.StartCount() + frameCount++, blend);//Result is cleared and reassigned each time inside of Spin().
|
||||
FormatName(result, os, padding);
|
||||
cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
|
||||
}
|
||||
@ -489,9 +485,9 @@ bool EmberGenome(EmberOptions& opt)
|
||||
//The loop above will have rotated just shy of a complete rotation.
|
||||
//Rotate the next step and save in result, but do not print.
|
||||
//result will be the starting point for the interp phase below.
|
||||
frame = size_t(std::round(opt.Frames() * opt.Loops()));
|
||||
frame = roundFrames;
|
||||
blend = T(frame) / T(opt.Frames());
|
||||
tools.Spin(embers[i], pTemplate, result, frameCount, blend);//Do not increment frameCount here.
|
||||
tools.Spin(embers[i], pTemplate, result, opt.StartCount() + frameCount, blend);//Do not increment frameCount here.
|
||||
FormatName(result, os, padding);
|
||||
}
|
||||
|
||||
@ -502,18 +498,17 @@ bool EmberGenome(EmberOptions& opt)
|
||||
|
||||
for (frame = 0; frame < opt.Frames(); frame++)
|
||||
{
|
||||
seqFlag = (frame == 0 || (frame == opt.Frames() - 1));
|
||||
seqFlag = frame == 0 || (frame == opt.Frames() - 1);
|
||||
blend = frame / T(opt.Frames());
|
||||
result.Clear();
|
||||
tools.SpinInter(&embers[i], pTemplate, result, frameCount++, seqFlag, blend);
|
||||
tools.SpinInter(&embers[i], pTemplate, result, opt.StartCount() + frameCount++, seqFlag, blend);
|
||||
FormatName(result, os, padding);
|
||||
cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = embers.back();
|
||||
tools.Spin(embers.back(), pTemplate, result, frameCount, 0);
|
||||
tools.Spin(embers.back(), pTemplate, result, opt.StartCount() + frameCount, 0);
|
||||
FormatName(result, os, padding);
|
||||
cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette());
|
||||
t.Toc("Sequencing");
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "EmberRender.h"
|
||||
#include "JpegUtils.h"
|
||||
|
||||
//template <class OpenCLInfo> weak_ptr<OpenCLInfo> Singleton<OpenCLInfo>::m_Instance = weak_ptr<OpenCLInfo>();
|
||||
using namespace EmberCommon;
|
||||
|
||||
/// <summary>
|
||||
/// The core of the EmberRender.exe program.
|
||||
@ -273,7 +273,7 @@ bool EmberRender(EmberOptions& opt)
|
||||
else
|
||||
{
|
||||
ostringstream fnstream;
|
||||
fnstream << inputPath << opt.Prefix() << setfill('0') << setw(padding) << i << opt.Suffix() << "." << opt.Format();
|
||||
fnstream << inputPath << opt.Prefix() << setfill('0') << setprecision(0) << fixed << setw(padding) << i << opt.Suffix() << "." << opt.Format();
|
||||
filename = fnstream.str();
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
/// </summary>
|
||||
|
||||
using namespace EmberNs;
|
||||
using namespace EmberCommon;
|
||||
|
||||
template <typename T>
|
||||
void SaveFinalImage(Renderer<T, T>& renderer, vector<byte>& pixels, char* suffix)
|
||||
|
@ -159,9 +159,9 @@ public:
|
||||
/// Return the default filename based on the current date/time.
|
||||
/// </summary>
|
||||
/// <returns>The default filename</returns>
|
||||
static QString DefaultFilename()
|
||||
static QString DefaultFilename(QString prefix = "Flame_")
|
||||
{
|
||||
return "Flame_" + QDateTime(QDateTime::currentDateTime()).toString("yyyy-MM-dd-hhmmss");
|
||||
return prefix + QDateTime(QDateTime::currentDateTime()).toString("yyyy-MM-dd-hhmmss");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -28,7 +28,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
connect(ui.FinalRenderDoublePrecisionCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoublePrecisionCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderDoAllCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoAllCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderDoSequenceCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoSequenceCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderCurrentSpin, SIGNAL(valueChanged(int)), this, SLOT(OnCurrentSpinChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderCurrentSpin, SIGNAL(valueChanged(int)), this, SLOT(OnCurrentSpinChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderApplyToAllCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnApplyAllCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderKeepAspectCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnKeepAspectCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderScaleNoneRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection);
|
||||
@ -189,6 +189,16 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
w = SetTabOrder(this, w, ui.FinalRenderCloseButton);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the final render dialog and specify whether it was called from the toolbar or the sequence render button.
|
||||
/// </summary>
|
||||
/// <param name="fromSequence">True if this is called from the sequence render button, else false.</param>
|
||||
void FractoriumFinalRenderDialog::Show(bool fromSequence)
|
||||
{
|
||||
m_FromSequence = fromSequence;
|
||||
show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GUI settings wrapper functions, getters only.
|
||||
/// </summary>
|
||||
@ -636,7 +646,7 @@ void FractoriumFinalRenderDialog::OnCancelRenderClicked(bool checked)
|
||||
/// <param name="e">The event</param>
|
||||
void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
{
|
||||
if (m_Controller.get() && m_Controller->m_Run)
|
||||
if (m_Controller.get() && m_Controller->m_Run)//On Linux, this event will be called when the main window minimized/maximized while rendering, so filter it out.
|
||||
return;
|
||||
|
||||
if (CreateControllerFromGUI(true))//Create controller if it does not exist, or if it does and the renderer is not running.
|
||||
@ -645,16 +655,17 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
#ifdef DO_DOUBLE
|
||||
Ember<double> ed;
|
||||
EmberFile<double> efi;
|
||||
m_Fractorium->m_Controller->CopyEmberFile(efi, [&](Ember<double>& ember)
|
||||
m_Fractorium->m_Controller->CopyEmberFile(efi, m_FromSequence, [&](Ember<double>& ember)
|
||||
{
|
||||
ember.SyncSize();
|
||||
ember.m_Quality = m_Settings->FinalQuality();
|
||||
ember.m_Supersample = m_Settings->FinalSupersample();
|
||||
ember.m_TemporalSamples = m_Settings->FinalTemporalSamples();
|
||||
});//Copy the whole file, will take about 0.2ms per ember in the file.
|
||||
#else
|
||||
Ember<float> ed;
|
||||
EmberFile<float> efi;
|
||||
m_Fractorium->m_Controller->CopyEmberFile(efi, [&](Ember<float>& ember)
|
||||
m_Fractorium->m_Controller->CopyEmberFile(efi, m_FromSequence, [&](Ember<float>& ember)
|
||||
{
|
||||
ember.SyncSize();
|
||||
ember.m_Quality = m_Settings->FinalQuality();
|
||||
@ -662,7 +673,7 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
ember.m_TemporalSamples = m_Settings->FinalTemporalSamples();
|
||||
});//Copy the whole file, will take about 0.2ms per ember in the file.
|
||||
#endif
|
||||
m_Controller->SetEmberFile(efi);//Copy the temp file into the final render controller.
|
||||
m_Controller->SetEmberFile(efi, true);//Move the temp file into the final render controller.
|
||||
ui.FinalRenderCurrentSpin->setMaximum(int(efi.Size()));
|
||||
ui.FinalRenderCurrentSpin->blockSignals(true);
|
||||
ui.FinalRenderCurrentSpin->setValue(index);//Set the currently selected ember to the one that was being edited.
|
||||
@ -677,6 +688,12 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
Path(m_Controller->ComposePath(m_Controller->Name()));//Update the GUI.
|
||||
}
|
||||
|
||||
if (m_FromSequence)
|
||||
{
|
||||
ui.FinalRenderDoAllCheckBox->setChecked(true);
|
||||
ui.FinalRenderDoSequenceCheckBox->setChecked(true);
|
||||
}
|
||||
|
||||
ui.FinalRenderTextOutput->clear();
|
||||
QDialog::showEvent(e);
|
||||
}
|
||||
@ -726,9 +743,9 @@ bool FractoriumFinalRenderDialog::CreateControllerFromGUI(bool createRenderer)
|
||||
if (m_Controller.get())
|
||||
{
|
||||
#ifdef DO_DOUBLE
|
||||
m_Controller->CopyEmberFile(efd, [&](Ember<double>& ember) { });//Convert float to double or save double verbatim;
|
||||
m_Controller->CopyEmberFile(efd, false, [&](Ember<double>& ember) { });//Convert float to double or save double verbatim;
|
||||
#else
|
||||
m_Controller->CopyEmberFile(efd, [&](Ember<float>& ember) { });//Convert float to double or save double verbatim;
|
||||
m_Controller->CopyEmberFile(efd, false, [&](Ember<float>& ember) { });//Convert float to double or save double verbatim;
|
||||
#endif
|
||||
m_Controller->Shutdown();
|
||||
}
|
||||
@ -745,7 +762,7 @@ bool FractoriumFinalRenderDialog::CreateControllerFromGUI(bool createRenderer)
|
||||
//Restore the ember and ember file.
|
||||
if (m_Controller.get())
|
||||
{
|
||||
m_Controller->SetEmberFile(efd);//Convert float to double or set double verbatim;
|
||||
m_Controller->SetEmberFile(efd, true);//Convert float to double and move or move double verbatim.
|
||||
m_Controller->SetEmber(index, false);
|
||||
}
|
||||
}
|
||||
|
@ -40,13 +40,18 @@ class FractoriumFinalRenderDialog : public QDialog
|
||||
friend Fractorium;
|
||||
friend FinalRenderEmberControllerBase;
|
||||
friend FinalRenderEmberController<float>;
|
||||
friend PreviewRenderer<float>;
|
||||
friend FinalRenderPreviewRenderer<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
friend FinalRenderEmberController<double>;
|
||||
friend PreviewRenderer<double>;
|
||||
friend FinalRenderPreviewRenderer<double>;
|
||||
#endif
|
||||
|
||||
public:
|
||||
FractoriumFinalRenderDialog(FractoriumSettings* settings, QWidget* p, Qt::WindowFlags f = 0);
|
||||
void Show(bool fromSequence);
|
||||
bool EarlyClip();
|
||||
bool YAxisUp();
|
||||
bool Transparency();
|
||||
@ -113,6 +118,7 @@ private:
|
||||
bool CreateControllerFromGUI(bool createRenderer);
|
||||
bool SetMemory();
|
||||
|
||||
bool m_FromSequence;
|
||||
int m_MemoryCellIndex;
|
||||
int m_ItersCellIndex;
|
||||
int m_PathCellIndex;
|
||||
|
@ -101,50 +101,7 @@ template<typename T>
|
||||
FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender)
|
||||
: FinalRenderEmberControllerBase(finalRender)
|
||||
{
|
||||
m_FinalPreviewRenderer = make_unique<EmberNs::Renderer<T, float>>();
|
||||
m_FinalPreviewRenderer->Callback(nullptr);
|
||||
m_FinalPreviewRenderer->NumChannels(4);
|
||||
m_FinalPreviewRenderFunc = [&]()
|
||||
{
|
||||
rlg l(m_PreviewCs);//Thread prep.
|
||||
m_PreviewRun = true;
|
||||
m_FinalPreviewRenderer->Abort();
|
||||
T scalePercentage;
|
||||
size_t maxDim = 100;
|
||||
QLabel* widget = m_FinalRenderDialog->ui.FinalRenderPreviewLabel;
|
||||
|
||||
//Determine how to scale the scaled ember to fit in the label with a max of 100x100.
|
||||
if (m_Ember->m_FinalRasW >= m_Ember->m_FinalRasH)
|
||||
scalePercentage = T(maxDim) / m_Ember->m_FinalRasW;
|
||||
else
|
||||
scalePercentage = T(maxDim) / m_Ember->m_FinalRasH;
|
||||
|
||||
m_PreviewEmber = *m_Ember;
|
||||
m_PreviewEmber.m_Quality = 100;
|
||||
m_PreviewEmber.m_TemporalSamples = 1;
|
||||
m_PreviewEmber.m_FinalRasW = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * m_Ember->m_FinalRasW)));//Ensure neither is zero.
|
||||
m_PreviewEmber.m_FinalRasH = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * m_Ember->m_FinalRasH)));
|
||||
m_PreviewEmber.m_PixelsPerUnit = scalePercentage * m_Ember->m_PixelsPerUnit;
|
||||
m_FinalPreviewRenderer->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_FinalPreviewRenderer->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_FinalPreviewRenderer->Transparency(m_FinalRenderDialog->Transparency());
|
||||
m_FinalPreviewRenderer->SetEmber(m_PreviewEmber);
|
||||
m_FinalPreviewRenderer->PrepFinalAccumVector(m_PreviewFinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
auto strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string & s) { }, [&](const string & s) { }, [&](const string & s) { });
|
||||
StripsRender<T>(m_FinalPreviewRenderer.get(), m_PreviewEmber, m_PreviewFinalImage, 0, strips, m_FinalRenderDialog->YAxisUp(),
|
||||
[&](size_t strip) { },//Pre strip.
|
||||
[&](size_t strip) { },//Post strip.
|
||||
[&](size_t strip) { },//Error.
|
||||
[&](Ember<T>& finalEmber)//Final strip.
|
||||
{
|
||||
QImage image(int(finalEmber.m_FinalRasW), int(finalEmber.m_FinalRasH), QImage::Format_RGBA8888);//The label wants RGBA.
|
||||
memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in.
|
||||
QPixmap pixmap(QPixmap::fromImage(image));
|
||||
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
|
||||
});
|
||||
m_PreviewRun = false;
|
||||
};
|
||||
m_FinalPreviewRenderer = make_unique<FinalRenderPreviewRenderer<T>>(this);
|
||||
//The main rendering function which will be called in a Qt thread.
|
||||
//A backup Xml is made before the rendering process starts just in case it crashes before finishing.
|
||||
//If it finishes successfully, delete the backup file.
|
||||
@ -380,24 +337,24 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
/// These are used to preserve the current ember/file when switching between renderers.
|
||||
/// Note that some precision will be lost when going from double to float.
|
||||
/// </summary>
|
||||
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<float>& emberFile)
|
||||
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<float>& emberFile, bool move)
|
||||
{
|
||||
m_EmberFile = emberFile;
|
||||
move ? m_EmberFile = std::move(emberFile) : m_EmberFile = emberFile;
|
||||
m_Ember = m_EmberFile.Get(0);
|
||||
}
|
||||
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<float>& emberFile, std::function<void(Ember<float>& ember)> perEmberOperation)
|
||||
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<float>& emberFile, bool sequence, std::function<void(Ember<float>& ember)> perEmberOperation)
|
||||
{
|
||||
emberFile.m_Filename = m_EmberFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation);
|
||||
}
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<double>& emberFile)
|
||||
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<double>& emberFile, bool move)
|
||||
{
|
||||
m_EmberFile = emberFile;
|
||||
move ? m_EmberFile = std::move(emberFile) : m_EmberFile = emberFile;
|
||||
m_Ember = m_EmberFile.Get(0);
|
||||
}
|
||||
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<double>& emberFile, std::function<void(Ember<double>& ember)> perEmberOperation)
|
||||
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<double>& emberFile, bool sequence, std::function<void(Ember<double>& ember)> perEmberOperation)
|
||||
{
|
||||
emberFile.m_Filename = m_EmberFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation);
|
||||
@ -692,8 +649,7 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
m_Renderer->ComputeBounds();
|
||||
m_Renderer->ComputeQuality();
|
||||
m_Renderer->ComputeCamera();
|
||||
CancelPreviewRender();
|
||||
m_FinalPreviewRenderFunc();
|
||||
m_FinalPreviewRenderer->Render(UINT_MAX, UINT_MAX);
|
||||
p = m_Renderer->MemoryRequired(strips, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderer->TotalIterCount(strips);
|
||||
}
|
||||
@ -710,8 +666,7 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
renderer->ComputeCamera();
|
||||
}
|
||||
|
||||
CancelPreviewRender();
|
||||
m_FinalPreviewRenderFunc();
|
||||
m_FinalPreviewRenderer->Render(UINT_MAX, UINT_MAX);
|
||||
strips = 1;
|
||||
p = m_Renderers[0]->MemoryRequired(1, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderers[0]->TotalIterCount(strips);
|
||||
@ -759,22 +714,6 @@ EmberNs::Renderer<T, float>* FinalRenderEmberController<T>::FirstOrDefaultRender
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the preview renderer.
|
||||
/// This is meant to only be called programatically and never by the user.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FinalRenderEmberController<T>::CancelPreviewRender()
|
||||
{
|
||||
m_FinalPreviewRenderer->Abort();
|
||||
|
||||
while (m_FinalPreviewRenderer->InRender()) { QApplication::processEvents(); }
|
||||
|
||||
while (m_PreviewRun) { QApplication::processEvents(); }
|
||||
|
||||
while (m_FinalPreviewResult.isRunning()) { QApplication::processEvents(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the output of the render.
|
||||
/// </summary>
|
||||
@ -1017,6 +956,56 @@ QString FinalRenderEmberController<T>::CheckMemory(const tuple<size_t, size_t, s
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thin derivation to handle preview rendering that is specific to the final render dialog.
|
||||
/// This differs from the preview renderers on the main window because they render multiple embers
|
||||
/// to a tree, whereas this renders a single preview.
|
||||
/// </summary>
|
||||
/// <param name="start">Ignored</param>
|
||||
/// <param name="end">Ignored</param>
|
||||
template <typename T>
|
||||
void FinalRenderPreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
{
|
||||
T scalePercentage;
|
||||
size_t maxDim = 100;
|
||||
auto d = m_Controller->m_FinalRenderDialog;
|
||||
QLabel* widget = d->ui.FinalRenderPreviewLabel;
|
||||
//Determine how to scale the scaled ember to fit in the label with a max of 100x100.
|
||||
auto e = m_Controller->m_Ember;
|
||||
|
||||
if (e->m_FinalRasW >= e->m_FinalRasH)
|
||||
scalePercentage = T(maxDim) / e->m_FinalRasW;
|
||||
else
|
||||
scalePercentage = T(maxDim) / e->m_FinalRasH;
|
||||
|
||||
m_PreviewEmber = *e;
|
||||
m_PreviewEmber.m_Quality = 100;
|
||||
m_PreviewEmber.m_TemporalSamples = 1;
|
||||
m_PreviewEmber.m_FinalRasW = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * e->m_FinalRasW)));//Ensure neither is zero.
|
||||
m_PreviewEmber.m_FinalRasH = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * e->m_FinalRasH)));
|
||||
m_PreviewEmber.m_PixelsPerUnit = scalePercentage * e->m_PixelsPerUnit;
|
||||
m_PreviewRenderer.EarlyClip(d->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(d->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(d->Transparency());
|
||||
m_PreviewRenderer.Callback(nullptr);
|
||||
m_PreviewRenderer.NumChannels(4);
|
||||
m_PreviewRenderer.SetEmber(m_PreviewEmber);
|
||||
m_PreviewRenderer.PrepFinalAccumVector(m_PreviewFinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
auto strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, d->Strips(),
|
||||
[&](const string & s) {}, [&](const string & s) {}, [&](const string & s) {});
|
||||
StripsRender<T>(&m_PreviewRenderer, m_PreviewEmber, m_PreviewFinalImage, 0, strips, d->YAxisUp(),
|
||||
[&](size_t strip) {},//Pre strip.
|
||||
[&](size_t strip) {},//Post strip.
|
||||
[&](size_t strip) {},//Error.
|
||||
[&](Ember<T>& finalEmber)//Final strip.
|
||||
{
|
||||
QImage image(int(finalEmber.m_FinalRasW), int(finalEmber.m_FinalRasH), QImage::Format_RGBA8888);//The label wants RGBA.
|
||||
memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in.
|
||||
QPixmap pixmap(QPixmap::fromImage(image));
|
||||
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
|
||||
});
|
||||
}
|
||||
|
||||
template class FinalRenderEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
|
@ -13,6 +13,7 @@
|
||||
/// </summary>
|
||||
class Fractorium;
|
||||
class FractoriumFinalRenderDialog;
|
||||
template <typename T> class FinalRenderPreviewRenderer;
|
||||
|
||||
/// <summary>
|
||||
/// Used to hold the options specified in the current state of the Gui for performing the final render.
|
||||
@ -74,19 +75,16 @@ public:
|
||||
|
||||
protected:
|
||||
bool m_Run = false;
|
||||
bool m_PreviewRun = false;
|
||||
size_t m_ImageCount = 0;
|
||||
std::atomic<size_t> m_FinishedImageCount;
|
||||
|
||||
QFuture<void> m_Result;
|
||||
QFuture<void> m_FinalPreviewResult;
|
||||
std::function<void (void)> m_FinalRenderFunc;
|
||||
std::function<void (void)> m_FinalPreviewRenderFunc;
|
||||
|
||||
FractoriumSettings* m_Settings;
|
||||
FractoriumFinalRenderDialog* m_FinalRenderDialog;
|
||||
FinalRenderGuiState m_GuiState;
|
||||
std::recursive_mutex m_PreviewCs, m_ProgressCs;
|
||||
std::recursive_mutex m_ProgressCs;
|
||||
Timing m_RenderTimer;
|
||||
Timing m_TotalTimer;
|
||||
};
|
||||
@ -98,16 +96,18 @@ protected:
|
||||
template<typename T>
|
||||
class FinalRenderEmberController : public FinalRenderEmberControllerBase
|
||||
{
|
||||
friend FinalRenderPreviewRenderer<T>;
|
||||
|
||||
public:
|
||||
FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender);
|
||||
virtual ~FinalRenderEmberController() { }
|
||||
|
||||
//Virtual functions overridden from FractoriumEmberControllerBase.
|
||||
virtual void SetEmberFile(const EmberFile<float>& emberFile) override;
|
||||
virtual void CopyEmberFile(EmberFile<float>& emberFile, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) override;
|
||||
virtual void SetEmberFile(const EmberFile<float>& emberFile, bool move) override;
|
||||
virtual void CopyEmberFile(EmberFile<float>& emberFile, bool sequence, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) override;
|
||||
#ifdef DO_DOUBLE
|
||||
virtual void SetEmberFile(const EmberFile<double>& emberFile) override;
|
||||
virtual void CopyEmberFile(EmberFile<double>& emberFile, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) override;
|
||||
virtual void SetEmberFile(const EmberFile<double>& emberFile, bool move) override;
|
||||
virtual void CopyEmberFile(EmberFile<double>& emberFile, bool sequence, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) override;
|
||||
#endif
|
||||
virtual void SetEmber(size_t index, bool verbatim) override;
|
||||
virtual bool Render() override;
|
||||
@ -132,7 +132,6 @@ public:
|
||||
EmberNs::Renderer<T, float>* FirstOrDefaultRenderer();
|
||||
|
||||
protected:
|
||||
void CancelPreviewRender();
|
||||
void HandleFinishedProgress();
|
||||
void SaveCurrentRender(Ember<T>& ember);
|
||||
void SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc);
|
||||
@ -143,10 +142,32 @@ protected:
|
||||
void SetProgressComplete(int val);
|
||||
|
||||
Ember<T>* m_Ember;
|
||||
Ember<T> m_PreviewEmber;
|
||||
EmberFile<T> m_EmberFile;
|
||||
EmberToXml<T> m_XmlWriter;
|
||||
unique_ptr<EmberNs::Renderer<T, float>> m_FinalPreviewRenderer;
|
||||
unique_ptr<FinalRenderPreviewRenderer<T>> m_FinalPreviewRenderer;
|
||||
vector<unique_ptr<EmberNs::Renderer<T, float>>> m_Renderers;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Thin derivation to handle preview rendering that is specific to the final render dialog.
|
||||
/// This differs from the preview renderers on the main window because they render multiple embers
|
||||
/// to a tree, whereas this renders a single preview.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
class FinalRenderPreviewRenderer : public PreviewRenderer<T>
|
||||
{
|
||||
public:
|
||||
using PreviewRenderer<T>::m_PreviewRun;
|
||||
using PreviewRenderer<T>::m_PreviewEmber;
|
||||
using PreviewRenderer<T>::m_PreviewRenderer;
|
||||
using PreviewRenderer<T>::m_PreviewFinalImage;
|
||||
|
||||
FinalRenderPreviewRenderer(FinalRenderEmberController<T>* controller) : m_Controller(controller)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void PreviewRenderFunc(uint start, uint end) override;
|
||||
|
||||
private:
|
||||
FinalRenderEmberController<T>* m_Controller;
|
||||
};
|
||||
|
@ -198,6 +198,7 @@ Fractorium::Fractorium(QWidget* p)
|
||||
/// </summary>
|
||||
Fractorium::~Fractorium()
|
||||
{
|
||||
SyncSequenceSettings();
|
||||
m_VarDialog->SyncSettings();
|
||||
m_Settings->setValue("windowState", saveState());
|
||||
m_Settings->sync();
|
||||
@ -373,7 +374,7 @@ void Fractorium::closeEvent(QCloseEvent* e)
|
||||
if (m_Controller.get())
|
||||
{
|
||||
m_Controller->StopRenderTimer(true);//Will wait until fully exited and stopped.
|
||||
m_Controller->StopPreviewRender();
|
||||
m_Controller->StopAllPreviewRenderers();
|
||||
}
|
||||
|
||||
if (e)
|
||||
@ -665,13 +666,15 @@ void Fractorium::ShowCritical(const QString& title, const QString& text, bool in
|
||||
/// </summary>
|
||||
void Fractorium::SetTabOrders()
|
||||
{
|
||||
QWidget* w = SetTabOrder(this, ui.ColorTable, m_BrightnessSpin);//Flame.
|
||||
QWidget* w = SetTabOrder(this, ui.ColorTable, m_BrightnessSpin);//Flame color.
|
||||
w = SetTabOrder(this, w, m_GammaSpin);
|
||||
w = SetTabOrder(this, w, m_GammaThresholdSpin);
|
||||
w = SetTabOrder(this, w, m_VibrancySpin);
|
||||
w = SetTabOrder(this, w, m_HighlightSpin);
|
||||
w = SetTabOrder(this, w, m_BackgroundColorButton);
|
||||
w = SetTabOrder(this, w, m_PaletteModeCombo);
|
||||
w = SetTabOrder(this, w, m_WidthSpin);//Flame geometry.
|
||||
w = SetTabOrder(this, w, m_HeightSpin);
|
||||
w = SetTabOrder(this, w, m_CenterXSpin);
|
||||
w = SetTabOrder(this, w, m_CenterYSpin);
|
||||
w = SetTabOrder(this, w, m_ScaleSpin);
|
||||
@ -682,18 +685,44 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, m_PitchSpin);
|
||||
w = SetTabOrder(this, w, m_YawSpin);
|
||||
w = SetTabOrder(this, w, m_DepthBlurSpin);
|
||||
w = SetTabOrder(this, w, m_SpatialFilterWidthSpin);
|
||||
w = SetTabOrder(this, w, m_SpatialFilterWidthSpin);//Flame filter.
|
||||
w = SetTabOrder(this, w, m_SpatialFilterTypeCombo);
|
||||
w = SetTabOrder(this, w, m_TemporalFilterTypeCombo);
|
||||
w = SetTabOrder(this, w, m_DEFilterMinRadiusSpin);
|
||||
w = SetTabOrder(this, w, m_DEFilterMaxRadiusSpin);
|
||||
w = SetTabOrder(this, w, m_DECurveSpin);
|
||||
w = SetTabOrder(this, w, m_TemporalSamplesSpin);
|
||||
w = SetTabOrder(this, w, m_SbsSpin);//Flame iteration.
|
||||
w = SetTabOrder(this, w, m_FuseSpin);
|
||||
w = SetTabOrder(this, w, m_QualitySpin);
|
||||
w = SetTabOrder(this, w, m_SupersampleSpin);
|
||||
w = SetTabOrder(this, w, m_InterpTypeCombo);//Flame animation.
|
||||
w = SetTabOrder(this, w, m_AffineInterpTypeCombo);
|
||||
w = SetTabOrder(this, w, m_InterpTypeCombo);
|
||||
w = SetTabOrder(this, w, m_TemporalSamplesSpin);
|
||||
w = SetTabOrder(this, w, m_TemporalFilterWidthSpin);
|
||||
w = SetTabOrder(this, w, m_TemporalFilterTypeCombo);
|
||||
w = SetTabOrder(this, ui.LibraryTree, ui.SequenceStartCountSpinBox);//Library.
|
||||
w = SetTabOrder(this, w, ui.SequenceStartPreviewsButton);
|
||||
w = SetTabOrder(this, w, ui.SequenceStopPreviewsButton);
|
||||
w = SetTabOrder(this, w, ui.SequenceStartFlameSpinBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceStopFlameSpinBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceAllButton);
|
||||
w = SetTabOrder(this, w, ui.SequenceRandomizeStaggerCheckBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceStaggerCheckBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceRandomizeFramesPerRotCheckBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceFramesPerRotSpinBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceRandomFramesPerRotMaxSpinBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceRandomizeRotationsCheckBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceRotationsSpinBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceRandomRotationsMaxSpinBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceRandomizeBlendFramesCheckBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceBlendFramesSpinBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceRandomBlendMaxFramesSpinBox);
|
||||
w = SetTabOrder(this, w, ui.SequenceGenerateButton);
|
||||
w = SetTabOrder(this, w, ui.SequenceRenderButton);
|
||||
w = SetTabOrder(this, w, ui.SequenceSaveButton);
|
||||
w = SetTabOrder(this, w, ui.SequenceOpenButton);
|
||||
w = SetTabOrder(this, w, ui.SequenceTree);
|
||||
w = SetTabOrder(this, ui.CurrentXformCombo, ui.AddXformButton);//Xforms.
|
||||
w = SetTabOrder(this, w, ui.AddLinkedXformButton);
|
||||
w = SetTabOrder(this, w, ui.DuplicateXformButton);
|
||||
w = SetTabOrder(this, w, ui.ClearXformButton);
|
||||
w = SetTabOrder(this, w, ui.DeleteXformButton);
|
||||
@ -701,11 +730,14 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, m_XformWeightSpin);
|
||||
w = SetTabOrder(this, w, m_XformWeightSpinnerButtonWidget->m_Button);
|
||||
w = SetTabOrder(this, m_XformColorIndexSpin, ui.XformColorScroll);//Xforms color.
|
||||
w = SetTabOrder(this, w, ui.RandomColorIndicesButton);
|
||||
w = SetTabOrder(this, w, ui.ToggleColorIndicesButton);
|
||||
w = SetTabOrder(this, w, m_XformColorSpeedSpin);
|
||||
w = SetTabOrder(this, w, m_XformOpacitySpin);
|
||||
w = SetTabOrder(this, w, m_XformDirectColorSpin);
|
||||
w = SetTabOrder(this, w, ui.SoloXformCheckBox);
|
||||
w = SetTabOrder(this, ui.PreAffineGroupBox, m_PreX1Spin);//Xforms affine.
|
||||
w = SetTabOrder(this, ui.LockAffineCheckBox, ui.PreAffineGroupBox);//Xforms affine.
|
||||
w = SetTabOrder(this, w, m_PreX1Spin);
|
||||
w = SetTabOrder(this, w, m_PreX2Spin);
|
||||
w = SetTabOrder(this, w, m_PreY1Spin);
|
||||
w = SetTabOrder(this, w, m_PreY2Spin);
|
||||
@ -727,6 +759,7 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.PreScaleDownButton);
|
||||
w = SetTabOrder(this, w, ui.PreScaleCombo);
|
||||
w = SetTabOrder(this, w, ui.PreScaleUpButton);
|
||||
w = SetTabOrder(this, w, ui.PreRandomButton);
|
||||
w = SetTabOrder(this, w, ui.ShowPreAffineCurrentRadio);
|
||||
w = SetTabOrder(this, w, ui.ShowPreAffineAllRadio);
|
||||
w = SetTabOrder(this, w, ui.PostAffineGroupBox);
|
||||
@ -752,21 +785,33 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.PostScaleDownButton);
|
||||
w = SetTabOrder(this, w, ui.PostScaleCombo);
|
||||
w = SetTabOrder(this, w, ui.PostScaleUpButton);
|
||||
w = SetTabOrder(this, w, ui.PostRandomButton);
|
||||
w = SetTabOrder(this, w, ui.ShowPostAffineCurrentRadio);
|
||||
w = SetTabOrder(this, w, ui.ShowPostAffineAllRadio);
|
||||
w = SetTabOrder(this, w, ui.PolarAffineCheckBox);
|
||||
w = SetTabOrder(this, w, ui.LocalPivotRadio);
|
||||
w = SetTabOrder(this, w, ui.WorldPivotRadio);
|
||||
w = SetTabOrder(this, ui.VariationsFilterLineEdit, ui.VariationsFilterClearButton);//Xforms variation.
|
||||
w = SetTabOrder(this, w, ui.VariationsTree);
|
||||
//Xforms xaos is done dynamically every time.
|
||||
w = SetTabOrder(this, m_PaletteHueSpin, m_PaletteContrastSpin);//Palette.
|
||||
w = SetTabOrder(this, ui.PaletteFilenameCombo, m_PaletteHueSpin);//Palette.
|
||||
w = SetTabOrder(this, w, m_PaletteContrastSpin);
|
||||
w = SetTabOrder(this, w, m_PaletteSaturationSpin);
|
||||
w = SetTabOrder(this, w, m_PaletteBlurSpin);
|
||||
w = SetTabOrder(this, w, m_PaletteBrightnessSpin);
|
||||
w = SetTabOrder(this, w, m_PaletteFrequencySpin);
|
||||
w = SetTabOrder(this, w, ui.PaletteRandomSelect);
|
||||
w = SetTabOrder(this, w, ui.PaletteRandomAdjust);
|
||||
w = SetTabOrder(this, w, ui.PaletteFilterLineEdit);
|
||||
w = SetTabOrder(this, w, ui.PaletteFilterClearButton);
|
||||
w = SetTabOrder(this, w, ui.PaletteListTable);
|
||||
w = SetTabOrder(this, w, ui.ResetCurvesButton);//Palette curves.
|
||||
w = SetTabOrder(this, w, ui.CurvesView);
|
||||
w = SetTabOrder(this, w, ui.CurvesGroupBox);
|
||||
w = SetTabOrder(this, w, ui.CurvesAllRadio);
|
||||
w = SetTabOrder(this, w, ui.CurvesRedRadio);
|
||||
w = SetTabOrder(this, w, ui.CurvesGreenRadio);
|
||||
w = SetTabOrder(this, w, ui.CurvesBlueRadio);
|
||||
w = SetTabOrder(this, ui.SummaryTable, ui.SummaryTree);//Info summary.
|
||||
w = SetTabOrder(this, ui.InfoBoundsGroupBox, ui.InfoBoundsFrame);//Info bounds.
|
||||
w = SetTabOrder(this, w, ui.InfoBoundsTable);
|
||||
|
@ -75,17 +75,24 @@ class Fractorium : public QMainWindow
|
||||
friend FractoriumEmberController<float>;
|
||||
friend FinalRenderEmberControllerBase;
|
||||
friend FinalRenderEmberController<float>;
|
||||
friend PreviewRenderer<float>;
|
||||
friend TreePreviewRenderer<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
friend GLEmberController<double>;
|
||||
friend FractoriumEmberController<double>;
|
||||
friend FinalRenderEmberController<double>;
|
||||
friend PreviewRenderer<double>;
|
||||
friend TreePreviewRenderer<double>;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Fractorium(QWidget* p = nullptr);
|
||||
~Fractorium();
|
||||
|
||||
//Library.
|
||||
void SyncFileCountToSequenceCount();
|
||||
|
||||
//Geometry.
|
||||
bool ApplyAll();
|
||||
void SetCenter(float x, float y);
|
||||
@ -156,6 +163,25 @@ public slots:
|
||||
void OnEmberTreeItemChanged(QTreeWidgetItem* item, int col);
|
||||
void OnEmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col);
|
||||
void OnDelete(const pair<size_t, QTreeWidgetItem*>& p);
|
||||
void OnSequenceTreeItemChanged(QTreeWidgetItem* item, int col);
|
||||
void OnSequenceStartPreviewsButtonClicked(bool checked);
|
||||
void OnSequenceStopPreviewsButtonClicked(bool checked);
|
||||
void OnSequenceAllButtonClicked(bool checked);
|
||||
void OnSequenceGenerateButtonClicked(bool checked);
|
||||
void OnSequenceRenderButtonClicked(bool checked);
|
||||
void OnSequenceSaveButtonClicked(bool checked);
|
||||
void OnSequenceOpenButtonClicked(bool checked);
|
||||
void OnSequenceRandomizeFramesPerRotCheckBoxStateChanged(int state);
|
||||
void OnSequenceRandomizeRotationsCheckBoxStateChanged(int state);
|
||||
void OnSequenceRandomizeBlendFramesCheckBoxStateChanged(int state);
|
||||
void OnSequenceStartFlameSpinBoxChanged(int d);
|
||||
void OnSequenceStopFlameSpinBoxChanged(int d);
|
||||
void OnSequenceFramesPerRotSpinBoxChanged(int d);
|
||||
void OnSequenceRandomFramesPerRotMaxSpinBoxChanged(int d);
|
||||
void OnSequenceRotationsSpinBoxChanged(double d);
|
||||
void OnSequenceRandomRotationsMaxSpinBoxChanged(double d);
|
||||
void OnSequenceBlendFramesSpinBoxChanged(int d);
|
||||
void OnSequenceRandomBlendMaxFramesSpinBoxChanged(int d);
|
||||
|
||||
//Params.
|
||||
void OnBrightnessChanged(double d);//Color.
|
||||
@ -342,6 +368,7 @@ private:
|
||||
|
||||
//Library.
|
||||
pair<size_t, QTreeWidgetItem*> GetCurrentEmberIndex();
|
||||
void SyncSequenceSettings();
|
||||
|
||||
//Params.
|
||||
|
||||
|
@ -74,7 +74,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1184</width>
|
||||
<width>1016</width>
|
||||
<height>987</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -6683,7 +6683,7 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>200</height>
|
||||
<height>251</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
@ -6711,6 +6711,12 @@
|
||||
<number>1</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="DockWidgetContents">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -6731,96 +6737,557 @@
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="LibraryTabScrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<widget class="QSplitter" name="LibrarySequenceSplitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="LibraryTabScrollWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>256</width>
|
||||
<height>956</height>
|
||||
</rect>
|
||||
<widget class="LibraryTreeWidget" name="LibraryTree">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::WheelFocus</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::SelectedClicked</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>27</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Current Flame File</string>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="SequenceScrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="SequenceScrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>424</width>
|
||||
<height>589</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="LibraryTreeWidget" name="LibraryTree">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::WheelFocus</enum>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::SelectedClicked</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>27</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Current Flame File</string>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10" stretch="3,0,8">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="SequenceParamsControlsGridLayout" columnstretch="0,0,0">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="SequenceFramesPerRotSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Frames per rot: </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" alignment="Qt::AlignLeft">
|
||||
<widget class="QCheckBox" name="SequenceStaggerCheckBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stagger</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="SequenceRotationsSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Rotations: </string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>3.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" alignment="Qt::AlignLeft">
|
||||
<widget class="QCheckBox" name="SequenceRandomizeFramesPerRotCheckBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QSpinBox" name="SequenceRandomFramesPerRotMaxSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Frames per rot max: </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" alignment="Qt::AlignLeft">
|
||||
<widget class="QCheckBox" name="SequenceRandomizeStaggerCheckBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Random</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="SequenceBlendFramesSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Blend frames: </string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>120</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QSpinBox" name="SequenceRandomBlendMaxFramesSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Blend max frames: </string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>120</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QDoubleSpinBox" name="SequenceRandomRotationsMaxSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Rotations max: </string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>3.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" alignment="Qt::AlignLeft">
|
||||
<widget class="QCheckBox" name="SequenceRandomizeRotationsCheckBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" alignment="Qt::AlignLeft">
|
||||
<widget class="QCheckBox" name="SequenceRandomizeBlendFramesCheckBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QSpinBox" name="SequenceStartFlameSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Start flame: </string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="SequenceStopFlameSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Stop flame: </string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="SequenceAllButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>33</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="SequenceStartCountSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Start count: </string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="SequenceStartPreviewsButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start Previews</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="SequenceStopPreviewsButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop Previews</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="SequenceSaveButtonsHLayout" stretch="0,0,0,0">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="SequenceGenerateButton">
|
||||
<property name="text">
|
||||
<string>Generate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="SequenceRenderButton">
|
||||
<property name="text">
|
||||
<string>Render</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="SequenceSaveButton">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="SequenceOpenButton">
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LibraryTreeWidget" name="SequenceTree">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::WheelFocus</enum>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::SelectedClicked</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>27</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Sequence</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -406,3 +406,47 @@ static QList<T> GetAllParents(QWidget* widget)
|
||||
|
||||
return parents;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constrain the value in low to be less than or equal to the value in high.
|
||||
/// Template expected to be any control which has member functions value() and setValue().
|
||||
/// Most likely QSpinBox or QDoubleSpinbox.
|
||||
/// </summary>
|
||||
/// <param name="low">The control which must contain the lower value</param>
|
||||
/// <param name="high">The control which must contain the higher value</param>
|
||||
/// <returns>True if the value of low had to be changed, else false.</returns>
|
||||
template <typename T>
|
||||
bool ConstrainLow(T* low, T* high)
|
||||
{
|
||||
if (low->value() > high->value())
|
||||
{
|
||||
low->blockSignals(true);
|
||||
low->setValue(high->value());
|
||||
low->blockSignals(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constrain the value in high to be greater than or equal to the value in low.
|
||||
/// Template expected to be any control which has member functions value() and setValue().
|
||||
/// Most likely QSpinBox or QDoubleSpinbox.
|
||||
/// </summary>
|
||||
/// <param name="low">The control which must contain the lower value</param>
|
||||
/// <param name="high">The control which must contain the higher value</param>
|
||||
/// <returns>True if the value of high had to be changed, else false.</returns>
|
||||
template <typename T>
|
||||
bool ConstrainHigh(T* low, T* high)
|
||||
{
|
||||
if (high->value() < low->value())
|
||||
{
|
||||
high->blockSignals(true);
|
||||
high->setValue(low->value());
|
||||
high->blockSignals(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
|
||||
{
|
||||
bool b = false;
|
||||
m_GLController = make_unique<GLEmberController<T>>(fractorium, fractorium->ui.GLDisplay, this);
|
||||
m_LibraryPreviewRenderer = make_unique<TreePreviewRenderer<T>>(this, m_Fractorium->ui.LibraryTree, m_EmberFile);
|
||||
m_SequencePreviewRenderer = make_unique<TreePreviewRenderer<T>>(this, m_Fractorium->ui.SequenceTree, m_SequenceFile);
|
||||
//Initial combo change event to fill the palette table will be called automatically later.
|
||||
//Look hard for a palette.
|
||||
static vector<string> paths =
|
||||
@ -70,57 +72,6 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
|
||||
|
||||
BackgroundChanged(QColor(0, 0, 0));//Default to black.
|
||||
ClearUndo();
|
||||
m_PreviewRenderer->Callback(nullptr);
|
||||
m_PreviewRenderer->NumChannels(4);
|
||||
m_PreviewRenderer->EarlyClip(m_Fractorium->m_Settings->EarlyClip());
|
||||
m_PreviewRenderer->YAxisUp(m_Fractorium->m_Settings->YAxisUp());
|
||||
m_PreviewRenderer->SetEmber(m_Ember);//Give it an initial ember, will be updated many times later.
|
||||
//m_PreviewRenderer->ThreadCount(1);//For debugging.
|
||||
m_PreviewRenderFunc = [&](uint start, uint end)
|
||||
{
|
||||
while (m_PreviewRun || m_PreviewRunning)
|
||||
{
|
||||
}
|
||||
|
||||
m_PreviewRun = true;
|
||||
m_PreviewRunning = true;
|
||||
m_PreviewRenderer->ThreadCount(std::max(1u, Timing::ProcessorCount() - 1));//Leave one processor free so the GUI can breathe.
|
||||
auto tree = m_Fractorium->ui.LibraryTree;
|
||||
|
||||
if (auto top = tree->topLevelItem(0))
|
||||
{
|
||||
size_t i = start;
|
||||
|
||||
for (auto b = Advance(m_EmberFile.m_Embers.begin(), start); m_PreviewRun && i < end && b != m_EmberFile.m_Embers.end(); ++b, ++i)
|
||||
{
|
||||
Ember<T> ember = *b;
|
||||
ember.SyncSize();
|
||||
ember.SetSizeAndAdjustScale(PREVIEW_SIZE, PREVIEW_SIZE, false, eScaleType::SCALE_WIDTH);
|
||||
ember.m_TemporalSamples = 1;
|
||||
ember.m_Quality = 25;
|
||||
ember.m_Supersample = 1;
|
||||
m_PreviewRenderer->SetEmber(ember);
|
||||
|
||||
if (m_PreviewRenderer->Run(m_PreviewFinalImage) == eRenderStatus::RENDER_OK)
|
||||
{
|
||||
if (auto treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(int(i))))
|
||||
{
|
||||
//It is critical that Qt::BlockingQueuedConnection is passed because this is running on a different thread than the UI.
|
||||
//This ensures the events are processed in order as each preview is updated, and that control does not return here
|
||||
//until the update is complete.
|
||||
QMetaObject::invokeMethod(m_Fractorium, "SetLibraryTreeItemData", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(EmberTreeWidgetItemBase*, dynamic_cast<EmberTreeWidgetItemBase*>(treeItem)),
|
||||
Q_ARG(vector<byte>&, m_PreviewFinalImage),
|
||||
Q_ARG(uint, PREVIEW_SIZE),
|
||||
Q_ARG(uint, PREVIEW_SIZE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_PreviewRun = false;
|
||||
m_PreviewRunning = false;
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -136,11 +87,19 @@ FractoriumEmberController<T>::~FractoriumEmberController() { }
|
||||
/// </summary>
|
||||
template <typename T> void FractoriumEmberController<T>::SetEmber(const Ember<float>& ember, bool verbatim, bool updatePointer) { SetEmberPrivate<float>(ember, verbatim, updatePointer); }
|
||||
template <typename T> void FractoriumEmberController<T>::CopyEmber(Ember<float>& ember, std::function<void(Ember<float>& ember)> perEmberOperation) { ember = m_Ember; perEmberOperation(ember); }
|
||||
template <typename T> void FractoriumEmberController<T>::SetEmberFile(const EmberFile<float>& emberFile) { m_EmberFile = emberFile; }
|
||||
template <typename T> void FractoriumEmberController<T>::CopyEmberFile(EmberFile<float>& emberFile, std::function<void(Ember<float>& ember)> perEmberOperation)
|
||||
template <typename T> void FractoriumEmberController<T>::SetEmberFile(const EmberFile<float>& emberFile, bool move) { move ? m_EmberFile = std::move(emberFile) : m_EmberFile = emberFile; }
|
||||
template <typename T> void FractoriumEmberController<T>::CopyEmberFile(EmberFile<float>& emberFile, bool sequence, std::function<void(Ember<float>& ember)> perEmberOperation)
|
||||
{
|
||||
emberFile.m_Filename = m_EmberFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation);
|
||||
if (sequence)
|
||||
{
|
||||
emberFile.m_Filename = m_SequenceFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_SequenceFile.m_Embers, perEmberOperation);
|
||||
}
|
||||
else
|
||||
{
|
||||
emberFile.m_Filename = m_EmberFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void FractoriumEmberController<T>::SetTempPalette(const Palette<float>& palette) { m_TempPalette = palette; }
|
||||
@ -148,11 +107,19 @@ template <typename T> void FractoriumEmberController<T>::CopyTempPalette(Palette
|
||||
#ifdef DO_DOUBLE
|
||||
template <typename T> void FractoriumEmberController<T>::SetEmber(const Ember<double>& ember, bool verbatim, bool updatePointer) { SetEmberPrivate<double>(ember, verbatim, updatePointer); }
|
||||
template <typename T> void FractoriumEmberController<T>::CopyEmber(Ember<double>& ember, std::function<void(Ember<double>& ember)> perEmberOperation) { ember = m_Ember; perEmberOperation(ember); }
|
||||
template <typename T> void FractoriumEmberController<T>::SetEmberFile(const EmberFile<double>& emberFile) { m_EmberFile = emberFile; }
|
||||
template <typename T> void FractoriumEmberController<T>::CopyEmberFile(EmberFile<double>& emberFile, std::function<void(Ember<double>& ember)> perEmberOperation)
|
||||
template <typename T> void FractoriumEmberController<T>::SetEmberFile(const EmberFile<double>& emberFile, bool move) { move ? m_EmberFile = std::move(emberFile) : m_EmberFile = emberFile; }
|
||||
template <typename T> void FractoriumEmberController<T>::CopyEmberFile(EmberFile<double>& emberFile, bool sequence, std::function<void(Ember<double>& ember)> perEmberOperation)
|
||||
{
|
||||
emberFile.m_Filename = m_EmberFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation);
|
||||
if (sequence)
|
||||
{
|
||||
emberFile.m_Filename = m_SequenceFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_SequenceFile.m_Embers, perEmberOperation);
|
||||
}
|
||||
else
|
||||
{
|
||||
emberFile.m_Filename = m_EmberFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void FractoriumEmberController<T>::SetTempPalette(const Palette<double>& palette) { m_TempPalette = palette; }
|
||||
@ -387,8 +354,58 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
|
||||
m_Fractorium->CenterScrollbars();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thin derivation to handle preview rendering multiple embers previews to a tree.
|
||||
/// </summary>
|
||||
/// <param name="start">The 0-based index to start rendering previews for</param>
|
||||
/// <param name="end">The 0-based index which is one beyond the last ember to render a preview for</param>
|
||||
template <typename T>
|
||||
void TreePreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
{
|
||||
auto f = m_Controller->m_Fractorium;
|
||||
m_PreviewRenderer.EarlyClip(f->m_Settings->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(f->m_Settings->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(f->m_Settings->Transparency());
|
||||
m_PreviewRenderer.ThreadCount(std::max(1u, Timing::ProcessorCount() - 1));//Leave one processor free so the GUI can breathe.
|
||||
|
||||
if (auto top = m_Tree->topLevelItem(0))
|
||||
{
|
||||
size_t i = start;
|
||||
|
||||
for (auto b = Advance(m_EmberFile.m_Embers.begin(), start); m_PreviewRun && i < end && b != m_EmberFile.m_Embers.end(); ++b, ++i)
|
||||
{
|
||||
m_PreviewEmber = *b;
|
||||
m_PreviewEmber.SyncSize();
|
||||
m_PreviewEmber.SetSizeAndAdjustScale(PREVIEW_SIZE, PREVIEW_SIZE, false, eScaleType::SCALE_WIDTH);
|
||||
m_PreviewEmber.m_TemporalSamples = 1;
|
||||
m_PreviewEmber.m_Quality = 25;
|
||||
m_PreviewEmber.m_Supersample = 1;
|
||||
m_PreviewRenderer.SetEmber(m_PreviewEmber);
|
||||
|
||||
if (m_PreviewRenderer.Run(m_PreviewFinalImage) == eRenderStatus::RENDER_OK)
|
||||
{
|
||||
if (auto treeItem = dynamic_cast<EmberTreeWidgetItemBase*>(top->child(int(i))))
|
||||
{
|
||||
//It is critical that Qt::BlockingQueuedConnection is passed because this is running on a different thread than the UI.
|
||||
//This ensures the events are processed in order as each preview is updated, and that control does not return here
|
||||
//until the update is complete.
|
||||
QMetaObject::invokeMethod(f, "SetLibraryTreeItemData", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(EmberTreeWidgetItemBase*, treeItem),
|
||||
Q_ARG(vector<byte>&, m_PreviewFinalImage),
|
||||
Q_ARG(uint, PREVIEW_SIZE),
|
||||
Q_ARG(uint, PREVIEW_SIZE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
template class PreviewRenderer<float>;
|
||||
template class TreePreviewRenderer<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class PreviewRenderer<double>;
|
||||
template class TreePreviewRenderer<double>;
|
||||
#endif
|
||||
|
@ -29,6 +29,9 @@ enum eLibraryUpdate { INDEX = 1, NAME = 2, POINTER = 4 };
|
||||
/// So Fractorium includes this file, and Fractorium is declared as a forward declaration here.
|
||||
/// </summary>
|
||||
class Fractorium;
|
||||
template <typename T> class PreviewRenderer;
|
||||
template <typename T> class TreePreviewRenderer;
|
||||
|
||||
#define PREVIEW_SIZE 256
|
||||
#define UNDO_SIZE 128
|
||||
|
||||
@ -54,20 +57,19 @@ public:
|
||||
//Embers.
|
||||
virtual void SetEmber(const Ember<float>& ember, bool verbatim, bool updatePointer) { }
|
||||
virtual void CopyEmber(Ember<float>& ember, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) { }//Uncomment default lambdas once LLVM fixes a crash in their compiler with default lambda parameters.//TODO
|
||||
virtual void SetEmberFile(const EmberFile<float>& emberFile) { }
|
||||
virtual void CopyEmberFile(EmberFile<float>& emberFile, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) { }
|
||||
virtual void SetEmberFile(const EmberFile<float>& emberFile, bool move) { }
|
||||
virtual void CopyEmberFile(EmberFile<float>& emberFile, bool sequence, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) { }
|
||||
virtual void SetTempPalette(const Palette<float>& palette) { }
|
||||
virtual void CopyTempPalette(Palette<float>& palette) { }
|
||||
#ifdef DO_DOUBLE
|
||||
virtual void SetEmber(const Ember<double>& ember, bool verbatim, bool updatePointer) { }
|
||||
virtual void CopyEmber(Ember<double>& ember, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) { }
|
||||
virtual void SetEmberFile(const EmberFile<double>& emberFile) { }
|
||||
virtual void CopyEmberFile(EmberFile<double>& emberFile, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) { }
|
||||
virtual void SetEmberFile(const EmberFile<double>& emberFile, bool move) { }
|
||||
virtual void CopyEmberFile(EmberFile<double>& emberFile, bool sequence, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) { }
|
||||
virtual void SetTempPalette(const Palette<double>& palette) { }
|
||||
virtual void CopyTempPalette(Palette<double>& palette) { }
|
||||
#endif
|
||||
virtual void SetEmber(size_t index, bool verbatim) { }
|
||||
//virtual void Clear() { }
|
||||
virtual void AddXform() { }
|
||||
virtual void AddLinkedXform() { }
|
||||
virtual void DuplicateXform() { }
|
||||
@ -119,10 +121,18 @@ public:
|
||||
virtual void UpdateLibraryTree() { }
|
||||
virtual void EmberTreeItemChanged(QTreeWidgetItem* item, int col) { }
|
||||
virtual void EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) { }
|
||||
virtual void RenderPreviews(uint start = UINT_MAX, uint end = UINT_MAX) { }
|
||||
virtual void StopPreviewRender() { }
|
||||
virtual void RenderLibraryPreviews(uint start = UINT_MAX, uint end = UINT_MAX) { }
|
||||
virtual void RenderSequencePreviews(uint start = UINT_MAX, uint end = UINT_MAX) { }
|
||||
virtual void SequenceTreeItemChanged(QTreeWidgetItem* item, int col) { }
|
||||
virtual void StopLibraryPreviewRender() { }
|
||||
virtual void StopSequencePreviewRender() { }
|
||||
virtual void StopAllPreviewRenderers() { }
|
||||
virtual void MoveLibraryItems(int startRow, int destRow) { }
|
||||
virtual void Delete(const pair<size_t, QTreeWidgetItem*>& p) { }
|
||||
virtual void FillSequenceTree() { }
|
||||
virtual void SequenceGenerateButtonClicked() { }
|
||||
virtual void SequenceSaveButtonClicked() { }
|
||||
virtual void SequenceOpenButtonClicked() { }
|
||||
|
||||
//Params.
|
||||
virtual void SetCenter(double x, double y) { }
|
||||
@ -287,6 +297,9 @@ protected:
|
||||
template<typename T>
|
||||
class FractoriumEmberController : public FractoriumEmberControllerBase
|
||||
{
|
||||
friend PreviewRenderer<T>;
|
||||
friend TreePreviewRenderer<T>;
|
||||
|
||||
public:
|
||||
FractoriumEmberController(Fractorium* fractorium);
|
||||
FractoriumEmberController(const FractoriumEmberController<T>& controller) = delete;
|
||||
@ -295,20 +308,19 @@ public:
|
||||
//Embers.
|
||||
virtual void SetEmber(const Ember<float>& ember, bool verbatim, bool updatePointer) override;
|
||||
virtual void CopyEmber(Ember<float>& ember, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) override;
|
||||
virtual void SetEmberFile(const EmberFile<float>& emberFile) override;
|
||||
virtual void CopyEmberFile(EmberFile<float>& emberFile, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) override;
|
||||
virtual void SetEmberFile(const EmberFile<float>& emberFile, bool move) override;
|
||||
virtual void CopyEmberFile(EmberFile<float>& emberFile, bool sequence, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) override;
|
||||
virtual void SetTempPalette(const Palette<float>& palette) override;
|
||||
virtual void CopyTempPalette(Palette<float>& palette) override;
|
||||
#ifdef DO_DOUBLE
|
||||
virtual void SetEmber(const Ember<double>& ember, bool verbatim, bool updatePointer) override;
|
||||
virtual void CopyEmber(Ember<double>& ember, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) override;
|
||||
virtual void SetEmberFile(const EmberFile<double>& emberFile) override;
|
||||
virtual void CopyEmberFile(EmberFile<double>& emberFile, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) override;
|
||||
virtual void SetEmberFile(const EmberFile<double>& emberFile, bool move) override;
|
||||
virtual void CopyEmberFile(EmberFile<double>& emberFile, bool sequence, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) override;
|
||||
virtual void SetTempPalette(const Palette<double>& palette) override;
|
||||
virtual void CopyTempPalette(Palette<double>& palette) override;
|
||||
#endif
|
||||
virtual void SetEmber(size_t index, bool verbatim) override;
|
||||
//virtual void Clear() override { }
|
||||
virtual void AddXform() override;
|
||||
virtual void AddLinkedXform() override;
|
||||
virtual void DuplicateXform() override;
|
||||
@ -316,7 +328,6 @@ public:
|
||||
virtual void DeleteXforms() override;
|
||||
virtual void AddFinalXform() override;
|
||||
virtual bool UseFinalXform() override { return m_Ember.UseFinalXform(); }
|
||||
//virtual bool IsFinal(uint i) { return false; }
|
||||
virtual size_t XformCount() const override { return m_Ember.XformCount(); }
|
||||
virtual size_t TotalXformCount() const override { return m_Ember.TotalXformCount(); }
|
||||
virtual QString Name() const override { return QString::fromStdString(m_Ember.m_Name); }
|
||||
@ -365,8 +376,17 @@ public:
|
||||
virtual void Delete(const pair<size_t, QTreeWidgetItem*>& p) override;
|
||||
virtual void EmberTreeItemChanged(QTreeWidgetItem* item, int col) override;
|
||||
virtual void EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) override;
|
||||
virtual void RenderPreviews(uint start = UINT_MAX, uint end = UINT_MAX) override;
|
||||
virtual void StopPreviewRender() override;
|
||||
void RenderPreviews(QTreeWidget* tree, TreePreviewRenderer<T>* renderer, EmberFile<T>& file, uint start = UINT_MAX, uint end = UINT_MAX);
|
||||
virtual void RenderLibraryPreviews(uint start = UINT_MAX, uint end = UINT_MAX) override;
|
||||
virtual void RenderSequencePreviews(uint start = UINT_MAX, uint end = UINT_MAX) override;
|
||||
virtual void SequenceTreeItemChanged(QTreeWidgetItem* item, int col) override;
|
||||
virtual void StopLibraryPreviewRender() override;
|
||||
virtual void StopSequencePreviewRender() override;
|
||||
virtual void StopAllPreviewRenderers() override;
|
||||
virtual void FillSequenceTree() override;
|
||||
virtual void SequenceGenerateButtonClicked() override;
|
||||
virtual void SequenceSaveButtonClicked() override;
|
||||
virtual void SequenceOpenButtonClicked() override;
|
||||
|
||||
//Params.
|
||||
virtual void SetCenter(double x, double y) override;
|
||||
@ -504,13 +524,13 @@ private:
|
||||
bool SyncSizes();
|
||||
|
||||
//Templated members.
|
||||
bool m_PreviewRun = false;
|
||||
bool m_PreviewRunning = false;
|
||||
vector<T> m_TempOpacities;
|
||||
vector<T> m_NormalizedWeights;
|
||||
Ember<T> m_Ember;
|
||||
const void* m_EmberFilePointer = nullptr;
|
||||
EmberFile<T> m_EmberFile;
|
||||
EmberFile<T> m_SequenceFile;
|
||||
deque<Ember<T>> m_UndoList;
|
||||
vector<Xform<T>> m_CopiedXforms;
|
||||
Xform<T> m_CopiedFinalXform;
|
||||
@ -519,8 +539,115 @@ private:
|
||||
shared_ptr<VariationList<T>> m_VariationList;
|
||||
unique_ptr<SheepTools<T, float>> m_SheepTools;
|
||||
unique_ptr<GLEmberController<T>> m_GLController;
|
||||
unique_ptr<EmberNs::Renderer<T, float>> m_PreviewRenderer = make_unique<EmberNs::Renderer<T, float>>();
|
||||
QFuture<void> m_PreviewResult;
|
||||
std::function<void (uint, uint)> m_PreviewRenderFunc;
|
||||
unique_ptr<TreePreviewRenderer<T>> m_LibraryPreviewRenderer;
|
||||
unique_ptr<TreePreviewRenderer<T>> m_SequencePreviewRenderer;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Base class for encapsulating a preview renderer which will be used
|
||||
/// in such places as the main library tree, the sequence tree and the
|
||||
/// single preview thumbnail shown in the final render dialog.
|
||||
/// Derived classes will implement PreviewRenderFunc() to handle the rendering
|
||||
/// functionality specific to their previews.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
class PreviewRenderer
|
||||
{
|
||||
public:
|
||||
PreviewRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
void Render(uint start, uint end)
|
||||
{
|
||||
Stop();
|
||||
m_PreviewResult = QtConcurrent::run([&](uint s, uint e)
|
||||
{
|
||||
rlg l(m_PreviewCs);
|
||||
m_PreviewRun = true;
|
||||
PreviewRenderFunc(s, e);
|
||||
m_PreviewRun = false;
|
||||
}, start, end);
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
m_PreviewRun = false;
|
||||
m_PreviewRenderer.Abort();
|
||||
m_PreviewResult.cancel();
|
||||
|
||||
while (m_PreviewResult.isRunning())
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
bool EarlyClip()
|
||||
{
|
||||
return m_PreviewRenderer.EarlyClip();
|
||||
}
|
||||
|
||||
bool YAxisUp()
|
||||
{
|
||||
return m_PreviewRenderer.YAxisUp();
|
||||
}
|
||||
|
||||
bool Transparency()
|
||||
{
|
||||
return m_PreviewRenderer.Transparency();
|
||||
}
|
||||
|
||||
bool Running()
|
||||
{
|
||||
return m_PreviewRun || m_PreviewResult.isRunning();
|
||||
}
|
||||
|
||||
virtual void PreviewRenderFunc(uint start, uint end) {}
|
||||
|
||||
protected:
|
||||
volatile bool m_PreviewRun = false;
|
||||
Ember<T> m_PreviewEmber;
|
||||
vector<byte> m_PreviewFinalImage;
|
||||
EmberNs::Renderer<T, float> m_PreviewRenderer;
|
||||
|
||||
private:
|
||||
QFuture<void> m_PreviewResult;
|
||||
std::recursive_mutex m_PreviewCs;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Thin derivation to handle preview rendering multiple embers previews to a tree.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
class TreePreviewRenderer : public PreviewRenderer<T>
|
||||
{
|
||||
public:
|
||||
using PreviewRenderer<T>::m_PreviewRun;
|
||||
using PreviewRenderer<T>::m_PreviewEmber;
|
||||
using PreviewRenderer<T>::m_PreviewRenderer;
|
||||
using PreviewRenderer<T>::m_PreviewFinalImage;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TreePreviewRenderer{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="controller">A pointer to the controller this instance is a member of</param>
|
||||
/// <param name="tree">A pointer to the tree to render to</param>
|
||||
/// <param name="emberFile">A reference to the ember file to render</param>
|
||||
TreePreviewRenderer(FractoriumEmberController<T>* controller, QTreeWidget* tree, EmberFile<T>& emberFile) :
|
||||
m_Controller(controller),
|
||||
m_Tree(tree),
|
||||
m_EmberFile(emberFile)
|
||||
{
|
||||
auto f = m_Controller->m_Fractorium;
|
||||
m_PreviewRenderer.Callback(nullptr);
|
||||
m_PreviewRenderer.NumChannels(4);
|
||||
m_PreviewRenderer.EarlyClip(f->m_Settings->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(f->m_Settings->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(f->m_Settings->Transparency());
|
||||
}
|
||||
|
||||
virtual void PreviewRenderFunc(uint start, uint end) override;
|
||||
|
||||
protected:
|
||||
FractoriumEmberController<T>* m_Controller;
|
||||
QTreeWidget* m_Tree;
|
||||
EmberFile<T>& m_EmberFile;
|
||||
};
|
||||
|
@ -7,9 +7,34 @@
|
||||
void Fractorium::InitLibraryUI()
|
||||
{
|
||||
ui.LibraryTree->SetMainWindow(this);
|
||||
connect(ui.LibraryTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemChanged(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
connect(ui.LibraryTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
connect(ui.LibraryTree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
ui.SequenceFramesPerRotSpinBox->setValue(m_Settings->FramesPerRot());
|
||||
ui.SequenceRandomFramesPerRotMaxSpinBox->setValue(m_Settings->FramesPerRotMax());
|
||||
ui.SequenceRotationsSpinBox->setValue(m_Settings->Rotations());
|
||||
ui.SequenceRandomRotationsMaxSpinBox->setValue(m_Settings->RotationsMax());
|
||||
ui.SequenceBlendFramesSpinBox->setValue(m_Settings->BlendFrames());
|
||||
ui.SequenceRandomBlendMaxFramesSpinBox->setValue(m_Settings->BlendFramesMax());
|
||||
connect(ui.LibraryTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemChanged(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
connect(ui.LibraryTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
connect(ui.LibraryTree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnSequenceTreeItemChanged(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceStartPreviewsButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceStartPreviewsButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceStopPreviewsButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceStopPreviewsButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceAllButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceAllButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceGenerateButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceGenerateButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRenderButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceRenderButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceSaveButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceSaveButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceOpenButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceOpenButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRandomizeFramesPerRotCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSequenceRandomizeFramesPerRotCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRandomizeRotationsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSequenceRandomizeRotationsCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRandomizeBlendFramesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSequenceRandomizeBlendFramesCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceStartFlameSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceStartFlameSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceStopFlameSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceStopFlameSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceFramesPerRotSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceFramesPerRotSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRandomFramesPerRotMaxSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceRandomFramesPerRotMaxSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRotationsSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSequenceRotationsSpinBoxChanged(double)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRandomRotationsMaxSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSequenceRandomRotationsMaxSpinBoxChanged(double)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceBlendFramesSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceBlendFramesSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRandomBlendMaxFramesSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceRandomBlendMaxFramesSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -95,7 +120,7 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
|
||||
uint i = 0;
|
||||
auto tree = m_Fractorium->ui.LibraryTree;
|
||||
vector<byte> v(size * size * 4);
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
tree->clear();
|
||||
QCoreApplication::flush();
|
||||
tree->blockSignals(true);
|
||||
@ -125,8 +150,9 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
|
||||
if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(selectIndex)))
|
||||
emberItem->setSelected(true);
|
||||
|
||||
m_Fractorium->SyncFileCountToSequenceCount();
|
||||
QCoreApplication::flush();
|
||||
RenderPreviews(0, uint(m_EmberFile.Size()));
|
||||
RenderLibraryPreviews(0, uint(m_EmberFile.Size()));
|
||||
tree->expandAll();
|
||||
}
|
||||
|
||||
@ -162,8 +188,9 @@ void FractoriumEmberController<T>::UpdateLibraryTree()
|
||||
|
||||
//When adding elements, ensure all indices are sequential.
|
||||
SyncLibrary(eLibraryUpdate::INDEX);
|
||||
m_Fractorium->SyncFileCountToSequenceCount();
|
||||
tree->blockSignals(false);
|
||||
RenderPreviews(origChildCount, uint(m_EmberFile.Size()));
|
||||
RenderLibraryPreviews(origChildCount, uint(m_EmberFile.Size()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,6 +307,7 @@ void FractoriumEmberController<T>::Delete(const pair<size_t, QTreeWidgetItem*>&
|
||||
{
|
||||
delete p.second;
|
||||
SyncLibrary(eLibraryUpdate::INDEX);
|
||||
m_Fractorium->SyncFileCountToSequenceCount();
|
||||
}
|
||||
|
||||
//If there is now only one item left and it wasn't selected, select it.
|
||||
@ -308,13 +336,12 @@ void Fractorium::OnDelete(const pair<size_t, QTreeWidgetItem*>& p)
|
||||
/// <param name="start">The 0-based index to start rendering previews for</param>
|
||||
/// <param name="end">The 0-based index which is one beyond the last ember to render a preview for</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::RenderPreviews(uint start, uint end)
|
||||
void FractoriumEmberController<T>::RenderPreviews(QTreeWidget* tree, TreePreviewRenderer<T>* renderer, EmberFile<T>& file, uint start, uint end)
|
||||
{
|
||||
StopPreviewRender();
|
||||
renderer->Stop();
|
||||
|
||||
if (start == UINT_MAX && end == UINT_MAX)
|
||||
{
|
||||
auto tree = m_Fractorium->ui.LibraryTree;
|
||||
tree->blockSignals(true);
|
||||
|
||||
if (auto top = tree->topLevelItem(0))
|
||||
@ -323,36 +350,401 @@ void FractoriumEmberController<T>::RenderPreviews(uint start, uint end)
|
||||
vector<byte> emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 4);
|
||||
|
||||
for (int i = 0; i < childCount; i++)
|
||||
if (auto treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
|
||||
if (auto treeItem = dynamic_cast<EmberTreeWidgetItemBase*>(top->child(i)))
|
||||
treeItem->SetImage(emptyPreview, PREVIEW_SIZE, PREVIEW_SIZE);
|
||||
}
|
||||
|
||||
tree->blockSignals(false);
|
||||
m_PreviewResult = QtConcurrent::run(m_PreviewRenderFunc, 0, uint(m_EmberFile.Size()));
|
||||
renderer->Render(0, uint(file.Size()));
|
||||
}
|
||||
else
|
||||
m_PreviewResult = QtConcurrent::run(m_PreviewRenderFunc, start, end);
|
||||
renderer->Render(start, end);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the preview rendering thread.
|
||||
/// Wrapper around calling RenderPreviews with the appropriate values passed in for the previews in the main library tree.
|
||||
/// </summary>
|
||||
/// <param name="start">The 0-based index to start rendering previews for</param>
|
||||
/// <param name="end">The 0-based index which is one beyond the last ember to render a preview for</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::RenderLibraryPreviews(uint start, uint end)
|
||||
{
|
||||
RenderPreviews(m_Fractorium->ui.LibraryTree, m_LibraryPreviewRenderer.get(), m_EmberFile, start, end);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::StopLibraryPreviewRender() { m_LibraryPreviewRenderer->Stop(); }
|
||||
|
||||
/// <summary>
|
||||
/// Thing wrapper around StopLibraryPreviewRender() and StopSequencePreviewRender() to stop both preview renderers.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::StopPreviewRender()
|
||||
void FractoriumEmberController<T>::StopAllPreviewRenderers()
|
||||
{
|
||||
m_PreviewRun = false;
|
||||
m_PreviewRenderer->Abort();
|
||||
StopLibraryPreviewRender();
|
||||
StopSequencePreviewRender();
|
||||
}
|
||||
|
||||
while (m_PreviewRunning)
|
||||
QApplication::processEvents();
|
||||
|
||||
m_PreviewResult.cancel();
|
||||
|
||||
while (m_PreviewResult.isRunning())
|
||||
QApplication::processEvents();
|
||||
|
||||
QCoreApplication::sendPostedEvents(m_Fractorium->ui.LibraryTree);
|
||||
/// <summary>
|
||||
/// Fill the sequence tree with the names of the embers in the
|
||||
/// currently generated sequence.
|
||||
/// Start the sequence preview render thread.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillSequenceTree()
|
||||
{
|
||||
uint size = 64;
|
||||
uint i = 0;
|
||||
auto tree = m_Fractorium->ui.SequenceTree;
|
||||
vector<byte> v(size * size * 4);
|
||||
m_SequencePreviewRenderer->Stop();
|
||||
tree->clear();
|
||||
QCoreApplication::flush();
|
||||
tree->blockSignals(true);
|
||||
auto fileItem = new QTreeWidgetItem(tree);
|
||||
QFileInfo info(m_SequenceFile.m_Filename);
|
||||
fileItem->setText(0, info.fileName());
|
||||
fileItem->setToolTip(0, m_SequenceFile.m_Filename);
|
||||
fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
|
||||
|
||||
for (auto& it : m_SequenceFile.m_Embers)
|
||||
{
|
||||
auto emberItem = new EmberTreeWidgetItemBase(fileItem);
|
||||
|
||||
if (it.m_Name.empty())
|
||||
emberItem->setText(0, ToString(i++));
|
||||
else
|
||||
emberItem->setText(0, it.m_Name.c_str());
|
||||
|
||||
emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||
emberItem->setToolTip(0, emberItem->text(0));
|
||||
emberItem->SetImage(v, size, size);
|
||||
}
|
||||
|
||||
tree->blockSignals(false);
|
||||
QCoreApplication::flush();
|
||||
RenderSequencePreviews(0, uint(m_SequenceFile.Size()));
|
||||
tree->expandAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the text of the root item to the name of the sequence file.
|
||||
/// Called whenever the text of the root item is changed.
|
||||
/// </summary>
|
||||
/// <param name="item">The root sequence tree item which changed</param>
|
||||
/// <param name="col">The column clicked, ignored.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SequenceTreeItemChanged(QTreeWidgetItem* item, int col)
|
||||
{
|
||||
if (auto parentItem = dynamic_cast<QTreeWidgetItem*>(item))
|
||||
{
|
||||
QString text = parentItem->text(0);
|
||||
|
||||
if (text != "")
|
||||
m_SequenceFile.m_Filename = text;
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceTreeItemChanged(QTreeWidgetItem* item, int col) { m_Controller->SequenceTreeItemChanged(item, col); }
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around calling RenderPreviews with the appropriate values passed in for the previews in the sequence tree.
|
||||
/// Called when Render Previews is clicked.
|
||||
/// </summary>
|
||||
/// <param name="start">Ignored, render all.</param>
|
||||
/// <param name="end">Ignored, render all.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::RenderSequencePreviews(uint start, uint end) { RenderPreviews(m_Fractorium->ui.SequenceTree, m_SequencePreviewRenderer.get(), m_SequenceFile, start, end); }
|
||||
void Fractorium::OnSequenceStartPreviewsButtonClicked(bool checked) { m_Controller->RenderSequencePreviews(); }
|
||||
|
||||
/// <summary>
|
||||
/// Stop rendering the sequence previews.
|
||||
/// Called when Stop Previews is clicked.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::StopSequencePreviewRender() { m_SequencePreviewRenderer->Stop(); }
|
||||
void Fractorium::OnSequenceStopPreviewsButtonClicked(bool checked) { m_Controller->StopSequencePreviewRender(); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the start and stop spin boxes to 0 and the length of the ember file minus 1, respectively.
|
||||
/// Called whenever the count of the current file changes or when All is clicked.
|
||||
/// </summary>
|
||||
void Fractorium::SyncFileCountToSequenceCount()
|
||||
{
|
||||
if (auto top = ui.LibraryTree->topLevelItem(0))
|
||||
{
|
||||
int count = top->childCount() - 1;
|
||||
ui.SequenceStartFlameSpinBox->setMinimum(0);
|
||||
ui.SequenceStartFlameSpinBox->setMaximum(count);
|
||||
ui.SequenceStartFlameSpinBox->setValue(0);
|
||||
ui.SequenceStopFlameSpinBox->setMinimum(0);
|
||||
ui.SequenceStopFlameSpinBox->setMaximum(count);
|
||||
ui.SequenceStopFlameSpinBox->setValue(count);
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceAllButtonClicked(bool checked) { SyncFileCountToSequenceCount(); }
|
||||
|
||||
/// <summary>
|
||||
/// Generate an animation sequence and place it in the sequence tree. This code is
|
||||
/// mostly similar to that of EmberGenome.
|
||||
/// It differs in a few ways:
|
||||
/// The number of frames used in a rotation and in blending can differ. In EmberGenome, they are the same.
|
||||
/// The number of rotations, frames used in rotations and frames used in blending can all be randomized.
|
||||
/// Called when the Generate button is clicked.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SequenceGenerateButtonClicked()
|
||||
{
|
||||
StopAllPreviewRenderers();
|
||||
SaveCurrentToOpenedFile(false);
|
||||
Ember<T> result;
|
||||
auto& ui = m_Fractorium->ui;
|
||||
auto s = m_Fractorium->m_Settings;
|
||||
bool randStagger = ui.SequenceRandomizeStaggerCheckBox->isChecked();
|
||||
bool randFramesRot = ui.SequenceRandomizeFramesPerRotCheckBox->isChecked();
|
||||
bool randRot = ui.SequenceRandomizeRotationsCheckBox->isChecked();
|
||||
bool randBlend = ui.SequenceRandomizeBlendFramesCheckBox->isChecked();
|
||||
bool stagger = ui.SequenceStaggerCheckBox->isChecked();
|
||||
double rots = ui.SequenceRotationsSpinBox->value();
|
||||
double rotsMax = ui.SequenceRandomRotationsMaxSpinBox->value();
|
||||
int framesPerRot = ui.SequenceFramesPerRotSpinBox->value();
|
||||
int framesPerRotMax = ui.SequenceRandomFramesPerRotMaxSpinBox->value();
|
||||
int framesBlend = ui.SequenceBlendFramesSpinBox->value();
|
||||
int framesBlendMax = ui.SequenceRandomBlendMaxFramesSpinBox->value();
|
||||
size_t start = ui.SequenceStartFlameSpinBox->value();
|
||||
size_t stop = ui.SequenceStopFlameSpinBox->value();
|
||||
size_t startCount = ui.SequenceStartCountSpinBox->value();
|
||||
size_t keyFrames = (stop - start) + 1;
|
||||
size_t frameCount = 0;
|
||||
double frames = 0;
|
||||
vector<pair<size_t, size_t>> devices;//Dummy.
|
||||
EmberReport emberReport;
|
||||
ostringstream os;
|
||||
string palettePath =
|
||||
#ifdef _WIN32
|
||||
"./flam3-palettes.xml";
|
||||
#else
|
||||
"~/.config/fractorium";
|
||||
#endif
|
||||
SheepTools<T, float> tools(palettePath, EmberCommon::CreateRenderer<T>(eRendererType::CPU_RENDERER, devices, false, 0, emberReport));
|
||||
tools.SetSpinParams(true,
|
||||
randStagger ? m_Rand.RandBit() : stagger,
|
||||
0,
|
||||
0,
|
||||
s->Nick().toStdString(),
|
||||
s->Url().toStdString(),
|
||||
s->Id().toStdString(),
|
||||
"",
|
||||
0,
|
||||
0);
|
||||
|
||||
if (randFramesRot)
|
||||
frames = ui.SequenceRandomFramesPerRotMaxSpinBox->value();
|
||||
else
|
||||
frames = ui.SequenceFramesPerRotSpinBox->value();
|
||||
|
||||
if (randRot)
|
||||
frames *= ui.SequenceRandomRotationsMaxSpinBox->value();
|
||||
else
|
||||
frames *= ui.SequenceRotationsSpinBox->value();
|
||||
|
||||
if (randBlend)
|
||||
frames += ui.SequenceRandomBlendMaxFramesSpinBox->value();
|
||||
else
|
||||
frames += ui.SequenceBlendFramesSpinBox->value();
|
||||
|
||||
frames *= keyFrames;
|
||||
frames += startCount;
|
||||
os << setfill('0') << setprecision(0) << fixed;
|
||||
m_SequenceFile.Clear();
|
||||
m_SequenceFile.m_Filename = EmberFile<T>::DefaultFilename("Sequence_");
|
||||
double blend;
|
||||
size_t frame;
|
||||
Ember<T> embers[2];//Spin needs contiguous array below, and this will also get modified, so a copy is needed to avoid modifying the embers in the original file.
|
||||
auto padding = streamsize(std::log10(frames)) + 1;
|
||||
auto it = Advance(m_EmberFile.m_Embers.begin(), start);
|
||||
|
||||
for (size_t i = start; i <= stop && it != m_EmberFile.m_Embers.end(); i++, ++it)
|
||||
{
|
||||
double rotations = randRot ? m_Rand.Frand<double>(rots, rotsMax) : rots;
|
||||
embers[0] = *it;
|
||||
|
||||
if (rotations > 0)
|
||||
{
|
||||
double rotFrames = randFramesRot ? m_Rand.Frand<double>(framesPerRot, framesPerRotMax) : framesPerRot;
|
||||
size_t roundFrames = size_t(std::round(rotFrames * rotations));
|
||||
|
||||
for (frame = 0; frame < roundFrames; frame++)
|
||||
{
|
||||
blend = frame / rotFrames;
|
||||
tools.Spin(embers[0], nullptr, result, startCount + frameCount++, blend);//Result is cleared and reassigned each time inside of Spin().
|
||||
FormatName(result, os, padding);
|
||||
m_SequenceFile.m_Embers.push_back(result);
|
||||
}
|
||||
|
||||
//The loop above will have rotated just shy of a complete rotation.
|
||||
//Rotate the next step and save in result, but do not print.
|
||||
//result will be the starting point for the interp phase below.
|
||||
frame = roundFrames;
|
||||
blend = frame / rotFrames;
|
||||
tools.Spin(embers[0], nullptr, result, startCount + frameCount, blend);//Do not increment frameCount here.
|
||||
FormatName(result, os, padding);
|
||||
}
|
||||
|
||||
if (i < stop)
|
||||
{
|
||||
if (rotations > 0)//Store the last result as the flame to interpolate from. This applies for whole or fractional values of opt.Loops().
|
||||
embers[0] = result;
|
||||
|
||||
auto it2 = it;//Need a quick temporary to avoid modifying it which is used in the loop.
|
||||
embers[1] = *(++it2);//Get the next ember to be used with blending below.
|
||||
size_t blendFrames = randBlend ? m_Rand.Frand<double>(framesBlend, framesBlendMax) : framesBlend;
|
||||
|
||||
for (frame = 0; frame < blendFrames; frame++)
|
||||
{
|
||||
bool seqFlag = frame == 0 || (frame == blendFrames - 1);
|
||||
blend = frame / double(blendFrames);
|
||||
result.Clear();
|
||||
|
||||
if (randStagger)
|
||||
tools.Stagger(m_Rand.RandBit());
|
||||
|
||||
tools.SpinInter(&embers[0], nullptr, result, startCount + frameCount++, seqFlag, blend);
|
||||
FormatName(result, os, padding);
|
||||
m_SequenceFile.m_Embers.push_back(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it = Advance(m_EmberFile.m_Embers.begin(), stop);
|
||||
tools.Spin(*it, nullptr, result, startCount + frameCount, 0);
|
||||
FormatName(result, os, padding);
|
||||
m_SequenceFile.m_Embers.push_back(result);
|
||||
FillSequenceTree();//The sequence has been generated, now create preview thumbnails.
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceGenerateButtonClicked(bool checked) { m_Controller->SequenceGenerateButtonClicked(); }
|
||||
|
||||
/// <summary>
|
||||
/// Show the final render dialog and load the sequence into it.
|
||||
/// This will automatically check the Render All and Render as Animation sequence checkboxes.
|
||||
/// Called when the Render Sequence button is clicked.
|
||||
/// </summary>
|
||||
/// <param name="checked">Ignored.</param>
|
||||
void Fractorium::OnSequenceRenderButtonClicked(bool checked)
|
||||
{
|
||||
//First completely stop what the current rendering process is doing.
|
||||
m_Controller->DeleteRenderer();//Delete the renderer, but not the controller.
|
||||
m_Controller->StopAllPreviewRenderers();
|
||||
m_Controller->SaveCurrentToOpenedFile(false);//Save whatever was edited back to the current open file.
|
||||
m_RenderStatusLabel->setText("Renderer stopped.");
|
||||
m_FinalRenderDialog->Show(true);//Show with a bool specifying that it came from the sequence generator.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the sequence to a file.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SequenceSaveButtonClicked()
|
||||
{
|
||||
auto s = m_Fractorium->m_Settings;
|
||||
QString filename = m_Fractorium->SetupSaveXmlDialog(m_SequenceFile.m_Filename);
|
||||
|
||||
if (filename != "")
|
||||
{
|
||||
EmberToXml<T> writer;
|
||||
QFileInfo fileInfo(filename);
|
||||
|
||||
if (writer.Save(filename.toStdString().c_str(), m_SequenceFile.m_Embers, 0, true, true))
|
||||
s->SaveFolder(fileInfo.canonicalPath());
|
||||
else
|
||||
m_Fractorium->ShowCritical("Save Failed", "Could not save sequence file, try saving to a different folder.");
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceSaveButtonClicked(bool checked) { m_Controller->SequenceSaveButtonClicked(); }
|
||||
|
||||
/// <summary>
|
||||
/// Open one or more sequence file, concatenate them all, place them in the sequence
|
||||
/// tree and begin rendering the sequence previews.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SequenceOpenButtonClicked()
|
||||
{
|
||||
m_SequencePreviewRenderer->Stop();
|
||||
auto filenames = m_Fractorium->SetupOpenXmlDialog();
|
||||
|
||||
if (!filenames.empty())
|
||||
{
|
||||
size_t i;
|
||||
EmberFile<T> emberFile;
|
||||
XmlToEmber<T> parser;
|
||||
vector<Ember<T>> embers;
|
||||
vector<string> errors;
|
||||
emberFile.m_Filename = filenames[0];
|
||||
|
||||
for (auto& filename : filenames)
|
||||
{
|
||||
embers.clear();
|
||||
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers) && !embers.empty())
|
||||
{
|
||||
for (i = 0; i < embers.size(); i++)
|
||||
if (embers[i].m_Name == "" || embers[i].m_Name == "No name")//Ensure it has a name.
|
||||
embers[i].m_Name = ToString<qulonglong>(i).toStdString();
|
||||
|
||||
emberFile.m_Embers.insert(emberFile.m_Embers.end(), embers.begin(), embers.end());
|
||||
errors = parser.ErrorReport();
|
||||
}
|
||||
else
|
||||
{
|
||||
errors = parser.ErrorReport();
|
||||
m_Fractorium->ShowCritical("Open Failed", "Could not open sequence file, see info tab for details.");
|
||||
}
|
||||
|
||||
if (!errors.empty())
|
||||
m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit, false);//Concat errors from all files.
|
||||
}
|
||||
|
||||
if (emberFile.Size() > 0)//Ensure at least something was read.
|
||||
{
|
||||
emberFile.MakeNamesUnique();
|
||||
m_SequenceFile = std::move(emberFile);//Move the temp to avoid creating dupes because we no longer need it.
|
||||
FillSequenceTree();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceOpenButtonClicked(bool checked) { m_Controller->SequenceOpenButtonClicked(); }
|
||||
|
||||
void Fractorium::OnSequenceRandomizeFramesPerRotCheckBoxStateChanged(int state) { ui.SequenceRandomFramesPerRotMaxSpinBox->setEnabled(state); }
|
||||
void Fractorium::OnSequenceRandomizeRotationsCheckBoxStateChanged(int state) { ui.SequenceRandomRotationsMaxSpinBox->setEnabled(state); }
|
||||
void Fractorium::OnSequenceRandomizeBlendFramesCheckBoxStateChanged(int state) { ui.SequenceRandomBlendMaxFramesSpinBox->setEnabled(state); }
|
||||
|
||||
/// <summary>
|
||||
/// Constrain all min/max spinboxes.
|
||||
/// </summary>
|
||||
void Fractorium::OnSequenceStartFlameSpinBoxChanged(int d) { ConstrainLow(ui.SequenceStartFlameSpinBox, ui.SequenceStopFlameSpinBox); }
|
||||
void Fractorium::OnSequenceStopFlameSpinBoxChanged(int d) { ConstrainHigh(ui.SequenceStartFlameSpinBox, ui.SequenceStopFlameSpinBox); }
|
||||
void Fractorium::OnSequenceFramesPerRotSpinBoxChanged(int d) { if (ui.SequenceRandomizeFramesPerRotCheckBox->isChecked()) ConstrainLow(ui.SequenceFramesPerRotSpinBox, ui.SequenceRandomFramesPerRotMaxSpinBox); }
|
||||
void Fractorium::OnSequenceRandomFramesPerRotMaxSpinBoxChanged(int d) { ConstrainHigh(ui.SequenceFramesPerRotSpinBox, ui.SequenceRandomFramesPerRotMaxSpinBox); }
|
||||
void Fractorium::OnSequenceRotationsSpinBoxChanged(double d) { if (ui.SequenceRandomizeRotationsCheckBox->isChecked()) ConstrainLow(ui.SequenceRotationsSpinBox, ui.SequenceRandomRotationsMaxSpinBox); }
|
||||
void Fractorium::OnSequenceRandomRotationsMaxSpinBoxChanged(double d) { ConstrainHigh(ui.SequenceRotationsSpinBox, ui.SequenceRandomRotationsMaxSpinBox); }
|
||||
void Fractorium::OnSequenceBlendFramesSpinBoxChanged(int d) { if (ui.SequenceRandomizeBlendFramesCheckBox->isChecked()) ConstrainLow(ui.SequenceBlendFramesSpinBox, ui.SequenceRandomBlendMaxFramesSpinBox); }
|
||||
void Fractorium::OnSequenceRandomBlendMaxFramesSpinBoxChanged(int d) { ConstrainHigh(ui.SequenceBlendFramesSpinBox, ui.SequenceRandomBlendMaxFramesSpinBox); }
|
||||
|
||||
/// <summary>
|
||||
/// Save all sequence settings to match the values in the controls.
|
||||
/// </summary>
|
||||
void Fractorium::SyncSequenceSettings()
|
||||
{
|
||||
m_Settings->FramesPerRot(ui.SequenceFramesPerRotSpinBox->value());
|
||||
m_Settings->FramesPerRotMax(ui.SequenceRandomFramesPerRotMaxSpinBox->value());
|
||||
m_Settings->Rotations(ui.SequenceRotationsSpinBox->value());
|
||||
m_Settings->RotationsMax(ui.SequenceRandomRotationsMaxSpinBox->value());
|
||||
m_Settings->BlendFrames(ui.SequenceBlendFramesSpinBox->value());
|
||||
m_Settings->BlendFramesMax(ui.SequenceRandomBlendMaxFramesSpinBox->value());
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
|
@ -52,7 +52,7 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::NewFlock(size_t count)
|
||||
{
|
||||
Ember<T> ember;
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
m_EmberFile.Clear();
|
||||
m_EmberFile.m_Filename = EmberFile<T>::DefaultFilename();
|
||||
|
||||
@ -91,7 +91,7 @@ void FractoriumEmberController<T>::NewEmptyFlameInCurrentFile()
|
||||
Ember<T> ember;
|
||||
Xform<T> xform;
|
||||
QDateTime local(QDateTime::currentDateTime());
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
ParamsToEmber(ember);
|
||||
xform.m_Weight = T(0.25);
|
||||
xform.m_ColorX = m_Rand.Frand01<T>();
|
||||
@ -116,7 +116,7 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::NewRandomFlameInCurrentFile()
|
||||
{
|
||||
Ember<T> ember;
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<int>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, MAX_CL_VARS);
|
||||
ParamsToEmber(ember);
|
||||
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
|
||||
@ -138,7 +138,7 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::CopyFlameInCurrentFile()
|
||||
{
|
||||
auto ember = m_Ember;
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
|
||||
ember.m_Index = m_EmberFile.Size();
|
||||
m_EmberFile.m_Embers.push_back(ember);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync.
|
||||
@ -172,7 +172,7 @@ void FractoriumEmberController<T>::OpenAndPrepFiles(const QStringList& filenames
|
||||
vector<Ember<T>> embers;
|
||||
vector<string> errors;
|
||||
uint previousSize = append ? uint(m_EmberFile.Size()) : 0u;
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
emberFile.m_Filename = filenames[0];
|
||||
|
||||
for (auto& filename : filenames)
|
||||
@ -377,7 +377,7 @@ uint FractoriumEmberController<T>::SaveCurrentToOpenedFile(bool render)
|
||||
uint i = 0;
|
||||
bool fileFound = false;
|
||||
|
||||
if (!m_PreviewRunning)
|
||||
if (!m_LibraryPreviewRenderer->Running())
|
||||
{
|
||||
for (auto& it : m_EmberFile.m_Embers)
|
||||
{
|
||||
@ -393,7 +393,7 @@ uint FractoriumEmberController<T>::SaveCurrentToOpenedFile(bool render)
|
||||
|
||||
if (!fileFound)
|
||||
{
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
m_EmberFile.m_Embers.push_back(m_Ember);
|
||||
m_EmberFile.MakeNamesUnique();
|
||||
|
||||
@ -401,7 +401,7 @@ uint FractoriumEmberController<T>::SaveCurrentToOpenedFile(bool render)
|
||||
UpdateLibraryTree();
|
||||
}
|
||||
else if (render)
|
||||
RenderPreviews(i, i + 1);
|
||||
RenderLibraryPreviews(i, i + 1);
|
||||
}
|
||||
|
||||
return i;
|
||||
@ -532,7 +532,7 @@ void FractoriumEmberController<T>::PasteXmlAppend()
|
||||
}
|
||||
|
||||
b.clear();
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", embers);
|
||||
errors = parser.ErrorReportString();
|
||||
|
||||
@ -586,7 +586,7 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
}
|
||||
|
||||
b.clear();
|
||||
StopPreviewRender();
|
||||
StopAllPreviewRenderers();
|
||||
m_EmberFile.m_Embers.clear();//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync.
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", m_EmberFile.m_Embers);
|
||||
errors = parser.ErrorReportString();
|
||||
@ -812,14 +812,14 @@ void Fractorium::OnActionClearFlame(bool checked) { m_Controller->ClearFlame();
|
||||
/// </summary>
|
||||
void Fractorium::OnActionRenderPreviews(bool checked)
|
||||
{
|
||||
m_Controller->RenderPreviews();
|
||||
m_Controller->RenderLibraryPreviews();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop all previews from being rendered. This is handy if the user
|
||||
/// opens a large file with many embers in it, such as an animation sequence.
|
||||
/// </summary>
|
||||
void Fractorium::OnActionStopRenderingPreviews(bool checked) { m_Controller->StopPreviewRender(); }
|
||||
void Fractorium::OnActionStopRenderingPreviews(bool checked) { m_Controller->StopLibraryPreviewRender(); }
|
||||
|
||||
/// <summary>
|
||||
/// Show the final render dialog as a modeless dialog to allow
|
||||
@ -832,10 +832,10 @@ void Fractorium::OnActionFinalRender(bool checked)
|
||||
{
|
||||
//First completely stop what the current rendering process is doing.
|
||||
m_Controller->DeleteRenderer();//Delete the renderer, but not the controller.
|
||||
m_Controller->StopPreviewRender();
|
||||
m_Controller->StopAllPreviewRenderers();
|
||||
m_Controller->SaveCurrentToOpenedFile(false);//Save whatever was edited back to the current open file.
|
||||
m_RenderStatusLabel->setText("Renderer stopped.");
|
||||
m_FinalRenderDialog->show();
|
||||
m_FinalRenderDialog->Show(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -24,7 +24,7 @@ void Fractorium::InitParamsUI()
|
||||
//Color.
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.05, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(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_HighlightSpin, spinHeight, 1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, -1.0, -1.0, -1.0);
|
||||
m_GammaThresholdSpin->setDecimals(4);
|
||||
@ -469,19 +469,17 @@ void Fractorium::OnTemporalFilterTypeComboCurrentIndexChanged(const QString& tex
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::DEFilterMinRadiusWidthChanged(double d)
|
||||
{
|
||||
if (m_Fractorium->m_DEFilterMinRadiusSpin->value() > m_Fractorium->m_DEFilterMaxRadiusSpin->value())
|
||||
{
|
||||
m_Fractorium->m_DEFilterMinRadiusSpin->SetValueStealth(m_Fractorium->m_DEFilterMaxRadiusSpin->value());
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateAll([&](Ember<T>& ember)
|
||||
{
|
||||
ember.m_MinRadDE = d;
|
||||
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
void Fractorium::OnDEFilterMinRadiusWidthChanged(double d) { m_Controller->DEFilterMinRadiusWidthChanged(d); }
|
||||
void Fractorium::OnDEFilterMinRadiusWidthChanged(double d)
|
||||
{
|
||||
if (!ConstrainLow(m_DEFilterMinRadiusSpin, m_DEFilterMaxRadiusSpin))
|
||||
m_Controller->DEFilterMinRadiusWidthChanged(d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the density estimation filter max radius value.
|
||||
@ -491,19 +489,17 @@ void Fractorium::OnDEFilterMinRadiusWidthChanged(double d) { m_Controller->DEFil
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::DEFilterMaxRadiusWidthChanged(double d)
|
||||
{
|
||||
if (m_Fractorium->m_DEFilterMaxRadiusSpin->value() < m_Fractorium->m_DEFilterMinRadiusSpin->value())
|
||||
{
|
||||
m_Fractorium->m_DEFilterMaxRadiusSpin->SetValueStealth(m_Fractorium->m_DEFilterMinRadiusSpin->value());
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateAll([&](Ember<T>& ember)
|
||||
{
|
||||
ember.m_MaxRadDE = d;
|
||||
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
void Fractorium::OnDEFilterMaxRadiusWidthChanged(double d) { m_Controller->DEFilterMaxRadiusWidthChanged(d); }
|
||||
void Fractorium::OnDEFilterMaxRadiusWidthChanged(double d)
|
||||
{
|
||||
if (!ConstrainHigh(m_DEFilterMinRadiusSpin, m_DEFilterMaxRadiusSpin))
|
||||
m_Controller->DEFilterMaxRadiusWidthChanged(d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the density estimation filter curve value.
|
||||
|
@ -85,4 +85,6 @@
|
||||
using namespace std;
|
||||
using namespace EmberNs;
|
||||
using namespace EmberCLns;
|
||||
using namespace EmberCommon;
|
||||
|
||||
#endif
|
||||
|
@ -580,13 +580,11 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
else
|
||||
m_Renderer->InteractiveFilter(s->OpenCLDEFilter() ? eInteractiveFilter::FILTER_DE : eInteractiveFilter::FILTER_LOG);
|
||||
|
||||
if ((m_Renderer->EarlyClip() != m_PreviewRenderer->EarlyClip()) ||
|
||||
(m_Renderer->YAxisUp() != m_PreviewRenderer->YAxisUp()))
|
||||
if ((m_Renderer->EarlyClip() != m_LibraryPreviewRenderer->EarlyClip()) ||
|
||||
(m_Renderer->YAxisUp() != m_LibraryPreviewRenderer->YAxisUp()) ||
|
||||
(m_Renderer->Transparency() != m_LibraryPreviewRenderer->Transparency()))
|
||||
{
|
||||
StopPreviewRender();
|
||||
m_PreviewRenderer->EarlyClip(m_Renderer->EarlyClip());
|
||||
m_PreviewRenderer->YAxisUp(m_Renderer->YAxisUp());
|
||||
RenderPreviews();
|
||||
RenderLibraryPreviews();
|
||||
}
|
||||
|
||||
m_FailedRenders = 0;
|
||||
@ -690,7 +688,7 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
if (m_Controller.get())
|
||||
{
|
||||
scale = m_Controller->LockedScale();
|
||||
m_Controller->StopPreviewRender();//Must stop any previews first, else changing controllers will crash the program and SaveCurrentToOpenedFile() will return 0.
|
||||
m_Controller->StopAllPreviewRenderers();//Must stop any previews first, else changing controllers will crash the program and SaveCurrentToOpenedFile() will return 0.
|
||||
current = m_Controller->SaveCurrentToOpenedFile(false);
|
||||
m_Controller->CopyTempPalette(tempPalette);//Convert float to double or save double verbatim;
|
||||
//Replace below with this once LLVM fixes a crash in their compiler with default lambda parameters.//TODO
|
||||
@ -698,10 +696,10 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
//m_Controller->CopyEmberFile(efd);
|
||||
#ifdef DO_DOUBLE
|
||||
m_Controller->CopyEmber(ed, [&](Ember<double>& ember) { });
|
||||
m_Controller->CopyEmberFile(efd, [&](Ember<double>& ember) { });
|
||||
m_Controller->CopyEmberFile(efd, false, [&](Ember<double>& ember) { });
|
||||
#else
|
||||
m_Controller->CopyEmber(ed, [&](Ember<float>& ember) { });
|
||||
m_Controller->CopyEmberFile(efd, [&](Ember<float>& ember) { });
|
||||
m_Controller->CopyEmberFile(efd, false, [&](Ember<float>& ember) { });
|
||||
#endif
|
||||
m_Controller->Shutdown();
|
||||
}
|
||||
@ -718,7 +716,7 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
if (m_Controller.get())
|
||||
{
|
||||
ed.m_Palette = tempPalette;//Restore base temp palette. Adjustments will be then be applied and stored back in in m_Ember.m_Palette below.
|
||||
m_Controller->SetEmberFile(efd);
|
||||
m_Controller->SetEmberFile(efd, true);
|
||||
m_Controller->SetEmber(current, true);
|
||||
m_Controller->LockedScale(scale);
|
||||
//Setting these and updating the GUI overwrites the work of clearing them done in SetEmber() above.
|
||||
|
@ -134,6 +134,51 @@ void FractoriumSettings::OpenCLSubBatch(uint i) { setValue(OPENCLSUBBATCH,
|
||||
uint FractoriumSettings::RandomCount() { return value(RANDOMCOUNT).toUInt(); }
|
||||
void FractoriumSettings::RandomCount(uint i) { setValue(RANDOMCOUNT, i); }
|
||||
|
||||
/// <summary>
|
||||
/// Sequence generation settings.
|
||||
/// </summary>
|
||||
|
||||
uint FractoriumSettings::FramesPerRot() { return value(FRAMESPERROT).toUInt(); }
|
||||
void FractoriumSettings::FramesPerRot(uint i) { setValue(FRAMESPERROT, i); }
|
||||
uint FractoriumSettings::FramesPerRotMax() { return value(FRAMESPERROTMAX).toUInt(); }
|
||||
void FractoriumSettings::FramesPerRotMax(uint i) { setValue(FRAMESPERROTMAX, i); }
|
||||
uint FractoriumSettings::Rotations() { return value(ROTATIONS).toUInt(); }
|
||||
void FractoriumSettings::Rotations(uint i) { setValue(ROTATIONS, i); }
|
||||
uint FractoriumSettings::RotationsMax() { return value(ROTATIONSMAX).toUInt(); }
|
||||
void FractoriumSettings::RotationsMax(uint i) { setValue(ROTATIONSMAX, i); }
|
||||
uint FractoriumSettings::BlendFrames() { return value(BLENDFRAMES).toUInt(); }
|
||||
void FractoriumSettings::BlendFrames(uint i) { setValue(BLENDFRAMES, i); }
|
||||
uint FractoriumSettings::BlendFramesMax() { return value(BLENDFRAMESMAX).toUInt(); }
|
||||
void FractoriumSettings::BlendFramesMax(uint i) { setValue(BLENDFRAMESMAX, i); }
|
||||
|
||||
/// <summary>
|
||||
/// Variations filter settings.
|
||||
/// </summary>
|
||||
|
||||
int FractoriumSettings::VarFilterSum() { return value(VARFILTERSUM).toInt(); }
|
||||
void FractoriumSettings::VarFilterSum(int i) { setValue(VARFILTERSUM, i); }
|
||||
|
||||
int FractoriumSettings::VarFilterAssign() { return value(VARFILTERASSIGN).toInt(); }
|
||||
void FractoriumSettings::VarFilterAssign(int i) { setValue(VARFILTERASSIGN, i); }
|
||||
|
||||
int FractoriumSettings::VarFilterPpsum() { return value(VARFILTERPPSUM).toInt(); }
|
||||
void FractoriumSettings::VarFilterPpsum(int i) { setValue(VARFILTERPPSUM, i); }
|
||||
|
||||
int FractoriumSettings::VarFilterPpassign() { return value(VARFILTERPPASSIGN).toInt(); }
|
||||
void FractoriumSettings::VarFilterPpassign(int i) { setValue(VARFILTERPPASSIGN, i); }
|
||||
|
||||
int FractoriumSettings::VarFilterSdc() { return value(VARFILTERSDC).toInt(); }
|
||||
void FractoriumSettings::VarFilterSdc(int i) { setValue(VARFILTERSDC, i); }
|
||||
|
||||
int FractoriumSettings::VarFilterState() { return value(VARFILTERSTATE).toInt(); }
|
||||
void FractoriumSettings::VarFilterState(int i) { setValue(VARFILTERSTATE, i); }
|
||||
|
||||
int FractoriumSettings::VarFilterParam() { return value(VARFILTERPARAM).toInt(); }
|
||||
void FractoriumSettings::VarFilterParam(int i) { setValue(VARFILTERPARAM, i); }
|
||||
|
||||
int FractoriumSettings::VarFilterNonparam() { return value(VARFILTERNONPARAM).toInt(); }
|
||||
void FractoriumSettings::VarFilterNonparam(int i) { setValue(VARFILTERNONPARAM, i); }
|
||||
|
||||
/// <summary>
|
||||
/// Final render settings.
|
||||
/// </summary>
|
||||
|
@ -21,12 +21,19 @@
|
||||
#define OPENCLSUBBATCH "render/openclsubbatch"
|
||||
#define RANDOMCOUNT "render/randomcount"
|
||||
|
||||
#define FRAMESPERROT "sequence/framesperrot"
|
||||
#define FRAMESPERROTMAX "sequence/framesperrotmax"
|
||||
#define ROTATIONS "sequence/rotations"
|
||||
#define ROTATIONSMAX "sequence/rotationsmax"
|
||||
#define BLENDFRAMES "sequence/blendframes"
|
||||
#define BLENDFRAMESMAX "sequence/blendframesmax"
|
||||
|
||||
#define VARFILTERSUM "varfilter/sumcheckbox"
|
||||
#define VARFILTERASSIGN "varfilter/assigncheckbox"
|
||||
#define VARFILTERPPSUM "varfilter/ppsumcheckbox"
|
||||
#define VARFILTERPPASSIGN "varfilter/ppassigncheckbox"
|
||||
#define VARFILTERSDC "varfilter/dccheckbox"
|
||||
#define VARFILTERSSTATE "varfilter/statecheckbox"
|
||||
#define VARFILTERSTATE "varfilter/statecheckbox"
|
||||
#define VARFILTERPARAM "varfilter/paramcheckbox"
|
||||
#define VARFILTERNONPARAM "varfilter/nonparamcheckbox"
|
||||
|
||||
@ -126,6 +133,43 @@ public:
|
||||
uint RandomCount();
|
||||
void RandomCount(uint i);
|
||||
|
||||
uint FramesPerRot();
|
||||
void FramesPerRot(uint i);
|
||||
uint FramesPerRotMax();
|
||||
void FramesPerRotMax(uint i);
|
||||
uint Rotations();
|
||||
void Rotations(uint i);
|
||||
uint RotationsMax();
|
||||
void RotationsMax(uint i);
|
||||
uint BlendFrames();
|
||||
void BlendFrames(uint i);
|
||||
uint BlendFramesMax();
|
||||
void BlendFramesMax(uint i);
|
||||
|
||||
int VarFilterSum();
|
||||
void VarFilterSum(int i);
|
||||
|
||||
int VarFilterAssign();
|
||||
void VarFilterAssign(int i);
|
||||
|
||||
int VarFilterPpsum();
|
||||
void VarFilterPpsum(int i);
|
||||
|
||||
int VarFilterPpassign();
|
||||
void VarFilterPpassign(int i);
|
||||
|
||||
int VarFilterSdc();
|
||||
void VarFilterSdc(int i);
|
||||
|
||||
int VarFilterState();
|
||||
void VarFilterState(int i);
|
||||
|
||||
int VarFilterParam();
|
||||
void VarFilterParam(int i);
|
||||
|
||||
int VarFilterNonparam();
|
||||
void VarFilterNonparam(int i);
|
||||
|
||||
bool FinalEarlyClip();
|
||||
void FinalEarlyClip(bool b);
|
||||
|
||||
|
@ -26,14 +26,14 @@ FractoriumVariationsDialog::FractoriumVariationsDialog(FractoriumSettings* setti
|
||||
m_CheckBoxes.push_back(ui.StateCheckBox);
|
||||
m_CheckBoxes.push_back(ui.ParamCheckBox);
|
||||
m_CheckBoxes.push_back(ui.NonParamCheckBox);
|
||||
ui.SumCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERSUM).toInt()));
|
||||
ui.AssignCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERASSIGN).toInt()));
|
||||
ui.PpSumCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERPPSUM).toInt()));
|
||||
ui.PpAssignCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERPPASSIGN).toInt()));
|
||||
ui.DcCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERSDC).toInt()));
|
||||
ui.StateCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERSSTATE).toInt()));
|
||||
ui.ParamCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERPARAM).toInt()));
|
||||
ui.NonParamCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERNONPARAM).toInt()));
|
||||
ui.SumCheckBox->setCheckState (Qt::CheckState(m_Settings->VarFilterSum ()));
|
||||
ui.AssignCheckBox->setCheckState (Qt::CheckState(m_Settings->VarFilterAssign ()));
|
||||
ui.PpSumCheckBox->setCheckState (Qt::CheckState(m_Settings->VarFilterPpsum ()));
|
||||
ui.PpAssignCheckBox->setCheckState(Qt::CheckState(m_Settings->VarFilterPpassign()));
|
||||
ui.DcCheckBox->setCheckState (Qt::CheckState(m_Settings->VarFilterSdc ()));
|
||||
ui.StateCheckBox->setCheckState (Qt::CheckState(m_Settings->VarFilterState ()));
|
||||
ui.ParamCheckBox->setCheckState (Qt::CheckState(m_Settings->VarFilterParam ()));
|
||||
ui.NonParamCheckBox->setCheckState(Qt::CheckState(m_Settings->VarFilterNonparam()));
|
||||
|
||||
for (auto& cb : m_CheckBoxes)
|
||||
{
|
||||
@ -112,14 +112,14 @@ void FractoriumVariationsDialog::SyncSettings()
|
||||
m[cb->text()] = cb->checkState() == Qt::CheckState::Checked;
|
||||
});
|
||||
m_Settings->Variations(m);
|
||||
m_Settings->setValue(VARFILTERSUM , int(ui.SumCheckBox->checkState()));
|
||||
m_Settings->setValue(VARFILTERASSIGN , int(ui.AssignCheckBox->checkState()));
|
||||
m_Settings->setValue(VARFILTERPPSUM , int(ui.PpSumCheckBox->checkState()));
|
||||
m_Settings->setValue(VARFILTERPPASSIGN, int(ui.PpAssignCheckBox->checkState()));
|
||||
m_Settings->setValue(VARFILTERSDC , int(ui.DcCheckBox->checkState()));
|
||||
m_Settings->setValue(VARFILTERSSTATE , int(ui.StateCheckBox->checkState()));
|
||||
m_Settings->setValue(VARFILTERPARAM , int(ui.ParamCheckBox->checkState()));
|
||||
m_Settings->setValue(VARFILTERNONPARAM, int(ui.NonParamCheckBox->checkState()));
|
||||
m_Settings->VarFilterSum (int(ui.SumCheckBox->checkState()));
|
||||
m_Settings->VarFilterAssign (int(ui.AssignCheckBox->checkState()));
|
||||
m_Settings->VarFilterPpsum (int(ui.PpSumCheckBox->checkState()));
|
||||
m_Settings->VarFilterPpassign(int(ui.PpAssignCheckBox->checkState()));
|
||||
m_Settings->VarFilterSdc (int(ui.DcCheckBox->checkState()));
|
||||
m_Settings->VarFilterState (int(ui.StateCheckBox->checkState()));
|
||||
m_Settings->VarFilterParam (int(ui.ParamCheckBox->checkState()));
|
||||
m_Settings->VarFilterNonparam(int(ui.NonParamCheckBox->checkState()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -243,6 +243,20 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>SelectAllButton</tabstop>
|
||||
<tabstop>InvertSelectionButton</tabstop>
|
||||
<tabstop>SelectNoneButton</tabstop>
|
||||
<tabstop>SumCheckBox</tabstop>
|
||||
<tabstop>AssignCheckBox</tabstop>
|
||||
<tabstop>PpSumCheckBox</tabstop>
|
||||
<tabstop>PpAssignCheckBox</tabstop>
|
||||
<tabstop>DcCheckBox</tabstop>
|
||||
<tabstop>StateCheckBox</tabstop>
|
||||
<tabstop>ParamCheckBox</tabstop>
|
||||
<tabstop>NonParamCheckBox</tabstop>
|
||||
<tabstop>VariationsTable</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
Loading…
Reference in New Issue
Block a user