Scale gizmo transform functionality implemented
This commit is contained in:
parent
8d633553c9
commit
281a605586
|
@ -115,9 +115,9 @@ CQuaternion CQuaternion::FromEuler(CVector3f euler)
|
|||
quat.y = ((c1 * s2 * c3) - (s1 * c2 * s3));
|
||||
quat.z = ((s1 * s2 * c3) + (c1 * c2 * s3));*/
|
||||
|
||||
CQuaternion x = CQuaternion::FromAxisAngle(euler.x, CVector3f(1,0,0));
|
||||
CQuaternion y = CQuaternion::FromAxisAngle(euler.y, CVector3f(0,1,0));
|
||||
CQuaternion z = CQuaternion::FromAxisAngle(euler.z, CVector3f(0,0,1));
|
||||
CQuaternion x = CQuaternion::FromAxisAngle(Math::DegreesToRadians(euler.x), CVector3f(1,0,0));
|
||||
CQuaternion y = CQuaternion::FromAxisAngle(Math::DegreesToRadians(euler.y), CVector3f(0,1,0));
|
||||
CQuaternion z = CQuaternion::FromAxisAngle(Math::DegreesToRadians(euler.z), CVector3f(0,0,1));
|
||||
CQuaternion quat = z * y * x;
|
||||
|
||||
return quat;
|
||||
|
@ -127,7 +127,6 @@ CQuaternion CQuaternion::FromAxisAngle(float angle, CVector3f axis)
|
|||
{
|
||||
CQuaternion quat;
|
||||
axis = axis.Normalized();
|
||||
angle = Math::DegreesToRadians(angle);
|
||||
|
||||
float sa = sinf(angle / 2);
|
||||
quat.w = cosf(angle / 2);
|
||||
|
|
|
@ -213,8 +213,9 @@ void CSceneNode::Rotate(const CQuaternion& rotation, ETransformSpace transformSp
|
|||
MarkTransformChanged();
|
||||
}
|
||||
|
||||
void CSceneNode::Scale(const CVector3f& scale, ETransformSpace transformSpace)
|
||||
void CSceneNode::Scale(const CVector3f& scale)
|
||||
{
|
||||
// No support for stretch/skew world-space scaling; local only
|
||||
mScale *= scale;
|
||||
MarkTransformChanged();
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
// Transform
|
||||
void Translate(const CVector3f& translation, ETransformSpace transformSpace);
|
||||
void Rotate(const CQuaternion& rotation, ETransformSpace transformSpace);
|
||||
void Scale(const CVector3f& scale, ETransformSpace transformSpace);
|
||||
void Scale(const CVector3f& scale);
|
||||
void UpdateTransform();
|
||||
void ForceRecalculateTransform();
|
||||
void MarkTransformChanged();
|
||||
|
|
|
@ -45,7 +45,7 @@ CScriptNode::CScriptNode(CSceneManager *pScene, CSceneNode *pParent, CScriptObje
|
|||
{
|
||||
mpVolumePreviewNode = new CModelNode(pScene, this, pVolumeModel);
|
||||
mpVolumePreviewNode->SetInheritance(true, (VolumeShape == 1), false);
|
||||
mpVolumePreviewNode->Scale(mpInstance->GetVolume(), eWorldTransform);
|
||||
mpVolumePreviewNode->Scale(mpInstance->GetVolume());
|
||||
mpVolumePreviewNode->ForceAlphaEnabled(true);
|
||||
}
|
||||
}
|
||||
|
|
161
UI/CGizmo.cpp
161
UI/CGizmo.cpp
|
@ -25,15 +25,17 @@ CGizmo::CGizmo()
|
|||
|
||||
mPosition = CVector3f::skZero;
|
||||
mRotation = CQuaternion::skIdentity;
|
||||
mLocalRotation = CQuaternion::skIdentity;
|
||||
mScale = CVector3f::skOne;
|
||||
mFlipScaleX = false;
|
||||
mFlipScaleY = false;
|
||||
mFlipScaleZ = false;
|
||||
|
||||
mDeltaTranslation = CVector3f::skZero;
|
||||
mDeltaRotation = CQuaternion::skIdentity;
|
||||
mDeltaScale = CVector3f::skOne;
|
||||
mTotalScale = CVector3f::skOne;
|
||||
mSetOffset = false;
|
||||
mFlipScaleX = false;
|
||||
mFlipScaleY = false;
|
||||
mFlipScaleZ = false;
|
||||
}
|
||||
|
||||
CGizmo::~CGizmo()
|
||||
|
@ -74,7 +76,13 @@ void CGizmo::DrawAsset(ERenderOptions options, u32 asset)
|
|||
SModelPart *pPart = mpCurrentParts;
|
||||
|
||||
// Set model matrix
|
||||
CGraphics::sMVPBlock.ModelMatrix = (pPart[asset].isBillboard ? mBillboardTransform.ToMatrix4f() : mTransform.ToMatrix4f());
|
||||
if (pPart[asset].isBillboard)
|
||||
CGraphics::sMVPBlock.ModelMatrix = mBillboardTransform.ToMatrix4f();
|
||||
else if ((mMode == eScale) && ((mSelectedAxes & pPart[asset].modelAxes) != 0))
|
||||
CGraphics::sMVPBlock.ModelMatrix = mScaledTransform.ToMatrix4f();
|
||||
else
|
||||
CGraphics::sMVPBlock.ModelMatrix = mTransform.ToMatrix4f();
|
||||
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
// Choose material set
|
||||
|
@ -107,24 +115,23 @@ void CGizmo::DecrementSize()
|
|||
void CGizmo::UpdateForCamera(const CCamera &camera)
|
||||
{
|
||||
CVector3f camPos = camera.Position();
|
||||
mFlipScaleX = camPos.x < mPosition.x;
|
||||
mFlipScaleY = camPos.y < mPosition.y;
|
||||
mFlipScaleZ = camPos.z < mPosition.z;
|
||||
CVector3f cameraToGizmo = (mPosition - camPos).Normalized();
|
||||
mFlipScaleX = (mRotation.XAxis().Dot(cameraToGizmo) >= 0.f);
|
||||
mFlipScaleY = (mRotation.YAxis().Dot(cameraToGizmo) >= 0.f);
|
||||
mFlipScaleZ = (mRotation.ZAxis().Dot(cameraToGizmo) >= 0.f);
|
||||
|
||||
if ((!mIsTransforming) || (mMode != eTranslate))
|
||||
mCameraDist = mPosition.Distance(camPos);
|
||||
|
||||
// todo: make this cleaner...
|
||||
CVector3f billDir = (mPosition - camPos).Normalized();
|
||||
CVector3f billDir = (camPos - mPosition).Normalized();
|
||||
CVector3f axis = CVector3f::skForward.Cross(billDir);
|
||||
float angle = acosf(CVector3f::skForward.Dot(billDir));
|
||||
angle = 180 + (angle * 180 / 3.14159265358979323846f);
|
||||
mBillboardRotation = CQuaternion::FromAxisAngle(angle, axis);
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
|
@ -231,7 +238,7 @@ void CGizmo::StartTransform()
|
|||
mCurrentRotation = CQuaternion::skIdentity;
|
||||
mTotalScale = CVector3f::skOne;
|
||||
|
||||
// Set rotation clockwise direction
|
||||
// Set rotation direction
|
||||
if (mMode == eRotate)
|
||||
{
|
||||
CVector3f axis;
|
||||
|
@ -240,7 +247,31 @@ void CGizmo::StartTransform()
|
|||
else axis = mRotation.ZAxis();
|
||||
|
||||
CVector3f gizmoToHit = (mHitPoint - mPosition).Normalized();
|
||||
mClockwiseDir = axis.Cross(gizmoToHit);
|
||||
mMoveDir = axis.Cross(gizmoToHit);
|
||||
}
|
||||
|
||||
// Set scale direction
|
||||
else if (mMode == eScale)
|
||||
{
|
||||
// Only need to set scale direction if < 3 axes selected
|
||||
if (NumSelectedAxes() != 3)
|
||||
{
|
||||
// One axis; direction = selected axis
|
||||
if (NumSelectedAxes() == 1)
|
||||
{
|
||||
if (mSelectedAxes & eX) mMoveDir = mRotation.XAxis();
|
||||
else if (mSelectedAxes & eY) mMoveDir = mRotation.YAxis();
|
||||
else mMoveDir = mRotation.ZAxis();
|
||||
}
|
||||
|
||||
// Two axes; interpolate between the two selected axes
|
||||
else if (NumSelectedAxes() == 2)
|
||||
{
|
||||
CVector3f axisA = (mSelectedAxes & eX ? mRotation.XAxis() : mRotation.YAxis());
|
||||
CVector3f axisB = (mSelectedAxes & eZ ? mRotation.ZAxis() : mRotation.YAxis());
|
||||
mMoveDir = (axisA + axisB) / 2.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,11 +378,11 @@ bool CGizmo::TransformFromInput(const CRay& ray, CCamera& camera)
|
|||
else if (mSelectedAxes & eY) axis = CVector3f::skUnitY;
|
||||
else axis = CVector3f::skUnitZ;
|
||||
|
||||
// Convert hit point + clockwise direction into a line in screen space
|
||||
// Convert hit point + move 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();
|
||||
CVector2f lineDir = (((mHitPoint + mMoveDir) * VP).xy() - lineOrigin).Normalized();
|
||||
float rotAmount = lineDir.Dot(mouseCoords + mWrapOffset - lineOrigin) * 180.f;
|
||||
|
||||
// Set offset
|
||||
|
@ -366,7 +397,7 @@ bool CGizmo::TransformFromInput(const CRay& ray, CCamera& camera)
|
|||
// Apply rotation
|
||||
rotAmount += mRotateOffset;
|
||||
CQuaternion oldRot = mCurrentRotation;
|
||||
mCurrentRotation = CQuaternion::FromAxisAngle(rotAmount, axis);
|
||||
mCurrentRotation = CQuaternion::FromAxisAngle(Math::DegreesToRadians(rotAmount), axis);
|
||||
mDeltaRotation = mCurrentRotation * oldRot.Inverse();
|
||||
|
||||
if (mTransformSpace == eLocalTransform)
|
||||
|
@ -383,11 +414,80 @@ bool CGizmo::TransformFromInput(const CRay& ray, CCamera& camera)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Scale
|
||||
else if (mMode == eScale)
|
||||
{
|
||||
// Create a line in screen space. First step: line origin
|
||||
CMatrix4f VP = camera.ViewMatrix().Transpose() * camera.ProjectionMatrix().Transpose();
|
||||
CVector2f lineOrigin = (mPosition * VP).xy();
|
||||
|
||||
// Next step: determine the appropriate world space direction using the selected axes and then convert to screen space
|
||||
// Since the axes can be flipped while the gizmo is transforming, this has to be done every frame rather than
|
||||
// pre-saving the world space direction like the rotate gizmo does.
|
||||
CVector3f dirX = (mFlipScaleX ? -mRotation.XAxis() : mRotation.XAxis());
|
||||
CVector3f dirY = (mFlipScaleY ? -mRotation.YAxis() : mRotation.YAxis());
|
||||
CVector3f dirZ = (mFlipScaleZ ? -mRotation.ZAxis() : mRotation.ZAxis());
|
||||
CVector2f lineDir;
|
||||
|
||||
// One axis - world space direction is just the selected axis
|
||||
if (NumSelectedAxes() == 1)
|
||||
{
|
||||
CVector3f worldDir;
|
||||
if (mSelectedAxes & eX) worldDir = dirX;
|
||||
else if (mSelectedAxes & eY) worldDir = dirY;
|
||||
else worldDir = dirZ;
|
||||
lineDir = (((mPosition + worldDir) * VP).xy() - lineOrigin).Normalized();
|
||||
}
|
||||
// Two axes - take the two selected axes and convert them to world space, then average them for the line direction
|
||||
else if (NumSelectedAxes() == 2)
|
||||
{
|
||||
CVector3f axisA = (mSelectedAxes & eX ? dirX : dirY);
|
||||
CVector3f axisB = (mSelectedAxes & eZ ? dirZ : dirY);
|
||||
CVector2f screenA = (((mPosition + axisA) * VP).xy() - lineOrigin).Normalized();
|
||||
CVector2f screenB = (((mPosition + axisB) * VP).xy() - lineOrigin).Normalized();
|
||||
lineDir = ((screenA + screenB) / 2.f).Normalized();
|
||||
}
|
||||
// Three axes - use straight up
|
||||
else lineDir = CVector2f::skUp;
|
||||
|
||||
float scaleAmount = lineDir.Dot(mouseCoords + mWrapOffset - lineOrigin) * 5.f;
|
||||
|
||||
// Set offset
|
||||
if (!mSetOffset)
|
||||
{
|
||||
mScaleOffset = -scaleAmount;
|
||||
mDeltaScale = CVector3f::skOne;
|
||||
mSetOffset = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apply scale
|
||||
scaleAmount = scaleAmount + mScaleOffset + 1.f;
|
||||
|
||||
if (scaleAmount < 1.f)
|
||||
scaleAmount = 1.f / (-(scaleAmount - 1.f) + 1.f);
|
||||
|
||||
CVector3f oldScale = mTotalScale;
|
||||
|
||||
mTotalScale = CVector3f::skOne;
|
||||
if (mSelectedAxes & eX) mTotalScale.x = scaleAmount;
|
||||
if (mSelectedAxes & eY) mTotalScale.y = scaleAmount;
|
||||
if (mSelectedAxes & eZ) mTotalScale.z = scaleAmount;
|
||||
|
||||
mDeltaScale = mTotalScale / oldScale;
|
||||
|
||||
if (!mHasTransformed && (scaleAmount != 0.f))
|
||||
mHasTransformed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGizmo::EndTransform()
|
||||
{
|
||||
mTotalScale = CVector3f::skOne;
|
||||
mIsTransforming = false;
|
||||
}
|
||||
|
||||
|
@ -478,6 +578,11 @@ void CGizmo::SetMode(EGizmoMode mode)
|
|||
void CGizmo::SetTransformSpace(ETransformSpace space)
|
||||
{
|
||||
mTransformSpace = space;
|
||||
|
||||
if (space == eWorldTransform)
|
||||
mRotation = CQuaternion::skIdentity;
|
||||
else
|
||||
mRotation = mLocalRotation;
|
||||
}
|
||||
|
||||
void CGizmo::SetPosition(const CVector3f& position)
|
||||
|
@ -485,9 +590,12 @@ void CGizmo::SetPosition(const CVector3f& position)
|
|||
mPosition = position;
|
||||
}
|
||||
|
||||
void CGizmo::SetRotation(const CQuaternion& orientation)
|
||||
void CGizmo::SetLocalRotation(const CQuaternion& orientation)
|
||||
{
|
||||
mRotation = orientation;
|
||||
mLocalRotation = orientation;
|
||||
|
||||
if (mTransformSpace == eLocalTransform)
|
||||
mRotation = orientation;
|
||||
}
|
||||
|
||||
void CGizmo::EnableCursorWrap(bool wrap)
|
||||
|
@ -524,9 +632,9 @@ void CGizmo::LoadModels()
|
|||
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_POLY_XY] = SModelPart(eXY, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScalePolyXY.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_POLY_XZ] = SModelPart(eXZ, true, false, (CModel*) gResCache.GetResource("../resources/editor/ScalePolyXZ.CMDL"));
|
||||
smScaleModels[CGIZMO_SCALE_POLY_YZ] = SModelPart(eYZ, true, 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;
|
||||
|
@ -540,11 +648,9 @@ void CGizmo::UpdateTransform()
|
|||
// Rotation and position values are just saved directly
|
||||
mScale = mGizmoSize * (mCameraDist / 10.f);
|
||||
|
||||
// Scale also factors in total scale + axis flip if mode is Scale.
|
||||
// Scale also factors in axis flip if mode is Scale.
|
||||
if (mMode == eScale)
|
||||
{
|
||||
mScale *= mTotalScale;
|
||||
|
||||
if (mFlipScaleX) mScale.x = -mScale.x;
|
||||
if (mFlipScaleY) mScale.y = -mScale.y;
|
||||
if (mFlipScaleZ) mScale.z = -mScale.z;
|
||||
|
@ -564,6 +670,15 @@ void CGizmo::UpdateTransform()
|
|||
mBillboardTransform.Rotate(mBillboardRotation);
|
||||
mBillboardTransform.Translate(mPosition);
|
||||
}
|
||||
|
||||
// Create scaled transform for scale gizmo
|
||||
else if (mMode == eScale)
|
||||
{
|
||||
mScaledTransform = CTransform4f::skIdentity;
|
||||
mScaledTransform.Scale(mScale * mTotalScale);
|
||||
mScaledTransform.Rotate(mRotation);
|
||||
mScaledTransform.Translate(mPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void CGizmo::WrapCursor()
|
||||
|
|
27
UI/CGizmo.h
27
UI/CGizmo.h
|
@ -60,8 +60,6 @@ private:
|
|||
EGizmoMode mMode;
|
||||
EGizmoAxes mSelectedAxes;
|
||||
ETransformSpace mTransformSpace;
|
||||
CVector3f mHitPoint;
|
||||
CTransform4f mBillboardTransform;
|
||||
CQuaternion mBillboardRotation;
|
||||
float mGizmoSize;
|
||||
float mCameraDist;
|
||||
|
@ -71,27 +69,32 @@ private:
|
|||
bool mEnableCursorWrap;
|
||||
|
||||
CTransform4f mTransform;
|
||||
CTransform4f mBillboardTransform;
|
||||
CTransform4f mScaledTransform;
|
||||
CVector3f mPosition;
|
||||
CVector3f mDeltaTranslation;
|
||||
CVector3f mTotalTranslation;
|
||||
CQuaternion mRotation;
|
||||
CQuaternion mDeltaRotation;
|
||||
CQuaternion mCurrentRotation;
|
||||
CVector3f mTotalRotation; // This is a CVector3f because this value displays on the UI and a quat would cause rollover
|
||||
CQuaternion mLocalRotation;
|
||||
CVector3f mScale;
|
||||
CVector3f mDeltaScale;
|
||||
CVector3f mTotalScale;
|
||||
bool mFlipScaleX;
|
||||
bool mFlipScaleY;
|
||||
bool mFlipScaleZ;
|
||||
|
||||
CVector3f mDeltaTranslation;
|
||||
CVector3f mTotalTranslation;
|
||||
CQuaternion mDeltaRotation;
|
||||
CQuaternion mCurrentRotation;
|
||||
CVector3f mTotalRotation; // This is a CVector3f because this value displays on the UI and a quat would cause rollover
|
||||
CVector3f mDeltaScale;
|
||||
CVector3f mTotalScale;
|
||||
|
||||
CPlane mTranslatePlane;
|
||||
CVector3f mTranslateOffset;
|
||||
float mRotateOffset;
|
||||
float mScaleOffset;
|
||||
bool mSetOffset;
|
||||
|
||||
CVector3f mRotateHitPoint;
|
||||
CVector3f mClockwiseDir;
|
||||
CVector3f mHitPoint;
|
||||
CVector3f mMoveDir;
|
||||
|
||||
struct SModelPart
|
||||
{
|
||||
|
@ -145,7 +148,7 @@ public:
|
|||
void SetMode(EGizmoMode mode);
|
||||
void SetTransformSpace(ETransformSpace space);
|
||||
void SetPosition(const CVector3f& position);
|
||||
void SetRotation(const CQuaternion& orientation);
|
||||
void SetLocalRotation(const CQuaternion& orientation);
|
||||
void EnableCursorWrap(bool wrap);
|
||||
|
||||
// Protected
|
||||
|
|
|
@ -61,13 +61,14 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
|||
ui->CamSpeedSpinBox->SetDefaultValue(1.0);
|
||||
ResetHover();
|
||||
|
||||
mTransformSpace = eWorldTransform;
|
||||
mTranslateSpace = eWorldTransform;
|
||||
mRotateSpace = eWorldTransform;
|
||||
|
||||
QComboBox *pTransformCombo = new QComboBox(this);
|
||||
pTransformCombo->setMinimumWidth(75);
|
||||
pTransformCombo->addItem("World");
|
||||
pTransformCombo->addItem("Local");
|
||||
ui->MainToolBar->insertWidget(0, pTransformCombo);
|
||||
mpTransformSpaceComboBox = new QComboBox(this);
|
||||
mpTransformSpaceComboBox->setMinimumWidth(75);
|
||||
mpTransformSpaceComboBox->addItem("World");
|
||||
mpTransformSpaceComboBox->addItem("Local");
|
||||
ui->MainToolBar->insertWidget(0, mpTransformSpaceComboBox);
|
||||
|
||||
// Initialize offscreen actions
|
||||
addAction(ui->ActionIncrementGizmo);
|
||||
|
@ -76,7 +77,7 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
|||
// Connect signals and slots
|
||||
connect(ui->TransformSpinBox, SIGNAL(EditingDone(CVector3f)), this, SLOT(OnTransformSpinBoxEdited(CVector3f)));
|
||||
connect(ui->TransformSpinBox, SIGNAL(ValueChanged(CVector3f)), this, SLOT(OnTransformSpinBoxModified(CVector3f)));
|
||||
connect(pTransformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(SetTransformSpace(int)));
|
||||
connect(mpTransformSpaceComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SetTransformSpace(int)));
|
||||
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&)));
|
||||
|
@ -193,27 +194,37 @@ void CWorldEditor::ViewportRayCast()
|
|||
{
|
||||
switch (mGizmo.Mode())
|
||||
{
|
||||
case CGizmo::eTranslate:
|
||||
{
|
||||
CVector3f delta = mGizmo.DeltaTranslation();
|
||||
|
||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
||||
case CGizmo::eTranslate:
|
||||
{
|
||||
(*it)->Translate(delta, mTransformSpace);
|
||||
(*it)->BuildLightList(this->mpArea);
|
||||
CVector3f delta = mGizmo.DeltaTranslation();
|
||||
|
||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
||||
{
|
||||
(*it)->Translate(delta, mTranslateSpace);
|
||||
(*it)->BuildLightList(this->mpArea);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CGizmo::eRotate:
|
||||
{
|
||||
CQuaternion delta = mGizmo.DeltaRotation();
|
||||
case CGizmo::eRotate:
|
||||
{
|
||||
CQuaternion delta = mGizmo.DeltaRotation();
|
||||
|
||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
||||
(*it)->Rotate(delta, mTransformSpace);
|
||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
||||
(*it)->Rotate(delta, mRotateSpace);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CGizmo::eScale:
|
||||
{
|
||||
CVector3f delta = mGizmo.DeltaScale();
|
||||
|
||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
||||
(*it)->Scale(delta);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RecalculateSelectionBounds();
|
||||
|
@ -432,20 +443,23 @@ void CWorldEditor::SetViewportSize(int Width, int Height)
|
|||
|
||||
void CWorldEditor::SetTransformSpace(int space)
|
||||
{
|
||||
if (mGizmo.Mode() == CGizmo::eScale) return;
|
||||
ETransformSpace& transformSpace = (mGizmo.Mode() == CGizmo::eTranslate ? mTranslateSpace : mRotateSpace);
|
||||
|
||||
switch (space)
|
||||
{
|
||||
case 0:
|
||||
mTransformSpace = eWorldTransform;
|
||||
mGizmo.SetRotation(CQuaternion::skIdentity);
|
||||
transformSpace = eWorldTransform;
|
||||
mGizmo.SetLocalRotation(CQuaternion::skIdentity);
|
||||
break;
|
||||
case 1:
|
||||
mTransformSpace = eLocalTransform;
|
||||
transformSpace = eLocalTransform;
|
||||
if (!mSelectedNodes.empty())
|
||||
mGizmo.SetRotation(mSelectedNodes.front()->AbsoluteRotation());
|
||||
mGizmo.SetLocalRotation(mSelectedNodes.front()->AbsoluteRotation());
|
||||
break;
|
||||
}
|
||||
|
||||
mGizmo.SetTransformSpace(mTransformSpace);
|
||||
mGizmo.SetTransformSpace(transformSpace);
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
|
@ -570,10 +584,17 @@ void CWorldEditor::UpdateGizmoUI()
|
|||
if (!mSelectedNodes.empty())
|
||||
mGizmo.SetPosition(mSelectedNodes.front()->AbsolutePosition());
|
||||
|
||||
if ((mTransformSpace == eLocalTransform) && !mSelectedNodes.empty())
|
||||
mGizmo.SetRotation(mSelectedNodes.front()->AbsoluteRotation());
|
||||
else
|
||||
mGizmo.SetRotation(CQuaternion::skIdentity);
|
||||
// Determine transform space
|
||||
ETransformSpace space;
|
||||
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;
|
||||
|
@ -764,6 +785,16 @@ void CWorldEditor::on_ActionSelectObjects_triggered()
|
|||
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()
|
||||
|
@ -771,13 +802,22 @@ 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()
|
||||
|
@ -785,13 +825,22 @@ 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()
|
||||
|
@ -799,13 +848,21 @@ 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()
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
#include <QList>
|
||||
#include <QComboBox>
|
||||
|
||||
#include "CGizmo.h"
|
||||
#include <Common/CRay.h>
|
||||
|
@ -26,7 +27,8 @@ class CWorldEditor : public QMainWindow
|
|||
CRenderer *mpRenderer;
|
||||
CSceneManager *mpSceneManager;
|
||||
CGizmo mGizmo;
|
||||
ETransformSpace mTransformSpace;
|
||||
ETransformSpace mTranslateSpace;
|
||||
ETransformSpace mRotateSpace;
|
||||
CCamera mCamera;
|
||||
CGameArea *mpArea;
|
||||
CWorld *mpWorld;
|
||||
|
@ -44,6 +46,8 @@ class CWorldEditor : public QMainWindow
|
|||
std::list<CSceneNode*> mSelectedNodes;
|
||||
CAABox mSelectionAABox;
|
||||
|
||||
QComboBox *mpTransformSpaceComboBox;
|
||||
|
||||
CTimer mFPSTimer;
|
||||
int mFrameCount;
|
||||
|
||||
|
|
Loading…
Reference in New Issue