From b690bf8071bf0de4efb6b9fcf02091e4c5c48fb0 Mon Sep 17 00:00:00 2001 From: mfeemster Date: Sun, 3 Apr 2016 18:55:12 -0700 Subject: [PATCH] --User changes -Remove the option --intpalette to format the palette in the xml as ints. If they are not hex formatted, then they should always be float. This option was pointless. -Cleanup some options text for the command line programs. -Allow for dragging around flames in the library tab. This is useful for setting up the order of an animation. -Make the opening of large files in Fractorium much more efficient when not-appending. -Make the opening of large files in all EmberRender and EmberAnimate more efficient. -Better error reporting when opening files. --Bug fixes -Get rid of leftover artifacts that would appear on preview thumbnails when either switching SP/DP or re-rendering previews. -Filename extension was not being appended on Linux when saving as Xml, thus making it impossible to drag that file back in becase drop is filtered on extension. --Code changes -Move GCC compiler spec to C++14. Building with 5.3 now on linux. -Use inline member data initializers. -Make a #define for static for use in Utils.h to make things a little cleaner. -Make various functions able to take arbitrary collections as their parameters rather than just vectors. -Make library collection a list rather than vector. This alleviates the need to re-sync pointers whenever the collection changes. -Subclass QTreeWidget for the library tree. Two new files added for this. -Remove all usage of #ifdef ROW_ONLY_DE in DEOpenCLKernelCreator, it was never used. -Add move constructor and assignment operator to EmberFile. -Add the ability to use a pointer to outside memory in the renderer for the vector of Ember. -Make a lot more functions const where they should be. --- Builds/MSVC/VS2013/Ember.vcxproj | 1 - Builds/MSVC/VS2013/Ember.vcxproj.filters | 3 - Builds/MSVC/VS2013/Fractorium.vcxproj | 17 ++ Builds/MSVC/VS2013/Fractorium.vcxproj.filters | 12 + Builds/QtCreator/Fractorium/Fractorium.pro | 6 +- Builds/QtCreator/defaults.pri | 2 +- Source/Ember/CarToRas.h | 4 +- Source/Ember/Ember.h | 193 +++++--------- Source/Ember/EmberDefines.h | 2 + Source/Ember/EmberMotion.h | 20 +- Source/Ember/EmberPch.h | 1 + Source/Ember/EmberToXml.h | 46 ++-- Source/Ember/Interpolate.h | 22 +- Source/Ember/Isaac.h | 3 +- Source/Ember/Iterator.h | 15 +- Source/Ember/Palette.h | 27 +- Source/Ember/PaletteList.h | 3 + Source/Ember/Point.h | 39 +-- Source/Ember/Renderer.cpp | 96 ++++--- Source/Ember/Renderer.h | 29 ++- Source/Ember/RendererBase.cpp | 23 -- Source/Ember/RendererBase.h | 64 ++--- Source/Ember/SheepTools.h | 27 +- Source/Ember/Utils.h | 172 ++++++------- Source/Ember/Xform.h | 6 +- Source/Ember/XmlToEmber.h | 45 ++-- Source/EmberAnimate/EmberAnimate.cpp | 14 +- Source/EmberCL/DEOpenCLKernelCreator.cpp | 235 ------------------ Source/EmberCL/DEOpenCLKernelCreator.h | 16 +- .../EmberCL/FinalAccumOpenCLKernelCreator.cpp | 18 +- .../EmberCL/FinalAccumOpenCLKernelCreator.h | 16 +- Source/EmberCL/IterOpenCLKernelCreator.cpp | 9 +- Source/EmberCL/IterOpenCLKernelCreator.h | 6 +- Source/EmberCL/OpenCLWrapper.cpp | 6 - Source/EmberCL/OpenCLWrapper.h | 12 +- Source/EmberCL/RendererCL.cpp | 8 - Source/EmberCL/RendererCL.h | 4 +- Source/EmberCommon/EmberCommon.h | 33 ++- Source/EmberCommon/EmberOptions.h | 40 +-- Source/EmberGenome/EmberGenome.cpp | 28 +-- Source/EmberRender/EmberRender.cpp | 4 +- Source/EmberTester/EmberTester.cpp | 25 +- Source/Fractorium/AboutDialog.h | 2 +- Source/Fractorium/DoubleSpinBox.h | 2 +- Source/Fractorium/EmberFile.h | 60 ++++- Source/Fractorium/EmberTreeWidgetItem.h | 16 +- .../Fractorium/FinalRenderEmberController.cpp | 83 ++++--- .../Fractorium/FinalRenderEmberController.h | 6 +- Source/Fractorium/Fractorium.cpp | 24 +- Source/Fractorium/Fractorium.h | 3 +- Source/Fractorium/Fractorium.ui | 27 +- .../Fractorium/FractoriumEmberController.cpp | 36 +-- Source/Fractorium/FractoriumEmberController.h | 41 +-- Source/Fractorium/FractoriumLibrary.cpp | 126 +++++----- Source/Fractorium/FractoriumMenus.cpp | 51 ++-- Source/Fractorium/GLWidget.cpp | 6 - Source/Fractorium/GLWidget.h | 18 +- Source/Fractorium/LibraryTreeWidget.cpp | 40 +++ Source/Fractorium/LibraryTreeWidget.h | 29 +++ Source/Fractorium/OptionsDialog.h | 2 +- Source/Fractorium/SpinBox.h | 2 +- Source/Fractorium/StealthComboBox.h | 4 +- Source/Fractorium/TableWidget.h | 6 +- Source/Fractorium/VariationTreeWidgetItem.h | 2 +- 64 files changed, 890 insertions(+), 1048 deletions(-) create mode 100644 Source/Fractorium/LibraryTreeWidget.cpp create mode 100644 Source/Fractorium/LibraryTreeWidget.h diff --git a/Builds/MSVC/VS2013/Ember.vcxproj b/Builds/MSVC/VS2013/Ember.vcxproj index 51e8293..a302f49 100644 --- a/Builds/MSVC/VS2013/Ember.vcxproj +++ b/Builds/MSVC/VS2013/Ember.vcxproj @@ -144,7 +144,6 @@ - diff --git a/Builds/MSVC/VS2013/Ember.vcxproj.filters b/Builds/MSVC/VS2013/Ember.vcxproj.filters index 70e574d..88dd77d 100644 --- a/Builds/MSVC/VS2013/Ember.vcxproj.filters +++ b/Builds/MSVC/VS2013/Ember.vcxproj.filters @@ -128,9 +128,6 @@ Header Files\Variations - - Header Files - diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj b/Builds/MSVC/VS2013/Fractorium.vcxproj index 5e3de1a..00001fe 100644 --- a/Builds/MSVC/VS2013/Fractorium.vcxproj +++ b/Builds/MSVC/VS2013/Fractorium.vcxproj @@ -158,6 +158,7 @@ xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindows.dll" "$(OutDir)\platforms + @@ -198,6 +199,9 @@ xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindows.dll" "$(OutDir)\platforms true + + true + true @@ -255,6 +259,9 @@ xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindows.dll" "$(OutDir)\platforms true + + true + true @@ -311,6 +318,16 @@ xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindows.dll" "$(OutDir)\platforms $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing LibraryTreeWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/LibraryTreeWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing LibraryTreeWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/LibraryTreeWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." + diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj.filters b/Builds/MSVC/VS2013/Fractorium.vcxproj.filters index 8dd37fd..36aabeb 100644 --- a/Builds/MSVC/VS2013/Fractorium.vcxproj.filters +++ b/Builds/MSVC/VS2013/Fractorium.vcxproj.filters @@ -257,6 +257,15 @@ Generated Files\Release + + Generated Files\Debug + + + Generated Files\Release + + + Widgets + @@ -393,6 +402,9 @@ Dialogs\Qss + + Widgets + diff --git a/Builds/QtCreator/Fractorium/Fractorium.pro b/Builds/QtCreator/Fractorium/Fractorium.pro index 272f0ed..8231734 100644 --- a/Builds/QtCreator/Fractorium/Fractorium.pro +++ b/Builds/QtCreator/Fractorium/Fractorium.pro @@ -113,7 +113,8 @@ SOURCES += \ $$PRJ_SRC_DIR/QssDialog.cpp \ $$PRJ_SRC_DIR/QssTextEdit.cpp \ $$PRJ_SRC_DIR/SpinBox.cpp \ - $$PRJ_SRC_DIR/VariationsDialog.cpp + $$PRJ_SRC_DIR/VariationsDialog.cpp \ + $$PRJ_SRC_DIR/LibraryTreeWidget.cpp HEADERS += \ $$SRC_COMMON_DIR/EmberCommon.h \ @@ -148,7 +149,8 @@ HEADERS += \ $$PRJ_SRC_DIR/TableWidget.h \ $$PRJ_SRC_DIR/TwoButtonComboWidget.h \ $$PRJ_SRC_DIR/VariationsDialog.h \ - $$PRJ_SRC_DIR/VariationTreeWidgetItem.h + $$PRJ_SRC_DIR/VariationTreeWidgetItem.h \ + $$PRJ_SRC_DIR/LibraryTreeWidget.h FORMS += \ $$PRJ_SRC_DIR/AboutDialog.ui \ diff --git a/Builds/QtCreator/defaults.pri b/Builds/QtCreator/defaults.pri index 83ad867..1a90047 100644 --- a/Builds/QtCreator/defaults.pri +++ b/Builds/QtCreator/defaults.pri @@ -158,7 +158,7 @@ win32 { QMAKE_CXXFLAGS += -fPIC QMAKE_CXXFLAGS += -fpermissive QMAKE_CXXFLAGS += -pedantic - QMAKE_CXXFLAGS += -std=c++11 + QMAKE_CXXFLAGS += -std=c++14 QMAKE_CXXFLAGS += -Wnon-virtual-dtor QMAKE_CXXFLAGS += -Wshadow QMAKE_CXXFLAGS += -Winit-self diff --git a/Source/Ember/CarToRas.h b/Source/Ember/CarToRas.h index 265782b..54bf2a7 100644 --- a/Source/Ember/CarToRas.h +++ b/Source/Ember/CarToRas.h @@ -25,9 +25,7 @@ public: /// /// Empty constructor. This class should never be used unless it's been properly constructed with the constructor that takes arguments. /// - CarToRas() - { - } + CarToRas() = default; /// /// Constructor that takes arguments to set up the bounds and passes them to Init(). diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h index 9643b21..16272be 100644 --- a/Source/Ember/Ember.h +++ b/Source/Ember/Ember.h @@ -44,9 +44,12 @@ public: /// Default constructor which calls Init() to set default values. /// Ember() - : m_VariationList(VariationList::Instance()) { - Init(); + m_Background.Reset(); + m_Curves.Init(); + m_Xforms.reserve(12); + m_CamMat = m3T(0); + m_ProjFunc = &EmberNs::Ember::ProjectNone; } /// @@ -54,8 +57,6 @@ public: /// /// The Ember object to copy Ember(const Ember& ember) - : m_Edits(nullptr), - m_VariationList(VariationList::Instance()) { Ember::operator=(ember); } @@ -66,8 +67,6 @@ public: /// The Ember object to copy template Ember(const Ember& ember) - : m_Edits(nullptr), - m_VariationList(VariationList::Instance()) { Ember::operator=(ember); } @@ -178,74 +177,10 @@ public: if (ember.m_Edits) m_Edits = xmlCopyDoc(ember.m_Edits, 1); - CopyVec(m_EmberMotionElements, ember.m_EmberMotionElements); + CopyCont(m_EmberMotionElements, ember.m_EmberMotionElements); return *this; } - /// - /// Set common default values. - /// - void Init() - { - m_FinalRasW = 1920; - m_FinalRasH = 1080; - m_OrigFinalRasW = 1920; - m_OrigFinalRasH = 1080; - m_OrigPixPerUnit = 240; - m_SubBatchSize = DEFAULT_SBS; - m_FuseCount = 15; - m_Supersample = 1; - m_TemporalSamples = 100; - m_Symmetry = 0; - m_Quality = 100; - m_PixelsPerUnit = 240; - m_Zoom = 0; - m_ProjFunc = &EmberNs::Ember::ProjectNone; - m_CamZPos = 0; - m_CamPerspective = 0; - m_CamYaw = 0; - m_CamPitch = 0; - m_CamDepthBlur = 0; - m_BlurCoef = 0; - m_CamMat = m3T(0); - m_CenterX = 0; - m_CenterY = 0; - m_RotCenterY = 0; - m_Rotate = 0; - m_Brightness = 4; - m_Gamma = 4; - m_Vibrancy = 1; - m_GammaThresh = T(0.01); - m_HighlightPower = -1; - m_Time = 0; - m_Background.Reset(); - m_Interp = eInterp::EMBER_INTERP_SMOOTH; - m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG; - //DE filter. - m_MinRadDE = 0; - m_MaxRadDE = 9; - m_CurveDE = T(0.4); - //Spatial filter. - m_SpatialFilterType = eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER; - m_SpatialFilterRadius = T(0.5); - //Temporal filter. - m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER; - m_TemporalFilterExp = 0; - m_TemporalFilterWidth = 1; - //Palette. - m_PaletteMode = ePaletteMode::PALETTE_LINEAR; - m_PaletteInterp = ePaletteInterp::INTERP_HSV; - //Curves. - m_Curves.Init(); - m_Name = "No name"; - m_ParentFilename = "No parent"; - //Internal values. - m_Index = 0; - m_ScaleType = eScaleType::SCALE_NONE; - m_Xforms.reserve(12); - m_Edits = nullptr; - } - /// /// Add a copy of a new xform to the xforms vector. /// @@ -286,7 +221,7 @@ public: /// The total number of xforms if additional padding xforms are desired. Default: 0. /// Whether to copy the final xform. Default: false. /// The newly constructed ember - Ember Copy(size_t xformPad = 0, bool doFinal = false) + Ember Copy(size_t xformPad = 0, bool doFinal = false) const { Ember ember(*this); ember.PadXforms(xformPad); @@ -443,7 +378,7 @@ public: /// /// A pointer to the xform to test /// True if matched, else false. - bool IsFinalXform(Xform* xform) + bool IsFinalXform(Xform* xform) const { return &m_FinalXform == xform; } @@ -695,7 +630,7 @@ public: /// Vector of embers /// Coefficients vector which must be the same length as the vector of embers /// Stagger if greater than 0 - void Interpolate(vector>& embers, vector& coefs, T stagger) + void Interpolate(const vector>& embers, vector& coefs, T stagger) { Interpolate(embers.data(), embers.size(), coefs, stagger); } @@ -708,7 +643,7 @@ public: /// Number of elements in the buffer of embers /// Coefficients vector which must be the same length as the vector of embers /// Stagger if greater than 0 - void Interpolate(Ember* embers, size_t size, vector& coefs, T stagger) + void Interpolate(const Ember* embers, size_t size, vector& coefs, T stagger) { if (size != coefs.size() || size < 2) return; @@ -996,7 +931,7 @@ public: /// /// Vector of embers /// Used in calculating Catmull-Rom coefficients - void InterpolateCatmullRom(vector>& embers, T t) + void InterpolateCatmullRom(const vector>& embers, T t) { InterpolateCatmullRom(embers.data(), embers.size(), t); } @@ -1008,7 +943,7 @@ public: /// Pointer to buffer of embers /// Number of elements in the buffer of embers /// Used in calculating Catmull-Rom coefficients - void InterpolateCatmullRom(Ember* embers, size_t size, T t) + void InterpolateCatmullRom(const Ember* embers, size_t size, T t) { T t2 = t * t; T t3 = t2 * t; @@ -1537,50 +1472,50 @@ public: //The width and height in pixels of the final output image. The size of the histogram and DE filtering buffers will differ from this. //Xml fields: "size". - size_t m_FinalRasW; - size_t m_FinalRasH; - size_t m_OrigFinalRasW;//Keep track of the originals read from the Xml, because... - size_t m_OrigFinalRasH;//the dimension may change in an editor and the originals are needed for the aspect ratio. - T m_OrigPixPerUnit; + size_t m_FinalRasW = 1920; + size_t m_FinalRasH = 1080; + size_t m_OrigFinalRasW = 1920;//Keep track of the originals read from the Xml, because... + size_t m_OrigFinalRasH = 1080;//the dimension may change in an editor and the originals are needed for the aspect ratio. + T m_OrigPixPerUnit = 240; //The iteration depth. This was a rendering parameter in flam3 but has been made a member here //so that it can be adjusted more easily. - size_t m_SubBatchSize; + size_t m_SubBatchSize = DEFAULT_SBS; //The number of iterations to disregard for each sub batch. This was a rendering parameter in flam3 but has been made a member here //so that it can be adjusted more easily. - size_t m_FuseCount; + size_t m_FuseCount = 15; //The multiplier in size of the histogram and DE filtering buffers. Must be at least one, preferrably never larger than 4, only useful at 2. //Xml field: "supersample" or "overample (deprecated)". - size_t m_Supersample; + size_t m_Supersample = 1; //When animating, split each pass into this many pieces, each doing a fraction of the total iterations. Each temporal sample //will render an interpolated instance of the ember that is a fraction of the current ember and the next one. //When rendering a single image, this field is always set to 1. //Xml field: "temporal_samples". - size_t m_TemporalSamples; + size_t m_TemporalSamples = 100; //Whether or not any symmetry was added. This field is in a bit of a state of conflict right now as flam3 has a severe bug. //Xml field: "symmetry". - intmax_t m_Symmetry; + intmax_t m_Symmetry = 0; //The number of iterations per pixel of the final output image. Note this is not affected by the increase in pixels in the //histogram and DE filtering buffer due to supersampling. It can be affected by a non-zero zoom value though. //10 is a good value for interactive/real-time rendering, 100-200 is good for previewing, 1000 is good for final output. Above that is mostly a waste of energy. //Xml field: "quality". - T m_Quality; + T m_Quality = 100; //The number of pixels in the final output image that corresponds to the distance from 0-1 in the cartesian plane used for iterating. //A larger value produces a more zoomed in imgage. A value of 240 is commonly used, but in practice it varies widely depending on the image. //Note that increasing this value does not adjust the quality by a proportional amount, so an increased value may produce a degraded image. //Xml field: "scale". - T m_PixelsPerUnit; + T m_PixelsPerUnit = 240; //A value greater than 0 will zoom in the field of view, however it will also increase the quality by a proportional amount. This is used to //overcome the shortcoming of scale by also adjusting the quality. //Xml field: "zoom". - T m_Zoom; + T m_Zoom = 0; //3D fields. private: @@ -1589,22 +1524,22 @@ private: public: //Xml field: "cam_zpos". - T m_CamZPos; + T m_CamZPos = 0; //Xml field: "cam_persp". - T m_CamPerspective; + T m_CamPerspective = 0; //Xml field: "cam_yaw". - T m_CamYaw; + T m_CamYaw = 0; //Xml field: "cam_pitch". - T m_CamPitch; + T m_CamPitch = 0; //Xml field: "cam_dof". - T m_CamDepthBlur; + T m_CamDepthBlur = 0; private: - T m_BlurCoef; + T m_BlurCoef = 0; public: m3T m_CamMat; @@ -1612,38 +1547,38 @@ public: //The camera offset from the center of the cartesian plane. Since this is the camera offset, the final output image will be moved in the opposite //direction of the values specified. There is also a second copy of the Y coordinate needed because m_CenterY will be modified during strips rendering. //Xml field: "center". - T m_CenterX; - T m_CenterY; - T m_RotCenterY; + T m_CenterX = 0; + T m_CenterY = 0; + T m_RotCenterY = 0; //Rotate the camera by this many degrees. Since this is a camera rotation, the final output image will be rotated counter-clockwise. //Xml field: "rotate". - T m_Rotate; + T m_Rotate = 0; //Determine how bright to make the image during final accumulation. //Xml field: "brightness". - T m_Brightness; + T m_Brightness = 4; //Gamma level used in gamma correction during final accumulation. //Xml field: "gamma". - T m_Gamma; + T m_Gamma = 4; //Used in color correction during final accumulation. //Xml field: "vibrancy". - T m_Vibrancy; + T m_Vibrancy = 1; //Gamma threshold used in gamma correction during final accumulation. //Xml field: "gamma_threshold". - T m_GammaThresh; + T m_GammaThresh = T(0.01); //Value to control saturation of some pixels in gamma correction during final accumulation. //Xml field: "highlight_power". - T m_HighlightPower; + T m_HighlightPower = -1; //When animating a file full of many embers, this value is used to specify the time in the animation //that this ember should be rendered. They must all be sequential and increase by a default value of 1. //Xml field: "time". - T m_Time; + T m_Time = 0; //The background color of the image used in final accumulation, ranged 0-1. //Xml field: "background". @@ -1653,66 +1588,66 @@ public: //The type of interpolation to use when interpolating between embers for animation. //Xml field: "interpolation". - eInterp m_Interp; + eInterp m_Interp = eInterp::EMBER_INTERP_SMOOTH; //The type of interpolation to use on affine transforms when interpolating embers for animation. //Xml field: "interpolation_type" or "interpolation_space (deprecated)". - eAffineInterp m_AffineInterp; + eAffineInterp m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG; //The type of interpolation to use for the palette when interpolating embers for animation. //Xml field: "palette_interpolation". - ePaletteInterp m_PaletteInterp; + ePaletteInterp m_PaletteInterp = ePaletteInterp::INTERP_HSV; //Temporal Filter. //Only used if temporal filter type is exp, else unused. //Xml field: "temporal_filter_exp". - T m_TemporalFilterExp; + T m_TemporalFilterExp = 0; //The width of the temporal filter. //Xml field: "temporal_filter_width". - T m_TemporalFilterWidth; + T m_TemporalFilterWidth = 1; //The type of the temporal filter: Gaussian, Box or Exp. //Xml field: "temporal_filter_type". - eTemporalFilterType m_TemporalFilterType; + eTemporalFilterType m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER; //Density Estimation Filter. //The minimum radius of the DE filter. //Xml field: "estimator_minimum". - T m_MinRadDE; + T m_MinRadDE = 0; //The maximum radius of the DE filter. //Xml field: "estimator_radius". - T m_MaxRadDE; + T m_MaxRadDE = 9; //The shape of the curve that governs how quickly or slowly the filter drops off as it moves away from the center point. //Xml field: "estimator_curve". - T m_CurveDE; + T m_CurveDE = T(0.4); //Spatial Filter. //The radius of the spatial filter used in final accumulation. //Xml field: "filter". - T m_SpatialFilterRadius; + T m_SpatialFilterRadius = T(0.5); //The type of spatial filter used in final accumulation: //Gaussian, Hermite, Box, Triangle, Bell, Bspline, Lanczos3 //Lanczos2, Mitchell, Blackman, Catrom, Hamming, Hanning, Quadratic. //Xml field: "filter_shape". - eSpatialFilterType m_SpatialFilterType; + eSpatialFilterType m_SpatialFilterType = eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER; //Palette. //The method used for retrieving a color from the palette when accumulating to the histogram: step, linear. //Xml field: "palette_mode". - ePaletteMode m_PaletteMode; + ePaletteMode m_PaletteMode = ePaletteMode::PALETTE_LINEAR; //The color palette to use. Can be specified inline as Xml color fields, or as a hex buffer. Can also be specified //as an index into the palette file with an optional hue rotation applied. Inserting as a hex buffer is the preferred method. //Xml field: "color" or "colors" or "palette" . - Palette m_Palette; + Palette m_Palette;//Final palette that is actually used is a copy of this inside of render, which will be of type bucketT (float). //Curves used to adjust the color during final accumulation. Curves m_Curves; @@ -1721,18 +1656,18 @@ public: //The name of this ember. //Xml field: "name". - string m_Name; + string m_Name = string("No name"); //The name of the file that this ember was contained in. //Xml field: "". - string m_ParentFilename; + string m_ParentFilename = string("No parent"); //An Xml edit document describing information about the author as well as an edit history of the ember. //Xml field: "edit". - xmlDocPtr m_Edits; + xmlDocPtr m_Edits = nullptr; //The 0-based position of this ember in the file it was contained in. - size_t m_Index; + size_t m_Index = 0; //The list of motion elements for the top-level flame params vector> m_EmberMotionElements; @@ -1741,7 +1676,7 @@ private: /// /// The type of scaling used when resizing. /// - eScaleType m_ScaleType; + eScaleType m_ScaleType = eScaleType::SCALE_NONE; //The vector containing all of the xforms. //Xml field: "xform". @@ -1753,7 +1688,7 @@ private: Xform m_FinalXform; //Single global reference to create variations with. - VariationList& m_VariationList; + VariationList& m_VariationList = VariationList::Instance(); /// /// Interpolation function that takes the address of a member variable of type T as a template parameter. @@ -1763,7 +1698,7 @@ private: /// The list of coefficients to interpolate /// The size of the lists, both must match. template ::*m> - void InterpT(Ember* embers, vector& coefs, size_t size) + void InterpT(const Ember* embers, const vector& coefs, size_t size) { this->*m = 0; @@ -1778,7 +1713,7 @@ private: /// The list of coefficients to interpolate /// The size of the lists, both must match. template ::*m> - void InterpX(Ember* embers, vector& coefs, size_t size) + void InterpX(const Ember* embers, const vector& coefs, size_t size) { this->*m = M(); @@ -1793,7 +1728,7 @@ private: /// The list of coefficients to interpolate /// The size of the lists, both must match. template ::*m> - void InterpI(Ember* embers, vector& coefs, size_t size) + void InterpI(const Ember* embers, const vector& coefs, size_t size) { T t = 0; @@ -1813,7 +1748,7 @@ private: /// The list of coefficients to interpolate /// The size of the lists, both must match. template ::*m> - void InterpXform(Xform* xform, size_t i, Ember* embers, vector& coefs, size_t size) + void InterpXform(Xform* xform, size_t i, const Ember* embers, const vector& coefs, size_t size) { xform->*m = T(0); diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h index 61d36fe..cc8cc69 100644 --- a/Source/Ember/EmberDefines.h +++ b/Source/Ember/EmberDefines.h @@ -94,8 +94,10 @@ static inline size_t NowMs() //These two must always match. #ifdef _WIN32 #define ALIGN __declspec(align(16)) + #define STATIC static #else #define ALIGN __attribute__ ((aligned (16))) + #define STATIC #endif #define ALIGN_CL "((aligned (16)))"//The extra parens are necessary. diff --git a/Source/Ember/EmberMotion.h b/Source/Ember/EmberMotion.h index 7690422..e841931 100644 --- a/Source/Ember/EmberMotion.h +++ b/Source/Ember/EmberMotion.h @@ -17,9 +17,7 @@ public: /// /// Default constructor, which calls the base, which sets first and second to their defaults. /// - MotionParam() - { - } + MotionParam() = default; /// /// Member-wise constructor. @@ -90,12 +88,8 @@ public: /// /// Default constructor to initialize motion freq and offset to 0 and the motion func to SIN. /// - EmberMotion() - { - m_MotionFreq = 0; - m_MotionFunc = eMotion::MOTION_SIN; - m_MotionOffset = 0; - } + EmberMotion() = default; + ~EmberMotion() = default; /// /// Default copy constructor. @@ -136,16 +130,16 @@ public: template EmberMotion& operator = (const EmberMotion& other) { - CopyVec(m_MotionParams, other.m_MotionParams); + CopyCont(m_MotionParams, other.m_MotionParams); m_MotionFunc = other.m_MotionFunc; m_MotionFreq = T(other.m_MotionFreq); m_MotionOffset = T(other.m_MotionOffset); return *this; } - T m_MotionFreq; - T m_MotionOffset; - eMotion m_MotionFunc; + T m_MotionFreq = 0; + T m_MotionOffset = 0; + eMotion m_MotionFunc = eMotion::MOTION_SIN; vector> m_MotionParams; }; } diff --git a/Source/Ember/EmberPch.h b/Source/Ember/EmberPch.h index 4b0d4f1..0661215 100644 --- a/Source/Ember/EmberPch.h +++ b/Source/Ember/EmberPch.h @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef __APPLE__ #include #else diff --git a/Source/Ember/EmberToXml.h b/Source/Ember/EmberToXml.h index 3269833..3206bdb 100644 --- a/Source/Ember/EmberToXml.h +++ b/Source/Ember/EmberToXml.h @@ -23,9 +23,9 @@ public: /// /// Empty constructor. /// - EmberToXml() - { - } + EmberToXml() = default; + ~EmberToXml() = default; + EmberToXml(const EmberToXml& e) = delete; /// /// Save the ember to the specified file. @@ -34,33 +34,32 @@ public: /// The ember to save /// How deep the edit depth goes /// If true included edit tags, else don't. - /// If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers. /// If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags. /// If true, append to the file if it already exists, else create a new file. /// Whether a new file is to be started /// Whether an existing file is to be ended /// True if successful, else false - bool Save(const string& filename, Ember& ember, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette, bool append = false, bool start = false, bool finish = false) + bool Save(const string& filename, Ember& ember, size_t printEditDepth, bool doEdits, bool hexPalette, bool append = false, bool start = false, bool finish = false) { vector> vec; vec.push_back(ember); - return Save(filename, vec, printEditDepth, doEdits, intPalette, hexPalette, append, start, finish); + return Save(filename, vec, printEditDepth, doEdits, hexPalette, append, start, finish); } /// - /// Save a vector of embers to the specified file. + /// Save a container of embers to the specified file. /// /// Full path and filename - /// The vector of embers to save + /// The container of embers to save /// How deep the edit depth goes /// If true included edit tags, else don't. - /// If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers. /// If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags. /// If true, append to the file if it already exists, else create a new file. /// Whether a new file is to be started /// Whether an existing file is to be ended /// True if successful, else false - bool Save(const string& filename, vector>& embers, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette, bool append = false, bool start = false, bool finish = false) + template class C> + bool Save(const string& filename, C, Alloc>& embers, size_t printEditDepth, bool doEdits, bool hexPalette, bool append = false, bool start = false, bool finish = false) { bool b = false; bool hasTimes = false; @@ -77,15 +76,19 @@ public: if (f.is_open()) { + auto prev = embers.begin(); + //Check to see if there are valid times by checking if any differed. //If so, assume they were intentionally entered times. - for (size_t i = 1; i < embers.size(); i++) + for (auto it = Advance(embers.begin(), 1); it != embers.end(); ++it) { - if (embers[i].m_Time != embers[i - 1].m_Time) + if (it->m_Time != prev->m_Time) { hasTimes = true; break; } + + prev = it; } if (!hasTimes) @@ -101,7 +104,7 @@ public: for (auto& ember : embers) { - string s = ToString(ember, "", printEditDepth, doEdits, intPalette, hexPalette); + string s = ToString(ember, "", printEditDepth, doEdits, hexPalette); f.write(s.c_str(), s.size()); } @@ -144,10 +147,9 @@ public: /// If true, add extra attributes, else don't /// How deep the edit depth goes /// If true included edit tags, else don't. - /// If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers. /// If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags. /// The Xml string representation of the passed in ember - string ToString(Ember& ember, const string& extraAttributes, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette = true) + string ToString(Ember& ember, const string& extraAttributes, size_t printEditDepth, bool doEdits, bool hexPalette = true) { size_t i, j; string s; @@ -292,19 +294,9 @@ public: //The original used a precision of 6 which is totally unnecessary, use 2. if (IsClose(a, 255.0)) - { - if (intPalette) - os << ""; - else - os << ""; - } + os << ""; else - { - if (intPalette) - os << " "; - else - os << " "; - } + os << " "; os << "\n"; } diff --git a/Source/Ember/Interpolate.h b/Source/Ember/Interpolate.h index e89bbec..6626f16 100644 --- a/Source/Ember/Interpolate.h +++ b/Source/Ember/Interpolate.h @@ -38,7 +38,7 @@ public: /// The array of embers to align /// The array which will contain the aligned embers /// The number of elements in sourceEmbers - static void Align(Ember* sourceEmbers, Ember* destEmbers, size_t count) + static void Align(const Ember* sourceEmbers, Ember* destEmbers, size_t count) { bool aligned = true; bool currentFinal, final = sourceEmbers[0].UseFinalXform(); @@ -297,7 +297,7 @@ public: /// /// The vector of embers to inspect for xaos /// True if at least one ember contained xaos, else false. - static bool AnyXaosPresent(vector>& embers) + static bool AnyXaosPresent(const vector>& embers) { return AnyXaosPresent(embers.data(), embers.size()); } @@ -308,7 +308,7 @@ public: /// The array of embers to inspect /// The size of the embers array /// True if at least one ember contained xaos, else false. - static bool AnyXaosPresent(Ember* embers, size_t size) + static bool AnyXaosPresent(const Ember* embers, size_t size) { for (size_t i = 0; i < size; i++) if (embers[i].XaosPresent()) @@ -333,7 +333,7 @@ public: /// The array of embers to inspect /// The size of the embers array /// The greatest non-final xform count in any of the embers - static size_t MaxXformCount(Ember* embers, size_t size) + static size_t MaxXformCount(const Ember* embers, size_t size) { size_t i, maxCount = 0; @@ -349,7 +349,7 @@ public: /// /// The vector of embers to inspect the presence of a final xform /// True if any contained a non-empty final xform, else false. - static bool AnyFinalPresent(vector>& embers) + static bool AnyFinalPresent(const vector>& embers) { return AnyFinalPresent(embers.data(), embers.size()); } @@ -360,7 +360,7 @@ public: /// The array of embers to inspect the presence of a final xform /// The size of the embers array /// True if any contained a final xform, else false. - static bool AnyFinalPresent(Ember* embers, size_t size) + static bool AnyFinalPresent(const Ember* embers, size_t size) { for (size_t i = 0; i < size; i++) if (embers[i].UseFinalXform()) @@ -376,7 +376,7 @@ public: /// The time position in the vector specifying the point of interpolation /// Stagger if > 0 /// The interpolated result - static void Interpolate(vector>& embers, T time, T stagger, Ember& result) + static void Interpolate(const vector>& embers, T time, T stagger, Ember& result) { Interpolate(embers.data(), embers.size(), time, stagger, result); } @@ -389,7 +389,7 @@ public: /// The time position in the vector specifying the point of interpolation /// Stagger if > 0 /// The interpolated result - static void Interpolate(Ember* embers, size_t size, T time, T stagger, Ember& result) + static void Interpolate(const Ember* embers, size_t size, T time, T stagger, Ember& result) { if (size == 1) { @@ -585,7 +585,7 @@ public: /// The vec2 vector to store the polar angular values /// The vec2 vector to store the polar magnitude values /// The vec2 vector to store the polar translation values - static void ConvertLinearToPolar(vector>& embers, size_t xfi, size_t cflag, vector& cxAng, vector& cxMag, vector& cxTrn) + static void ConvertLinearToPolar(const vector>& embers, size_t xfi, size_t cflag, vector& cxAng, vector& cxMag, vector& cxTrn) { ConvertLinearToPolar(embers.data(), embers.size(), xfi, cflag, cxAng, cxMag, cxTrn); } @@ -601,7 +601,7 @@ public: /// The vec2 vector to store the polar angular values /// The vec2 vector to store the polar magnitude values /// The vec2 vector to store the polar translation values - static void ConvertLinearToPolar(Ember* embers, size_t size, size_t xfi, size_t cflag, vector& cxAng, vector& cxMag, vector& cxTrn) + static void ConvertLinearToPolar(const Ember* embers, size_t size, size_t xfi, size_t cflag, vector& cxAng, vector& cxMag, vector& cxTrn) { if (size == cxAng.size() && size == cxMag.size() && @@ -765,7 +765,7 @@ public: /// The vec2 vector to store the polar magnitude values /// The vec2 vector to store the polar translation values /// The Affine2D to store the inerpolated values in - static void InterpAndConvertBack(vector& coefs, vector& cxAng, vector& cxMag, vector& cxTrn, Affine2D& store) + static void InterpAndConvertBack(const vector& coefs, const vector& cxAng, const vector& cxMag, const vector& cxTrn, Affine2D& store) { size_t size = coefs.size(); glm::length_t i, col, accmode[2] = { 0, 0 }; diff --git a/Source/Ember/Isaac.h b/Source/Ember/Isaac.h index 220317f..58e0298 100644 --- a/Source/Ember/Isaac.h +++ b/Source/Ember/Isaac.h @@ -56,7 +56,7 @@ class EMBER_API QTIsaac public: enum { N = (1 << ALPHA) }; UintBytes m_Cache; - size_t m_LastIndex; + size_t m_LastIndex = 0; /// /// The structure which holds all of the random information. @@ -85,7 +85,6 @@ public: QTIsaac(T a = 0, T b = 0, T c = 0, T* s = nullptr) { Srand(a, b, c, s); - m_LastIndex = 0; m_Cache.Uint = Rand(); RandByte();//Need to call at least once so other libraries can link. } diff --git a/Source/Ember/Iterator.h b/Source/Ember/Iterator.h index b6a2cc0..1f9734c 100644 --- a/Source/Ember/Iterator.h +++ b/Source/Ember/Iterator.h @@ -52,18 +52,11 @@ class EMBER_API Iterator { public: /// - /// Empty constructor. + /// Empty constructor and virtual destructor so proper derived class destructors get called. /// - Iterator() - { - } - - /// - /// Empty virtual destructor so proper derived class destructors get called. - /// - virtual ~Iterator() - { - } + Iterator() = default; + virtual ~Iterator() = default; + Iterator(const Iterator& iter) = delete; /// /// Accessors. diff --git a/Source/Ember/Palette.h b/Source/Ember/Palette.h index 6bab110..18c58fc 100644 --- a/Source/Ember/Palette.h +++ b/Source/Ember/Palette.h @@ -25,8 +25,6 @@ public: /// Palette() { - m_Name = "-"; - m_Index = -1; m_Entries.resize(COLORMAP_LENGTH); Clear(); } @@ -119,12 +117,9 @@ public: } /// - /// Empty destructor. /// Needed to eliminate warnings about inlining. /// - ~Palette() - { - } + ~Palette() = default; /// /// Default assignment operator. @@ -149,7 +144,7 @@ public: m_Index = palette.m_Index; m_Name = palette.m_Name; m_Filename = palette.m_Filename; - CopyVec(m_Entries, palette.m_Entries); + CopyCont(m_Entries, palette.m_Entries); return *this; } @@ -163,6 +158,16 @@ public: return m_Entries[i]; } + /// + /// Convenience [] operator to index into the color entries vector in a const context. + /// + /// The index to get + /// The color value at the specified index + const v4T& operator[] (size_t i) const + { + return m_Entries[i]; + } + /// /// Convenience * operator to get a pointer to the beginning of the color entries vector. /// @@ -421,7 +426,7 @@ public: /// /// The RGB buffer /// The HSV buffer - static void RgbToHsv(T* rgb, T* hsv) + static void RgbToHsv(const T* rgb, T* hsv) { RgbToHsv(rgb[0], rgb[1], rgb[2], hsv[0], hsv[1], hsv[2]); } @@ -576,9 +581,9 @@ public: } } - int m_Index;//Index in the xml palette file of this palette, use -1 for random. - string m_Name;//Name of this palette. + int m_Index = -1;//Index in the xml palette file of this palette, use -1 for random. + string m_Name = "-";//Name of this palette. shared_ptr m_Filename;//Name of the parent file this palette came from, can be empty. - vector m_Entries;//Storage for the color values. + vector m_Entries; }; } diff --git a/Source/Ember/PaletteList.h b/Source/Ember/PaletteList.h index 702fb13..d782d85 100644 --- a/Source/Ember/PaletteList.h +++ b/Source/Ember/PaletteList.h @@ -28,6 +28,9 @@ public: Add(string(m_DefaultFilename)); } + ~PaletteList() = default; + PaletteList(const PaletteList& paletteList) = delete; + /// /// Read an Xml palette file into memory. /// This must be called before any palette file usage. diff --git a/Source/Ember/Point.h b/Source/Ember/Point.h index d4e8274..a71bee2 100644 --- a/Source/Ember/Point.h +++ b/Source/Ember/Point.h @@ -25,10 +25,8 @@ public: /// /// Constructor to initialize spatial and color coordinates to zero, with full visibility. /// - Point() - { - Init(); - } + Point() = default; + ~Point() = default; /// /// Default copy constructor. @@ -75,29 +73,16 @@ public: m_ColorX = point.m_ColorX; //m_ColorY = point.m_ColorY; m_VizAdjusted = point.m_VizAdjusted; - return *this; } - /// - /// Set spatial and color coordinates to zero, with full visibility. - /// - void Init() - { - m_X = 0; - m_Y = 0; - m_Z = 0; - m_ColorX = 0; - //m_ColorY = 0; - m_VizAdjusted = 1; - } - - T m_X; - T m_Y; - T m_Z; - T m_ColorX; + //Set spatial and color coordinates to zero, with full visibility. + T m_X = 0; + T m_Y = 0; + T m_Z = 0; + T m_ColorX = 0; //T m_ColorY; - T m_VizAdjusted; + T m_VizAdjusted = 1; }; /// @@ -132,10 +117,10 @@ template struct EMBER_API Color : public v4T { #ifndef _WIN32 -using v4T::r; -using v4T::g; -using v4T::b; -using v4T::a; + using v4T::r; + using v4T::g; + using v4T::b; + using v4T::a; #endif public: /// diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp index ab87d37..d780bd4 100644 --- a/Source/Ember/Renderer.cpp +++ b/Source/Ember/Renderer.cpp @@ -3,27 +3,6 @@ namespace EmberNs { -/// -/// Constructor that sets default values and allocates iterators. -/// The thread count is set to the number of cores detected on the system. -/// -template -Renderer::Renderer() -{ - m_PixelAspectRatio = 1; - m_StandardIterator = unique_ptr>(new StandardIterator()); - m_XaosIterator = unique_ptr>(new XaosIterator()); - m_Iterator = m_StandardIterator.get(); -} - -/// -/// Virtual destructor so derived class destructors get called. -/// -template -Renderer::~Renderer() -{ -} - /// /// Non-virtual processing functions. /// @@ -89,7 +68,7 @@ void Renderer::ComputeBounds() ////Check the size of the density estimation filter. ////If the radius of the density estimation filter is greater than the ////gutter width, have to pad with more. Otherwise, use the same value. - //for (auto& ember : m_Embers) + //for (auto& ember : *m_EmbersP) // maxDEFilterWidth = std::max(size_t(ceil(ember.m_MaxRadDE) * m_Ember.m_Supersample), maxDEFilterWidth); // ////Need an extra ss = (int)floor(m_Supersample / 2.0) of pixels so that a local iteration count for DE can be determined.//SMOULDER @@ -162,7 +141,7 @@ void Renderer::ComputeCamera() /// However, changing only the brightness and setting action to ACCUM_ONLY is perfectly fine. /// template -void Renderer::SetEmber(Ember& ember, eProcessAction action) +void Renderer::SetEmber(const Ember& ember, eProcessAction action) { ChangeVal([&] { @@ -170,26 +149,64 @@ void Renderer::SetEmber(Ember& ember, eProcessAction action) m_Embers.push_back(ember); m_Embers[0].m_TemporalSamples = 1;//Set temporal samples here to 1 because using the real value only makes sense when using a vector of Embers for animation. m_Ember = m_Embers[0]; + m_EmbersP = &m_Embers; }, action); } /// -/// Set the vector of embers and set the m_Ember member to a copy of the first element. +/// Copy the embers in the passed in container to the internal vector of embers +/// and set the m_Ember member to a copy of the first element. /// Reset the rendering process. /// -/// The vector of embers +/// The container of embers to be copied template -void Renderer::SetEmber(vector>& embers) +template +void Renderer::SetEmber(const C& embers) { ChangeVal([&] { - m_Embers = embers; + CopyCont(m_Embers, embers); + m_EmbersP = &m_Embers; if (!m_Embers.empty()) m_Ember = m_Embers[0]; }, eProcessAction::FULL_RENDER); } +/// +/// Move the embers in the passed in vector to the internal vector of embers +/// and set the m_Ember member to a copy of the first element. +/// Reset the rendering process. +/// This is preferred over SetEmber when the size of embers is large and/or +/// the caller no longer needs to use the argument after this function returns. +/// +/// The vector of embers to be moved +template +void Renderer::MoveEmbers(vector>& embers) +{ + ChangeVal([&] + { + m_Embers = std::move(embers); + m_EmbersP = &m_Embers; + + if (!m_Embers.empty()) + m_Ember = m_Embers[0]; + }, eProcessAction::FULL_RENDER); +} + +template +void Renderer::SetExternalEmbersPointer(vector>* embers) +{ + ChangeVal([&] + { + m_Embers.clear(); + m_EmbersP = embers; + + if (!m_EmbersP->empty()) + m_Ember = (*m_EmbersP)[0]; + }, eProcessAction::FULL_RENDER); +} + /// /// Create the density filter if the current filter parameters differ /// from the last density filter created. @@ -213,7 +230,7 @@ bool Renderer::CreateDEFilter(bool& newAlloc) (m_Ember.m_CurveDE != m_DensityFilter->Curve()) || (m_Ember.m_Supersample != m_DensityFilter->Supersample())) { - m_DensityFilter = unique_ptr>(new DensityFilter(bucketT(m_Ember.m_MinRadDE), bucketT(m_Ember.m_MaxRadDE), bucketT(m_Ember.m_CurveDE), m_Ember.m_Supersample)); + m_DensityFilter = make_unique>(bucketT(m_Ember.m_MinRadDE), bucketT(m_Ember.m_MaxRadDE), bucketT(m_Ember.m_CurveDE), m_Ember.m_Supersample); newAlloc = true; } @@ -384,7 +401,7 @@ eRenderStatus Renderer::Run(vector& finalImage, double time, s //Vib, gam and background are normally summed for each temporal sample. However if iteration is skipped, make sure to get the latest. if ((filterAndAccumOnly || accumOnly) && TemporalSamples() == 1)//Disallow jumping when temporal samples > 1. { - m_Ember = m_Embers[0]; + m_Ember = (*m_EmbersP)[0]; m_Vibrancy = Vibrancy(); m_Gamma = Gamma(); m_Background = m_Ember.m_Background; @@ -398,8 +415,8 @@ eRenderStatus Renderer::Run(vector& finalImage, double time, s //it.Tic(); //Interpolate. - if (m_Embers.size() > 1) - Interpolater::Interpolate(m_Embers, T(time), 0, m_Ember); + if (m_EmbersP->size() > 1) + Interpolater::Interpolate(*m_EmbersP, T(time), 0, m_Ember); //it.Toc("Interp 1"); @@ -436,8 +453,8 @@ eRenderStatus Renderer::Run(vector& finalImage, double time, s //Interpolate and get an ember for DE purposes. //Additional interpolation will be done in the temporal samples loop. //it.Tic(); - if (m_Embers.size() > 1) - Interpolater::Interpolate(m_Embers, deTime, 0, m_Ember); + if (m_EmbersP->size() > 1) + Interpolater::Interpolate(*m_EmbersP, deTime, 0, m_Ember); //it.Toc("Interp 2"); ClampGteRef(m_Ember.m_MinRadDE, 0); @@ -461,8 +478,8 @@ eRenderStatus Renderer::Run(vector& finalImage, double time, s //Interpolate again. //it.Tic(); - if (TemporalSamples() > 1 && m_Embers.size() > 1) - Interpolater::Interpolate(m_Embers, temporalTime, 0, m_Ember);//This will perform all necessary precalcs via the ember/xform/variation assignment operators. + if (TemporalSamples() > 1 && m_EmbersP->size() > 1) + Interpolater::Interpolate(*m_EmbersP, temporalTime, 0, m_Ember);//This will perform all necessary precalcs via the ember/xform/variation assignment operators. //it.Toc("Interp 3"); @@ -678,16 +695,15 @@ Finish: /// Run() should have completed before calling this. /// /// The depth of the edit tags -/// If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers. /// If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags. /// The EmberImageComments object with image comments filled out template -EmberImageComments Renderer::ImageComments(const EmberStats& stats, size_t printEditDepth, bool intPalette, bool hexPalette) +EmberImageComments Renderer::ImageComments(const EmberStats& stats, size_t printEditDepth, bool hexPalette) { ostringstream ss; EmberImageComments comments; ss.imbue(std::locale("")); - comments.m_Genome = m_EmberToXml.ToString(m_Ember, "", printEditDepth, false, intPalette, hexPalette); + comments.m_Genome = m_EmberToXml.ToString(m_Ember, "", printEditDepth, false, hexPalette); ss << (double(stats.m_Badvals) / double(stats.m_Iters));//Percentage of bad values to iters. comments.m_Badvals = ss.str(); ss.str(""); ss << stats.m_Iters; @@ -1702,8 +1718,12 @@ void Renderer::CurveAdjust(bucketT& a, const glm::length_t& index) //So the explicit instantiation must be declared here rather than in Ember.cpp where //all of the other classes are done. template EMBER_API class Renderer; +template EMBER_API void Renderer::SetEmber(const vector>& embers); +template EMBER_API void Renderer::SetEmber(const list>& embers); #ifdef DO_DOUBLE template EMBER_API class Renderer; + template EMBER_API void Renderer::SetEmber(const vector>& embers); + template EMBER_API void Renderer::SetEmber(const list>& embers); #endif } diff --git a/Source/Ember/Renderer.h b/Source/Ember/Renderer.h index 6e0d7d0..cc942d5 100644 --- a/Source/Ember/Renderer.h +++ b/Source/Ember/Renderer.h @@ -43,10 +43,12 @@ namespace EmberNs template class EMBER_API Renderer : public RendererBase { -//using EmberReport::m_ErrorReport; public: - Renderer(); - virtual ~Renderer(); + + Renderer() = default; + Renderer(const Renderer& renderer) = delete; + Renderer& operator = (const Renderer& renderer) = delete; + virtual ~Renderer() = default; //Non-virtual processing functions. void AddEmber(Ember& ember); @@ -56,14 +58,17 @@ public: virtual void ComputeBounds() override; virtual void ComputeQuality() override; virtual void ComputeCamera() override; - virtual void SetEmber(Ember& ember, eProcessAction action = eProcessAction::FULL_RENDER) override; - virtual void SetEmber(vector>& embers) override; + virtual void SetEmber(const Ember& ember, eProcessAction action = eProcessAction::FULL_RENDER) override; + template + void SetEmber(const C& embers); + void MoveEmbers(vector>& embers); + void SetExternalEmbersPointer(vector>* embers); virtual bool CreateDEFilter(bool& newAlloc) override; virtual bool CreateSpatialFilter(bool& newAlloc) override; virtual bool CreateTemporalFilter(bool& newAlloc) override; virtual size_t HistBucketSize() const override { return sizeof(tvec4); } virtual eRenderStatus Run(vector& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) override; - virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) override; + virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool hexPalette = true) override; protected: //New virtual functions to be overridden in derived renderers that use the GPU, but not accessed outside. @@ -158,7 +163,7 @@ protected: T m_Scale; T m_PixelsPerUnitX; T m_PixelsPerUnitY; - T m_PixelAspectRatio; + T m_PixelAspectRatio = 1; T m_LowerLeftX; T m_LowerLeftY; T m_UpperRightX; @@ -173,12 +178,16 @@ protected: Ember m_Ember; Ember m_TempEmber; Ember m_LastEmber; +private: vector> m_Embers; + +protected: + vector>* m_EmbersP = &m_Embers; vector> m_ThreadEmbers; CarToRas m_CarToRas; - Iterator* m_Iterator; - unique_ptr> m_StandardIterator; - unique_ptr> m_XaosIterator; + unique_ptr> m_StandardIterator = make_unique>(); + unique_ptr> m_XaosIterator = make_unique>(); + Iterator* m_Iterator = m_StandardIterator.get(); Palette m_Dmap, m_Csa; vector> m_HistBuckets; vector> m_AccumulatorBuckets; diff --git a/Source/Ember/RendererBase.cpp b/Source/Ember/RendererBase.cpp index d39889a..02c27e6 100644 --- a/Source/Ember/RendererBase.cpp +++ b/Source/Ember/RendererBase.cpp @@ -8,31 +8,8 @@ namespace EmberNs /// The thread count is set to the number of cores detected on the system. /// RendererBase::RendererBase() - : m_TaskGroup(new tbb::task_group) { - m_Abort = false; - m_LockAccum = false; - m_EarlyClip = false; - m_YAxisUp = false; - m_InsertPalette = false; - m_ReclaimOnResize = false; - m_CurvesSet = false; - m_NumChannels = 3; - m_BytesPerChannel = 1; - m_SuperSize = 0; - m_Transparency = false; ThreadCount(Timing::ProcessorCount()); - m_Callback = nullptr; - m_ProgressParameter = nullptr; - m_LastTemporalSample = 0; - m_LastIter = 0; - m_LastIterPercent = 0; - m_InteractiveFilter = eInteractiveFilter::FILTER_LOG; - m_Priority = eThreadPriority::NORMAL; - m_ProcessState = eProcessState::NONE; - m_ProcessAction = eProcessAction::FULL_RENDER; - m_InRender = false; - m_InFinalAccum = false; } /// diff --git a/Source/Ember/RendererBase.h b/Source/Ember/RendererBase.h index fbdcabc..36bb163 100644 --- a/Source/Ember/RendererBase.h +++ b/Source/Ember/RendererBase.h @@ -21,10 +21,13 @@ namespace EmberNs class EMBER_API RenderCallback { public: + RenderCallback() = default; + RenderCallback(RenderCallback& callback) = delete; + /// /// Virtual destructor to ensure anything declared in derived classes gets cleaned up. /// - virtual ~RenderCallback() { } + virtual ~RenderCallback() = default; /// /// Empty progress function to be implemented in derived classes to take action on progress updates. @@ -91,10 +94,11 @@ enum class eRendererType : et { CPU_RENDERER, OPENCL_RENDERER }; /// class EMBER_API RendererBase : public EmberReport { -//using EmberReport::m_ErrorReport; public: RendererBase(); - virtual ~RendererBase() { } + RendererBase(const RendererBase& renderer) = delete; + RendererBase& operator = (const RendererBase& renderer) = delete; + virtual ~RendererBase() = default; //Non-virtual processing functions. void ChangeVal(std::function func, eProcessAction action); @@ -106,10 +110,8 @@ public: //Virtual processing functions. virtual bool Ok() const; virtual size_t MemoryAvailable(); - virtual void SetEmber(Ember& ember, eProcessAction action = eProcessAction::FULL_RENDER) { } - virtual void SetEmber(vector>& embers) { } - virtual void SetEmber(Ember& ember, eProcessAction action = eProcessAction::FULL_RENDER) { } - virtual void SetEmber(vector>& embers) { } + virtual void SetEmber(const Ember& ember, eProcessAction action = eProcessAction::FULL_RENDER) { } + virtual void SetEmber(const Ember& ember, eProcessAction action = eProcessAction::FULL_RENDER) { } virtual bool RandVec(vector>& randVec); //Abstract processing functions. @@ -120,7 +122,7 @@ public: virtual void ComputeQuality() = 0; virtual void ComputeCamera() = 0; virtual eRenderStatus Run(vector& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) = 0; - virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) = 0; + virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool hexPalette = true) = 0; virtual DensityFilterBase* GetDensityFilter() = 0; //Non-virtual renderer properties, getters only. @@ -193,41 +195,41 @@ public: bool InRender(); bool InFinalAccum(); - void* m_ProgressParameter; + void* m_ProgressParameter = nullptr; protected: - bool m_EarlyClip; - bool m_YAxisUp; - bool m_Transparency; - bool m_LockAccum; - bool m_InRender; - bool m_InFinalAccum; - bool m_InsertPalette; - bool m_ReclaimOnResize; - bool m_CurvesSet; - volatile bool m_Abort; + bool m_EarlyClip = false; + bool m_YAxisUp = false; + bool m_Transparency = false; + bool m_LockAccum = false; + bool m_InRender = false; + bool m_InFinalAccum = false; + bool m_InsertPalette = false; + bool m_ReclaimOnResize = false; + bool m_CurvesSet = false; + volatile bool m_Abort = false; size_t m_SuperRasW; size_t m_SuperRasH; - size_t m_SuperSize; + size_t m_SuperSize = 0; size_t m_GutterWidth; size_t m_DensityFilterOffset; - size_t m_NumChannels; - size_t m_BytesPerChannel; + size_t m_NumChannels = 3; + size_t m_BytesPerChannel = 1; size_t m_ThreadsToUse; size_t m_VibGamCount; - size_t m_LastTemporalSample; - size_t m_LastIter; - double m_LastIterPercent; - eThreadPriority m_Priority; - eProcessAction m_ProcessAction; - eProcessState m_ProcessState; - eInteractiveFilter m_InteractiveFilter; + size_t m_LastTemporalSample = 0; + size_t m_LastIter = 0; + double m_LastIterPercent = 0; + eThreadPriority m_Priority = eThreadPriority::NORMAL; + eProcessAction m_ProcessAction = eProcessAction::FULL_RENDER; + eProcessState m_ProcessState = eProcessState::NONE; + eInteractiveFilter m_InteractiveFilter = eInteractiveFilter::FILTER_LOG; EmberStats m_Stats; - RenderCallback* m_Callback; + RenderCallback* m_Callback = nullptr; vector m_SubBatch; vector m_BadVals; vector> m_Rand; - auto_ptr m_TaskGroup; + unique_ptr m_TaskGroup = make_unique(); std::recursive_mutex m_RenderingCs, m_AccumCs, m_FinalAccumCs, m_ResizeCs; Timing m_RenderTimer, m_IterTimer, m_ProgressTimer; }; diff --git a/Source/Ember/SheepTools.h b/Source/Ember/SheepTools.h index 87853c3..60c2f87 100644 --- a/Source/Ember/SheepTools.h +++ b/Source/Ember/SheepTools.h @@ -65,19 +65,14 @@ public: : m_VariationList(VariationList::Instance()) { Timing t; - m_Smooth = true; - m_SheepGen = -1; - m_SheepId = -1; - m_Stagger = 0; - m_OffsetX = 0; - m_OffsetY = 0; m_PaletteList.Add(palettePath); - m_StandardIterator = unique_ptr>(new StandardIterator()); - m_XaosIterator = unique_ptr>(new XaosIterator()); m_Renderer = unique_ptr>(renderer); m_Rand = QTIsaac(ISAAC_INT(t.Tic()), ISAAC_INT(t.Tic() * 2), ISAAC_INT(t.Tic() * 3)); } + SheepTools(const SheepTools& sheepTools) = delete; + SheepTools& operator = (const SheepTools& sheepTools) = delete; + /// /// Create the linear default ember with a random palette. /// @@ -1329,12 +1324,12 @@ public: } private: - bool m_Smooth; - intmax_t m_SheepGen; - intmax_t m_SheepId; - T m_Stagger; - T m_OffsetX; - T m_OffsetY; + bool m_Smooth = true; + intmax_t m_SheepGen = -1; + intmax_t m_SheepId = -1; + T m_Stagger = 0; + T m_OffsetX = 0; + T m_OffsetY = 0; string m_Nick; string m_Url; string m_Id; @@ -1345,8 +1340,8 @@ private: vector m_Hist; EmberToXml m_EmberToXml; Iterator* m_Iterator; - unique_ptr> m_StandardIterator; - unique_ptr> m_XaosIterator; + unique_ptr> m_StandardIterator = make_unique>(); + unique_ptr> m_XaosIterator = make_unique>(); unique_ptr> m_Renderer; QTIsaac m_Rand; PaletteList m_PaletteList; diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h index f90a75a..5f3db64 100644 --- a/Source/Ember/Utils.h +++ b/Source/Ember/Utils.h @@ -72,12 +72,16 @@ class EMBER_API EmberImageComments { public: /// - /// Empty destructor. + /// Basic defaults. + /// + EmberImageComments() = default; + EmberImageComments(const EmberImageComments& comments) = default; + EmberImageComments& operator = (const EmberImageComments& comments) = default; + + /// /// Needed to eliminate warnings about inlining. /// - ~EmberImageComments() - { - } + ~EmberImageComments() = default; /// /// Set all values to the empty string. @@ -304,81 +308,105 @@ static bool ReadFile(const char* filename, string& buf, bool nullTerminate = tru } /// -/// Clear dest and copy all of the elements of vector source with elements of type U to the vector -/// dest with elements of type T. +/// Thin wrapper around std::advance that returns the advanced iterator. +/// Note the passed in iterator is constant so it will not be changed, unlike +/// std::advance does. /// -/// The vector of type T to copy to -/// The vector of type U to copy from -template -static void CopyVec(vector& dest, const vector& source) +/// A const reference to an iterator, a copy of which will be advanced. +/// How far to move the iterator forward +/// A copy of the passed in iterator, advanced the specified number of elements +template +static iter Advance(const iter& it, diff off) { - dest.clear(); - dest.resize(source.size()); - - for (size_t i = 0; i < source.size(); i++) - dest[i] = static_cast(source[i]);//Valid assignment operator between T and U types must be defined somewhere. + auto temp = it; + std::advance(temp, off); + return temp; } /// -/// Clear dest and copy all of the elements of vector source with elements of type U to the vector +/// Clear dest and copy all of the elements of container source with elements of type U to the container /// dest with elements of type T. -/// Call a function on each element after it's been copied. /// -/// The vector of type T to copy to -/// The vector of type U to copy from -/// A function to call on each element after it's copied -template -static void CopyVec(vector& dest, const vector& source, std::function perElementOperation) +/// The container of type Cdest with elements of type T to copy to +/// The container of type Csource with elements of type U to copy from +template class Cdest, template class Csource> +static void CopyCont(Cdest& dest, const Csource& source) { dest.clear(); dest.resize(source.size()); + auto it1 = source.begin(); + auto it2 = dest.begin(); - for (size_t i = 0; i < source.size(); i++) + for (; it1 != source.end(); it1++, it2++) + *it2 = static_cast(*it1);//Valid assignment operator between T and U types must be defined somewhere. +} + +/// +/// Clear dest and copy all of the elements of container source with elements of type U to the container +/// dest with elements of type T. +/// Call a function on each element after it's been copied. +/// +/// The container of type Cdest with elements of type T to copy to +/// The container of type Csource with elements of type U to copy from +/// A function to call on each element after it's copied +template class Cdest, template class Csource> +static void CopyCont(Cdest& dest, const Csource& source, std::function perElementOperation) +{ + dest.clear(); + dest.resize(source.size()); + auto it1 = source.begin(); + auto it2 = dest.begin(); + + for (; it1 != source.end(); it1++, it2++) { - dest[i] = static_cast(source[i]);//Valid assignment operator between T and U types must be defined somewhere. - perElementOperation(dest[i]); + *it2 = static_cast(*it1);//Valid assignment operator between T and U types must be defined somewhere. + perElementOperation(*it2); } } /// -/// Clear a vector of pointers to any type by checking each element for nullptr and calling delete on it, then clearing the entire vector. +/// Clear a container of pointers to any type by checking each element for nullptr and calling delete on it, then clearing the entire vector. /// Optionally call array delete if the elements themselves are pointers to dynamically allocated arrays. /// /// The vector to be cleared /// Whether to call delete or delete []. Default: false. -template -static void ClearVec(vector& vec, bool arrayDelete = false) +template class C> +static void ClearVec(C& cont, bool arrayDelete = false) { - for (size_t i = 0; i < vec.size(); i++) + for (auto& it : cont) { - if (vec[i]) + if (it) { if (arrayDelete) - delete [] vec[i]; + delete [] it; else - delete vec[i]; + delete it; } - vec[i] = nullptr; + it = nullptr; } - vec.clear(); + cont.clear(); } /// /// Determine whether all elements in two containers are equal. +/// The container types do not have to match, but their element types do. /// /// The first collection to compare /// The second collection to compare /// True if the sizes and all elements in both collections are equal, else false. -template -static bool Equal(const T& c1, const T& c2) +template class C1, template class C2> +static bool Equal(const C1& c1, const C2& c2) { bool equal = c1.size() == c2.size(); if (equal) { - for (auto it1 = c1.begin(), it2 = c2.begin(); it1 != c1.end(); ++it1, ++it2) + auto it1 = c1.begin(); + auto it2 = c2.begin(); + + for (; it1 != c1.end(); ++it1, ++it2) { if (*it1 != *it2) { @@ -443,10 +471,7 @@ static inline T Clamp(T val, T min, T max) } template <> -#ifdef _WIN32 - static -#endif -float Clamp(float val, float min, float max) +STATIC float Clamp(float val, float min, float max) { if (val < min) return min; @@ -459,10 +484,7 @@ float Clamp(float val, float min, float max) } template <> -#ifdef _WIN32 - static -#endif -double Clamp(double val, double min, double max) +STATIC double Clamp(double val, double min, double max) { if (val < min) return min; @@ -512,10 +534,7 @@ static inline void ClampRef(T& val, T min, T max) } template <> -#ifdef _WIN32 - static -#endif -void ClampRef(float& val, float min, float max) +STATIC void ClampRef(float& val, float min, float max) { if (val < min) val = min; @@ -526,10 +545,7 @@ void ClampRef(float& val, float min, float max) } template <> -#ifdef _WIN32 - static -#endif -void ClampRef(double& val, double min, double max) +STATIC void ClampRef(double& val, double min, double max) { if (val < min) val = min; @@ -552,20 +568,14 @@ static inline void ClampLteRef(T& val, T lte) } template <> -#ifdef _WIN32 - static -#endif -void ClampLteRef(float& val, float lte) +STATIC void ClampLteRef(float& val, float lte) { if (val > lte || !std::isfinite(val)) val = lte; } template <> -#ifdef _WIN32 - static -#endif -void ClampLteRef(double& val, double lte) +STATIC void ClampLteRef(double& val, double lte) { if (val > lte || !std::isfinite(val)) val = lte; @@ -585,10 +595,7 @@ static inline T ClampGte(T val, T gte) } template <> -#ifdef _WIN32 - static -#endif -float ClampGte(float val, float gte) +STATIC float ClampGte(float val, float gte) { if (val < gte || !std::isfinite(val)) return gte; @@ -597,10 +604,7 @@ float ClampGte(float val, float gte) } template <> -#ifdef _WIN32 - static -#endif -double ClampGte(double val, double gte) +STATIC double ClampGte(double val, double gte) { if (val < gte || !std::isfinite(val)) return gte; @@ -621,20 +625,14 @@ static inline void ClampGteRef(T& val, T gte) } template <> -#ifdef _WIN32 - static -#endif -void ClampGteRef(float& val, float gte) +STATIC void ClampGteRef(float& val, float gte) { if (val < gte || !std::isfinite(val)) val = gte; } template <> -#ifdef _WIN32 - static -#endif -void ClampGteRef(double& val, double gte) +STATIC void ClampGteRef(double& val, double gte) { if (val < gte || !std::isfinite(val)) val = gte; @@ -721,19 +719,13 @@ static inline T SafeTan(T x) } template <> -#ifdef _WIN32 - static -#endif -float SafeTan(float x) +STATIC float SafeTan(float x) { return std::tan(Clamp(x, FLOAT_MIN_TAN, FLOAT_MAX_TAN)); } template <> -#ifdef _WIN32 - static -#endif -double SafeTan(double x) +STATIC double SafeTan(double x) { return std::tan(x); } @@ -940,10 +932,7 @@ static inline T Arg(char* name, T def) /// The default value to return if the environment variable was not present /// The value of the specified environment variable if found, else default template <> -#ifdef _WIN32 - static -#endif -bool Arg(char* name, bool def) +STATIC bool Arg(char* name, bool def) { return (Arg(name, -999) != -999) ? true : def; } @@ -955,10 +944,7 @@ bool Arg(char* name, bool def) /// The default value to return if the environment variable was not present /// The value of the specified environment variable if found, else default template <> -#ifdef _WIN32 - static -#endif -string Arg(char* name, string def) +STATIC string Arg(char* name, string def) { char* ch; string returnVal; diff --git a/Source/Ember/Xform.h b/Source/Ember/Xform.h index aebc342..e8d6bf5 100644 --- a/Source/Ember/Xform.h +++ b/Source/Ember/Xform.h @@ -69,9 +69,9 @@ public: T pe = 1, T pc = 0, T pf = 0) + : Xform() { - Init(); m_Weight = weight; m_ColorX = colorX; m_ColorSpeed = colorSpeed; @@ -184,8 +184,8 @@ public: if (!m_ParentEmber && (typeid(T) == typeid(U))) m_ParentEmber = reinterpret_cast*>(xform.ParentEmber()); - CopyVec(m_Xaos, xform.XaosVec()); - CopyVec(m_Motion, xform.m_Motion); + CopyCont(m_Xaos, xform.XaosVec());// needed?//TODO + CopyCont(m_Motion, xform.m_Motion); m_Name = xform.m_Name; return *this; } diff --git a/Source/Ember/XmlToEmber.h b/Source/Ember/XmlToEmber.h index 1dbbdf1..bf69e1b 100644 --- a/Source/Ember/XmlToEmber.h +++ b/Source/Ember/XmlToEmber.h @@ -296,14 +296,15 @@ public: } /// - /// Parse the specified buffer and place the results in the vector of embers passed in. + /// Parse the specified buffer and place the results in the container of embers passed in. /// /// The buffer to parse /// Full path and filename, optionally empty /// The newly constructed embers based on what was parsed /// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. Default: true. /// True if there were no errors, else false. - bool Parse(byte* buf, const char* filename, vector>& embers, bool useDefaults = true) + template class C> + bool Parse(byte* buf, const char* filename, C, Alloc>& embers, bool useDefaults = true) { char* bn; const char* xmlPtr; @@ -318,7 +319,7 @@ public: //Parse XML string into internal document. xmlPtr = CX(&buf[0]); bufSize = strlen(xmlPtr); - embers.reserve(bufSize / 2500);//The Xml text for an ember is around 2500 bytes, but can be much more. Pre-allocate to aovid unnecessary resizing. + //embers.reserve(bufSize / 2500);//The Xml text for an ember is around 2500 bytes, but can be much more. Pre-allocate to aovid unnecessary resizing. doc = xmlReadMemory(xmlPtr, int(bufSize), filename, "ISO-8859-1", XML_PARSE_NONET);//Forbid network access during read. //t.Toc("xmlReadMemory"); @@ -336,6 +337,8 @@ public: ScanForEmberNodes(rootnode, bn, embers, useDefaults); xmlFreeDoc(doc); emberSize = embers.size(); + auto b = embers.begin(); + auto secondToLast = Advance(embers.begin(), emberSize - 2); //t.Toc("ScanForEmberNodes"); //Check to see if the first control point or the second-to-last @@ -343,11 +346,11 @@ public: //and should be reset to linear (with a warning). if (emberSize > 0) { - if (embers[0].m_Interp == eInterp::EMBER_INTERP_SMOOTH) - embers[0].m_Interp = eInterp::EMBER_INTERP_LINEAR; + if (b->m_Interp == eInterp::EMBER_INTERP_SMOOTH) + b->m_Interp = eInterp::EMBER_INTERP_LINEAR; - if (emberSize >= 2 && embers[emberSize - 2].m_Interp == eInterp::EMBER_INTERP_SMOOTH) - embers[emberSize - 2].m_Interp = eInterp::EMBER_INTERP_LINEAR; + if (emberSize >= 2 && secondToLast->m_Interp == eInterp::EMBER_INTERP_SMOOTH) + secondToLast->m_Interp = eInterp::EMBER_INTERP_LINEAR; } //Finally, ensure that consecutive 'rotate' parameters never exceed @@ -355,17 +358,22 @@ public: //An adjustment of +/- 360 degrees is made until this is true. if (emberSize > 1) { - for (size_t i = 1; i < emberSize; i++) + auto prev = embers.begin(); + auto second = Advance(embers.begin(), 1); + + for (auto it = second; it != embers.end(); ++it) { //Only do this adjustment if not in compat mode. - if (embers[i - 1].m_AffineInterp != eAffineInterp::AFFINE_INTERP_COMPAT && embers[i - 1].m_AffineInterp != eAffineInterp::AFFINE_INTERP_OLDER) + if (prev->m_AffineInterp != eAffineInterp::AFFINE_INTERP_COMPAT && prev->m_AffineInterp != eAffineInterp::AFFINE_INTERP_OLDER) { - while (embers[i].m_Rotate < embers[i - 1].m_Rotate - 180) - embers[i].m_Rotate += 360; + while (it->m_Rotate < prev->m_Rotate - 180) + it->m_Rotate += 360; - while (embers[i].m_Rotate > embers[i - 1].m_Rotate + 180) - embers[i].m_Rotate -= 360; + while (it->m_Rotate > prev->m_Rotate + 180) + it->m_Rotate -= 360; } + + prev = it; } } @@ -373,14 +381,16 @@ public: } /// - /// Parse the specified file and place the results in the vector of embers passed in. + /// Parse the specified file and place the results in the container of embers passed in. /// This will strip out ampersands because the Xml parser can't handle them. /// /// Full path and filename /// The newly constructed embers based on what was parsed /// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. Default: true. /// True if there were no errors, else false. - bool Parse(const char* filename, vector>& embers, bool useDefaults = true) + //template class C> + template class C> + bool Parse(const char* filename, C, Alloc>& embers, bool useDefaults = true) { const char* loc = __FUNCTION__; string buf; @@ -465,13 +475,14 @@ public: private: /// - /// Scan the file for ember nodes, and parse them out into the vector of embers. + /// Scan the file for ember nodes, and parse them out into the container of embers. /// /// The current node to parse /// The full path and filename /// The newly constructed embers based on what was parsed /// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. - void ScanForEmberNodes(xmlNode* curNode, char* parentFile, vector>& embers, bool useDefaults) + template class C> + void ScanForEmberNodes(xmlNode* curNode, char* parentFile, C, Alloc>& embers, bool useDefaults) { bool parseEmberSuccess; xmlNodePtr thisNode = nullptr; diff --git a/Source/EmberAnimate/EmberAnimate.cpp b/Source/EmberAnimate/EmberAnimate.cpp index 3542585..77c5f90 100644 --- a/Source/EmberAnimate/EmberAnimate.cpp +++ b/Source/EmberAnimate/EmberAnimate.cpp @@ -38,7 +38,7 @@ bool EmberAnimate(EmberOptions& opt) const vector> devices = Devices(opt.Devices()); std::atomic atomfTime; vector threadVec; - unique_ptr> progress; + auto progress = make_unique>(); vector>> renderers; vector errorReport; std::recursive_mutex verboseCs; @@ -58,10 +58,7 @@ bool EmberAnimate(EmberOptions& opt) } if (opt.DoProgress()) - { - progress = unique_ptr>(new RenderProgress()); renderers[0]->Callback(progress.get()); - } cout << "Using OpenCL to render.\n"; @@ -103,10 +100,7 @@ bool EmberAnimate(EmberOptions& opt) } if (opt.DoProgress()) - { - progress = unique_ptr>(new RenderProgress()); tempRenderer->Callback(progress.get()); - } if (opt.ThreadCount() == 0) { @@ -304,7 +298,7 @@ bool EmberAnimate(EmberOptions& opt) for (auto& r : renderers) { - r->SetEmber(embers); + r->SetExternalEmbersPointer(&embers);//All will share a pointer to the original vector to conserve memory with large files. Ok because the vec doesn't get modified. r->EarlyClip(opt.EarlyClip()); r->YAxisUp(opt.YAxisUp()); r->LockAccum(opt.LockAccum()); @@ -390,12 +384,12 @@ bool EmberAnimate(EmberOptions& opt) } Interpolater::Interpolate(embers, localTime, 0, centerEmber);//Get center flame. - emberToXml.Save(flameName, centerEmber, opt.PrintEditDepth(), true, opt.IntPalette(), opt.HexPalette(), true, false, false); + emberToXml.Save(flameName, centerEmber, opt.PrintEditDepth(), true, opt.HexPalette(), true, false, false); centerEmber.Clear(); } stats = renderer->Stats(); - comments = renderer->ImageComments(stats, opt.PrintEditDepth(), opt.IntPalette(), opt.HexPalette()); + comments = renderer->ImageComments(stats, opt.PrintEditDepth(), opt.HexPalette()); os.str(""); size_t iterCount = renderer->TotalIterCount(1); os << comments.m_NumIters << " / " << iterCount << " (" << std::fixed << std::setprecision(2) << ((double(stats.m_Iters) / double(iterCount)) * 100) << "%)"; diff --git a/Source/EmberCL/DEOpenCLKernelCreator.cpp b/Source/EmberCL/DEOpenCLKernelCreator.cpp index 2c2910a..f794617 100644 --- a/Source/EmberCL/DEOpenCLKernelCreator.cpp +++ b/Source/EmberCL/DEOpenCLKernelCreator.cpp @@ -16,14 +16,6 @@ DEOpenCLKernelCreator::DEOpenCLKernelCreator(bool doublePrecision, bool nVidia) { m_DoublePrecision = doublePrecision; m_NVidia = nVidia; -#ifdef ROW_ONLY_DE - m_LogScaleAssignDEEntryPoint = "LogScaleAssignDensityFilterKernel"; - m_GaussianDEWithoutSsEntryPoint = "GaussianDEWithoutSsKernel"; - m_GaussianDESsWithScfEntryPoint = "GaussianDESsWithScfKernel"; - m_GaussianDESsWithoutScfEntryPoint = "GaussianDESsWithoutScfKernel"; - m_GaussianDEWithoutSsNoCacheEntryPoint = "GaussianDEWithoutSsNoCacheKernel"; - m_GaussianDESsWithScfNoCacheEntryPoint = "GaussianDESsWithScfNoCacheKernel"; - m_GaussianDESsWithoutScfNoCacheEntryPoint = "GaussianDESsWithoutScfNoCacheKernel"; m_LogScaleAssignDEKernel = CreateLogScaleAssignDEKernelString(); m_GaussianDEWithoutSsKernel = CreateGaussianDEKernel(1); m_GaussianDESsWithScfKernel = CreateGaussianDEKernel(2); @@ -31,22 +23,6 @@ DEOpenCLKernelCreator::DEOpenCLKernelCreator(bool doublePrecision, bool nVidia) m_GaussianDEWithoutSsNoCacheKernel = CreateGaussianDEKernelNoLocalCache(1); m_GaussianDESsWithScfNoCacheKernel = CreateGaussianDEKernelNoLocalCache(2); m_GaussianDESsWithoutScfNoCacheKernel = CreateGaussianDEKernelNoLocalCache(3); -#else - m_LogScaleAssignDEEntryPoint = "LogScaleAssignDensityFilterKernel"; - m_GaussianDEWithoutSsEntryPoint = "GaussianDEWithoutSsKernel"; - m_GaussianDESsWithScfEntryPoint = "GaussianDESsWithScfKernel"; - m_GaussianDESsWithoutScfEntryPoint = "GaussianDESsWithoutScfKernel"; - m_GaussianDEWithoutSsNoCacheEntryPoint = "GaussianDEWithoutSsNoCacheKernel"; - m_GaussianDESsWithScfNoCacheEntryPoint = "GaussianDESsWithScfNoCacheKernel"; - m_GaussianDESsWithoutScfNoCacheEntryPoint = "GaussianDESsWithoutScfNoCacheKernel"; - m_LogScaleAssignDEKernel = CreateLogScaleAssignDEKernelString(); - m_GaussianDEWithoutSsKernel = CreateGaussianDEKernel(1); - m_GaussianDESsWithScfKernel = CreateGaussianDEKernel(2); - m_GaussianDESsWithoutScfKernel = CreateGaussianDEKernel(3); - m_GaussianDEWithoutSsNoCacheKernel = CreateGaussianDEKernelNoLocalCache(1); - m_GaussianDESsWithScfNoCacheKernel = CreateGaussianDEKernelNoLocalCache(2); - m_GaussianDESsWithoutScfNoCacheKernel = CreateGaussianDEKernelNoLocalCache(3); -#endif } /// @@ -64,8 +40,6 @@ const string& DEOpenCLKernelCreator::LogScaleAssignDEEntryPoint() const { return /// The kernel source const string& DEOpenCLKernelCreator::GaussianDEKernel(size_t ss, uint filterWidth) const { -#ifndef ROW_ONLY_DE - if (filterWidth > MaxDEFilterSize()) { if (ss > 1) @@ -79,7 +53,6 @@ const string& DEOpenCLKernelCreator::GaussianDEKernel(size_t ss, uint filterWidt return m_GaussianDEWithoutSsNoCacheKernel;//SS 1; } else//Use cache. -#endif { if (ss > 1) { @@ -101,8 +74,6 @@ const string& DEOpenCLKernelCreator::GaussianDEKernel(size_t ss, uint filterWidt /// The name of the density estimation filtering entry point kernel function const string& DEOpenCLKernelCreator::GaussianDEEntryPoint(size_t ss, uint filterWidth) const { -#ifndef ROW_ONLY_DE - if (filterWidth > MaxDEFilterSize()) { if (ss > 1) @@ -116,7 +87,6 @@ const string& DEOpenCLKernelCreator::GaussianDEEntryPoint(size_t ss, uint filter return m_GaussianDEWithoutSsNoCacheEntryPoint; } else -#endif { if (ss > 1) { @@ -206,210 +176,6 @@ string DEOpenCLKernelCreator::CreateLogScaleAssignDEKernelString() return os.str(); } -#ifdef ROW_ONLY_DE -string DEOpenCLKernelCreator::CreateGaussianDEKernel(size_t ss) -{ - bool doSS = ss > 1; - bool doScf = !(ss & 1); - ostringstream os; - os << - ConstantDefinesString(m_DoublePrecision) << - DensityFilterCLStructString << - UnionCLStructString << - "__kernel void " << GaussianDEEntryPoint(ss, MaxDEFilterSize()) << "(\n" << - " const __global real4_bucket* histogram,\n" - " __global real4reals_bucket* accumulator,\n" - " __constant DensityFilterCL* densityFilter,\n" - " const __global real_bucket_t* filterCoefs,\n" - " const __global real_bucket_t* filterWidths,\n" - " const __global uint* coefIndices,\n" - " const uint chunkSizeW,\n" - " const uint chunkSizeH,\n" - " const uint colChunkPass,\n" - " const uint rowChunkPass\n" - "\t)\n" - "{\n" - " uint rowsToProcess = 32;\n"//Rows to process. - "\n" - " if (((((BLOCK_ID_X * chunkSizeW) + colChunkPass) * BLOCK_SIZE_X) + THREAD_ID_X >= densityFilter->m_SuperRasW) ||\n" - " ((((BLOCK_ID_Y * chunkSizeH) + rowChunkPass) * rowsToProcess) + THREAD_ID_Y >= densityFilter->m_SuperRasH))\n" - " return;\n" - "\n"; - - if (doSS) - { - os << - " uint ss = (uint)floor((real_bucket_t)densityFilter->m_Supersample / 2.0);\n" - " int densityBoxLeftX;\n" - " int densityBoxRightX;\n" - " int densityBoxTopY;\n" - " int densityBoxBottomY;\n" - "\n"; - - if (doScf) - os << - " real_bucket_t scfact = pow(densityFilter->m_Supersample / (densityFilter->m_Supersample + (real_bucket_t)1.0), (real_bucket_t)2.0);\n"; - } - - os << - " uint fullTempBoxWidth;\n" - " uint leftBound, rightBound, topBound, botBound;\n" - " uint blockHistStartRow, blockHistEndRow, histCol;\n" - " uint blockHistStartCol, boxReadStartCol, boxReadEndCol;\n" - " uint accumWriteStartCol, colsToWrite, colOffset, colsToWriteOffset;\n" - " int histRow, filterRow, accumWriteOffset;\n" - "\n" - " fullTempBoxWidth = BLOCK_SIZE_X + (densityFilter->m_FilterWidth * 2);\n" - //Compute the bounds of the area to be sampled, which is just the ends minus the super sample minus 1. - " leftBound = densityFilter->m_Supersample - 1;\n" - " rightBound = densityFilter->m_SuperRasW - (densityFilter->m_Supersample - 1);\n" - " topBound = densityFilter->m_Supersample - 1;\n" - " botBound = densityFilter->m_SuperRasH - (densityFilter->m_Supersample - 1);\n" - "\n" - //Start and end values are the indices in the histogram read from - //and written to in the accumulator. They are not the indices for the local block of data. - //Before computing local offsets, compute the global offsets first to determine if any rows or cols fall outside of the bounds. - " blockHistStartRow = min(botBound, topBound + (((BLOCK_ID_Y * chunkSizeH) + rowChunkPass) * rowsToProcess));\n"//The first histogram row this block will process. - " blockHistEndRow = min(botBound, blockHistStartRow + rowsToProcess);\n"//The last histogram row this block will process, clamped to the last row. - " blockHistStartCol = min(rightBound, leftBound + (((BLOCK_ID_X * chunkSizeW) + colChunkPass) * BLOCK_SIZE_X));\n"//The first histogram column this block will process. - " boxReadStartCol = densityFilter->m_FilterWidth - min(densityFilter->m_FilterWidth, blockHistStartCol);\n"//The first box col this block will read from when copying to the accumulator. - " boxReadEndCol = densityFilter->m_FilterWidth + min(densityFilter->m_FilterWidth + BLOCK_SIZE_X, densityFilter->m_SuperRasW - blockHistStartCol);\n"//The last box col this block will read from when copying to the accumulator. - "\n" - //Last, the indices in the global accumulator that the local bounds will be writing to. - " accumWriteStartCol = blockHistStartCol - min(densityFilter->m_FilterWidth, blockHistStartCol);\n"//The first column in the accumulator this block will write to. - " colsToWrite = ceil((real_bucket_t)(boxReadEndCol - boxReadStartCol) / (real_bucket_t)BLOCK_SIZE_X);\n"//Elements per thread to be written to the accumulator. - " histCol = blockHistStartCol + THREAD_ID_X;\n"//The histogram column this individual thread will be reading from. - "\n" - " if (histCol >= rightBound)\n" - " return;\n" - "\n" - //Compute the col position in this local box to serve as the center position - //from which filter application offsets are computed. - //These are the local indices for the local data that are temporarily accumulated to before - //writing out to the global accumulator. - " uint boxCol = densityFilter->m_FilterWidth + THREAD_ID_X;\n" - " uint colsToZeroOffset, colsToZero = ceil((real_bucket_t)fullTempBoxWidth / (real_bucket_t)(BLOCK_SIZE_X));\n"//Usually is 2. - " int i, j, k, jmin, jmax;\n" - " uint filterSelectInt, filterCoefIndex;\n" - " real_bucket_t cacheLog;\n" - " real_bucket_t filterSelect;\n" - " real4_bucket bucket;\n" - ; - os << " __local real4reals_bucket filterBox[192];\n";//Must be >= fullTempBoxWidth. - os << - "\n" - " colsToZeroOffset = colsToZero * THREAD_ID_X;\n" - " colsToWriteOffset = colsToWrite * THREAD_ID_X;\n" - " k = (int)densityFilter->m_FilterWidth;\n"//Need a signed int to use below, really is filter width, but reusing a variable to save space. - "\n" - " for (histRow = blockHistStartRow; histRow < blockHistEndRow; histRow++)\n"//Process pixels by row, for 32 rows. - " {\n" - " bucket = histogram[(histRow * densityFilter->m_SuperRasW) + histCol];\n" - "\n" - " if (bucket.w != 0)\n" - " cacheLog = (densityFilter->m_K1 * log(1.0 + bucket.w * densityFilter->m_K2)) / bucket.w;\n" - "\n"; - - if (doSS) - { - os << - " filterSelect = 0;\n" - " densityBoxLeftX = histCol - min(histCol, ss);\n" - " densityBoxRightX = histCol + min(ss, (densityFilter->m_SuperRasW - histCol) - 1);\n" - " densityBoxTopY = histRow - min((uint)histRow, ss);\n" - " densityBoxBottomY = histRow + min(ss, (densityFilter->m_SuperRasH - histRow) - 1);\n" - "\n" - " for (j = densityBoxTopY; j <= densityBoxBottomY; j++)\n" - " {\n" - " for (i = densityBoxLeftX; i <= densityBoxRightX; i++)\n" - " {\n" - " filterSelect += histogram[(j * densityFilter->m_SuperRasW) + i].w;\n" - " }\n" - " }\n" - "\n"; - - if (doScf) - os << " filterSelect *= scfact;\n"; - } - else - { - os - << " filterSelect = bucket.w;\n"; - } - - os << - "\n" - " if (filterSelect > densityFilter->m_MaxFilteredCounts)\n" - " filterSelectInt = densityFilter->m_MaxFilterIndex;\n" - " else if (filterSelect <= DE_THRESH)\n" - " filterSelectInt = (int)ceil(filterSelect) - 1;\n" - " else if (filterSelect != 0)\n" - " filterSelectInt = (int)DE_THRESH + (int)floor(pow((real_bucket_t)(filterSelect - DE_THRESH), densityFilter->m_Curve));\n" - " else\n" - " filterSelectInt = 0;\n" - "\n" - " if (filterSelectInt > densityFilter->m_MaxFilterIndex)\n" - " filterSelectInt = densityFilter->m_MaxFilterIndex;\n" - "\n" - " filterCoefIndex = filterSelectInt * densityFilter->m_KernelSize;\n" - "\n" - //With this new method, only accumulate to the temp local buffer first. Write to the final accumulator last. - //For each loop through, note that there is a local memory barrier call inside of each call to AddToAccumNoCheck(). - //If this isn't done, pixel errors occurr and even an out of resources error occurrs because too many writes are done to the same place in memory at once. - " jmin = min(k, histRow);\n" - " jmax = (int)min((densityFilter->m_SuperRasH - 1) - histRow, densityFilter->m_FilterWidth);\n" - "\n" - " for (j = -jmin; j <= jmax; j++)\n" - " {\n" - " for (i = 0; i < colsToZero && (colsToZeroOffset + i) < fullTempBoxWidth; i++)\n"//Each thread zeroizes a few columns. - " {\n" - " filterBox[colsToZeroOffset + i].m_Real4 = 0;\n" - " }\n" - "\n" - " barrier(CLK_LOCAL_MEM_FENCE);\n" - "\n" - " if (bucket.w != 0)\n" - " {\n" - " filterRow = abs(j) * (densityFilter->m_FilterWidth + 1);\n" - "\n" - " for (i = -k; i <= k; i++)\n" - " {\n" - " filterSelectInt = filterCoefIndex + coefIndices[filterRow + abs(i)];\n"//Really is filterCoeffIndexPlusOffset, but reusing a variable to save space. - " filterBox[i + boxCol].m_Real4 += (bucket * (filterCoefs[filterSelectInt] * cacheLog));\n" - " }\n" - " }\n" - "\n" - " barrier(CLK_LOCAL_MEM_FENCE);\n" - "\n" - //At this point, all threads in this block have applied the filter to their surrounding pixels and stored the results in the temp local box. - //Add the cells of it that are in bounds to the global accumulator. - //Compute offsets in local box to read from, and offsets into global accumulator to write to. - //Use a method here that is similar to the zeroization above: Each thread (column) in the first row iterates through all of the - //rows and adds a few columns to the accumulator. - //" if (THREAD_ID_X == 0)\n" - //" {\n" - //" for (int kk = boxReadStartCol, i = 0; kk < boxReadEndCol; kk++, i++)\n"//Each thread writes a few columns.//Could do away with kk//TODO//OPT - //" {\n" - //" accumulator[((histRow + j) * densityFilter->m_SuperRasW) + (accumWriteStartCol + i)].m_Real4 += filterBox[kk].m_Real4;\n" - //" }\n" - //" }\n" - " accumWriteOffset = ((histRow + j) * densityFilter->m_SuperRasW) + accumWriteStartCol;\n" - "\n" - " for (i = 0; i < colsToWrite; i++)\n"//Each thread writes a few columns. - " {\n" - " colOffset = colsToWriteOffset + i;\n" - "\n" - " if (boxReadStartCol + colOffset < boxReadEndCol)\n" - " accumulator[accumWriteOffset + colOffset].m_Real4 += filterBox[boxReadStartCol + colOffset].m_Real4;\n" - " }\n" - " }\n"//for() filter rows. - " barrier(CLK_GLOBAL_MEM_FENCE);\n" - " }\n"//for() histogram rows. - "}\n"; - return os.str(); -} - -#else /// /// Create the gaussian density filtering kernel string. /// 6 different methods of processing were tried before settling on this final and fastest 7th one. @@ -660,7 +426,6 @@ string DEOpenCLKernelCreator::CreateGaussianDEKernel(size_t ss) "}\n"; return os.str(); } -#endif /// /// Create the gaussian density filtering kernel string, but use no local cache and perform diff --git a/Source/EmberCL/DEOpenCLKernelCreator.h b/Source/EmberCL/DEOpenCLKernelCreator.h index c396572..59087c1 100644 --- a/Source/EmberCL/DEOpenCLKernelCreator.h +++ b/Source/EmberCL/DEOpenCLKernelCreator.h @@ -8,8 +8,6 @@ /// DEOpenCLKernelCreator class. /// -//#define ROW_ONLY_DE 1 - namespace EmberCLns { /// @@ -51,25 +49,25 @@ private: string CreateGaussianDEKernelNoLocalCache(size_t ss); string m_LogScaleAssignDEKernel; - string m_LogScaleAssignDEEntryPoint; + string m_LogScaleAssignDEEntryPoint = "LogScaleAssignDensityFilterKernel"; string m_GaussianDEWithoutSsKernel; - string m_GaussianDEWithoutSsEntryPoint; + string m_GaussianDEWithoutSsEntryPoint = "GaussianDEWithoutSsKernel"; string m_GaussianDESsWithScfKernel; - string m_GaussianDESsWithScfEntryPoint; + string m_GaussianDESsWithScfEntryPoint = "GaussianDESsWithScfKernel"; string m_GaussianDESsWithoutScfKernel; - string m_GaussianDESsWithoutScfEntryPoint; + string m_GaussianDESsWithoutScfEntryPoint = "GaussianDESsWithoutScfKernel"; string m_GaussianDEWithoutSsNoCacheKernel; - string m_GaussianDEWithoutSsNoCacheEntryPoint; + string m_GaussianDEWithoutSsNoCacheEntryPoint = "GaussianDEWithoutSsNoCacheKernel"; string m_GaussianDESsWithScfNoCacheKernel; - string m_GaussianDESsWithScfNoCacheEntryPoint; + string m_GaussianDESsWithScfNoCacheEntryPoint = "GaussianDESsWithScfNoCacheKernel"; string m_GaussianDESsWithoutScfNoCacheKernel; - string m_GaussianDESsWithoutScfNoCacheEntryPoint; + string m_GaussianDESsWithoutScfNoCacheEntryPoint = "GaussianDESsWithoutScfNoCacheKernel"; bool m_DoublePrecision; bool m_NVidia; diff --git a/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp b/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp index a595d41..d8ba24c 100644 --- a/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp +++ b/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp @@ -10,22 +10,14 @@ namespace EmberCLns FinalAccumOpenCLKernelCreator::FinalAccumOpenCLKernelCreator(bool doublePrecision) { m_DoublePrecision = doublePrecision; - m_GammaCorrectionWithAlphaCalcEntryPoint = "GammaCorrectionWithAlphaCalcKernel"; - m_GammaCorrectionWithoutAlphaCalcEntryPoint = "GammaCorrectionWithoutAlphaCalcKernel"; - m_GammaCorrectionWithAlphaCalcKernel = CreateGammaCorrectionKernelString(true); - m_GammaCorrectionWithoutAlphaCalcKernel = CreateGammaCorrectionKernelString(false); - m_FinalAccumEarlyClipEntryPoint = "FinalAccumEarlyClipKernel"; - m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel"; - m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel"; + m_GammaCorrectionWithAlphaCalcKernel = CreateGammaCorrectionKernelString(true); + m_GammaCorrectionWithoutAlphaCalcKernel = CreateGammaCorrectionKernelString(false); m_FinalAccumEarlyClipKernel = CreateFinalAccumKernelString(true, false, false); m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true, true, true); m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true, false, true); - m_FinalAccumLateClipEntryPoint = "FinalAccumLateClipKernel"; - m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel"; - m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel"; - m_FinalAccumLateClipKernel = CreateFinalAccumKernelString(false, false, false); - m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, true, true); - m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, false, true); + m_FinalAccumLateClipKernel = CreateFinalAccumKernelString(false, false, false); + m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, true, true); + m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, false, true); } /// diff --git a/Source/EmberCL/FinalAccumOpenCLKernelCreator.h b/Source/EmberCL/FinalAccumOpenCLKernelCreator.h index 1018768..bd66e93 100644 --- a/Source/EmberCL/FinalAccumOpenCLKernelCreator.h +++ b/Source/EmberCL/FinalAccumOpenCLKernelCreator.h @@ -58,24 +58,24 @@ private: string CreateCalcNewRgbFunctionString(bool globalBucket); string m_GammaCorrectionWithAlphaCalcKernel; - string m_GammaCorrectionWithAlphaCalcEntryPoint; + string m_GammaCorrectionWithAlphaCalcEntryPoint = "GammaCorrectionWithAlphaCalcKernel"; string m_GammaCorrectionWithoutAlphaCalcKernel; - string m_GammaCorrectionWithoutAlphaCalcEntryPoint; + string m_GammaCorrectionWithoutAlphaCalcEntryPoint = "GammaCorrectionWithoutAlphaCalcKernel"; string m_FinalAccumEarlyClipKernel;//False, false. - string m_FinalAccumEarlyClipEntryPoint; + string m_FinalAccumEarlyClipEntryPoint = "FinalAccumEarlyClipKernel"; string m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel;//True, true. - string m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint; + string m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel"; string m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel;//False, true. - string m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint; + string m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel"; string m_FinalAccumLateClipKernel;//False, false. - string m_FinalAccumLateClipEntryPoint; + string m_FinalAccumLateClipEntryPoint = "FinalAccumLateClipKernel"; string m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel;//True, true. - string m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint; + string m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel"; string m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel;//False, true. - string m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint; + string m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel"; string m_Empty; bool m_DoublePrecision; diff --git a/Source/EmberCL/IterOpenCLKernelCreator.cpp b/Source/EmberCL/IterOpenCLKernelCreator.cpp index 317d61d..97e2772 100644 --- a/Source/EmberCL/IterOpenCLKernelCreator.cpp +++ b/Source/EmberCL/IterOpenCLKernelCreator.cpp @@ -12,9 +12,6 @@ namespace EmberCLns template IterOpenCLKernelCreator::IterOpenCLKernelCreator() { - m_IterEntryPoint = "IterateKernel"; - m_ZeroizeEntryPoint = "ZeroizeKernel"; - m_SumHistEntryPoint = "SumHisteKernel"; m_ZeroizeKernel = CreateZeroizeKernelString(); m_SumHistKernel = CreateSumHistKernelString(); } @@ -23,11 +20,11 @@ IterOpenCLKernelCreator::IterOpenCLKernelCreator() /// Accessors. /// -template const string& IterOpenCLKernelCreator::ZeroizeKernel() const { return m_ZeroizeKernel; } +template const string& IterOpenCLKernelCreator::ZeroizeKernel() const { return m_ZeroizeKernel; } template const string& IterOpenCLKernelCreator::ZeroizeEntryPoint() const { return m_ZeroizeEntryPoint; } -template const string& IterOpenCLKernelCreator::SumHistKernel() const { return m_SumHistKernel; } +template const string& IterOpenCLKernelCreator::SumHistKernel() const { return m_SumHistKernel; } template const string& IterOpenCLKernelCreator::SumHistEntryPoint() const { return m_SumHistEntryPoint; } -template const string& IterOpenCLKernelCreator::IterEntryPoint() const { return m_IterEntryPoint; } +template const string& IterOpenCLKernelCreator::IterEntryPoint() const { return m_IterEntryPoint; } /// /// Create the iteration kernel string using the Cuburn method. diff --git a/Source/EmberCL/IterOpenCLKernelCreator.h b/Source/EmberCL/IterOpenCLKernelCreator.h index f67ecdf..7a4b7f6 100644 --- a/Source/EmberCL/IterOpenCLKernelCreator.h +++ b/Source/EmberCL/IterOpenCLKernelCreator.h @@ -43,11 +43,11 @@ private: string CreateSumHistKernelString() const; string CreateProjectionString(const Ember& ember) const; - string m_IterEntryPoint; + string m_IterEntryPoint = "IterateKernel"; string m_ZeroizeKernel; - string m_ZeroizeEntryPoint; + string m_ZeroizeEntryPoint = "ZeroizeKernel"; string m_SumHistKernel; - string m_SumHistEntryPoint; + string m_SumHistEntryPoint = "SumHisteKernel"; FunctionMapper m_FunctionMapper; }; diff --git a/Source/EmberCL/OpenCLWrapper.cpp b/Source/EmberCL/OpenCLWrapper.cpp index fffae8e..25a0ba1 100644 --- a/Source/EmberCL/OpenCLWrapper.cpp +++ b/Source/EmberCL/OpenCLWrapper.cpp @@ -10,17 +10,11 @@ namespace EmberCLns /// OpenCLWrapper::OpenCLWrapper() { - m_Init = false; - m_Shared = false; - m_PlatformIndex = 0; - m_DeviceIndex = 0; - m_LocalMemSize = 0; //Pre-allocate some space to avoid temporary copying. m_Programs.reserve(4); m_Buffers.reserve(4); m_Images.reserve(4); m_GLImages.reserve(4); - m_Info = OpenCLInfo::Instance(); } /// diff --git a/Source/EmberCL/OpenCLWrapper.h b/Source/EmberCL/OpenCLWrapper.h index 9d1888a..2dd4f07 100644 --- a/Source/EmberCL/OpenCLWrapper.h +++ b/Source/EmberCL/OpenCLWrapper.h @@ -184,18 +184,18 @@ public: private: bool CreateSPK(const string& name, const string& program, const string& entryPoint, Spk& spk, bool doublePrecision); - bool m_Init; - bool m_Shared; - size_t m_PlatformIndex; - size_t m_DeviceIndex; - size_t m_LocalMemSize; + bool m_Init = false; + bool m_Shared = false; + size_t m_PlatformIndex = 0; + size_t m_DeviceIndex = 0; + size_t m_LocalMemSize = 0; size_t m_GlobalMemSize; size_t m_MaxAllocSize; cl::Platform m_Platform; cl::Context m_Context; cl::Device m_Device; cl::CommandQueue m_Queue; - shared_ptr m_Info; + shared_ptr m_Info = OpenCLInfo::Instance(); std::vector m_DeviceVec; std::vector m_Programs; std::vector m_Buffers; diff --git a/Source/EmberCL/RendererCL.cpp b/Source/EmberCL/RendererCL.cpp index 22fd9f9..b3e7fef 100644 --- a/Source/EmberCL/RendererCL.cpp +++ b/Source/EmberCL/RendererCL.cpp @@ -76,14 +76,6 @@ void RendererCL::Init() m_FinalFormat.image_channel_data_type = CL_UNORM_INT8;//Change if this ever supports 2BPC outputs for PNG. } -/// -/// Virtual destructor. -/// -template -RendererCL::~RendererCL() -{ -} - /// /// Non-virtual member functions for OpenCL specific tasks. /// diff --git a/Source/EmberCL/RendererCL.h b/Source/EmberCL/RendererCL.h index d6a95eb..1be9b42 100644 --- a/Source/EmberCL/RendererCL.h +++ b/Source/EmberCL/RendererCL.h @@ -95,7 +95,9 @@ class EMBERCL_API RendererCL : public Renderer, public RendererCLBas public: RendererCL(const vector>& devices, bool shared = false, GLuint outputTexID = 0); - ~RendererCL(); + RendererCL(const RendererCL& renderer) = delete; + RendererCL& operator = (const RendererCL& renderer) = delete; + virtual ~RendererCL() = default; //Non-virtual member functions for OpenCL specific tasks. bool Init(const vector>& devices, bool shared, GLuint outputTexID); diff --git a/Source/EmberCommon/EmberCommon.h b/Source/EmberCommon/EmberCommon.h index 7b1e368..ab4fc46 100644 --- a/Source/EmberCommon/EmberCommon.h +++ b/Source/EmberCommon/EmberCommon.h @@ -20,10 +20,9 @@ public: /// /// Constructor that initializes the state to zero. /// - RenderProgress() - { - Clear(); - } + RenderProgress() = default; + RenderProgress(RenderProgress& progress) = delete; + ~RenderProgress() = default; /// /// The progress function which will be called from inside the renderer. @@ -33,7 +32,7 @@ public: /// The progress fraction from 0-100 /// The stage of iteration. 1 is iterating, 2 is density filtering, 2 is final accumulation. /// The estimated milliseconds to completion of the current stage - /// 1 since this is intended to run in an environment where the render runs to completion, unlike interactive rendering. + /// The value of m_Running, which is always true since this is intended to run in an environment where the render runs to completion, unlike interactive rendering. virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) { if (stage == 0 || stage == 1) @@ -51,7 +50,7 @@ public: } m_LastStage = stage; - return 1; + return m_Running; } /// @@ -59,15 +58,25 @@ public: /// void Clear() { + m_Running = 1; m_LastStage = 0; m_LastLength = 0; m_SS.clear(); m_S.clear(); } + /// + /// Stop this instance. + /// + void Stop() + { + m_Running = 0; + } + private: - int m_LastStage; - int m_LastLength; + int m_Running = 1; + int m_LastStage = 0; + int m_LastLength = 0; stringstream m_SS; string m_S; Timing t; @@ -286,7 +295,7 @@ static Renderer* CreateRenderer(eRendererType renderType, const vector if (renderType == eRendererType::OPENCL_RENDERER && !devices.empty()) { s = "OpenCL"; - renderer = unique_ptr>(new RendererCL(devices, shared, texId)); + renderer = unique_ptr>(new RendererCL(devices, shared, texId));//Can't use make_unique here. if (!renderer.get() || !renderer->Ok()) { @@ -294,13 +303,13 @@ static Renderer* CreateRenderer(eRendererType renderType, const vector errorReport.AddToReport(renderer->ErrorReport()); errorReport.AddToReport("Error initializing OpenCL renderer, using CPU renderer instead."); - renderer = unique_ptr>(new Renderer()); + renderer = make_unique>(); } } else { s = "CPU"; - renderer = unique_ptr>(new Renderer()); + renderer = make_unique>(); } } catch (const std::exception& e) @@ -343,7 +352,7 @@ static vector>> CreateRenderers(eRendererType rend for (size_t i = 0; i < devices.size(); i++) { vector> tempDevices{ devices[i] }; - auto renderer = unique_ptr>(new RendererCL(tempDevices, !i ? shared : false, texId)); + auto renderer = unique_ptr>(new RendererCL(tempDevices, !i ? shared : false, texId));//Can't use make_unique here. if (!renderer.get() || !renderer->Ok()) { diff --git a/Source/EmberCommon/EmberOptions.h b/Source/EmberCommon/EmberOptions.h index fa29ba1..9ca0a2b 100644 --- a/Source/EmberCommon/EmberOptions.h +++ b/Source/EmberCommon/EmberOptions.h @@ -308,7 +308,7 @@ public: INITBOOLOPTION(Verbose, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_VERBOSE, _T("--verbose"), false, SO_NONE, "\t--verbose Verbose output.\n")); INITBOOLOPTION(Debug, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_DEBUG, _T("--debug"), false, SO_NONE, "\t--debug Debug output.\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.\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%%.\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%.\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.\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.\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.\n")); @@ -319,15 +319,14 @@ public: 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(IntPalette, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_INT_PALETTE, _T("--intpalette"), false, SO_NONE, "\t--intpalette Force palette RGB values to be integers [default: false (float)].\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_USE_ALL, eOptionIDs::OPT_HEX_PALETTE, _T("--hex_palette"), true, SO_OPT, "\t--hex_palette Force palette RGB values to be hex [default: true].\n")); INITBOOLOPTION(InsertPalette, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_INSERT_PALETTE, _T("--insert_palette"), false, SO_NONE, "\t--insert_palette Insert the palette into the image for debugging purposes [default: false].\n")); INITBOOLOPTION(JpegComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG_COMMENTS, _T("--enable_jpeg_comments"), true, SO_OPT, "\t--enable_jpeg_comments Enables comments in the jpeg header [default: true].\n")); INITBOOLOPTION(PngComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PNG_COMMENTS, _T("--enable_png_comments"), true, SO_OPT, "\t--enable_png_comments Enables comments in the png header [default: true].\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_RENDER_ANIM, 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(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")); @@ -346,13 +345,13 @@ public: INITUINTOPTION(ThreadCount, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_NTHREADS, _T("--nthreads"), 0, SO_REQ_SEP, "\t--nthreads= The number of threads to use [default: use all available cores].\n")); INITUINTOPTION(Strips, Eou(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_STRIPS, _T("--nstrips"), 1, SO_REQ_SEP, "\t--nstrips= The number of fractions to split a single render frame into. Useful for print size renders or low memory systems [default: 1].\n")); INITUINTOPTION(Supersample, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUPERSAMPLE, _T("--supersample"), 0, SO_REQ_SEP, "\t--supersample= The supersample value used to override the one specified in the file [default: 0 (use value from file)].\n")); - INITUINTOPTION(BitsPerChannel, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_BPC, _T("--bpc"), 8, SO_REQ_SEP, "\t--bpc= Bits per channel. 8 or 16 for PNG, 8 for all others [default: 8].\n")); + INITUINTOPTION(BitsPerChannel, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_BPC, _T("--bpc"), 8, SO_REQ_SEP, "\t--bpc= Bits per channel. 8 or 16 for PNG, 8 for all others, always 8 with OpenCL [default: 8].\n")); INITUINTOPTION(SubBatchSize, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_SBS, _T("--sub_batch_size"), DEFAULT_SBS, SO_REQ_SEP, "\t--sub_batch_size= The chunk size that iterating will be broken into [default: 10k].\n")); - INITUINTOPTION(Bits, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_BITS, _T("--bits"), 33, SO_REQ_SEP, "\t--bits= Determines the types used for the histogram and accumulator [default: 33].\n" - "\t\t\t\t\t32: Histogram: float, Accumulator: float.\n" - "\t\t\t\t\t33: Histogram: float, Accumulator: float.\n"//This differs from the original which used an int hist for bits 33. - "\t\t\t\t\t64: Histogram: double, Accumulator: double.\n")); - INITUINTOPTION(PrintEditDepth, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PRINT_EDIT_DEPTH, _T("--print_edit_depth"), 0, SO_REQ_SEP, "\t--print_edit_depth= Depth to truncate tag structure when converting a flame to xml. 0 prints all tags [default: 0].\n")); + INITUINTOPTION(Bits, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_BITS, _T("--bits"), 33, SO_REQ_SEP, "\t--bits= Determines the types used for the calculations [default: 33].\n" + "\t\t\t\t\t32: float.\n" + "\t\t\t\t\t33: float.\n"//This differs from the original which used an int hist for bits 33. + "\t\t\t\t\t64: double.\n")); + INITUINTOPTION(PrintEditDepth, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PRINT_EDIT_DEPTH, _T("--print_edit_depth"), 0, SO_REQ_SEP, "\t--print_edit_depth= Depth to truncate tag structure when converting a flame to Xml. 0 prints all tags [default: 0].\n")); INITUINTOPTION(JpegQuality, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG, _T("--jpeg"), 95, SO_REQ_SEP, "\t--jpeg= Jpeg quality 0-100 for compression [default: 95].\n")); INITUINTOPTION(FirstFrame, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_BEGIN, _T("--begin"), UINT_MAX, SO_REQ_SEP, "\t--begin= Time of first frame to render [default: first time specified in file].\n")); INITUINTOPTION(LastFrame, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_END, _T("--end"), UINT_MAX, SO_REQ_SEP, "\t--end= Time of last frame to render [default: last time specified in the input file].\n")); @@ -390,7 +389,6 @@ public: INITSTRINGOPTION(Suffix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUFFIX, _T("--suffix"), "", SO_REQ_SEP, "\t--suffix= 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= 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= Path and name of the palette file [default: flam3-palettes.xml].\n")); - //INITSTRINGOPTION(PaletteImage, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PALETTE_IMAGE, _T("--image"), "", SO_REQ_SEP, "\t--image= Replace palette with png, jpg, or ppm image.\n")); INITSTRINGOPTION(Id, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_ID, _T("--id"), "", SO_REQ_SEP, "\t--id= ID to use in tags / image comments.\n")); INITSTRINGOPTION(Url, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_URL, _T("--url"), "", SO_REQ_SEP, "\t--url= URL to use in tags / image comments.\n")); INITSTRINGOPTION(Nick, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_NICK, _T("--nick"), "", SO_REQ_SEP, "\t--nick= Nickname to use in tags / image comments.\n")); @@ -465,7 +463,6 @@ public: PARSEBOOLOPTION(eOptionIDs::OPT_POS_Y_UP, YAxisUp); PARSEBOOLOPTION(eOptionIDs::OPT_TRANSPARENCY, Transparency); PARSEBOOLOPTION(eOptionIDs::OPT_NAME_ENABLE, NameEnable); - PARSEBOOLOPTION(eOptionIDs::OPT_INT_PALETTE, IntPalette); PARSEBOOLOPTION(eOptionIDs::OPT_HEX_PALETTE, HexPalette); PARSEBOOLOPTION(eOptionIDs::OPT_INSERT_PALETTE, InsertPalette); PARSEBOOLOPTION(eOptionIDs::OPT_JPEG_COMMENTS, JpegComments); @@ -667,17 +664,29 @@ public: if (optUsage == eOptionUse::OPT_USE_RENDER) { cout << "Usage:\n" - "\tEmberRender.exe --in=test.flam3 [--out=outfile --format=png --verbose --progress --opencl]\n\n"; +#ifdef _WIN32 + "\tEmberRender.exe --in=test.flame [--out=outfile --format=png --verbose --progress --opencl]\n\n"; +#else + "\temberrender --in=test.flame [--out=outfile --format=png --verbose --progress --opencl]\n\n"; +#endif } else if (optUsage == eOptionUse::OPT_USE_ANIMATE) { cout << "Usage:\n" - "\tEmberAnimate.exe --in=sequence.flam3 [--format=png --verbose --progress --opencl]\n\n"; +#ifdef _WIN32 + "\tEmberAnimate.exe --in=sequence.flame [--format=png --verbose --progress --opencl]\n\n"; +#else + "\temberanimate --in=sequence.flame [--format=png --verbose --progress --opencl]\n\n"; +#endif } else if (optUsage == eOptionUse::OPT_USE_GENOME) { cout << "Usage:\n" - "\tEmberGenome.exe --sequence=test.flam3 > sequenceout.flam3\n\n"; +#ifdef _WIN32 + "\tEmberGenome.exe --sequence=test.flame > sequenceout.flame\n\n"; +#else + "\tembergenome --sequence=test.flame > sequenceout.flame\n\n"; +#endif } cout << GetUsage(optUsage) << "\n"; @@ -730,7 +739,6 @@ public: Eob YAxisUp; Eob Transparency; Eob NameEnable; - Eob IntPalette; Eob HexPalette; Eob InsertPalette; Eob JpegComments; diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp index 5db4d78..2391f80 100644 --- a/Source/EmberGenome/EmberGenome.cpp +++ b/Source/EmberGenome/EmberGenome.cpp @@ -118,7 +118,7 @@ bool EmberGenome(EmberOptions& opt) EmberToXml emberToXml; EmberReport emberReport, emberReport2; const vector> devices = Devices(opt.Devices()); - unique_ptr> progress(new RenderProgress()); + auto progress = make_unique>(); unique_ptr> renderer(CreateRenderer(opt.EmberCL() ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, devices, false, 0, emberReport)); QTIsaac rand(ISAAC_INT(t.Tic()), ISAAC_INT(t.Tic() * 2), ISAAC_INT(t.Tic() * 3)); vector errorReport = emberReport.ErrorReport(); @@ -337,7 +337,7 @@ bool EmberGenome(EmberOptions& opt) tools.ApplyTemplate(embers[i], *pTemplate); tools.Offset(embers[i], T(opt.OffsetX()), T(opt.OffsetY())); - cout << emberToXml.ToString(embers[i], opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); + cout << emberToXml.ToString(embers[i], opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); } cout << "\n"; @@ -399,7 +399,7 @@ bool EmberGenome(EmberOptions& opt) if (pTemplate) tools.ApplyTemplate(interpolated, *pTemplate); - cout << emberToXml.ToString(interpolated, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); + cout << emberToXml.ToString(interpolated, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); } cout << "\n"; @@ -434,7 +434,7 @@ bool EmberGenome(EmberOptions& opt) blend = T(frame) / T(opt.Frames()); tools.Spin(embers[i], pTemplate, result, 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(), false, opt.HexPalette()); + cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); } //The loop above will have rotated just shy of a complete rotation. @@ -458,7 +458,7 @@ bool EmberGenome(EmberOptions& opt) result.Clear(); tools.SpinInter(&embers[i], pTemplate, result, frameCount++, seqFlag, blend); FormatName(result, os, padding); - cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); + cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); } } } @@ -466,7 +466,7 @@ bool EmberGenome(EmberOptions& opt) result = embers.back(); tools.Spin(embers.back(), pTemplate, result, frameCount, 0); FormatName(result, os, padding); - cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); + cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); if (opt.Enclosed()) cout << "\n"; @@ -501,9 +501,9 @@ bool EmberGenome(EmberOptions& opt) tools.Spin(embers[0], pTemplate, result1, frame - 1, blend - spread); tools.Spin(embers[0], pTemplate, result2, frame , blend ); tools.Spin(embers[0], pTemplate, result3, frame + 1, blend + spread); - cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); - cout << emberToXml.ToString(result2, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); - cout << emberToXml.ToString(result3, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); + cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); + cout << emberToXml.ToString(result2, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); + cout << emberToXml.ToString(result3, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); } else { @@ -516,9 +516,9 @@ bool EmberGenome(EmberOptions& opt) tools.SpinInter(embers.data(), pTemplate, result1, frame - 1, 0, blend - spread); tools.SpinInter(embers.data(), pTemplate, result2, frame , 0, blend ); tools.SpinInter(embers.data(), pTemplate, result3, frame + 1, 0, blend + spread); - cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); - cout << emberToXml.ToString(result2, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); - cout << emberToXml.ToString(result3, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); + cout << emberToXml.ToString(result1, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); + cout << emberToXml.ToString(result2, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); + cout << emberToXml.ToString(result3, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); } if (opt.Enclosed()) @@ -548,7 +548,7 @@ bool EmberGenome(EmberOptions& opt) tools.ApplyTemplate(embers[i], *pTemplate); tools.Offset(embers[i], T(opt.OffsetX()), T(opt.OffsetY())); - cout << emberToXml.ToString(embers[i], opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); + cout << emberToXml.ToString(embers[i], opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); } if (opt.Enclosed()) @@ -792,7 +792,7 @@ bool EmberGenome(EmberOptions& opt) save.DeleteTotalXform(save.TotalXformCount() - 1); } - cout << emberToXml.ToString(save, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); + cout << emberToXml.ToString(save, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), opt.HexPalette()); VerbosePrint("\nDone. Action = " << os.str() << "\n"); cout.flush(); save.Clear(); diff --git a/Source/EmberRender/EmberRender.cpp b/Source/EmberRender/EmberRender.cpp index fb019ce..3eb730b 100644 --- a/Source/EmberRender/EmberRender.cpp +++ b/Source/EmberRender/EmberRender.cpp @@ -46,7 +46,7 @@ bool EmberRender(EmberOptions& opt) EmberToXml emberToXml; vector> randVec; const vector> devices = Devices(opt.Devices()); - unique_ptr> progress(new RenderProgress()); + auto progress = make_unique>(); unique_ptr> renderer(CreateRenderer(opt.EmberCL() ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, devices, false, 0, emberReport)); vector errorReport = emberReport.ErrorReport(); @@ -282,7 +282,7 @@ bool EmberRender(EmberOptions& opt) //TotalIterCount() is actually using ScaledQuality() which does not get reset upon ember assignment, //so it ends up using the correct value for quality * strips. iterCount = renderer->TotalIterCount(1); - comments = renderer->ImageComments(stats, opt.PrintEditDepth(), opt.IntPalette(), opt.HexPalette()); + comments = renderer->ImageComments(stats, opt.PrintEditDepth(), opt.HexPalette()); os.str(""); os << comments.m_NumIters << " / " << iterCount << " (" << std::fixed << std::setprecision(2) << ((double(stats.m_Iters) / double(iterCount)) * 100) << "%)"; VerbosePrint("\nIters ran/requested: " + os.str()); diff --git a/Source/EmberTester/EmberTester.cpp b/Source/EmberTester/EmberTester.cpp index 76b43d0..0894c1e 100644 --- a/Source/EmberTester/EmberTester.cpp +++ b/Source/EmberTester/EmberTester.cpp @@ -1984,6 +1984,18 @@ void TestRotate() auto xrot = glm::rotate(xtrans, angle * DEG_2_RAD_T, v3T(0, 0, 1)); } +template +class EmberContainerTester +{ +public: + template class C> + static void TestEmberContainer(C, Alloc>& cont) + { + Ember e; + cont.push_back(e); + } +}; + #define DO_NVIDIA 1 int _tmain(int argc, _TCHAR* argv[]) @@ -1991,8 +2003,17 @@ int _tmain(int argc, _TCHAR* argv[]) //int i; bool b = true; Timing t(4); - QTIsaac rand(1, 2, 3); - mt19937 meow(1729); + vector> fv; + vector> dv; + list> fl; + list> dl; + EmberContainerTester::TestEmberContainer(fv); + EmberContainerTester::TestEmberContainer(dv); + EmberContainerTester::TestEmberContainer(fl); + EmberContainerTester::TestEmberContainer(dl); + CopyCont(fv, fl); + //QTIsaac rand(1, 2, 3); + //mt19937 meow(1729); /* TestAffine(); TestAffine();*/ /* TestRotate(); diff --git a/Source/Fractorium/AboutDialog.h b/Source/Fractorium/AboutDialog.h index 3209d26..f6a9ab2 100644 --- a/Source/Fractorium/AboutDialog.h +++ b/Source/Fractorium/AboutDialog.h @@ -15,7 +15,7 @@ class FractoriumAboutDialog : public QDialog { Q_OBJECT public: - FractoriumAboutDialog(QWidget* p = 0, Qt::WindowFlags f = 0); + FractoriumAboutDialog(QWidget* p = nullptr, Qt::WindowFlags f = 0); private: Ui::AboutDialog ui; diff --git a/Source/Fractorium/DoubleSpinBox.h b/Source/Fractorium/DoubleSpinBox.h index 0af59a7..5b1eb60 100644 --- a/Source/Fractorium/DoubleSpinBox.h +++ b/Source/Fractorium/DoubleSpinBox.h @@ -16,7 +16,7 @@ class DoubleSpinBox : public QDoubleSpinBox Q_OBJECT public: - explicit DoubleSpinBox(QWidget* parent = 0, int height = 16, double step = 0.05); + explicit DoubleSpinBox(QWidget* parent = nullptr, int height = 16, double step = 0.05); virtual ~DoubleSpinBox() { } void SetValueStealth(double d); void DoubleClick(bool b); diff --git a/Source/Fractorium/EmberFile.h b/Source/Fractorium/EmberFile.h index 3d42b06..fc3d78a 100644 --- a/Source/Fractorium/EmberFile.h +++ b/Source/Fractorium/EmberFile.h @@ -17,11 +17,10 @@ class EmberFile { public: /// - /// Empty constructor that does nothing. + /// Default constructor and destructor. /// - EmberFile() - { - } + EmberFile() = default; + ~EmberFile() = default; /// /// Default copy constructor. @@ -63,7 +62,31 @@ public: EmberFile& operator = (const EmberFile& emberFile) { m_Filename = emberFile.m_Filename; - CopyVec(m_Embers, emberFile.m_Embers); + CopyCont(m_Embers, emberFile.m_Embers); + return *this; + } + + /// + /// Move constructor. + /// + /// The EmberFile object to move + EmberFile(EmberFile&& emberFile) + { + EmberFile::operator=(emberFile); + } + + /// + /// Move assignment operator. + /// + /// The EmberFile object to move + EmberFile& operator = (EmberFile&& emberFile) + { + if (this != &emberFile) + { + m_Filename = emberFile.m_Filename; + m_Embers = std::move(emberFile.m_Embers); + } + return *this; } @@ -84,6 +107,19 @@ public: return m_Embers.size(); } + /// + /// Get a pointer to the ember at the specified index. + /// + /// The index of the ember to retrieve + /// A pointer to the ember if it was within bounds, else nullptr. + Ember* Get(size_t i) + { + if (i < m_Embers.size()) + return &(*Advance(m_Embers.begin(), i)); + + return nullptr; + } + /// /// Delete the ember at the given index. /// Will not delete anything if the size is already 1. @@ -94,7 +130,7 @@ public: { if (Size() > 1 && index < Size()) { - m_Embers.erase(m_Embers.begin() + index); + m_Embers.erase(Advance(m_Embers.begin(), index)); return true; } else @@ -106,14 +142,14 @@ public: /// void MakeNamesUnique() { - for (size_t i = 0; i < m_Embers.size(); i++) + for (auto it1 = m_Embers.begin(); it1 != m_Embers.end(); ++it1) { - for (size_t j = 0; j < m_Embers.size(); j++) + for (auto it2 = m_Embers.begin(); it2 != m_Embers.end(); ++it2) { - if (i != j && m_Embers[i].m_Name == m_Embers[j].m_Name) + if (it1 != it2 && it1->m_Name == it2->m_Name) { - m_Embers[j].m_Name = IncrementTrailingUnderscoreInt(QString::fromStdString(m_Embers[j].m_Name)).toStdString(); - j = 0; + it2->m_Name = IncrementTrailingUnderscoreInt(QString::fromStdString(it2->m_Name)).toStdString(); + it2 = m_Embers.begin(); } } } @@ -195,5 +231,5 @@ public: } QString m_Filename; - vector> m_Embers; + list> m_Embers; }; diff --git a/Source/Fractorium/EmberTreeWidgetItem.h b/Source/Fractorium/EmberTreeWidgetItem.h index 3296b2d..4451ece 100644 --- a/Source/Fractorium/EmberTreeWidgetItem.h +++ b/Source/Fractorium/EmberTreeWidgetItem.h @@ -44,7 +44,7 @@ public: { int size = 64; m_Image = QImage(width, height, QImage::Format_RGBA8888); - memcpy(m_Image.scanLine(0), v.data(), v.size() * sizeof(v[0]));//Memcpy the data in. + memcpy(m_Image.scanLine(0), v.data(), SizeOf(v));//Memcpy the data in. m_Pixmap = QPixmap::fromImage(m_Image).scaled(QSize(size, size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//Create a QPixmap out of the QImage, scaled to size. setData(0, Qt::DecorationRole, m_Pixmap); } @@ -68,10 +68,11 @@ public: /// /// A pointer to the ember this item will represent /// The parent widget of this item - explicit EmberTreeWidgetItem(Ember* ember, QTreeWidget* p = 0) - : EmberTreeWidgetItemBase(p) + explicit EmberTreeWidgetItem(Ember* ember, QTreeWidget* p = nullptr) + : EmberTreeWidgetItemBase(p), + m_Ember(ember) { - m_Ember = ember; + setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); } /// @@ -80,10 +81,11 @@ public: /// /// A pointer to the ember this item will represent /// The parent widget of this item - explicit EmberTreeWidgetItem(Ember* ember, QTreeWidgetItem* p = 0) - : EmberTreeWidgetItemBase(p) + explicit EmberTreeWidgetItem(Ember* ember, QTreeWidgetItem* p = nullptr) + : EmberTreeWidgetItemBase(p), + m_Ember(ember) { - m_Ember = ember; + setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); } /// diff --git a/Source/Fractorium/FinalRenderEmberController.cpp b/Source/Fractorium/FinalRenderEmberController.cpp index aaddb44..9990ef3 100644 --- a/Source/Fractorium/FinalRenderEmberController.cpp +++ b/Source/Fractorium/FinalRenderEmberController.cpp @@ -10,13 +10,10 @@ /// /// Pointer to the final render dialog FinalRenderEmberControllerBase::FinalRenderEmberControllerBase(FractoriumFinalRenderDialog* finalRenderDialog) - : FractoriumEmberControllerBase(finalRenderDialog->m_Fractorium) + : FractoriumEmberControllerBase(finalRenderDialog->m_Fractorium), + m_FinalRenderDialog(finalRenderDialog) { - m_Run = false; - m_PreviewRun = false; - m_ImageCount = 0; m_FinishedImageCount.store(0); - m_FinalRenderDialog = finalRenderDialog; m_Settings = m_Fractorium->m_Settings; } @@ -105,7 +102,7 @@ template FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender) : FinalRenderEmberControllerBase(finalRender) { - m_FinalPreviewRenderer = unique_ptr>(new EmberNs::Renderer()); + m_FinalPreviewRenderer = make_unique>(); m_FinalPreviewRenderer->Callback(nullptr); m_FinalPreviewRenderer->NumChannels(4); m_FinalPreviewRenderFunc = [&]() @@ -157,10 +154,10 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD m_Run = true; m_TotalTimer.Tic();//Begin timing for progress of all operations. m_GuiState = m_FinalRenderDialog->State();//Cache render settings from the GUI before running. - size_t i; + size_t i = 0; bool doAll = m_GuiState.m_DoAll && m_EmberFile.Size() > 1; size_t currentStripForProgress = 0;//Sort of a hack to get the strip value to the progress function. - QString path = doAll ? ComposePath(QString::fromStdString(m_EmberFile.m_Embers[0].m_Name)) : ComposePath(Name()); + QString path = doAll ? ComposePath(QString::fromStdString(m_EmberFile.m_Embers.begin()->m_Name)) : ComposePath(Name()); QString backup = path + "_backup.flame"; //Save backup Xml. @@ -186,33 +183,40 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD //Different action required for rendering as animation or not. if (m_GuiState.m_DoSequence && !m_Renderers.empty()) { - Ember* firstEmber = &m_EmberFile.m_Embers[0]; + Ember* prev = nullptr; + vector> embers; + vector threadVec; + std::atomic atomfTime; + auto firstEmber = m_EmberFile.m_Embers.begin(); //Need to loop through and set all w, h, q, ts, ss and t vals. - for (i = 0; i < m_EmberFile.Size() && m_Run; i++) + for (auto& it : m_EmberFile.m_Embers) { - SyncGuiToEmber(m_EmberFile.m_Embers[i], firstEmber->m_FinalRasW, firstEmber->m_FinalRasH); + if (!m_Run) + break; - if (i > 0) + SyncGuiToEmber(it, firstEmber->m_FinalRasW, firstEmber->m_FinalRasH); + + if (&it == &(*firstEmber))//First. { - if (m_EmberFile.m_Embers[i].m_Time <= m_EmberFile.m_Embers[i - 1].m_Time) - m_EmberFile.m_Embers[i].m_Time = m_EmberFile.m_Embers[i - 1].m_Time + 1; + it.m_Time = 0; } - else if (i == 0) + else//All others { - m_EmberFile.m_Embers[i].m_Time = 0; + if (it.m_Time <= prev->m_Time) + it.m_Time = prev->m_Time + 1; } - m_EmberFile.m_Embers[i].m_TemporalSamples = m_GuiState.m_TemporalSamples; + it.m_TemporalSamples = m_GuiState.m_TemporalSamples; + prev = ⁢ } - std::atomic atomfTime; - vector threadVec; //Not supporting strips with animation. //Shouldn't be a problem because animations will be at max 4k x 2k which will take about 1GB //even when using double precision, which most cards at the time of this writing already exceed. m_GuiState.m_Strips = 1; atomfTime.store(0); + CopyCont(embers, m_EmberFile.m_Embers); std::function iterFunc = [&](size_t index) { size_t ftime; @@ -223,13 +227,13 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD EmberImageComments comments; Timing renderTimer; auto renderer = m_Renderers[index].get(); - renderer->SetEmber(m_EmberFile.m_Embers);//Copy all embers to the local storage inside the renderer. + renderer->SetExternalEmbersPointer(&embers);//All will share a pointer to the original vector to conserve memory with large files. Ok because the vec doesn't get modified. //Render each image, cancelling if m_Run ever gets set to false. while (atomfTime.fetch_add(1), ((ftime = atomfTime.load() - 1) < m_EmberFile.Size()) && m_Run)//Needed to set 1 to claim this iter from other threads, so decrement it to be zero-indexed here. { T localTime = T(ftime); - Output("Image " + ToString(ftime + 1ULL) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[ftime].m_Name))); + Output("Image " + ToString(ftime + 1ULL) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.Get(ftime)->m_Name))); renderer->Reset();//Have to manually set this since the ember is not set each time through. renderTimer.Tic();//Toc() is called in RenderComplete(). @@ -247,10 +251,10 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD writeThread.join(); stats = renderer->Stats(); - comments = renderer->ImageComments(stats, 0, false, true); + comments = renderer->ImageComments(stats, 0, true); writeThread = std::thread([&](size_t tempTime, size_t threadFinalImageIndex) { - SaveCurrentRender(m_EmberFile.m_Embers[tempTime], + SaveCurrentRender(*m_EmberFile.Get(tempTime), comments,//These all don't change during the renders, so it's ok to access them in the thread. finalImages[threadFinalImageIndex], renderer->FinalRasW(), @@ -259,7 +263,7 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD renderer->BytesPerChannel()); }, ftime, finalImageIndex); m_FinishedImageCount.fetch_add(1); - RenderComplete(m_EmberFile.m_Embers[ftime], stats, renderTimer); + RenderComplete(*m_EmberFile.Get(ftime), stats, renderTimer); if (!index)//Only first device has a progress callback, so it also makes sense to only manually set the progress on the first device as well. HandleFinishedProgress(); @@ -290,16 +294,19 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD else if (m_Renderer.get())//Make sure a renderer was created and render all images, but not as an animation sequence (without temporal samples motion blur). { //Render each image, cancelling if m_Run ever gets set to false. - for (i = 0; i < m_EmberFile.Size() && m_Run; i++) + for (auto& it : m_EmberFile.m_Embers) { - Output("Image " + ToString(m_FinishedImageCount.load() + 1) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name))); - m_EmberFile.m_Embers[i].m_TemporalSamples = 1;//No temporal sampling. - m_Renderer->SetEmber(m_EmberFile.m_Embers[i]); + if (!m_Run) + break; + + Output("Image " + ToString(m_FinishedImageCount.load() + 1) + ":\n" + ComposePath(QString::fromStdString(it.m_Name))); + it.m_TemporalSamples = 1;//No temporal sampling. + m_Renderer->SetEmber(it); m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run(). m_Stats.Clear(); Memset(m_FinalImage); m_RenderTimer.Tic();//Toc() is called in RenderComplete(). - StripsRender(m_Renderer.get(), m_EmberFile.m_Embers[i], m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp, + StripsRender(m_Renderer.get(), it, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp, [&](size_t strip) { currentStripForProgress = strip; },//Pre strip. [&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip. [&](size_t strip)//Error. @@ -371,28 +378,24 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD template void FinalRenderEmberController::SetEmberFile(const EmberFile& emberFile) { m_EmberFile = emberFile; - - if (m_EmberFile.Size()) - m_Ember = &(m_EmberFile.m_Embers[0]); + m_Ember = m_EmberFile.Get(0); } template void FinalRenderEmberController::CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation) { emberFile.m_Filename = m_EmberFile.m_Filename; - CopyVec(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); + CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); } #ifdef DO_DOUBLE template void FinalRenderEmberController::SetEmberFile(const EmberFile& emberFile) { m_EmberFile = emberFile; - - if (m_EmberFile.Size()) - m_Ember = &(m_EmberFile.m_Embers[0]); + m_Ember = m_EmberFile.Get(0); } template void FinalRenderEmberController::CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation) { emberFile.m_Filename = m_EmberFile.m_Filename; - CopyVec(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); + CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); } #endif @@ -407,12 +410,12 @@ void FinalRenderEmberController::SetEmber(size_t index) { if (index < m_EmberFile.Size()) { - m_Ember = &(m_EmberFile.m_Embers[index]); + m_Ember = m_EmberFile.Get(index); SyncCurrentToGui(); } else if (m_EmberFile.Size() > 1) { - m_Ember = &(m_EmberFile.m_Embers[0]);//Should never happen. + m_Ember = m_EmberFile.Get(0);//Should never happen. } } @@ -774,7 +777,7 @@ void FinalRenderEmberController::CancelPreviewRender() template void FinalRenderEmberController::SaveCurrentRender(Ember& ember) { - auto comments = m_Renderer->ImageComments(m_Stats, 0, false, true); + auto comments = m_Renderer->ImageComments(m_Stats, 0, true); SaveCurrentRender(ember, comments, m_FinalImage, m_Renderer->FinalRasW(), m_Renderer->FinalRasH(), m_Renderer->NumChannels(), m_Renderer->BytesPerChannel()); } diff --git a/Source/Fractorium/FinalRenderEmberController.h b/Source/Fractorium/FinalRenderEmberController.h index 9ea2c07..9a46daf 100644 --- a/Source/Fractorium/FinalRenderEmberController.h +++ b/Source/Fractorium/FinalRenderEmberController.h @@ -73,9 +73,9 @@ public: void Output(const QString& s); protected: - bool m_Run; - bool m_PreviewRun; - size_t m_ImageCount; + bool m_Run = false; + bool m_PreviewRun = false; + size_t m_ImageCount = 0; std::atomic m_FinishedImageCount; QFuture m_Result; diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index eff02fa..a4f09de 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -140,7 +140,7 @@ Fractorium::Fractorium(QWidget* p) connect(ui.LibraryDockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(dockLocationChanged(Qt::DockWidgetArea))); connect(ui.LibraryDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(OnDockTopLevelChanged(bool))); - //Always ensure the library tab is selected, which will show preview renders. + //Always ensure the library tab is selected if not restoring, which will show preview renders. if (!restored) { ui.LibraryDockWidget->raise(); @@ -298,6 +298,7 @@ void Fractorium::dockLocationChanged(Qt::DockWidgetArea area) /// Event filter for taking special action on: /// Dock widget resize events, which in turn trigger GLParentScrollArea events. /// Library tree key events, specifically delete. +/// Library tree drag n drop events. /// /// The object /// The eevent @@ -309,7 +310,7 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e) m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width()); m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height()); } - else if (QKeyEvent* ke = dynamic_cast(e)) + else if (auto ke = dynamic_cast(e)) { bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); @@ -499,7 +500,7 @@ QStringList Fractorium::SetupOpenXmlDialog() QStringList filenames; m_FileDialog->disconnect(SIGNAL(filterSelected(const QString&))); - connect(m_FileDialog, &QFileDialog::filterSelected, [ = ](const QString & filter) { m_Settings->OpenXmlExt(filter); }); + connect(m_FileDialog, &QFileDialog::filterSelected, [&](const QString & filter) { m_Settings->OpenXmlExt(filter); }); m_FileDialog->setFileMode(QFileDialog::ExistingFiles); m_FileDialog->setAcceptMode(QFileDialog::AcceptOpen); m_FileDialog->setNameFilter("Flam3 (*.flam3);;Flame (*.flame);;Xml (*.xml)"); @@ -527,6 +528,7 @@ QStringList Fractorium::SetupOpenXmlDialog() QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename) { //Lazy instantiate since it takes a long time. + //QS if (!m_FileDialog) { m_FileDialog = new QFileDialog(this); @@ -538,7 +540,7 @@ QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename) QString filename; m_FileDialog->disconnect(SIGNAL(filterSelected(const QString&))); - connect(m_FileDialog, &QFileDialog::filterSelected, [ = ](const QString & filter) { m_Settings->SaveXmlExt(filter); }); + connect(m_FileDialog, &QFileDialog::filterSelected, [&](const QString & filter) { m_Settings->SaveXmlExt(filter); }); //This must come first because it clears various internal states which allow the file text to be properly set. //This is most likely a bug in QFileDialog. m_FileDialog->setAcceptMode(QFileDialog::AcceptSave); @@ -549,7 +551,19 @@ QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename) m_FileDialog->selectNameFilter(m_Settings->SaveXmlExt()); if (m_FileDialog->exec() == QDialog::Accepted) + { filename = m_FileDialog->selectedFiles().value(0); + //For some reason, linux doesn't automatically append this, but Windows does. Force it to be safe. + auto filt = m_FileDialog->selectedNameFilter().split('*');//Qt makes it very hard to get the actual extension used. + + if (filt.size() > 1)//Should always be true. + { + auto s = filt[1].replace(")", ""); + + if (!filename.endsWith(s)) + filename.append(s); + } + } return filename; } @@ -574,7 +588,7 @@ QString Fractorium::SetupSaveImageDialog(const QString& defaultFilename) QString filename; m_FileDialog->disconnect(SIGNAL(filterSelected(const QString&))); - connect(m_FileDialog, &QFileDialog::filterSelected, [ = ](const QString & filter) { m_Settings->SaveImageExt(filter); }); + connect(m_FileDialog, &QFileDialog::filterSelected, [&](const QString & filter) { m_Settings->SaveImageExt(filter); }); //This must come first because it clears various internal states which allow the file text to be properly set. //This is most likely a bug in QFileDialog. m_FileDialog->setAcceptMode(QFileDialog::AcceptSave); diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index 5c8e12a..2eeba3c 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -65,6 +65,7 @@ class Fractorium : public QMainWindow friend GLWidget; friend QssDialog; + friend LibraryTreeWidget; friend FractoriumOptionsDialog; friend FractoriumFinalRenderDialog; friend FractoriumAboutDialog; @@ -82,7 +83,7 @@ class Fractorium : public QMainWindow #endif public: - Fractorium(QWidget* p = 0); + Fractorium(QWidget* p = nullptr); ~Fractorium(); //Geometry. diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index 825de2b..71c3659 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -6681,12 +6681,15 @@ 0 - + Qt::WheelFocus - Qt::CustomContextMenu + Qt::DefaultContextMenu + + + false QFrame::Panel @@ -6697,6 +6700,21 @@ QAbstractItemView::SelectedClicked + + true + + + false + + + QAbstractItemView::InternalMove + + + Qt::MoveAction + + + QAbstractItemView::SelectRows + 10 @@ -7239,6 +7257,11 @@ QGraphicsView
CurvesGraphicsView.h
+ + LibraryTreeWidget + QTreeWidget +
LibraryTreeWidget.h
+
LibraryDockWidget diff --git a/Source/Fractorium/FractoriumEmberController.cpp b/Source/Fractorium/FractoriumEmberController.cpp index ee4996c..2133b1f 100644 --- a/Source/Fractorium/FractoriumEmberController.cpp +++ b/Source/Fractorium/FractoriumEmberController.cpp @@ -11,21 +11,12 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractorium) { Timing t; - m_Rendering = false; - m_Shared = true; - m_FailedRenders = 0; - m_UndoIndex = 0; - m_LockedScale = 1; - m_RenderType = eRendererType::CPU_RENDERER; - m_OutputTexID = 0; - m_SubBatchCount = 1;//Will be ovewritten by the options on first render. m_Fractorium = fractorium; - m_Info = OpenCLInfo::Instance(); m_Rand = QTIsaac(ISAAC_INT(t.Tic()), ISAAC_INT(t.Tic() * 2), ISAAC_INT(t.Tic() * 3));//Ensure a different rand seed on each instance. - m_RenderTimer = std::unique_ptr(new QTimer(m_Fractorium)); + m_RenderTimer = make_unique(m_Fractorium); m_RenderTimer->setInterval(0); m_Fractorium->connect(m_RenderTimer.get(), SIGNAL(timeout()), SLOT(IdleTimer())); - m_RenderRestartTimer = std::unique_ptr(new QTimer(m_Fractorium)); + m_RenderRestartTimer = make_unique(m_Fractorium); m_Fractorium->connect(m_RenderRestartTimer.get(), SIGNAL(timeout()), SLOT(StartRenderTimer())); } @@ -52,10 +43,7 @@ FractoriumEmberController::FractoriumEmberController(Fractorium* fractorium) m_VariationList(VariationList::Instance()) { bool b = false; - m_PreviewRun = false; - m_PreviewRunning = false; - m_GLController = unique_ptr>(new GLEmberController(fractorium, fractorium->ui.GLDisplay, this)); - m_PreviewRenderer = unique_ptr>(new EmberNs::Renderer()); + m_GLController = make_unique>(fractorium, fractorium->ui.GLDisplay, this); //Initial combo change event to fill the palette table will be called automatically later. //Look hard for a palette. static vector paths = @@ -72,8 +60,7 @@ FractoriumEmberController::FractoriumEmberController(Fractorium* fractorium) { if (b = InitPaletteList(path)) { - m_SheepTools = unique_ptr>(new SheepTools( - m_PaletteList.Name(0), new EmberNs::Renderer())); + m_SheepTools = make_unique>(m_PaletteList.Name(0), new EmberNs::Renderer()); break; } } @@ -102,9 +89,11 @@ FractoriumEmberController::FractoriumEmberController(Fractorium* fractorium) if (auto top = tree->topLevelItem(0)) { - for (auto i = start; m_PreviewRun && i < end && i < m_EmberFile.Size(); i++) + 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 ember = m_EmberFile.m_Embers[i]; + Ember ember = *b; ember.SyncSize(); ember.SetSizeAndAdjustScale(PREVIEW_SIZE, PREVIEW_SIZE, false, eScaleType::SCALE_WIDTH); ember.m_TemporalSamples = 1; @@ -124,7 +113,6 @@ FractoriumEmberController::FractoriumEmberController(Fractorium* fractorium) Q_ARG(vector&, m_PreviewFinalImage), Q_ARG(uint, PREVIEW_SIZE), Q_ARG(uint, PREVIEW_SIZE)); - //treeItem->SetImage(m_PreviewFinalImage, PREVIEW_SIZE, PREVIEW_SIZE); } } } @@ -152,7 +140,7 @@ template void FractoriumEmberController::SetEmberFile(const Embe template void FractoriumEmberController::CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation) { emberFile.m_Filename = m_EmberFile.m_Filename; - CopyVec(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); + CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); } template void FractoriumEmberController::SetTempPalette(const Palette& palette) { m_TempPalette = palette; } @@ -164,7 +152,7 @@ template void FractoriumEmberController::SetEmberFile(const Embe template void FractoriumEmberController::CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation) { emberFile.m_Filename = m_EmberFile.m_Filename; - CopyVec(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); + CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); } template void FractoriumEmberController::SetTempPalette(const Palette& palette) { m_TempPalette = palette; } @@ -200,7 +188,7 @@ void FractoriumEmberController::SetEmber(size_t index) } ClearUndo(); - SetEmber(m_EmberFile.m_Embers[index]); + SetEmber(*m_EmberFile.Get(index)); } } @@ -340,10 +328,10 @@ void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool v size_t w = m_Ember.m_FinalRasW;//Cache values for use below. size_t h = m_Ember.m_FinalRasH; m_Ember = ember; + m_EmberFilePointer = &ember; if (!verbatim) { - //m_Ember.SetSizeAndAdjustScale(m_Fractorium->ui.GLDisplay->width(), m_Fractorium->ui.GLDisplay->height(), true, SCALE_WIDTH); m_Ember.m_TemporalSamples = 1;//Change once animation is supported. m_Ember.m_Quality = m_Fractorium->m_QualitySpin->value(); m_Ember.m_Supersample = m_Fractorium->m_SupersampleSpin->value(); diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index 5711a0c..70f7cf2 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -18,6 +18,12 @@ enum class eEditUndoState : et { REGULAR_EDIT, UNDO_REDO, EDIT_UNDO }; ///
enum class eXformUpdate : et { UPDATE_CURRENT, UPDATE_SELECTED, UPDATE_CURRENT_AND_SELECTED, UPDATE_SELECTED_EXCEPT_FINAL, UPDATE_ALL, UPDATE_ALL_EXCEPT_FINAL }; +/// +/// An enum representing the type of synchronizing to do between the list of Embers kept in memory +/// and the widgets in the library tree. +/// +enum eLibraryUpdate { INDEX = 1, NAME = 2, POINTER = 4 }; + /// /// FractoriumEmberController and Fractorium need each other, but each can't include the other. /// So Fractorium includes this file, and Fractorium is declared as a forward declaration here. @@ -42,6 +48,7 @@ class FractoriumEmberControllerBase : public RenderCallback { public: FractoriumEmberControllerBase(Fractorium* fractorium); + FractoriumEmberControllerBase(const FractoriumEmberControllerBase& controller) = delete; virtual ~FractoriumEmberControllerBase(); //Embers. @@ -107,14 +114,14 @@ public: //Toolbar. //Library. - virtual void SyncNames() { } - virtual void SyncPointers() { } + virtual void SyncLibrary(eLibraryUpdate update) { } virtual void FillLibraryTree(int selectIndex = -1) { } 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 MoveLibraryItems(int startRow, int destRow) { } virtual void Delete(const pair& p) { } //Params. @@ -237,17 +244,17 @@ protected: eProcessState ProcessState() { return m_Renderer.get() ? m_Renderer->ProcessState() : eProcessState::NONE; } //Non-templated members. - bool m_Rendering; - bool m_Shared; + bool m_Rendering = false; + bool m_Shared = true; bool m_LastEditWasUndoRedo; vector> m_Devices; - size_t m_SubBatchCount; - uint m_FailedRenders; - size_t m_UndoIndex; - double m_LockedScale; - eRendererType m_RenderType; + size_t m_SubBatchCount = 1;//Will be ovewritten by the options on first render. + uint m_FailedRenders = 0; + size_t m_UndoIndex = 0; + double m_LockedScale = 1; + eRendererType m_RenderType = eRendererType::CPU_RENDERER; eEditUndoState m_EditState; - GLuint m_OutputTexID; + GLuint m_OutputTexID = 0; Timing m_RenderElapsedTimer; EmberStats m_Stats; QImage m_FinalPaletteImage; @@ -265,7 +272,7 @@ protected: Fractorium* m_Fractorium; std::unique_ptr m_RenderTimer; std::unique_ptr m_RenderRestartTimer; - shared_ptr m_Info; + shared_ptr m_Info = OpenCLInfo::Instance(); }; /// @@ -279,6 +286,7 @@ class FractoriumEmberController : public FractoriumEmberControllerBase { public: FractoriumEmberController(Fractorium* fractorium); + FractoriumEmberController(const FractoriumEmberController& controller) = delete; virtual ~FractoriumEmberController(); //Embers. @@ -347,10 +355,10 @@ public: //Toolbar. //Library. - virtual void SyncNames() override; - virtual void SyncPointers() override; + virtual void SyncLibrary(eLibraryUpdate update) override; virtual void FillLibraryTree(int selectIndex = -1) override; virtual void UpdateLibraryTree() override; + virtual void MoveLibraryItems(int startRow, int destRow) override; virtual void Delete(const pair& p) override; virtual void EmberTreeItemChanged(QTreeWidgetItem* item, int col) override; virtual void EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) override; @@ -489,11 +497,12 @@ private: bool SyncSizes(); //Templated members. - bool m_PreviewRun; - bool m_PreviewRunning; + bool m_PreviewRun = false; + bool m_PreviewRunning = false; vector m_TempOpacities; vector m_NormalizedWeights; Ember m_Ember; + const void* m_EmberFilePointer = nullptr; EmberFile m_EmberFile; deque> m_UndoList; vector> m_CopiedXforms; @@ -503,7 +512,7 @@ private: VariationList& m_VariationList; unique_ptr> m_SheepTools; unique_ptr> m_GLController; - unique_ptr> m_PreviewRenderer; + unique_ptr> m_PreviewRenderer = make_unique>(); QFuture m_PreviewResult; std::function m_PreviewRenderFunc; }; diff --git a/Source/Fractorium/FractoriumLibrary.cpp b/Source/Fractorium/FractoriumLibrary.cpp index c057866..79ad94e 100644 --- a/Source/Fractorium/FractoriumLibrary.cpp +++ b/Source/Fractorium/FractoriumLibrary.cpp @@ -6,12 +6,12 @@ /// 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); } - /// /// Get the index of the currently selected ember in the library tree. /// @@ -52,44 +52,30 @@ void Fractorium::SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vector /// Set all libary tree entries to the name of the corresponding ember they represent. -/// -template -void FractoriumEmberController::SyncNames() -{ - EmberTreeWidgetItem* item; - auto tree = m_Fractorium->ui.LibraryTree; - tree->blockSignals(true); - - if (auto top = tree->topLevelItem(0)) - { - for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers. - { - if ((item = dynamic_cast*>(top->child(i))) && i < m_EmberFile.Size())//Cast the child widget to the EmberTreeWidgetItem type. - item->setText(0, QString::fromStdString(m_EmberFile.m_Embers[i].m_Name)); - } - } - - tree->blockSignals(false); -} - -/// /// Set all libary tree entries to point to the underlying ember they represent. /// template -void FractoriumEmberController::SyncPointers() +void FractoriumEmberController::SyncLibrary(eLibraryUpdate update) { - EmberTreeWidgetItem* item; + auto it = m_EmberFile.m_Embers.begin(); auto tree = m_Fractorium->ui.LibraryTree; tree->blockSignals(true); if (auto top = tree->topLevelItem(0)) { - size_t childCount = top->childCount(); - - for (int i = 0; i < childCount; i++)//Iterate through all of the children, which will represent the open embers. + for (int i = 0; i < top->childCount() && it != m_EmberFile.m_Embers.end(); ++i, ++it)//Iterate through all of the children, which will represent the open embers. { - if ((item = dynamic_cast*>(top->child(i))) && i < m_EmberFile.Size())//Cast the child widget to the EmberTreeWidgetItem type. - item->SetEmberPointer(&m_EmberFile.m_Embers[i]); + if (auto item = dynamic_cast*>(top->child(i)))//Cast the child widget to the EmberTreeWidgetItem type. + { + if (update & eLibraryUpdate::INDEX) + it->m_Index = i; + + if (update & eLibraryUpdate::NAME) + item->setText(0, QString::fromStdString(it->m_Name)); + + if (update & eLibraryUpdate::POINTER) + item->SetEmberPointer(&(*it)); + } } } @@ -105,7 +91,8 @@ void FractoriumEmberController::SyncPointers() template void FractoriumEmberController::FillLibraryTree(int selectIndex) { - uint j, size = 64; + uint size = 64; + uint i = 0; auto tree = m_Fractorium->ui.LibraryTree; vector v(size * size * 4); StopPreviewRender(); @@ -116,18 +103,16 @@ void FractoriumEmberController::FillLibraryTree(int selectIndex) QFileInfo info(m_EmberFile.m_Filename); fileItem->setText(0, info.fileName()); fileItem->setToolTip(0, m_EmberFile.m_Filename); - fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); + fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled); - for (j = 0; j < m_EmberFile.Size(); j++) + for (auto& it : m_EmberFile.m_Embers) { - auto ember = &m_EmberFile.m_Embers[j]; - auto emberItem = new EmberTreeWidgetItem(ember, fileItem); - emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); + auto emberItem = new EmberTreeWidgetItem(&it, fileItem); - if (ember->m_Name.empty()) - emberItem->setText(0, ToString(j)); + if (it.m_Name.empty()) + emberItem->setText(0, ToString(i++)); else - emberItem->setText(0, ember->m_Name.c_str()); + emberItem->setText(0, it.m_Name.c_str()); emberItem->setToolTip(0, emberItem->text(0)); emberItem->SetImage(v, size, size); @@ -152,35 +137,33 @@ void FractoriumEmberController::FillLibraryTree(int selectIndex) template void FractoriumEmberController::UpdateLibraryTree() { - uint i, size = 64; - auto tree = m_Fractorium->ui.LibraryTree; + uint size = 64; vector v(size * size * 4); + auto tree = m_Fractorium->ui.LibraryTree; if (auto top = tree->topLevelItem(0)) { - int childCount = top->childCount(); + int origChildCount = top->childCount(); + int i = origChildCount; tree->blockSignals(true); - for (i = childCount; i < m_EmberFile.Size(); i++) + for (auto it = Advance(m_EmberFile.m_Embers.begin(), i); it != m_EmberFile.m_Embers.end(); ++it) { - Ember* ember = &m_EmberFile.m_Embers[i]; - auto emberItem = new EmberTreeWidgetItem(ember, top); - emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); + auto emberItem = new EmberTreeWidgetItem(&(*it), top); - if (ember->m_Name.empty()) - emberItem->setText(0, ToString(i)); + if (it->m_Name.empty()) + emberItem->setText(0, ToString(i++)); else - emberItem->setText(0, ember->m_Name.c_str()); + emberItem->setText(0, it->m_Name.c_str()); emberItem->setToolTip(0, emberItem->text(0)); emberItem->SetImage(v, size, size); } - //When adding elements to the vector, they may have been reshuffled which will have invalidated - //the pointers contained in the EmberTreeWidgetItems. So reassign all pointers here. - SyncPointers(); + //When adding elements, ensure all indices are sequential. + SyncLibrary(eLibraryUpdate::INDEX); tree->blockSignals(false); - RenderPreviews(childCount, uint(m_EmberFile.Size())); + RenderPreviews(origChildCount, uint(m_EmberFile.Size())); } } @@ -200,9 +183,8 @@ void FractoriumEmberController::EmberTreeItemChanged(QTreeWidgetItem* item, i try { auto tree = m_Fractorium->ui.LibraryTree; - auto emberItem = dynamic_cast*>(item); - if (emberItem) + if (auto emberItem = dynamic_cast*>(item)) { if (emberItem->text(0).isEmpty())//Prevent empty string. { @@ -214,10 +196,10 @@ void FractoriumEmberController::EmberTreeItemChanged(QTreeWidgetItem* item, i tree->blockSignals(true); emberItem->UpdateEmberName();//Copy edit text to the ember's name variable. m_EmberFile.MakeNamesUnique();//Ensure all names remain unique. - SyncNames();//Copy all ember names to the tree items since some might have changed to be made unique. + SyncLibrary(eLibraryUpdate::NAME);//Copy all ember names to the tree items since some might have changed to be made unique. string newName = emberItem->GetEmber()->m_Name;//Get the new, final, unique name. - if (m_Ember.m_Name == oldName && oldName != newName)//If the ember edited was the current one, and the name was indeed changed, update the name of the current one. + if (m_EmberFilePointer == emberItem->GetEmber() && oldName != newName)//If the ember edited was the current one, and the name was indeed changed, update the name of the current one. { m_Ember.m_Name = newName; m_LastSaveCurrent = "";//Reset will force the dialog to show on the next save current since the user probably wants a different name. @@ -259,6 +241,7 @@ void FractoriumEmberController::EmberTreeItemDoubleClicked(QTreeWidgetItem* i { if (auto emberItem = dynamic_cast*>(item)) { + //qDebug() << "Setting current ember to: " << QString::fromStdString(emberItem->GetEmber()->m_Name); ClearUndo(); SetEmber(*emberItem->GetEmber()); } @@ -266,6 +249,24 @@ void FractoriumEmberController::EmberTreeItemDoubleClicked(QTreeWidgetItem* i void Fractorium::OnEmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) { m_Controller->EmberTreeItemDoubleClicked(item, col); } +/// +/// Move a library item at one index to the next index. +/// +/// The index of the source item to move +/// The destination index to move the item to +template +void FractoriumEmberController::MoveLibraryItems(int startRow, int destRow) +{ + int i = 0; + auto tree = m_Fractorium->ui.LibraryTree; + auto top = tree->topLevelItem(0); + auto b = m_EmberFile.m_Embers.begin(); + auto s = Advance(b, startRow); + auto d = Advance(b, destRow); + m_EmberFile.m_Embers.splice(d, m_EmberFile.m_Embers, s); + SyncLibrary(eLibraryUpdate::INDEX);//Only indices need syncing. +} + /// /// Delete the currently selected item in the tree. /// Note this is not necessarilly the current ember, it's just the item @@ -275,25 +276,18 @@ void Fractorium::OnEmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) { template void FractoriumEmberController::Delete(const pair& p) { - auto tree = m_Fractorium->ui.LibraryTree; - tree->blockSignals(true); - if (m_EmberFile.Delete(p.first)) { delete p.second; - SyncPointers(); + SyncLibrary(eLibraryUpdate::INDEX); } - tree->blockSignals(false); - //If there is now only one item left and it wasn't selected, select it. - if (auto top = tree->topLevelItem(0)) - { + if (auto top = m_Fractorium->ui.LibraryTree->topLevelItem(0)) if (top->childCount() == 1) if (auto item = dynamic_cast*>(top->child(0))) if (item->GetEmber()->m_Name != m_Ember.m_Name) EmberTreeItemDoubleClicked(top->child(0), 0); - } } /// @@ -326,7 +320,7 @@ void FractoriumEmberController::RenderPreviews(uint start, uint end) if (auto top = tree->topLevelItem(0)) { int childCount = top->childCount(); - vector emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 3); + vector emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 4); for (int i = 0; i < childCount; i++) if (auto treeItem = dynamic_cast*>(top->child(i))) diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index e6d9dfd..0611b7d 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -55,7 +55,6 @@ void FractoriumEmberController::NewFlock(size_t count) Ember ember; StopPreviewRender(); m_EmberFile.Clear(); - m_EmberFile.m_Embers.reserve(count); m_EmberFile.m_Filename = EmberFile::DefaultFilename(); for (size_t i = 0; i < count; i++) @@ -206,7 +205,7 @@ void FractoriumEmberController::OpenAndPrepFiles(const QStringList& filenames } if (!errors.empty()) - m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit); + m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit, false);//Concat errors from all files. } if (append) @@ -216,12 +215,14 @@ void FractoriumEmberController::OpenAndPrepFiles(const QStringList& filenames m_EmberFile.m_Embers.insert(m_EmberFile.m_Embers.end(), emberFile.m_Embers.begin(), emberFile.m_Embers.end()); } - else - m_EmberFile = emberFile; + else if (emberFile.Size() > 0)//Ensure at least something was read. + m_EmberFile = std::move(emberFile);//Move the temp to avoid creating dupes because we no longer need it. //Resync indices and names. - for (i = 0; i < m_EmberFile.Size(); i++) - m_EmberFile.m_Embers[i].m_Index = i; + i = 0; + + for (auto& it : m_EmberFile.m_Embers) + it.m_Index = i++; m_EmberFile.MakeNamesUnique(); @@ -281,7 +282,7 @@ void FractoriumEmberController::SaveCurrentAsXml() if (tempEdit) xmlFreeDoc(tempEdit); - if (writer.Save(filename.toStdString().c_str(), ember, 0, true, false, true)) + if (writer.Save(filename.toStdString().c_str(), ember, 0, true, true)) { s->SaveFolder(fileInfo.canonicalPath()); @@ -324,7 +325,7 @@ void FractoriumEmberController::SaveEntireFileAsXml() for (auto& ember : emberFile.m_Embers) ApplyXmlSavingTemplate(ember); - if (writer.Save(filename.toStdString().c_str(), emberFile.m_Embers, 0, true, false, true)) + if (writer.Save(filename.toStdString().c_str(), emberFile.m_Embers, 0, true, true)) { if (!s->SaveAutoUnique() || m_LastSaveAll == "")//Only save filename on first time through when doing auto unique names. m_LastSaveAll = filename; @@ -349,7 +350,7 @@ void Fractorium::OnActionSaveCurrentScreen(bool checked) auto& pixels = *m_Controller->FinalImage(); auto rendererCL = dynamic_cast(m_Controller->Renderer()); auto stats = m_Controller->Stats(); - auto comments = renderer->ImageComments(stats, 0, false, true); + auto comments = renderer->ImageComments(stats, 0, true); if (rendererCL && renderer->PrepFinalAccumVector(pixels)) { @@ -370,18 +371,19 @@ void Fractorium::OnActionSaveCurrentScreen(bool checked) template void FractoriumEmberController::SaveCurrentToOpenedFile() { - uint i; + uint i = 0; bool fileFound = false; - for (i = 0; i < m_EmberFile.Size(); i++) + for (auto& it : m_EmberFile.m_Embers) { - if ((m_Ember.m_Name == m_EmberFile.m_Embers[i].m_Name) &&//Check both to be extra sure. - (m_Ember.m_Index == m_EmberFile.m_Embers[i].m_Index)) + if (&it == m_EmberFilePointer)//Just compare memory addresses. { - m_EmberFile.m_Embers[i] = m_Ember; + it = m_Ember;//Save it to the opened file in memory. fileFound = true; break; } + + i++; } if (!fileFound) @@ -470,7 +472,7 @@ void FractoriumEmberController::CopyXml() ember.m_Quality = settings->XmlQuality(); ember.m_Supersample = settings->XmlSupersample(); ember.m_TemporalSamples = settings->XmlTemporalSamples(); - QApplication::clipboard()->setText(QString::fromStdString(emberToXml.ToString(ember, "", 0, false, false, true))); + QApplication::clipboard()->setText(QString::fromStdString(emberToXml.ToString(ember, "", 0, false, true))); } void Fractorium::OnActionCopyXml(bool checked) { m_Controller->CopyXml(); } @@ -490,7 +492,7 @@ void FractoriumEmberController::CopyAllXml() { Ember ember = e; ApplyXmlSavingTemplate(ember); - os << emberToXml.ToString(ember, "", 0, false, false, true); + os << emberToXml.ToString(ember, "", 0, false, true); } os << "\n"; @@ -563,9 +565,10 @@ void Fractorium::OnActionPasteXmlAppend(bool checked) { m_Controller->PasteXmlAp template void FractoriumEmberController::PasteXmlOver() { + size_t i = 0; string s, errors; XmlToEmber parser; - auto backupEmber = m_EmberFile.m_Embers[0]; + auto backupEmber = m_EmberFile.m_Embers.begin(); auto codec = QTextCodec::codecForName("UTF-8"); auto b = codec->fromUnicode(QApplication::clipboard()->text()); s.reserve(b.size()); @@ -589,20 +592,20 @@ void FractoriumEmberController::PasteXmlOver() if (m_EmberFile.Size()) { - for (auto i = 0; i < m_EmberFile.Size(); i++) + for (auto it : m_EmberFile.m_Embers) { - m_EmberFile.m_Embers[i].m_Index = i; - ConstrainDimensions(m_EmberFile.m_Embers[i]);//Do not exceed the max texture size. + it.m_Index = i++; + ConstrainDimensions(it);//Do not exceed the max texture size. //Also ensure it has a name. - if (m_EmberFile.m_Embers[i].m_Name == "" || m_EmberFile.m_Embers[i].m_Name == "No name") - m_EmberFile.m_Embers[i].m_Name = ToString(m_EmberFile.m_Embers[i].m_Index).toStdString(); + if (it.m_Name == "" || it.m_Name == "No name") + it.m_Name = ToString(it.m_Index).toStdString(); } } else { - backupEmber.m_Index = 0; - m_EmberFile.m_Embers.push_back(backupEmber); + backupEmber->m_Index = 0; + m_EmberFile.m_Embers.push_back(*backupEmber); } m_EmberFile.MakeNamesUnique(); diff --git a/Source/Fractorium/GLWidget.cpp b/Source/Fractorium/GLWidget.cpp index 026ed1d..d3ed1c7 100644 --- a/Source/Fractorium/GLWidget.cpp +++ b/Source/Fractorium/GLWidget.cpp @@ -11,12 +11,6 @@ GLWidget::GLWidget(QWidget* p) : QOpenGLWidget(p) { QSurfaceFormat qsf; - m_Init = false; - m_Drawing = false; - m_TexWidth = 0; - m_TexHeight = 0; - m_OutputTexID = 0; - m_Fractorium = nullptr; qsf.setSwapInterval(1);//Vsync. qsf.setSwapBehavior(QSurfaceFormat::DoubleBuffer); qsf.setVersion(2, 0); diff --git a/Source/Fractorium/GLWidget.h b/Source/Fractorium/GLWidget.h index f412669..8364ea5 100644 --- a/Source/Fractorium/GLWidget.h +++ b/Source/Fractorium/GLWidget.h @@ -73,13 +73,13 @@ private: void DrawAffineHelper(int index, bool selected, bool pre, bool final, bool background); GLEmberControllerBase* GLController(); - bool m_Init; - bool m_Drawing; - GLint m_MaxTexSize; - GLint m_TexWidth; - GLint m_TexHeight; - GLint m_ViewWidth; - GLint m_ViewHeight; - GLuint m_OutputTexID; - Fractorium* m_Fractorium; + bool m_Init = false; + bool m_Drawing = false; + GLint m_MaxTexSize = 16384; + GLint m_TexWidth = 0; + GLint m_TexHeight = 0; + GLint m_ViewWidth = 0; + GLint m_ViewHeight = 0; + GLuint m_OutputTexID = 0; + Fractorium* m_Fractorium = nullptr; }; diff --git a/Source/Fractorium/LibraryTreeWidget.cpp b/Source/Fractorium/LibraryTreeWidget.cpp new file mode 100644 index 0000000..c18d759 --- /dev/null +++ b/Source/Fractorium/LibraryTreeWidget.cpp @@ -0,0 +1,40 @@ +#include "FractoriumPch.h" +#include "LibraryTreeWidget.h" +#include "Fractorium.h" + +/// +/// Set a pointer to the main window. +/// +/// Pointer to the main Fractorium object +void LibraryTreeWidget::SetMainWindow(Fractorium* f) +{ + m_Fractorium = f; +} + +/// +/// Process the drop event to allow for moving items around inside of the tree. +/// +/// Pointer to the QDropEvent object +void LibraryTreeWidget::dropEvent(QDropEvent* de) +{ + QModelIndex droppedIndex = indexAt(de->pos()); + auto items = selectionModel()->selectedIndexes(); + + if (!droppedIndex.isValid())//Don't process drop because it's outside of the droppable area. + { + de->ignore(); + return; + } + else if (!items.empty())//Actually do the drop and move the item to a new location. + { + int row = droppedIndex.row(); + DropIndicatorPosition dp = dropIndicatorPosition(); + + if (dp == QAbstractItemView::BelowItem) + row++; + + m_Fractorium->m_Controller->MoveLibraryItems(items[0].row(), row); + } + + QTreeWidget::dropEvent(de); +} \ No newline at end of file diff --git a/Source/Fractorium/LibraryTreeWidget.h b/Source/Fractorium/LibraryTreeWidget.h new file mode 100644 index 0000000..83b7458 --- /dev/null +++ b/Source/Fractorium/LibraryTreeWidget.h @@ -0,0 +1,29 @@ +#pragma once + +#include "FractoriumPch.h" + +class Fractorium; + +/// +/// A thin derivation of QTreeWidget which allows for processing the drop event. +/// +class LibraryTreeWidget : public QTreeWidget +{ + Q_OBJECT +public: + /// + /// Constructor that passes p to the parent. + /// + /// The parent widget + explicit LibraryTreeWidget(QWidget* p = nullptr) + : QTreeWidget(p) + { + } + + void SetMainWindow(Fractorium* f); + +protected: + virtual void dropEvent(QDropEvent* de) override; + + Fractorium* m_Fractorium = nullptr; +}; \ No newline at end of file diff --git a/Source/Fractorium/OptionsDialog.h b/Source/Fractorium/OptionsDialog.h index dd4cf37..0aae7a7 100644 --- a/Source/Fractorium/OptionsDialog.h +++ b/Source/Fractorium/OptionsDialog.h @@ -24,7 +24,7 @@ class FractoriumOptionsDialog : public QDialog friend Fractorium; public: - FractoriumOptionsDialog(FractoriumSettings* settings, QWidget* p = 0, Qt::WindowFlags f = 0); + FractoriumOptionsDialog(FractoriumSettings* settings, QWidget* p = nullptr, Qt::WindowFlags f = 0); public slots: void OnOpenCLCheckBoxStateChanged(int state); diff --git a/Source/Fractorium/SpinBox.h b/Source/Fractorium/SpinBox.h index 8ed2ce0..35ad263 100644 --- a/Source/Fractorium/SpinBox.h +++ b/Source/Fractorium/SpinBox.h @@ -16,7 +16,7 @@ class SpinBox : public QSpinBox Q_OBJECT public: - explicit SpinBox(QWidget* p = 0, int height = 16, int step = 1); + explicit SpinBox(QWidget* p = nullptr, int height = 16, int step = 1); virtual ~SpinBox() { } void SetValueStealth(int d); void SetValueStealth(size_t d); diff --git a/Source/Fractorium/StealthComboBox.h b/Source/Fractorium/StealthComboBox.h index 87123e2..b881696 100644 --- a/Source/Fractorium/StealthComboBox.h +++ b/Source/Fractorium/StealthComboBox.h @@ -15,8 +15,8 @@ class StealthComboBox : public QComboBox Q_OBJECT public: - explicit StealthComboBox(QWidget* p = 0) : QComboBox(p) { } - + explicit StealthComboBox(QWidget* p = nullptr) : QComboBox(p) { } + /// /// Set the current index of the combo box without triggering signals. /// diff --git a/Source/Fractorium/TableWidget.h b/Source/Fractorium/TableWidget.h index f0ae134..13bb131 100644 --- a/Source/Fractorium/TableWidget.h +++ b/Source/Fractorium/TableWidget.h @@ -24,14 +24,14 @@ /// class TableWidget : public QTableWidget { - Q_OBJECT + Q_OBJECT public: /// /// Constructor that passes the parent to the base and installs /// the event filter. /// /// The parent widget - explicit TableWidget(QWidget* p = 0) + explicit TableWidget(QWidget* p = nullptr) : QTableWidget(p) { viewport()->installEventFilter(this); @@ -46,7 +46,7 @@ protected: /// True if mouse wheel, else return the result of calling the base fucntion. bool eventFilter(QObject* obj, QEvent* e) { - if(e->type() == QEvent::Wheel) + if (e->type() == QEvent::Wheel) { e->ignore(); return true; diff --git a/Source/Fractorium/VariationTreeWidgetItem.h b/Source/Fractorium/VariationTreeWidgetItem.h index 522fffc..d887218 100644 --- a/Source/Fractorium/VariationTreeWidgetItem.h +++ b/Source/Fractorium/VariationTreeWidgetItem.h @@ -22,7 +22,7 @@ public: /// /// The ID of the variation this widget will represent /// The parent widget - VariationTreeWidgetItem(eVariationId id, QTreeWidget* p = 0) + VariationTreeWidgetItem(eVariationId id, QTreeWidget* p = nullptr) : QTreeWidgetItem(p) { m_Id = id;