Files
XCEngine/editor/src/Viewport/SceneViewportMoveGizmo.h

130 lines
4.1 KiB
C++

#pragma once
#include "IViewportHostService.h"
#include <XCEngine/Core/Math/Color.h>
#include <XCEngine/Core/Math/Plane.h>
#include <XCEngine/Core/Math/Quaternion.h>
#include <XCEngine/Core/Math/Vector2.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <array>
#include <cstdint>
#include <vector>
namespace XCEngine {
namespace Components {
class GameObject;
} // namespace Components
namespace Editor {
class IUndoManager;
enum class SceneViewportGizmoAxis : uint8_t {
None = 0,
X,
Y,
Z
};
enum class SceneViewportGizmoPlane : 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;
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 : 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;
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 = {};
};
} // namespace Editor
} // namespace XCEngine