Split off lots of editor functionality into new abstract INodeEditor class and viewport functionality into CBasicViewport class; added viewport subclasses and undo/redo system in the World Editor
This commit is contained in:
parent
281a605586
commit
dbf002d12a
|
@ -1,4 +1,6 @@
|
||||||
#include "Math.h"
|
#include "Math.h"
|
||||||
|
#include <Common/CMatrix4f.h>
|
||||||
|
#include <gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
namespace Math
|
namespace Math
|
||||||
{
|
{
|
||||||
|
@ -336,4 +338,10 @@ std::pair<bool,float> RayTriangleIntersection(const CRay& Ray,
|
||||||
return std::pair<bool,float>(true, t);
|
return std::pair<bool,float>(true, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CMatrix4f PerspectiveMatrix(float fov, float aspect, float near, float far)
|
||||||
|
{
|
||||||
|
// todo: don't use glm
|
||||||
|
return CMatrix4f::FromGlmMat4(glm::perspective(fov, aspect, near, far)).Transpose();
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace
|
} // End namespace
|
||||||
|
|
|
@ -32,6 +32,8 @@ std::pair<bool,float> RayTriangleIntersection(const CRay& Ray, const CVector3f&
|
||||||
const CVector3f& PointB, const CVector3f& PointC,
|
const CVector3f& PointB, const CVector3f& PointC,
|
||||||
bool AllowBackfaces = false);
|
bool AllowBackfaces = false);
|
||||||
|
|
||||||
|
CMatrix4f PerspectiveMatrix(float fov, float aspect, float near, float far);
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
static const float skPi = 3.14159265358979323846f;
|
static const float skPi = 3.14159265358979323846f;
|
||||||
static const float skHalfPi = skPi / 2.f;
|
static const float skHalfPi = skPi / 2.f;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "CCamera.h"
|
#include "CCamera.h"
|
||||||
#include "CGraphics.h"
|
#include "CGraphics.h"
|
||||||
#include <Common/CQuaternion.h>
|
#include <Common/CQuaternion.h>
|
||||||
|
#include <Common/Math.h>
|
||||||
#include <gtc/matrix_transform.hpp>
|
#include <gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#define HALF_PI 1.570796371f
|
#define HALF_PI 1.570796371f
|
||||||
|
@ -170,21 +170,25 @@ CVector3f CCamera::Position() const
|
||||||
return mPosition;
|
return mPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CCamera::GetDirection() const
|
CVector3f CCamera::Direction() const
|
||||||
{
|
{
|
||||||
return mDirection;
|
return mDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CCamera::GetYaw() const
|
float CCamera::Yaw() const
|
||||||
{
|
{
|
||||||
return mYaw;
|
return mYaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CCamera::GetPitch() const
|
float CCamera::Pitch() const
|
||||||
{
|
{
|
||||||
return mPitch;
|
return mPitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CCamera::FieldOfView() const
|
||||||
|
{
|
||||||
|
return 55.f;
|
||||||
|
}
|
||||||
|
|
||||||
const CMatrix4f& CCamera::ViewMatrix()
|
const CMatrix4f& CCamera::ViewMatrix()
|
||||||
{
|
{
|
||||||
|
@ -298,7 +302,6 @@ void CCamera::CalculateView()
|
||||||
|
|
||||||
void CCamera::CalculateProjection()
|
void CCamera::CalculateProjection()
|
||||||
{
|
{
|
||||||
// todo: don't use glm
|
mCachedProjectionMatrix = Math::PerspectiveMatrix(55.f, mAspectRatio, 0.1f, 4096.f);
|
||||||
mCachedProjectionMatrix = CMatrix4f::FromGlmMat4(glm::perspective(55.f, mAspectRatio, 0.1f, 4096.f)).Transpose();
|
|
||||||
mProjectionOutdated = false;
|
mProjectionOutdated = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,10 @@ public:
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
CVector3f Position() const;
|
CVector3f Position() const;
|
||||||
CVector3f GetDirection() const;
|
CVector3f Direction() const;
|
||||||
float GetYaw() const;
|
float Yaw() const;
|
||||||
float GetPitch() const;
|
float Pitch() const;
|
||||||
|
float FieldOfView() const;
|
||||||
const CMatrix4f& ViewMatrix();
|
const CMatrix4f& ViewMatrix();
|
||||||
const CMatrix4f& RotationOnlyViewMatrix();
|
const CMatrix4f& RotationOnlyViewMatrix();
|
||||||
const CMatrix4f& ProjectionMatrix();
|
const CMatrix4f& ProjectionMatrix();
|
||||||
|
|
|
@ -30,7 +30,7 @@ void CRenderBucket::Sort(CCamera& Camera)
|
||||||
CCamera *pCamera;
|
CCamera *pCamera;
|
||||||
bool operator()(SRenderablePtr left, SRenderablePtr right) {
|
bool operator()(SRenderablePtr left, SRenderablePtr right) {
|
||||||
CVector3f cPos = pCamera->Position();
|
CVector3f cPos = pCamera->Position();
|
||||||
CVector3f cDir = pCamera->GetDirection();
|
CVector3f cDir = pCamera->Direction();
|
||||||
|
|
||||||
CVector3f distL = left.AABox.ClosestPointAlongVector(cDir) - cPos;
|
CVector3f distL = left.AABox.ClosestPointAlongVector(cDir) - cPos;
|
||||||
float dotL = distL.Dot(cDir);
|
float dotL = distL.Dot(cDir);
|
||||||
|
|
|
@ -126,7 +126,7 @@ void CRenderer::RenderBuckets(CCamera& Camera)
|
||||||
{
|
{
|
||||||
if (!mInitialized) Init();
|
if (!mInitialized) Init();
|
||||||
mSceneFramebuffer.Bind();
|
mSceneFramebuffer.Bind();
|
||||||
Camera.LoadMatrices();
|
//Camera.LoadMatrices();
|
||||||
|
|
||||||
// Set backface culling
|
// Set backface culling
|
||||||
if (mOptions & eEnableBackfaceCull) glEnable(GL_CULL_FACE);
|
if (mOptions & eEnableBackfaceCull) glEnable(GL_CULL_FACE);
|
||||||
|
|
|
@ -199,9 +199,12 @@ void CSceneManager::SetActiveWorld(CWorld* _world)
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneManager::ClearScene()
|
void CSceneManager::ClearScene()
|
||||||
|
{
|
||||||
|
if (mpAreaRootNode)
|
||||||
{
|
{
|
||||||
mpAreaRootNode->Unparent();
|
mpAreaRootNode->Unparent();
|
||||||
delete mpAreaRootNode;
|
delete mpAreaRootNode;
|
||||||
|
}
|
||||||
|
|
||||||
mModelNodes.clear();
|
mModelNodes.clear();
|
||||||
mStaticNodes.clear();
|
mStaticNodes.clear();
|
||||||
|
|
|
@ -72,7 +72,6 @@ SOURCES += \
|
||||||
Resource/factory/CWorldLoader.cpp \
|
Resource/factory/CWorldLoader.cpp \
|
||||||
Resource/CStringTable.cpp \
|
Resource/CStringTable.cpp \
|
||||||
Resource/factory/CStringLoader.cpp \
|
Resource/factory/CStringLoader.cpp \
|
||||||
UI/CEditorGLWidget.cpp \
|
|
||||||
Core/CGraphics.cpp \
|
Core/CGraphics.cpp \
|
||||||
Resource/CFont.cpp \
|
Resource/CFont.cpp \
|
||||||
Resource/factory/CFontLoader.cpp \
|
Resource/factory/CFontLoader.cpp \
|
||||||
|
@ -135,7 +134,17 @@ SOURCES += \
|
||||||
UI/WIntegralSpinBox.cpp \
|
UI/WIntegralSpinBox.cpp \
|
||||||
UI/CAboutDialog.cpp \
|
UI/CAboutDialog.cpp \
|
||||||
UI/CGizmo.cpp \
|
UI/CGizmo.cpp \
|
||||||
Common/CPlane.cpp
|
Common/CPlane.cpp \
|
||||||
|
UI/undo/CTranslateNodeCommand.cpp \
|
||||||
|
UI/undo/CClearSelectionCommand.cpp \
|
||||||
|
UI/undo/CSelectNodeCommand.cpp \
|
||||||
|
UI/undo/CDeselectNodeCommand.cpp \
|
||||||
|
UI/CBasicViewport.cpp \
|
||||||
|
UI/INodeEditor.cpp \
|
||||||
|
UI/CSceneViewport.cpp \
|
||||||
|
UI/undo/CRotateNodeCommand.cpp \
|
||||||
|
UI/undo/CScaleNodeCommand.cpp \
|
||||||
|
UI/CModelEditorViewport.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Common/AnimUtil.h \
|
Common/AnimUtil.h \
|
||||||
|
@ -208,7 +217,6 @@ HEADERS += \
|
||||||
Resource/SDependency.h \
|
Resource/SDependency.h \
|
||||||
Resource/CStringTable.h \
|
Resource/CStringTable.h \
|
||||||
Resource/factory/CStringLoader.h \
|
Resource/factory/CStringLoader.h \
|
||||||
UI/CEditorGLWidget.h \
|
|
||||||
Core/CGraphics.h \
|
Core/CGraphics.h \
|
||||||
Resource/CFont.h \
|
Resource/CFont.h \
|
||||||
Resource/factory/CFontLoader.h \
|
Resource/factory/CFontLoader.h \
|
||||||
|
@ -286,7 +294,19 @@ HEADERS += \
|
||||||
Core/IRenderable.h \
|
Core/IRenderable.h \
|
||||||
Core/SRenderablePtr.h \
|
Core/SRenderablePtr.h \
|
||||||
Common/ETransformSpace.h \
|
Common/ETransformSpace.h \
|
||||||
Common/CPlane.h
|
Common/CPlane.h \
|
||||||
|
UI/undo/CTranslateNodeCommand.h \
|
||||||
|
UI/undo/EUndoCommand.h \
|
||||||
|
UI/undo/CClearSelectionCommand.h \
|
||||||
|
UI/undo/CSelectNodeCommand.h \
|
||||||
|
UI/undo/CDeselectNodeCommand.h \
|
||||||
|
UI/undo/UndoCommands.h \
|
||||||
|
UI/CBasicViewport.h \
|
||||||
|
UI/INodeEditor.h \
|
||||||
|
UI/CSceneViewport.h \
|
||||||
|
UI/undo/CRotateNodeCommand.h \
|
||||||
|
UI/undo/CScaleNodeCommand.h \
|
||||||
|
UI/CModelEditorViewport.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
UI/CWorldEditorWindow.ui \
|
UI/CWorldEditorWindow.ui \
|
||||||
|
|
|
@ -108,6 +108,12 @@ void CScriptNode::AddToRenderer(CRenderer *pRenderer)
|
||||||
|
|
||||||
if (mHasVolumePreview)
|
if (mHasVolumePreview)
|
||||||
mpVolumePreviewNode->AddToRenderer(pRenderer);
|
mpVolumePreviewNode->AddToRenderer(pRenderer);
|
||||||
|
|
||||||
|
if (mpInstance->ObjectTypeID() == 0xC)
|
||||||
|
{
|
||||||
|
CGraphics::sMVPBlock.ViewMatrix = Transform().Inverse().ToMatrix4f();
|
||||||
|
CGraphics::UpdateMVPBlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,49 +1,31 @@
|
||||||
|
#include "CBasicViewport.h"
|
||||||
|
#include <Core/CDrawUtil.h>
|
||||||
|
#include <Core/CGraphics.h>
|
||||||
|
#include <Common/Math.h>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <gtc/matrix_transform.hpp>
|
|
||||||
#include <gtx/transform.hpp>
|
|
||||||
#include <Core/CGraphics.h>
|
|
||||||
#include <Core/CRenderer.h>
|
|
||||||
#include <QTimer>
|
|
||||||
#include "CEditorGLWidget.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <Core/CGraphics.h>
|
|
||||||
#include <Resource/factory/CTextureDecoder.h>
|
|
||||||
#include <Common/CTimer.h>
|
|
||||||
#include <Common/CVector4f.h>
|
|
||||||
#include <QOpenGLContext>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QOpenGLPaintDevice>
|
|
||||||
|
|
||||||
QTimer CEditorGLWidget::sRefreshTimer;
|
CBasicViewport::CBasicViewport(QWidget *pParent) :
|
||||||
|
QOpenGLWidget(pParent),
|
||||||
CEditorGLWidget::CEditorGLWidget(QWidget *pParent) :
|
mLastDrawTime(CTimer::GlobalTime()),
|
||||||
QOpenGLWidget(pParent)
|
mKeysPressed(0),
|
||||||
|
mButtonsPressed(0),
|
||||||
|
mCursorState(Qt::ArrowCursor),
|
||||||
|
mCursorVisible(true)
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
mLastDrawTime = CTimer::GlobalTime();
|
|
||||||
mKeysPressed = 0;
|
|
||||||
mButtonsPressed = 0;
|
|
||||||
mCursorState = Qt::ArrowCursor;
|
|
||||||
mCursorVisible = true;
|
|
||||||
mCamera.SetAspectRatio((float) width() / height());
|
mCamera.SetAspectRatio((float) width() / height());
|
||||||
|
|
||||||
connect(&sRefreshTimer, SIGNAL(timeout()), this, SLOT(update()));
|
|
||||||
|
|
||||||
if (!sRefreshTimer.isActive())
|
|
||||||
sRefreshTimer.start(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CEditorGLWidget::~CEditorGLWidget()
|
CBasicViewport::~CBasicViewport()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::initializeGL()
|
void CBasicViewport::initializeGL()
|
||||||
{
|
{
|
||||||
// Initialize CGraphics
|
// Initialize CGraphics
|
||||||
CGraphics::Initialize();
|
CGraphics::Initialize();
|
||||||
|
|
||||||
// Setting various GL flags
|
// Setting various GL flags
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_PRIMITIVE_RESTART);
|
glEnable(GL_PRIMITIVE_RESTART);
|
||||||
glPrimitiveRestartIndex(0xFFFF);
|
glPrimitiveRestartIndex(0xFFFF);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
@ -55,44 +37,33 @@ void CEditorGLWidget::initializeGL()
|
||||||
CMaterial::KillCachedMaterial();
|
CMaterial::KillCachedMaterial();
|
||||||
CShader::KillCachedShader();
|
CShader::KillCachedShader();
|
||||||
|
|
||||||
// Initialize renderer
|
// Initialize size
|
||||||
emit ViewportResized(width(), height());
|
OnResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::paintGL()
|
void CBasicViewport::paintGL()
|
||||||
{
|
{
|
||||||
double DeltaTime = CTimer::GlobalTime() - mLastDrawTime;
|
// Prep render
|
||||||
mLastDrawTime = CTimer::GlobalTime();
|
glViewport(0, 0, width(), height());
|
||||||
|
glLineWidth(1.f);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
// Camera movement is processed here in order to sync it with the paint event
|
// Actual rendering is intended to be handled by subclassing CBasicViewport and
|
||||||
// This way movement happens exactly once per frame - no more, no less
|
// reimplementing Render().
|
||||||
ProcessInput(DeltaTime);
|
Paint();
|
||||||
|
|
||||||
// Pre-render signal allows for per-frame operations to be performed before the draw happens
|
// Finally, draw XYZ axes in the corner
|
||||||
emit PreRender();
|
// DrawAxes();
|
||||||
|
|
||||||
// We emit a signal to indicate it's time to render the viewport instead of doing the rendering here.
|
|
||||||
// This allows the editor GL widget class to be reused among multiple editors with different rendering needs.
|
|
||||||
emit Render(mCamera);
|
|
||||||
|
|
||||||
// Post-render signal allows for the frame to be completed with post-processing
|
|
||||||
emit PostRender();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::resizeGL(int w, int h)
|
void CBasicViewport::resizeGL(int w, int h)
|
||||||
{
|
{
|
||||||
mCamera.SetAspectRatio((float) w / h);
|
mCamera.SetAspectRatio((float) w / h);
|
||||||
glViewport(0, 0, w, h);
|
glViewport(0, 0, w, h);
|
||||||
emit ViewportResized(w, h);
|
OnResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::mouseMoveEvent(QMouseEvent *pEvent)
|
void CBasicViewport::mousePressEvent(QMouseEvent *pEvent)
|
||||||
{
|
|
||||||
if ((!IsMouseInputActive()) && (mButtonsPressed & eLeftButton))
|
|
||||||
emit MouseDrag(pEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEditorGLWidget::mousePressEvent(QMouseEvent *pEvent)
|
|
||||||
{
|
{
|
||||||
setFocus();
|
setFocus();
|
||||||
|
|
||||||
|
@ -100,7 +71,11 @@ void CEditorGLWidget::mousePressEvent(QMouseEvent *pEvent)
|
||||||
if (pEvent->button() == Qt::RightButton) mButtonsPressed |= eRightButton;
|
if (pEvent->button() == Qt::RightButton) mButtonsPressed |= eRightButton;
|
||||||
|
|
||||||
if (IsMouseInputActive())
|
if (IsMouseInputActive())
|
||||||
|
{
|
||||||
SetCursorVisible(false);
|
SetCursorVisible(false);
|
||||||
|
mMouseMoved = false;
|
||||||
|
mMoveTimer.Restart();
|
||||||
|
}
|
||||||
|
|
||||||
// Left click only activates if mouse input is inactive to prevent the user from
|
// Left click only activates if mouse input is inactive to prevent the user from
|
||||||
// clicking on things and creating selection rectangles while the cursor is hidden
|
// clicking on things and creating selection rectangles while the cursor is hidden
|
||||||
|
@ -109,13 +84,13 @@ void CEditorGLWidget::mousePressEvent(QMouseEvent *pEvent)
|
||||||
if (pEvent->button() == Qt::LeftButton)
|
if (pEvent->button() == Qt::LeftButton)
|
||||||
mButtonsPressed |= eLeftButton;
|
mButtonsPressed |= eLeftButton;
|
||||||
|
|
||||||
emit MouseClick(pEvent);
|
OnMouseClick(pEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastMousePos = pEvent->globalPos();
|
mLastMousePos = pEvent->globalPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::mouseReleaseEvent(QMouseEvent *pEvent)
|
void CBasicViewport::mouseReleaseEvent(QMouseEvent *pEvent)
|
||||||
{
|
{
|
||||||
bool fromMouseInput = IsMouseInputActive();
|
bool fromMouseInput = IsMouseInputActive();
|
||||||
if (pEvent->button() == Qt::LeftButton) mButtonsPressed &= ~eLeftButton;
|
if (pEvent->button() == Qt::LeftButton) mButtonsPressed &= ~eLeftButton;
|
||||||
|
@ -126,12 +101,23 @@ void CEditorGLWidget::mouseReleaseEvent(QMouseEvent *pEvent)
|
||||||
if (!IsMouseInputActive())
|
if (!IsMouseInputActive())
|
||||||
SetCursorVisible(true);
|
SetCursorVisible(true);
|
||||||
|
|
||||||
// Emit mouse release event if we didn't just exit mouse input (or regardless on left click)
|
// Run mouse release if we didn't just exit mouse input (or regardless on left click)
|
||||||
if (!fromMouseInput || (pEvent->button() == Qt::LeftButton))
|
if (!fromMouseInput || (pEvent->button() == Qt::LeftButton))
|
||||||
emit MouseRelease(pEvent);
|
OnMouseRelease(pEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::keyPressEvent(QKeyEvent *pEvent)
|
void CBasicViewport::mouseMoveEvent(QMouseEvent *pEvent)
|
||||||
|
{
|
||||||
|
// todo: draggable selection rectangle
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBasicViewport::wheelEvent(QWheelEvent *pEvent)
|
||||||
|
{
|
||||||
|
// Maybe track a "wheel delta" member variable and let CCamera decide what to do with it?
|
||||||
|
mCamera.Zoom(pEvent->angleDelta().y() / 6000.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBasicViewport::keyPressEvent(QKeyEvent *pEvent)
|
||||||
{
|
{
|
||||||
switch (pEvent->key())
|
switch (pEvent->key())
|
||||||
{
|
{
|
||||||
|
@ -145,7 +131,7 @@ void CEditorGLWidget::keyPressEvent(QKeyEvent *pEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::keyReleaseEvent(QKeyEvent *pEvent)
|
void CBasicViewport::keyReleaseEvent(QKeyEvent *pEvent)
|
||||||
{
|
{
|
||||||
switch (pEvent->key())
|
switch (pEvent->key())
|
||||||
{
|
{
|
||||||
|
@ -159,13 +145,7 @@ void CEditorGLWidget::keyReleaseEvent(QKeyEvent *pEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::wheelEvent(QWheelEvent *pEvent)
|
void CBasicViewport::focusOutEvent(QFocusEvent*)
|
||||||
{
|
|
||||||
// Maybe track a "wheel delta" member variable and let CCamera decide what to do with it?
|
|
||||||
mCamera.Zoom(pEvent->angleDelta().y() / 6000.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEditorGLWidget::focusOutEvent(QFocusEvent*)
|
|
||||||
{
|
{
|
||||||
// When the widget loses focus, release all input.
|
// When the widget loses focus, release all input.
|
||||||
mButtonsPressed = 0;
|
mButtonsPressed = 0;
|
||||||
|
@ -173,7 +153,14 @@ void CEditorGLWidget::focusOutEvent(QFocusEvent*)
|
||||||
SetCursorVisible(true);
|
SetCursorVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::SetCursorState(const QCursor &Cursor)
|
void CBasicViewport::contextMenuEvent(QContextMenuEvent *pEvent)
|
||||||
|
{
|
||||||
|
// Only allow context menu if we aren't exiting mouse input mode.
|
||||||
|
if (!mMouseMoved && (mMoveTimer.Time() < 0.5))
|
||||||
|
ContextMenu(pEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBasicViewport::SetCursorState(const QCursor &Cursor)
|
||||||
{
|
{
|
||||||
mCursorState = Cursor;
|
mCursorState = Cursor;
|
||||||
|
|
||||||
|
@ -181,7 +168,7 @@ void CEditorGLWidget::SetCursorState(const QCursor &Cursor)
|
||||||
setCursor(Cursor);
|
setCursor(Cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::SetCursorVisible(bool visible)
|
void CBasicViewport::SetCursorVisible(bool visible)
|
||||||
{
|
{
|
||||||
mCursorVisible = visible;
|
mCursorVisible = visible;
|
||||||
|
|
||||||
|
@ -191,35 +178,35 @@ void CEditorGLWidget::SetCursorVisible(bool visible)
|
||||||
setCursor(Qt::BlankCursor);
|
setCursor(Qt::BlankCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEditorGLWidget::IsCursorVisible()
|
bool CBasicViewport::IsCursorVisible()
|
||||||
{
|
{
|
||||||
return mCursorVisible;
|
return mCursorVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEditorGLWidget::IsMouseInputActive()
|
bool CBasicViewport::IsMouseInputActive()
|
||||||
{
|
{
|
||||||
static const int skMoveButtons = eMiddleButton | eRightButton;
|
static const int skMoveButtons = eMiddleButton | eRightButton;
|
||||||
return ((mButtonsPressed & skMoveButtons) != 0);
|
return ((mButtonsPressed & skMoveButtons) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEditorGLWidget::IsKeyboardInputActive()
|
bool CBasicViewport::IsKeyboardInputActive()
|
||||||
{
|
{
|
||||||
static const int skMoveKeys = eQKey | eWKey | eEKey | eAKey | eSKey | eDKey;
|
static const int skMoveKeys = eQKey | eWKey | eEKey | eAKey | eSKey | eDKey;
|
||||||
return ((mKeysPressed & skMoveKeys) != 0);
|
return ((mKeysPressed & skMoveKeys) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCamera& CEditorGLWidget::Camera()
|
CCamera& CBasicViewport::Camera()
|
||||||
{
|
{
|
||||||
return mCamera;
|
return mCamera;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRay CEditorGLWidget::CastRay()
|
CRay CBasicViewport::CastRay()
|
||||||
{
|
{
|
||||||
CVector2f MouseCoords = MouseDeviceCoordinates();
|
CVector2f MouseCoords = MouseDeviceCoordinates();
|
||||||
return mCamera.CastRay(MouseCoords);
|
return mCamera.CastRay(MouseCoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector2f CEditorGLWidget::MouseDeviceCoordinates()
|
CVector2f CBasicViewport::MouseDeviceCoordinates()
|
||||||
{
|
{
|
||||||
QPoint MousePos = QCursor::pos();
|
QPoint MousePos = QCursor::pos();
|
||||||
QPoint ThisPos = this->mapToGlobal(pos());
|
QPoint ThisPos = this->mapToGlobal(pos());
|
||||||
|
@ -232,10 +219,18 @@ CVector2f CEditorGLWidget::MouseDeviceCoordinates()
|
||||||
return Device;
|
return Device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double CBasicViewport::LastRenderDuration()
|
||||||
// ************ PRIVATE ************
|
|
||||||
void CEditorGLWidget::ProcessInput(double DeltaTime)
|
|
||||||
{
|
{
|
||||||
|
return mFrameTimer.Time();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ PUBLIC SLOTS ************
|
||||||
|
void CBasicViewport::ProcessInput()
|
||||||
|
{
|
||||||
|
// Process camera input
|
||||||
|
double DeltaTime = CTimer::GlobalTime() - mLastDrawTime;
|
||||||
|
mLastDrawTime = CTimer::GlobalTime();
|
||||||
|
|
||||||
if (IsMouseInputActive())
|
if (IsMouseInputActive())
|
||||||
{
|
{
|
||||||
float XMovement = (QCursor::pos().x() - mLastMousePos.x()) * 0.01f;
|
float XMovement = (QCursor::pos().x() - mLastMousePos.x()) * 0.01f;
|
||||||
|
@ -245,9 +240,42 @@ void CEditorGLWidget::ProcessInput(double DeltaTime)
|
||||||
{
|
{
|
||||||
mCamera.ProcessMouseInput((EKeyInputs) mKeysPressed, (EMouseInputs) mButtonsPressed, XMovement, YMovement);
|
mCamera.ProcessMouseInput((EKeyInputs) mKeysPressed, (EMouseInputs) mButtonsPressed, XMovement, YMovement);
|
||||||
QCursor::setPos(mLastMousePos);
|
QCursor::setPos(mLastMousePos);
|
||||||
|
mMouseMoved = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyboardInputActive())
|
if (IsKeyboardInputActive())
|
||||||
mCamera.ProcessKeyInput((EKeyInputs) mKeysPressed, DeltaTime);
|
mCamera.ProcessKeyInput((EKeyInputs) mKeysPressed, DeltaTime);
|
||||||
|
|
||||||
|
// Check user input
|
||||||
|
CheckUserInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBasicViewport::Render()
|
||||||
|
{
|
||||||
|
mFrameTimer.Start();
|
||||||
|
update();
|
||||||
|
mFrameTimer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ PRIVATE ************
|
||||||
|
void CBasicViewport::ProcessInput(double DeltaTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBasicViewport::DrawAxes()
|
||||||
|
{
|
||||||
|
// Draw 64x64 axes in lower-left corner with 8px margins
|
||||||
|
glViewport(8, height() - 72, 64, 64);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
CGraphics::sMVPBlock.ViewMatrix = CTransform4f::TranslationMatrix(CVector3f(0,2,0)).ToMatrix4f() * mCamera.RotationOnlyViewMatrix();
|
||||||
|
CGraphics::sMVPBlock.ProjectionMatrix = Math::PerspectiveMatrix(mCamera.FieldOfView(), 1.f, 0.1f, 4096.f);
|
||||||
|
CGraphics::UpdateMVPBlock();
|
||||||
|
|
||||||
|
glLineWidth(2.f);
|
||||||
|
CDrawUtil::DrawLine(CVector3f(0,0,0), CVector3f(1,0,0), CColor::skRed); // X
|
||||||
|
CDrawUtil::DrawLine(CVector3f(0,0,0), CVector3f(0,1,0), CColor::skGreen); // Y
|
||||||
|
CDrawUtil::DrawLine(CVector3f(0,0,0), CVector3f(0,0,1), CColor::skBlue); // Z
|
||||||
}
|
}
|
|
@ -11,34 +11,44 @@
|
||||||
#include <Core/CRenderer.h>
|
#include <Core/CRenderer.h>
|
||||||
#include <Resource/CFont.h>
|
#include <Resource/CFont.h>
|
||||||
#include <Common/CRay.h>
|
#include <Common/CRay.h>
|
||||||
|
#include <Common/CTimer.h>
|
||||||
|
|
||||||
class CEditorGLWidget : public QOpenGLWidget
|
class CBasicViewport : public QOpenGLWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
static QTimer sRefreshTimer;
|
protected:
|
||||||
|
// Render
|
||||||
CCamera mCamera;
|
CCamera mCamera;
|
||||||
QPoint mLastMousePos;
|
CTimer mFrameTimer;
|
||||||
double mLastDrawTime;
|
double mLastDrawTime;
|
||||||
QPoint mLeftClickPoint;
|
|
||||||
int mButtonsPressed; // int container for EMouseInputs flags
|
// Cursor settings
|
||||||
int mKeysPressed; // int container for EKeyInputs flags
|
|
||||||
QCursor mCursorState;
|
QCursor mCursorState;
|
||||||
bool mCursorVisible;
|
bool mCursorVisible;
|
||||||
|
|
||||||
|
// Input
|
||||||
|
QPoint mLastMousePos;
|
||||||
|
bool mMouseMoved;
|
||||||
|
CTimer mMoveTimer;
|
||||||
|
int mButtonsPressed; // int container for EMouseInputs flags
|
||||||
|
int mKeysPressed; // int container for EKeyInputs flags
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CEditorGLWidget(QWidget *pParent = 0);
|
explicit CBasicViewport(QWidget *pParent = 0);
|
||||||
~CEditorGLWidget();
|
~CBasicViewport();
|
||||||
void initializeGL();
|
void initializeGL();
|
||||||
void paintGL();
|
void paintGL();
|
||||||
void resizeGL(int w, int h);
|
void resizeGL(int w, int h);
|
||||||
void mouseMoveEvent(QMouseEvent *pEvent);
|
|
||||||
void mousePressEvent(QMouseEvent *pEvent);
|
void mousePressEvent(QMouseEvent *pEvent);
|
||||||
void mouseReleaseEvent(QMouseEvent *pEvent);
|
void mouseReleaseEvent(QMouseEvent *pEvent);
|
||||||
|
void mouseMoveEvent(QMouseEvent *pEvent);
|
||||||
|
void wheelEvent(QWheelEvent *pEvent);
|
||||||
void keyPressEvent(QKeyEvent *pEvent);
|
void keyPressEvent(QKeyEvent *pEvent);
|
||||||
void keyReleaseEvent(QKeyEvent *pEvent);
|
void keyReleaseEvent(QKeyEvent *pEvent);
|
||||||
void wheelEvent(QWheelEvent *pEvent);
|
|
||||||
void focusOutEvent(QFocusEvent *pEvent);
|
void focusOutEvent(QFocusEvent *pEvent);
|
||||||
|
void contextMenuEvent(QContextMenuEvent *pEvent);
|
||||||
|
|
||||||
void SetCursorState(const QCursor& Cursor);
|
void SetCursorState(const QCursor& Cursor);
|
||||||
void SetCursorVisible(bool visible);
|
void SetCursorVisible(bool visible);
|
||||||
bool IsCursorVisible();
|
bool IsCursorVisible();
|
||||||
|
@ -47,18 +57,23 @@ public:
|
||||||
CCamera& Camera();
|
CCamera& Camera();
|
||||||
CRay CastRay();
|
CRay CastRay();
|
||||||
CVector2f MouseDeviceCoordinates();
|
CVector2f MouseDeviceCoordinates();
|
||||||
|
double LastRenderDuration();
|
||||||
|
|
||||||
signals:
|
public slots:
|
||||||
void ViewportResized(int w, int h);
|
void ProcessInput();
|
||||||
void PreRender();
|
void Render();
|
||||||
void Render(CCamera& Camera);
|
|
||||||
void PostRender();
|
protected slots:
|
||||||
void MouseClick(QMouseEvent *pEvent);
|
virtual void CheckUserInput() {}
|
||||||
void MouseRelease(QMouseEvent *pEvent);
|
virtual void Paint() {}
|
||||||
void MouseDrag(QMouseEvent *pEvent);
|
virtual void ContextMenu(QContextMenuEvent *pEvent) {}
|
||||||
|
virtual void OnResize() {}
|
||||||
|
virtual void OnMouseClick(QMouseEvent *pEvent) {}
|
||||||
|
virtual void OnMouseRelease(QMouseEvent *pEvent) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessInput(double DeltaTime);
|
void ProcessInput(double DeltaTime);
|
||||||
|
void DrawAxes();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -476,7 +476,7 @@ bool CGizmo::TransformFromInput(const CRay& ray, CCamera& camera)
|
||||||
|
|
||||||
mDeltaScale = mTotalScale / oldScale;
|
mDeltaScale = mTotalScale / oldScale;
|
||||||
|
|
||||||
if (!mHasTransformed && (scaleAmount != 0.f))
|
if (!mHasTransformed && (scaleAmount != 1.f))
|
||||||
mHasTransformed = true;
|
mHasTransformed = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -491,6 +491,11 @@ void CGizmo::EndTransform()
|
||||||
mIsTransforming = false;
|
mIsTransforming = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGizmo::IsTransforming()
|
||||||
|
{
|
||||||
|
return mIsTransforming;
|
||||||
|
}
|
||||||
|
|
||||||
bool CGizmo::HasTransformed()
|
bool CGizmo::HasTransformed()
|
||||||
{
|
{
|
||||||
return mHasTransformed;
|
return mHasTransformed;
|
||||||
|
@ -501,6 +506,11 @@ CGizmo::EGizmoMode CGizmo::Mode()
|
||||||
return mMode;
|
return mMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ETransformSpace CGizmo::TransformSpace()
|
||||||
|
{
|
||||||
|
return mTransformSpace;
|
||||||
|
}
|
||||||
|
|
||||||
CVector3f CGizmo::Position()
|
CVector3f CGizmo::Position()
|
||||||
{
|
{
|
||||||
return mPosition;
|
return mPosition;
|
||||||
|
|
|
@ -41,7 +41,7 @@ class CGizmo : public IRenderable
|
||||||
public:
|
public:
|
||||||
enum EGizmoMode
|
enum EGizmoMode
|
||||||
{
|
{
|
||||||
eTranslate, eRotate, eScale
|
eTranslate, eRotate, eScale, eOff
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EGizmoAxes
|
enum EGizmoAxes
|
||||||
|
@ -68,6 +68,7 @@ private:
|
||||||
CVector2f mWrapOffset;
|
CVector2f mWrapOffset;
|
||||||
bool mEnableCursorWrap;
|
bool mEnableCursorWrap;
|
||||||
|
|
||||||
|
// Transform
|
||||||
CTransform4f mTransform;
|
CTransform4f mTransform;
|
||||||
CTransform4f mBillboardTransform;
|
CTransform4f mBillboardTransform;
|
||||||
CTransform4f mScaledTransform;
|
CTransform4f mScaledTransform;
|
||||||
|
@ -79,6 +80,7 @@ private:
|
||||||
bool mFlipScaleY;
|
bool mFlipScaleY;
|
||||||
bool mFlipScaleZ;
|
bool mFlipScaleZ;
|
||||||
|
|
||||||
|
// Delta transform
|
||||||
CVector3f mDeltaTranslation;
|
CVector3f mDeltaTranslation;
|
||||||
CVector3f mTotalTranslation;
|
CVector3f mTotalTranslation;
|
||||||
CQuaternion mDeltaRotation;
|
CQuaternion mDeltaRotation;
|
||||||
|
@ -87,15 +89,16 @@ private:
|
||||||
CVector3f mDeltaScale;
|
CVector3f mDeltaScale;
|
||||||
CVector3f mTotalScale;
|
CVector3f mTotalScale;
|
||||||
|
|
||||||
|
// Transform helpers
|
||||||
CPlane mTranslatePlane;
|
CPlane mTranslatePlane;
|
||||||
CVector3f mTranslateOffset;
|
CVector3f mTranslateOffset;
|
||||||
float mRotateOffset;
|
float mRotateOffset;
|
||||||
float mScaleOffset;
|
float mScaleOffset;
|
||||||
bool mSetOffset;
|
bool mSetOffset;
|
||||||
|
|
||||||
CVector3f mHitPoint;
|
CVector3f mHitPoint;
|
||||||
CVector3f mMoveDir;
|
CVector3f mMoveDir;
|
||||||
|
|
||||||
|
// Model parts
|
||||||
struct SModelPart
|
struct SModelPart
|
||||||
{
|
{
|
||||||
EGizmoAxes modelAxes;
|
EGizmoAxes modelAxes;
|
||||||
|
@ -133,9 +136,11 @@ public:
|
||||||
void StartTransform();
|
void StartTransform();
|
||||||
bool TransformFromInput(const CRay& ray, CCamera& camera);
|
bool TransformFromInput(const CRay& ray, CCamera& camera);
|
||||||
void EndTransform();
|
void EndTransform();
|
||||||
|
bool IsTransforming();
|
||||||
bool HasTransformed();
|
bool HasTransformed();
|
||||||
|
|
||||||
EGizmoMode Mode();
|
EGizmoMode Mode();
|
||||||
|
ETransformSpace TransformSpace();
|
||||||
CVector3f Position();
|
CVector3f Position();
|
||||||
CVector3f DeltaTranslation();
|
CVector3f DeltaTranslation();
|
||||||
CVector3f TotalTranslation();
|
CVector3f TotalTranslation();
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include "CModelEditorViewport.h"
|
||||||
|
#include <Core/CDrawUtil.h>
|
||||||
|
|
||||||
|
CModelEditorViewport::CModelEditorViewport(QWidget *pParent)
|
||||||
|
: CBasicViewport(pParent),
|
||||||
|
mMode(eDrawMesh),
|
||||||
|
mpActiveMaterial(nullptr),
|
||||||
|
mpModelNode(nullptr)
|
||||||
|
{
|
||||||
|
mpRenderer = new CRenderer();
|
||||||
|
mpRenderer->SetViewportSize(width(), height());
|
||||||
|
mpRenderer->SetClearColor(CColor::skBlack);
|
||||||
|
mpRenderer->ToggleGrid(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CModelEditorViewport::~CModelEditorViewport()
|
||||||
|
{
|
||||||
|
delete mpRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelEditorViewport::SetNode(CModelNode *pNode)
|
||||||
|
{
|
||||||
|
mpModelNode = pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelEditorViewport::SetActiveMaterial(CMaterial *pMat)
|
||||||
|
{
|
||||||
|
mpActiveMaterial = pMat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelEditorViewport::SetDrawMode(EDrawMode mode)
|
||||||
|
{
|
||||||
|
mMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelEditorViewport::SetClearColor(CColor color)
|
||||||
|
{
|
||||||
|
mpRenderer->SetClearColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelEditorViewport::Paint()
|
||||||
|
{
|
||||||
|
mpRenderer->BeginFrame();
|
||||||
|
mCamera.LoadMatrices();
|
||||||
|
|
||||||
|
if (!mpModelNode->Model())
|
||||||
|
CDrawUtil::DrawGrid();
|
||||||
|
|
||||||
|
else if (mMode == eDrawMesh)
|
||||||
|
{
|
||||||
|
CDrawUtil::DrawGrid();
|
||||||
|
mpModelNode->AddToRenderer(mpRenderer);
|
||||||
|
mpRenderer->RenderBuckets(mCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mMode == eDrawSphere)
|
||||||
|
{
|
||||||
|
if (!mpActiveMaterial) return;
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
CGraphics::sVertexBlock.COLOR0_Amb = CGraphics::skDefaultAmbientColor.ToVector4f();
|
||||||
|
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||||
|
CGraphics::UpdateMVPBlock();
|
||||||
|
CGraphics::SetDefaultLighting();
|
||||||
|
CGraphics::UpdateLightBlock(); // Note: vertex block is updated by the material
|
||||||
|
mpActiveMaterial->SetCurrent(eEnableUVScroll | eEnableBackfaceCull | eEnableOccluders);
|
||||||
|
|
||||||
|
CDrawUtil::DrawSphere(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mMode == eDrawSquare)
|
||||||
|
{
|
||||||
|
if (!mpActiveMaterial) return;
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
CGraphics::SetDefaultLighting();
|
||||||
|
CGraphics::UpdateLightBlock();
|
||||||
|
CGraphics::sVertexBlock.COLOR0_Amb = CGraphics::skDefaultAmbientColor.ToVector4f();
|
||||||
|
|
||||||
|
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||||
|
CGraphics::sMVPBlock.ViewMatrix = CMatrix4f::skIdentity;
|
||||||
|
CGraphics::sMVPBlock.ProjectionMatrix = CMatrix4f::skIdentity;
|
||||||
|
CGraphics::UpdateMVPBlock();
|
||||||
|
|
||||||
|
mpActiveMaterial->SetCurrent(eEnableUVScroll | eEnableOccluders);
|
||||||
|
CDrawUtil::DrawSquare();
|
||||||
|
}
|
||||||
|
|
||||||
|
mpRenderer->EndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelEditorViewport::OnResize()
|
||||||
|
{
|
||||||
|
mpRenderer->SetViewportSize(width(), height());
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef CMODELEDITORVIEWPORT_H
|
||||||
|
#define CMODELEDITORVIEWPORT_H
|
||||||
|
|
||||||
|
#include "CBasicViewport.h"
|
||||||
|
|
||||||
|
class CModelEditorViewport : public CBasicViewport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum EDrawMode {
|
||||||
|
eDrawMesh, eDrawSphere, eDrawSquare
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
EDrawMode mMode;
|
||||||
|
CModelNode *mpModelNode;
|
||||||
|
CMaterial *mpActiveMaterial;
|
||||||
|
CRenderer *mpRenderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CModelEditorViewport(QWidget *pParent = 0);
|
||||||
|
~CModelEditorViewport();
|
||||||
|
void SetNode(CModelNode *pNode);
|
||||||
|
void SetActiveMaterial(CMaterial *pMat);
|
||||||
|
void SetDrawMode(EDrawMode mode);
|
||||||
|
void SetClearColor(CColor color);
|
||||||
|
void Paint();
|
||||||
|
void OnResize();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CMODELEDITORVIEWPORT_H
|
|
@ -33,15 +33,13 @@ CModelEditorWindow::CModelEditorWindow(QWidget *parent) :
|
||||||
mpCurrentPass = nullptr;
|
mpCurrentPass = nullptr;
|
||||||
mIgnoreSignals = false;
|
mIgnoreSignals = false;
|
||||||
|
|
||||||
mpRenderer = new CRenderer();
|
ui->Viewport->SetNode(mpCurrentModelNode);
|
||||||
mpRenderer->ToggleGrid(true);
|
ui->Viewport->SetClearColor(CColor(0.3f, 0.3f, 0.3f, 1.f));
|
||||||
mpRenderer->SetClearColor(CColor(0.3f, 0.3f, 0.3f, 1.f));
|
|
||||||
|
|
||||||
CCamera& Camera = ui->PreviewGLWidget->Camera();
|
CCamera& camera = ui->Viewport->Camera();
|
||||||
Camera.Snap(CVector3f(0, 3, 1));
|
camera.Snap(CVector3f(0, 3, 1));
|
||||||
Camera.SetFree();
|
camera.SetFree();
|
||||||
Camera.SetMoveSpeed(0.5f);
|
camera.SetMoveSpeed(0.5f);
|
||||||
mDrawMode = eDrawMesh;
|
|
||||||
|
|
||||||
// UI initialization
|
// UI initialization
|
||||||
UpdateAnimParamUI(-1);
|
UpdateAnimParamUI(-1);
|
||||||
|
@ -54,8 +52,8 @@ CModelEditorWindow::CModelEditorWindow(QWidget *parent) :
|
||||||
ui->ClearColorPicker->setColor(QColor(76, 76, 76, 255));
|
ui->ClearColorPicker->setColor(QColor(76, 76, 76, 255));
|
||||||
|
|
||||||
// Viewport Signal/Slot setup
|
// Viewport Signal/Slot setup
|
||||||
connect(ui->PreviewGLWidget, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
|
connect(&mRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViewport()));
|
||||||
connect(ui->PreviewGLWidget, SIGNAL(Render(CCamera&)), this, SLOT(PaintViewport(CCamera&)));
|
mRefreshTimer.start(0);
|
||||||
|
|
||||||
// Editor UI Signal/Slot setup
|
// Editor UI Signal/Slot setup
|
||||||
ui->SetSelectionComboBox->setProperty ("ModelEditorWidgetType", eSetSelectComboBox);
|
ui->SetSelectionComboBox->setProperty ("ModelEditorWidgetType", eSetSelectComboBox);
|
||||||
|
@ -139,10 +137,15 @@ CModelEditorWindow::CModelEditorWindow(QWidget *parent) :
|
||||||
CModelEditorWindow::~CModelEditorWindow()
|
CModelEditorWindow::~CModelEditorWindow()
|
||||||
{
|
{
|
||||||
delete mpCurrentModelNode;
|
delete mpCurrentModelNode;
|
||||||
delete mpRenderer;
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CModelEditorWindow::RefreshViewport()
|
||||||
|
{
|
||||||
|
ui->Viewport->ProcessInput();
|
||||||
|
ui->Viewport->Render();
|
||||||
|
}
|
||||||
|
|
||||||
void CModelEditorWindow::SetActiveModel(CModel *pModel)
|
void CModelEditorWindow::SetActiveModel(CModel *pModel)
|
||||||
{
|
{
|
||||||
mpCurrentModelNode->SetModel(pModel);
|
mpCurrentModelNode->SetModel(pModel);
|
||||||
|
@ -194,6 +197,7 @@ void CModelEditorWindow::SetActiveMaterial(int MatIndex)
|
||||||
|
|
||||||
u32 SetIndex = ui->SetSelectionComboBox->currentIndex();
|
u32 SetIndex = ui->SetSelectionComboBox->currentIndex();
|
||||||
mpCurrentMat = mpCurrentModel->GetMaterialByIndex(SetIndex, MatIndex);
|
mpCurrentMat = mpCurrentModel->GetMaterialByIndex(SetIndex, MatIndex);
|
||||||
|
ui->Viewport->SetActiveMaterial(mpCurrentMat);
|
||||||
if (!mpCurrentMat) return;
|
if (!mpCurrentMat) return;
|
||||||
//mpCurrentMat->SetTint(CColor(1.f, 0.5f, 0.5f, 1.f));
|
//mpCurrentMat->SetTint(CColor(1.f, 0.5f, 0.5f, 1.f));
|
||||||
|
|
||||||
|
@ -572,66 +576,6 @@ void CModelEditorWindow::UpdateUI(int Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelEditorWindow::PaintViewport(CCamera& Camera)
|
|
||||||
{
|
|
||||||
mpRenderer->BeginFrame();
|
|
||||||
|
|
||||||
Camera.LoadMatrices();
|
|
||||||
|
|
||||||
if (!mpCurrentModel)
|
|
||||||
{
|
|
||||||
CDrawUtil::DrawGrid();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (mDrawMode == eDrawMesh)
|
|
||||||
{
|
|
||||||
CDrawUtil::DrawGrid();
|
|
||||||
mpCurrentModelNode->AddToRenderer(mpRenderer);
|
|
||||||
mpRenderer->RenderBuckets(Camera);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (mDrawMode == eDrawSphere)
|
|
||||||
{
|
|
||||||
if (!mpCurrentMat) return;
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
CGraphics::sVertexBlock.COLOR0_Amb = CGraphics::skDefaultAmbientColor.ToVector4f();
|
|
||||||
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
|
||||||
CGraphics::UpdateMVPBlock();
|
|
||||||
CGraphics::SetDefaultLighting();
|
|
||||||
CGraphics::UpdateLightBlock(); // Note: vertex block is updated by the material
|
|
||||||
mpCurrentMat->SetCurrent(eEnableUVScroll | eEnableBackfaceCull | eEnableOccluders);
|
|
||||||
|
|
||||||
CDrawUtil::DrawSphere(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (mDrawMode == eDrawSquare)
|
|
||||||
{
|
|
||||||
if (!mpCurrentMat) return;
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
CGraphics::SetDefaultLighting();
|
|
||||||
CGraphics::UpdateLightBlock();
|
|
||||||
CGraphics::sVertexBlock.COLOR0_Amb = CGraphics::skDefaultAmbientColor.ToVector4f();
|
|
||||||
|
|
||||||
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
|
||||||
CGraphics::sMVPBlock.ViewMatrix = CMatrix4f::skIdentity;
|
|
||||||
CGraphics::sMVPBlock.ProjectionMatrix = CMatrix4f::skIdentity;
|
|
||||||
CGraphics::UpdateMVPBlock();
|
|
||||||
|
|
||||||
mpCurrentMat->SetCurrent(eEnableUVScroll | eEnableOccluders);
|
|
||||||
CDrawUtil::DrawSquare();
|
|
||||||
}
|
|
||||||
|
|
||||||
mpRenderer->EndFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CModelEditorWindow::SetViewportSize(int Width, int Height)
|
|
||||||
{
|
|
||||||
mViewportAspectRatio = (float) Width / (float) Height;
|
|
||||||
mpRenderer->SetViewportSize(Width, Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************ PRIVATE ************
|
// ************ PRIVATE ************
|
||||||
void CModelEditorWindow::ActivateMatEditUI(bool Active)
|
void CModelEditorWindow::ActivateMatEditUI(bool Active)
|
||||||
{
|
{
|
||||||
|
@ -793,23 +737,23 @@ void CModelEditorWindow::closeEvent(QCloseEvent*)
|
||||||
|
|
||||||
void CModelEditorWindow::on_MeshPreviewButton_clicked()
|
void CModelEditorWindow::on_MeshPreviewButton_clicked()
|
||||||
{
|
{
|
||||||
mDrawMode = eDrawMesh;
|
ui->Viewport->SetDrawMode(CModelEditorViewport::eDrawMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelEditorWindow::on_SpherePreviewButton_clicked()
|
void CModelEditorWindow::on_SpherePreviewButton_clicked()
|
||||||
{
|
{
|
||||||
mDrawMode = eDrawSphere;
|
ui->Viewport->SetDrawMode(CModelEditorViewport::eDrawSphere);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelEditorWindow::on_FlatPreviewButton_clicked()
|
void CModelEditorWindow::on_FlatPreviewButton_clicked()
|
||||||
{
|
{
|
||||||
mDrawMode = eDrawSquare;
|
ui->Viewport->SetDrawMode(CModelEditorViewport::eDrawSquare);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelEditorWindow::on_ClearColorPicker_colorChanged(const QColor &Color)
|
void CModelEditorWindow::on_ClearColorPicker_colorChanged(const QColor &Color)
|
||||||
{
|
{
|
||||||
CColor NewColor((u8) Color.red(), (u8) Color.green(), (u8) Color.blue(), 255);
|
CColor NewColor((u8) Color.red(), (u8) Color.green(), (u8) Color.blue(), 255);
|
||||||
mpRenderer->SetClearColor(NewColor);
|
ui->Viewport->SetClearColor(NewColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelEditorWindow::on_actionImport_triggered()
|
void CModelEditorWindow::on_actionImport_triggered()
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include <Resource/CFont.h>
|
#include <Resource/CFont.h>
|
||||||
#include <Resource/model/CModel.h>
|
#include <Resource/model/CModel.h>
|
||||||
#include <Scene/CModelNode.h>
|
#include <Scene/CModelNode.h>
|
||||||
|
#include <QTimer>
|
||||||
|
#include "CModelEditorViewport.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class CModelEditorWindow;
|
class CModelEditorWindow;
|
||||||
|
@ -18,12 +20,7 @@ class CModelEditorWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
enum EDrawMode {
|
|
||||||
eDrawMesh, eDrawSphere, eDrawSquare
|
|
||||||
};
|
|
||||||
|
|
||||||
Ui::CModelEditorWindow *ui;
|
Ui::CModelEditorWindow *ui;
|
||||||
CRenderer *mpRenderer;
|
|
||||||
CSceneManager *mpScene;
|
CSceneManager *mpScene;
|
||||||
QString mOutputFilename;
|
QString mOutputFilename;
|
||||||
CModel *mpCurrentModel;
|
CModel *mpCurrentModel;
|
||||||
|
@ -32,8 +29,7 @@ class CModelEditorWindow : public QMainWindow
|
||||||
CMaterial *mpCurrentMat;
|
CMaterial *mpCurrentMat;
|
||||||
CMaterialPass *mpCurrentPass;
|
CMaterialPass *mpCurrentPass;
|
||||||
bool mIgnoreSignals;
|
bool mIgnoreSignals;
|
||||||
EDrawMode mDrawMode;
|
QTimer mRefreshTimer;
|
||||||
float mViewportAspectRatio;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CModelEditorWindow(QWidget *parent = 0);
|
explicit CModelEditorWindow(QWidget *parent = 0);
|
||||||
|
@ -42,6 +38,7 @@ public:
|
||||||
void closeEvent(QCloseEvent *pEvent);
|
void closeEvent(QCloseEvent *pEvent);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void RefreshViewport();
|
||||||
void SetActiveMaterial(int MatIndex);
|
void SetActiveMaterial(int MatIndex);
|
||||||
void SetActivePass(int PassIndex);
|
void SetActivePass(int PassIndex);
|
||||||
void UpdateMaterial();
|
void UpdateMaterial();
|
||||||
|
@ -52,8 +49,6 @@ public slots:
|
||||||
void UpdateMaterial(QColor eColorProperty);
|
void UpdateMaterial(QColor eColorProperty);
|
||||||
void UpdateUI(int Value);
|
void UpdateUI(int Value);
|
||||||
void UpdateAnimParamUI(int Mode);
|
void UpdateAnimParamUI(int Mode);
|
||||||
void PaintViewport(CCamera& Camera);
|
|
||||||
void SetViewportSize(int Width, int Height);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ActivateMatEditUI(bool Active);
|
void ActivateMatEditUI(bool Active);
|
||||||
|
|
|
@ -2124,7 +2124,7 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="CEditorGLWidget" name="PreviewGLWidget" native="true">
|
<widget class="CModelEditorViewport" name="Viewport" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
<horstretch>250</horstretch>
|
<horstretch>250</horstretch>
|
||||||
|
@ -2480,6 +2480,11 @@
|
||||||
</action>
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>WDraggableSpinBox</class>
|
||||||
|
<extends>QDoubleSpinBox</extends>
|
||||||
|
<header>WDraggableSpinBox.h</header>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>WColorPicker</class>
|
<class>WColorPicker</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
|
@ -2496,16 +2501,11 @@
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>CEditorGLWidget</class>
|
<class>CModelEditorViewport</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>CEditorGLWidget.h</header>
|
<header>CModelEditorViewport.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>WDraggableSpinBox</class>
|
|
||||||
<extends>QDoubleSpinBox</extends>
|
|
||||||
<header>WDraggableSpinBox.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../Icons.qrc"/>
|
<include location="../Icons.qrc"/>
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
#include "CSceneViewport.h"
|
||||||
|
#include "undo/UndoCommands.h"
|
||||||
|
|
||||||
|
CSceneViewport::CSceneViewport(QWidget *pParent)
|
||||||
|
: CBasicViewport(pParent),
|
||||||
|
mpEditor(nullptr),
|
||||||
|
mpScene(nullptr),
|
||||||
|
mDrawSky(true),
|
||||||
|
mGizmoTransforming(false),
|
||||||
|
mpHoverNode(nullptr),
|
||||||
|
mHoverPoint(CVector3f::skZero)
|
||||||
|
{
|
||||||
|
mpRenderer = new CRenderer();
|
||||||
|
mpRenderer->SetClearColor(CColor::skBlack);
|
||||||
|
mpRenderer->SetViewportSize(width(), height());
|
||||||
|
}
|
||||||
|
|
||||||
|
CSceneViewport::~CSceneViewport()
|
||||||
|
{
|
||||||
|
delete mpRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::SetScene(INodeEditor *pEditor, CSceneManager *pScene)
|
||||||
|
{
|
||||||
|
mpEditor = pEditor;
|
||||||
|
mpScene = pScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::SetSkyEnabled(bool b)
|
||||||
|
{
|
||||||
|
mDrawSky = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRenderer* CSceneViewport::Renderer()
|
||||||
|
{
|
||||||
|
return mpRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSceneNode* CSceneViewport::HoverNode()
|
||||||
|
{
|
||||||
|
return mpHoverNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector3f CSceneViewport::HoverPoint()
|
||||||
|
{
|
||||||
|
return mHoverPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::CheckGizmoInput(const CRay& ray)
|
||||||
|
{
|
||||||
|
CGizmo *pGizmo = mpEditor->Gizmo();
|
||||||
|
|
||||||
|
// Gizmo not transforming: Check for gizmo hover
|
||||||
|
if (!pGizmo->IsTransforming())
|
||||||
|
{
|
||||||
|
if (mpEditor->IsGizmoVisible())
|
||||||
|
mGizmoHovering = pGizmo->CheckSelectedAxes(ray);
|
||||||
|
else
|
||||||
|
mGizmoHovering = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gizmo transforming: Run gizmo input with ray/mouse coords
|
||||||
|
else if (mGizmoTransforming)
|
||||||
|
{
|
||||||
|
bool transformed = pGizmo->TransformFromInput(ray, mCamera);
|
||||||
|
if (transformed) emit GizmoMoved();
|
||||||
|
}
|
||||||
|
|
||||||
|
else mGizmoHovering = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::SceneRayCast(const CRay& ray)
|
||||||
|
{
|
||||||
|
if (mpEditor->Gizmo()->IsTransforming())
|
||||||
|
{
|
||||||
|
ResetHover();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRayIntersection result = mpScene->SceneRayCast(ray);
|
||||||
|
|
||||||
|
if (result.Hit)
|
||||||
|
{
|
||||||
|
if (mpHoverNode)
|
||||||
|
mpHoverNode->SetMouseHovering(false);
|
||||||
|
|
||||||
|
mpHoverNode = result.pNode;
|
||||||
|
mpHoverNode->SetMouseHovering(true);
|
||||||
|
mHoverPoint = ray.PointOnRay(result.Distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
ResetHover();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::ResetHover()
|
||||||
|
{
|
||||||
|
if (mpHoverNode) mpHoverNode->SetMouseHovering(false);
|
||||||
|
mpHoverNode = nullptr;
|
||||||
|
mHoverPoint = CVector3f::skZero;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSceneViewport::IsHoveringGizmo()
|
||||||
|
{
|
||||||
|
return mGizmoHovering;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ PROTECTED SLOTS ************
|
||||||
|
void CSceneViewport::CheckUserInput()
|
||||||
|
{
|
||||||
|
if (!underMouse() || IsMouseInputActive())
|
||||||
|
{
|
||||||
|
ResetHover();
|
||||||
|
mGizmoHovering = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRay ray = CastRay();
|
||||||
|
CheckGizmoInput(ray);
|
||||||
|
|
||||||
|
if (!mpEditor->Gizmo()->IsTransforming())
|
||||||
|
SceneRayCast(ray);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::Paint()
|
||||||
|
{
|
||||||
|
if (!mpScene) return;
|
||||||
|
|
||||||
|
mpRenderer->BeginFrame();
|
||||||
|
|
||||||
|
if (mDrawSky)
|
||||||
|
{
|
||||||
|
CModel *pSky = mpScene->GetActiveSkybox();
|
||||||
|
if (pSky) mpRenderer->RenderSky(pSky, mCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
mCamera.LoadMatrices();
|
||||||
|
mpScene->AddSceneToRenderer(mpRenderer);
|
||||||
|
mpRenderer->RenderBuckets(mCamera);
|
||||||
|
mpRenderer->RenderBloom();
|
||||||
|
|
||||||
|
if (mpEditor->IsGizmoVisible())
|
||||||
|
{
|
||||||
|
CGizmo *pGizmo = mpEditor->Gizmo();
|
||||||
|
mCamera.LoadMatrices();
|
||||||
|
|
||||||
|
mpRenderer->ClearDepthBuffer();
|
||||||
|
pGizmo->UpdateForCamera(mCamera);
|
||||||
|
pGizmo->AddToRenderer(mpRenderer);
|
||||||
|
mpRenderer->RenderBuckets(mCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpRenderer->EndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::ContextMenu(QContextMenuEvent *pEvent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::OnResize()
|
||||||
|
{
|
||||||
|
mpRenderer->SetViewportSize(width(), height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::OnMouseClick(QMouseEvent *pEvent)
|
||||||
|
{
|
||||||
|
bool altPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
||||||
|
bool ctrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
||||||
|
|
||||||
|
if (mGizmoHovering && !altPressed && !ctrlPressed)
|
||||||
|
{
|
||||||
|
mGizmoTransforming = true;
|
||||||
|
mpEditor->Gizmo()->StartTransform();
|
||||||
|
mpEditor->BeginGizmoTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneViewport::OnMouseRelease(QMouseEvent *pEvent)
|
||||||
|
{
|
||||||
|
if (pEvent->button() == Qt::LeftButton)
|
||||||
|
{
|
||||||
|
// Stop gizmo transform
|
||||||
|
if (mGizmoTransforming)
|
||||||
|
{
|
||||||
|
CGizmo *pGizmo = mpEditor->Gizmo();
|
||||||
|
pGizmo->EndTransform();
|
||||||
|
mpEditor->EndGizmoTransform();
|
||||||
|
mGizmoTransforming = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object selection/deselection
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool validNode = (mpHoverNode && (mpHoverNode->NodeType() != eStaticNode));
|
||||||
|
bool altPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
||||||
|
bool ctrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
||||||
|
|
||||||
|
// Alt: Deselect
|
||||||
|
if (altPressed)
|
||||||
|
{
|
||||||
|
if (!validNode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mpEditor->DeselectNode(mpHoverNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ctrl: Add to selection
|
||||||
|
else if (ctrlPressed)
|
||||||
|
{
|
||||||
|
if (validNode)
|
||||||
|
mpEditor->SelectNode(mpHoverNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neither: clear selection + select
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!mGizmoHovering)
|
||||||
|
{
|
||||||
|
if (validNode)
|
||||||
|
mpEditor->ClearAndSelectNode(mpHoverNode);
|
||||||
|
else
|
||||||
|
mpEditor->ClearSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->UpdateSelectionUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef CSCENEVIEWPORT_H
|
||||||
|
#define CSCENEVIEWPORT_H
|
||||||
|
|
||||||
|
#include "CBasicViewport.h"
|
||||||
|
#include "INodeEditor.h"
|
||||||
|
|
||||||
|
class CSceneViewport : public CBasicViewport
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
INodeEditor *mpEditor;
|
||||||
|
CSceneManager *mpScene;
|
||||||
|
CRenderer *mpRenderer;
|
||||||
|
|
||||||
|
// Render settings
|
||||||
|
bool mDrawSky;
|
||||||
|
|
||||||
|
// Scene interaction
|
||||||
|
bool mGizmoHovering;
|
||||||
|
bool mGizmoTransforming;
|
||||||
|
CSceneNode *mpHoverNode;
|
||||||
|
CVector3f mHoverPoint;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CSceneViewport(QWidget *pParent = 0);
|
||||||
|
~CSceneViewport();
|
||||||
|
void SetScene(INodeEditor *pEditor, CSceneManager *pScene);
|
||||||
|
void SetSkyEnabled(bool b);
|
||||||
|
CRenderer* Renderer();
|
||||||
|
CSceneNode* HoverNode();
|
||||||
|
CVector3f HoverPoint();
|
||||||
|
void CheckGizmoInput(const CRay& ray);
|
||||||
|
void SceneRayCast(const CRay& ray);
|
||||||
|
void ResetHover();
|
||||||
|
bool IsHoveringGizmo();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void GizmoMoved();
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void CheckUserInput();
|
||||||
|
void Paint();
|
||||||
|
void ContextMenu(QContextMenuEvent *pEvent);
|
||||||
|
void OnResize();
|
||||||
|
void OnMouseClick(QMouseEvent *pEvent);
|
||||||
|
void OnMouseRelease(QMouseEvent *pEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CSCENEVIEWPORT_H
|
|
@ -1,6 +1,6 @@
|
||||||
#include "CWorldEditor.h"
|
#include "CWorldEditor.h"
|
||||||
#include "ui_CWorldEditor.h"
|
#include "ui_CWorldEditor.h"
|
||||||
#include "CEditorGLWidget.h"
|
#include "CBasicViewport.h"
|
||||||
#include <gtc/matrix_transform.hpp>
|
#include <gtc/matrix_transform.hpp>
|
||||||
#include <Core/CDrawUtil.h>
|
#include <Core/CDrawUtil.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -10,36 +10,27 @@
|
||||||
#include <Core/Log.h>
|
#include <Core/Log.h>
|
||||||
#include "WDraggableSpinBox.h"
|
#include "WDraggableSpinBox.h"
|
||||||
#include "WVectorEditor.h"
|
#include "WVectorEditor.h"
|
||||||
|
#include "undo/UndoCommands.h"
|
||||||
|
|
||||||
#include "WorldEditor/CLayerEditor.h"
|
#include "WorldEditor/CLayerEditor.h"
|
||||||
#include "WorldEditor/WModifyTab.h"
|
#include "WorldEditor/WModifyTab.h"
|
||||||
#include "WorldEditor/WInstancesTab.h"
|
#include "WorldEditor/WInstancesTab.h"
|
||||||
|
|
||||||
CWorldEditor::CWorldEditor(QWidget *parent) :
|
CWorldEditor::CWorldEditor(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
INodeEditor(parent),
|
||||||
ui(new Ui::CWorldEditor)
|
ui(new Ui::CWorldEditor)
|
||||||
{
|
{
|
||||||
Log::Write("Creating World Editor");
|
Log::Write("Creating World Editor");
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
mpRenderer = new CRenderer();
|
|
||||||
mpRenderer->SetClearColor(CColor::skBlack);
|
|
||||||
QSize ViewSize = ui->MainViewport->size();
|
|
||||||
mpRenderer->SetViewportSize(ViewSize.width(), ViewSize.height());
|
|
||||||
|
|
||||||
mpSceneManager = new CSceneManager();
|
|
||||||
|
|
||||||
mpArea = nullptr;
|
mpArea = nullptr;
|
||||||
mpWorld = nullptr;
|
mpWorld = nullptr;
|
||||||
mpHoverNode = nullptr;
|
|
||||||
mDrawSky = true;
|
|
||||||
mShowGizmo = false;
|
|
||||||
mGizmoHovering = false;
|
mGizmoHovering = false;
|
||||||
mGizmoTransforming = false;
|
mGizmoTransforming = false;
|
||||||
mGizmoUIOutdated = true;
|
|
||||||
|
|
||||||
mFrameCount = 0;
|
// Start refresh timer
|
||||||
mFPSTimer.Start();
|
connect(&mRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViewport()));
|
||||||
|
mRefreshTimer.start(0);
|
||||||
|
|
||||||
// Create blank title bar with some space to allow for dragging the dock
|
// Create blank title bar with some space to allow for dragging the dock
|
||||||
QWidget *pOldTitleBar = ui->MainDock->titleBarWidget();
|
QWidget *pOldTitleBar = ui->MainDock->titleBarWidget();
|
||||||
|
@ -53,38 +44,28 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
||||||
delete pOldTitleBar;
|
delete pOldTitleBar;
|
||||||
|
|
||||||
// Initialize UI stuff
|
// Initialize UI stuff
|
||||||
|
ui->MainViewport->SetScene(this, &mScene);
|
||||||
ui->ModifyTabContents->SetEditor(this);
|
ui->ModifyTabContents->SetEditor(this);
|
||||||
ui->InstancesTabContents->SetEditor(this, mpSceneManager);
|
ui->InstancesTabContents->SetEditor(this, &mScene);
|
||||||
ui->MainDock->installEventFilter(this);
|
ui->MainDock->installEventFilter(this);
|
||||||
ui->TransformSpinBox->SetOrientation(Qt::Horizontal);
|
ui->TransformSpinBox->SetOrientation(Qt::Horizontal);
|
||||||
ui->TransformSpinBox->layout()->setContentsMargins(0,0,0,0);
|
ui->TransformSpinBox->layout()->setContentsMargins(0,0,0,0);
|
||||||
ui->CamSpeedSpinBox->SetDefaultValue(1.0);
|
ui->CamSpeedSpinBox->SetDefaultValue(1.0);
|
||||||
ResetHover();
|
|
||||||
|
|
||||||
mTranslateSpace = eWorldTransform;
|
mpTransformCombo->setMinimumWidth(75);
|
||||||
mRotateSpace = eWorldTransform;
|
ui->MainToolBar->addActions(mGizmoActions);
|
||||||
|
ui->MainToolBar->addWidget(mpTransformCombo);
|
||||||
mpTransformSpaceComboBox = new QComboBox(this);
|
ui->menuEdit->addActions(mUndoActions);
|
||||||
mpTransformSpaceComboBox->setMinimumWidth(75);
|
|
||||||
mpTransformSpaceComboBox->addItem("World");
|
|
||||||
mpTransformSpaceComboBox->addItem("Local");
|
|
||||||
ui->MainToolBar->insertWidget(0, mpTransformSpaceComboBox);
|
|
||||||
|
|
||||||
// Initialize offscreen actions
|
// Initialize offscreen actions
|
||||||
addAction(ui->ActionIncrementGizmo);
|
addAction(ui->ActionIncrementGizmo);
|
||||||
addAction(ui->ActionDecrementGizmo);
|
addAction(ui->ActionDecrementGizmo);
|
||||||
|
|
||||||
// Connect signals and slots
|
// Connect signals and slots
|
||||||
connect(ui->TransformSpinBox, SIGNAL(EditingDone(CVector3f)), this, SLOT(OnTransformSpinBoxEdited(CVector3f)));
|
connect(ui->MainViewport, SIGNAL(GizmoMoved()), this, SLOT(OnGizmoMoved()));
|
||||||
connect(ui->TransformSpinBox, SIGNAL(ValueChanged(CVector3f)), this, SLOT(OnTransformSpinBoxModified(CVector3f)));
|
connect(ui->TransformSpinBox, SIGNAL(ValueChanged(CVector3f)), this, SLOT(OnTransformSpinBoxModified(CVector3f)));
|
||||||
connect(mpTransformSpaceComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SetTransformSpace(int)));
|
connect(ui->TransformSpinBox, SIGNAL(EditingDone(CVector3f)), this, SLOT(OnTransformSpinBoxEdited(CVector3f)));
|
||||||
connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double)));
|
connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double)));
|
||||||
connect(ui->MainViewport, SIGNAL(PreRender()), this, SLOT(ViewportPreRender()));
|
|
||||||
connect(ui->MainViewport, SIGNAL(Render(CCamera&)), this, SLOT(ViewportRender(CCamera&)));
|
|
||||||
connect(ui->MainViewport, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
|
|
||||||
connect(ui->MainViewport, SIGNAL(frameSwapped()), this, SLOT(ViewportPostRender()));
|
|
||||||
connect(ui->MainViewport, SIGNAL(MouseClick(QMouseEvent*)), this, SLOT(ViewportMouseClick(QMouseEvent*)));
|
|
||||||
connect(ui->MainViewport, SIGNAL(MouseRelease(QMouseEvent*)), this, SLOT(ViewportMouseRelease(QMouseEvent*)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CWorldEditor::~CWorldEditor()
|
CWorldEditor::~CWorldEditor()
|
||||||
|
@ -107,7 +88,7 @@ bool CWorldEditor::eventFilter(QObject *pObj, QEvent *pEvent)
|
||||||
|
|
||||||
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
||||||
{
|
{
|
||||||
ResetHover();
|
ui->MainViewport->ResetHover();
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
ui->ModifyTabContents->ClearUI();
|
ui->ModifyTabContents->ClearUI();
|
||||||
ui->ModifyTabContents->ClearCachedEditors();
|
ui->ModifyTabContents->ClearCachedEditors();
|
||||||
|
@ -124,8 +105,8 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
||||||
mAreaToken = CToken(pArea);
|
mAreaToken = CToken(pArea);
|
||||||
mWorldToken = CToken(pWorld);
|
mWorldToken = CToken(pWorld);
|
||||||
|
|
||||||
mpSceneManager->SetActiveWorld(pWorld);
|
mScene.SetActiveWorld(pWorld);
|
||||||
mpSceneManager->SetActiveArea(pArea);
|
mScene.SetActiveArea(pArea);
|
||||||
|
|
||||||
// Snap camera to location of area
|
// Snap camera to location of area
|
||||||
CTransform4f AreaTransform = pArea->GetTransform();
|
CTransform4f AreaTransform = pArea->GetTransform();
|
||||||
|
@ -150,350 +131,21 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
||||||
ui->InstancesTabContents->SetMaster(pMaster);
|
ui->InstancesTabContents->SetMaster(pMaster);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::ViewportRayCast()
|
|
||||||
{
|
|
||||||
if (!ui->MainViewport->IsMouseInputActive())
|
|
||||||
{
|
|
||||||
// Cast ray
|
|
||||||
CVector2f mouseCoords = ui->MainViewport->MouseDeviceCoordinates();
|
|
||||||
CCamera camera = ui->MainViewport->Camera();
|
|
||||||
CRay ray = camera.CastRay(mouseCoords);
|
|
||||||
|
|
||||||
if (!mGizmoTransforming)
|
|
||||||
{
|
|
||||||
// Gizmo hover check
|
|
||||||
if (mShowGizmo && !mSelectedNodes.empty())
|
|
||||||
mGizmoHovering = mGizmo.CheckSelectedAxes(ray);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mGizmoHovering = false;
|
|
||||||
mGizmo.ResetSelectedAxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scene ray check
|
|
||||||
SRayIntersection Result = mpSceneManager->SceneRayCast(ray);
|
|
||||||
|
|
||||||
if (Result.Hit)
|
|
||||||
{
|
|
||||||
if (mpHoverNode)
|
|
||||||
mpHoverNode->SetMouseHovering(false);
|
|
||||||
|
|
||||||
mpHoverNode = Result.pNode;
|
|
||||||
mpHoverNode->SetMouseHovering(true);
|
|
||||||
|
|
||||||
mHoverPoint = ray.PointOnRay(Result.Distance);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ResetHover();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool transformed = mGizmo.TransformFromInput(ray, ui->MainViewport->Camera());
|
|
||||||
|
|
||||||
if (transformed)
|
|
||||||
{
|
|
||||||
switch (mGizmo.Mode())
|
|
||||||
{
|
|
||||||
case CGizmo::eTranslate:
|
|
||||||
{
|
|
||||||
CVector3f delta = mGizmo.DeltaTranslation();
|
|
||||||
|
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
|
||||||
{
|
|
||||||
(*it)->Translate(delta, mTranslateSpace);
|
|
||||||
(*it)->BuildLightList(this->mpArea);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case CGizmo::eRotate:
|
|
||||||
{
|
|
||||||
CQuaternion delta = mGizmo.DeltaRotation();
|
|
||||||
|
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
|
||||||
(*it)->Rotate(delta, mRotateSpace);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case CGizmo::eScale:
|
|
||||||
{
|
|
||||||
CVector3f delta = mGizmo.DeltaScale();
|
|
||||||
|
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
|
||||||
(*it)->Scale(delta);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RecalculateSelectionBounds();
|
|
||||||
mGizmoUIOutdated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!mGizmoTransforming)
|
|
||||||
{
|
|
||||||
mGizmoHovering = false;
|
|
||||||
mGizmo.ResetSelectedAxes();
|
|
||||||
}
|
|
||||||
ResetHover();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CRenderer* CWorldEditor::Renderer()
|
|
||||||
{
|
|
||||||
return mpRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSceneManager* CWorldEditor::Scene()
|
|
||||||
{
|
|
||||||
return mpSceneManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGameArea* CWorldEditor::ActiveArea()
|
CGameArea* CWorldEditor::ActiveArea()
|
||||||
{
|
{
|
||||||
return mpArea;
|
return mpArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ SELECTION ************
|
|
||||||
void CWorldEditor::SelectNode(CSceneNode *pNode)
|
|
||||||
{
|
|
||||||
if (!pNode->IsSelected())
|
|
||||||
{
|
|
||||||
pNode->SetSelected(true);
|
|
||||||
mSelectedNodes.push_back(pNode);
|
|
||||||
mSelectionAABox.ExpandBounds(pNode->AABox());
|
|
||||||
|
|
||||||
if (pNode->NodeType() == eScriptNode)
|
|
||||||
{
|
|
||||||
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
|
||||||
if (pScript->HasPreviewVolume())
|
|
||||||
mSelectionAABox.ExpandBounds(pScript->PreviewVolumeAABox());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateSelectionUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::DeselectNode(CSceneNode *pNode)
|
|
||||||
{
|
|
||||||
if (pNode->IsSelected())
|
|
||||||
{
|
|
||||||
pNode->SetSelected(false);
|
|
||||||
|
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
|
||||||
{
|
|
||||||
if (*it == pNode)
|
|
||||||
{
|
|
||||||
mSelectedNodes.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RecalculateSelectionBounds();
|
|
||||||
UpdateSelectionUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::ClearSelection()
|
|
||||||
{
|
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
|
||||||
(*it)->SetSelected(false);
|
|
||||||
|
|
||||||
mSelectedNodes.clear();
|
|
||||||
mSelectionAABox = CAABox::skInfinite;
|
|
||||||
UpdateSelectionUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************ SLOTS ************
|
// ************ SLOTS ************
|
||||||
void CWorldEditor::ViewportMouseDrag(QMouseEvent *pEvent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::ViewportMouseClick(QMouseEvent *pEvent)
|
|
||||||
{
|
|
||||||
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
|
||||||
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
|
||||||
|
|
||||||
if (mGizmoHovering && !AltPressed && !CtrlPressed)
|
|
||||||
{
|
|
||||||
mGizmoTransforming = true;
|
|
||||||
mGizmo.StartTransform();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::ViewportMouseRelease(QMouseEvent *pEvent)
|
|
||||||
{
|
|
||||||
if (pEvent->button() == Qt::LeftButton)
|
|
||||||
{
|
|
||||||
// Gizmo transform stop
|
|
||||||
if (mGizmoTransforming)
|
|
||||||
{
|
|
||||||
mGizmo.EndTransform();
|
|
||||||
mGizmoTransforming = false;
|
|
||||||
mGizmoUIOutdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Object selection/deselection
|
|
||||||
else if (!ui->MainViewport->IsMouseInputActive())
|
|
||||||
{
|
|
||||||
bool ValidNode = ((mpHoverNode) && (mpHoverNode->NodeType() != eStaticNode));
|
|
||||||
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
|
||||||
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
|
||||||
|
|
||||||
// Alt pressed - deselect object
|
|
||||||
if (AltPressed)
|
|
||||||
{
|
|
||||||
// No valid node selected - do nothing
|
|
||||||
if (!ValidNode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DeselectNode(mpHoverNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ctrl pressed - add object to selection
|
|
||||||
else if (CtrlPressed)
|
|
||||||
{
|
|
||||||
// Add hover node to selection
|
|
||||||
if (ValidNode)
|
|
||||||
SelectNode(mpHoverNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neither pressed
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the gizmo isn't under the mouse, clear existing selection + select object (if applicable)
|
|
||||||
if (!mGizmoHovering)
|
|
||||||
{
|
|
||||||
ClearSelection();
|
|
||||||
|
|
||||||
if (ValidNode)
|
|
||||||
SelectNode(mpHoverNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateSelectionUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: context menu creation on right-click goes here
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************ SLOTS ************
|
|
||||||
void CWorldEditor::ViewportPreRender()
|
|
||||||
{
|
|
||||||
// Perform raycast
|
|
||||||
if (ui->MainViewport->underMouse())
|
|
||||||
ViewportRayCast();
|
|
||||||
else
|
|
||||||
ResetHover();
|
|
||||||
|
|
||||||
// Start frame
|
|
||||||
mFrameTimer.Start();
|
|
||||||
mpRenderer->BeginFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::ViewportRender(CCamera& Camera)
|
|
||||||
{
|
|
||||||
mpSceneManager->AddSceneToRenderer(mpRenderer);
|
|
||||||
|
|
||||||
if (mDrawSky)
|
|
||||||
{
|
|
||||||
CModel *pSky = mpSceneManager->GetActiveSkybox();
|
|
||||||
if (pSky) mpRenderer->RenderSky(pSky, Camera);
|
|
||||||
}
|
|
||||||
|
|
||||||
Camera.LoadMatrices();
|
|
||||||
mpRenderer->RenderBuckets(Camera);
|
|
||||||
mpRenderer->RenderBloom();
|
|
||||||
|
|
||||||
if (mShowGizmo && (mSelectedNodes.size() > 0))
|
|
||||||
{
|
|
||||||
mpRenderer->ClearDepthBuffer();
|
|
||||||
|
|
||||||
Camera.LoadMatrices();
|
|
||||||
mGizmo.UpdateForCamera(Camera);
|
|
||||||
mGizmo.AddToRenderer(mpRenderer);
|
|
||||||
|
|
||||||
mpRenderer->RenderBuckets(Camera);
|
|
||||||
mpRenderer->ClearDepthBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
mpRenderer->EndFrame();
|
|
||||||
mFrameTimer.Stop();
|
|
||||||
mFrameCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::ViewportPostRender()
|
|
||||||
{
|
|
||||||
// Update UI with raycast results
|
|
||||||
UpdateCursor();
|
|
||||||
UpdateStatusBar();
|
|
||||||
|
|
||||||
if (mGizmoUIOutdated) UpdateGizmoUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::SetViewportSize(int Width, int Height)
|
|
||||||
{
|
|
||||||
mpRenderer->SetViewportSize(Width, Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::SetTransformSpace(int space)
|
|
||||||
{
|
|
||||||
if (mGizmo.Mode() == CGizmo::eScale) return;
|
|
||||||
ETransformSpace& transformSpace = (mGizmo.Mode() == CGizmo::eTranslate ? mTranslateSpace : mRotateSpace);
|
|
||||||
|
|
||||||
switch (space)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
transformSpace = eWorldTransform;
|
|
||||||
mGizmo.SetLocalRotation(CQuaternion::skIdentity);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
transformSpace = eLocalTransform;
|
|
||||||
if (!mSelectedNodes.empty())
|
|
||||||
mGizmo.SetLocalRotation(mSelectedNodes.front()->AbsoluteRotation());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mGizmo.SetTransformSpace(transformSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************ PRIVATE ************
|
|
||||||
void CWorldEditor::RecalculateSelectionBounds()
|
|
||||||
{
|
|
||||||
mSelectionAABox = CAABox::skInfinite;
|
|
||||||
|
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
|
||||||
{
|
|
||||||
mSelectionAABox.ExpandBounds( (*it)->AABox() );
|
|
||||||
|
|
||||||
if ((*it)->NodeType() == eScriptNode)
|
|
||||||
{
|
|
||||||
CScriptNode *pScript = static_cast<CScriptNode*>(*it);
|
|
||||||
if (pScript->HasPreviewVolume())
|
|
||||||
mSelectionAABox.ExpandBounds(pScript->PreviewVolumeAABox());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::ResetHover()
|
|
||||||
{
|
|
||||||
if (mpHoverNode) mpHoverNode->SetMouseHovering(false);
|
|
||||||
mpHoverNode = nullptr;
|
|
||||||
mHoverPoint = CVector3f::skZero;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::UpdateCursor()
|
void CWorldEditor::UpdateCursor()
|
||||||
{
|
{
|
||||||
if (ui->MainViewport->IsCursorVisible())
|
if (ui->MainViewport->IsCursorVisible())
|
||||||
{
|
{
|
||||||
if (mGizmoHovering)
|
CSceneNode *pHoverNode = ui->MainViewport->HoverNode();
|
||||||
|
|
||||||
|
if (ui->MainViewport->IsHoveringGizmo())
|
||||||
ui->MainViewport->SetCursorState(Qt::SizeAllCursor);
|
ui->MainViewport->SetCursorState(Qt::SizeAllCursor);
|
||||||
else if ((mpHoverNode) && (mpHoverNode->NodeType() != eStaticNode))
|
else if ((pHoverNode) && (pHoverNode->NodeType() != eStaticNode))
|
||||||
ui->MainViewport->SetCursorState(Qt::PointingHandCursor);
|
ui->MainViewport->SetCursorState(Qt::PointingHandCursor);
|
||||||
else
|
else
|
||||||
ui->MainViewport->SetCursorState(Qt::ArrowCursor);
|
ui->MainViewport->SetCursorState(Qt::ArrowCursor);
|
||||||
|
@ -505,10 +157,15 @@ void CWorldEditor::UpdateStatusBar()
|
||||||
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.
|
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.
|
||||||
QString StatusText = "";
|
QString StatusText = "";
|
||||||
|
|
||||||
if (!mGizmoHovering && mpHoverNode)
|
if (!mGizmoHovering)
|
||||||
{
|
{
|
||||||
if (mpHoverNode->NodeType() != eStaticNode)
|
if (ui->MainViewport->underMouse())
|
||||||
StatusText = QString::fromStdString(mpHoverNode->Name());
|
{
|
||||||
|
CSceneNode *pHoverNode = ui->MainViewport->HoverNode();
|
||||||
|
|
||||||
|
if (pHoverNode && (pHoverNode->NodeType() != eStaticNode))
|
||||||
|
StatusText = QString::fromStdString(pHoverNode->Name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ui->statusbar->currentMessage() != StatusText)
|
if (ui->statusbar->currentMessage() != StatusText)
|
||||||
|
@ -518,15 +175,15 @@ void CWorldEditor::UpdateStatusBar()
|
||||||
void CWorldEditor::UpdateSelectionUI()
|
void CWorldEditor::UpdateSelectionUI()
|
||||||
{
|
{
|
||||||
// Update sidebar
|
// Update sidebar
|
||||||
ui->ModifyTabContents->GenerateUI(mSelectedNodes);
|
ui->ModifyTabContents->GenerateUI(mSelection);
|
||||||
|
|
||||||
// Update selection info text
|
// Update selection info text
|
||||||
QString SelectionText;
|
QString SelectionText;
|
||||||
|
|
||||||
if (mSelectedNodes.size() == 1)
|
if (mSelection.size() == 1)
|
||||||
SelectionText = QString::fromStdString(mSelectedNodes.front()->Name());
|
SelectionText = QString::fromStdString(mSelection.front()->Name());
|
||||||
else if (mSelectedNodes.size() > 1)
|
else if (mSelection.size() > 1)
|
||||||
SelectionText = QString("%1 objects selected").arg(mSelectedNodes.size());
|
SelectionText = QString("%1 objects selected").arg(mSelection.size());
|
||||||
|
|
||||||
QFontMetrics Metrics(ui->SelectionInfoLabel->font());
|
QFontMetrics Metrics(ui->SelectionInfoLabel->font());
|
||||||
SelectionText = Metrics.elidedText(SelectionText, Qt::ElideRight, ui->SelectionInfoFrame->width() - 10);
|
SelectionText = Metrics.elidedText(SelectionText, Qt::ElideRight, ui->SelectionInfoFrame->width() - 10);
|
||||||
|
@ -552,26 +209,26 @@ void CWorldEditor::UpdateGizmoUI()
|
||||||
case CGizmo::eTranslate:
|
case CGizmo::eTranslate:
|
||||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||||
spinBoxValue = mGizmo.TotalTranslation();
|
spinBoxValue = mGizmo.TotalTranslation();
|
||||||
else if (!mSelectedNodes.empty())
|
else if (!mSelection.empty())
|
||||||
spinBoxValue = mSelectedNodes.front()->AbsolutePosition();
|
spinBoxValue = mSelection.front()->AbsolutePosition();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CGizmo::eRotate:
|
case CGizmo::eRotate:
|
||||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||||
spinBoxValue = mGizmo.TotalRotation();
|
spinBoxValue = mGizmo.TotalRotation();
|
||||||
else if (!mSelectedNodes.empty())
|
else if (!mSelection.empty())
|
||||||
spinBoxValue = mSelectedNodes.front()->AbsoluteRotation().ToEuler();
|
spinBoxValue = mSelection.front()->AbsoluteRotation().ToEuler();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CGizmo::eScale:
|
case CGizmo::eScale:
|
||||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||||
spinBoxValue = mGizmo.TotalScale();
|
spinBoxValue = mGizmo.TotalScale();
|
||||||
else if (!mSelectedNodes.empty())
|
else if (!mSelection.empty())
|
||||||
spinBoxValue = mSelectedNodes.front()->AbsoluteScale();
|
spinBoxValue = mSelection.front()->AbsoluteScale();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!mSelectedNodes.empty()) spinBoxValue = mSelectedNodes.front()->AbsolutePosition();
|
else if (!mSelection.empty()) spinBoxValue = mSelection.front()->AbsolutePosition();
|
||||||
|
|
||||||
ui->TransformSpinBox->blockSignals(true);
|
ui->TransformSpinBox->blockSignals(true);
|
||||||
ui->TransformSpinBox->SetValue(spinBoxValue);
|
ui->TransformSpinBox->SetValue(spinBoxValue);
|
||||||
|
@ -581,26 +238,37 @@ void CWorldEditor::UpdateGizmoUI()
|
||||||
// Update gizmo
|
// Update gizmo
|
||||||
if (!mGizmoTransforming)
|
if (!mGizmoTransforming)
|
||||||
{
|
{
|
||||||
if (!mSelectedNodes.empty())
|
// Set gizmo transform
|
||||||
mGizmo.SetPosition(mSelectedNodes.front()->AbsolutePosition());
|
if (!mSelection.empty())
|
||||||
|
{
|
||||||
// Determine transform space
|
mGizmo.SetPosition(mSelection.front()->AbsolutePosition());
|
||||||
ETransformSpace space;
|
mGizmo.SetLocalRotation(mSelection.front()->AbsoluteRotation());
|
||||||
if (mGizmo.Mode() == CGizmo::eTranslate) space = mTranslateSpace;
|
}
|
||||||
else if (mGizmo.Mode() == CGizmo::eRotate) space = mRotateSpace;
|
}
|
||||||
else space = eLocalTransform;
|
|
||||||
|
|
||||||
// Set gizmo transform space
|
|
||||||
mGizmo.SetTransformSpace(space);
|
|
||||||
|
|
||||||
if (!mSelectedNodes.empty())
|
|
||||||
mGizmo.SetLocalRotation(mSelectedNodes.front()->AbsoluteRotation());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mGizmoUIOutdated = false;
|
void CWorldEditor::GizmoModeChanged(CGizmo::EGizmoMode mode)
|
||||||
|
{
|
||||||
|
ui->TransformSpinBox->SetSingleStep( (mode == CGizmo::eRotate ? 1.0 : 0.1) );
|
||||||
|
ui->TransformSpinBox->SetDefaultValue( (mode == CGizmo::eScale ? 1.0 : 0.0) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ ACTIONS ************
|
// ************ ACTIONS ************
|
||||||
|
void CWorldEditor::RefreshViewport()
|
||||||
|
{
|
||||||
|
if (!mGizmo.IsTransforming())
|
||||||
|
mGizmo.ResetSelectedAxes();
|
||||||
|
|
||||||
|
// Process input + update UI
|
||||||
|
ui->MainViewport->ProcessInput();
|
||||||
|
UpdateCursor();
|
||||||
|
UpdateStatusBar();
|
||||||
|
UpdateGizmoUI();
|
||||||
|
|
||||||
|
// Render
|
||||||
|
ui->MainViewport->Render();
|
||||||
|
}
|
||||||
|
|
||||||
void CWorldEditor::OnCameraSpeedChange(double speed)
|
void CWorldEditor::OnCameraSpeedChange(double speed)
|
||||||
{
|
{
|
||||||
static const double skDefaultSpeed = 1.0;
|
static const double skDefaultSpeed = 1.0;
|
||||||
|
@ -613,23 +281,31 @@ void CWorldEditor::OnCameraSpeedChange(double speed)
|
||||||
|
|
||||||
void CWorldEditor::OnTransformSpinBoxModified(CVector3f value)
|
void CWorldEditor::OnTransformSpinBoxModified(CVector3f value)
|
||||||
{
|
{
|
||||||
|
if (mSelection.empty()) return;
|
||||||
|
|
||||||
switch (mGizmo.Mode())
|
switch (mGizmo.Mode())
|
||||||
{
|
{
|
||||||
case CGizmo::eTranslate:
|
case CGizmo::eTranslate:
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
{
|
||||||
(*it)->SetPosition(value);
|
CVector3f delta = value - mSelection.front()->AbsolutePosition();
|
||||||
|
mUndoStack.push(new CTranslateNodeCommand(this, mSelection, delta, mTranslateSpace));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CGizmo::eRotate:
|
case CGizmo::eRotate:
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
{
|
||||||
(*it)->SetRotation(value);
|
CQuaternion delta = CQuaternion::FromEuler(value) * mSelection.front()->AbsoluteRotation().Inverse();
|
||||||
|
mUndoStack.push(new CRotateNodeCommand(this, mSelection, CVector3f::skZero, delta, mRotateSpace));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CGizmo::eScale:
|
case CGizmo::eScale:
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
{
|
||||||
(*it)->SetScale(value);
|
CVector3f delta = value / mSelection.front()->AbsoluteScale();
|
||||||
|
mUndoStack.push(new CScaleNodeCommand(this, mSelection, CVector3f::skZero, delta));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RecalculateSelectionBounds();
|
RecalculateSelectionBounds();
|
||||||
UpdateGizmoUI();
|
UpdateGizmoUI();
|
||||||
|
@ -637,33 +313,42 @@ void CWorldEditor::OnTransformSpinBoxModified(CVector3f value)
|
||||||
|
|
||||||
void CWorldEditor::OnTransformSpinBoxEdited(CVector3f)
|
void CWorldEditor::OnTransformSpinBoxEdited(CVector3f)
|
||||||
{
|
{
|
||||||
|
ui->TransformSpinBox->blockSignals(true);
|
||||||
|
setFocus();
|
||||||
|
ui->TransformSpinBox->blockSignals(false);
|
||||||
|
if (mSelection.empty()) return;
|
||||||
|
|
||||||
|
if (mGizmo.Mode() == CGizmo::eTranslate) mUndoStack.push(CTranslateNodeCommand::End());
|
||||||
|
else if (mGizmo.Mode() == CGizmo::eRotate) mUndoStack.push(CRotateNodeCommand::End());
|
||||||
|
else if (mGizmo.Mode() == CGizmo::eScale) mUndoStack.push(CScaleNodeCommand::End());
|
||||||
|
|
||||||
UpdateGizmoUI();
|
UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
// These functions are from "Go to slot" in the designer
|
// These functions are from "Go to slot" in the designer
|
||||||
void CWorldEditor::on_ActionDrawWorld_triggered()
|
void CWorldEditor::on_ActionDrawWorld_triggered()
|
||||||
{
|
{
|
||||||
mpSceneManager->SetWorld(ui->ActionDrawWorld->isChecked());
|
mScene.SetWorld(ui->ActionDrawWorld->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::on_ActionDrawCollision_triggered()
|
void CWorldEditor::on_ActionDrawCollision_triggered()
|
||||||
{
|
{
|
||||||
mpSceneManager->SetCollision(ui->ActionDrawCollision->isChecked());
|
mScene.SetCollision(ui->ActionDrawCollision->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::on_ActionDrawObjects_triggered()
|
void CWorldEditor::on_ActionDrawObjects_triggered()
|
||||||
{
|
{
|
||||||
mpSceneManager->SetObjects(ui->ActionDrawObjects->isChecked());
|
mScene.SetObjects(ui->ActionDrawObjects->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::on_ActionDrawLights_triggered()
|
void CWorldEditor::on_ActionDrawLights_triggered()
|
||||||
{
|
{
|
||||||
mpSceneManager->SetLights(ui->ActionDrawLights->isChecked());
|
mScene.SetLights(ui->ActionDrawLights->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::on_ActionDrawSky_triggered()
|
void CWorldEditor::on_ActionDrawSky_triggered()
|
||||||
{
|
{
|
||||||
mDrawSky = ui->ActionDrawSky->isChecked();
|
ui->MainViewport->SetSkyEnabled(ui->ActionDrawSky->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::on_ActionNoLighting_triggered()
|
void CWorldEditor::on_ActionNoLighting_triggered()
|
||||||
|
@ -692,7 +377,7 @@ void CWorldEditor::on_ActionWorldLighting_triggered()
|
||||||
|
|
||||||
void CWorldEditor::on_ActionNoBloom_triggered()
|
void CWorldEditor::on_ActionNoBloom_triggered()
|
||||||
{
|
{
|
||||||
mpRenderer->SetBloom(CRenderer::eNoBloom);
|
ui->MainViewport->Renderer()->SetBloom(CRenderer::eNoBloom);
|
||||||
ui->ActionNoBloom->setChecked(true);
|
ui->ActionNoBloom->setChecked(true);
|
||||||
ui->ActionBloomMaps->setChecked(false);
|
ui->ActionBloomMaps->setChecked(false);
|
||||||
ui->ActionFakeBloom->setChecked(false);
|
ui->ActionFakeBloom->setChecked(false);
|
||||||
|
@ -701,7 +386,7 @@ void CWorldEditor::on_ActionNoBloom_triggered()
|
||||||
|
|
||||||
void CWorldEditor::on_ActionBloomMaps_triggered()
|
void CWorldEditor::on_ActionBloomMaps_triggered()
|
||||||
{
|
{
|
||||||
mpRenderer->SetBloom(CRenderer::eBloomMaps);
|
ui->MainViewport->Renderer()->SetBloom(CRenderer::eBloomMaps);
|
||||||
ui->ActionNoBloom->setChecked(false);
|
ui->ActionNoBloom->setChecked(false);
|
||||||
ui->ActionBloomMaps->setChecked(true);
|
ui->ActionBloomMaps->setChecked(true);
|
||||||
ui->ActionFakeBloom->setChecked(false);
|
ui->ActionFakeBloom->setChecked(false);
|
||||||
|
@ -710,7 +395,7 @@ void CWorldEditor::on_ActionBloomMaps_triggered()
|
||||||
|
|
||||||
void CWorldEditor::on_ActionFakeBloom_triggered()
|
void CWorldEditor::on_ActionFakeBloom_triggered()
|
||||||
{
|
{
|
||||||
mpRenderer->SetBloom(CRenderer::eFakeBloom);
|
ui->MainViewport->Renderer()->SetBloom(CRenderer::eFakeBloom);
|
||||||
ui->ActionNoBloom->setChecked(false);
|
ui->ActionNoBloom->setChecked(false);
|
||||||
ui->ActionBloomMaps->setChecked(false);
|
ui->ActionBloomMaps->setChecked(false);
|
||||||
ui->ActionFakeBloom->setChecked(true);
|
ui->ActionFakeBloom->setChecked(true);
|
||||||
|
@ -719,7 +404,7 @@ void CWorldEditor::on_ActionFakeBloom_triggered()
|
||||||
|
|
||||||
void CWorldEditor::on_ActionBloom_triggered()
|
void CWorldEditor::on_ActionBloom_triggered()
|
||||||
{
|
{
|
||||||
mpRenderer->SetBloom(CRenderer::eBloom);
|
ui->MainViewport->Renderer()->SetBloom(CRenderer::eBloom);
|
||||||
ui->ActionNoBloom->setChecked(false);
|
ui->ActionNoBloom->setChecked(false);
|
||||||
ui->ActionBloomMaps->setChecked(false);
|
ui->ActionBloomMaps->setChecked(false);
|
||||||
ui->ActionFakeBloom->setChecked(false);
|
ui->ActionFakeBloom->setChecked(false);
|
||||||
|
@ -732,17 +417,16 @@ void CWorldEditor::on_ActionZoomOnSelection_triggered()
|
||||||
static const float skAreaDistScale = 0.8f;
|
static const float skAreaDistScale = 0.8f;
|
||||||
|
|
||||||
CCamera& Camera = ui->MainViewport->Camera();
|
CCamera& Camera = ui->MainViewport->Camera();
|
||||||
CVector3f CamDir = Camera.GetDirection();
|
CVector3f CamDir = Camera.Direction();
|
||||||
CVector3f NewPos;
|
CVector3f NewPos;
|
||||||
|
|
||||||
// Zoom on selection
|
// Zoom on selection
|
||||||
if (mSelectedNodes.size() != 0)
|
if (mSelection.size() != 0)
|
||||||
{
|
{
|
||||||
CVector3f Min = mSelectionAABox.Min();
|
CVector3f Min = mSelectionBounds.Min();
|
||||||
CVector3f Max = mSelectionAABox.Max();
|
CVector3f Max = mSelectionBounds.Max();
|
||||||
float Dist = ((Max.x - Min.x) + (Max.y - Min.y) + (Max.z - Min.z)) / 3.f;
|
float Dist = ((Max.x - Min.x) + (Max.y - Min.y) + (Max.z - Min.z)) / 3.f;
|
||||||
//float Dist = mSelectionAABox.Min().Distance(mSelectionAABox.Max());
|
NewPos = mSelectionBounds.Center() + (CamDir * -(Dist * skDistScale));
|
||||||
NewPos = mSelectionAABox.Center() + (CamDir * -(Dist * skDistScale));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zoom on area
|
// Zoom on area
|
||||||
|
@ -752,7 +436,6 @@ void CWorldEditor::on_ActionZoomOnSelection_triggered()
|
||||||
CVector3f Min = AreaBox.Min();
|
CVector3f Min = AreaBox.Min();
|
||||||
CVector3f Max = AreaBox.Max();
|
CVector3f Max = AreaBox.Max();
|
||||||
float Dist = ((Max.x - Min.x) + (Max.y - Min.y) + (Max.z - Min.z)) / 3.f;
|
float Dist = ((Max.x - Min.x) + (Max.y - Min.y) + (Max.z - Min.z)) / 3.f;
|
||||||
//float Dist = AreaBox.Min().Distance(AreaBox.Max());
|
|
||||||
NewPos = AreaBox.Center() + (CamDir * -(Dist * skAreaDistScale));
|
NewPos = AreaBox.Center() + (CamDir * -(Dist * skAreaDistScale));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,12 +444,12 @@ void CWorldEditor::on_ActionZoomOnSelection_triggered()
|
||||||
|
|
||||||
void CWorldEditor::on_ActionDisableBackfaceCull_triggered()
|
void CWorldEditor::on_ActionDisableBackfaceCull_triggered()
|
||||||
{
|
{
|
||||||
mpRenderer->ToggleBackfaceCull(!ui->ActionDisableBackfaceCull->isChecked());
|
ui->MainViewport->Renderer()->ToggleBackfaceCull(!ui->ActionDisableBackfaceCull->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::on_ActionDisableAlpha_triggered()
|
void CWorldEditor::on_ActionDisableAlpha_triggered()
|
||||||
{
|
{
|
||||||
mpRenderer->ToggleAlphaDisabled(ui->ActionDisableAlpha->isChecked());
|
ui->MainViewport->Renderer()->ToggleAlphaDisabled(ui->ActionDisableAlpha->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::on_ActionEditLayers_triggered()
|
void CWorldEditor::on_ActionEditLayers_triggered()
|
||||||
|
@ -777,94 +460,6 @@ void CWorldEditor::on_ActionEditLayers_triggered()
|
||||||
Editor.exec();
|
Editor.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::on_ActionSelectObjects_triggered()
|
|
||||||
{
|
|
||||||
mShowGizmo = false;
|
|
||||||
mGizmoUIOutdated = true;
|
|
||||||
ui->ActionSelectObjects->setChecked(true);
|
|
||||||
ui->ActionTranslate->setChecked(false);
|
|
||||||
ui->ActionRotate->setChecked(false);
|
|
||||||
ui->ActionScale->setChecked(false);
|
|
||||||
|
|
||||||
// Set transform spin box settings
|
|
||||||
ui->TransformSpinBox->SetSingleStep(0.1);
|
|
||||||
ui->TransformSpinBox->SetDefaultValue(0.0);
|
|
||||||
|
|
||||||
// Set transform space combo box
|
|
||||||
mpTransformSpaceComboBox->setEnabled(false);
|
|
||||||
mpTransformSpaceComboBox->blockSignals(true);
|
|
||||||
mpTransformSpaceComboBox->setCurrentIndex(0);
|
|
||||||
mpTransformSpaceComboBox->blockSignals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::on_ActionTranslate_triggered()
|
|
||||||
{
|
|
||||||
mShowGizmo = true;
|
|
||||||
mGizmoUIOutdated = true;
|
|
||||||
mGizmo.SetMode(CGizmo::eTranslate);
|
|
||||||
mGizmo.SetTransformSpace(mTranslateSpace);
|
|
||||||
ui->ActionSelectObjects->setChecked(false);
|
|
||||||
ui->ActionTranslate->setChecked(true);
|
|
||||||
ui->ActionRotate->setChecked(false);
|
|
||||||
ui->ActionScale->setChecked(false);
|
|
||||||
|
|
||||||
// Set transform spin box settings
|
|
||||||
ui->TransformSpinBox->SetSingleStep(0.1);
|
|
||||||
ui->TransformSpinBox->SetDefaultValue(0.0);
|
|
||||||
|
|
||||||
// Set transform space combo box
|
|
||||||
int index = (mTranslateSpace == eWorldTransform ? 0 : 1);
|
|
||||||
mpTransformSpaceComboBox->setEnabled(true);
|
|
||||||
mpTransformSpaceComboBox->blockSignals(true);
|
|
||||||
mpTransformSpaceComboBox->setCurrentIndex(index);
|
|
||||||
mpTransformSpaceComboBox->blockSignals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::on_ActionRotate_triggered()
|
|
||||||
{
|
|
||||||
mShowGizmo = true;
|
|
||||||
mGizmoUIOutdated = true;
|
|
||||||
mGizmo.SetMode(CGizmo::eRotate);
|
|
||||||
mGizmo.SetTransformSpace(mRotateSpace);
|
|
||||||
ui->ActionSelectObjects->setChecked(false);
|
|
||||||
ui->ActionTranslate->setChecked(false);
|
|
||||||
ui->ActionRotate->setChecked(true);
|
|
||||||
ui->ActionScale->setChecked(false);
|
|
||||||
|
|
||||||
// Set transform spin box settings
|
|
||||||
ui->TransformSpinBox->SetSingleStep(1.0);
|
|
||||||
ui->TransformSpinBox->SetDefaultValue(0.0);
|
|
||||||
|
|
||||||
// Set transform space combo box
|
|
||||||
int index = (mRotateSpace == eWorldTransform ? 0 : 1);
|
|
||||||
mpTransformSpaceComboBox->setEnabled(true);
|
|
||||||
mpTransformSpaceComboBox->blockSignals(true);
|
|
||||||
mpTransformSpaceComboBox->setCurrentIndex(index);
|
|
||||||
mpTransformSpaceComboBox->blockSignals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::on_ActionScale_triggered()
|
|
||||||
{
|
|
||||||
mShowGizmo = true;
|
|
||||||
mGizmoUIOutdated = true;
|
|
||||||
mGizmo.SetMode(CGizmo::eScale);
|
|
||||||
mGizmo.SetTransformSpace(eLocalTransform);
|
|
||||||
ui->ActionSelectObjects->setChecked(false);
|
|
||||||
ui->ActionTranslate->setChecked(false);
|
|
||||||
ui->ActionRotate->setChecked(false);
|
|
||||||
ui->ActionScale->setChecked(true);
|
|
||||||
|
|
||||||
// Set transform spin box settings
|
|
||||||
ui->TransformSpinBox->SetSingleStep(0.1);
|
|
||||||
ui->TransformSpinBox->SetDefaultValue(1.0);
|
|
||||||
|
|
||||||
// Set transform space combo box - force to local
|
|
||||||
mpTransformSpaceComboBox->setEnabled(false);
|
|
||||||
mpTransformSpaceComboBox->blockSignals(true);
|
|
||||||
mpTransformSpaceComboBox->setCurrentIndex(1);
|
|
||||||
mpTransformSpaceComboBox->blockSignals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::on_ActionIncrementGizmo_triggered()
|
void CWorldEditor::on_ActionIncrementGizmo_triggered()
|
||||||
{
|
{
|
||||||
mGizmo.IncrementSize();
|
mGizmo.IncrementSize();
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
#ifndef CWORLDEDITOR_H
|
#ifndef CWORLDEDITOR_H
|
||||||
#define CWORLDEDITOR_H
|
#define CWORLDEDITOR_H
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include "INodeEditor.h"
|
||||||
#include <QList>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QList>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QUndoStack>
|
||||||
|
|
||||||
#include "CGizmo.h"
|
#include "CGizmo.h"
|
||||||
#include <Common/CRay.h>
|
#include <Common/CRay.h>
|
||||||
|
@ -21,74 +25,38 @@ namespace Ui {
|
||||||
class CWorldEditor;
|
class CWorldEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CWorldEditor : public QMainWindow
|
class CWorldEditor : public INodeEditor
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
CRenderer *mpRenderer;
|
Ui::CWorldEditor *ui;
|
||||||
CSceneManager *mpSceneManager;
|
|
||||||
CGizmo mGizmo;
|
|
||||||
ETransformSpace mTranslateSpace;
|
|
||||||
ETransformSpace mRotateSpace;
|
|
||||||
CCamera mCamera;
|
|
||||||
CGameArea *mpArea;
|
|
||||||
CWorld *mpWorld;
|
CWorld *mpWorld;
|
||||||
|
CGameArea *mpArea;
|
||||||
CToken mAreaToken;
|
CToken mAreaToken;
|
||||||
CToken mWorldToken;
|
CToken mWorldToken;
|
||||||
CTimer mFrameTimer;
|
QTimer mRefreshTimer;
|
||||||
bool mDrawSky;
|
|
||||||
bool mShowGizmo;
|
|
||||||
bool mGizmoHovering;
|
|
||||||
bool mGizmoTransforming;
|
|
||||||
bool mGizmoUIOutdated;
|
|
||||||
|
|
||||||
CVector3f mHoverPoint;
|
|
||||||
CSceneNode *mpHoverNode;
|
|
||||||
std::list<CSceneNode*> mSelectedNodes;
|
|
||||||
CAABox mSelectionAABox;
|
|
||||||
|
|
||||||
QComboBox *mpTransformSpaceComboBox;
|
|
||||||
|
|
||||||
CTimer mFPSTimer;
|
|
||||||
int mFrameCount;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CWorldEditor(QWidget *parent = 0);
|
explicit CWorldEditor(QWidget *parent = 0);
|
||||||
~CWorldEditor();
|
~CWorldEditor();
|
||||||
bool eventFilter(QObject *pObj, QEvent *pEvent);
|
bool eventFilter(QObject *pObj, QEvent *pEvent);
|
||||||
void SetArea(CWorld *pWorld, CGameArea *pArea);
|
void SetArea(CWorld *pWorld, CGameArea *pArea);
|
||||||
void ViewportRayCast();
|
|
||||||
CRenderer* Renderer();
|
|
||||||
CSceneManager* Scene();
|
|
||||||
CGameArea* ActiveArea();
|
CGameArea* ActiveArea();
|
||||||
|
|
||||||
// Selection
|
// Update UI
|
||||||
void SelectNode(CSceneNode *pNode);
|
void UpdateGizmoUI();
|
||||||
void DeselectNode(CSceneNode *pNode);
|
|
||||||
void ClearSelection();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void ViewportPreRender();
|
|
||||||
void ViewportRender(CCamera& Camera);
|
|
||||||
void ViewportPostRender();
|
|
||||||
void ViewportMouseDrag(QMouseEvent *pEvent);
|
|
||||||
void ViewportMouseClick(QMouseEvent *pEvent);
|
|
||||||
void ViewportMouseRelease(QMouseEvent *pEvent);
|
|
||||||
void SetViewportSize(int Width, int Height);
|
|
||||||
void SetTransformSpace(int space);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::CWorldEditor *ui;
|
|
||||||
void RecalculateSelectionBounds();
|
|
||||||
void ResetHover();
|
|
||||||
void UpdateCursor();
|
|
||||||
|
|
||||||
// UI
|
|
||||||
void OnSidebarResize();
|
|
||||||
void UpdateSelectionUI();
|
void UpdateSelectionUI();
|
||||||
void UpdateStatusBar();
|
void UpdateStatusBar();
|
||||||
void UpdateGizmoUI();
|
|
||||||
|
protected:
|
||||||
|
void GizmoModeChanged(CGizmo::EGizmoMode mode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UpdateCursor();
|
||||||
|
void OnSidebarResize();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void RefreshViewport();
|
||||||
void OnCameraSpeedChange(double speed);
|
void OnCameraSpeedChange(double speed);
|
||||||
void OnTransformSpinBoxModified(CVector3f value);
|
void OnTransformSpinBoxModified(CVector3f value);
|
||||||
void OnTransformSpinBoxEdited(CVector3f value);
|
void OnTransformSpinBoxEdited(CVector3f value);
|
||||||
|
@ -108,10 +76,6 @@ private slots:
|
||||||
void on_ActionDisableBackfaceCull_triggered();
|
void on_ActionDisableBackfaceCull_triggered();
|
||||||
void on_ActionDisableAlpha_triggered();
|
void on_ActionDisableAlpha_triggered();
|
||||||
void on_ActionEditLayers_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_ActionIncrementGizmo_triggered();
|
||||||
void on_ActionDecrementGizmo_triggered();
|
void on_ActionDecrementGizmo_triggered();
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="CEditorGLWidget" name="MainViewport" native="true">
|
<widget class="CSceneViewport" name="MainViewport" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
|
@ -245,8 +245,6 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Edit</string>
|
<string>Edit</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="ActionUndo"/>
|
|
||||||
<addaction name="ActionRedo"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuView">
|
<widget class="QMenu" name="menuView">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -475,10 +473,6 @@
|
||||||
<addaction name="ActionLink"/>
|
<addaction name="ActionLink"/>
|
||||||
<addaction name="ActionUnlink"/>
|
<addaction name="ActionUnlink"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="ActionSelectObjects"/>
|
|
||||||
<addaction name="ActionTranslate"/>
|
|
||||||
<addaction name="ActionRotate"/>
|
|
||||||
<addaction name="ActionScale"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<action name="ActionOpen">
|
<action name="ActionOpen">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -490,60 +484,6 @@
|
||||||
<string>Save</string>
|
<string>Save</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="ActionTranslate">
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../Icons.qrc">
|
|
||||||
<normaloff>:/icons/EditorAssets/Translate.png</normaloff>:/icons/EditorAssets/Translate.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Translate</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Translate</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+W</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="ActionRotate">
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../Icons.qrc">
|
|
||||||
<normaloff>:/icons/EditorAssets/Rotate.png</normaloff>:/icons/EditorAssets/Rotate.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Rotate</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Rotate</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+E</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="ActionScale">
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../Icons.qrc">
|
|
||||||
<normaloff>:/icons/EditorAssets/Scale.png</normaloff>:/icons/EditorAssets/Scale.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Scale</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Scale</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+R</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionOpen_model_viewer">
|
<action name="actionOpen_model_viewer">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Model Viewer</string>
|
<string>Open Model Viewer</string>
|
||||||
|
@ -573,22 +513,6 @@
|
||||||
<string>Unlink</string>
|
<string>Unlink</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="ActionUndo">
|
|
||||||
<property name="text">
|
|
||||||
<string>Undo</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+Z</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="ActionRedo">
|
|
||||||
<property name="text">
|
|
||||||
<string>Redo</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+Y</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="ActionDrawWorld">
|
<action name="ActionDrawWorld">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -753,27 +677,6 @@
|
||||||
<string>Fake Bloom</string>
|
<string>Fake Bloom</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="ActionSelectObjects">
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../Icons.qrc">
|
|
||||||
<normaloff>:/icons/EditorAssets/SelectMode.png</normaloff>:/icons/EditorAssets/SelectMode.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Select Objects</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Select Objects</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+Q</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="ActionIncrementGizmo">
|
<action name="ActionIncrementGizmo">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Increment Gizmo Size</string>
|
<string>Increment Gizmo Size</string>
|
||||||
|
@ -804,12 +707,6 @@
|
||||||
</action>
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
|
||||||
<class>CEditorGLWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>CEditorGLWidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>WDraggableSpinBox</class>
|
<class>WDraggableSpinBox</class>
|
||||||
<extends>QDoubleSpinBox</extends>
|
<extends>QDoubleSpinBox</extends>
|
||||||
|
@ -833,6 +730,12 @@
|
||||||
<header>WVectorEditor.h</header>
|
<header>WVectorEditor.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>CSceneViewport</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>CSceneViewport.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>TabWidget</tabstop>
|
<tabstop>TabWidget</tabstop>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <Common/StringUtil.h>
|
#include <Common/StringUtil.h>
|
||||||
#include <Core/CGraphics.h>
|
#include <Core/CGraphics.h>
|
||||||
#include <gtc/matrix_transform.hpp>
|
#include <gtc/matrix_transform.hpp>
|
||||||
#include "CEditorGLWidget.h"
|
#include "CBasicViewport.h"
|
||||||
|
|
||||||
CWorldEditorWindow::CWorldEditorWindow(QWidget *parent) :
|
CWorldEditorWindow::CWorldEditorWindow(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
|
@ -30,13 +30,13 @@ CWorldEditorWindow::CWorldEditorWindow(QWidget *parent) :
|
||||||
mViewportKeysPressed = 0;
|
mViewportKeysPressed = 0;
|
||||||
mShouldDrawSky = true;
|
mShouldDrawSky = true;
|
||||||
|
|
||||||
connect(ui->CentralGLWidget, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
|
/*connect(ui->CentralGLWidget, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
|
||||||
connect(ui->CentralGLWidget, SIGNAL(PaintViewport(double)), this, SLOT(PaintViewport(double)));
|
connect(ui->CentralGLWidget, SIGNAL(PaintViewport(double)), this, SLOT(PaintViewport(double)));
|
||||||
connect(ui->CentralGLWidget, SIGNAL(MouseClicked(QMouseEvent*)), this, SLOT(OnViewportRayCast(QMouseEvent*)));
|
connect(ui->CentralGLWidget, SIGNAL(MouseClicked(QMouseEvent*)), this, SLOT(OnViewportRayCast(QMouseEvent*)));
|
||||||
connect(ui->CentralGLWidget, SIGNAL(MouseMoved(QMouseEvent*, float, float)), this, SLOT(OnViewportMouseMove(QMouseEvent*, float, float)));
|
connect(ui->CentralGLWidget, SIGNAL(MouseMoved(QMouseEvent*, float, float)), this, SLOT(OnViewportMouseMove(QMouseEvent*, float, float)));
|
||||||
connect(ui->CentralGLWidget, SIGNAL(KeyPressed(QKeyEvent*)), this, SLOT(OnViewportKeyPress(QKeyEvent*)));
|
connect(ui->CentralGLWidget, SIGNAL(KeyPressed(QKeyEvent*)), this, SLOT(OnViewportKeyPress(QKeyEvent*)));
|
||||||
connect(ui->CentralGLWidget, SIGNAL(KeyReleased(QKeyEvent*)), this, SLOT(OnViewportKeyRelease(QKeyEvent*)));
|
connect(ui->CentralGLWidget, SIGNAL(KeyReleased(QKeyEvent*)), this, SLOT(OnViewportKeyRelease(QKeyEvent*)));
|
||||||
connect(ui->CentralGLWidget, SIGNAL(WheelScroll(int)), this, SLOT(OnViewportWheelScroll(int)));
|
connect(ui->CentralGLWidget, SIGNAL(WheelScroll(int)), this, SLOT(OnViewportWheelScroll(int)));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
CWorldEditorWindow::~CWorldEditorWindow()
|
CWorldEditorWindow::~CWorldEditorWindow()
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="CEditorGLWidget" name="CentralGLWidget" native="true"/>
|
<widget class="QWidget" name="CentralGLWidget" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -133,8 +133,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>294</width>
|
<width>272</width>
|
||||||
<height>654</height>
|
<height>330</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
@ -447,14 +447,6 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>CEditorGLWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>CEditorGLWidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -0,0 +1,272 @@
|
||||||
|
#include "INodeEditor.h"
|
||||||
|
#include "undo/UndoCommands.h"
|
||||||
|
|
||||||
|
INodeEditor::INodeEditor(QWidget *pParent)
|
||||||
|
: QMainWindow(pParent),
|
||||||
|
mShowGizmo(false),
|
||||||
|
mGizmoHovering(false),
|
||||||
|
mGizmoTransforming(false),
|
||||||
|
mTranslateSpace(eWorldTransform),
|
||||||
|
mRotateSpace(eWorldTransform)
|
||||||
|
{
|
||||||
|
// Create undo actions
|
||||||
|
QAction *pUndoAction = mUndoStack.createUndoAction(this);
|
||||||
|
QAction *pRedoAction = mUndoStack.createRedoAction(this);
|
||||||
|
pUndoAction->setShortcut(QKeySequence("Ctrl+Z"));
|
||||||
|
pRedoAction->setShortcut(QKeySequence("Ctrl+Y"));
|
||||||
|
mUndoActions.push_back(pUndoAction);
|
||||||
|
mUndoActions.push_back(pRedoAction);
|
||||||
|
|
||||||
|
// Create gizmo actions
|
||||||
|
mGizmoActions.append(new QAction(QIcon(":/icons/EditorAssets/SelectMode.png"), "Select Objects", this));
|
||||||
|
mGizmoActions.append(new QAction(QIcon(":/icons/EditorAssets/Translate.png"), "Translate", this));
|
||||||
|
mGizmoActions.append(new QAction(QIcon(":/icons/EditorAssets/Rotate.png"), "Rotate", this));
|
||||||
|
mGizmoActions.append(new QAction(QIcon(":/icons/EditorAssets/Scale.png"), "Scale", this));
|
||||||
|
|
||||||
|
mGizmoActions[0]->setShortcut(QKeySequence("Ctrl+Q"));
|
||||||
|
mGizmoActions[1]->setShortcut(QKeySequence("Ctrl+W"));
|
||||||
|
mGizmoActions[2]->setShortcut(QKeySequence("Ctrl+E"));
|
||||||
|
mGizmoActions[3]->setShortcut(QKeySequence("Ctrl+R"));
|
||||||
|
|
||||||
|
mpGizmoGroup = new QActionGroup(this);
|
||||||
|
|
||||||
|
foreach (QAction *pAction, mGizmoActions)
|
||||||
|
{
|
||||||
|
pAction->setCheckable(true);
|
||||||
|
mpGizmoGroup->addAction(pAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
mGizmoActions[0]->setChecked(true);
|
||||||
|
|
||||||
|
// Create transform combo box
|
||||||
|
mpTransformCombo = new QComboBox(this);
|
||||||
|
mpTransformCombo->addItem("World");
|
||||||
|
mpTransformCombo->addItem("Local");
|
||||||
|
|
||||||
|
// Connect signals and slots
|
||||||
|
connect(mGizmoActions[0], SIGNAL(triggered()), this, SLOT(OnSelectObjectsTriggered()));
|
||||||
|
connect(mGizmoActions[1], SIGNAL(triggered()), this, SLOT(OnTranslateTriggered()));
|
||||||
|
connect(mGizmoActions[2], SIGNAL(triggered()), this, SLOT(OnRotateTriggered()));
|
||||||
|
connect(mGizmoActions[3], SIGNAL(triggered()), this, SLOT(OnScaleTriggered()));
|
||||||
|
connect(mpTransformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnTransformSpaceChanged(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
INodeEditor::~INodeEditor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QUndoStack* INodeEditor::UndoStack()
|
||||||
|
{
|
||||||
|
return &mUndoStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSceneManager* INodeEditor::Scene()
|
||||||
|
{
|
||||||
|
return &mScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGizmo* INodeEditor::Gizmo()
|
||||||
|
{
|
||||||
|
return &mGizmo;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool INodeEditor::IsGizmoVisible()
|
||||||
|
{
|
||||||
|
return (mShowGizmo && !mSelection.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::BeginGizmoTransform()
|
||||||
|
{
|
||||||
|
mGizmoTransforming = true;
|
||||||
|
|
||||||
|
foreach (QAction *pAction, mGizmoActions)
|
||||||
|
pAction->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::EndGizmoTransform()
|
||||||
|
{
|
||||||
|
mGizmoTransforming = false;
|
||||||
|
|
||||||
|
foreach (QAction *pAction, mGizmoActions)
|
||||||
|
pAction->setEnabled(true);
|
||||||
|
|
||||||
|
if (mGizmo.Mode() == CGizmo::eTranslate)
|
||||||
|
mUndoStack.push(CTranslateNodeCommand::End());
|
||||||
|
else if (mGizmo.Mode() == CGizmo::eRotate)
|
||||||
|
mUndoStack.push(CRotateNodeCommand::End());
|
||||||
|
else if (mGizmo.Mode() == CGizmo::eScale)
|
||||||
|
mUndoStack.push(CScaleNodeCommand::End());
|
||||||
|
}
|
||||||
|
|
||||||
|
ETransformSpace INodeEditor::CurrentTransformSpace()
|
||||||
|
{
|
||||||
|
switch (mGizmo.Mode())
|
||||||
|
{
|
||||||
|
case CGizmo::eTranslate: return mTranslateSpace;
|
||||||
|
case CGizmo::eRotate: return mRotateSpace;
|
||||||
|
case CGizmo::eScale: return eLocalTransform;
|
||||||
|
default: return eWorldTransform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::RecalculateSelectionBounds()
|
||||||
|
{
|
||||||
|
mSelectionBounds = CAABox::skInfinite;
|
||||||
|
|
||||||
|
foreach (CSceneNode *pNode, mSelection)
|
||||||
|
ExpandSelectionBounds(pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::ExpandSelectionBounds(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
mSelectionBounds.ExpandBounds(pNode->AABox());
|
||||||
|
|
||||||
|
if (pNode->NodeType() == eScriptNode)
|
||||||
|
{
|
||||||
|
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
||||||
|
|
||||||
|
if (pScript->HasPreviewVolume())
|
||||||
|
mSelectionBounds.ExpandBounds(pScript->PreviewVolumeAABox());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::SelectNode(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
if (!pNode->IsSelected())
|
||||||
|
mUndoStack.push(new CSelectNodeCommand(this, pNode, mSelection));
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::DeselectNode(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
if (pNode->IsSelected())
|
||||||
|
mUndoStack.push(new CDeselectNodeCommand(this, pNode, mSelection));
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::ClearSelection()
|
||||||
|
{
|
||||||
|
if (!mSelection.empty())
|
||||||
|
mUndoStack.push(new CClearSelectionCommand(this, mSelection));
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::ClearAndSelectNode(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
if (mSelection.empty())
|
||||||
|
mUndoStack.push(new CSelectNodeCommand(this, pNode, mSelection));
|
||||||
|
|
||||||
|
else if ((mSelection.size() == 1) && (mSelection.front() == pNode))
|
||||||
|
return;
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mUndoStack.beginMacro("Select");
|
||||||
|
mUndoStack.push(new CClearSelectionCommand(this, mSelection));
|
||||||
|
mUndoStack.push(new CSelectNodeCommand(this, pNode, mSelection));
|
||||||
|
mUndoStack.endMacro();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ PUBLIC SLOTS ************
|
||||||
|
void INodeEditor::OnGizmoMoved()
|
||||||
|
{
|
||||||
|
switch (mGizmo.Mode())
|
||||||
|
{
|
||||||
|
case CGizmo::eTranslate:
|
||||||
|
{
|
||||||
|
CVector3f delta = mGizmo.DeltaTranslation();
|
||||||
|
mUndoStack.push(new CTranslateNodeCommand(this, mSelection, delta, mTranslateSpace));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CGizmo::eRotate:
|
||||||
|
{
|
||||||
|
CQuaternion delta = mGizmo.DeltaRotation();
|
||||||
|
mUndoStack.push(new CRotateNodeCommand(this, mSelection, CVector3f::skZero, delta, mRotateSpace));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CGizmo::eScale:
|
||||||
|
{
|
||||||
|
CVector3f delta = mGizmo.DeltaScale();
|
||||||
|
mUndoStack.push(new CScaleNodeCommand(this, mSelection, CVector3f::skZero, delta));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RecalculateSelectionBounds();
|
||||||
|
UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ PRIVATE SLOTS ************
|
||||||
|
void INodeEditor::OnSelectObjectsTriggered()
|
||||||
|
{
|
||||||
|
mGizmo.SetMode(CGizmo::eOff);
|
||||||
|
mGizmo.SetTransformSpace(eWorldTransform);
|
||||||
|
mShowGizmo = false;
|
||||||
|
|
||||||
|
mpTransformCombo->setEnabled(false);
|
||||||
|
mpTransformCombo->blockSignals(true);
|
||||||
|
mpTransformCombo->setCurrentIndex(0);
|
||||||
|
mpTransformCombo->blockSignals(false);
|
||||||
|
|
||||||
|
GizmoModeChanged(CGizmo::eOff);
|
||||||
|
UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::OnTranslateTriggered()
|
||||||
|
{
|
||||||
|
mGizmo.SetMode(CGizmo::eTranslate);
|
||||||
|
mGizmo.SetTransformSpace(mTranslateSpace);
|
||||||
|
mShowGizmo = true;
|
||||||
|
|
||||||
|
mpTransformCombo->setEnabled(true);
|
||||||
|
mpTransformCombo->blockSignals(true);
|
||||||
|
mpTransformCombo->setCurrentIndex( (mTranslateSpace == eWorldTransform) ? 0 : 1 );
|
||||||
|
mpTransformCombo->blockSignals(false);
|
||||||
|
|
||||||
|
GizmoModeChanged(CGizmo::eTranslate);
|
||||||
|
UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::OnRotateTriggered()
|
||||||
|
{
|
||||||
|
mGizmo.SetMode(CGizmo::eRotate);
|
||||||
|
mGizmo.SetTransformSpace(mRotateSpace);
|
||||||
|
mShowGizmo = true;
|
||||||
|
|
||||||
|
mpTransformCombo->setEnabled(true);
|
||||||
|
mpTransformCombo->blockSignals(true);
|
||||||
|
mpTransformCombo->setCurrentIndex( (mRotateSpace == eWorldTransform) ? 0 : 1 );
|
||||||
|
mpTransformCombo->blockSignals(false);
|
||||||
|
|
||||||
|
GizmoModeChanged(CGizmo::eRotate);
|
||||||
|
UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::OnScaleTriggered()
|
||||||
|
{
|
||||||
|
mGizmo.SetMode(CGizmo::eScale);
|
||||||
|
mGizmo.SetTransformSpace(eLocalTransform);
|
||||||
|
mShowGizmo = true;
|
||||||
|
|
||||||
|
mpTransformCombo->setEnabled(false);
|
||||||
|
mpTransformCombo->blockSignals(true);
|
||||||
|
mpTransformCombo->setCurrentIndex(1);
|
||||||
|
mpTransformCombo->blockSignals(false);
|
||||||
|
|
||||||
|
GizmoModeChanged(CGizmo::eScale);
|
||||||
|
UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::OnTransformSpaceChanged(int spaceIndex)
|
||||||
|
{
|
||||||
|
if ((mGizmo.Mode() == CGizmo::eScale) || (mGizmo.Mode() == CGizmo::eOff)) return;
|
||||||
|
|
||||||
|
ETransformSpace space = (spaceIndex == 0 ? eWorldTransform : eLocalTransform);
|
||||||
|
|
||||||
|
if (mGizmo.Mode() == CGizmo::eTranslate)
|
||||||
|
mTranslateSpace = space;
|
||||||
|
else
|
||||||
|
mRotateSpace = space;
|
||||||
|
|
||||||
|
mGizmo.SetTransformSpace(space);
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
#ifndef INODEEDITOR_H
|
||||||
|
#define INODEEDITOR_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QActionGroup>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QList>
|
||||||
|
#include <QUndoStack>
|
||||||
|
|
||||||
|
#include "CGizmo.h"
|
||||||
|
#include <Common/ETransformSpace.h>
|
||||||
|
#include <Core/CSceneManager.h>
|
||||||
|
|
||||||
|
class INodeEditor : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Undo stack
|
||||||
|
QUndoStack mUndoStack;
|
||||||
|
QList<QAction*> mUndoActions;
|
||||||
|
|
||||||
|
// Node management
|
||||||
|
CSceneManager mScene;
|
||||||
|
QList<CSceneNode*> mSelection;
|
||||||
|
CAABox mSelectionBounds;
|
||||||
|
|
||||||
|
// Gizmo
|
||||||
|
CGizmo mGizmo;
|
||||||
|
bool mShowGizmo;
|
||||||
|
bool mGizmoHovering;
|
||||||
|
bool mGizmoTransforming;
|
||||||
|
ETransformSpace mTranslateSpace;
|
||||||
|
ETransformSpace mRotateSpace;
|
||||||
|
|
||||||
|
// Gizmo widgets
|
||||||
|
QActionGroup *mpGizmoGroup;
|
||||||
|
QList<QAction*> mGizmoActions;
|
||||||
|
QComboBox *mpTransformCombo;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit INodeEditor(QWidget *pParent = 0);
|
||||||
|
virtual ~INodeEditor();
|
||||||
|
QUndoStack* UndoStack();
|
||||||
|
CSceneManager* Scene();
|
||||||
|
CGizmo* Gizmo();
|
||||||
|
bool IsGizmoVisible();
|
||||||
|
void BeginGizmoTransform();
|
||||||
|
void EndGizmoTransform();
|
||||||
|
|
||||||
|
ETransformSpace CurrentTransformSpace();
|
||||||
|
void RecalculateSelectionBounds();
|
||||||
|
void ExpandSelectionBounds(CSceneNode *pNode);
|
||||||
|
void SelectNode(CSceneNode *pNode);
|
||||||
|
void DeselectNode(CSceneNode *pNode);
|
||||||
|
void ClearSelection();
|
||||||
|
void ClearAndSelectNode(CSceneNode *pNode);
|
||||||
|
|
||||||
|
virtual void UpdateGizmoUI() = 0;
|
||||||
|
virtual void UpdateSelectionUI() = 0;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void OnGizmoMoved();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void GizmoModeChanged(CGizmo::EGizmoMode mode) {}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void OnSelectObjectsTriggered();
|
||||||
|
void OnTranslateTriggered();
|
||||||
|
void OnRotateTriggered();
|
||||||
|
void OnScaleTriggered();
|
||||||
|
void OnTransformSpaceChanged(int spaceIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INODEEDITOR_H
|
|
@ -154,7 +154,7 @@ void WPropertyEditor::CreateEditor()
|
||||||
|
|
||||||
pLineEdit->setText(QString::fromStdString(pStringCast->Get()));
|
pLineEdit->setText(QString::fromStdString(pStringCast->Get()));
|
||||||
pLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
pLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
pLineEdit->setCursorPosition(0);
|
//pLineEdit->setCursorPosition(0);
|
||||||
|
|
||||||
mUI.EditorWidget = pLineEdit;
|
mUI.EditorWidget = pLineEdit;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -61,8 +61,6 @@ void WVectorEditor::SetOrientation(Qt::Orientation orientation)
|
||||||
mpLayout->addItem(mpZLayout);
|
mpLayout->addItem(mpZLayout);
|
||||||
mpLayout->setContentsMargins(5,5,5,5);
|
mpLayout->setContentsMargins(5,5,5,5);
|
||||||
setLayout(mpLayout);
|
setLayout(mpLayout);
|
||||||
|
|
||||||
emit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WVectorEditor::SetDefaultValue(double value)
|
void WVectorEditor::SetDefaultValue(double value)
|
||||||
|
|
|
@ -38,7 +38,7 @@ void WModifyTab::SetEditor(CWorldEditor *pEditor)
|
||||||
mpWorldEditor = pEditor;
|
mpWorldEditor = pEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WModifyTab::GenerateUI(std::list<CSceneNode*>& Selection)
|
void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
|
||||||
{
|
{
|
||||||
WPropertyEditor *pOldEditor = mpCurPropEditor;
|
WPropertyEditor *pOldEditor = mpCurPropEditor;
|
||||||
ClearUI();
|
ClearUI();
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
explicit WModifyTab(QWidget *pParent = 0);
|
explicit WModifyTab(QWidget *pParent = 0);
|
||||||
~WModifyTab();
|
~WModifyTab();
|
||||||
void SetEditor(CWorldEditor *pEditor);
|
void SetEditor(CWorldEditor *pEditor);
|
||||||
void GenerateUI(std::list<CSceneNode*>& Selection);
|
void GenerateUI(QList<CSceneNode*>& Selection);
|
||||||
void ClearUI();
|
void ClearUI();
|
||||||
void ClearCachedEditors();
|
void ClearCachedEditors();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include "CClearSelectionCommand.h"
|
||||||
|
#include "../CWorldEditor.h"
|
||||||
|
|
||||||
|
CClearSelectionCommand::CClearSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& selection)
|
||||||
|
: QUndoCommand("Clear Selection"),
|
||||||
|
mpEditor(pEditor),
|
||||||
|
mSelectionState(selection),
|
||||||
|
mpSelection(&selection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CClearSelectionCommand::~CClearSelectionCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClearSelectionCommand::undo()
|
||||||
|
{
|
||||||
|
mpSelection->reserve(mSelectionState.size());
|
||||||
|
|
||||||
|
foreach (CSceneNode *pNode, mSelectionState)
|
||||||
|
{
|
||||||
|
if (!pNode->IsSelected())
|
||||||
|
{
|
||||||
|
pNode->SetSelected(true);
|
||||||
|
mpSelection->push_back(pNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateSelectionUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClearSelectionCommand::redo()
|
||||||
|
{
|
||||||
|
foreach (CSceneNode *pNode, *mpSelection)
|
||||||
|
if (pNode->IsSelected())
|
||||||
|
pNode->SetSelected(false);
|
||||||
|
|
||||||
|
mpSelection->clear();
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateSelectionUI();
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef CCLEARSELECTIONCOMMAND_H
|
||||||
|
#define CCLEARSELECTIONCOMMAND_H
|
||||||
|
|
||||||
|
#include <QUndoCommand>
|
||||||
|
#include "../INodeEditor.h"
|
||||||
|
#include <Scene/CSceneNode.h>
|
||||||
|
|
||||||
|
class CClearSelectionCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
INodeEditor *mpEditor;
|
||||||
|
QList<CSceneNode*> mSelectionState;
|
||||||
|
QList<CSceneNode*> *mpSelection;
|
||||||
|
public:
|
||||||
|
CClearSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& selection);
|
||||||
|
~CClearSelectionCommand();
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCLEARSELECTIONCOMMAND_H
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include "CDeselectNodeCommand.h"
|
||||||
|
#include "../CWorldEditor.h"
|
||||||
|
|
||||||
|
CDeselectNodeCommand::CDeselectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection)
|
||||||
|
: QUndoCommand("Deselect"),
|
||||||
|
mpEditor(pEditor),
|
||||||
|
mpNode(pNode),
|
||||||
|
mpSelection(&selection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDeselectNodeCommand::undo()
|
||||||
|
{
|
||||||
|
if (!mpNode->IsSelected())
|
||||||
|
{
|
||||||
|
mpNode->SetSelected(true);
|
||||||
|
mpSelection->push_back(mpNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->ExpandSelectionBounds(mpNode);
|
||||||
|
mpEditor->UpdateSelectionUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDeselectNodeCommand::redo()
|
||||||
|
{
|
||||||
|
if (mpNode->IsSelected())
|
||||||
|
{
|
||||||
|
mpNode->SetSelected(false);
|
||||||
|
|
||||||
|
for (auto it = mpSelection->begin(); it != mpSelection->end(); it++)
|
||||||
|
{
|
||||||
|
if (*it == mpNode)
|
||||||
|
{
|
||||||
|
mpSelection->erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateSelectionUI();
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef CDESELECTNODECOMMAND_H
|
||||||
|
#define CDESELECTNODECOMMAND_H
|
||||||
|
|
||||||
|
#include <QUndoCommand>
|
||||||
|
#include "../INodeEditor.h"
|
||||||
|
#include <Scene/CSceneNode.h>
|
||||||
|
|
||||||
|
class CDeselectNodeCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
INodeEditor *mpEditor;
|
||||||
|
CSceneNode *mpNode;
|
||||||
|
QList<CSceneNode*> *mpSelection;
|
||||||
|
public:
|
||||||
|
CDeselectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CDESELECTNODECOMMAND_H
|
|
@ -0,0 +1,103 @@
|
||||||
|
#include "CRotateNodeCommand.h"
|
||||||
|
#include "EUndoCommand.h"
|
||||||
|
#include "../CWorldEditor.h"
|
||||||
|
|
||||||
|
CRotateNodeCommand::CRotateNodeCommand()
|
||||||
|
: QUndoCommand("Rotate"),
|
||||||
|
mpEditor(nullptr),
|
||||||
|
mCommandEnded(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CRotateNodeCommand::CRotateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& pivot, const CQuaternion& delta, ETransformSpace transformSpace)
|
||||||
|
: QUndoCommand("Rotate"),
|
||||||
|
mpEditor(pEditor),
|
||||||
|
mCommandEnded(false)
|
||||||
|
{
|
||||||
|
mNodeList.reserve(nodes.size());
|
||||||
|
|
||||||
|
foreach (CSceneNode *pNode, nodes)
|
||||||
|
{
|
||||||
|
SNodeRotate rotate;
|
||||||
|
rotate.pNode = pNode;
|
||||||
|
rotate.initialPos = pNode->LocalPosition();
|
||||||
|
rotate.initialRot = pNode->LocalRotation();
|
||||||
|
pNode->Rotate(delta, transformSpace);
|
||||||
|
rotate.newPos = pNode->LocalPosition();
|
||||||
|
rotate.newRot = pNode->LocalRotation();
|
||||||
|
mNodeList.push_back(rotate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CRotateNodeCommand::~CRotateNodeCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int CRotateNodeCommand::id() const
|
||||||
|
{
|
||||||
|
return eRotateNodeCmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRotateNodeCommand::mergeWith(const QUndoCommand *other)
|
||||||
|
{
|
||||||
|
if (mCommandEnded) return false;
|
||||||
|
|
||||||
|
if (other->id() == eRotateNodeCmd)
|
||||||
|
{
|
||||||
|
const CRotateNodeCommand *pCmd = static_cast<const CRotateNodeCommand*>(other);
|
||||||
|
|
||||||
|
if (pCmd->mCommandEnded)
|
||||||
|
{
|
||||||
|
mCommandEnded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mpEditor == pCmd->mpEditor) && (mNodeList.size() == pCmd->mNodeList.size()))
|
||||||
|
{
|
||||||
|
for (u32 iNode = 0; iNode < mNodeList.size(); iNode++)
|
||||||
|
{
|
||||||
|
mNodeList[iNode].newPos = pCmd->mNodeList[iNode].newPos;
|
||||||
|
mNodeList[iNode].newRot = pCmd->mNodeList[iNode].newRot;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRotateNodeCommand::undo()
|
||||||
|
{
|
||||||
|
if (!mpEditor) return;
|
||||||
|
|
||||||
|
foreach (SNodeRotate rotate, mNodeList)
|
||||||
|
{
|
||||||
|
rotate.pNode->SetPosition(rotate.initialPos);
|
||||||
|
rotate.pNode->SetRotation(rotate.initialRot);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRotateNodeCommand::redo()
|
||||||
|
{
|
||||||
|
if (!mpEditor) return;
|
||||||
|
|
||||||
|
foreach (SNodeRotate rotate, mNodeList)
|
||||||
|
{
|
||||||
|
rotate.pNode->SetPosition(rotate.newPos);
|
||||||
|
rotate.pNode->SetRotation(rotate.newRot);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
CRotateNodeCommand* CRotateNodeCommand::End()
|
||||||
|
{
|
||||||
|
CRotateNodeCommand *pCmd = new CRotateNodeCommand();
|
||||||
|
pCmd->mCommandEnded = true;
|
||||||
|
return pCmd;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef CROTATENODECOMMAND_H
|
||||||
|
#define CROTATENODECOMMAND_H
|
||||||
|
|
||||||
|
#include <QUndoCommand>
|
||||||
|
#include <QList>
|
||||||
|
#include <Scene/CSceneNode.h>
|
||||||
|
#include "../INodeEditor.h"
|
||||||
|
|
||||||
|
class CRotateNodeCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
struct SNodeRotate
|
||||||
|
{
|
||||||
|
CSceneNode *pNode;
|
||||||
|
CVector3f initialPos;
|
||||||
|
CQuaternion initialRot;
|
||||||
|
CVector3f newPos;
|
||||||
|
CQuaternion newRot;
|
||||||
|
};
|
||||||
|
QList<SNodeRotate> mNodeList;
|
||||||
|
INodeEditor *mpEditor;
|
||||||
|
bool mCommandEnded;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CRotateNodeCommand();
|
||||||
|
CRotateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& pivot, const CQuaternion& delta, ETransformSpace transformSpace);
|
||||||
|
~CRotateNodeCommand();
|
||||||
|
int id() const;
|
||||||
|
bool mergeWith(const QUndoCommand *other);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
static CRotateNodeCommand* End();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CROTATENODECOMMAND_H
|
|
@ -0,0 +1,103 @@
|
||||||
|
#include "CScaleNodeCommand.h"
|
||||||
|
#include "EUndoCommand.h"
|
||||||
|
#include "../CWorldEditor.h"
|
||||||
|
|
||||||
|
CScaleNodeCommand::CScaleNodeCommand()
|
||||||
|
: QUndoCommand("Scale"),
|
||||||
|
mpEditor(nullptr),
|
||||||
|
mCommandEnded(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CScaleNodeCommand::CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& pivot, const CVector3f& delta)
|
||||||
|
: QUndoCommand("Scale"),
|
||||||
|
mpEditor(pEditor),
|
||||||
|
mCommandEnded(false)
|
||||||
|
{
|
||||||
|
mNodeList.reserve(nodes.size());
|
||||||
|
|
||||||
|
foreach (CSceneNode *pNode, nodes)
|
||||||
|
{
|
||||||
|
SNodeScale scale;
|
||||||
|
scale.pNode = pNode;
|
||||||
|
scale.initialPos = pNode->LocalPosition();
|
||||||
|
scale.initialScale = pNode->LocalScale();
|
||||||
|
pNode->Scale(delta);
|
||||||
|
scale.newPos = pNode->LocalPosition();
|
||||||
|
scale.newScale = pNode->LocalScale();
|
||||||
|
mNodeList.push_back(scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CScaleNodeCommand::~CScaleNodeCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int CScaleNodeCommand::id() const
|
||||||
|
{
|
||||||
|
return eScaleNodeCmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CScaleNodeCommand::mergeWith(const QUndoCommand *other)
|
||||||
|
{
|
||||||
|
if (mCommandEnded) return false;
|
||||||
|
|
||||||
|
if (other->id() == eScaleNodeCmd)
|
||||||
|
{
|
||||||
|
const CScaleNodeCommand *pCmd = static_cast<const CScaleNodeCommand*>(other);
|
||||||
|
|
||||||
|
if (pCmd->mCommandEnded)
|
||||||
|
{
|
||||||
|
mCommandEnded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mpEditor == pCmd->mpEditor) && (mNodeList.size() == pCmd->mNodeList.size()))
|
||||||
|
{
|
||||||
|
for (u32 iNode = 0; iNode < mNodeList.size(); iNode++)
|
||||||
|
{
|
||||||
|
mNodeList[iNode].newPos = pCmd->mNodeList[iNode].newPos;
|
||||||
|
mNodeList[iNode].newScale = pCmd->mNodeList[iNode].newScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScaleNodeCommand::undo()
|
||||||
|
{
|
||||||
|
if (!mpEditor) return;
|
||||||
|
|
||||||
|
foreach (SNodeScale scale, mNodeList)
|
||||||
|
{
|
||||||
|
scale.pNode->SetPosition(scale.initialPos);
|
||||||
|
scale.pNode->SetScale(scale.initialScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScaleNodeCommand::redo()
|
||||||
|
{
|
||||||
|
if (!mpEditor) return;
|
||||||
|
|
||||||
|
foreach (SNodeScale scale, mNodeList)
|
||||||
|
{
|
||||||
|
scale.pNode->SetPosition(scale.newPos);
|
||||||
|
scale.pNode->SetScale(scale.newScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
CScaleNodeCommand* CScaleNodeCommand::End()
|
||||||
|
{
|
||||||
|
CScaleNodeCommand *pCmd = new CScaleNodeCommand();
|
||||||
|
pCmd->mCommandEnded = true;
|
||||||
|
return pCmd;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef CSCALENODECOMMAND_H
|
||||||
|
#define CSCALENODECOMMAND_H
|
||||||
|
|
||||||
|
#include <QUndoCommand>
|
||||||
|
#include <QList>
|
||||||
|
#include <Scene/CSceneNode.h>
|
||||||
|
#include "../INodeEditor.h"
|
||||||
|
|
||||||
|
class CScaleNodeCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
struct SNodeScale
|
||||||
|
{
|
||||||
|
CSceneNode *pNode;
|
||||||
|
CVector3f initialPos;
|
||||||
|
CVector3f initialScale;
|
||||||
|
CVector3f newPos;
|
||||||
|
CVector3f newScale;
|
||||||
|
};
|
||||||
|
QList<SNodeScale> mNodeList;
|
||||||
|
INodeEditor *mpEditor;
|
||||||
|
bool mCommandEnded;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CScaleNodeCommand();
|
||||||
|
CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& pivot, const CVector3f& delta);
|
||||||
|
~CScaleNodeCommand();
|
||||||
|
int id() const;
|
||||||
|
bool mergeWith(const QUndoCommand *other);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
static CScaleNodeCommand* End();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CScaleNODECOMMAND_H
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include "CSelectNodeCommand.h"
|
||||||
|
#include "../CWorldEditor.h"
|
||||||
|
|
||||||
|
CSelectNodeCommand::CSelectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection)
|
||||||
|
: QUndoCommand("Select"),
|
||||||
|
mpEditor(pEditor),
|
||||||
|
mpNode(pNode),
|
||||||
|
mpSelection(&selection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSelectNodeCommand::undo()
|
||||||
|
{
|
||||||
|
if (mpNode->IsSelected())
|
||||||
|
{
|
||||||
|
mpNode->SetSelected(false);
|
||||||
|
|
||||||
|
for (auto it = mpSelection->begin(); it != mpSelection->end(); it++)
|
||||||
|
{
|
||||||
|
if (*it == mpNode)
|
||||||
|
{
|
||||||
|
mpSelection->erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateSelectionUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSelectNodeCommand::redo()
|
||||||
|
{
|
||||||
|
if (!mpNode->IsSelected())
|
||||||
|
{
|
||||||
|
mpNode->SetSelected(true);
|
||||||
|
mpSelection->push_back(mpNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpEditor->ExpandSelectionBounds(mpNode);
|
||||||
|
mpEditor->UpdateSelectionUI();
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef CSELECTNODECOMMAND_H
|
||||||
|
#define CSELECTNODECOMMAND_H
|
||||||
|
|
||||||
|
#include <QUndoCommand>
|
||||||
|
#include "../INodeEditor.h"
|
||||||
|
#include <Scene/CSceneNode.h>
|
||||||
|
|
||||||
|
class CSelectNodeCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
INodeEditor *mpEditor;
|
||||||
|
CSceneNode *mpNode;
|
||||||
|
QList<CSceneNode*> *mpSelection;
|
||||||
|
public:
|
||||||
|
CSelectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CSELECTNODECOMMAND_H
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include "CTranslateNodeCommand.h"
|
||||||
|
#include "EUndoCommand.h"
|
||||||
|
#include "../CWorldEditor.h"
|
||||||
|
|
||||||
|
CTranslateNodeCommand::CTranslateNodeCommand()
|
||||||
|
: QUndoCommand("Translate"),
|
||||||
|
mpEditor(nullptr),
|
||||||
|
mCommandEnded(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CTranslateNodeCommand::CTranslateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& delta, ETransformSpace transformSpace)
|
||||||
|
: QUndoCommand("Translate"),
|
||||||
|
mpEditor(pEditor),
|
||||||
|
mCommandEnded(false)
|
||||||
|
{
|
||||||
|
mNodeList.reserve(nodes.size());
|
||||||
|
|
||||||
|
foreach (CSceneNode *pNode, nodes)
|
||||||
|
{
|
||||||
|
SNodeTranslate translate;
|
||||||
|
translate.pNode = pNode;
|
||||||
|
translate.initialPos = pNode->LocalPosition();
|
||||||
|
pNode->Translate(delta, transformSpace);
|
||||||
|
translate.newPos = pNode->LocalPosition();
|
||||||
|
mNodeList.push_back(translate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CTranslateNodeCommand::~CTranslateNodeCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int CTranslateNodeCommand::id() const
|
||||||
|
{
|
||||||
|
return eTranslateNodeCmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTranslateNodeCommand::mergeWith(const QUndoCommand *other)
|
||||||
|
{
|
||||||
|
if (mCommandEnded) return false;
|
||||||
|
|
||||||
|
if (other->id() == eTranslateNodeCmd)
|
||||||
|
{
|
||||||
|
const CTranslateNodeCommand *pCmd = static_cast<const CTranslateNodeCommand*>(other);
|
||||||
|
|
||||||
|
if (pCmd->mCommandEnded)
|
||||||
|
{
|
||||||
|
mCommandEnded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mpEditor == pCmd->mpEditor) && (mNodeList.size() == pCmd->mNodeList.size()))
|
||||||
|
{
|
||||||
|
for (u32 iNode = 0; iNode < mNodeList.size(); iNode++)
|
||||||
|
mNodeList[iNode].newPos = pCmd->mNodeList[iNode].newPos;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTranslateNodeCommand::undo()
|
||||||
|
{
|
||||||
|
if (!mpEditor) return;
|
||||||
|
|
||||||
|
foreach (SNodeTranslate translate, mNodeList)
|
||||||
|
translate.pNode->SetPosition(translate.initialPos);
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTranslateNodeCommand::redo()
|
||||||
|
{
|
||||||
|
if (!mpEditor) return;
|
||||||
|
|
||||||
|
foreach (SNodeTranslate translate, mNodeList)
|
||||||
|
translate.pNode->SetPosition(translate.newPos);
|
||||||
|
|
||||||
|
mpEditor->RecalculateSelectionBounds();
|
||||||
|
mpEditor->UpdateGizmoUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
CTranslateNodeCommand* CTranslateNodeCommand::End()
|
||||||
|
{
|
||||||
|
CTranslateNodeCommand *pCmd = new CTranslateNodeCommand();
|
||||||
|
pCmd->mCommandEnded = true;
|
||||||
|
return pCmd;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef CTRANSLATENODECOMMAND_H
|
||||||
|
#define CTRANSLATENODECOMMAND_H
|
||||||
|
|
||||||
|
#include <QUndoCommand>
|
||||||
|
#include <QList>
|
||||||
|
#include <Scene/CSceneNode.h>
|
||||||
|
#include "../INodeEditor.h"
|
||||||
|
|
||||||
|
class CTranslateNodeCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
struct SNodeTranslate
|
||||||
|
{
|
||||||
|
CSceneNode *pNode;
|
||||||
|
CVector3f initialPos;
|
||||||
|
CVector3f newPos;
|
||||||
|
};
|
||||||
|
QList<SNodeTranslate> mNodeList;
|
||||||
|
INodeEditor *mpEditor;
|
||||||
|
bool mCommandEnded;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CTranslateNodeCommand();
|
||||||
|
CTranslateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& delta, ETransformSpace transformSpace);
|
||||||
|
~CTranslateNodeCommand();
|
||||||
|
int id() const;
|
||||||
|
bool mergeWith(const QUndoCommand *other);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
static CTranslateNodeCommand* End();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CTRANSLATENODECOMMAND_H
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef EUNDOCOMMAND
|
||||||
|
#define EUNDOCOMMAND
|
||||||
|
|
||||||
|
enum EUndoCommand
|
||||||
|
{
|
||||||
|
eTranslateNodeCmd,
|
||||||
|
eRotateNodeCmd,
|
||||||
|
eScaleNodeCmd
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EUNDOCOMMAND
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef UNDOCOMMANDS
|
||||||
|
#define UNDOCOMMANDS
|
||||||
|
|
||||||
|
#include "CTranslateNodeCommand.h"
|
||||||
|
#include "CRotateNodeCommand.h"
|
||||||
|
#include "CScaleNodeCommand.h"
|
||||||
|
#include "CSelectNodeCommand.h"
|
||||||
|
#include "CDeselectNodeCommand.h"
|
||||||
|
#include "CClearSelectionCommand.h"
|
||||||
|
#include "EUndoCommand.h"
|
||||||
|
|
||||||
|
#endif // UNDOCOMMANDS
|
||||||
|
|
Loading…
Reference in New Issue