diff --git a/Source/Ember/Palette.h b/Source/Ember/Palette.h index eadffa6..2b88792 100644 --- a/Source/Ember/Palette.h +++ b/Source/Ember/Palette.h @@ -305,12 +305,14 @@ public: palette = *this; } + auto tempPal = palette; + for (size_t i = 0; i < Size(); i++) { - size_t ii = (i * 256) / COLORMAP_LENGTH; - rgb[0] = palette[(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].r;//Rotation. - rgb[1] = palette[(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].g; - rgb[2] = palette[(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].b; + int ii = int(i); + rgb[0] = tempPal[std::abs(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].r;//Rotation. + rgb[1] = tempPal[std::abs(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].g; + rgb[2] = tempPal[std::abs(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].b; RgbToHsv(rgb, hsv); hsv[0] += hue * T(6.0);//Hue. hsv[1] = Clamp(hsv[1] + sat, 0, 1);//Saturation. @@ -331,7 +333,7 @@ public: if (blur > 0) { - Palette blurPal = palette; + tempPal = palette; for (int i = 0; i < 256; i++) { @@ -347,9 +349,9 @@ public: if (k != i) { - rgb[0] = rgb[0] + blurPal[k].r; - rgb[1] = rgb[1] + blurPal[k].g; - rgb[2] = rgb[2] + blurPal[k].b; + rgb[0] = rgb[0] + tempPal[k].r; + rgb[1] = rgb[1] + tempPal[k].g; + rgb[2] = rgb[2] + tempPal[k].b; } } diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index 47af362..d83cca6 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -325,6 +325,10 @@ public slots: void OnPaletteAdjust(int d); void OnPaletteCellClicked(int row, int col); void OnPaletteCellDoubleClicked(int row, int col); + void OnPreviewPaletteMouseDragged(const QPointF& local, const QPoint& global); + void OnPreviewPaletteMouseReleased(); + void OnPreviewPaletteCellDoubleClicked(int row, int col); + void OnPreviewPaletteCellPressed(int row, int col); void OnPaletteRandomSelectButtonClicked(bool checked); void OnPaletteRandomAdjustButtonClicked(bool checked); void OnPaletteEditorButtonClicked(bool checked); @@ -513,8 +517,12 @@ private: DoubleSpinBoxTableItemDelegate* m_XaosTableItemDelegate; //Palette. - bool m_PaletteChanged; - bool m_PaletteFileChanged; + bool m_PaletteChanged = false; + bool m_PaletteFileChanged = false; + bool m_PreviewPaletteMouseDown = false; + int m_PreviewPaletteMouseDownRotation = 0; + int m_PreviewPaletteRotation = 0; + QPoint m_PreviewPaletteMouseDownPosition = QPoint(0, 0); SpinBox* m_PaletteHueSpin; SpinBox* m_PaletteSaturationSpin; SpinBox* m_PaletteBrightnessSpin; diff --git a/Source/Fractorium/FractoriumPalette.cpp b/Source/Fractorium/FractoriumPalette.cpp index ac5b120..fefd61d 100644 --- a/Source/Fractorium/FractoriumPalette.cpp +++ b/Source/Fractorium/FractoriumPalette.cpp @@ -13,6 +13,10 @@ void Fractorium::InitPaletteUI() connect(ui.PaletteFilenameCombo, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnPaletteFilenameComboChanged(const QString&)), Qt::QueuedConnection); connect(paletteTable, SIGNAL(cellClicked(int, int)), this, SLOT(OnPaletteCellClicked(int, int)), Qt::QueuedConnection); connect(paletteTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(OnPaletteCellDoubleClicked(int, int)), Qt::QueuedConnection); + connect(palettePreviewTable, SIGNAL(MouseDragged(const QPointF&, const QPoint&)), this, SLOT(OnPreviewPaletteMouseDragged(const QPointF&, const QPoint&)), Qt::QueuedConnection); + connect(palettePreviewTable, SIGNAL(MouseReleased()), this, SLOT(OnPreviewPaletteMouseReleased()), Qt::QueuedConnection); + connect(palettePreviewTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(OnPreviewPaletteCellDoubleClicked(int, int)), Qt::QueuedConnection); + connect(palettePreviewTable, SIGNAL(cellPressed(int, int)), this, SLOT(OnPreviewPaletteCellPressed(int, int)), Qt::QueuedConnection); //Palette adjustment table. auto table = ui.PaletteAdjustTable; table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//Split width over all columns evenly. @@ -34,6 +38,7 @@ void Fractorium::InitPaletteUI() palettePreviewTable->setItem(0, 0, previewNameCol); auto previewPaletteItem = new QTableWidgetItem(); palettePreviewTable->setItem(0, 1, previewPaletteItem); + palettePreviewTable->installEventFilter(this); connect(ui.PaletteFilterLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnPaletteFilterLineEditTextChanged(const QString&))); connect(ui.PaletteFilterClearButton, SIGNAL(clicked(bool)), this, SLOT(OnPaletteFilterClearButtonClicked(bool))); paletteTable->setColumnWidth(1, 260);//256 plus small margin on each side. @@ -140,7 +145,7 @@ void FractoriumEmberController::ApplyPaletteToEmber() double contrast = double(m_Fractorium->m_PaletteContrastSpin->value() > 0 ? (m_Fractorium->m_PaletteContrastSpin->value() * 2) : m_Fractorium->m_PaletteContrastSpin->value()) / 100.0; double hue = double(m_Fractorium->m_PaletteHueSpin->value()) / 360.0; //Use the temp palette as the base and apply the adjustments gotten from the GUI and save the result in the ember palette. - m_TempPalette.MakeAdjustedPalette(m_Ember.m_Palette, 0, hue, sat, brightness, contrast, blur, freq); + m_TempPalette.MakeAdjustedPalette(m_Ember.m_Palette, m_Fractorium->m_PreviewPaletteRotation, hue, sat, brightness, contrast, blur, freq); } /// @@ -249,6 +254,61 @@ void Fractorium::OnPaletteCellClicked(int row, int col) } } +/// +/// Called when the mouse has been moved while pressed on the palette preview table. +/// Computes the difference between where the mouse was clicked and where it is now, then +/// uses that difference as a rotation value to pass into the palette adjustment. +/// Updates the palette and resets the rendering process. +/// +/// The local mouse coordinates relative to the palette preview table +/// The global mouse coordinates +void Fractorium::OnPreviewPaletteMouseDragged(const QPointF& local, const QPoint& global) +{ + if (m_PreviewPaletteMouseDown) + { + m_PreviewPaletteRotation = m_PreviewPaletteMouseDownRotation + (global.x() - m_PreviewPaletteMouseDownPosition.x()); + //qDebug() << "Palette preview table drag reached main window event: " << local.x() << ' ' << local.y() << ", global: " << global.x() << ' ' << global.y() << ", final: " << m_PreviewPaletteRotation; + m_Controller->PaletteAdjust(); + } +} + +/// +/// Called when the mouse has been released over the palette preview table. +/// Does nothing but set the dragging state to false. +/// +void Fractorium::OnPreviewPaletteMouseReleased() +{ + m_PreviewPaletteMouseDown = false; +} + +/// +/// Sets the palette rotation to zero. +/// Updates the palette and resets the rendering process. +/// +/// Ignored +/// Ignored +void Fractorium::OnPreviewPaletteCellDoubleClicked(int row, int col) +{ + m_PreviewPaletteRotation = 0; + m_PreviewPaletteMouseDown = false; + m_Controller->PaletteAdjust(); +} + +/// +/// Called when the mouse has been pressed on the palette preview table. +/// Subsequent mouse movements will compute a rotation value to pass into the palette adjustment, based on the location +/// of the mouse when this slot is called. +/// +/// Ignored +/// Ignored +void Fractorium::OnPreviewPaletteCellPressed(int row, int col) +{ + m_PreviewPaletteMouseDown = true; + m_PreviewPaletteMouseDownPosition = QCursor::pos();//Get the global mouse position. + m_PreviewPaletteMouseDownRotation = m_PreviewPaletteRotation; + //qDebug() << "Mouse down with initial pos: " << m_PreviewPaletteMouseDownPosition.x() << " and initial rotation: " << m_PreviewPaletteMouseDownRotation; +} + /// /// Set the selected palette as the current one, /// resetting any adjustments previously specified. diff --git a/Source/Fractorium/GLWidget.cpp b/Source/Fractorium/GLWidget.cpp index e90c426..c6c1498 100644 --- a/Source/Fractorium/GLWidget.cpp +++ b/Source/Fractorium/GLWidget.cpp @@ -520,7 +520,7 @@ void GLEmberController::DrawAffines(bool pre, bool post) #else GLfloat vertices[] =//Should these be of type T?//TODO { - m_DragHandlePos.x, m_DragHandlePos.y + GLfloat(m_DragHandlePos.x), GLfloat(m_DragHandlePos.y) }; QVector4D col(1.0f, 1.0f, 0.5f, 1.0f); m_GL->DrawPointOrLine(col, vertices, 1, GL_POINTS); @@ -545,14 +545,14 @@ void GLEmberController::DrawAffines(bool pre, bool post) #else GLfloat vertices[] =//Should these be of type T?//TODO { - m_MouseDownWorldPos.x, m_MouseDownWorldPos.y,//UL->UR - m_MouseWorldPos.x, m_MouseDownWorldPos.y, - m_MouseDownWorldPos.x, m_MouseWorldPos.y,//LL->LR - m_MouseWorldPos.x, m_MouseWorldPos.y, - m_MouseDownWorldPos.x, m_MouseDownWorldPos.y,//UL->LL - m_MouseDownWorldPos.x, m_MouseWorldPos.y, - m_MouseWorldPos.x, m_MouseDownWorldPos.y,//UR->LR - m_MouseWorldPos.x, m_MouseWorldPos.y + GLfloat(m_MouseDownWorldPos.x), GLfloat(m_MouseDownWorldPos.y),//UL->UR + GLfloat(m_MouseWorldPos.x ), GLfloat(m_MouseDownWorldPos.y), + GLfloat(m_MouseDownWorldPos.x), GLfloat(m_MouseWorldPos.y),//LL->LR + GLfloat(m_MouseWorldPos.x ), GLfloat(m_MouseWorldPos.y), + GLfloat(m_MouseDownWorldPos.x), GLfloat(m_MouseDownWorldPos.y),//UL->LL + GLfloat(m_MouseDownWorldPos.x), GLfloat(m_MouseWorldPos.y), + GLfloat(m_MouseWorldPos.x ), GLfloat(m_MouseDownWorldPos.y),//UR->LR + GLfloat(m_MouseWorldPos.x ), GLfloat(m_MouseWorldPos.y) }; QVector4D col(0.0f, 0.0f, 1.0f, 1.0f); m_GL->DrawPointOrLine(col, vertices, 8, GL_LINES); @@ -570,7 +570,7 @@ void GLEmberController::DrawAffines(bool pre, bool post) #else GLfloat vertices[] =//Should these be of type T?//TODO { - m_HoverHandlePos.x, m_HoverHandlePos.y + GLfloat(m_HoverHandlePos.x), GLfloat(m_HoverHandlePos.y) }; QVector4D col(0.5f, 1.0f, 1.0f, 1.0f); m_GL->DrawPointOrLine(col, vertices, 1, GL_POINTS); @@ -931,7 +931,7 @@ void GLWidget::wheelEvent(QWheelEvent* e) /// The type of primitive to draw, such as GL_POINT or GL_LINES void GLWidget::DrawPointOrLine(const QVector4D& col, const std::vector& vertices, int drawType) { - DrawPointOrLine(col, vertices.data(), vertices.size() / 2, drawType); + DrawPointOrLine(col, vertices.data(), int(vertices.size() / 2), drawType); } /// diff --git a/Source/Fractorium/TableWidget.h b/Source/Fractorium/TableWidget.h index 13bb131..d1d165f 100644 --- a/Source/Fractorium/TableWidget.h +++ b/Source/Fractorium/TableWidget.h @@ -37,9 +37,16 @@ public: viewport()->installEventFilter(this); } + +signals: + void MouseDragged(const QPointF& local, const QPoint& global); + void MouseReleased(); + protected: + /// - /// Event filter to ignore mouse wheel events. + /// Event filter to ignore mouse wheel events and also handle others such as mouse move and mouse button release. + /// Sadly, QTableWidget makes these hard to get to, so we must handle them here. /// /// The object sending the event /// The event @@ -51,6 +58,17 @@ protected: e->ignore(); return true; } + else if (e->type() == QEvent::MouseMove) + { + if (auto me = dynamic_cast(e)) + { + emit MouseDragged(me->localPos(), me->globalPos()); + } + } + else if (e->type() == QEvent::MouseButtonRelease) + { + emit MouseReleased(); + } return QTableWidget::eventFilter(obj, e); }