#pragma once #include "IComponentEditor.h" #include "Core/IUndoManager.h" #include "UI/UI.h" #include #include #include namespace XCEngine { namespace Editor { class TransformComponentEditor : public IComponentEditor { public: const char* GetComponentTypeName() const override { return "Transform"; } const char* GetDisplayName() const override { return "Transform"; } bool Render(::XCEngine::Components::Component* component, IUndoManager* undoManager) override { auto* transform = dynamic_cast<::XCEngine::Components::TransformComponent*>(component); if (!transform) { return false; } constexpr const char* kUndoLabel = "Modify Transform"; RotationEditState& rotationState = m_rotationStates[transform]; ::XCEngine::Math::Vector3 position = transform->GetLocalPosition(); ::XCEngine::Math::Vector3 scale = transform->GetLocalScale(); const ::XCEngine::Math::Quaternion currentRotation = transform->GetLocalRotation(); if (!rotationState.initialized || (!rotationState.isEditing && !SameRotation(currentRotation, rotationState.lastRotation))) { rotationState.displayedEuler = transform->GetLocalEulerAngles(); rotationState.lastRotation = currentRotation; rotationState.initialized = true; } bool changed = false; changed |= UI::ApplyPropertyChange( UI::DrawPropertyVec3Input("Position", position, 0.1f), undoManager, kUndoLabel, [&]() { transform->SetLocalPosition(position); }); bool rotationActive = false; changed |= UI::ApplyPropertyChange( UI::DrawPropertyVec3Input("Rotation", rotationState.displayedEuler, 1.0f, &rotationActive), undoManager, kUndoLabel, [&]() { transform->SetLocalEulerAngles(rotationState.displayedEuler); rotationState.lastRotation = transform->GetLocalRotation(); }); rotationState.isEditing = rotationActive; changed |= UI::ApplyPropertyChange( UI::DrawPropertyVec3Input("Scale", scale, 0.1f), undoManager, kUndoLabel, [&]() { transform->SetLocalScale(scale); }); return changed; } bool CanAddTo(::XCEngine::Components::GameObject* gameObject) const override { (void)gameObject; return false; } const char* GetAddDisabledReason(::XCEngine::Components::GameObject* gameObject) const override { (void)gameObject; return "Built-in"; } bool CanRemove(::XCEngine::Components::Component* component) const override { (void)component; return false; } private: struct RotationEditState { ::XCEngine::Math::Vector3 displayedEuler = ::XCEngine::Math::Vector3::Zero(); ::XCEngine::Math::Quaternion lastRotation = ::XCEngine::Math::Quaternion::Identity(); bool initialized = false; bool isEditing = false; }; static bool SameRotation(const ::XCEngine::Math::Quaternion& a, const ::XCEngine::Math::Quaternion& b) { return std::abs(a.Dot(b)) > 0.9999f; } std::unordered_map<::XCEngine::Components::TransformComponent*, RotationEditState> m_rotationStates; }; } // namespace Editor } // namespace XCEngine