git mv Code\Sandbox\Editor Code/Editor
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "AxisHelperShared.inl"
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_RENDERHELPERS_AXISHELPER_H
|
||||
#define CRYINCLUDE_EDITOR_RENDERHELPERS_AXISHELPER_H
|
||||
#pragma once
|
||||
|
||||
#include "IEditor.h" // for AxisConstrains and RefCoordSys
|
||||
|
||||
struct DisplayContext;
|
||||
struct HitContext;
|
||||
struct IDisplayViewport;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SGizmoParameters
|
||||
{
|
||||
bool axisGizmoText;
|
||||
bool enabled;
|
||||
float axisGizmoScale;
|
||||
AxisConstrains axisConstraint;
|
||||
RefCoordSys referenceCoordSys;
|
||||
|
||||
SGizmoParameters()
|
||||
: axisGizmoText(false)
|
||||
, enabled(true)
|
||||
, axisGizmoScale(1.0f)
|
||||
, axisConstraint(AXIS_TERRAIN)
|
||||
, referenceCoordSys(COORDS_LOCAL)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helper Axis object.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CAxisHelper
|
||||
{
|
||||
public:
|
||||
enum EHelperMode
|
||||
{
|
||||
MOVE_MODE = 0x1,
|
||||
SCALE_MODE = 0x2,
|
||||
ROTATE_MODE = 0x4,
|
||||
SELECT_MODE = 0x8,
|
||||
ROTATE_CIRCLE_MODE = 0x10,
|
||||
};
|
||||
|
||||
CAxisHelper();
|
||||
|
||||
void SetMode(int nModeFlags);
|
||||
void DrawAxis(const Matrix34& worldTM, const SGizmoParameters& setup, DisplayContext& dc);
|
||||
void DrawDome(const Matrix34& worldTM, const SGizmoParameters& setup, DisplayContext& dc, AABB& objectBox);
|
||||
bool HitTest(const Matrix34& worldTM, const SGizmoParameters& setup, HitContext& hc);
|
||||
|
||||
bool HitTestForRotationCircle(const Matrix34& worldTM, IDisplayViewport* view, const QPoint& pos, float fHitWidth, Vec3* pOutHitPos = NULL, Vec3* pOutHitNormal = NULL);
|
||||
|
||||
void SetHighlightAxis(int axis) { m_highlightAxis = axis; };
|
||||
int GetHighlightAxis() const { return m_highlightAxis; };
|
||||
|
||||
private:
|
||||
void Prepare(const Matrix34& worldTM, const SGizmoParameters& setup, IDisplayViewport* view);
|
||||
float GetDistance2D(IDisplayViewport* view, const QPoint& p, const Vec3& wp);
|
||||
|
||||
int m_nModeFlags;
|
||||
int m_highlightAxis;
|
||||
int m_highlightMode;
|
||||
int m_currentMode;
|
||||
bool m_bHighlightRotationCircle;
|
||||
|
||||
float m_fScreenScale;
|
||||
bool m_bNeedX;
|
||||
bool m_bNeedY;
|
||||
bool m_bNeedZ;
|
||||
float m_size;
|
||||
Matrix34 m_matrix;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_RENDERHELPERS_AXISHELPER_H
|
||||
|
||||
@@ -0,0 +1,848 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "AxisHelper.h"
|
||||
|
||||
#include "Objects/DisplayContext.h"
|
||||
#include "Include/IDisplayViewport.h"
|
||||
#include "Include/HitContext.h"
|
||||
#include "Util/Math.h"
|
||||
#include "IObjectManager.h"
|
||||
#include <Cry_Geo.h>
|
||||
|
||||
const float kPlaneScale = 0.3f;
|
||||
const float kBoldLine3D = 4.f;
|
||||
const float kBoldLine2D = 2.f;
|
||||
const float kSelectionBallScale = 0.05f;
|
||||
const float kRotateCircleRadiusScale = 0.2f;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAxisHelper::CAxisHelper()
|
||||
: m_matrix(IDENTITY)
|
||||
{
|
||||
m_nModeFlags = MOVE_MODE;
|
||||
m_currentMode = MOVE_MODE;
|
||||
m_highlightMode = 1;
|
||||
m_highlightAxis = 0;
|
||||
m_bHighlightRotationCircle = false;
|
||||
|
||||
m_bNeedX = true;
|
||||
m_bNeedY = true;
|
||||
m_bNeedZ = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisHelper::SetMode(int nModeFlags)
|
||||
{
|
||||
m_nModeFlags = nModeFlags;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisHelper::Prepare(const Matrix34& worldTM, const SGizmoParameters& setup, IDisplayViewport* view)
|
||||
{
|
||||
m_fScreenScale = view->GetScreenScaleFactor(worldTM.GetTranslation());
|
||||
m_size = setup.axisGizmoScale * m_fScreenScale;
|
||||
|
||||
m_bNeedX = true;
|
||||
m_bNeedY = true;
|
||||
m_bNeedZ = true;
|
||||
|
||||
IDisplayViewport::EAxis axis = IDisplayViewport::AXIS_NONE;
|
||||
bool b2D = false;
|
||||
|
||||
view->GetPerpendicularAxis(&axis, &b2D);
|
||||
switch (axis)
|
||||
{
|
||||
case static_cast<IDisplayViewport::EAxis>(AXIS_X):
|
||||
m_bNeedX = false;
|
||||
break;
|
||||
case static_cast<IDisplayViewport::EAxis>(AXIS_Y):
|
||||
m_bNeedY = false;
|
||||
break;
|
||||
case static_cast<IDisplayViewport::EAxis>(AXIS_Z):
|
||||
m_bNeedZ = false;
|
||||
break;
|
||||
}
|
||||
|
||||
m_matrix = worldTM;
|
||||
RefCoordSys refCoordSys = setup.referenceCoordSys;
|
||||
if (b2D && refCoordSys == COORDS_VIEW)
|
||||
{
|
||||
m_matrix = view->GetViewTM();
|
||||
m_matrix.SetTranslation(worldTM.GetTranslation());
|
||||
}
|
||||
m_matrix.OrthonormalizeFast();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisHelper::DrawDome(const Matrix34& worldTM, const SGizmoParameters& setup, DisplayContext& dc, AABB& objectBox)
|
||||
{
|
||||
Prepare(worldTM, setup, dc.view);
|
||||
Vec3 x(m_size, 0, 0);
|
||||
Vec3 y(0, m_size, 0);
|
||||
Vec3 z(0, 0, m_size);
|
||||
|
||||
|
||||
int prevRState = dc.GetState();
|
||||
|
||||
if (!(dc.flags & DISPLAY_2D))
|
||||
{
|
||||
dc.DepthTestOff();
|
||||
}
|
||||
|
||||
dc.PushMatrix(m_matrix);
|
||||
dc.SetDrawInFrontMode(true);
|
||||
|
||||
float radius = objectBox.GetRadius();
|
||||
dc.DrawCircle(Vec3(0, 0, 0), radius);
|
||||
dc.DrawCircle(Vec3(0, 0, 0), radius / 3.0f);
|
||||
|
||||
dc.DrawArc(Vec3(0, 0, 0), radius, 0.0f, 180.0f, 1, Vec3(0, -1, 0));
|
||||
dc.DrawArc(Vec3(0, 0, 0), radius, 90.0f, 180.0f, 1, Vec3(1, 0, 0));
|
||||
|
||||
|
||||
dc.PopMatrix();
|
||||
if (!(dc.flags & DISPLAY_2D))
|
||||
{
|
||||
dc.DepthTestOn();
|
||||
}
|
||||
|
||||
dc.SetState(prevRState);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisHelper::DrawAxis(const Matrix34& worldTM, const SGizmoParameters& setup, DisplayContext& dc)
|
||||
{
|
||||
Prepare(worldTM, setup, dc.view);
|
||||
|
||||
Vec3 x(m_size, 0, 0);
|
||||
Vec3 y(0, m_size, 0);
|
||||
Vec3 z(0, 0, m_size);
|
||||
|
||||
int prevRState = dc.GetState();
|
||||
|
||||
if (!(dc.flags & DISPLAY_2D))
|
||||
{
|
||||
dc.DepthTestOff();
|
||||
}
|
||||
|
||||
dc.PushMatrix(m_matrix);
|
||||
dc.SetDrawInFrontMode(true);
|
||||
|
||||
Vec3 colSelected(1, 1, 0);
|
||||
Vec3 axisColor(1, 1, 1);
|
||||
Vec3 disabledColor(0.75, 0.75, 0.75);
|
||||
|
||||
Matrix34 worldTMWithoutScale(worldTM);
|
||||
worldTMWithoutScale.OrthonormalizeFast();
|
||||
float textSize = 1.4f;
|
||||
|
||||
if (!(m_nModeFlags & ROTATE_CIRCLE_MODE))
|
||||
{
|
||||
dc.SetColor(setup.enabled ? axisColor : disabledColor);
|
||||
if (m_bNeedX && setup.axisGizmoText)
|
||||
{
|
||||
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(x), textSize, "x");
|
||||
}
|
||||
if (m_bNeedY && setup.axisGizmoText)
|
||||
{
|
||||
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(y), textSize, "y");
|
||||
}
|
||||
if (m_bNeedZ && setup.axisGizmoText)
|
||||
{
|
||||
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(z), textSize, "z");
|
||||
}
|
||||
}
|
||||
|
||||
int axis = setup.axisConstraint;
|
||||
if (m_highlightAxis)
|
||||
{
|
||||
axis = m_highlightAxis;
|
||||
}
|
||||
|
||||
float lineWidth = kBoldLine3D;
|
||||
if (dc.flags & DISPLAY_2D)
|
||||
{
|
||||
lineWidth = kBoldLine2D;
|
||||
}
|
||||
|
||||
float linew[3];
|
||||
linew[0] = linew[1] = linew[2] = 0;
|
||||
Vec3 colX, colY, colZ;
|
||||
if (setup.enabled)
|
||||
{
|
||||
colX = Vec3(1, 0, 0);
|
||||
colY = Vec3(0, 1, 0);
|
||||
colZ = Vec3(0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
colX = colY = colZ = disabledColor;
|
||||
}
|
||||
Vec3 colXArrow = colX, colYArrow = colY, colZArrow = colZ;
|
||||
if (!(m_nModeFlags & ROTATE_CIRCLE_MODE))
|
||||
{
|
||||
if (axis)
|
||||
{
|
||||
float col[4] = { 1, 0, 0, 1 };
|
||||
if (axis == AXIS_X || axis == AXIS_XY || axis == AXIS_XZ || axis == AXIS_XYZ)
|
||||
{
|
||||
colX = colSelected;
|
||||
dc.SetColor(colSelected);
|
||||
if (m_bNeedX && setup.axisGizmoText)
|
||||
{
|
||||
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(x), textSize, "x");
|
||||
}
|
||||
linew[0] = lineWidth;
|
||||
}
|
||||
if (axis == AXIS_Y || axis == AXIS_XY || axis == AXIS_YZ || axis == AXIS_XYZ)
|
||||
{
|
||||
colY = colSelected;
|
||||
dc.SetColor(colSelected);
|
||||
if (m_bNeedY && setup.axisGizmoText)
|
||||
{
|
||||
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(y), textSize, "y");
|
||||
}
|
||||
linew[1] = lineWidth;
|
||||
}
|
||||
if (axis == AXIS_Z || axis == AXIS_XZ || axis == AXIS_YZ || axis == AXIS_XYZ)
|
||||
{
|
||||
colZ = colSelected;
|
||||
dc.SetColor(colSelected);
|
||||
if (m_bNeedZ && setup.axisGizmoText)
|
||||
{
|
||||
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(z), textSize, "z");
|
||||
}
|
||||
linew[2] = lineWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Calc sizes.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float headOfs[8];
|
||||
float headScl[8];
|
||||
headOfs[MOVE_MODE] = 0;
|
||||
headScl[MOVE_MODE] = 0.07f * m_fScreenScale;
|
||||
headOfs[ROTATE_MODE] = 0;
|
||||
headScl[ROTATE_MODE] = 0.01f * m_fScreenScale;
|
||||
headOfs[SCALE_MODE] = 0;
|
||||
headScl[SCALE_MODE] = 0.01f * m_fScreenScale;
|
||||
if (m_nModeFlags == (MOVE_MODE | ROTATE_MODE | SCALE_MODE))
|
||||
{
|
||||
headOfs[ROTATE_MODE] += 0.05f * m_fScreenScale;
|
||||
headOfs[SCALE_MODE] += 0.1f * m_fScreenScale;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (!(m_nModeFlags & ROTATE_CIRCLE_MODE))
|
||||
{
|
||||
if (m_bNeedX)
|
||||
{
|
||||
dc.SetColor(colX);
|
||||
dc.SetLineWidth(linew[0]);
|
||||
dc.DrawLine(Vec3(0, 0, 0), x + Vec3(headOfs[SCALE_MODE], 0, 0));
|
||||
}
|
||||
if (m_bNeedY)
|
||||
{
|
||||
dc.SetColor(colY);
|
||||
dc.SetLineWidth(linew[1]);
|
||||
dc.DrawLine(Vec3(0, 0, 0), y + Vec3(0, headOfs[SCALE_MODE], 0));
|
||||
}
|
||||
if (m_bNeedZ)
|
||||
{
|
||||
dc.SetColor(colZ);
|
||||
dc.SetLineWidth(linew[2]);
|
||||
dc.DrawLine(Vec3(0, 0, 0), z + Vec3(0, 0, headOfs[SCALE_MODE]));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Draw Move Arrows.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (m_nModeFlags & MOVE_MODE)
|
||||
{
|
||||
if (m_bNeedX)
|
||||
{
|
||||
if (m_highlightMode == 1)
|
||||
{
|
||||
dc.SetColor(colX);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetColor(colXArrow);
|
||||
}
|
||||
dc.DrawArrow(x - x * 0.1f, x, headScl[MOVE_MODE]);
|
||||
}
|
||||
if (m_bNeedY)
|
||||
{
|
||||
if (m_highlightMode == 1)
|
||||
{
|
||||
dc.SetColor(colY);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetColor(colYArrow);
|
||||
}
|
||||
dc.DrawArrow(y - y * 0.1f, y, headScl[MOVE_MODE]);
|
||||
}
|
||||
if (m_bNeedZ)
|
||||
{
|
||||
if (m_highlightMode == 1)
|
||||
{
|
||||
dc.SetColor(colZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetColor(colZArrow);
|
||||
}
|
||||
dc.DrawArrow(z - z * 0.1f, z, headScl[MOVE_MODE]);
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Draw Scale Boxes.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (m_nModeFlags & SCALE_MODE)
|
||||
{
|
||||
dc.SetColor(QColor(128, 128, 0));
|
||||
Vec3 boxsz = Vec3(headScl[SCALE_MODE], headScl[SCALE_MODE], headScl[SCALE_MODE]);
|
||||
dc.DrawSolidBox(-boxsz, boxsz);
|
||||
if (m_bNeedX)
|
||||
{
|
||||
if (m_highlightMode == 3)
|
||||
{
|
||||
dc.SetColor(colX);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetColor(colXArrow);
|
||||
}
|
||||
dc.DrawSolidBox(x + boxsz + Vec3(headOfs[SCALE_MODE], 0, 0), x - boxsz + Vec3(headOfs[SCALE_MODE], 0, 0));
|
||||
}
|
||||
if (m_bNeedY)
|
||||
{
|
||||
if (m_highlightMode == 3)
|
||||
{
|
||||
dc.SetColor(colY);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetColor(colYArrow);
|
||||
}
|
||||
dc.DrawSolidBox(y + boxsz + Vec3(0, headOfs[SCALE_MODE], 0), y - boxsz + Vec3(0, headOfs[SCALE_MODE], 0));
|
||||
}
|
||||
if (m_bNeedZ)
|
||||
{
|
||||
if (m_highlightMode == 3)
|
||||
{
|
||||
dc.SetColor(colZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetColor(colZArrow);
|
||||
}
|
||||
dc.DrawSolidBox(z + boxsz + Vec3(0, 0, headOfs[SCALE_MODE]), z - boxsz + Vec3(0, 0, headOfs[SCALE_MODE]));
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Draw Rotate Circle
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (m_nModeFlags & ROTATE_CIRCLE_MODE)
|
||||
{
|
||||
if (m_bHighlightRotationCircle)
|
||||
{
|
||||
dc.SetLineWidth(5);
|
||||
dc.SetColor(colSelected);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetLineWidth(0);
|
||||
dc.SetColor(axisColor);
|
||||
}
|
||||
dc.DrawCircle(Vec3(0, 0, 0), kRotateCircleRadiusScale * m_fScreenScale, 0);
|
||||
}
|
||||
|
||||
dc.SetLineWidth(0);
|
||||
|
||||
// If only in move mode.
|
||||
if (m_nModeFlags == MOVE_MODE)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Draw axis planes.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 colXY[2];
|
||||
Vec3 colXZ[2];
|
||||
Vec3 colYZ[2];
|
||||
|
||||
if (setup.enabled)
|
||||
{
|
||||
colX = Vec3(1, 0, 0);
|
||||
colY = Vec3(0, 1, 0);
|
||||
colZ = Vec3(0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
colX = colY = colZ = disabledColor;
|
||||
}
|
||||
colXY[0] = colX;
|
||||
colXY[1] = colY;
|
||||
colXZ[0] = colX;
|
||||
colXZ[1] = colZ;
|
||||
colYZ[0] = colY;
|
||||
colYZ[1] = colZ;
|
||||
|
||||
linew[0] = linew[1] = linew[2] = 0;
|
||||
if (axis)
|
||||
{
|
||||
if (axis == AXIS_XY)
|
||||
{
|
||||
colXY[0] = colSelected;
|
||||
colXY[1] = colSelected;
|
||||
linew[0] = lineWidth;
|
||||
}
|
||||
else if (axis == AXIS_XZ)
|
||||
{
|
||||
colXZ[0] = colSelected;
|
||||
colXZ[1] = colSelected;
|
||||
linew[1] = lineWidth;
|
||||
}
|
||||
else if (axis == AXIS_YZ)
|
||||
{
|
||||
colYZ[0] = colSelected;
|
||||
colYZ[1] = colSelected;
|
||||
linew[2] = lineWidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dc.flags & DISPLAY_2D))
|
||||
{
|
||||
if (axis == AXIS_TERRAIN)
|
||||
{
|
||||
dc.SetColor(colSelected, 0.4f);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetColor(QColor(128, 32, 32), 0.4f);
|
||||
}
|
||||
Vec3 org = worldTM.GetTranslation();
|
||||
dc.DrawBall(Vec3(0.0f), m_size * kSelectionBallScale);
|
||||
}
|
||||
|
||||
dc.SetColor(QColor(255, 255, 0), 0.5f);
|
||||
|
||||
float sz = m_size * kPlaneScale;
|
||||
Vec3 p1(sz, sz, 0);
|
||||
Vec3 p2(sz, 0, sz);
|
||||
Vec3 p3(0, sz, sz);
|
||||
|
||||
float colAlpha = 1.0f;
|
||||
x *= kPlaneScale;
|
||||
y *= kPlaneScale;
|
||||
z *= kPlaneScale;
|
||||
|
||||
// XY
|
||||
if (m_bNeedX && m_bNeedY)
|
||||
{
|
||||
dc.SetLineWidth(linew[0]);
|
||||
dc.SetColor(colXY[0], colAlpha);
|
||||
dc.DrawLine(p1, p1 - x);
|
||||
dc.SetColor(colXY[1], colAlpha);
|
||||
dc.DrawLine(p1, p1 - y);
|
||||
}
|
||||
|
||||
// XZ
|
||||
if (m_bNeedX && m_bNeedZ)
|
||||
{
|
||||
dc.SetLineWidth(linew[1]);
|
||||
dc.SetColor(colXZ[0], colAlpha);
|
||||
dc.DrawLine(p2, p2 - x);
|
||||
dc.SetColor(colXZ[1], colAlpha);
|
||||
dc.DrawLine(p2, p2 - z);
|
||||
}
|
||||
|
||||
// YZ
|
||||
if (m_bNeedY && m_bNeedZ)
|
||||
{
|
||||
dc.SetLineWidth(linew[2]);
|
||||
dc.SetColor(colYZ[0], colAlpha);
|
||||
dc.DrawLine(p3, p3 - y);
|
||||
dc.SetColor(colYZ[1], colAlpha);
|
||||
dc.DrawLine(p3, p3 - z);
|
||||
}
|
||||
|
||||
dc.SetLineWidth(0);
|
||||
|
||||
colAlpha = 0.25f;
|
||||
|
||||
if (axis == AXIS_XY && m_bNeedX && m_bNeedY)
|
||||
{
|
||||
dc.CullOff();
|
||||
dc.SetColor(colSelected, colAlpha);
|
||||
dc.DrawQuad(p1, p1 - x, p1 - x - y, p1 - y);
|
||||
dc.CullOn();
|
||||
}
|
||||
else if (axis == AXIS_XZ && m_bNeedX && m_bNeedZ)
|
||||
{
|
||||
dc.CullOff();
|
||||
dc.SetColor(colSelected, colAlpha);
|
||||
dc.DrawQuad(p2, p2 - x, p2 - x - z, p2 - z);
|
||||
dc.CullOn();
|
||||
}
|
||||
else if (axis == AXIS_YZ && m_bNeedY && m_bNeedZ)
|
||||
{
|
||||
dc.CullOff();
|
||||
dc.SetColor(colSelected, colAlpha);
|
||||
dc.DrawQuad(p3, p3 - y, p3 - y - z, p3 - z);
|
||||
dc.CullOn();
|
||||
}
|
||||
}
|
||||
|
||||
dc.PopMatrix();
|
||||
if (!(dc.flags & DISPLAY_2D))
|
||||
{
|
||||
dc.DepthTestOn();
|
||||
}
|
||||
|
||||
dc.SetState(prevRState);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAxisHelper::HitTestForRotationCircle(const Matrix34& worldTM, IDisplayViewport* view, const QPoint& pos, float fHitWidth, Vec3* pOutHitPos, Vec3* pOutHitNormal)
|
||||
{
|
||||
Ray ray;
|
||||
view->ViewToWorldRay(pos, ray.origin, ray.direction);
|
||||
|
||||
const float fCircleRadius = kRotateCircleRadiusScale * m_fScreenScale;
|
||||
|
||||
std::vector<Vec3> vList;
|
||||
float step = 30.0f / 180 * gf_PI;
|
||||
for (float angle = 0; angle < 360.0f / 180 * gf_PI + step; angle += step)
|
||||
{
|
||||
Vec3 p(0, fCircleRadius * sin(angle), fCircleRadius * cos(angle));
|
||||
vList.push_back(worldTM.TransformPoint(p));
|
||||
}
|
||||
|
||||
Vec3 vDir0 = (vList[0] - vList[1]).GetNormalized();
|
||||
Vec3 vDir1 = (vList[2] - vList[1]).GetNormalized();
|
||||
Vec3 vNormal = vDir1.Cross(vDir0).GetNormalized();
|
||||
|
||||
if (pOutHitNormal)
|
||||
{
|
||||
*pOutHitNormal = vNormal;
|
||||
}
|
||||
|
||||
Vec3 vShortestHitPos;
|
||||
float shortestDist = 3e11f;
|
||||
|
||||
for (int i = 0, iCount(vList.size()); i < iCount; ++i)
|
||||
{
|
||||
const Vec3& v0 = vList[i];
|
||||
const Vec3& v1 = vList[(i + 1) % iCount];
|
||||
Vec3 vRight = (v1 - v0).Cross(vNormal).GetNormalized() * m_fScreenScale * fHitWidth;
|
||||
|
||||
Vec3 p_v0 = v0 + vRight;
|
||||
Vec3 p_v1 = v1 + vRight;
|
||||
Vec3 p_v2 = v1 - vRight;
|
||||
Vec3 p_v3 = v0 - vRight;
|
||||
|
||||
Vec3 hitPos;
|
||||
if (Intersect::Ray_Triangle(ray, p_v0, p_v1, p_v2, hitPos) || Intersect::Ray_Triangle(ray, p_v0, p_v2, p_v3, hitPos) ||
|
||||
Intersect::Ray_Triangle(ray, p_v0, p_v2, p_v1, hitPos) || Intersect::Ray_Triangle(ray, p_v0, p_v3, p_v2, hitPos))
|
||||
{
|
||||
Vec3 hitPosToEdge;
|
||||
if (PointToLineDistance(v0, v1, hitPos, hitPosToEdge))
|
||||
{
|
||||
if (!pOutHitPos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
float hitDistance = hitPosToEdge.GetDistance(hitPos);
|
||||
if (hitDistance < shortestDist)
|
||||
{
|
||||
vShortestHitPos = hitPosToEdge;
|
||||
shortestDist = hitDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shortestDist < 3e10f)
|
||||
{
|
||||
if (pOutHitPos)
|
||||
{
|
||||
*pOutHitPos = vShortestHitPos;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAxisHelper::HitTest(const Matrix34& worldTM, const SGizmoParameters& setup, HitContext& hc)
|
||||
{
|
||||
if (hc.distanceTolerance != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Prepare(worldTM, setup, hc.view);
|
||||
|
||||
m_bHighlightRotationCircle = false;
|
||||
hc.manipulatorMode = 0;
|
||||
|
||||
if (m_nModeFlags == ROTATE_CIRCLE_MODE)
|
||||
{
|
||||
if (HitTestForRotationCircle(m_matrix, hc.view, hc.point2d, 0.05f))
|
||||
{
|
||||
m_bHighlightRotationCircle = true;
|
||||
hc.manipulatorMode = 4;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Vec3 x(m_size, 0, 0);
|
||||
Vec3 y(0, m_size, 0);
|
||||
Vec3 z(0, 0, m_size);
|
||||
|
||||
Vec3 pos = m_matrix.GetTranslation();
|
||||
|
||||
Vec3 intPoint;
|
||||
hc.view->ViewToWorldRay(hc.point2d, hc.raySrc, hc.rayDir);
|
||||
Ray ray(hc.raySrc, hc.rayDir);
|
||||
Sphere sphere(pos, m_size + 0.1f * m_fScreenScale);
|
||||
if (!Intersect::Ray_SphereFirst(ray, sphere, intPoint))
|
||||
{
|
||||
m_highlightAxis = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
x = m_matrix.TransformVector(x);
|
||||
y = m_matrix.TransformVector(y);
|
||||
z = m_matrix.TransformVector(z);
|
||||
|
||||
float sz = m_size * kPlaneScale;
|
||||
Vec3 p1(sz, sz, 0);
|
||||
Vec3 p2(sz, 0, sz);
|
||||
Vec3 p3(0, sz, sz);
|
||||
|
||||
p1 = m_matrix.TransformPoint(p1);
|
||||
p2 = m_matrix.TransformPoint(p2);
|
||||
p3 = m_matrix.TransformPoint(p3);
|
||||
|
||||
Vec3 planeX = x * kPlaneScale;
|
||||
Vec3 planeY = y * kPlaneScale;
|
||||
Vec3 planeZ = z * kPlaneScale;
|
||||
|
||||
int axis = 0;
|
||||
|
||||
Sphere testSphere(pos, m_size * kSelectionBallScale);
|
||||
if (!hc.b2DViewport && m_nModeFlags == MOVE_MODE && Intersect::Ray_SphereFirst(ray, testSphere, intPoint))
|
||||
{
|
||||
axis = AXIS_TERRAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start the closestAxis value at the maximum selection radius based on the user's settings
|
||||
float closestAxis = aznumeric_cast<float>(GetIEditor()->GetObjectManager()->GetAxisHelperHitRadius());
|
||||
|
||||
float distanceToAxis = hc.view->GetDistanceToLine(pos, pos + x, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_X;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
distanceToAxis = hc.view->GetDistanceToLine(pos, pos + y, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_Y;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
distanceToAxis = hc.view->GetDistanceToLine(pos, pos + z, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_Z;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
if (m_nModeFlags == MOVE_MODE)
|
||||
{
|
||||
// If only in move mode.
|
||||
distanceToAxis = hc.view->GetDistanceToLine(p1, p1 - planeX, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_XY;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
distanceToAxis = hc.view->GetDistanceToLine(p1, p1 - planeY, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_XY;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
distanceToAxis = hc.view->GetDistanceToLine(p2, p2 - planeX, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_XZ;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
distanceToAxis = hc.view->GetDistanceToLine(p2, p2 - planeZ, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_XZ;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
distanceToAxis = hc.view->GetDistanceToLine(p3, p3 - planeY, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_YZ;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
distanceToAxis = hc.view->GetDistanceToLine(p3, p3 - planeZ, hc.point2d);
|
||||
if(distanceToAxis < closestAxis)
|
||||
{
|
||||
axis = AXIS_YZ;
|
||||
closestAxis = distanceToAxis;
|
||||
}
|
||||
if (axis != 0)
|
||||
{
|
||||
hc.manipulatorMode = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Calc sizes.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float headOfs[8];
|
||||
float headScl[8];
|
||||
headOfs[MOVE_MODE] = 0;
|
||||
headScl[MOVE_MODE] = 0.07f * m_fScreenScale;
|
||||
headOfs[ROTATE_MODE] = 0;
|
||||
headScl[ROTATE_MODE] = 0.01f * m_fScreenScale;
|
||||
headOfs[SCALE_MODE] = 0;
|
||||
headScl[SCALE_MODE] = 0.01f * m_fScreenScale;
|
||||
if (m_nModeFlags == (MOVE_MODE | ROTATE_MODE | SCALE_MODE))
|
||||
{
|
||||
headOfs[ROTATE_MODE] += 0.05f * m_fScreenScale;
|
||||
headOfs[SCALE_MODE] += 0.1f * m_fScreenScale;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (axis == 0 && (m_nModeFlags & ROTATE_MODE))
|
||||
{
|
||||
Vec3 x2(m_size, 0, 0);
|
||||
Vec3 y2(0, m_size, 0);
|
||||
Vec3 z2(0, 0, m_size);
|
||||
int hitr = 10;
|
||||
if (m_bNeedX)
|
||||
{
|
||||
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(x2 + Vec3(headOfs[ROTATE_MODE], 0, 0))) < hitr)
|
||||
{
|
||||
axis = AXIS_X;
|
||||
hc.manipulatorMode = 2;
|
||||
}
|
||||
}
|
||||
if (m_bNeedY)
|
||||
{
|
||||
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(y2 + Vec3(0, headOfs[ROTATE_MODE], 0))) < hitr)
|
||||
{
|
||||
axis = AXIS_Y;
|
||||
hc.manipulatorMode = 2;
|
||||
}
|
||||
}
|
||||
if (m_bNeedZ)
|
||||
{
|
||||
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(z2 + Vec3(0, 0, headOfs[ROTATE_MODE]))) < hitr)
|
||||
{
|
||||
axis = AXIS_Z;
|
||||
hc.manipulatorMode = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_nModeFlags & SCALE_MODE)
|
||||
{
|
||||
Vec3 x2(m_size, 0, 0);
|
||||
Vec3 y2(0, m_size, 0);
|
||||
Vec3 z2(0, 0, m_size);
|
||||
int hitr = 14;
|
||||
if (GetDistance2D(hc.view, hc.point2d, m_matrix.GetTranslation()) < hitr + 2)
|
||||
{
|
||||
axis = AXIS_XYZ;
|
||||
hc.manipulatorMode = 3;
|
||||
}
|
||||
if (axis == 0)
|
||||
{
|
||||
if (m_bNeedX)
|
||||
{
|
||||
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(x2 + Vec3(headOfs[SCALE_MODE], 0, 0))) < hitr)
|
||||
{
|
||||
axis = AXIS_X;
|
||||
hc.manipulatorMode = 3;
|
||||
}
|
||||
}
|
||||
if (m_bNeedY)
|
||||
{
|
||||
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(y2 + Vec3(0, headOfs[SCALE_MODE], 0))) < hitr)
|
||||
{
|
||||
axis = AXIS_Y;
|
||||
hc.manipulatorMode = 3;
|
||||
}
|
||||
}
|
||||
if (m_bNeedZ)
|
||||
{
|
||||
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(z2 + Vec3(0, 0, headOfs[SCALE_MODE]))) < hitr)
|
||||
{
|
||||
axis = AXIS_Z;
|
||||
hc.manipulatorMode = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (axis != 0)
|
||||
{
|
||||
if (hc.manipulatorMode == 0)
|
||||
{
|
||||
if (m_nModeFlags & MOVE_MODE)
|
||||
{
|
||||
hc.manipulatorMode = 1;
|
||||
}
|
||||
else if (m_nModeFlags & ROTATE_MODE)
|
||||
{
|
||||
hc.manipulatorMode = 2;
|
||||
}
|
||||
else if (m_nModeFlags & SCALE_MODE)
|
||||
{
|
||||
hc.manipulatorMode = 3;
|
||||
}
|
||||
}
|
||||
hc.axis = axis;
|
||||
hc.dist = 0;
|
||||
m_highlightMode = hc.manipulatorMode;
|
||||
}
|
||||
|
||||
m_highlightAxis = axis;
|
||||
|
||||
return axis != 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float CAxisHelper::GetDistance2D(IDisplayViewport* view, const QPoint& p, const Vec3& wp)
|
||||
{
|
||||
QPoint vp = view->WorldToView(wp);
|
||||
float dx = static_cast<float>(p.x() - vp.x());
|
||||
float dy = static_cast<float>(p.y() - vp.y());
|
||||
return sqrtf(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user