From 44d0900125ef1a53b76d51439da34f2b5da9caa3 Mon Sep 17 00:00:00 2001 From: parax0 Date: Sun, 16 Aug 2015 00:29:37 -0400 Subject: [PATCH] Beginning impementation of CGizmo; loading assets + rendering are implemented as well as toggling modes and scaling it on the UI (plus minor renderer bug fixes) --- Common/CVector3f.cpp | 6 + Common/CVector3f.h | 6 + Core/CRenderer.cpp | 7 +- Core/IRenderable.h | 4 +- EditorAssets/SelectMode.png | Bin 0 -> 3486 bytes Icons.qrc | 1 + UI/CGizmo.cpp | 221 ++++++++++++++++++++++++++++++++++++ UI/CGizmo.h | 113 ++++++++++++++++++ UI/CWorldEditor.cpp | 70 ++++++++++++ UI/CWorldEditor.h | 9 ++ UI/CWorldEditor.ui | 75 +++++++++++- 11 files changed, 501 insertions(+), 11 deletions(-) create mode 100644 EditorAssets/SelectMode.png create mode 100644 UI/CGizmo.cpp create mode 100644 UI/CGizmo.h diff --git a/Common/CVector3f.cpp b/Common/CVector3f.cpp index 381aa7f0..8104000f 100644 --- a/Common/CVector3f.cpp +++ b/Common/CVector3f.cpp @@ -279,6 +279,12 @@ const float& CVector3f::operator[](long index) const const CVector3f CVector3f::skZero = CVector3f(0.f); const CVector3f CVector3f::skOne = CVector3f(1.f); const CVector3f CVector3f::skInfinite = CVector3f(FLT_MAX); +const CVector3f CVector3f::skForward = CVector3f(0.f, 1.f, 0.f); +const CVector3f CVector3f::skBack = CVector3f(0.f, -1.f, 0.f); +const CVector3f CVector3f::skRight = CVector3f( 1.f, 0.f, 0.f); +const CVector3f CVector3f::skLeft = CVector3f(-1.f, 0.f, 0.f); +const CVector3f CVector3f::skUp = CVector3f(0.f, 0.f, 1.f); +const CVector3f CVector3f::skDown = CVector3f(0.f, 0.f, -1.f); // ************ OTHER ************ std::ostream& operator<<(std::ostream& o, const CVector3f& Vector) diff --git a/Common/CVector3f.h b/Common/CVector3f.h index 9b81c511..565fb07b 100644 --- a/Common/CVector3f.h +++ b/Common/CVector3f.h @@ -75,6 +75,12 @@ public: static const CVector3f skZero; static const CVector3f skOne; static const CVector3f skInfinite; + static const CVector3f skForward; + static const CVector3f skBack; + static const CVector3f skRight; + static const CVector3f skLeft; + static const CVector3f skUp; + static const CVector3f skDown; // Other friend std::ostream& operator<<(std::ostream& o, const CVector3f& Vector); diff --git a/Core/CRenderer.cpp b/Core/CRenderer.cpp index 58d9e6b6..be0e8c49 100644 --- a/Core/CRenderer.cpp +++ b/Core/CRenderer.cpp @@ -125,6 +125,7 @@ void CRenderer::SetViewportSize(u32 Width, u32 Height) void CRenderer::RenderBuckets(CCamera& Camera) { if (!mInitialized) Init(); + mSceneFramebuffer.Bind(); // Set backface culling if (mOptions & eEnableBackfaceCull) glEnable(GL_CULL_FACE); @@ -141,6 +142,7 @@ void CRenderer::RenderBuckets(CCamera& Camera) mTransparentBucket.Clear(); // Clear depth buffer to enable more rendering passes + glDepthMask(GL_TRUE); glClear(GL_DEPTH_BUFFER_BIT); } @@ -172,6 +174,7 @@ void CRenderer::RenderBloom() glViewport(0, 0, BloomWidth, BloomHeight); glClearColor(0.f, 0.f, 0.f, 0.f); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_FALSE); CGraphics::SetIdentityMVP(); CGraphics::UpdateMVPBlock(); @@ -308,10 +311,6 @@ void CRenderer::BeginFrame() void CRenderer::EndFrame() { - // Post-processing - if (mBloomMode != eNoBloom) - RenderBloom(); - // Render result to screen glBindFramebuffer(GL_FRAMEBUFFER, mDefaultFramebuffer); InitFramebuffer(); diff --git a/Core/IRenderable.h b/Core/IRenderable.h index c77e933f..814efe25 100644 --- a/Core/IRenderable.h +++ b/Core/IRenderable.h @@ -13,8 +13,8 @@ public: IRenderable() {} virtual ~IRenderable() {} virtual void AddToRenderer(CRenderer *pRenderer) = 0; - virtual void Draw(ERenderOptions options) = 0; - virtual void DrawAsset(ERenderOptions, u32) {} + virtual void Draw(ERenderOptions options) {} + virtual void DrawAsset(ERenderOptions options, u32 asset) {} virtual void DrawSelection() {} }; diff --git a/EditorAssets/SelectMode.png b/EditorAssets/SelectMode.png new file mode 100644 index 0000000000000000000000000000000000000000..2997b2c92ea42389d81ac8881916ba72377822ec GIT binary patch literal 3486 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/Modify.png EditorAssets/Unlink.png EditorAssets/World.png + EditorAssets/SelectMode.png diff --git a/UI/CGizmo.cpp b/UI/CGizmo.cpp new file mode 100644 index 00000000..4f8f5e9a --- /dev/null +++ b/UI/CGizmo.cpp @@ -0,0 +1,221 @@ +#include "CGizmo.h" +#include +#include + +CGizmo::CGizmo() +{ + LoadModels(); + + mMode = eRotate; + mSelectedAxes = eNone; + mGizmoSize = 1.f; + mCameraDist = 0.f; + + mPosition = CVector3f::skZero; + mRotation = CQuaternion::skIdentity; + mScale = CVector3f::skOne; + mDeltaPosition = CVector3f::skZero; + mDeltaRotation = CQuaternion::skIdentity; + mDeltaScale = CVector3f::skOne; + mFlipScaleX = false; + mFlipScaleY = false; + mFlipScaleZ = false; +} + +CGizmo::~CGizmo() +{ +} + +void CGizmo::AddToRenderer(CRenderer *pRenderer) +{ + // Transform is updated every frame even if the user doesn't modify the gizmo + // in order to account for scale changes based on camera distance + UpdateTransform(); + + // Determine which SModelPart array to use + SModelPart *pParts; + u32 numParts; + + if (mMode == eTranslate) { + pParts = smTranslateModels; + numParts = 6; + } else if (mMode == eRotate) { + pParts = smRotateModels; + numParts = 4; + } else if (mMode == eScale) { + pParts = smScaleModels; + numParts = 7; + } + + // Add all parts to renderer + for (u32 iPart = 0; iPart < numParts; iPart++) + { + CModel *pModel = pParts->pModel; + + // Determine whether to use the mat set for regular (0) or highlight (1) + bool isHighlighted = (mSelectedAxes & pParts->modelAxes) == pParts->modelAxes; + u32 setID = (isHighlighted ? 1 : 0); + + // Add to renderer... + if (pModel->HasTransparency(setID)) + pRenderer->AddTransparentMesh(this, iPart, pModel->AABox().Transformed(mTransform), eDrawAsset); + else + pRenderer->AddOpaqueMesh(this, iPart, pModel->AABox().Transformed(mTransform), eDrawAsset); + + pParts++; + } +} + +void CGizmo::DrawAsset(ERenderOptions options, u32 asset) +{ + CGraphics::sMVPBlock.ModelMatrix = mTransform.ToMatrix4f(); + CGraphics::UpdateMVPBlock(); + + // Determine which SModelPart array to use + SModelPart *pParts; + u32 numParts; + + if (mMode == eTranslate) { + pParts = smTranslateModels; + numParts = 6; + } else if (mMode == eRotate) { + pParts = smRotateModels; + numParts = 4; + } else if (mMode == eScale) { + pParts = smScaleModels; + numParts = 7; + } + + if (asset >= numParts) return; + + // Draw model + bool isHighlighted = (mSelectedAxes & pParts[asset].modelAxes) == pParts[asset].modelAxes; + u32 setID = (isHighlighted ? 1 : 0); + pParts[asset].pModel->Draw((ERenderOptions) 0, setID); +} + +void CGizmo::DrawRotationOutline() +{ + CGraphics::sMVPBlock.ModelMatrix = mBillboardTransform.ToMatrix4f(); + CGraphics::UpdateMVPBlock(); + smRotateClipOutline.pModel->Draw((ERenderOptions) 0, 0); +} + +void CGizmo::IncrementSize() +{ + static const float skIncAmount = 1.3f; + static const float skMaxSize = powf(skIncAmount, 4); + + mGizmoSize *= skIncAmount; + if (mGizmoSize > skMaxSize) mGizmoSize = skMaxSize; +} + +void CGizmo::DecrementSize() +{ + static const float skDecAmount = (1.f / 1.3f); + static const float skMinSize = powf(skDecAmount, 4); + + mGizmoSize *= skDecAmount; + if (mGizmoSize < skMinSize) mGizmoSize = skMinSize; +} + +void CGizmo::UpdateForCamera(const CCamera &camera) +{ + CVector3f camPos = camera.Position(); + mCameraDist = mPosition.Distance(camPos); + mFlipScaleX = camPos.x < mPosition.x; + mFlipScaleY = camPos.y < mPosition.y; + mFlipScaleZ = camPos.z < mPosition.z; + + // todo: make this cleaner... + CVector3f billDir = (mPosition - camPos).Normalized(); + CVector3f axis = CVector3f::skForward.Cross(billDir); + float angle = acos(CVector3f::skForward.Dot(billDir)); + angle = 180 + (angle * 180 / 3.14159265358979323846f); + mBillboardRotation = CQuaternion::FromAxisAngle(angle, axis); +} + +CGizmo::EGizmoMode CGizmo::Mode() +{ + return mMode; +} + +void CGizmo::SetMode(EGizmoMode mode) +{ + mMode = mode; +} + +void CGizmo::SetPosition(const CVector3f& position) +{ + mPosition = position; +} + +// ************ PRIVATE STATIC ************ +void CGizmo::LoadModels() +{ + if (!smModelsLoaded) + { + smTranslateModels[CGIZMO_TRANSLATE_X] = SModelPart(eX, (CModel*) gResCache.GetResource("../resources/editor/TranslateGizmoX.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_Y] = SModelPart(eY, (CModel*) gResCache.GetResource("../resources/editor/TranslateGizmoY.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_Z] = SModelPart(eZ, (CModel*) gResCache.GetResource("../resources/editor/TranslateGizmoZ.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_XY] = SModelPart(eXY, (CModel*) gResCache.GetResource("../resources/editor/TranslateGizmoXY.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_XZ] = SModelPart(eXZ, (CModel*) gResCache.GetResource("../resources/editor/TranslateGizmoXZ.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_YZ] = SModelPart(eYZ, (CModel*) gResCache.GetResource("../resources/editor/TranslateGizmoYZ.CMDL")); + + smRotateModels[CGIZMO_ROTATE_X] = SModelPart(eX, (CModel*) gResCache.GetResource("../resources/editor/RotateGizmoX.CMDL")); + smRotateModels[CGIZMO_ROTATE_Y] = SModelPart(eY, (CModel*) gResCache.GetResource("../resources/editor/RotateGizmoY.CMDL")); + smRotateModels[CGIZMO_ROTATE_Z] = SModelPart(eZ, (CModel*) gResCache.GetResource("../resources/editor/RotateGizmoZ.CMDL")); + smRotateModels[CGIZMO_ROTATE_XYZ] = SModelPart(eXYZ, (CModel*) gResCache.GetResource("../resources/editor/RotateGizmoXYZ.CMDL")); + smRotateClipOutline = SModelPart(eNone, (CModel*) gResCache.GetResource("../resources/editor/RotateGizmoClipOutline.CMDL")); + + smScaleModels[CGIZMO_SCALE_X] = SModelPart(eX, (CModel*) gResCache.GetResource("../resources/editor/ScaleGizmoX.CMDL")); + smScaleModels[CGIZMO_SCALE_Y] = SModelPart(eY, (CModel*) gResCache.GetResource("../resources/editor/ScaleGizmoY.CMDL")); + smScaleModels[CGIZMO_SCALE_Z] = SModelPart(eZ, (CModel*) gResCache.GetResource("../resources/editor/ScaleGizmoZ.CMDL")); + smScaleModels[CGIZMO_SCALE_XY] = SModelPart(eXY, (CModel*) gResCache.GetResource("../resources/editor/ScaleGizmoXY.CMDL")); + smScaleModels[CGIZMO_SCALE_XZ] = SModelPart(eXZ, (CModel*) gResCache.GetResource("../resources/editor/ScaleGizmoXZ.CMDL")); + smScaleModels[CGIZMO_SCALE_YZ] = SModelPart(eYZ, (CModel*) gResCache.GetResource("../resources/editor/ScaleGizmoYZ.CMDL")); + smScaleModels[CGIZMO_SCALE_XYZ] = SModelPart(eXYZ, (CModel*) gResCache.GetResource("../resources/editor/ScaleGizmoXYZ.CMDL")); + + smModelsLoaded = true; + } +} + +// ************ PROTECTED ************ +void CGizmo::UpdateTransform() +{ + // Scale is recalculated every frame because it changes frequently, based on camera distance + // Rotation and position values are just saved directly + mScale = mGizmoSize * (mCameraDist / 10.f); + + // Scale also factors in delta scale + axis flip if mode is Scale. + if (mMode == eScale) + { + mScale *= mDeltaScale; + + if (mFlipScaleX) mScale.x = -mScale.x; + if (mFlipScaleY) mScale.y = -mScale.y; + if (mFlipScaleZ) mScale.z = -mScale.z; + } + + // Create transform + mTransform = CTransform4f::skIdentity; + mTransform.Scale(mScale); + mTransform.Rotate(mRotation); + mTransform.Translate(mPosition); + + // Create billboard transform for rotation gizmo + if (mMode == eRotate) + { + mBillboardTransform = CTransform4f::skIdentity; + mBillboardTransform.Scale(mScale); + mBillboardTransform.Rotate(mBillboardRotation); + mBillboardTransform.Translate(mPosition); + } +} + +// ************ STATIC MEMBER INITIALIZATION ************ +bool CGizmo::smModelsLoaded = false; +CGizmo::SModelPart CGizmo::smTranslateModels[6]; +CGizmo::SModelPart CGizmo::smRotateModels[4]; +CGizmo::SModelPart CGizmo::smScaleModels[7]; +CGizmo::SModelPart CGizmo::smRotateClipOutline; diff --git a/UI/CGizmo.h b/UI/CGizmo.h new file mode 100644 index 00000000..a1acd33d --- /dev/null +++ b/UI/CGizmo.h @@ -0,0 +1,113 @@ +#ifndef CGIZMO_H +#define CGIZMO_H + +#include +#include +#include +#include +#include +#include +#include + +#define CGIZMO_TRANSLATE_X 0 +#define CGIZMO_TRANSLATE_Y 1 +#define CGIZMO_TRANSLATE_Z 2 +#define CGIZMO_TRANSLATE_XY 3 +#define CGIZMO_TRANSLATE_XZ 4 +#define CGIZMO_TRANSLATE_YZ 5 +#define CGIZMO_ROTATE_X 0 +#define CGIZMO_ROTATE_Y 1 +#define CGIZMO_ROTATE_Z 2 +#define CGIZMO_ROTATE_XYZ 3 +#define CGIZMO_SCALE_X 0 +#define CGIZMO_SCALE_Y 1 +#define CGIZMO_SCALE_Z 2 +#define CGIZMO_SCALE_XY 3 +#define CGIZMO_SCALE_XZ 4 +#define CGIZMO_SCALE_YZ 5 +#define CGIZMO_SCALE_XYZ 6 + +class CGizmo : public IRenderable +{ +public: + enum EGizmoMode + { + eTranslate, eRotate, eScale + }; + + enum EGizmoAxes + { + eNone = 0x0, + eX = 0x1, + eY = 0x2, + eZ = 0x4, + eXY = eX | eY, + eXZ = eX | eZ, + eYZ = eY | eZ, + eXYZ = eX | eY | eZ + }; + +private: + EGizmoMode mMode; + EGizmoAxes mSelectedAxes; + CTransform4f mBillboardTransform; + CQuaternion mBillboardRotation; + float mGizmoSize; + float mCameraDist; + + CTransform4f mTransform; + CVector3f mPosition; + CQuaternion mRotation; + CVector3f mScale; + CVector3f mDeltaPosition; + CQuaternion mDeltaRotation; + CVector3f mDeltaScale; + bool mFlipScaleX; + bool mFlipScaleY; + bool mFlipScaleZ; + + // Static + struct SModelPart + { + EGizmoAxes modelAxes; + CModel *pModel; + CToken modelToken; + + SModelPart() {} + SModelPart(EGizmoAxes axes, CModel *_pModel) : + modelAxes(axes), pModel(_pModel), modelToken(_pModel) {} + }; + + static bool smModelsLoaded; + static SModelPart smTranslateModels[6]; + static SModelPart smRotateModels[4]; + static SModelPart smScaleModels[7]; + static SModelPart smRotateClipOutline; + +public: + CGizmo(); + ~CGizmo(); + void AddToRenderer(CRenderer *pRenderer); + void DrawAsset(ERenderOptions options, u32 asset); + void DrawRotationOutline(); + + void IncrementSize(); + void DecrementSize(); + void UpdateForCamera(const CCamera& camera); + bool IntersectsRay(const CRay& ray); + + EGizmoMode Mode(); + void SetMode(EGizmoMode mode); + void SetPosition(const CVector3f& position); + + // Protected +protected: + void UpdateTransform(); + + // Private Static +private: + static void LoadModels(); +}; +DEFINE_ENUM_FLAGS(CGizmo::EGizmoAxes) + +#endif // CGIZMO_H diff --git a/UI/CWorldEditor.cpp b/UI/CWorldEditor.cpp index 3b6e7c2d..9abb5b6a 100644 --- a/UI/CWorldEditor.cpp +++ b/UI/CWorldEditor.cpp @@ -31,6 +31,7 @@ CWorldEditor::CWorldEditor(QWidget *parent) : mpWorld = nullptr; mpHoverNode = nullptr; mDrawSky = true; + mShowGizmo = false; mFrameCount = 0; mFPSTimer.Start(); @@ -54,6 +55,10 @@ CWorldEditor::CWorldEditor(QWidget *parent) : ui->CamSpeedSpinBox->SetDefaultValue(1.0); ResetHover(); + // Initialize offscreen actions + addAction(ui->ActionIncrementGizmo); + addAction(ui->ActionDecrementGizmo); + // Connect signals and slots connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double))); connect(ui->MainViewport, SIGNAL(PreRender()), this, SLOT(ViewportPreRender())); @@ -283,6 +288,19 @@ void CWorldEditor::ViewportRender(CCamera& Camera) mpRenderer->RenderBuckets(Camera); mpRenderer->RenderBloom(); + + if (mShowGizmo && (mSelectedNodes.size() > 0)) + { + Camera.LoadMatrices(); + mGizmo.UpdateForCamera(Camera); + mGizmo.AddToRenderer(mpRenderer); + + if (mGizmo.Mode() == CGizmo::eRotate) + mGizmo.DrawRotationOutline(); + + mpRenderer->RenderBuckets(Camera); + } + mpRenderer->EndFrame(); mFrameTimer.Stop(); mFrameCount++; @@ -373,6 +391,9 @@ void CWorldEditor::UpdateSelectionUI() ui->XSpinBox->setValue(pos.x); ui->YSpinBox->setValue(pos.y); ui->ZSpinBox->setValue(pos.z); + + // Update gizmo + mGizmo.SetPosition(pos); } // ************ ACTIONS ************ @@ -522,3 +543,52 @@ void CWorldEditor::on_ActionEditLayers_triggered() Editor.SetArea(mpArea); Editor.exec(); } + +void CWorldEditor::on_ActionSelectObjects_triggered() +{ + mShowGizmo = false; + ui->ActionSelectObjects->setChecked(true); + ui->ActionTranslate->setChecked(false); + ui->ActionRotate->setChecked(false); + ui->ActionScale->setChecked(false); +} + +void CWorldEditor::on_ActionTranslate_triggered() +{ + mShowGizmo = true; + mGizmo.SetMode(CGizmo::eTranslate); + ui->ActionSelectObjects->setChecked(false); + ui->ActionTranslate->setChecked(true); + ui->ActionRotate->setChecked(false); + ui->ActionScale->setChecked(false); +} + +void CWorldEditor::on_ActionRotate_triggered() +{ + mShowGizmo = true; + mGizmo.SetMode(CGizmo::eRotate); + ui->ActionSelectObjects->setChecked(false); + ui->ActionTranslate->setChecked(false); + ui->ActionRotate->setChecked(true); + ui->ActionScale->setChecked(false); +} + +void CWorldEditor::on_ActionScale_triggered() +{ + mShowGizmo = true; + mGizmo.SetMode(CGizmo::eScale); + ui->ActionSelectObjects->setChecked(false); + ui->ActionTranslate->setChecked(false); + ui->ActionRotate->setChecked(false); + ui->ActionScale->setChecked(true); +} + +void CWorldEditor::on_ActionIncrementGizmo_triggered() +{ + mGizmo.IncrementSize(); +} + +void CWorldEditor::on_ActionDecrementGizmo_triggered() +{ + mGizmo.DecrementSize(); +} diff --git a/UI/CWorldEditor.h b/UI/CWorldEditor.h index 717d742b..4b26b0db 100644 --- a/UI/CWorldEditor.h +++ b/UI/CWorldEditor.h @@ -4,6 +4,7 @@ #include #include +#include "CGizmo.h" #include #include #include @@ -23,6 +24,7 @@ class CWorldEditor : public QMainWindow Q_OBJECT CRenderer *mpRenderer; CSceneManager *mpSceneManager; + CGizmo mGizmo; CCamera mCamera; CGameArea *mpArea; CWorld *mpWorld; @@ -30,6 +32,7 @@ class CWorldEditor : public QMainWindow CToken mWorldToken; CTimer mFrameTimer; bool mDrawSky; + bool mShowGizmo; CVector3f mHoverPoint; CSceneNode *mpHoverNode; @@ -91,6 +94,12 @@ private slots: void on_ActionDisableBackfaceCull_triggered(); void on_ActionDisableAlpha_triggered(); void on_ActionEditLayers_triggered(); + void on_ActionSelectObjects_triggered(); + void on_ActionTranslate_triggered(); + void on_ActionRotate_triggered(); + void on_ActionScale_triggered(); + void on_ActionIncrementGizmo_triggered(); + void on_ActionDecrementGizmo_triggered(); }; #endif // CWORLDEDITOR_H diff --git a/UI/CWorldEditor.ui b/UI/CWorldEditor.ui index 3a5c92f1..ac3ecab7 100644 --- a/UI/CWorldEditor.ui +++ b/UI/CWorldEditor.ui @@ -441,6 +441,9 @@ + + Qt::NoContextMenu + toolBar_2 @@ -591,6 +594,9 @@ + + Qt::NoContextMenu + toolBar @@ -603,6 +609,7 @@ + @@ -631,6 +638,9 @@ Translate + + Ctrl+W + @@ -646,6 +656,9 @@ Rotate + + Ctrl+E + @@ -661,6 +674,9 @@ Scale + + Ctrl+R + @@ -871,6 +887,55 @@ Fake Bloom + + + true + + + true + + + + :/icons/EditorAssets/SelectMode.png:/icons/EditorAssets/SelectMode.png + + + Select Objects + + + Select Objects + + + Ctrl+Q + + + + + Increment Gizmo Size + + + Increment Gizmo Size + + + = + + + Qt::WindowShortcut + + + + + Decrement Gizmo Size + + + Decrement Gizmo Size + + + - + + + Qt::WindowShortcut + + @@ -879,6 +944,11 @@
CEditorGLWidget.h
1
+ + WDraggableSpinBox + QDoubleSpinBox +
WDraggableSpinBox.h
+
WModifyTab QWidget @@ -891,11 +961,6 @@
WorldEditor/WInstancesTab.h
1
- - WDraggableSpinBox - QDoubleSpinBox -
WDraggableSpinBox.h
-
XSpinBox