Rotate gizmo transform functionality implemented
This commit is contained in:
parent
04b4f36da9
commit
614f73487e
|
@ -28,6 +28,26 @@ void CVector2f::Write(COutputStream &Output)
|
|||
Output.WriteFloat(y);
|
||||
}
|
||||
|
||||
float CVector2f::Magnitude() const
|
||||
{
|
||||
return sqrtf(SquaredMagnitude());
|
||||
}
|
||||
|
||||
float CVector2f::SquaredMagnitude() const
|
||||
{
|
||||
return Dot(*this);
|
||||
}
|
||||
|
||||
CVector2f CVector2f::Normalized() const
|
||||
{
|
||||
return *this / Magnitude();
|
||||
}
|
||||
|
||||
float CVector2f::Dot(const CVector2f& other) const
|
||||
{
|
||||
return ((x * other.x) + (y * other.y));
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator+(const CVector2f& src) const
|
||||
{
|
||||
CVector2f out;
|
||||
|
@ -142,11 +162,21 @@ bool CVector2f::operator!=(const CVector2f& other) const
|
|||
return (!(*this == other));
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator-() const
|
||||
{
|
||||
return CVector2f(-x, -y);
|
||||
}
|
||||
|
||||
float& CVector2f::operator[](long index)
|
||||
{
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
const float& CVector2f::operator[](long index) const
|
||||
{
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
const CVector2f CVector2f::skZero = CVector2f(0, 0);
|
||||
const CVector2f CVector2f::skOne = CVector2f(1, 1);
|
||||
|
|
|
@ -14,6 +14,11 @@ public:
|
|||
CVector2f(CInputStream& Input);
|
||||
void Write(COutputStream& Output);
|
||||
|
||||
float Magnitude() const;
|
||||
float SquaredMagnitude() const;
|
||||
CVector2f Normalized() const;
|
||||
float Dot(const CVector2f& other) const;
|
||||
|
||||
CVector2f operator+(const CVector2f& other) const;
|
||||
CVector2f operator-(const CVector2f& other) const;
|
||||
CVector2f operator*(const CVector2f& other) const;
|
||||
|
@ -32,7 +37,9 @@ public:
|
|||
void operator/=(const float other);
|
||||
bool operator==(const CVector2f& other) const;
|
||||
bool operator!=(const CVector2f& other) const;
|
||||
CVector2f operator-() const;
|
||||
float& operator[](long index);
|
||||
const float& operator[](long index) const;
|
||||
|
||||
// Static Members
|
||||
static const CVector2f skZero;
|
||||
|
|
|
@ -65,7 +65,7 @@ float CVector3f::SquaredMagnitude() const
|
|||
|
||||
CVector3f CVector3f::Normalized() const
|
||||
{
|
||||
return *this / Magnitude();;
|
||||
return *this / Magnitude();
|
||||
}
|
||||
|
||||
float CVector3f::Dot(const CVector3f& other) const
|
||||
|
|
|
@ -157,6 +157,13 @@ void CCamera::LoadMatrices()
|
|||
CGraphics::UpdateMVPBlock();
|
||||
}
|
||||
|
||||
void CCamera::LoadRotationOnlyMatrices()
|
||||
{
|
||||
CGraphics::sMVPBlock.ViewMatrix = RotationOnlyViewMatrix();
|
||||
CGraphics::sMVPBlock.ProjectionMatrix = ProjectionMatrix();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
}
|
||||
|
||||
// ************ GETTERS ************
|
||||
CVector3f CCamera::Position() const
|
||||
{
|
||||
|
@ -187,6 +194,17 @@ const CMatrix4f& CCamera::ViewMatrix()
|
|||
return mCachedViewMatrix;
|
||||
}
|
||||
|
||||
const CMatrix4f& CCamera::RotationOnlyViewMatrix()
|
||||
{
|
||||
if (mViewOutdated)
|
||||
CalculateView();
|
||||
|
||||
return CMatrix4f(mCachedViewMatrix[0][0], mCachedViewMatrix[0][1], mCachedViewMatrix[0][2], 0.f,
|
||||
mCachedViewMatrix[1][0], mCachedViewMatrix[1][1], mCachedViewMatrix[1][2], 0.f,
|
||||
mCachedViewMatrix[2][0], mCachedViewMatrix[2][1], mCachedViewMatrix[2][2], 0.f,
|
||||
mCachedViewMatrix[3][0], mCachedViewMatrix[3][1], mCachedViewMatrix[3][2], 1.f);
|
||||
}
|
||||
|
||||
const CMatrix4f& CCamera::ProjectionMatrix()
|
||||
{
|
||||
if (mProjectionOutdated)
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
void ProcessMouseInput(EKeyInputs KeyFlags, EMouseInputs MouseFlags, float XMovement, float YMovement);
|
||||
CRay CastRay(CVector2f DeviceCoords);
|
||||
void LoadMatrices();
|
||||
void LoadRotationOnlyMatrices();
|
||||
|
||||
// Getters
|
||||
CVector3f Position() const;
|
||||
|
@ -52,6 +53,7 @@ public:
|
|||
float GetYaw() const;
|
||||
float GetPitch() const;
|
||||
const CMatrix4f& ViewMatrix();
|
||||
const CMatrix4f& RotationOnlyViewMatrix();
|
||||
const CMatrix4f& ProjectionMatrix();
|
||||
|
||||
// Setters
|
||||
|
|
|
@ -245,6 +245,9 @@ void CRenderer::RenderBloom()
|
|||
glBlendFunc(GL_DST_ALPHA, GL_ZERO);
|
||||
CDrawUtil::DrawSquare();
|
||||
}
|
||||
|
||||
// Clean up
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void CRenderer::RenderSky(CModel *pSkyboxModel, CVector3f CameraPosition)
|
||||
|
|
|
@ -201,7 +201,15 @@ void CSceneNode::Translate(const CVector3f& translation, ETransformSpace transfo
|
|||
|
||||
void CSceneNode::Rotate(const CQuaternion& rotation, ETransformSpace transformSpace)
|
||||
{
|
||||
switch (transformSpace)
|
||||
{
|
||||
case eWorldTransform:
|
||||
mRotation = rotation * mRotation;
|
||||
break;
|
||||
case eLocalTransform:
|
||||
mRotation *= rotation;
|
||||
break;
|
||||
}
|
||||
MarkTransformChanged();
|
||||
}
|
||||
|
||||
|
@ -370,6 +378,30 @@ void CSceneNode::SetName(const std::string& Name)
|
|||
mName = Name;
|
||||
}
|
||||
|
||||
void CSceneNode::SetPosition(const CVector3f& position)
|
||||
{
|
||||
mPosition = position;
|
||||
MarkTransformChanged();
|
||||
}
|
||||
|
||||
void CSceneNode::SetRotation(const CQuaternion& rotation)
|
||||
{
|
||||
mRotation = rotation;
|
||||
MarkTransformChanged();
|
||||
}
|
||||
|
||||
void CSceneNode::SetRotation(const CVector3f& rotEuler)
|
||||
{
|
||||
mRotation = CQuaternion::FromEuler(rotEuler);
|
||||
MarkTransformChanged();
|
||||
}
|
||||
|
||||
void CSceneNode::SetScale(const CVector3f& scale)
|
||||
{
|
||||
mScale = scale;
|
||||
MarkTransformChanged();
|
||||
}
|
||||
|
||||
void CSceneNode::SetMouseHovering(bool Hovering)
|
||||
{
|
||||
mMouseHovering = Hovering;
|
||||
|
|
|
@ -98,6 +98,10 @@ public:
|
|||
|
||||
// Setters
|
||||
void SetName(const std::string& Name);
|
||||
void SetPosition(const CVector3f& position);
|
||||
void SetRotation(const CQuaternion& rotation);
|
||||
void SetRotation(const CVector3f& rotEuler);
|
||||
void SetScale(const CVector3f& scale);
|
||||
void SetMouseHovering(bool Hovering);
|
||||
void SetSelected(bool Selected);
|
||||
void SetVisible(bool Visible);
|
||||
|
|
279
UI/CGizmo.cpp
279
UI/CGizmo.cpp
|
@ -3,6 +3,10 @@
|
|||
#include <Core/CRenderer.h>
|
||||
#include <Core/CResCache.h>
|
||||
#include <Core/CDrawUtil.h>
|
||||
#include <Core/Log.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <iostream>
|
||||
|
||||
CGizmo::CGizmo()
|
||||
|
@ -11,8 +15,13 @@ CGizmo::CGizmo()
|
|||
|
||||
SetMode(eTranslate);
|
||||
mSelectedAxes = eNone;
|
||||
mTransformSpace = eWorldTransform;
|
||||
mGizmoSize = 1.f;
|
||||
mCameraDist = 0.f;
|
||||
mIsTransforming = false;
|
||||
mHasTransformed = false;
|
||||
mWrapOffset = 0.f;
|
||||
mEnableCursorWrap = true;
|
||||
|
||||
mPosition = CVector3f::skZero;
|
||||
mRotation = CQuaternion::skIdentity;
|
||||
|
@ -43,7 +52,8 @@ void CGizmo::AddToRenderer(CRenderer *pRenderer)
|
|||
CModel *pModel = pPart->pModel;
|
||||
|
||||
// Determine whether to use the mat set for regular (0) or highlight (1)
|
||||
bool isHighlighted = (mSelectedAxes & pPart->modelAxes) == pPart->modelAxes;
|
||||
EGizmoAxes partAxes = pPart->modelAxes;
|
||||
bool isHighlighted = (partAxes != eNone) && ((mSelectedAxes & partAxes) == pPart->modelAxes);
|
||||
u32 setID = (isHighlighted ? 1 : 0);
|
||||
|
||||
// Add to renderer...
|
||||
|
@ -58,24 +68,21 @@ void CGizmo::AddToRenderer(CRenderer *pRenderer)
|
|||
|
||||
void CGizmo::DrawAsset(ERenderOptions options, u32 asset)
|
||||
{
|
||||
CGraphics::sMVPBlock.ModelMatrix = mTransform.ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
// Determine which SModelPart array to use
|
||||
if (asset >= mNumCurrentParts) return;
|
||||
SModelPart *pPart = mpCurrentParts;
|
||||
|
||||
// Draw model
|
||||
bool isHighlighted = (mSelectedAxes & pPart[asset].modelAxes) == pPart[asset].modelAxes;
|
||||
u32 setID = (isHighlighted ? 1 : 0);
|
||||
pPart[asset].pModel->Draw((ERenderOptions) 0, setID);
|
||||
}
|
||||
|
||||
void CGizmo::DrawRotationOutline()
|
||||
{
|
||||
CGraphics::sMVPBlock.ModelMatrix = mBillboardTransform.ToMatrix4f();
|
||||
// Set model matrix
|
||||
CGraphics::sMVPBlock.ModelMatrix = (pPart[asset].isBillboard ? mBillboardTransform.ToMatrix4f() : mTransform.ToMatrix4f());
|
||||
CGraphics::UpdateMVPBlock();
|
||||
smRotateClipOutline.pModel->Draw((ERenderOptions) 0, 0);
|
||||
|
||||
// Choose material set
|
||||
EGizmoAxes partAxes = pPart[asset].modelAxes;
|
||||
bool isHighlighted = (partAxes != eNone) && ((mSelectedAxes & partAxes) == pPart[asset].modelAxes);
|
||||
u32 setID = (isHighlighted ? 1 : 0);
|
||||
|
||||
// Draw model
|
||||
pPart[asset].pModel->Draw((ERenderOptions) 0, setID);
|
||||
}
|
||||
|
||||
void CGizmo::IncrementSize()
|
||||
|
@ -99,15 +106,17 @@ void CGizmo::DecrementSize()
|
|||
void CGizmo::UpdateForCamera(const CCamera &camera)
|
||||
{
|
||||
CVector3f camPos = camera.Position();
|
||||
mCameraDist = mPosition.Distance(camPos);
|
||||
mFlipScaleX = camPos.x < mPosition.x;
|
||||
mFlipScaleY = camPos.y < mPosition.y;
|
||||
mFlipScaleZ = camPos.z < mPosition.z;
|
||||
|
||||
if ((!mIsTransforming) || (mMode != eTranslate))
|
||||
mCameraDist = mPosition.Distance(camPos);
|
||||
|
||||
// todo: make this cleaner...
|
||||
CVector3f billDir = (mPosition - camPos).Normalized();
|
||||
CVector3f axis = CVector3f::skForward.Cross(billDir);
|
||||
float angle = acos(CVector3f::skForward.Dot(billDir));
|
||||
float angle = acosf(CVector3f::skForward.Dot(billDir));
|
||||
angle = 180 + (angle * 180 / 3.14159265358979323846f);
|
||||
mBillboardRotation = CQuaternion::FromAxisAngle(angle, axis);
|
||||
}
|
||||
|
@ -116,6 +125,7 @@ bool CGizmo::CheckSelectedAxes(const CRay &ray)
|
|||
{
|
||||
// todo: fix raycasting for rotate gizmo; currently it can hit the invisible back side of the model
|
||||
CRay localRay = ray.Transformed(mTransform.Inverse());
|
||||
CRay billRay = ray.Transformed(mBillboardTransform.Inverse());
|
||||
|
||||
// Do raycast on each model
|
||||
SModelPart *pPart = mpCurrentParts;
|
||||
|
@ -135,11 +145,12 @@ bool CGizmo::CheckSelectedAxes(const CRay &ray)
|
|||
}
|
||||
|
||||
CModel *pModel = pPart->pModel;
|
||||
CRay& partRay = (pPart->isBillboard ? billRay : localRay);
|
||||
|
||||
// Ray/Model AABox test - allow buffer room because lines are small
|
||||
CAABox AABox = pModel->AABox();
|
||||
AABox.ExpandBy(CVector3f::skOne);
|
||||
bool modelBoxCheck = Math::RayBoxIntersection(localRay, AABox).first;
|
||||
bool modelBoxCheck = Math::RayBoxIntersection(partRay, AABox).first;
|
||||
|
||||
if (modelBoxCheck)
|
||||
{
|
||||
|
@ -150,7 +161,7 @@ bool CGizmo::CheckSelectedAxes(const CRay &ray)
|
|||
{
|
||||
// Skip surface/box check - since we use lines the boxes might be too small
|
||||
SSurface *pSurf = pModel->GetSurface(iSurf);
|
||||
std::pair<bool,float> surfCheck = pSurf->IntersectsRay(localRay, 0.05f);
|
||||
std::pair<bool,float> surfCheck = pSurf->IntersectsRay(partRay, 0.05f);
|
||||
|
||||
if (surfCheck.first)
|
||||
{
|
||||
|
@ -186,8 +197,11 @@ bool CGizmo::CheckSelectedAxes(const CRay &ray)
|
|||
return (a.dist < b.dist);
|
||||
});
|
||||
|
||||
CRay& partRay = (pPart->isBillboard ? billRay : localRay);
|
||||
mSelectedAxes = results.front().pPart->modelAxes;
|
||||
return true;
|
||||
mHitPoint = mTransform * partRay.PointOnRay(results.front().dist);
|
||||
|
||||
return (mSelectedAxes != eNone);
|
||||
}
|
||||
|
||||
u32 CGizmo::NumSelectedAxes()
|
||||
|
@ -207,14 +221,43 @@ void CGizmo::ResetSelectedAxes()
|
|||
|
||||
void CGizmo::StartTransform()
|
||||
{
|
||||
mIsTransforming = true;
|
||||
mHasTransformed = false;
|
||||
mWrapOffset = CVector2f::skZero;
|
||||
mSetOffset = false;
|
||||
mTotalTranslation = CVector3f::skZero;
|
||||
mTotalRotation = CQuaternion::skIdentity;
|
||||
mTotalRotation = CVector3f::skZero;
|
||||
mCurrentRotation = CQuaternion::skIdentity;
|
||||
mTotalScale = CVector3f::skOne;
|
||||
|
||||
// Set rotation clockwise direction
|
||||
if (mMode == eRotate)
|
||||
{
|
||||
CVector3f axis;
|
||||
if (mSelectedAxes & eX) axis = mRotation.XAxis();
|
||||
else if (mSelectedAxes & eY) axis = mRotation.YAxis();
|
||||
else axis = mRotation.ZAxis();
|
||||
|
||||
CVector3f gizmoToHit = (mHitPoint - mPosition).Normalized();
|
||||
mClockwiseDir = axis.Cross(gizmoToHit);
|
||||
}
|
||||
}
|
||||
|
||||
bool CGizmo::TransformFromInput(const CRay& ray, const CCamera& camera)
|
||||
bool CGizmo::TransformFromInput(const CRay& ray, CCamera& camera)
|
||||
{
|
||||
// Wrap cursor (this has no effect until the next time this function is called)
|
||||
if (mEnableCursorWrap && (mMode != eTranslate))
|
||||
WrapCursor();
|
||||
|
||||
// Calculate normalized cursor position
|
||||
QPoint cursorPos = QCursor::pos();
|
||||
QRect geom = QApplication::desktop()->screenGeometry();
|
||||
CVector2f mouseCoords(
|
||||
(((2.f * cursorPos.x()) / geom.width()) - 1.f),
|
||||
(1.f - ((2.f * cursorPos.y()) / geom.height()))
|
||||
);
|
||||
|
||||
// Translate
|
||||
if (mMode == eTranslate)
|
||||
{
|
||||
// Create translate plane
|
||||
|
@ -273,8 +316,16 @@ bool CGizmo::TransformFromInput(const CRay& ray, const CCamera& camera)
|
|||
else
|
||||
{
|
||||
mDeltaTranslation = mRotation.Inverse() * (newPos - mPosition + mTranslateOffset);
|
||||
if (!(mSelectedAxes & eX)) mDeltaTranslation.x = 0.f;
|
||||
if (!(mSelectedAxes & eY)) mDeltaTranslation.y = 0.f;
|
||||
if (!(mSelectedAxes & eZ)) mDeltaTranslation.z = 0.f;
|
||||
|
||||
mTotalTranslation += mDeltaTranslation;
|
||||
mPosition = newPos + mTranslateOffset;
|
||||
mPosition += mRotation * mDeltaTranslation;
|
||||
|
||||
if (!mHasTransformed && (mDeltaTranslation != CVector3f::skZero))
|
||||
mHasTransformed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -286,11 +337,62 @@ bool CGizmo::TransformFromInput(const CRay& ray, const CCamera& camera)
|
|||
}
|
||||
}
|
||||
|
||||
// Rotate
|
||||
else if (mMode == eRotate)
|
||||
{
|
||||
// Choose rotation axis
|
||||
CVector3f axis;
|
||||
if (mSelectedAxes & eX) axis = CVector3f::skUnitX;
|
||||
else if (mSelectedAxes & eY) axis = CVector3f::skUnitY;
|
||||
else axis = CVector3f::skUnitZ;
|
||||
|
||||
// Convert hit point + clockwise direction into a line in screen space
|
||||
// Clockwise direction is set in StartTransform(). Is there a cleaner way to calculate the direction?
|
||||
CMatrix4f VP = camera.ViewMatrix().Transpose() * camera.ProjectionMatrix().Transpose();
|
||||
CVector2f lineOrigin = (mHitPoint * VP).xy();
|
||||
CVector2f lineDir = (((mHitPoint + mClockwiseDir) * VP).xy() - lineOrigin).Normalized();
|
||||
float rotAmount = lineDir.Dot(mouseCoords + mWrapOffset - lineOrigin) * 180.f;
|
||||
|
||||
// Set offset
|
||||
if (!mSetOffset)
|
||||
{
|
||||
mRotateOffset = -rotAmount;
|
||||
mDeltaRotation = CQuaternion::skIdentity;
|
||||
mSetOffset = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apply rotation
|
||||
rotAmount += mRotateOffset;
|
||||
CQuaternion oldRot = mCurrentRotation;
|
||||
mCurrentRotation = CQuaternion::FromAxisAngle(rotAmount, axis);
|
||||
mDeltaRotation = mCurrentRotation * oldRot.Inverse();
|
||||
|
||||
if (mTransformSpace == eLocalTransform)
|
||||
mRotation *= mDeltaRotation;
|
||||
|
||||
// Add to total
|
||||
if (mSelectedAxes & eX) mTotalRotation.x = rotAmount;
|
||||
else if (mSelectedAxes & eY) mTotalRotation.y = rotAmount;
|
||||
else mTotalRotation.z = rotAmount;
|
||||
|
||||
if (!mHasTransformed && (rotAmount != 0.f))
|
||||
mHasTransformed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGizmo::EndTransform()
|
||||
{
|
||||
mIsTransforming = false;
|
||||
}
|
||||
|
||||
bool CGizmo::HasTransformed()
|
||||
{
|
||||
return mHasTransformed;
|
||||
}
|
||||
|
||||
CGizmo::EGizmoMode CGizmo::Mode()
|
||||
|
@ -313,6 +415,36 @@ CVector3f CGizmo::TotalTranslation()
|
|||
return mTotalTranslation;
|
||||
}
|
||||
|
||||
CQuaternion CGizmo::Rotation()
|
||||
{
|
||||
return mRotation;
|
||||
}
|
||||
|
||||
CQuaternion CGizmo::DeltaRotation()
|
||||
{
|
||||
return mDeltaRotation;
|
||||
}
|
||||
|
||||
CVector3f CGizmo::TotalRotation()
|
||||
{
|
||||
return mTotalRotation;
|
||||
}
|
||||
|
||||
CVector3f CGizmo::Scale()
|
||||
{
|
||||
return mScale;
|
||||
}
|
||||
|
||||
CVector3f CGizmo::DeltaScale()
|
||||
{
|
||||
return mDeltaScale;
|
||||
}
|
||||
|
||||
CVector3f CGizmo::TotalScale()
|
||||
{
|
||||
return mTotalScale;
|
||||
}
|
||||
|
||||
void CGizmo::SetMode(EGizmoMode mode)
|
||||
{
|
||||
mMode = mode;
|
||||
|
@ -328,7 +460,7 @@ void CGizmo::SetMode(EGizmoMode mode)
|
|||
|
||||
case eRotate:
|
||||
mpCurrentParts = smRotateModels;
|
||||
mNumCurrentParts = 4;
|
||||
mNumCurrentParts = 5;
|
||||
mDeltaTranslation = CVector3f::skZero;
|
||||
mDeltaScale = CVector3f::skOne;
|
||||
break;
|
||||
|
@ -342,47 +474,59 @@ void CGizmo::SetMode(EGizmoMode mode)
|
|||
}
|
||||
}
|
||||
|
||||
void CGizmo::SetTransformSpace(ETransformSpace space)
|
||||
{
|
||||
mTransformSpace = space;
|
||||
}
|
||||
|
||||
void CGizmo::SetPosition(const CVector3f& position)
|
||||
{
|
||||
mPosition = position;
|
||||
}
|
||||
|
||||
void CGizmo::SetOrientation(const CQuaternion& orientation)
|
||||
void CGizmo::SetRotation(const CQuaternion& orientation)
|
||||
{
|
||||
mRotation = orientation;
|
||||
}
|
||||
|
||||
void CGizmo::EnableCursorWrap(bool wrap)
|
||||
{
|
||||
mEnableCursorWrap = wrap;
|
||||
}
|
||||
|
||||
// ************ PRIVATE STATIC ************
|
||||
void CGizmo::LoadModels()
|
||||
{
|
||||
if (!smModelsLoaded)
|
||||
{
|
||||
smTranslateModels[CGIZMO_TRANSLATE_X] = SModelPart(eX, true, (CModel*) gResCache.GetResource("../resources/editor/TranslateX.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_Y] = SModelPart(eY, true, (CModel*) gResCache.GetResource("../resources/editor/TranslateY.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_Z] = SModelPart(eZ, true, (CModel*) gResCache.GetResource("../resources/editor/TranslateZ.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_LINES_XY] = SModelPart(eXY, true, (CModel*) gResCache.GetResource("../resources/editor/TranslateLinesXY.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_LINES_XZ] = SModelPart(eXZ, true, (CModel*) gResCache.GetResource("../resources/editor/TranslateLinesXZ.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_LINES_YZ] = SModelPart(eYZ, true, (CModel*) gResCache.GetResource("../resources/editor/TranslateLinesYZ.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_POLY_XY] = SModelPart(eXY, false, (CModel*) gResCache.GetResource("../resources/editor/TranslatePolyXY.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_POLY_XZ] = SModelPart(eXZ, false, (CModel*) gResCache.GetResource("../resources/editor/TranslatePolyXZ.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_POLY_YZ] = SModelPart(eYZ, false, (CModel*) gResCache.GetResource("../resources/editor/TranslatePolyYZ.CMDL"));
|
||||
Log::Write("Loading transform gizmo models");
|
||||
|
||||
smRotateModels[CGIZMO_ROTATE_X] = SModelPart(eX, true, (CModel*) gResCache.GetResource("../resources/editor/RotateX.CMDL"));
|
||||
smRotateModels[CGIZMO_ROTATE_Y] = SModelPart(eY, true, (CModel*) gResCache.GetResource("../resources/editor/RotateY.CMDL"));
|
||||
smRotateModels[CGIZMO_ROTATE_Z] = SModelPart(eZ, true, (CModel*) gResCache.GetResource("../resources/editor/RotateZ.CMDL"));
|
||||
smRotateModels[CGIZMO_ROTATE_XYZ] = SModelPart(eXYZ, false, (CModel*) gResCache.GetResource("../resources/editor/RotateXYZ.CMDL"));
|
||||
smRotateClipOutline = SModelPart(eNone, false, (CModel*) gResCache.GetResource("../resources/editor/RotateClipOutline.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_X] = SModelPart(eX, true, false, (CModel*) gResCache.GetResource("../resources/editor/TranslateX.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_Y] = SModelPart(eY, true, false, (CModel*) gResCache.GetResource("../resources/editor/TranslateY.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_Z] = SModelPart(eZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/TranslateZ.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_LINES_XY] = SModelPart(eXY, true, false, (CModel*) gResCache.GetResource("../resources/editor/TranslateLinesXY.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_LINES_XZ] = SModelPart(eXZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/TranslateLinesXZ.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_LINES_YZ] = SModelPart(eYZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/TranslateLinesYZ.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_POLY_XY] = SModelPart(eXY, false, false, (CModel*) gResCache.GetResource("../resources/editor/TranslatePolyXY.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_POLY_XZ] = SModelPart(eXZ, false, false, (CModel*) gResCache.GetResource("../resources/editor/TranslatePolyXZ.CMDL"));
|
||||
smTranslateModels[CGIZMO_TRANSLATE_POLY_YZ] = SModelPart(eYZ, false, false, (CModel*) gResCache.GetResource("../resources/editor/TranslatePolyYZ.CMDL"));
|
||||
|
||||
smScaleModels[CGIZMO_SCALE_X] = SModelPart(eX, true, (CModel*) gResCache.GetResource("../resources/editor/ScaleX.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_Y] = SModelPart(eY, true, (CModel*) gResCache.GetResource("../resources/editor/ScaleY.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_Z] = SModelPart(eZ, true, (CModel*) gResCache.GetResource("../resources/editor/ScaleZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_LINES_XY] = SModelPart(eXY, true, (CModel*) gResCache.GetResource("../resources/editor/ScaleLinesXY.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_LINES_XZ] = SModelPart(eXZ, true, (CModel*) gResCache.GetResource("../resources/editor/ScaleLinesXZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_LINES_YZ] = SModelPart(eYZ, true, (CModel*) gResCache.GetResource("../resources/editor/ScaleLinesYZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_POLY_XY] = SModelPart(eXY, false, (CModel*) gResCache.GetResource("../resources/editor/ScalePolyXY.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_POLY_XZ] = SModelPart(eXZ, false, (CModel*) gResCache.GetResource("../resources/editor/ScalePolyXZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_POLY_YZ] = SModelPart(eYZ, false, (CModel*) gResCache.GetResource("../resources/editor/ScalePolyYZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_XYZ] = SModelPart(eXYZ, true, (CModel*) gResCache.GetResource("../resources/editor/ScaleXYZ.CMDL"));
|
||||
smRotateModels[CGIZMO_ROTATE_OUTLINE] = SModelPart(eNone, true, true, (CModel*) gResCache.GetResource("../resources/editor/RotateClipOutline.CMDL"));
|
||||
smRotateModels[CGIZMO_ROTATE_X] = SModelPart(eX, true, false, (CModel*) gResCache.GetResource("../resources/editor/RotateX.CMDL"));
|
||||
smRotateModels[CGIZMO_ROTATE_Y] = SModelPart(eY, true, false, (CModel*) gResCache.GetResource("../resources/editor/RotateY.CMDL"));
|
||||
smRotateModels[CGIZMO_ROTATE_Z] = SModelPart(eZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/RotateZ.CMDL"));
|
||||
smRotateModels[CGIZMO_ROTATE_XYZ] = SModelPart(eXYZ, false, false, (CModel*) gResCache.GetResource("../resources/editor/RotateXYZ.CMDL"));
|
||||
|
||||
smScaleModels[CGIZMO_SCALE_X] = SModelPart(eX, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScaleX.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_Y] = SModelPart(eY, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScaleY.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_Z] = SModelPart(eZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScaleZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_LINES_XY] = SModelPart(eXY, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScaleLinesXY.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_LINES_XZ] = SModelPart(eXZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScaleLinesXZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_LINES_YZ] = SModelPart(eYZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScaleLinesYZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_POLY_XY] = SModelPart(eXY, false, false, (CModel*) gResCache.GetResource("../resources/editor/ScalePolyXY.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_POLY_XZ] = SModelPart(eXZ, false, false, (CModel*) gResCache.GetResource("../resources/editor/ScalePolyXZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_POLY_YZ] = SModelPart(eYZ, false, false, (CModel*) gResCache.GetResource("../resources/editor/ScalePolyYZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_XYZ] = SModelPart(eXYZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScaleXYZ.CMDL"));
|
||||
|
||||
smModelsLoaded = true;
|
||||
}
|
||||
|
@ -395,10 +539,10 @@ void CGizmo::UpdateTransform()
|
|||
// Rotation and position values are just saved directly
|
||||
mScale = mGizmoSize * (mCameraDist / 10.f);
|
||||
|
||||
// Scale also factors in delta scale + axis flip if mode is Scale.
|
||||
// Scale also factors in total scale + axis flip if mode is Scale.
|
||||
if (mMode == eScale)
|
||||
{
|
||||
mScale *= mDeltaScale;
|
||||
mScale *= mTotalScale;
|
||||
|
||||
if (mFlipScaleX) mScale.x = -mScale.x;
|
||||
if (mFlipScaleY) mScale.y = -mScale.y;
|
||||
|
@ -421,9 +565,40 @@ void CGizmo::UpdateTransform()
|
|||
}
|
||||
}
|
||||
|
||||
void CGizmo::WrapCursor()
|
||||
{
|
||||
QRect geom = QApplication::desktop()->screenGeometry();
|
||||
QPoint cursorPos = QCursor::pos();
|
||||
|
||||
// Horizontal
|
||||
if (cursorPos.x() == geom.width() - 1)
|
||||
{
|
||||
QCursor::setPos(1, cursorPos.y());
|
||||
mWrapOffset.x += 2.f;
|
||||
}
|
||||
else if (cursorPos.x() == 0)
|
||||
{
|
||||
QCursor::setPos(geom.width() - 2, cursorPos.y());
|
||||
mWrapOffset.x -= 2.f;
|
||||
}
|
||||
|
||||
// Vertical
|
||||
cursorPos = QCursor::pos(); // Grab again to account for changes on horizontal wrap
|
||||
|
||||
if (cursorPos.y() == geom.height() - 1)
|
||||
{
|
||||
QCursor::setPos(cursorPos.x(), 1);
|
||||
mWrapOffset.y -= 2.f;
|
||||
}
|
||||
else if (cursorPos.y() == 0)
|
||||
{
|
||||
QCursor::setPos(cursorPos.x(), geom.height() - 2);
|
||||
mWrapOffset.y += 2.f;
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
bool CGizmo::smModelsLoaded = false;
|
||||
CGizmo::SModelPart CGizmo::smTranslateModels[9];
|
||||
CGizmo::SModelPart CGizmo::smRotateModels[4];
|
||||
CGizmo::SModelPart CGizmo::smRotateModels[5];
|
||||
CGizmo::SModelPart CGizmo::smScaleModels[10];
|
||||
CGizmo::SModelPart CGizmo::smRotateClipOutline;
|
||||
|
|
46
UI/CGizmo.h
46
UI/CGizmo.h
|
@ -5,6 +5,7 @@
|
|||
#include <Common/CQuaternion.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <Common/EnumUtil.h>
|
||||
#include <Common/ETransformSpace.h>
|
||||
#include <Core/CCamera.h>
|
||||
#include <Core/CToken.h>
|
||||
#include <Core/IRenderable.h>
|
||||
|
@ -19,10 +20,11 @@
|
|||
#define CGIZMO_TRANSLATE_POLY_XY 6
|
||||
#define CGIZMO_TRANSLATE_POLY_XZ 7
|
||||
#define CGIZMO_TRANSLATE_POLY_YZ 8
|
||||
#define CGIZMO_ROTATE_X 0
|
||||
#define CGIZMO_ROTATE_Y 1
|
||||
#define CGIZMO_ROTATE_Z 2
|
||||
#define CGIZMO_ROTATE_XYZ 3
|
||||
#define CGIZMO_ROTATE_OUTLINE 0
|
||||
#define CGIZMO_ROTATE_X 1
|
||||
#define CGIZMO_ROTATE_Y 2
|
||||
#define CGIZMO_ROTATE_Z 3
|
||||
#define CGIZMO_ROTATE_XYZ 4
|
||||
#define CGIZMO_SCALE_X 0
|
||||
#define CGIZMO_SCALE_Y 1
|
||||
#define CGIZMO_SCALE_Z 2
|
||||
|
@ -57,10 +59,16 @@ public:
|
|||
private:
|
||||
EGizmoMode mMode;
|
||||
EGizmoAxes mSelectedAxes;
|
||||
ETransformSpace mTransformSpace;
|
||||
CVector3f mHitPoint;
|
||||
CTransform4f mBillboardTransform;
|
||||
CQuaternion mBillboardRotation;
|
||||
float mGizmoSize;
|
||||
float mCameraDist;
|
||||
bool mIsTransforming;
|
||||
bool mHasTransformed;
|
||||
CVector2f mWrapOffset;
|
||||
bool mEnableCursorWrap;
|
||||
|
||||
CTransform4f mTransform;
|
||||
CVector3f mPosition;
|
||||
|
@ -68,7 +76,8 @@ private:
|
|||
CVector3f mTotalTranslation;
|
||||
CQuaternion mRotation;
|
||||
CQuaternion mDeltaRotation;
|
||||
CQuaternion mTotalRotation;
|
||||
CQuaternion mCurrentRotation;
|
||||
CVector3f mTotalRotation; // This is a CVector3f because this value displays on the UI and a quat would cause rollover
|
||||
CVector3f mScale;
|
||||
CVector3f mDeltaScale;
|
||||
CVector3f mTotalScale;
|
||||
|
@ -77,21 +86,24 @@ private:
|
|||
bool mFlipScaleZ;
|
||||
|
||||
CPlane mTranslatePlane;
|
||||
CVector3f mLastTranslatePosition;
|
||||
CVector3f mTranslateOffset;
|
||||
float mRotateOffset;
|
||||
bool mSetOffset;
|
||||
|
||||
CVector3f mRotateHitPoint;
|
||||
CVector3f mClockwiseDir;
|
||||
|
||||
struct SModelPart
|
||||
{
|
||||
EGizmoAxes modelAxes;
|
||||
bool enableRayCast;
|
||||
bool isBillboard;
|
||||
CModel *pModel;
|
||||
CToken modelToken;
|
||||
|
||||
SModelPart() {}
|
||||
SModelPart(EGizmoAxes axes, bool rayCastOn, CModel *_pModel) :
|
||||
modelAxes(axes), enableRayCast(rayCastOn), pModel(_pModel), modelToken(_pModel) {}
|
||||
SModelPart(EGizmoAxes axes, bool rayCastOn, bool billboard, CModel *_pModel) :
|
||||
modelAxes(axes), enableRayCast(rayCastOn), isBillboard(billboard), pModel(_pModel), modelToken(_pModel) {}
|
||||
};
|
||||
SModelPart *mpCurrentParts;
|
||||
u32 mNumCurrentParts;
|
||||
|
@ -99,9 +111,8 @@ private:
|
|||
// Static
|
||||
static bool smModelsLoaded;
|
||||
static SModelPart smTranslateModels[9];
|
||||
static SModelPart smRotateModels[4];
|
||||
static SModelPart smRotateModels[5];
|
||||
static SModelPart smScaleModels[10];
|
||||
static SModelPart smRotateClipOutline;
|
||||
|
||||
public:
|
||||
CGizmo();
|
||||
|
@ -109,7 +120,6 @@ public:
|
|||
|
||||
void AddToRenderer(CRenderer *pRenderer);
|
||||
void DrawAsset(ERenderOptions options, u32 asset);
|
||||
void DrawRotationOutline();
|
||||
|
||||
void IncrementSize();
|
||||
void DecrementSize();
|
||||
|
@ -118,20 +128,30 @@ public:
|
|||
u32 NumSelectedAxes();
|
||||
void ResetSelectedAxes();
|
||||
void StartTransform();
|
||||
bool TransformFromInput(const CRay& ray, const CCamera& camera);
|
||||
bool TransformFromInput(const CRay& ray, CCamera& camera);
|
||||
void EndTransform();
|
||||
bool HasTransformed();
|
||||
|
||||
EGizmoMode Mode();
|
||||
CVector3f Position();
|
||||
CVector3f DeltaTranslation();
|
||||
CVector3f TotalTranslation();
|
||||
CQuaternion Rotation();
|
||||
CQuaternion DeltaRotation();
|
||||
CVector3f TotalRotation();
|
||||
CVector3f Scale();
|
||||
CVector3f DeltaScale();
|
||||
CVector3f TotalScale();
|
||||
void SetMode(EGizmoMode mode);
|
||||
void SetTransformSpace(ETransformSpace space);
|
||||
void SetPosition(const CVector3f& position);
|
||||
void SetOrientation(const CQuaternion& orientation);
|
||||
void SetRotation(const CQuaternion& orientation);
|
||||
void EnableCursorWrap(bool wrap);
|
||||
|
||||
// Protected
|
||||
protected:
|
||||
void UpdateTransform();
|
||||
void WrapCursor();
|
||||
|
||||
// Private Static
|
||||
private:
|
||||
|
|
|
@ -35,7 +35,7 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
|||
mShowGizmo = false;
|
||||
mGizmoHovering = false;
|
||||
mGizmoTransforming = false;
|
||||
mUpdateUILater = false;
|
||||
mGizmoUIOutdated = true;
|
||||
|
||||
mFrameCount = 0;
|
||||
mFPSTimer.Start();
|
||||
|
@ -144,15 +144,20 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
|||
ui->InstancesTabContents->SetMaster(pMaster);
|
||||
}
|
||||
|
||||
void CWorldEditor::ViewportRayCast(CRay Ray)
|
||||
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);
|
||||
mGizmoHovering = mGizmo.CheckSelectedAxes(ray);
|
||||
else
|
||||
{
|
||||
mGizmoHovering = false;
|
||||
|
@ -160,7 +165,7 @@ void CWorldEditor::ViewportRayCast(CRay Ray)
|
|||
}
|
||||
|
||||
// Scene ray check
|
||||
SRayIntersection Result = mpSceneManager->SceneRayCast(Ray);
|
||||
SRayIntersection Result = mpSceneManager->SceneRayCast(ray);
|
||||
|
||||
if (Result.Hit)
|
||||
{
|
||||
|
@ -170,16 +175,20 @@ void CWorldEditor::ViewportRayCast(CRay Ray)
|
|||
mpHoverNode = Result.pNode;
|
||||
mpHoverNode->SetMouseHovering(true);
|
||||
|
||||
mHoverPoint = Ray.PointOnRay(Result.Distance);
|
||||
mHoverPoint = ray.PointOnRay(Result.Distance);
|
||||
}
|
||||
else
|
||||
ResetHover();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool moved = mGizmo.TransformFromInput(Ray, ui->MainViewport->Camera());
|
||||
bool transformed = mGizmo.TransformFromInput(ray, ui->MainViewport->Camera());
|
||||
|
||||
if (moved)
|
||||
if (transformed)
|
||||
{
|
||||
switch (mGizmo.Mode())
|
||||
{
|
||||
case CGizmo::eTranslate:
|
||||
{
|
||||
CVector3f delta = mGizmo.DeltaTranslation();
|
||||
|
||||
|
@ -188,8 +197,22 @@ void CWorldEditor::ViewportRayCast(CRay Ray)
|
|||
(*it)->Translate(delta, mTransformSpace);
|
||||
(*it)->BuildLightList(this->mpArea);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CGizmo::eRotate:
|
||||
{
|
||||
CQuaternion delta = mGizmo.DeltaRotation();
|
||||
|
||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
||||
(*it)->Rotate(delta, mTransformSpace);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RecalculateSelectionBounds();
|
||||
mUpdateUILater = true;
|
||||
mGizmoUIOutdated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -293,7 +316,9 @@ void CWorldEditor::ViewportMouseRelease(QMouseEvent *pEvent)
|
|||
// Gizmo transform stop
|
||||
if (mGizmoTransforming)
|
||||
{
|
||||
mGizmo.EndTransform();
|
||||
mGizmoTransforming = false;
|
||||
mGizmoUIOutdated = true;
|
||||
}
|
||||
|
||||
// Object selection/deselection
|
||||
|
@ -346,7 +371,7 @@ void CWorldEditor::ViewportPreRender()
|
|||
{
|
||||
// Perform raycast
|
||||
if (ui->MainViewport->underMouse())
|
||||
ViewportRayCast(ui->MainViewport->CastRay());
|
||||
ViewportRayCast();
|
||||
else
|
||||
ResetHover();
|
||||
|
||||
|
@ -373,13 +398,11 @@ void CWorldEditor::ViewportRender(CCamera& Camera)
|
|||
mpRenderer->ClearDepthBuffer();
|
||||
|
||||
Camera.LoadMatrices();
|
||||
if (!mGizmoTransforming) mGizmo.UpdateForCamera(Camera);
|
||||
mGizmo.UpdateForCamera(Camera);
|
||||
mGizmo.AddToRenderer(mpRenderer);
|
||||
|
||||
if (mGizmo.Mode() == CGizmo::eRotate)
|
||||
mGizmo.DrawRotationOutline();
|
||||
|
||||
mpRenderer->RenderBuckets(Camera);
|
||||
mpRenderer->ClearDepthBuffer();
|
||||
}
|
||||
|
||||
mpRenderer->EndFrame();
|
||||
|
@ -393,11 +416,7 @@ void CWorldEditor::ViewportPostRender()
|
|||
UpdateCursor();
|
||||
UpdateStatusBar();
|
||||
|
||||
if (mUpdateUILater)
|
||||
{
|
||||
UpdateSelectionUI();
|
||||
mUpdateUILater = false;
|
||||
}
|
||||
if (mGizmoUIOutdated) UpdateGizmoUI();
|
||||
}
|
||||
|
||||
void CWorldEditor::SetViewportSize(int Width, int Height)
|
||||
|
@ -411,14 +430,16 @@ void CWorldEditor::SetTransformSpace(int space)
|
|||
{
|
||||
case 0:
|
||||
mTransformSpace = eWorldTransform;
|
||||
mGizmo.SetOrientation(CQuaternion::skIdentity);
|
||||
mGizmo.SetRotation(CQuaternion::skIdentity);
|
||||
break;
|
||||
case 1:
|
||||
mTransformSpace = eLocalTransform;
|
||||
if (!mSelectedNodes.empty())
|
||||
mGizmo.SetOrientation(mSelectedNodes.front()->AbsoluteRotation());
|
||||
mGizmo.SetRotation(mSelectedNodes.front()->AbsoluteRotation());
|
||||
break;
|
||||
}
|
||||
|
||||
mGizmo.SetTransformSpace(mTransformSpace);
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
|
@ -491,22 +512,62 @@ void CWorldEditor::UpdateSelectionUI()
|
|||
SelectionText = Metrics.elidedText(SelectionText, Qt::ElideRight, ui->SelectionInfoFrame->width() - 10);
|
||||
ui->SelectionInfoLabel->setText(SelectionText);
|
||||
|
||||
// Update transform
|
||||
CVector3f pos = (!mSelectedNodes.empty() ? mSelectedNodes.front()->AbsolutePosition() : CVector3f::skZero);
|
||||
ui->XSpinBox->setValue(pos.x);
|
||||
ui->YSpinBox->setValue(pos.y);
|
||||
ui->ZSpinBox->setValue(pos.z);
|
||||
// Update gizmo stuff
|
||||
UpdateGizmoUI();
|
||||
}
|
||||
|
||||
void CWorldEditor::UpdateGizmoUI()
|
||||
{
|
||||
// Update transform XYZ spin boxes
|
||||
CVector3f spinBoxValue = CVector3f::skZero;
|
||||
|
||||
// If the gizmo is transforming, use the total transform amount
|
||||
// Otherwise, use the first selected node transform, or 0 if no selection
|
||||
if (mShowGizmo)
|
||||
{
|
||||
switch (mGizmo.Mode())
|
||||
{
|
||||
case CGizmo::eTranslate:
|
||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||
spinBoxValue = mGizmo.TotalTranslation();
|
||||
else if (!mSelectedNodes.empty())
|
||||
spinBoxValue = mSelectedNodes.front()->AbsolutePosition();
|
||||
break;
|
||||
|
||||
case CGizmo::eRotate:
|
||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||
spinBoxValue = mGizmo.TotalRotation();
|
||||
else if (!mSelectedNodes.empty())
|
||||
spinBoxValue = mSelectedNodes.front()->AbsoluteRotation().ToEuler();
|
||||
break;
|
||||
|
||||
case CGizmo::eScale:
|
||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||
spinBoxValue = mGizmo.TotalScale();
|
||||
else if (!mSelectedNodes.empty())
|
||||
spinBoxValue = mSelectedNodes.front()->AbsoluteScale();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!mSelectedNodes.empty()) spinBoxValue = mSelectedNodes.front()->AbsolutePosition();
|
||||
|
||||
ui->XSpinBox->setValue(spinBoxValue.x);
|
||||
ui->YSpinBox->setValue(spinBoxValue.y);
|
||||
ui->ZSpinBox->setValue(spinBoxValue.z);
|
||||
|
||||
// Update gizmo
|
||||
if (!mGizmoTransforming)
|
||||
{
|
||||
mGizmo.SetPosition(pos);
|
||||
if (!mSelectedNodes.empty())
|
||||
mGizmo.SetPosition(mSelectedNodes.front()->AbsolutePosition());
|
||||
|
||||
if ((mTransformSpace == eLocalTransform) && !mSelectedNodes.empty())
|
||||
mGizmo.SetOrientation(mSelectedNodes.front()->AbsoluteRotation());
|
||||
mGizmo.SetRotation(mSelectedNodes.front()->AbsoluteRotation());
|
||||
else
|
||||
mGizmo.SetOrientation(CQuaternion::skIdentity);
|
||||
mGizmo.SetRotation(CQuaternion::skIdentity);
|
||||
}
|
||||
|
||||
mGizmoUIOutdated = false;
|
||||
}
|
||||
|
||||
// ************ ACTIONS ************
|
||||
|
@ -660,6 +721,7 @@ void CWorldEditor::on_ActionEditLayers_triggered()
|
|||
void CWorldEditor::on_ActionSelectObjects_triggered()
|
||||
{
|
||||
mShowGizmo = false;
|
||||
mGizmoUIOutdated = true;
|
||||
ui->ActionSelectObjects->setChecked(true);
|
||||
ui->ActionTranslate->setChecked(false);
|
||||
ui->ActionRotate->setChecked(false);
|
||||
|
@ -669,6 +731,7 @@ void CWorldEditor::on_ActionSelectObjects_triggered()
|
|||
void CWorldEditor::on_ActionTranslate_triggered()
|
||||
{
|
||||
mShowGizmo = true;
|
||||
mGizmoUIOutdated = true;
|
||||
mGizmo.SetMode(CGizmo::eTranslate);
|
||||
ui->ActionSelectObjects->setChecked(false);
|
||||
ui->ActionTranslate->setChecked(true);
|
||||
|
@ -679,6 +742,7 @@ void CWorldEditor::on_ActionTranslate_triggered()
|
|||
void CWorldEditor::on_ActionRotate_triggered()
|
||||
{
|
||||
mShowGizmo = true;
|
||||
mGizmoUIOutdated = true;
|
||||
mGizmo.SetMode(CGizmo::eRotate);
|
||||
ui->ActionSelectObjects->setChecked(false);
|
||||
ui->ActionTranslate->setChecked(false);
|
||||
|
@ -689,6 +753,7 @@ void CWorldEditor::on_ActionRotate_triggered()
|
|||
void CWorldEditor::on_ActionScale_triggered()
|
||||
{
|
||||
mShowGizmo = true;
|
||||
mGizmoUIOutdated = true;
|
||||
mGizmo.SetMode(CGizmo::eScale);
|
||||
ui->ActionSelectObjects->setChecked(false);
|
||||
ui->ActionTranslate->setChecked(false);
|
||||
|
|
|
@ -37,7 +37,7 @@ class CWorldEditor : public QMainWindow
|
|||
bool mShowGizmo;
|
||||
bool mGizmoHovering;
|
||||
bool mGizmoTransforming;
|
||||
bool mUpdateUILater;
|
||||
bool mGizmoUIOutdated;
|
||||
|
||||
CVector3f mHoverPoint;
|
||||
CSceneNode *mpHoverNode;
|
||||
|
@ -52,7 +52,7 @@ public:
|
|||
~CWorldEditor();
|
||||
bool eventFilter(QObject *pObj, QEvent *pEvent);
|
||||
void SetArea(CWorld *pWorld, CGameArea *pArea);
|
||||
void ViewportRayCast(CRay Ray);
|
||||
void ViewportRayCast();
|
||||
CRenderer* Renderer();
|
||||
CSceneManager* Scene();
|
||||
CGameArea* ActiveArea();
|
||||
|
@ -82,6 +82,7 @@ private:
|
|||
void OnSidebarResize();
|
||||
void UpdateSelectionUI();
|
||||
void UpdateStatusBar();
|
||||
void UpdateGizmoUI();
|
||||
|
||||
private slots:
|
||||
void OnCameraSpeedChange(double speed);
|
||||
|
|
Loading…
Reference in New Issue