You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
12 KiB
C++
284 lines
12 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
#ifndef CRYINCLUDE_EDITOR_ROTATETOOL_H
|
|
#define CRYINCLUDE_EDITOR_ROTATETOOL_H
|
|
#pragma once
|
|
|
|
#if !defined(Q_MOC_RUN)
|
|
#include "EditTool.h"
|
|
#include "IObjectManager.h"
|
|
#include "EditMode/ObjectMode.h"
|
|
#include "Objects/BaseObject.h" // for CBaseObject::EventListener
|
|
#include "Objects/DisplayContext.h"
|
|
#include "Include/HitContext.h"
|
|
#endif
|
|
|
|
//! Provides rendering utilities to support CRotateTool
|
|
namespace RotationDrawHelper
|
|
{
|
|
//! Circle drawing and hit testing functionality over arbitrary axes
|
|
class Axis
|
|
{
|
|
public:
|
|
|
|
//! \param defaultColor Color used to draw the camera aligned portion of the axis.
|
|
//! \param highlightColor Color used to draw the circle when it is in focus.
|
|
Axis(const ColorF& defaultColor = Col_White, const ColorF& highlightColor = Col_Yellow);
|
|
|
|
//! Draws an axis aligned circle.
|
|
//! \param dc DisplayContext to use for rendering.
|
|
//! \param position World space position used as the center of the circle.
|
|
//! \param axis The axis by which to align the circle.
|
|
//! \param angleRadians The angle towards which the circle will be highlighted.
|
|
//! \param radius The radius of the circle.
|
|
//! \param highlighted If true it will draw the circle in the specified highlightColor.
|
|
void Draw(DisplayContext& dc, const Vec3& position, const Vec3& axis, float angleRadians, float angleStepRadians, float radius, bool highlighted, CBaseObject* object, float screenScale);
|
|
|
|
//! Calculates a hit testing mesh (invisible) used for intersection testing.
|
|
//! \param object The object selected if hit testing return true.
|
|
//! \param hc The HitContext in which the hit object is set if an intersection is true.
|
|
//! \param radius The radius for the axis' circle.
|
|
//! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle.
|
|
//! \param axis The axis by which to align the intersection geometry.
|
|
//! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool.
|
|
bool HitTest(CBaseObject* object, HitContext& hc, float radius, float angleStepRadians, const Vec3& axis, float screenScale);
|
|
|
|
//! Draws the generated hit testing geometry, good for diagnostics and debugging.
|
|
//! \param dc DisplayContext to use for rendering.
|
|
//! \param hc The HitContext that contains the view direction raycast.
|
|
//! \param position World space position used as the center of the circle.
|
|
//! \param radius The radius for the axis' circle.
|
|
//! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle.
|
|
//! \param axis The axis by which to align the intersection geometry.
|
|
//! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool.
|
|
void DebugDrawHitTestSurface(DisplayContext& dc, HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale);
|
|
|
|
protected:
|
|
|
|
enum States
|
|
{
|
|
StateDefault,
|
|
StateHighlight,
|
|
StateCount
|
|
};
|
|
|
|
ColorF m_colors[StateCount];
|
|
|
|
//! Defines the width of the generated hit testing geometry.
|
|
float m_hitTestWidth = 0.4f;
|
|
|
|
//! Contains the vertices that make up the ring for the intersection testing geometry.
|
|
//! \remark Only contains the center positions, quads are generated by calculating the four vertices offset by m_hitTestWidth.
|
|
std::vector<Vec3> m_vertices;
|
|
|
|
//! Generates the world space geometry necessary to perform hit testing.
|
|
//! \param hc The HitContext data.
|
|
//! \param position The world space position around which the geometry will be centered.
|
|
//! \param radius The radius of the ring.
|
|
//! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle.
|
|
//! \param axis The axis to which the geometry will be aligned to.
|
|
//! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool.
|
|
void GenerateHitTestGeometry(HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale);
|
|
|
|
//! Performs intersection testing between a ray and both sides of a quad
|
|
//! \param ray The ray to test (in world space)
|
|
//! \param quad An array of four Vec3 points in world space.
|
|
//! \param[out] contact The intersection position in world space at which the intersection occurred.
|
|
bool IntersectRayWithQuad(const Ray&ray, Vec3 quad[4], Vec3 & contact);
|
|
};
|
|
|
|
//! Provides the means to set and restore DisplayContext settings within a given scope.
|
|
class DisplayContextScope
|
|
{
|
|
public:
|
|
DisplayContextScope(DisplayContext& dc)
|
|
: m_dc(dc)
|
|
{
|
|
m_dc.DepthTestOff();
|
|
m_dc.CullOff();
|
|
}
|
|
|
|
~DisplayContextScope()
|
|
{
|
|
m_dc.DepthTestOn();
|
|
m_dc.CullOn();
|
|
}
|
|
|
|
DisplayContext& m_dc;
|
|
};
|
|
|
|
//! Helper function that draws the representation of the inner angle of a rotation.
|
|
namespace AngleDecorator
|
|
{
|
|
//! \param dc
|
|
//! \param position World space position of the center of the decorator.
|
|
//! \param axisToAlign Axis to which the decorator will be aligned to.
|
|
//! \param startAngleRadians The starting angle from which the rotation will be performed.
|
|
//! \param sweepAngleRadians An angle that represents the sweep of the rotation arc.
|
|
//! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle.
|
|
//! \param radius The radius of the decorator.
|
|
//! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool.
|
|
void Draw(DisplayContext& dc, const Vec3& position, const Vec3& axisToAlign, float startAngleRadians, float sweepAngleRadians, float stepAngleRadians, float radius, float screenScale);
|
|
}
|
|
}
|
|
|
|
//! Provides rotation manipulation controls.
|
|
class SANDBOX_API CRotateTool
|
|
: public CObjectMode
|
|
, public IObjectSelectCallback
|
|
, public CBaseObject::EventListener
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
Q_INVOKABLE CRotateTool(CBaseObject* pObject = nullptr, QWidget* parent = nullptr);
|
|
virtual ~CRotateTool();
|
|
|
|
static const GUID& GetClassID();
|
|
|
|
// Registration function.
|
|
static void RegisterTool(CRegistrationContext& rc);
|
|
|
|
void Display(DisplayContext& dc) override;
|
|
void DrawObjectHelpers([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] DisplayContext& dc) override {}
|
|
bool HitTest(CBaseObject* pObject, HitContext& hc) override;
|
|
void DeleteThis() override;
|
|
bool OnLButtonDown(CViewport* view, int nFlags, const QPoint& point) override;
|
|
bool OnLButtonUp(CViewport* view, int nFlags, const QPoint& point) override;
|
|
bool OnMouseMove(CViewport* view, int nFlags, const QPoint& point) override;
|
|
|
|
protected:
|
|
|
|
//! Utility to calculate the view distance ratio used to scale the tool.
|
|
float GetScreenScale(IDisplayViewport* view, CCamera* camera = nullptr);
|
|
|
|
enum Axis
|
|
{
|
|
AxisNone,
|
|
AxisX, //! X axis visualization and hit testing
|
|
AxisY, //! Y axis visualization and hit testing
|
|
AxisZ, //! Z axis visualization and hit testing
|
|
AxisView, //! View direction axis, used to rotate along the vector from the camera to the object.
|
|
AxisCount
|
|
};
|
|
|
|
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
//! Axis visualization and hit testing
|
|
RotationDrawHelper::Axis m_axes[Axis::AxisCount];
|
|
|
|
//! We record the starting angle when we begin to drag an object
|
|
float m_initialViewAxisAngleRadians;
|
|
|
|
//! The angle from the object's (or selection's) center to the mouse cursor.
|
|
float m_angleToCursor;
|
|
|
|
//! Specified which axis is currently selected.
|
|
Axis m_highlightAxis;
|
|
|
|
//! True when we are using the view direction rotation axis.
|
|
bool m_viewAxisRotation;
|
|
|
|
//! True when the mouse has been pressed, becomes false on release.
|
|
bool m_draggingMouse;
|
|
|
|
//! The last mouse position on screen when rotating.
|
|
QPoint m_lastPosition;
|
|
|
|
//! Cumulative rotation angle in degrees.
|
|
Ang3 m_rotationAngles;
|
|
|
|
//! The selected object.
|
|
CBaseObject* m_object;
|
|
|
|
//! True if there has been a change in rotation that affects the object.
|
|
bool m_bTransformChanged;
|
|
|
|
//! Sum of the total rotation angles.
|
|
float m_totalRotationAngle;
|
|
|
|
//! Radius used to draw the XYZ axes
|
|
float m_basisAxisRadius;
|
|
|
|
//! Radius used to draw the view direction axis
|
|
float m_viewAxisRadius;
|
|
|
|
//! Rotation step controls the quality of the axes, a smaller angle represents a higher number of vertices.
|
|
float m_arcRotationStepRadians;
|
|
|
|
//! Thickness of for the axis line rendering.
|
|
float m_lineThickness = 4.f;
|
|
|
|
//! Draws angle decorator for the current rotation axis.
|
|
void DrawAngleDecorator(DisplayContext& dc);
|
|
|
|
//! Useful for debugging and visualizing hit testing
|
|
void DrawHitTestGeometry(DisplayContext& dc, HitContext& hc);
|
|
|
|
//! Diagnostic tool to examine view direction angle (follows mouse cursor)
|
|
void DrawViewDirectionAngleTracking(DisplayContext& dc, HitContext& hc);
|
|
|
|
//! Callback registered to receive Selection callbacks to set m_object
|
|
bool OnSelectObject(CBaseObject* object) override;
|
|
|
|
//! Callback to check that an object can be selected
|
|
bool CanSelectObject(CBaseObject* object) override;
|
|
|
|
//! Callback installed on the object, used to determine destruction or deselection.
|
|
void OnObjectEvent(CBaseObject* object, int event) override;
|
|
|
|
//! Handle key down events.
|
|
bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags) override;
|
|
|
|
//! Retrieves the object's transformation according to the specified reference coordinate system.
|
|
Matrix34 GetTransform(RefCoordSys referenceCoordinateSystem, IDisplayViewport* view);
|
|
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
|
|
//! Calculate orientation of 3 points on screen, return 1.0f if clockwise, -1.0f if counter-clockwise
|
|
float CalculateOrientation(const QPoint& p1, const QPoint& p2, const QPoint& p3);
|
|
|
|
private:
|
|
|
|
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
HitContext m_hc; //!< HACK: Cache the hitcontext given that it's values may differ depending on the viewport they are coming from.
|
|
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
};
|
|
|
|
//! Singleton that holds all the configuration cvars for the different features and debug options
|
|
//! used by the CRotationControl
|
|
class RotationControlConfiguration
|
|
{
|
|
public:
|
|
|
|
static RotationControlConfiguration& Get()
|
|
{
|
|
static RotationControlConfiguration instance;
|
|
return instance;
|
|
}
|
|
|
|
//! If enabled it will draw the inner rotation decorator.
|
|
DeclareConstIntCVar(RotationControl_DrawDecorators, 0);
|
|
|
|
//! If enabled the hit testing geometry is rendered.
|
|
DeclareConstIntCVar(RotationControl_DebugHitTesting, 0);
|
|
|
|
//! If enabled a sphere will be drawn to represent the view axis angle to the mouse cursor.
|
|
DeclareConstIntCVar(RotationControl_AngleTracking, 0);
|
|
|
|
private:
|
|
|
|
RotationControlConfiguration();
|
|
RotationControlConfiguration(const RotationControlConfiguration&) = delete;
|
|
RotationControlConfiguration& operator = (const RotationControlConfiguration&) = delete;
|
|
~RotationControlConfiguration() {}
|
|
};
|
|
|
|
#endif // CRYINCLUDE_EDITOR_ROTATETOOL_H
|