diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index b2d3b42..d47e530 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -103,6 +103,7 @@ Fractorium::Fractorium(QWidget* p) InitXaosUI(); InitPaletteUI(); InitLibraryUI(); + InitInfoUI(); InitMenusUI(); //This will init the controller and fill in the variations and palette tables with template specific instances @@ -175,6 +176,7 @@ Fractorium::Fractorium(QWidget* p) ui.XformPaletteRefTable->setStyleSheet("QTableWidget::item { padding: 0px; border: none; margin: 0px; }"); ui.PaletteAdjustTable->setStyleSheet("QTableWidget::item { padding: 1px; }");//Need this to avoid covering the top border pixel with the spinners. ui.statusBar->setStyleSheet("QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }"); + ui.XaosTableView->setStyleSheet("QTableView { margin: 1px}"); //setStyleSheet("QGroupBox { border: 2px solid gray; border-radius: 3px; } "); @@ -747,7 +749,11 @@ void Fractorium::SetTabOrders() w = SetTabOrder(this, w, ui.PaletteFilterClearButton); w = SetTabOrder(this, w, ui.PaletteListTable); - w = SetTabOrder(this, ui.InfoBoundsGroupBox, ui.InfoBoundsFrame);//Info. + + w = SetTabOrder(this, ui.SummaryTableWidget, ui.SummaryTreeWidget);//Info summary. + + w = SetTabOrder(this, ui.InfoBoundsGroupBox, ui.InfoBoundsFrame);//Info bounds. + w = SetTabOrder(this, w, ui.InfoBoundsTable); w = SetTabOrder(this, w, ui.InfoFileOpeningGroupBox); w = SetTabOrder(this, w, ui.InfoFileOpeningTextEdit); diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index ac92fe1..9f5fc9f 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -142,9 +142,6 @@ public slots: void OnActionAbout(bool checked);//Help. //Toolbar. - void OnSaveCurrentAsXmlButtonClicked(bool checked); - void OnSaveEntireFileAsXmlButtonClicked(bool checked); - void OnSaveCurrentToOpenedFileButtonClicked(bool checked); //Library. void OnEmberTreeItemChanged(QTreeWidgetItem* item, int col); @@ -275,6 +272,10 @@ public slots: void OnPaletteFilterClearButtonClicked(bool checked); void OnPaletteHeaderSectionClicked(int col); + //Info. + void OnSummaryTableHeaderResized(int logicalIndex, int oldSize, int newSize); + void OnSummaryTreeHeaderSectionClicked(int logicalIndex); + //Rendering/progress. void StartRenderTimer(); void IdleTimer(); @@ -311,6 +312,7 @@ private: void InitXaosUI(); void InitPaletteUI(); void InitLibraryUI(); + void InitInfoUI(); void SetTabOrders(); void ToggleTableRow(QTableView* table, int logicalIndex); @@ -342,10 +344,13 @@ private: //Palette. void ResetPaletteControls(); void SetPaletteFileComboIndex(const string& filename); + void SetPaletteTableItem(QPixmap* pixmap, QTableWidget* table, QTableWidgetItem* item, int row, int col); //Info. + void FillSummary(); void UpdateHistogramBounds(); void ErrorReportToQTextEdit(const vector& errors, QTextEdit* textEdit, bool clear = true); + void SetTableWidgetBackgroundColor(); //Rendering/progress. bool CreateRendererFromOptions(); @@ -441,6 +446,14 @@ private: SpinBox* m_PaletteBlurSpin; SpinBox* m_PaletteFrequencySpin; + //Info. + QTableWidgetItem* m_InfoNameItem; + QTableWidgetItem* m_InfoPaletteItem; + QTableWidgetItem* m_Info3dItem; + QTableWidgetItem* m_InfoXaosItem; + QTableWidgetItem* m_InfoXformCountItem; + QTableWidgetItem* m_InfoFinalXformItem; + //Files. QFileDialog* m_FileDialog; QFileDialog* m_FolderDialog; diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index caf978c..d2af808 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -6,7 +6,7 @@ 0 0 - 1418 + 1442 926 @@ -74,8 +74,8 @@ 0 0 - 1217 - 885 + 1175 + 861 @@ -1551,19 +1551,31 @@ 4 - 5 + 4 - 5 + 4 - 5 + 4 4 + + 4 + + + QLayout::SetDefaultConstraint + + + 0 + + + 0 + @@ -1572,6 +1584,15 @@ Clear Xaos + + false + + + false + + + false + @@ -1715,7 +1736,7 @@ 240 - 200 + 498 @@ -1741,202 +1762,6 @@ 4 - - - - - - - - 2 - 0 - - - - - 0 - 67 - - - - - 16777215 - 67 - - - - Qt::NoFocus - - - QFrame::Panel - - - QFrame::Plain - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - false - - - QAbstractItemView::NoEditTriggers - - - false - - - QAbstractItemView::NoSelection - - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - - - false - - - false - - - 3 - - - 4 - - - false - - - 62 - - - 62 - - - true - - - false - - - 22 - - - false - - - 22 - - - - - - - - - - - Hue - - - - - Contrast - - - - - Saturation - - - - - Blur - - - - - Brightness - - - - - - - - - - Frequency - - - - - - - - 4 - - - 0 - - - 0 - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - Select a random palette from the list - - - Random Palette - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - Apply a random adjustment to the current palette - - - Random Adjustment - - - false - - - - - @@ -2140,6 +1965,202 @@ + + + + + + + + 2 + 0 + + + + + 0 + 67 + + + + + 16777215 + 67 + + + + Qt::NoFocus + + + QFrame::Panel + + + QFrame::Plain + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + false + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + false + + + false + + + 3 + + + 4 + + + false + + + 62 + + + 62 + + + true + + + false + + + 22 + + + false + + + 22 + + + + + + + + + + + Hue + + + + + Contrast + + + + + Saturation + + + + + Blur + + + + + Brightness + + + + + + + + + + Frequency + + + + + + + + 4 + + + 0 + + + 0 + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + Select a random palette from the list + + + Random Palette + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + Apply a random adjustment to the current palette + + + Random Adjustment + + + false + + + + + @@ -3284,7 +3305,7 @@ SpinBox 0 0 - 237 + 243 745 @@ -4941,7 +4962,7 @@ SpinBox 0 0 - 237 + 243 680 @@ -4998,15 +5019,15 @@ SpinBox - 1030 + 1000 0 - 200 + 301 881 - 80 + 137 200 @@ -5019,7 +5040,7 @@ SpinBox Info - + 6 @@ -5037,7 +5058,13 @@ SpinBox 4 - + + + + 0 + 0 + + QFrame::NoFrame @@ -5047,18 +5074,27 @@ SpinBox 1 + + Qt::ScrollBarAsNeeded + true - + 0 0 - 190 + 291 851 + + + 0 + 0 + + 0 @@ -5076,451 +5112,820 @@ SpinBox 0 - + - + 0 0 - - - 0 - 250 - + + QTabWidget::Triangular - - - 16777215 - 250 - + + 0 - - - 0 - 0 - - - - Qt::StrongFocus - - - false - - - Histogram Bounds - - - - 4 - - - 6 - - - 4 - - - 6 - - - 6 - - - - - - 0 - 0 - - - - - 0 - 173 - - - - - 16777215 - 173 - - - - false - - - QFrame::Box - - - QFrame::Plain - - - - 2 + + + Summary + + + + 5 + + + 5 + + + 4 + + + 5 + + + 4 + + + + + + 0 + 0 + - - 2 + + + 0 + 128 + - - 2 + + + 16777215 + 128 + - - 2 + + Qt::NoFocus - - 2 + + QFrame::StyledPanel + + QFrame::Plain + + + 1 + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerItem + + + true + + + false + + + false + + + false + + + 22 + + + 22 + + + true + + + true + + + false + + + 21 + + + 21 + + + false + + + + Name + + + + + Palette + + + + + 3D Used + + + + + Xaos Used + + + + + Xform Count + + + + + Final Xform + + + + + + + - - - QFrame::Box - - - QFrame::Plain - - - UL: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - + + Test Flame + - - - - QFrame::Box - - - LR: - - - Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing - - - - - - - QFrame::Box - - - UR: - - - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing - - - - - - - QFrame::Box - - - W x H: - - - Qt::AlignCenter - - + + + + - - - QFrame::Box + + Yes + + + + + Yes + + + + + 5 + + + + + Yes + + + + + + + + + 0 + 0 + + + + QFrame::Plain + + + Qt::ScrollBarAsNeeded + + + Qt::ScrollBarAsNeeded + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::NoSelection + + + true + + + true + + + 2 + + + true + + + false + + + 100 + + + 30 + + + false + + + true + + + + + + + + + + + + + + Xform 1 + + + Xform 1 Name + + + + Pre Affine - LL: + 1, 2, 3, 4, 5, 6 - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + Post Affine - + + 7, 8, 9, 10, 11, 12 + + + + + Variation 1 + + + 1.234 + + + + Var1p1 + + + 2.4456 + + + + + Var1p2 + + + 3.56 + + + + + + Variation 2 + + + 2.2 + + - - - - - - - - 0 - 0 - - - - - 0 - 46 - - - - - 16777215 - 46 - - - - - true - - - - Qt::NoFocus - - - - - - QFrame::Panel - - - QFrame::Plain - - - 1 - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - false - - - QAbstractItemView::NoEditTriggers - - - false - - - false - - - false - - - QAbstractItemView::NoSelection - - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - - - true - - - Qt::SolidLine - - - false - - - false - - - 2 - - - false - - - false - - - 110 - - - false - - - 27 - - - true - - - false - - - 22 - - - false - - - 22 - - - false - - - - Gutter - - - - - DE Box Dimensions - - - - - Field - - - - - - - - - - Gutter - - - - - 0 - - - - - DE Box Dimensions - - - - - 0 - - - - true - - - - AlignLeft|AlignVCenter - - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::StrongFocus - - - File Opening - - - - 4 + + + + + + + + + + + Xform 2 + + + + + + + + + + + + + + + + Final Xform + + + + + + + + + + + + + 0 + 0 + - - 6 - - - 4 - - - 6 - - - 6 - - - - - - 0 - 0 - - - - Qt::StrongFocus - - - true - - - - - - - - - - - 0 - 0 - - - - Qt::StrongFocus - - - Rendering - - - - 4 - - - 6 - - - 4 - - - 6 - - - 6 - - - - - - 0 - 0 - - - - Qt::StrongFocus - - - true - - - true - - - Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - + + Bounds + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 250 + + + + + 16777215 + 250 + + + + + 0 + 0 + + + + Qt::StrongFocus + + + false + + + Histogram Bounds + + + + 4 + + + 6 + + + 4 + + + 6 + + + 6 + + + + + + 0 + 0 + + + + + 0 + 173 + + + + + 16777215 + 173 + + + + false + + + QFrame::Box + + + QFrame::Plain + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + QFrame::Box + + + QFrame::Plain + + + UL: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + QFrame::Box + + + LR: + + + Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing + + + + + + + QFrame::Box + + + UR: + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + + + QFrame::Box + + + W x H: + + + Qt::AlignCenter + + + + + + + QFrame::Box + + + LL: + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + + + + 0 + 0 + + + + + 0 + 46 + + + + + 16777215 + 46 + + + + + true + + + + Qt::NoFocus + + + + + + QFrame::Panel + + + QFrame::Plain + + + 1 + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + false + + + QAbstractItemView::NoEditTriggers + + + false + + + false + + + false + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + true + + + Qt::SolidLine + + + false + + + false + + + 2 + + + false + + + false + + + 110 + + + false + + + 27 + + + true + + + false + + + 22 + + + false + + + 22 + + + false + + + + Gutter + + + + + DE Box Dimensions + + + + + Field + + + + + + + + + + Gutter + + + + + 0 + + + + + DE Box Dimensions + + + + + 0 + + + + true + + + + AlignLeft|AlignVCenter + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::StrongFocus + + + File Opening + + + + 4 + + + 6 + + + 4 + + + 6 + + + 6 + + + + + + 0 + 0 + + + + Qt::StrongFocus + + + true + + + + + + + + + + + 0 + 0 + + + + Qt::StrongFocus + + + Rendering + + + + 4 + + + 6 + + + 4 + + + 6 + + + 6 + + + + + + 0 + 0 + + + + Qt::StrongFocus + + + true + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + @@ -5537,7 +5942,7 @@ SpinBox 0 0 - 1418 + 1442 21 @@ -5671,102 +6076,17 @@ SpinBox 4 - 6 + 5 - 3 + 5 - 6 + 5 - 6 + 4 - - - - 4 - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - Save the current flame as an xml file - - - - - - - :/Fractorium/Icons/database-medium.png:/Fractorium/Icons/database-medium.png - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - Save all flames as a single xml file - - - - - - - :/Fractorium/Icons/databases.png:/Fractorium/Icons/databases.png - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - <html><head/><body><p>Save the currently displayed flame back to the opened file in memory.</p><p>This overwrites the original flame but does not store the file back to disk.</p></body></html> - - - - - - - :/Fractorium/Icons/document-hf-insert.png:/Fractorium/Icons/document-hf-insert.png - - - - - @@ -5786,8 +6106,8 @@ SpinBox 0 0 - 188 - 824 + 256 + 830 @@ -5843,6 +6163,42 @@ SpinBox + + + toolBar + + + true + + + true + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + + @@ -6194,9 +6550,6 @@ SpinBox LibraryDockWidget - SaveCurrentAsXmlButton - SaveEntireFileAsXmlButton - SaveCurrentToOpenedFileButton diff --git a/Source/Fractorium/FractoriumCommon.h b/Source/Fractorium/FractoriumCommon.h index ff8f80d..0e318ce 100644 --- a/Source/Fractorium/FractoriumCommon.h +++ b/Source/Fractorium/FractoriumCommon.h @@ -111,3 +111,78 @@ static bool Exists(const QString& s) { return s != "" && QDir(s).exists(); } + +/// +/// Convert a color to one that is displayable on any background. +/// +/// The color to convert +/// The converted color +static QColor VisibleColor(const QColor& color) +{ + int threshold = 105; + int delta = (color.red() * 0.299) + //Magic numbers gotten from a Stack Overflow post. + (color.green() * 0.587) + + (color.blue() * 0.114); + + QColor textColor = (255 - delta < threshold) ? QColor(0, 0, 0) : QColor(255, 255, 255); + return textColor; +} + +/// +/// Determine whether an xform in an ember is linked to any other xform +/// in the ember. +/// +/// The ember which contains the xform +/// The xform to inspect +/// The index of the xform that the xform argument is linked to, else -1 +template +static intmax_t IsXformLinked(Ember& ember, Xform* xform) +{ + auto count = ember.XformCount(); + auto index = ember.GetXformIndex(xform); + intmax_t linked = -1; + size_t toOneCount = 0; + size_t toZeroCount = 0; + size_t toOneIndex = 0; + size_t fromOneCount = 0; + size_t fromZeroCount = 0; + size_t fromOneIndex = 0; + + if (index >= 0) + { + for (auto i = 0; i < count; i++) + { + if (xform->Xaos(i) == 0) + toZeroCount++; + else if (xform->Xaos(i) == 1) + { + toOneIndex = i; + toOneCount++; + } + } + + if ((toZeroCount == (count - 1)) && toOneCount == 1) + { + for (auto i = 0; i < count; i++) + { + if (auto fromXform = ember.GetXform(i)) + { + if (fromXform->Xaos(toOneIndex) == 0) + fromZeroCount++; + else if (fromXform->Xaos(toOneIndex) == 1) + { + fromOneIndex = i; + fromOneCount++; + } + } + } + + if ((fromZeroCount == (count - 1)) && fromOneCount == 1) + { + linked = toOneIndex; + } + } + } + + return linked; +} \ No newline at end of file diff --git a/Source/Fractorium/FractoriumEmberController.cpp b/Source/Fractorium/FractoriumEmberController.cpp index 70a4dbe..76774bb 100644 --- a/Source/Fractorium/FractoriumEmberController.cpp +++ b/Source/Fractorium/FractoriumEmberController.cpp @@ -217,6 +217,7 @@ template void FractoriumEmberController::Update(std::function func, bool updateRender, eProcessAction action) { func(); + FillSummary(); if (updateRender) UpdateRender(action); @@ -294,6 +295,8 @@ void FractoriumEmberController::UpdateXform(std::function*)> fu break; } + FillSummary(); + if (updateRender) UpdateRender(action); } @@ -305,6 +308,7 @@ void FractoriumEmberController::UpdateXform(std::function*)> fu /// Resets the rendering process. /// /// The ember to set as the current +/// If true, do not overwrite temporal samples, quality or supersample value, else overwrite. template template void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool verbatim) @@ -335,6 +339,7 @@ void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool v m_GLController->ResetMouseState(); FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo. FillParamTablesAndPalette(); + FillSummary(); //If a resize happened, this won't do anything because the new size is not reflected in the scroll area yet. //However, it will have been taken care of in SyncSizes() in that case, so it's ok. diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index 4a6b5af..07f7207 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -178,7 +178,7 @@ public: virtual void XformColorSpeedChanged(double d) { } virtual void XformOpacityChanged(double d) { } virtual void XformDirectColorChanged(double d) { } - void SetPaletteRefTable(QPixmap* pixmap); + virtual QColor ColorIndexToQColor(double d) { return QColor(); } //Xforms Variations. virtual void SetupVariationTree() { } @@ -199,11 +199,12 @@ public: virtual bool FillPaletteTable(const string& s) { return false; } virtual void ApplyPaletteToEmber() { } virtual void PaletteAdjust() { } - virtual QRgb GetQRgbFromPaletteIndex(uint i) { return QRgb(); } virtual void PaletteCellClicked(int row, int col) { } + QImage& FinalPaletteImage() { return m_FinalPaletteImage; } //Info. - + virtual void FillSummary() { } + //Rendering/progress. virtual bool Render() { return false; } virtual bool CreateRenderer(eRendererType renderType, uint platform, uint device, bool shared = true) { return false; } @@ -413,6 +414,7 @@ public: 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. @@ -433,10 +435,10 @@ public: virtual bool FillPaletteTable(const string& s) override; virtual void ApplyPaletteToEmber() override; virtual void PaletteAdjust() override; - virtual QRgb GetQRgbFromPaletteIndex(uint i) override { return QRgb(); } virtual void PaletteCellClicked(int row, int col) override; //Info. + virtual void FillSummary() override; //Rendering/progress. virtual bool Render() override; diff --git a/Source/Fractorium/FractoriumInfo.cpp b/Source/Fractorium/FractoriumInfo.cpp index c0d014a..6066c02 100644 --- a/Source/Fractorium/FractoriumInfo.cpp +++ b/Source/Fractorium/FractoriumInfo.cpp @@ -1,6 +1,219 @@ #include "FractoriumPch.h" #include "Fractorium.h" +/// +/// Initialize the info UI. +/// +void Fractorium::InitInfoUI() +{ + auto treeHeader = ui.SummaryTreeWidget->header(); + auto tableHeader = ui.SummaryTableWidget->horizontalHeader(); + + treeHeader->setVisible(true); + treeHeader->setSectionsClickable(true); + treeHeader->setSectionResizeMode(QHeaderView::ResizeToContents); + connect(treeHeader, SIGNAL(sectionClicked(int)), this, SLOT(OnSummaryTreeHeaderSectionClicked(int)), Qt::QueuedConnection); + connect(tableHeader, SIGNAL(sectionResized(int, int, int)), this, SLOT(OnSummaryTableHeaderResized(int, int, int)), Qt::QueuedConnection); + SetFixedTableHeader(ui.SummaryTableWidget->verticalHeader()); + + ui.SummaryTableWidget->setItem(0, 0, m_InfoNameItem = new QTableWidgetItem("")); + ui.SummaryTableWidget->setItem(1, 0, m_InfoPaletteItem = new QTableWidgetItem("")); + ui.SummaryTableWidget->setItem(2, 0, m_Info3dItem = new QTableWidgetItem("")); + ui.SummaryTableWidget->setItem(3, 0, m_InfoXaosItem = new QTableWidgetItem("")); + ui.SummaryTableWidget->setItem(4, 0, m_InfoXformCountItem = new QTableWidgetItem("")); + ui.SummaryTableWidget->setItem(5, 0, m_InfoFinalXformItem = new QTableWidgetItem("")); +} + +/// +/// Called when the palette cell of the summary table is resized in response +/// to a resizing of the Info dock. +/// +/// Ignored +/// Ignored +/// Ignored +void Fractorium::OnSummaryTableHeaderResized(int logicalIndex, int oldSize, int newSize) +{ + QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage());//Create a QPixmap out of the QImage. + SetPaletteTableItem(&pixmap, ui.SummaryTableWidget, m_InfoPaletteItem, 1, 0); +} + +/// +/// Expand or collapse the summary tree depending on the column index clicked. +/// 0: collapse, 1: expand. +/// +/// The column which was clicked +void Fractorium::OnSummaryTreeHeaderSectionClicked(int logicalIndex) +{ + auto tree = ui.SummaryTreeWidget; + + if (logicalIndex) + tree->expandAll(); + else + tree->collapseAll(); +} + +/// +/// Fill the summary tree with values from the current ember. +/// This is meant to be a rough summary by containing only the most relevant +/// values from the ember. +/// It's also meant to be used in a fire-and-forget way. Once the tree is filled +/// individual nodes are never referenced again. +/// The entire tree is cleared and refilled for every field change. +/// This would seem inefficient, but it appears to update with no flicker. +/// If this ever presents a problem in the future, revisit with a more +/// intelligent design. +/// +template +void FractoriumEmberController::FillSummary() +{ + int p = 3; + int vp = 4; + int vlen = 7; + char pc = 'f'; + size_t x = 0, total = m_Ember.TotalXformCount(); + Xform* xform = nullptr; + QColor color; + auto table = m_Fractorium->ui.SummaryTableWidget; + auto tree = m_Fractorium->ui.SummaryTreeWidget; + QVariantList states; + QTreeWidgetItemIterator it(tree); + + while (*it) + { + if (!(*it)->parent())//Top level only. + states += (*it)->isExpanded(); + + ++it; + } + + tree->blockSignals(true); + tree->clear(); + m_Fractorium->m_InfoNameItem->setText(m_Ember.m_Name.c_str()); + m_Fractorium->m_Info3dItem->setText(m_Ember.ProjBits() ? "Yes" : "No"); + m_Fractorium->m_InfoXaosItem->setText(m_Ember.XaosPresent() ? "Yes" : "No"); + m_Fractorium->m_InfoXformCountItem->setText(QString::number(m_Ember.XformCount())); + m_Fractorium->m_InfoFinalXformItem->setText(m_Ember.UseFinalXform() ? "Yes" : "No"); + + QPixmap pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage. + QSize size(table->columnWidth(0), table->rowHeight(1) + 1); + m_Fractorium->m_InfoPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + + for (x = 0; x < total && (xform = m_Ember.GetTotalXform(x)); x++) + { + size_t i = 0; + QString as = "Pre"; + auto item1 = new QTreeWidgetItem(tree); + intmax_t linkedIndex = IsXformLinked(m_Ember, xform); + QString linked = (linkedIndex != -1) ? (" Linked to " + QString::number(linkedIndex + 1)) : ""; + auto index = m_Ember.GetXformIndex(xform); + m_Ember.CalcNormalizedWeights(m_NormalizedWeights); + + if (!m_Ember.IsFinalXform(xform) && index != -1) + { + item1->setText(0, "Xform " + + QString::number(x + 1) + + " (" + QLocale::system().toString(xform->m_Weight, pc, p) + ") (" + + QLocale::system().toString(double(m_NormalizedWeights[index]), pc, p) + ") " + + linked); + } + else + item1->setText(0, "Final xform"); + + item1->setText(1, xform->m_Name.c_str()); + + auto affineItem = new QTreeWidgetItem(item1); + affineItem->setText(0, "Affine"); + + if (xform->m_Affine.IsZero()) + as += " Empty"; + else if (xform->m_Affine.IsID()) + as += " ID"; + + if (xform->HasPost()) + { + as += ", Post"; + + if (xform->m_Post.IsZero()) + as += " Empty";//Don't need to check further for IsID() because post is not included if it's ID. + } + + affineItem->setText(1, as); + + auto colorIndexItem = new QTreeWidgetItem(item1); + colorIndexItem->setText(0, "Color index"); + colorIndexItem->setText(1, QLocale::system().toString(xform->m_ColorX, pc, p)); + color = ColorIndexToQColor(xform->m_ColorX); + color.setAlphaF(xform->m_Opacity); + colorIndexItem->setBackgroundColor(1, color); + colorIndexItem->setTextColor(1, VisibleColor(color)); + + auto colorSpeedItem = new QTreeWidgetItem(item1); + colorSpeedItem->setText(0, "Color speed"); + colorSpeedItem->setText(1, QLocale::system().toString(xform->m_ColorSpeed, pc, p)); + + auto opacityItem = new QTreeWidgetItem(item1); + opacityItem->setText(0, "Opacity"); + opacityItem->setText(1, QLocale::system().toString(xform->m_Opacity, pc, p)); + + auto dcItem = new QTreeWidgetItem(item1); + dcItem->setText(0, "Direct color"); + dcItem->setText(1, QLocale::system().toString(xform->m_DirectColor, pc, p)); + + while (auto var = xform->GetVariation(i++)) + { + auto vitem = new QTreeWidgetItem(item1); + + vitem->setText(0, QString::fromStdString(var->Name())); + vitem->setText(1, QLocale::system().toString(var->m_Weight, pc, vp).rightJustified(vlen, ' ')); + + if (auto parVar = dynamic_cast*>(var)) + { + auto params = parVar->Params(); + + for (auto j = 0; j < parVar->ParamCount(); j++) + { + if (!params[j].IsPrecalc()) + { + auto pitem = new QTreeWidgetItem(vitem); + + pitem->setText(0, params[j].Name().c_str()); + pitem->setText(1, QLocale::system().toString(params[j].ParamVal(), pc, vp).rightJustified(vlen, ' ')); + } + } + } + } + + auto item2 = new QTreeWidgetItem(tree);//Empty item in between xforms. + } + + QTreeWidgetItemIterator it2(tree); + + if (!states.isEmpty()) + { + while (*it2) + { + if (!(*it2)->parent())//Top level only. + { + if (!states.isEmpty()) + (*it2)->setExpanded(states.takeFirst().toBool()); + else + (*it2)->setExpanded(true);//Expand any remainder when going from lesser to greater number of xforms. + } + + ++it2; + } + } + else + tree->expandAll(); + + tree->blockSignals(false); +} + +void Fractorium::FillSummary() +{ + m_Controller->FillSummary(); +} + /// /// Update the histogram bounds display labels. /// This shows the user the actual bounds of what's @@ -54,3 +267,9 @@ void Fractorium::ErrorReportToQTextEdit(const vector& errors, QTextEdit* for (auto& error : errors) QMetaObject::invokeMethod(textEdit, "append", Qt::QueuedConnection, Q_ARG(const QString&, QString::fromStdString(error) + "\n")); } + +template class FractoriumEmberController; + +#ifdef DO_DOUBLE +template class FractoriumEmberController; +#endif diff --git a/Source/Fractorium/FractoriumLibrary.cpp b/Source/Fractorium/FractoriumLibrary.cpp index d63e40b..b780518 100644 --- a/Source/Fractorium/FractoriumLibrary.cpp +++ b/Source/Fractorium/FractoriumLibrary.cpp @@ -226,8 +226,9 @@ void FractoriumEmberController::EmberTreeItemChanged(QTreeWidgetItem* item, i 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. } - + tree->blockSignals(false); + FillSummary(); } else if (QTreeWidgetItem* parentItem = dynamic_cast(item)) { diff --git a/Source/Fractorium/FractoriumPalette.cpp b/Source/Fractorium/FractoriumPalette.cpp index 00502c8..7623f46 100644 --- a/Source/Fractorium/FractoriumPalette.cpp +++ b/Source/Fractorium/FractoriumPalette.cpp @@ -192,7 +192,7 @@ void FractoriumEmberController::UpdateAdjustedPaletteGUI(Palette& palette) memcpy(m_FinalPaletteImage.scanLine(0), v.data(), v.size() * sizeof(v[0]));//Memcpy the data in. QPixmap pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage. previewPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(QSize(pixmap.width(), palettePreviewTable->rowHeight(0) + 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));//Set the pixmap on the palette tab. - SetPaletteRefTable(&pixmap);//Set the palette ref table on the xforms | color tab. + m_Fractorium->SetPaletteTableItem(&pixmap, m_Fractorium->ui.XformPaletteRefTable, m_Fractorium->m_PaletteRefItem, 0, 0);//Set the palette ref table on the xforms | color tab. QTableWidgetItem* previewNameItem = palettePreviewTable->item(0, 0); previewNameItem->setText(paletteName);//Finally, set the name of the palette to be both the text and the tooltip. diff --git a/Source/Fractorium/FractoriumParams.cpp b/Source/Fractorium/FractoriumParams.cpp index f434f14..f24c856 100644 --- a/Source/Fractorium/FractoriumParams.cpp +++ b/Source/Fractorium/FractoriumParams.cpp @@ -183,13 +183,7 @@ void FractoriumEmberController::BackgroundChanged(const QColor& color) QString g = ToString(color.green()); QString b = ToString(color.blue()); - int threshold = 105; - int delta = (color.red() * 0.299) + //Magic numbers gotten from a Stack Overflow post. - (color.green() * 0.587) + - (color.blue() * 0.114); - - QColor textColor = (255 - delta < threshold) ? QColor(0, 0, 0) : QColor(255, 255, 255); - colorTable->item(itemRow, 1)->setTextColor(textColor); + colorTable->item(itemRow, 1)->setTextColor(VisibleColor(color)); colorTable->item(itemRow, 1)->setText("rgb(" + r + ", " + g + ", " + b + ")"); //Color is 0-255, normalize to 0-1. diff --git a/Source/Fractorium/FractoriumToolbar.cpp b/Source/Fractorium/FractoriumToolbar.cpp index ad03925..8c74396 100644 --- a/Source/Fractorium/FractoriumToolbar.cpp +++ b/Source/Fractorium/FractoriumToolbar.cpp @@ -6,16 +6,5 @@ /// void Fractorium::InitToolbarUI() { - //These aren't menus but duplicate menu functionality in a pseudo-toolbar. - connect(ui.SaveCurrentAsXmlButton, SIGNAL(clicked(bool)), this, SLOT(OnSaveCurrentAsXmlButtonClicked(bool)), Qt::QueuedConnection); - connect(ui.SaveEntireFileAsXmlButton, SIGNAL(clicked(bool)), this, SLOT(OnSaveEntireFileAsXmlButtonClicked(bool)), Qt::QueuedConnection); - connect(ui.SaveCurrentToOpenedFileButton, SIGNAL(clicked(bool)), this, SLOT(OnSaveCurrentToOpenedFileButtonClicked(bool)), Qt::QueuedConnection); + //Empty for the moment, all functionality is handled in the designer. } - -/// -/// Wrappers around calls to menu items. -/// - -void Fractorium::OnSaveCurrentAsXmlButtonClicked(bool checked) { OnActionSaveCurrentAsXml(checked); } -void Fractorium::OnSaveEntireFileAsXmlButtonClicked(bool checked) { OnActionSaveEntireFileAsXml(checked); } -void Fractorium::OnSaveCurrentToOpenedFileButtonClicked(bool checked) { OnActionSaveCurrentToOpenedFile(checked); } diff --git a/Source/Fractorium/FractoriumXformsAffine.cpp b/Source/Fractorium/FractoriumXformsAffine.cpp index fcb40e3..4ffe748 100644 --- a/Source/Fractorium/FractoriumXformsAffine.cpp +++ b/Source/Fractorium/FractoriumXformsAffine.cpp @@ -150,8 +150,8 @@ void Fractorium::InitXformsAffineUI() //Further, the size of the dock widget won't be properly adjusted until the xforms tab is shown. //So show it here and it will be switched back in Fractorium's constructor. - //ui.ParamsTabWidget->setCurrentIndex(2); - //ui.DockWidget->update(); + //ui.ParamsTabWidget->setCurrentIndex(2); + //ui.DockWidget->update(); #endif //Placing pointers to the spin boxes in arrays makes them easier to access in various places. diff --git a/Source/Fractorium/FractoriumXformsColor.cpp b/Source/Fractorium/FractoriumXformsColor.cpp index 6c7474a..95efeaa 100644 --- a/Source/Fractorium/FractoriumXformsColor.cpp +++ b/Source/Fractorium/FractoriumXformsColor.cpp @@ -142,7 +142,9 @@ void Fractorium::OnSoloXformCheckBoxStateChanged(int state) /// Ignored void Fractorium::OnXformRefPaletteResized(int logicalIndex, int oldSize, int newSize) { - m_Controller->SetPaletteRefTable(nullptr); + QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage()); + + SetPaletteTableItem(&pixmap, ui.XformPaletteRefTable, m_PaletteRefItem, 0, 0); } /// @@ -194,6 +196,25 @@ void Fractorium::OnCurvesRedRadioButtonToggled(bool checked) { if (checked) ui void Fractorium::OnCurvesGreenRadioButtonToggled(bool checked) { if (checked) ui.CurvesView->SetTop(CurveIndex::GREEN); } void Fractorium::OnCurvesBlueRadioButtonToggled(bool checked) { if (checked) ui.CurvesView->SetTop(CurveIndex::BLUE); } +/// +/// Look up the passed in index in the current ember's palette +/// and return the QColor equivalent. +/// +/// The palette index to look up, 0-1. +/// The palette color at the given index as a QColor +template +QColor FractoriumEmberController::ColorIndexToQColor(double d) +{ + v4T entry = m_Ember.m_Palette[Clamp(d * COLORMAP_LENGTH_MINUS_1, 0, m_Ember.m_Palette.Size())]; + + entry.r *= 255; + entry.g *= 255; + entry.b *= 255; + + QRgb rgb = uint(entry.r) << 16 | uint(entry.g) << 8 | uint(entry.b); + return QColor::fromRgb(rgb); +} + /// /// Set the selected xforms color index to the passed in value. /// Set the color cell in the palette ref table. @@ -207,14 +228,7 @@ void FractoriumEmberController::SetCurrentXformColorIndex(double d, bool upda xform->m_ColorX = Clamp(d, 0, 1); //Grab the current color from the index and assign it to the first cell of the first table. - v4T entry = m_Ember.m_Palette[Clamp(d * COLORMAP_LENGTH_MINUS_1, 0, m_Ember.m_Palette.Size())]; - - entry.r *= 255; - entry.g *= 255; - entry.b *= 255; - - QRgb rgb = uint(entry.r) << 16 | uint(entry.g) << 8 | uint(entry.b); - m_Fractorium->ui.XformColorIndexTable->item(0, 0)->setBackgroundColor(QColor::fromRgb(rgb)); + m_Fractorium->ui.XformColorIndexTable->item(0, 0)->setBackgroundColor(ColorIndexToQColor(xform->m_ColorX)/*QColor::fromRgb(rgb)*/); }, eXformUpdate::UPDATE_SELECTED, updateRender); } @@ -257,22 +271,19 @@ void FractoriumEmberController::FillColorWithXform(Xform* xform) } /// -/// Set the palette reference table to the passed in pixmap +/// Set the cell at the row and column in the passed in table to the passed in pixmap. /// -/// The pixmap -void FractoriumEmberControllerBase::SetPaletteRefTable(QPixmap* pixmap) +/// The pixmap to assign +/// The table whose cell will be filled with the image +/// The QTableWidgetItem in the cell +/// The row of the cell +/// The column of the cell +void Fractorium::SetPaletteTableItem(QPixmap* pixmap, QTableWidget* table, QTableWidgetItem* item, int row, int col) { - QSize size(m_Fractorium->ui.XformPaletteRefTable->columnWidth(0), m_Fractorium->ui.XformPaletteRefTable->rowHeight(0) + 1); - if (pixmap) { - m_Fractorium->m_PaletteRefItem->setData(Qt::DecorationRole, pixmap->scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - } - else if (!m_FinalPaletteImage.isNull()) - { - QPixmap pixTemp = QPixmap::fromImage(m_FinalPaletteImage); - - m_Fractorium->m_PaletteRefItem->setData(Qt::DecorationRole, pixTemp.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QSize size(table->columnWidth(col), table->rowHeight(row) + 1); + item->setData(Qt::DecorationRole, pixmap->scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } } diff --git a/Source/Fractorium/FractoriumXformsVariations.cpp b/Source/Fractorium/FractoriumXformsVariations.cpp index 85b7b09..02843e3 100644 --- a/Source/Fractorium/FractoriumXformsVariations.cpp +++ b/Source/Fractorium/FractoriumXformsVariations.cpp @@ -150,6 +150,7 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d)//Would { if (xformParVar->SetParamVal(sender->ParamName().c_str(), d)) { + FillSummary(); UpdateRender(); } } @@ -203,6 +204,7 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d)//Would } } + FillSummary(); UpdateRender(); } } diff --git a/Source/Fractorium/OptionsDialog.ui b/Source/Fractorium/OptionsDialog.ui index 9c1a92a..a11eae5 100644 --- a/Source/Fractorium/OptionsDialog.ui +++ b/Source/Fractorium/OptionsDialog.ui @@ -7,7 +7,7 @@ 0 0 300 - 347 + 368 @@ -19,13 +19,13 @@ 300 - 347 + 368 300 - 347 + 368