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

110 lines
3.6 KiB
C++

#pragma once
#include "IViewportHostService.h"
#include <XCEngine/Core/Math/Color.h>
#include <XCEngine/Core/Math/Quaternion.h>
#include <XCEngine/Core/Math/Vector2.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <array>
#include <cstdint>
namespace XCEngine {
namespace Components {
class GameObject;
} // namespace Components
namespace Editor {
class IUndoManager;
enum class SceneViewportScaleGizmoHandle : 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;
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;
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();
};
} // namespace Editor
} // namespace XCEngine