#pragma once #include "EmberFile.h" #include "DoubleSpinBox.h" #include "GLEmberController.h" /// /// FractoriumEmberControllerBase and FractoriumEmberController classes. /// /// /// An enum representing the type of edit being done. /// enum class eEditUndoState : et { REGULAR_EDIT, UNDO_REDO, EDIT_UNDO }; /// /// An enum representing which xforms an update should be applied to. /// 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. /// class Fractorium; template class PreviewRenderer; template class TreePreviewRenderer; #define PREVIEW_SIZE 256 #define UNDO_SIZE 128 /// /// FractoriumEmberControllerBase serves as a non-templated base class with virtual /// functions which will be overridden in a derived class that takes a template parameter. /// The controller serves as a way to access both the Fractorium GUI and the underlying ember /// objects through an interface that doesn't require template argument, but does allow /// templated objects to be used underneath. /// Note that there are a few functions which access a templated object, so for those both /// versions for float and double must be provided, then overridden in the templated derived /// class. It's definitely a design flaw, but C++ doesn't offer any alternative since /// templated virtual functions are not supported. /// The functions not implemented in this file can be found in the GUI files which use them. /// class FractoriumEmberControllerBase : public RenderCallback { friend Fractorium; public: FractoriumEmberControllerBase(Fractorium* fractorium); FractoriumEmberControllerBase(const FractoriumEmberControllerBase& controller) = delete; virtual ~FractoriumEmberControllerBase(); //Embers. virtual void SetEmber(const Ember& ember, bool verbatim, bool updatePointer) { } virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) { }//Uncomment default lambdas once LLVM fixes a crash in their compiler with default lambda parameters.//TODO virtual void SetEmberFile(const EmberFile& emberFile, bool move) { } virtual void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) { } virtual void SetTempPalette(const Palette& palette) { } virtual void CopyTempPalette(Palette& palette) { } #ifdef DO_DOUBLE virtual void SetEmber(const Ember& ember, bool verbatim, bool updatePointer) { } virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) { } virtual void SetEmberFile(const EmberFile& emberFile, bool move) { } virtual void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) { } virtual void SetTempPalette(const Palette& palette) { } virtual void CopyTempPalette(Palette& palette) { } #endif virtual void SetEmber(size_t index, bool verbatim) { } virtual void AddXform() { } virtual void AddLinkedXform() { } virtual void DuplicateXform() { } virtual void ClearXform() { } virtual void DeleteXforms() { } virtual void AddFinalXform() { } virtual bool UseFinalXform() { return false; } virtual size_t XformCount() const { return 0; } virtual size_t TotalXformCount() const { return 0; } virtual QString Name() const { return ""; } virtual void Name(const string& s) { } virtual size_t FinalRasW() const { return 0; } virtual void FinalRasW(size_t w) { } virtual size_t FinalRasH() const { return 0; } virtual void FinalRasH(size_t h) { } virtual size_t Index() const { return 0; } virtual void AddSymmetry(int sym, QTIsaac& rand) { } virtual void CalcNormalizedWeights() { } //Menu. virtual void NewFlock(size_t count) { }//File. virtual void NewEmptyFlameInCurrentFile() { } virtual void NewRandomFlameInCurrentFile() { } virtual void CopyFlameInCurrentFile() { } virtual void OpenAndPrepFiles(const QStringList& filenames, bool append) { } virtual void SaveCurrentAsXml() { } virtual void SaveEntireFileAsXml() { } virtual uint SaveCurrentToOpenedFile(bool render = true) { return 0; } virtual void Undo() { }//Edit. virtual void Redo() { } virtual void CopyXml() { } virtual void CopyAllXml() { } virtual void PasteXmlAppend() { } virtual void PasteXmlOver() { } virtual void CopySelectedXforms() { } virtual void PasteSelectedXforms() { } virtual void AddReflectiveSymmetry() { }//Tools. virtual void AddRotationalSymmetry() { } virtual void AddBothSymmetry() { } virtual void Flatten() { } virtual void Unflatten() { } virtual void ClearFlame() { } //Toolbar. //Library. 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 RenderLibraryPreviews(uint start = UINT_MAX, uint end = UINT_MAX) { } virtual void RenderSequencePreviews(uint start = UINT_MAX, uint end = UINT_MAX) { } virtual void SequenceTreeItemChanged(QTreeWidgetItem* item, int col) { } virtual void StopLibraryPreviewRender() { } virtual void StopSequencePreviewRender() { } virtual void StopAllPreviewRenderers() { } virtual void MoveLibraryItems(const QModelIndexList& items, int destRow) { } virtual void Delete(const vector>& v) { } virtual void FillSequenceTree() { } virtual void SequenceGenerateButtonClicked() { } virtual void SequenceSaveButtonClicked() { } virtual void SequenceOpenButtonClicked() { } //Params. virtual void SetCenter(double x, double y) { } virtual void FillParamTablesAndPalette() { } virtual void BrightnessChanged(double d) { } virtual void GammaChanged(double d) { } virtual void GammaThresholdChanged(double d) { } virtual void VibrancyChanged(double d) { } virtual void HighlightPowerChanged(double d) { } virtual void PaletteModeChanged(uint i) { } virtual void WidthChanged(uint i) { } virtual void HeightChanged(uint i) { } virtual void CenterXChanged(double d) { } virtual void CenterYChanged(double d) { } virtual void ScaleChanged(double d) { } virtual void ZoomChanged(double d) { } virtual void RotateChanged(double d) { } virtual void ZPosChanged(double d) { } virtual void PerspectiveChanged(double d) { } virtual void PitchChanged(double d) { } virtual void YawChanged(double d) { } virtual void DepthBlurChanged(double d) { } virtual void SpatialFilterWidthChanged(double d) { } virtual void SpatialFilterTypeChanged(const QString& text) { } virtual void TemporalFilterWidthChanged(double d) { } virtual void TemporalFilterTypeChanged(const QString& text) { } virtual void DEFilterMinRadiusWidthChanged(double d) { } virtual void DEFilterMaxRadiusWidthChanged(double d) { } virtual void DEFilterCurveWidthChanged(double d) { } virtual void SbsChanged(int d) { } virtual void FuseChanged(int d) { } virtual void QualityChanged(double d) { } virtual void SupersampleChanged(int d) { } virtual void TemporalSamplesChanged(int d) { } virtual void AffineInterpTypeChanged(int i) { } virtual void InterpTypeChanged(int i) { } virtual void BackgroundChanged(const QColor& color) { } virtual void ClearColorCurves() { } virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) { } //Xforms. virtual void CurrentXformComboChanged(int index) { } virtual void XformWeightChanged(double d) { } virtual void EqualizeWeights() { } virtual void XformNameChanged(int row, int col) { } virtual void XformAnimateChanged(int state) { } virtual void FillXforms(int index = 0) { } //Xforms Affine. virtual void AffineSetHelper(double d, int index, bool pre) { } virtual void FlipXforms(bool horizontal, bool vertical, bool pre) { } virtual void RotateXformsByAngle(double angle, bool pre) { } virtual void MoveXforms(double x, double y, bool pre) { } virtual void ScaleXforms(double scale, bool pre) { } virtual void ResetXformsAffine(bool pre) { } virtual void RandomXformsAffine(bool pre) { } virtual void FillBothAffines() { } double LockedScale() { return m_LockedScale; } double LockedX() { return m_LockedX; } double LockedY() { return m_LockedY; } void LockedScale(double scale) { m_LockedScale = scale; } virtual void InitLockedScale() { } //Xforms Color. virtual void XformColorIndexChanged(double d, bool updateRender) { } virtual void XformScrollColorIndexChanged(int d) { } virtual void RandomColorIndicesButtonClicked() { } virtual void ToggleColorIndicesButtonClicked() { } virtual void RandomColorSpeedButtonClicked() { } virtual void ToggleColorSpeedButtonClicked() { } virtual void XformColorSpeedChanged(double d) { } virtual void XformOpacityChanged(double d) { } virtual void XformDirectColorChanged(double d) { } virtual QColor ColorIndexToQColor(double d) { return QColor(); } //Xforms Variations. virtual void Filter(const QString& text) { } virtual void SetupVariationsTree() { } virtual void ClearVariationsTree() { } virtual void VariationSpinBoxValueChanged(double d) { } virtual void FilteredVariations() { } //Xforms Selection. //Xaos. virtual void FillXaos() { } virtual void XaosChanged(int x, int y, double val) { } virtual void ClearXaos() { } virtual void RandomXaos() { } //Palette. virtual size_t InitPaletteList(const QString& s) { return 0; } virtual bool FillPaletteTable(const string& s) { return false; } virtual void ApplyPaletteToEmber() { } virtual void PaletteAdjust() { } virtual void PaletteCellClicked(int row, int col) { } virtual void SetBasePaletteAndAdjust(const Palette& palette) { } virtual void PaletteEditorButtonClicked() { } QImage& FinalPaletteImage() { return m_FinalPaletteImage; } //Info. virtual void FillSummary() { } //Rendering/progress. virtual bool Render() { return false; } virtual bool CreateRenderer(eRendererType renderType, const vector>& devices, bool shared = true) { return false; } virtual uint SizeOfT() const { return 0; } virtual void ClearUndo() { } virtual GLEmberControllerBase* GLController() { return nullptr; } bool RenderTimerRunning(); void StartRenderTimer(); void DelayedStartRenderTimer(); void StopRenderTimer(bool wait); void ClearFinalImages(); void Shutdown(); void UpdateRender(eProcessAction action = eProcessAction::FULL_RENDER); void DeleteRenderer(); void SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector& pixels, size_t width, size_t height, size_t channels, size_t bpc); RendererBase* Renderer() { return m_Renderer.get(); } vector* FinalImage() { return &(m_FinalImage); } vector* PreviewFinalImage() { return &m_PreviewFinalImage; } EmberStats Stats() { return m_Stats; } protected: //Rendering/progress. void AddProcessAction(eProcessAction action); eProcessAction CondenseAndClearProcessActions(); eProcessState ProcessState() { return m_Renderer.get() ? m_Renderer->ProcessState() : eProcessState::NONE; } //Non-templated members. bool m_Rendering = false; bool m_Shared = true; bool m_LastEditWasUndoRedo; vector> m_Devices; 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; double m_LockedX = 0; double m_LockedY = 0; eRendererType m_RenderType = eRendererType::CPU_RENDERER; eEditUndoState m_EditState; GLuint m_OutputTexID = 0; Timing m_RenderElapsedTimer; EmberStats m_Stats; QImage m_FinalPaletteImage; QString m_LastSaveAll; QString m_LastSaveCurrent; string m_CurrentPaletteFilePath; std::recursive_mutex m_Cs; std::thread m_WriteThread; vector m_FinalImage; vector m_PreviewFinalImage; vector m_ProcessActions; vector m_FilteredVariations; unique_ptr m_Renderer; QTIsaac m_Rand; Fractorium* m_Fractorium; Palette m_TempPalette; std::unique_ptr m_RenderTimer; std::unique_ptr m_RenderRestartTimer; shared_ptr> m_PaletteList; shared_ptr m_Info = OpenCLInfo::Instance(); }; /// /// Templated derived class which implements all interaction functionality between the embers /// of a specific template type and the GUI. /// Switching between template arguments requires complete re-creation of the controller and the /// underlying renderer. Switching between CPU and OpenCL only requires re-creation of the renderer. /// template class FractoriumEmberController : public FractoriumEmberControllerBase { friend PreviewRenderer; friend TreePreviewRenderer; public: FractoriumEmberController(Fractorium* fractorium); FractoriumEmberController(const FractoriumEmberController& controller) = delete; virtual ~FractoriumEmberController(); //Embers. virtual void SetEmber(const Ember& ember, bool verbatim, bool updatePointer) override; virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override; virtual void SetEmberFile(const EmberFile& emberFile, bool move) override; virtual void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override; virtual void SetTempPalette(const Palette& palette) override; virtual void CopyTempPalette(Palette& palette) override; #ifdef DO_DOUBLE virtual void SetEmber(const Ember& ember, bool verbatim, bool updatePointer) override; virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override; virtual void SetEmberFile(const EmberFile& emberFile, bool move) override; virtual void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override; virtual void SetTempPalette(const Palette& palette) override; virtual void CopyTempPalette(Palette& palette) override; #endif virtual void SetEmber(size_t index, bool verbatim) override; virtual void AddXform() override; virtual void AddLinkedXform() override; virtual void DuplicateXform() override; virtual void ClearXform() override; virtual void DeleteXforms() override; virtual void AddFinalXform() override; virtual bool UseFinalXform() override { return m_Ember.UseFinalXform(); } virtual size_t XformCount() const override { return m_Ember.XformCount(); } virtual size_t TotalXformCount() const override { return m_Ember.TotalXformCount(); } virtual QString Name() const override { return QString::fromStdString(m_Ember.m_Name); } virtual void Name(const string& s) override { m_Ember.m_Name = s; } virtual size_t FinalRasW() const override { return m_Ember.m_FinalRasW; } virtual void FinalRasW(size_t w) override { m_Ember.m_FinalRasW = w; } virtual size_t FinalRasH() const override { return m_Ember.m_FinalRasH; } virtual void FinalRasH(size_t h) override { m_Ember.m_FinalRasH = h; } virtual size_t Index() const override { return m_Ember.m_Index; } virtual void AddSymmetry(int sym, QTIsaac& rand) override { m_Ember.AddSymmetry(sym, rand); } virtual void CalcNormalizedWeights() override { m_Ember.CalcNormalizedWeights(m_NormalizedWeights); } void ConstrainDimensions(Ember& ember); Ember* CurrentEmber(); //Menu. virtual void NewFlock(size_t count) override; virtual void NewEmptyFlameInCurrentFile() override; virtual void NewRandomFlameInCurrentFile() override; virtual void CopyFlameInCurrentFile() override; virtual void OpenAndPrepFiles(const QStringList& filenames, bool append) override; virtual void SaveCurrentAsXml() override; virtual void SaveEntireFileAsXml() override; virtual uint SaveCurrentToOpenedFile(bool render = true) override; virtual void Undo() override; virtual void Redo() override; virtual void CopyXml() override; virtual void CopyAllXml() override; virtual void PasteXmlAppend() override; virtual void PasteXmlOver() override; virtual void CopySelectedXforms() override; virtual void PasteSelectedXforms() override; virtual void AddReflectiveSymmetry() override; virtual void AddRotationalSymmetry() override; virtual void AddBothSymmetry() override; virtual void Flatten() override; virtual void Unflatten() override; virtual void ClearFlame() override; //Toolbar. //Library. virtual void SyncLibrary(eLibraryUpdate update) override; virtual void FillLibraryTree(int selectIndex = -1) override; virtual void UpdateLibraryTree() override; virtual void MoveLibraryItems(const QModelIndexList& items, int destRow) override; virtual void Delete(const vector>& v) override; virtual void EmberTreeItemChanged(QTreeWidgetItem* item, int col) override; virtual void EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) override; void RenderPreviews(QTreeWidget* tree, TreePreviewRenderer* renderer, EmberFile& file, uint start = UINT_MAX, uint end = UINT_MAX); virtual void RenderLibraryPreviews(uint start = UINT_MAX, uint end = UINT_MAX) override; virtual void RenderSequencePreviews(uint start = UINT_MAX, uint end = UINT_MAX) override; virtual void SequenceTreeItemChanged(QTreeWidgetItem* item, int col) override; virtual void StopLibraryPreviewRender() override; virtual void StopSequencePreviewRender() override; virtual void StopAllPreviewRenderers() override; virtual void FillSequenceTree() override; virtual void SequenceGenerateButtonClicked() override; virtual void SequenceSaveButtonClicked() override; virtual void SequenceOpenButtonClicked() override; //Params. virtual void SetCenter(double x, double y) override; virtual void FillParamTablesAndPalette() override; virtual void BrightnessChanged(double d) override; virtual void GammaChanged(double d) override; virtual void GammaThresholdChanged(double d) override; virtual void VibrancyChanged(double d) override; virtual void HighlightPowerChanged(double d) override; virtual void PaletteModeChanged(uint i) override; virtual void WidthChanged(uint i) override; virtual void HeightChanged(uint i) override; virtual void CenterXChanged(double d) override; virtual void CenterYChanged(double d) override; virtual void ScaleChanged(double d) override; virtual void ZoomChanged(double d) override; virtual void RotateChanged(double d) override; virtual void ZPosChanged(double d) override; virtual void PerspectiveChanged(double d) override; virtual void PitchChanged(double d) override; virtual void YawChanged(double d) override; virtual void DepthBlurChanged(double d) override; virtual void SpatialFilterWidthChanged(double d) override; virtual void SpatialFilterTypeChanged(const QString& text) override; virtual void TemporalFilterWidthChanged(double d) override; virtual void TemporalFilterTypeChanged(const QString& text) override; virtual void DEFilterMinRadiusWidthChanged(double d) override; virtual void DEFilterMaxRadiusWidthChanged(double d) override; virtual void DEFilterCurveWidthChanged(double d) override; virtual void SbsChanged(int d) override; virtual void FuseChanged(int d) override; virtual void QualityChanged(double d) override; virtual void SupersampleChanged(int d) override; virtual void TemporalSamplesChanged(int d) override; virtual void AffineInterpTypeChanged(int index) override; virtual void InterpTypeChanged(int index) override; virtual void BackgroundChanged(const QColor& col) override; virtual void ClearColorCurves() override; virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) override; //Xforms. virtual void CurrentXformComboChanged(int index) override; virtual void XformWeightChanged(double d) override; virtual void EqualizeWeights() override; virtual void XformNameChanged(int row, int col) override; virtual void XformAnimateChanged(int state) override; virtual void FillXforms(int index = 0) override; void FillWithXform(Xform* xform); Xform* CurrentXform(); void UpdateXform(std::function*)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER); //Xforms Affine. virtual void AffineSetHelper(double d, int index, bool pre) override; virtual void FlipXforms(bool horizontal, bool vertical, bool pre) override; virtual void RotateXformsByAngle(double angle, bool pre) override; virtual void MoveXforms(double x, double y, bool pre) override; virtual void ScaleXforms(double scale, bool pre) override; virtual void ResetXformsAffine(bool pre) override; virtual void RandomXformsAffine(bool pre) override; virtual void FillBothAffines() override; virtual void InitLockedScale() override; void FillAffineWithXform(Xform* xform, bool pre); void ChangeLockedScale(T value); T AffineScaleCurrentToLocked(); T AffineScaleLockedToCurrent(); //Xforms Color. virtual void XformColorIndexChanged(double d, bool updateRender) override; virtual void XformScrollColorIndexChanged(int d) override; virtual void RandomColorIndicesButtonClicked() override; virtual void ToggleColorIndicesButtonClicked() override; virtual void RandomColorSpeedButtonClicked() override; virtual void ToggleColorSpeedButtonClicked() override; virtual void XformColorSpeedChanged(double d) override; virtual void XformOpacityChanged(double d) override; virtual void XformDirectColorChanged(double d) override; virtual QColor ColorIndexToQColor(double d) override; void FillColorWithXform(Xform* xform); //Xforms Variations. virtual void Filter(const QString& text) override; virtual void SetupVariationsTree() override; virtual void ClearVariationsTree() override; virtual void VariationSpinBoxValueChanged(double d) override; virtual void FilteredVariations() override; void FillVariationTreeWithXform(Xform* xform); //Xforms Xaos. virtual void FillXaos() override; virtual void XaosChanged(int x, int y, double val) override; virtual void ClearXaos() override; virtual void RandomXaos() override; //Xforms Selection. bool XformCheckboxAt(int i, std::function func); bool XformCheckboxAt(Xform* xform, std::function func); //Palette. virtual size_t InitPaletteList(const QString& s) override; virtual bool FillPaletteTable(const string& s) override; virtual void ApplyPaletteToEmber() override; virtual void PaletteAdjust() override; virtual void PaletteCellClicked(int row, int col) override; virtual void SetBasePaletteAndAdjust(const Palette& palette) override; virtual void PaletteEditorButtonClicked() override; //Info. virtual void FillSummary() override; //Rendering/progress. virtual bool Render() override; virtual bool CreateRenderer(eRendererType renderType, const vector>& devices, bool shared = true) override; virtual uint SizeOfT() const override { return sizeof(T); } virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) override; virtual void ClearUndo() override; virtual GLEmberControllerBase* GLController() override { return m_GLController.get(); } private: //Embers. void ApplyXmlSavingTemplate(Ember& ember); template void SetEmberPrivate(const Ember& ember, bool verbatim, bool updatePointer); //Params. void ParamsToEmber(Ember& ember); //Xforms. void SetNormalizedWeightText(Xform* xform); bool IsFinal(Xform* xform); //Xforms Color. void FillCurvesControl(); //Xforms Selection. QString MakeXformCaption(size_t i); //Palette. void UpdateAdjustedPaletteGUI(Palette& palette); //Rendering/progress. void Update(std::function func, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER); void UpdateAll(std::function&)> func, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER, bool applyAll = false); bool SyncSizes(); //Templated members. bool m_PreviewRunning = false; vector m_TempOpacities; vector m_NormalizedWeights; Ember m_Ember; const void* m_EmberFilePointer = nullptr; EmberFile m_EmberFile; EmberFile m_SequenceFile; deque> m_UndoList; vector> m_CopiedXforms; Xform m_CopiedFinalXform; shared_ptr> m_VariationList; unique_ptr> m_SheepTools; unique_ptr> m_GLController; unique_ptr> m_LibraryPreviewRenderer; unique_ptr> m_SequencePreviewRenderer; }; /// /// Base class for encapsulating a preview renderer which will be used /// in such places as the main library tree, the sequence tree and the /// single preview thumbnail shown in the final render dialog. /// Derived classes will implement PreviewRenderFunc() to handle the rendering /// functionality specific to their previews. /// template class PreviewRenderer { public: PreviewRenderer() { } void Render(uint start, uint end) { Stop(); m_PreviewResult = QtConcurrent::run([&](uint s, uint e) { rlg l(m_PreviewCs); m_PreviewRun = true; PreviewRenderFunc(s, e); m_PreviewRun = false; }, start, end); } void Stop() { m_PreviewRun = false; m_PreviewRenderer.Abort(); m_PreviewResult.cancel(); while (m_PreviewResult.isRunning()) QApplication::processEvents(); } bool EarlyClip() { return m_PreviewRenderer.EarlyClip(); } bool YAxisUp() { return m_PreviewRenderer.YAxisUp(); } bool Transparency() { return m_PreviewRenderer.Transparency(); } bool Running() { return m_PreviewRun || m_PreviewResult.isRunning(); } virtual void PreviewRenderFunc(uint start, uint end) {} protected: volatile bool m_PreviewRun = false; Ember m_PreviewEmber; vector m_PreviewFinalImage; EmberNs::Renderer m_PreviewRenderer; private: QFuture m_PreviewResult; std::recursive_mutex m_PreviewCs; }; /// /// Thin derivation to handle preview rendering multiple embers previews to a tree. /// template class TreePreviewRenderer : public PreviewRenderer { public: using PreviewRenderer::m_PreviewRun; using PreviewRenderer::m_PreviewEmber; using PreviewRenderer::m_PreviewRenderer; using PreviewRenderer::m_PreviewFinalImage; /// /// Initializes a new instance of the class. /// /// A pointer to the controller this instance is a member of /// A pointer to the tree to render to /// A reference to the ember file to render TreePreviewRenderer(FractoriumEmberController* controller, QTreeWidget* tree, EmberFile& emberFile) : m_Controller(controller), m_Tree(tree), m_EmberFile(emberFile) { auto f = m_Controller->m_Fractorium; m_PreviewRenderer.Callback(nullptr); m_PreviewRenderer.NumChannels(4); m_PreviewRenderer.EarlyClip(f->m_Settings->EarlyClip()); m_PreviewRenderer.YAxisUp(f->m_Settings->YAxisUp()); m_PreviewRenderer.Transparency(f->m_Settings->Transparency()); } virtual void PreviewRenderFunc(uint start, uint end) override; protected: FractoriumEmberController* m_Controller; QTreeWidget* m_Tree; EmberFile& m_EmberFile; };