From dee4304bf2a43aae14bdc9c704498508bcc39209 Mon Sep 17 00:00:00 2001 From: Person Date: Fri, 10 Aug 2018 18:06:04 -0700 Subject: [PATCH] --User changes -Attempt to preserve xaos when adding xforms. Note this is not an exact copy, but just a preservation of some values based on position. -Add some acceleration to the changing of spinner values when dragging the right mouse button to adjust. -Make the pivot be the center of the viewable area when doing drag/rotate/scale with the right mouse button. --Clamp minimum scale to 10 --Draw a line from the mouse position to the pivot. -Keep a cache of the last added final xform with each flame so that it can be quickly added, removed, then added back for testing its effect. --This is not saved with the xml file and is solely for interactive editing. --Bug fixes -File filtering in open and save dialogs were broken. -Right clicking on integer spin boxes was causing the context menu to pop up, when it should be supressed just like double spin boxes. -Deleting xforms was still broken. --Code changes -Refactor the code for adding and pasting xforms into a single global static function called AddXformsWithXaos(). --- Source/Ember/Ember.h | 11 +++-- Source/EmberCommon/EmberCommon.h | 37 +++++++++++++++++ Source/Fractorium/DoubleSpinBox.cpp | 1 + Source/Fractorium/Fractorium.cpp | 6 +-- Source/Fractorium/Fractorium.ui | 10 ++--- Source/Fractorium/FractoriumMenus.cpp | 3 +- Source/Fractorium/FractoriumXaos.cpp | 41 ++++++++----------- Source/Fractorium/FractoriumXforms.cpp | 53 ++++++++++++++++--------- Source/Fractorium/GLEmberController.cpp | 38 ++++++++++++++++-- Source/Fractorium/GLEmberController.h | 2 + Source/Fractorium/GLWidget.cpp | 29 +++++++++++++- Source/Fractorium/GLWidget.h | 2 + Source/Fractorium/SpinBox.cpp | 2 + 13 files changed, 173 insertions(+), 62 deletions(-) diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h index 108e917..68690f6 100644 --- a/Source/Ember/Ember.h +++ b/Source/Ember/Ember.h @@ -179,6 +179,7 @@ public: CopyCont(m_EmberMotionElements, ember.m_EmberMotionElements); m_Solo = ember.m_Solo; + m_CachedFinal = ember.m_CachedFinal; return *this; } @@ -1724,9 +1725,6 @@ public: //The list of motion elements for the top-level flame params vector> m_EmberMotionElements; - //Index of xform to have non-zero opacity, while all others have zero. This is an interactive rendering parameter and is not saved to Xml. -1 means solo is not used. - intmax_t m_Solo = -1; - private: /// /// The type of scaling used when resizing. @@ -1810,6 +1808,13 @@ private: for (size_t k = 0; k < size; k++) xform->*m += coefs[k] * embers[k].GetTotalXform(i)->*m; } + +public: + //Index of xform to have non-zero opacity, while all others have zero. This is an interactive rendering parameter and is not saved to Xml. -1 means solo is not used. + intmax_t m_Solo = -1; + + //Cached copy of the final xform which makes it easy to add and remove the final repeatedly during editing without losing information. Used only with interactive rendering. + Xform m_CachedFinal; }; /// diff --git a/Source/EmberCommon/EmberCommon.h b/Source/EmberCommon/EmberCommon.h index b3f8064..1005207 100644 --- a/Source/EmberCommon/EmberCommon.h +++ b/Source/EmberCommon/EmberCommon.h @@ -793,6 +793,43 @@ static vector*> FindVarsWithout(const vector +/// Add a vector of xforms to the passed in ember, and optionally preserve the xaos based on position. +/// +/// The ember to add xforms to +/// The vector of xforms to add +/// True to preserve xaos else false. +template +static void AddXformsWithXaos(Ember& ember, std::vector>& xforms, bool preserveXaos) +{ + auto origXformCount = ember.XformCount(); + + for (auto& it : xforms) + ember.AddXform(it); + + for (auto i = 0; i < ember.XformCount(); i++) + { + auto xf = ember.GetXform(i); + + if (i < origXformCount) + { + for (auto j = 0; j < ember.XformCount(); j++) + if (j >= origXformCount) + xf->SetXaos(j, 0); + } + else + { + for (auto j = 0; j < ember.XformCount(); j++) + if (j < origXformCount) + xf->SetXaos(j, 0); + else if (!preserveXaos) + xf->SetXaos(j, 1); + else if (i - origXformCount < xforms.size())//Should never be out of bounds, but just to be safe. + xf->SetXaos(j, xforms[i - origXformCount].Xaos(j - origXformCount)); + } + } +} } /// diff --git a/Source/Fractorium/DoubleSpinBox.cpp b/Source/Fractorium/DoubleSpinBox.cpp index c573af0..b867003 100644 --- a/Source/Fractorium/DoubleSpinBox.cpp +++ b/Source/Fractorium/DoubleSpinBox.cpp @@ -146,6 +146,7 @@ void DoubleSpinBox::OnTimeout() int xdistance = m_MouseMovePoint.x() - m_MouseDownPoint.x(); int ydistance = m_MouseMovePoint.y() - m_MouseDownPoint.y(); int distance = abs(xdistance) > abs(ydistance) ? xdistance : ydistance; + distance = Sqr(distance) * (distance < 0 ? -1 : 1); double scale, val; double d = value(); bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index e1b7086..6a967d7 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -601,7 +601,7 @@ QStringList Fractorium::SetupOpenXmlDialog() 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;;*.flame;;*.xml"); + m_FileDialog->setNameFilter("Flam3 (*.flam3);;Flame (*.flame);;Xml (*.xml)"); m_FileDialog->setWindowTitle("Open Flame"); m_FileDialog->setDirectory(m_Settings->OpenFolder()); m_FileDialog->selectNameFilter(m_Settings->OpenXmlExt()); @@ -616,7 +616,7 @@ QStringList Fractorium::SetupOpenXmlDialog() #else auto defaultFilter(m_Settings->OpenXmlExt()); - auto filenames = QFileDialog::getOpenFileNames(this, tr("Open Flame"), m_Settings->OpenFolder(), tr("Flame Files (*.flam3 *.flame *.xml)"), &defaultFilter); + auto filenames = QFileDialog::getOpenFileNames(this, tr("Open Flame"), m_Settings->OpenFolder(), tr("Flam3(*.flam3);; Flame(*.flame);; Xml(*.xml)"), &defaultFilter); m_Settings->OpenXmlExt(defaultFilter); if (!filenames.empty()) @@ -655,7 +655,7 @@ QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename) //This is most likely a bug in QFileDialog. m_FileDialog->setAcceptMode(QFileDialog::AcceptSave); m_FileDialog->selectFile(defaultFilename); - m_FileDialog->setNameFilter(".flam3;;.flame;;.xml"); + m_FileDialog->setNameFilter("Flam3 (*.flam3);;Flame (*.flame);;Xml (*.xml)"); m_FileDialog->setWindowTitle("Save flame as xml"); m_FileDialog->setDirectory(m_Settings->SaveFolder()); m_FileDialog->selectNameFilter(m_Settings->SaveXmlExt()); diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index edc14e8..19b738b 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -1922,10 +1922,13 @@ - + Qt::StrongFocus + + QAbstractSpinBox::NoButtons + Xforms @@ -8374,11 +8377,6 @@ QTreeWidget
LibraryTreeWidget.h
- - SpinBox - QSpinBox -
spinbox.h
-
LibraryDockWidget diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index 37a6e45..5b77550 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -699,8 +699,7 @@ void FractoriumEmberController::PasteSelectedXforms() { Update([&]() { - for (auto& it : m_CopiedXforms) - m_Ember.AddXform(it); + AddXformsWithXaos(m_Ember, m_CopiedXforms, true); if (!m_CopiedFinalXform.Empty()) m_Ember.SetFinalXform(m_CopiedFinalXform); diff --git a/Source/Fractorium/FractoriumXaos.cpp b/Source/Fractorium/FractoriumXaos.cpp index 56f679d..2b1967e 100644 --- a/Source/Fractorium/FractoriumXaos.cpp +++ b/Source/Fractorium/FractoriumXaos.cpp @@ -180,28 +180,9 @@ void FractoriumEmberController::AddLayer(int xforms) { Update([&] { - auto origXformCount = m_Ember.XformCount(); - m_Ember.AddXforms(xforms); + std::vector> vec(xforms); + AddXformsWithXaos(m_Ember, vec, false); - for (auto i = 0; i < m_Ember.XformCount(); i++) - { - auto xf = m_Ember.GetXform(i); - - if (i < origXformCount) - { - for (auto j = 0; j < m_Ember.XformCount(); j++) - if (j >= origXformCount) - xf->SetXaos(j, 0); - } - else - { - for (auto j = 0; j < m_Ember.XformCount(); j++) - if (j < origXformCount) - xf->SetXaos(j, 0); - else - xf->SetXaos(j, 1); - } - } }); FillXforms(); FillSummary(); @@ -210,25 +191,35 @@ void FractoriumEmberController::AddLayer(int xforms) void Fractorium::OnAddLayerButtonClicked(bool checked) { m_Controller->AddLayer(ui.AddLayerSpinBox->value()); } /// -/// Toggle all xaos values in one row. +/// Toggle all xaos values in one row on left mouse button double click and resize all cells to fit their data. +/// Skip toggling and only refit on right mouse button double click. /// Resets the rendering process. /// /// The index of the row that was double clicked void Fractorium::OnXaosRowDoubleClicked(int logicalIndex) { - ToggleTableRow(ui.XaosTableView, logicalIndex); + auto btn = QApplication::mouseButtons(); + + if (!btn.testFlag(Qt::RightButton)) + ToggleTableRow(ui.XaosTableView, logicalIndex); + ui.XaosTableView->resizeRowsToContents(); ui.XaosTableView->resizeColumnsToContents(); } /// -/// Toggle all xaos values in one column. +/// Toggle all xaos values in one column on left mouse button double click and resize all cells to fit their data. +/// Skip toggling and only refit on right mouse button double click. /// Resets the rendering process. /// /// The index of the column that was double clicked void Fractorium::OnXaosColDoubleClicked(int logicalIndex) { - ToggleTableCol(ui.XaosTableView, logicalIndex); + auto btn = QApplication::mouseButtons(); + + if (!btn.testFlag(Qt::RightButton)) + ToggleTableCol(ui.XaosTableView, logicalIndex); + ui.XaosTableView->resizeRowsToContents(); ui.XaosTableView->resizeColumnsToContents(); } diff --git a/Source/Fractorium/FractoriumXforms.cpp b/Source/Fractorium/FractoriumXforms.cpp index bcd9303..8913a9a 100644 --- a/Source/Fractorium/FractoriumXforms.cpp +++ b/Source/Fractorium/FractoriumXforms.cpp @@ -224,9 +224,7 @@ void FractoriumEmberController::DuplicateXform() }, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL, false); Update([&]() { - for (auto& it : vec) - m_Ember.AddXform(it); - + AddXformsWithXaos(m_Ember, vec, true); int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final. FillXforms(index);//Handles xaos. }); @@ -254,6 +252,7 @@ void Fractorium::OnClearXformButtonClicked(bool checked) { m_Controller->ClearXf /// /// Delete the selected xforms. +/// Cache a copy of the final xform if it's been selected for removal. /// Will not delete the last remaining non-final xform. /// Called when the delete xform button is clicked. /// Resets the rendering process. @@ -263,11 +262,12 @@ template void FractoriumEmberController::DeleteXforms() { bool removed = false; + bool anyChecked = false; bool haveFinal = m_Fractorium->HaveFinal(); auto combo = m_Fractorium->ui.CurrentXformCombo; Xform* finalXform = nullptr; - vector> xforms; - xforms.reserve(m_Ember.TotalXformCount()); + vector> xformsToKeep; + xformsToKeep.reserve(m_Ember.TotalXformCount()); //Iterating over the checkboxes must be done instead of using UpdateXform() to iterate over xforms //because xforms are being deleted inside the loop. //Also manually calling UpdateRender() rather than using the usual Update() call because @@ -280,37 +280,49 @@ void FractoriumEmberController::DeleteXforms() if (isFinal) finalXform = m_Ember.NonConstFinalXform(); else if (auto xform = m_Ember.GetXform(i)) - xforms.push_back(*xform); + xformsToKeep.push_back(*xform); } + else + anyChecked = true;//At least one was selected for removal. }); //They might not have selected any checkboxes, in which case just delete the current. auto current = combo->currentIndex(); - auto count = m_Ember.TotalXformCount(); - bool anySelected = xforms.size() < m_Ember.XformCount(); - bool finalSelected = !finalXform && haveFinal; + auto totalCount = m_Ember.TotalXformCount(); + bool keepFinal = finalXform && haveFinal; //Nothing was selected, so just delete current. - if (!anySelected && !finalSelected) + if (!anyChecked) { //Disallow deleting the only remaining non-final xform. - if (!(haveFinal && count <= 2 && current == 0) &&//One non-final, one final, disallow deleting non-final. - !(!haveFinal && count == 1))//One non-final, no final, disallow deleting. + if (!(haveFinal && totalCount <= 2 && current == 0) &&//One non-final, one final, disallow deleting non-final. + !(!haveFinal && totalCount == 1))//One non-final, no final, disallow deleting. { - m_Ember.DeleteTotalXform(current, haveFinal); + if (haveFinal && m_Ember.IsFinalXform(CurrentXform()))//Is final the current? + m_Ember.m_CachedFinal = *m_Ember.FinalXform();//Keep a copy in case the user wants to re-add the final. + + m_Ember.DeleteTotalXform(current, haveFinal);//Will cover the case of current either being final or non-final. removed = true; } } else { - if (!xforms.empty() && (xforms.size() != m_Ember.XformCount()))//Remove if they requested to do so, but ensure it's not removing all. + if (!xformsToKeep.empty())//Remove if they requested to do so, but ensure it's not removing all. { removed = true; - m_Ember.ReplaceXforms(xforms); + m_Ember.ReplaceXforms(xformsToKeep);//Replace with only those they chose to keep (the inverse of what was checked). + } + else//They selected all to delete, which is not allowed, so just keep the first xform. + { + removed = true; + + while (m_Ember.XformCount() > 1) + m_Ember.DeleteXform(m_Ember.XformCount() - 1); } - if (finalSelected) + if (!keepFinal)//They selected final to delete. { removed = true; + m_Ember.m_CachedFinal = *m_Ember.FinalXform();//Keep a copy in case the user wants to re-add the final. m_Ember.NonConstFinalXform()->Clear(); } } @@ -320,6 +332,7 @@ void FractoriumEmberController::DeleteXforms() int index = int(m_Ember.TotalXformCount() - (m_Ember.UseFinalXform() ? 2 : 1));//Set index to the last item before final. Note final is requeried one last time. FillXforms(index); UpdateRender(); + m_Fractorium->ui.GLDisplay->repaint();//Force update because for some reason it doesn't always happen. } } @@ -327,6 +340,7 @@ void Fractorium::OnDeleteXformButtonClicked(bool checked) { m_Controller->Delete /// /// Add a final xform to the ember and set it as the current xform. /// Will only take action if a final xform is not already present. +/// Will re-add a copy of the last used final xform for the current ember if one had already been added then removed. /// Called when the add final xform button is clicked. /// Resets the rendering process. /// @@ -339,9 +353,12 @@ void FractoriumEmberController::AddFinalXform() { Update([&]() { - Xform final; + auto& final = m_Ember.m_CachedFinal; final.m_Animate = 0; - final.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));//Just a placeholder so other parts of the code don't see it as being empty. + + if (final.Empty()) + final.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));//Just a placeholder so other parts of the code don't see it as being empty. + m_Ember.SetFinalXform(final); int index = int(m_Ember.TotalXformCount() - 1);//Set index to the last item. FillXforms(index); diff --git a/Source/Fractorium/GLEmberController.cpp b/Source/Fractorium/GLEmberController.cpp index ae81e89..b44036c 100644 --- a/Source/Fractorium/GLEmberController.cpp +++ b/Source/Fractorium/GLEmberController.cpp @@ -82,7 +82,7 @@ T GLEmberController::CalcScale() { //Can't operate using world coords here because every time scale changes, the world bounds change. //So must instead calculate distance traveled based on window coords, which do not change outside of resize events. - v2T windowCenter(T(m_GL->width()) / T(2), T(m_GL->height()) / T(2)); + auto windowCenter = ScrolledCenter(false); v2T windowMousePosDistanceFromCenter(m_MousePos.x - windowCenter.x, m_MousePos.y - windowCenter.y); v2T windowMouseDownDistanceFromCenter(m_MouseDownPos.x - windowCenter.x, m_MouseDownPos.y - windowCenter.y); T lengthMousePosFromCenterInPixels = glm::length(windowMousePosDistanceFromCenter); @@ -98,11 +98,43 @@ T GLEmberController::CalcScale() template T GLEmberController::CalcRotation() { - T rotStart = NormalizeDeg180(T(90) - (atan2(-m_MouseDownWorldPos.y, m_MouseDownWorldPos.x) * RAD_2_DEG_T)); - T rot = NormalizeDeg180(T(90) - (atan2(-m_MouseWorldPos.y, m_MouseWorldPos.x) * RAD_2_DEG_T)); + auto scrolledWorldCenter = ScrolledCenter(true); + T rotStart = NormalizeDeg180((std::atan2(m_MouseDownWorldPos.y - scrolledWorldCenter.y, m_MouseDownWorldPos.x - scrolledWorldCenter.x) * RAD_2_DEG_T)); + T rot = NormalizeDeg180((std::atan2(m_MouseWorldPos.y - scrolledWorldCenter.y, m_MouseWorldPos.x - scrolledWorldCenter.x) * RAD_2_DEG_T)); return rotStart - rot; } +/// +/// Return the window coordinates of the center of the viewable area. +/// This is the middle of the parent scroll area plus the scroll bar offset, all scaled by the device pixel ratio. +/// +/// True to return world coordinates, else return window coordinates. +/// The coordinates of the center of the viewable area in either window space or world space. +template +v3T GLEmberController::ScrolledCenter(bool toWorld) +{ + auto dprf = m_GL->devicePixelRatioF(); + auto wpsa = m_Fractorium->ui.GLParentScrollArea->width(); + auto hpsa = m_Fractorium->ui.GLParentScrollArea->height(); + auto hpos = m_Fractorium->ui.GLParentScrollArea->horizontalScrollBar()->value(); + auto vpos = m_Fractorium->ui.GLParentScrollArea->verticalScrollBar()->value(); + v3T v; + + if (!m_Fractorium->ui.GLParentScrollArea->horizontalScrollBar()->isVisible() && !m_Fractorium->ui.GLParentScrollArea->verticalScrollBar()->isVisible()) + v = v3T(((m_GL->width() / 2)) * dprf, + ((m_GL->height() / 2)) * dprf, + 0); + else + v = v3T((hpos + (wpsa / 2)) * dprf, + (vpos + (hpsa / 2)) * dprf, + 0); + + if (toWorld) + return WindowToWorld(v, true); + + return v; +} + /// /// Snap the passed in world cartesian coordinate to the grid for rotation, scale or translation. /// diff --git a/Source/Fractorium/GLEmberController.h b/Source/Fractorium/GLEmberController.h index 89f6a87..8588c75 100644 --- a/Source/Fractorium/GLEmberController.h +++ b/Source/Fractorium/GLEmberController.h @@ -61,6 +61,7 @@ public: void ClearAlt(); void ClearShift(); void ClearControl(); + eDragState DragState() { return m_DragState; } virtual void DrawImage() { } virtual void DrawAffines(bool pre, bool post) { } virtual void ClearWindow() { } @@ -111,6 +112,7 @@ public: T CalcScale(); T CalcRotation(); + v3T ScrolledCenter(bool toWorld = false); void CalcDragXAxis(); void CalcDragYAxis(); void CalcDragTranslation(); diff --git a/Source/Fractorium/GLWidget.cpp b/Source/Fractorium/GLWidget.cpp index 0a0b663..0dc7bf2 100644 --- a/Source/Fractorium/GLWidget.cpp +++ b/Source/Fractorium/GLWidget.cpp @@ -416,6 +416,8 @@ bool GLWidget::Init() { return m_Init; } bool GLWidget::Drawing() { return m_Drawing; } GLint GLWidget::MaxTexSize() { return m_MaxTexSize; } GLuint GLWidget::OutputTexID() { return m_OutputTexID; } +GLint GLWidget::TexWidth() { return m_TexWidth; } +GLint GLWidget::TexHeight() { return m_TexHeight; } /// /// Initialize OpenGL, called once at startup after the main window constructor finishes. @@ -622,13 +624,28 @@ void GLEmberController::DrawAffines(bool pre, bool post) { QueryVMP();//Resolves to float or double specialization function depending on T. - if (!m_Fractorium->DrawXforms() || (m_DragState == eDragState::DragRotateScale)) + if (!m_Fractorium->DrawXforms()) return; auto ember = m_FractoriumEmberController->CurrentEmber(); bool dragging = m_DragState == eDragState::DragDragging; bool forceFinal = m_Fractorium->HaveFinal(); + if (m_DragState == eDragState::DragRotateScale) + { + auto dprf = m_GL->devicePixelRatioF(); + auto world = ScrolledCenter(true); + + m_GL->glLineWidth(1.0f * dprf); + GLfloat vertices[] = + { + GLfloat(m_MouseWorldPos.x), GLfloat(m_MouseWorldPos.y),//Mouse position while dragging with right button down... + GLfloat(world.x), GLfloat(world.y)//...to center. + }; + QVector4D col(0.0f, 1.0f, 1.0f, 1.0f); + m_GL->DrawPointOrLine(col, vertices, 2, GL_LINES); + } + //Draw grid if control key is pressed. if ((m_GL->hasFocus() && GetControl()) || m_Fractorium->DrawGrid()) DrawGrid(); @@ -1003,7 +1020,7 @@ void GLEmberController::MouseMove(QMouseEvent* e) T scale = CalcScale(); ember->m_Rotate = NormalizeDeg180(m_RotationDown + rot); m_Fractorium->SetRotation(ember->m_Rotate, true); - m_Fractorium->SetScale(m_ScaleDown + scale);//Will restart the rendering process. + m_Fractorium->SetScale(std::max(T(10), m_ScaleDown + scale));//Will restart the rendering process. } else { @@ -1532,6 +1549,14 @@ void GLEmberController::DrawAffine(Xform* xform, bool pre, bool selected) m_Verts.push_back(1.0f); col = QVector4D(color.r, color.g, color.b, 1.0f); m_GL->DrawPointOrLine(col, m_Verts, GL_LINES, !pre); + //Line from x to y in the color of the xform combo, solid with no background to somewhat distinguish it. + m_Verts.clear(); + m_Verts.push_back(0); + m_Verts.push_back(1); + m_Verts.push_back(1); + m_Verts.push_back(0); + auto qcol = final ? m_Fractorium->m_FinalXformComboColor : m_Fractorium->m_XformComboColors[index % XFORM_COLOR_COUNT]; + m_GL->DrawPointOrLine(QVector4D(qcol.redF(), qcol.greenF(), qcol.blueF(), 1.0f), m_Verts, GL_LINES, !pre); // m_Verts.clear(); m_Verts.push_back(0.0f); diff --git a/Source/Fractorium/GLWidget.h b/Source/Fractorium/GLWidget.h index b9157c9..cfcc0a7 100644 --- a/Source/Fractorium/GLWidget.h +++ b/Source/Fractorium/GLWidget.h @@ -55,6 +55,8 @@ public: bool Drawing(); GLint MaxTexSize(); GLuint OutputTexID(); + GLint TexWidth(); + GLint TexHeight(); protected: virtual void initializeGL() override; diff --git a/Source/Fractorium/SpinBox.cpp b/Source/Fractorium/SpinBox.cpp index 9f1eff2..78d22d1 100644 --- a/Source/Fractorium/SpinBox.cpp +++ b/Source/Fractorium/SpinBox.cpp @@ -29,6 +29,7 @@ SpinBox::SpinBox(QWidget* p, int h, int step) setFocusPolicy(Qt::StrongFocus); setMinimumHeight(h);//setGeometry() has no effect, so set both of these instead. setMaximumHeight(h); + setContextMenuPolicy(Qt::PreventContextMenu); lineEdit()->installEventFilter(this); lineEdit()->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); connect(this, SIGNAL(valueChanged(int)), this, SLOT(onSpinBoxValueChanged(int)), Qt::QueuedConnection); @@ -136,6 +137,7 @@ void SpinBox::OnTimeout() int xdistance = m_MouseMovePoint.x() - m_MouseDownPoint.x(); int ydistance = m_MouseMovePoint.y() - m_MouseDownPoint.y(); int distance = abs(xdistance) > abs(ydistance) ? xdistance : ydistance; + distance = Sqr(distance) * (distance < 0 ? -1 : 1); double scale, val; int d = value(); bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);