2026-04-19 00:36:24 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <XCEngine/Core/Math/Color.h>
|
|
|
|
|
#include <XCEngine/Core/Math/Matrix4.h>
|
|
|
|
|
#include <XCEngine/Core/Math/Plane.h>
|
|
|
|
|
#include <XCEngine/Core/Math/Quaternion.h>
|
|
|
|
|
#include <XCEngine/Core/Math/Ray.h>
|
|
|
|
|
#include <XCEngine/Core/Math/Vector2.h>
|
|
|
|
|
#include <XCEngine/Core/Math/Vector3.h>
|
|
|
|
|
#include <XCEngine/Core/Math/Vector4.h>
|
|
|
|
|
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
namespace XCEngine::Components {
|
|
|
|
|
|
|
|
|
|
class GameObject;
|
|
|
|
|
|
|
|
|
|
} // namespace XCEngine::Components
|
|
|
|
|
|
2026-04-21 00:57:14 +08:00
|
|
|
namespace XCEngine::UI::Editor::App::SceneViewportGizmoSupport {
|
2026-04-19 00:36:24 +08:00
|
|
|
|
|
|
|
|
class IUndoManager {
|
|
|
|
|
public:
|
|
|
|
|
virtual ~IUndoManager() = default;
|
|
|
|
|
|
|
|
|
|
virtual void BeginInteractiveChange(const std::string& label) = 0;
|
|
|
|
|
virtual bool HasPendingInteractiveChange() const = 0;
|
|
|
|
|
virtual void FinalizeInteractiveChange() = 0;
|
|
|
|
|
virtual void CancelInteractiveChange() = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportOverlayData {
|
|
|
|
|
bool valid = false;
|
|
|
|
|
Math::Vector3 cameraPosition = Math::Vector3::Zero();
|
|
|
|
|
Math::Vector3 cameraForward = Math::Vector3::Forward();
|
|
|
|
|
Math::Vector3 cameraRight = Math::Vector3::Right();
|
|
|
|
|
Math::Vector3 cameraUp = Math::Vector3::Up();
|
|
|
|
|
float verticalFovDegrees = 60.0f;
|
|
|
|
|
float nearClipPlane = 0.03f;
|
|
|
|
|
float farClipPlane = 2000.0f;
|
|
|
|
|
float orbitDistance = 6.0f;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportProjectedPoint {
|
|
|
|
|
Math::Vector2 screenPosition = Math::Vector2::Zero();
|
|
|
|
|
float ndcDepth = 0.0f;
|
|
|
|
|
bool visible = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportOverlayScreenTriangleVertex {
|
|
|
|
|
Math::Vector2 screenPosition = Math::Vector2::Zero();
|
|
|
|
|
Math::Color color = Math::Color::White();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportOverlayScreenTrianglePrimitive {
|
|
|
|
|
std::array<SceneViewportOverlayScreenTriangleVertex, 3> vertices = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportOverlayFrameData {
|
|
|
|
|
SceneViewportOverlayData overlay = {};
|
|
|
|
|
std::vector<SceneViewportOverlayScreenTrianglePrimitive> screenTriangles = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Math::Matrix4x4 BuildSceneViewportViewMatrix(const SceneViewportOverlayData& overlay);
|
|
|
|
|
Math::Matrix4x4 BuildSceneViewportProjectionMatrix(
|
|
|
|
|
const SceneViewportOverlayData& overlay,
|
|
|
|
|
float viewportWidth,
|
|
|
|
|
float viewportHeight);
|
|
|
|
|
Math::Matrix4x4 BuildSceneViewportViewProjectionMatrix(
|
|
|
|
|
const SceneViewportOverlayData& overlay,
|
|
|
|
|
float viewportWidth,
|
|
|
|
|
float viewportHeight);
|
|
|
|
|
|
|
|
|
|
SceneViewportProjectedPoint ProjectSceneViewportWorldPoint(
|
|
|
|
|
const SceneViewportOverlayData& overlay,
|
|
|
|
|
float viewportWidth,
|
|
|
|
|
float viewportHeight,
|
|
|
|
|
const Math::Vector3& worldPoint);
|
|
|
|
|
|
|
|
|
|
bool ProjectSceneViewportAxisDirection(
|
|
|
|
|
const SceneViewportOverlayData& overlay,
|
|
|
|
|
const Math::Vector3& worldAxis,
|
|
|
|
|
Math::Vector2& outScreenDirection);
|
|
|
|
|
|
|
|
|
|
bool ProjectSceneViewportAxisDirectionAtPoint(
|
|
|
|
|
const SceneViewportOverlayData& overlay,
|
|
|
|
|
float viewportWidth,
|
|
|
|
|
float viewportHeight,
|
|
|
|
|
const Math::Vector3& worldPoint,
|
|
|
|
|
const Math::Vector3& worldAxis,
|
|
|
|
|
Math::Vector2& outScreenDirection,
|
|
|
|
|
float sampleDistance = 1.0f);
|
|
|
|
|
|
|
|
|
|
float DistanceToSegmentSquared(
|
|
|
|
|
const Math::Vector2& point,
|
|
|
|
|
const Math::Vector2& segmentStart,
|
|
|
|
|
const Math::Vector2& segmentEnd,
|
|
|
|
|
float* outSegmentT = nullptr);
|
|
|
|
|
|
|
|
|
|
Math::Plane BuildSceneViewportPlaneFromPointNormal(
|
|
|
|
|
const Math::Vector3& point,
|
|
|
|
|
const Math::Vector3& normal);
|
|
|
|
|
|
|
|
|
|
bool BuildSceneViewportAxisDragPlaneNormal(
|
|
|
|
|
const SceneViewportOverlayData& overlay,
|
|
|
|
|
const Math::Vector3& worldAxis,
|
|
|
|
|
Math::Vector3& outPlaneNormal);
|
|
|
|
|
|
|
|
|
|
bool BuildSceneViewportRay(
|
|
|
|
|
const SceneViewportOverlayData& overlay,
|
|
|
|
|
const Math::Vector2& viewportSize,
|
|
|
|
|
const Math::Vector2& viewportPosition,
|
|
|
|
|
Math::Ray& outRay);
|
|
|
|
|
|
|
|
|
|
enum class SceneViewportGizmoAxis : std::uint8_t {
|
|
|
|
|
None = 0,
|
|
|
|
|
X,
|
|
|
|
|
Y,
|
|
|
|
|
Z
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum class SceneViewportGizmoPlane : std::uint8_t {
|
|
|
|
|
None = 0,
|
|
|
|
|
XY,
|
|
|
|
|
XZ,
|
|
|
|
|
YZ
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportMoveGizmoHandleDrawData {
|
|
|
|
|
SceneViewportGizmoAxis axis = SceneViewportGizmoAxis::None;
|
|
|
|
|
Math::Vector2 start = Math::Vector2::Zero();
|
|
|
|
|
Math::Vector2 end = Math::Vector2::Zero();
|
|
|
|
|
Math::Color color = Math::Color::White();
|
|
|
|
|
bool visible = false;
|
|
|
|
|
bool hovered = false;
|
|
|
|
|
bool active = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportMoveGizmoPlaneDrawData {
|
|
|
|
|
SceneViewportGizmoPlane plane = SceneViewportGizmoPlane::None;
|
|
|
|
|
std::array<Math::Vector2, 4> corners = {};
|
|
|
|
|
Math::Color fillColor = Math::Color::White();
|
|
|
|
|
Math::Color outlineColor = Math::Color::White();
|
|
|
|
|
bool visible = false;
|
|
|
|
|
bool hovered = false;
|
|
|
|
|
bool active = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportMoveGizmoDrawData {
|
|
|
|
|
bool visible = false;
|
|
|
|
|
Math::Vector2 pivot = Math::Vector2::Zero();
|
|
|
|
|
float pivotRadius = 5.0f;
|
|
|
|
|
std::array<SceneViewportMoveGizmoHandleDrawData, 3> handles = {};
|
|
|
|
|
std::array<SceneViewportMoveGizmoPlaneDrawData, 3> planes = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportMoveGizmoContext {
|
|
|
|
|
SceneViewportOverlayData overlay = {};
|
|
|
|
|
Math::Vector2 viewportSize = Math::Vector2::Zero();
|
|
|
|
|
Math::Vector2 mousePosition = Math::Vector2::Zero();
|
|
|
|
|
Components::GameObject* selectedObject = nullptr;
|
|
|
|
|
std::vector<Components::GameObject*> selectedObjects = {};
|
|
|
|
|
Math::Vector3 pivotWorldPosition = Math::Vector3::Zero();
|
|
|
|
|
Math::Quaternion axisOrientation = Math::Quaternion::Identity();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportMoveGizmoHitResult {
|
|
|
|
|
SceneViewportGizmoAxis axis = SceneViewportGizmoAxis::None;
|
|
|
|
|
SceneViewportGizmoPlane plane = SceneViewportGizmoPlane::None;
|
|
|
|
|
float distanceSq = Math::FLOAT_MAX;
|
|
|
|
|
|
|
|
|
|
bool HasHit() const {
|
|
|
|
|
return axis != SceneViewportGizmoAxis::None || plane != SceneViewportGizmoPlane::None;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class SceneViewportMoveGizmo {
|
|
|
|
|
public:
|
|
|
|
|
void Update(const SceneViewportMoveGizmoContext& context);
|
|
|
|
|
bool TryBeginDrag(const SceneViewportMoveGizmoContext& context, IUndoManager& undoManager);
|
|
|
|
|
void UpdateDrag(const SceneViewportMoveGizmoContext& context);
|
|
|
|
|
void EndDrag(IUndoManager& undoManager);
|
|
|
|
|
void CancelDrag(IUndoManager* undoManager = nullptr);
|
|
|
|
|
|
|
|
|
|
bool IsHoveringHandle() const;
|
|
|
|
|
bool IsActive() const;
|
|
|
|
|
std::uint64_t GetActiveEntityId() const;
|
|
|
|
|
const SceneViewportMoveGizmoDrawData& GetDrawData() const;
|
|
|
|
|
SceneViewportMoveGizmoHitResult EvaluateHit(const Math::Vector2& mousePosition) const;
|
|
|
|
|
void SetHoveredHandle(SceneViewportGizmoAxis axis, SceneViewportGizmoPlane plane);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
enum class DragMode : std::uint8_t {
|
|
|
|
|
None = 0,
|
|
|
|
|
Axis,
|
|
|
|
|
Plane
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void BuildDrawData(const SceneViewportMoveGizmoContext& context);
|
|
|
|
|
void RefreshHandleState();
|
|
|
|
|
|
|
|
|
|
SceneViewportMoveGizmoDrawData m_drawData = {};
|
|
|
|
|
SceneViewportGizmoAxis m_hoveredAxis = SceneViewportGizmoAxis::None;
|
|
|
|
|
SceneViewportGizmoPlane m_hoveredPlane = SceneViewportGizmoPlane::None;
|
|
|
|
|
SceneViewportGizmoAxis m_activeAxis = SceneViewportGizmoAxis::None;
|
|
|
|
|
SceneViewportGizmoPlane m_activePlane = SceneViewportGizmoPlane::None;
|
|
|
|
|
DragMode m_dragMode = DragMode::None;
|
|
|
|
|
std::uint64_t m_activeEntityId = 0;
|
|
|
|
|
Math::Vector3 m_activeAxisDirection = Math::Vector3::Zero();
|
|
|
|
|
Math::Vector3 m_activePlaneNormal = Math::Vector3::Zero();
|
|
|
|
|
Math::Plane m_dragPlane = {};
|
|
|
|
|
Math::Vector3 m_dragStartPivotWorldPosition = Math::Vector3::Zero();
|
|
|
|
|
Math::Vector3 m_dragStartHitWorldPosition = Math::Vector3::Zero();
|
|
|
|
|
float m_dragStartAxisScalar = 0.0f;
|
|
|
|
|
std::vector<Components::GameObject*> m_dragObjects = {};
|
|
|
|
|
std::vector<Math::Vector3> m_dragStartObjectWorldPositions = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum class SceneViewportRotateGizmoAxis : std::uint8_t {
|
|
|
|
|
None = 0,
|
|
|
|
|
X,
|
|
|
|
|
Y,
|
|
|
|
|
Z,
|
|
|
|
|
View
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constexpr std::size_t kSceneViewportRotateGizmoSegmentCount = 96u;
|
|
|
|
|
constexpr std::size_t kSceneViewportRotateGizmoAngleFillPointCount =
|
|
|
|
|
kSceneViewportRotateGizmoSegmentCount + 1u;
|
|
|
|
|
|
|
|
|
|
struct SceneViewportRotateGizmoSegmentDrawData {
|
|
|
|
|
Math::Vector2 start = Math::Vector2::Zero();
|
|
|
|
|
Math::Vector2 end = Math::Vector2::Zero();
|
|
|
|
|
float startAngle = 0.0f;
|
|
|
|
|
float endAngle = 0.0f;
|
|
|
|
|
bool visible = false;
|
|
|
|
|
bool frontFacing = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportRotateGizmoHandleDrawData {
|
|
|
|
|
SceneViewportRotateGizmoAxis axis = SceneViewportRotateGizmoAxis::None;
|
|
|
|
|
std::array<SceneViewportRotateGizmoSegmentDrawData, kSceneViewportRotateGizmoSegmentCount>
|
|
|
|
|
segments = {};
|
|
|
|
|
Math::Color color = Math::Color::White();
|
|
|
|
|
bool visible = false;
|
|
|
|
|
bool hovered = false;
|
|
|
|
|
bool active = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportRotateGizmoAngleFillDrawData {
|
|
|
|
|
SceneViewportRotateGizmoAxis axis = SceneViewportRotateGizmoAxis::None;
|
|
|
|
|
Math::Vector2 pivot = Math::Vector2::Zero();
|
|
|
|
|
std::array<Math::Vector2, kSceneViewportRotateGizmoAngleFillPointCount> arcPoints = {};
|
|
|
|
|
std::size_t arcPointCount = 0u;
|
|
|
|
|
Math::Color fillColor = Math::Color::White();
|
|
|
|
|
Math::Color outlineColor = Math::Color::White();
|
|
|
|
|
bool visible = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportRotateGizmoDrawData {
|
|
|
|
|
bool visible = false;
|
|
|
|
|
Math::Vector2 pivot = Math::Vector2::Zero();
|
|
|
|
|
std::array<SceneViewportRotateGizmoHandleDrawData, 4> handles = {};
|
|
|
|
|
SceneViewportRotateGizmoAngleFillDrawData angleFill = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportRotateGizmoContext {
|
|
|
|
|
SceneViewportOverlayData overlay = {};
|
|
|
|
|
Math::Vector2 viewportSize = Math::Vector2::Zero();
|
|
|
|
|
Math::Vector2 mousePosition = Math::Vector2::Zero();
|
|
|
|
|
Components::GameObject* selectedObject = nullptr;
|
|
|
|
|
std::vector<Components::GameObject*> selectedObjects = {};
|
|
|
|
|
Math::Vector3 pivotWorldPosition = Math::Vector3::Zero();
|
|
|
|
|
Math::Quaternion axisOrientation = Math::Quaternion::Identity();
|
|
|
|
|
bool localSpace = false;
|
|
|
|
|
bool rotateAroundSharedPivot = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportRotateGizmoHitResult {
|
|
|
|
|
SceneViewportRotateGizmoAxis axis = SceneViewportRotateGizmoAxis::None;
|
|
|
|
|
float distanceSq = Math::FLOAT_MAX;
|
|
|
|
|
|
|
|
|
|
bool HasHit() const {
|
|
|
|
|
return axis != SceneViewportRotateGizmoAxis::None;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class SceneViewportRotateGizmo {
|
|
|
|
|
public:
|
|
|
|
|
void Update(const SceneViewportRotateGizmoContext& context);
|
|
|
|
|
bool TryBeginDrag(const SceneViewportRotateGizmoContext& context, IUndoManager& undoManager);
|
|
|
|
|
void UpdateDrag(const SceneViewportRotateGizmoContext& context);
|
|
|
|
|
void EndDrag(IUndoManager& undoManager);
|
|
|
|
|
void CancelDrag(IUndoManager* undoManager = nullptr);
|
|
|
|
|
|
|
|
|
|
bool IsHoveringHandle() const;
|
|
|
|
|
bool IsActive() const;
|
|
|
|
|
std::uint64_t GetActiveEntityId() const;
|
|
|
|
|
const SceneViewportRotateGizmoDrawData& GetDrawData() const;
|
|
|
|
|
SceneViewportRotateGizmoHitResult EvaluateHit(const Math::Vector2& mousePosition) const;
|
|
|
|
|
void SetHoveredHandle(SceneViewportRotateGizmoAxis axis);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void BuildDrawData(const SceneViewportRotateGizmoContext& context);
|
|
|
|
|
void RefreshHandleState();
|
|
|
|
|
bool TryGetClosestRingAngle(
|
|
|
|
|
SceneViewportRotateGizmoAxis axis,
|
|
|
|
|
const Math::Vector2& mousePosition,
|
|
|
|
|
bool allowBackFacing,
|
|
|
|
|
float& outAngle) const;
|
|
|
|
|
|
|
|
|
|
SceneViewportRotateGizmoDrawData m_drawData = {};
|
|
|
|
|
SceneViewportRotateGizmoAxis m_hoveredAxis = SceneViewportRotateGizmoAxis::None;
|
|
|
|
|
SceneViewportRotateGizmoAxis m_activeAxis = SceneViewportRotateGizmoAxis::None;
|
|
|
|
|
std::uint64_t m_activeEntityId = 0;
|
|
|
|
|
bool m_screenSpaceDrag = false;
|
|
|
|
|
bool m_localSpace = false;
|
|
|
|
|
bool m_rotateAroundSharedPivot = false;
|
|
|
|
|
Math::Vector3 m_activeWorldAxis = Math::Vector3::Zero();
|
|
|
|
|
Math::Plane m_dragPlane = {};
|
|
|
|
|
float m_dragStartRingAngle = 0.0f;
|
|
|
|
|
float m_dragCurrentDeltaRadians = 0.0f;
|
|
|
|
|
Math::Vector3 m_dragStartPivotWorldPosition = Math::Vector3::Zero();
|
|
|
|
|
std::vector<Components::GameObject*> m_dragObjects = {};
|
|
|
|
|
std::vector<Math::Vector3> m_dragStartWorldPositions = {};
|
|
|
|
|
std::vector<Math::Quaternion> m_dragStartWorldRotations = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum class SceneViewportScaleGizmoHandle : std::uint8_t {
|
|
|
|
|
None = 0,
|
|
|
|
|
X,
|
|
|
|
|
Y,
|
|
|
|
|
Z,
|
|
|
|
|
Uniform
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportScaleGizmoAxisHandleDrawData {
|
|
|
|
|
SceneViewportScaleGizmoHandle handle = SceneViewportScaleGizmoHandle::None;
|
|
|
|
|
Math::Vector2 start = Math::Vector2::Zero();
|
|
|
|
|
Math::Vector2 end = Math::Vector2::Zero();
|
|
|
|
|
Math::Vector2 capCenter = Math::Vector2::Zero();
|
|
|
|
|
float capHalfSize = 0.0f;
|
|
|
|
|
Math::Color color = Math::Color::White();
|
|
|
|
|
bool visible = false;
|
|
|
|
|
bool hovered = false;
|
|
|
|
|
bool active = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportScaleGizmoCenterHandleDrawData {
|
|
|
|
|
Math::Vector2 center = Math::Vector2::Zero();
|
|
|
|
|
float halfSize = 0.0f;
|
|
|
|
|
Math::Color fillColor = Math::Color::White();
|
|
|
|
|
Math::Color outlineColor = Math::Color::White();
|
|
|
|
|
bool visible = false;
|
|
|
|
|
bool hovered = false;
|
|
|
|
|
bool active = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportScaleGizmoDrawData {
|
|
|
|
|
bool visible = false;
|
|
|
|
|
std::array<SceneViewportScaleGizmoAxisHandleDrawData, 3> axisHandles = {};
|
|
|
|
|
SceneViewportScaleGizmoCenterHandleDrawData centerHandle = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportScaleGizmoContext {
|
|
|
|
|
SceneViewportOverlayData overlay = {};
|
|
|
|
|
Math::Vector2 viewportSize = Math::Vector2::Zero();
|
|
|
|
|
Math::Vector2 mousePosition = Math::Vector2::Zero();
|
|
|
|
|
Components::GameObject* selectedObject = nullptr;
|
|
|
|
|
Math::Vector3 pivotWorldPosition = Math::Vector3::Zero();
|
|
|
|
|
Math::Quaternion axisOrientation = Math::Quaternion::Identity();
|
|
|
|
|
bool uniformOnly = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportScaleGizmoHitResult {
|
|
|
|
|
SceneViewportScaleGizmoHandle handle = SceneViewportScaleGizmoHandle::None;
|
|
|
|
|
float distanceSq = Math::FLOAT_MAX;
|
|
|
|
|
|
|
|
|
|
bool HasHit() const {
|
|
|
|
|
return handle != SceneViewportScaleGizmoHandle::None;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class SceneViewportScaleGizmo {
|
|
|
|
|
public:
|
|
|
|
|
void Update(const SceneViewportScaleGizmoContext& context);
|
|
|
|
|
bool TryBeginDrag(const SceneViewportScaleGizmoContext& context, IUndoManager& undoManager);
|
|
|
|
|
void UpdateDrag(const SceneViewportScaleGizmoContext& context);
|
|
|
|
|
void EndDrag(IUndoManager& undoManager);
|
|
|
|
|
void CancelDrag(IUndoManager* undoManager = nullptr);
|
|
|
|
|
|
|
|
|
|
bool IsHoveringHandle() const;
|
|
|
|
|
bool IsActive() const;
|
|
|
|
|
std::uint64_t GetActiveEntityId() const;
|
|
|
|
|
const SceneViewportScaleGizmoDrawData& GetDrawData() const;
|
|
|
|
|
SceneViewportScaleGizmoHitResult EvaluateHit(const Math::Vector2& mousePosition) const;
|
|
|
|
|
void SetHoveredHandle(SceneViewportScaleGizmoHandle handle);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void BuildDrawData(const SceneViewportScaleGizmoContext& context);
|
|
|
|
|
void RefreshHandleState();
|
|
|
|
|
const SceneViewportScaleGizmoAxisHandleDrawData* FindAxisHandleDrawData(
|
|
|
|
|
SceneViewportScaleGizmoHandle handle) const;
|
|
|
|
|
|
|
|
|
|
SceneViewportScaleGizmoDrawData m_drawData = {};
|
|
|
|
|
SceneViewportScaleGizmoHandle m_hoveredHandle = SceneViewportScaleGizmoHandle::None;
|
|
|
|
|
SceneViewportScaleGizmoHandle m_activeHandle = SceneViewportScaleGizmoHandle::None;
|
|
|
|
|
std::uint64_t m_activeEntityId = 0;
|
|
|
|
|
Math::Vector3 m_dragStartLocalScale = Math::Vector3::Zero();
|
|
|
|
|
Math::Vector3 m_dragCurrentVisualScale = Math::Vector3::One();
|
|
|
|
|
Math::Vector2 m_dragStartMousePosition = Math::Vector2::Zero();
|
|
|
|
|
Math::Vector2 m_activeScreenDirection = Math::Vector2::Zero();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceneViewportTransformGizmoHandleBuildInputs {
|
|
|
|
|
const SceneViewportMoveGizmoDrawData* moveGizmo = nullptr;
|
|
|
|
|
std::uint64_t moveEntityId = 0;
|
|
|
|
|
const SceneViewportRotateGizmoDrawData* rotateGizmo = nullptr;
|
|
|
|
|
std::uint64_t rotateEntityId = 0;
|
|
|
|
|
const SceneViewportScaleGizmoDrawData* scaleGizmo = nullptr;
|
|
|
|
|
std::uint64_t scaleEntityId = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
SceneViewportOverlayFrameData BuildSceneViewportTransformGizmoOverlayFrameData(
|
|
|
|
|
const SceneViewportOverlayData& overlay,
|
|
|
|
|
const SceneViewportTransformGizmoHandleBuildInputs& inputs);
|
|
|
|
|
|
2026-04-21 00:57:14 +08:00
|
|
|
} // namespace XCEngine::UI::Editor::App::SceneViewportGizmoSupport
|