Files
XCEngine/editor/src/ComponentEditors/TransformComponentEditor.h

106 lines
3.4 KiB
C++

#pragma once
#include "IComponentEditor.h"
#include "Core/IUndoManager.h"
#include "UI/UI.h"
#include <XCEngine/Components/TransformComponent.h>
#include <cmath>
#include <unordered_map>
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