Add EditorCameraComponent and EditorCameraSystem
This commit is contained in:
parent
64171da71a
commit
13a50a87dd
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <NazaraEditor/Core/Core.hpp>
|
||||||
|
|
||||||
|
#include <Nazara/Platform/WindowEventHandler.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class NodeComponent;
|
||||||
|
class WindowEventHandler;
|
||||||
|
|
||||||
|
class NAZARAEDITOR_CORE_API EditorCameraComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EditorCameraComponent();
|
||||||
|
EditorCameraComponent(const EditorCameraComponent&) = delete;
|
||||||
|
|
||||||
|
EditorCameraComponent(EditorCameraComponent&&);
|
||||||
|
~EditorCameraComponent();
|
||||||
|
|
||||||
|
void Update(Time elapsedTime, NodeComponent& node);
|
||||||
|
|
||||||
|
inline void SetPosition(const Nz::Vector3f& position) { m_targetPosition = position; }
|
||||||
|
inline void SetRotation(const Nz::Quaternionf& rotation) { m_targetAngles = rotation.ToEulerAngles(); }
|
||||||
|
|
||||||
|
inline const Nz::Vector3f& GetPosition() const { return m_targetPosition; }
|
||||||
|
inline const Nz::EulerAnglesf& GetOrientation() const { return m_targetAngles; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, m_onMouseMoved);
|
||||||
|
|
||||||
|
Nz::EulerAnglesf m_targetAngles;
|
||||||
|
Nz::Vector3f m_targetPosition;
|
||||||
|
Nz::Vector3f m_currentVelocity;
|
||||||
|
|
||||||
|
float m_moveSpeed;
|
||||||
|
float m_smoothSpeed;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <NazaraEditor/Core/Core.hpp>
|
||||||
|
|
||||||
|
#include <entt/entt.hpp>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class NAZARAEDITOR_CORE_API EditorCameraSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr bool AllowConcurrent = false;
|
||||||
|
static constexpr Int64 ExecutionOrder = 1'001;
|
||||||
|
|
||||||
|
EditorCameraSystem(entt::registry& registry);
|
||||||
|
~EditorCameraSystem();
|
||||||
|
|
||||||
|
EditorCameraSystem(const EditorCameraSystem&) = delete;
|
||||||
|
EditorCameraSystem& operator=(const EditorCameraSystem&) = delete;
|
||||||
|
|
||||||
|
EditorCameraSystem(EditorCameraSystem&&) = delete;
|
||||||
|
EditorCameraSystem& operator=(EditorCameraSystem&&) = delete;
|
||||||
|
|
||||||
|
void Update(Time elapsedTime);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnCameraDestroy(entt::registry& registry, entt::entity entity);
|
||||||
|
|
||||||
|
entt::registry& m_registry;
|
||||||
|
|
||||||
|
entt::observer m_cameraConstructObserver;
|
||||||
|
entt::scoped_connection m_cameraDestroyConnection;
|
||||||
|
|
||||||
|
std::unordered_set<entt::entity> m_cameraEntities;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include <NazaraEditor/Core/Components/CameraComponent.hpp>
|
||||||
|
|
||||||
|
#include <NazaraEditor/Core/Application/BaseApplication.hpp>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// Unity SmoothDamp function
|
||||||
|
template <typename T>
|
||||||
|
T SmoothDamp(T current, T target, T& currentVelocity, float smoothTime, Nz::Time deltaTime)
|
||||||
|
{
|
||||||
|
if (current.SquaredDistance(target) < 0.0001f)
|
||||||
|
return target;
|
||||||
|
|
||||||
|
// Based on Game Programming Gems 4 Chapter 1.10
|
||||||
|
smoothTime = std::max(0.0001f, smoothTime);
|
||||||
|
float omega = 2.f / smoothTime;
|
||||||
|
|
||||||
|
float x = omega * deltaTime.AsSeconds();
|
||||||
|
float exp = 1.f / (1.f + x + 0.48f * x * x + 0.235f * x * x * x);
|
||||||
|
T change = current - target;
|
||||||
|
T originalTo = target;
|
||||||
|
|
||||||
|
// Clamp maximum speed
|
||||||
|
float maxChange = smoothTime;
|
||||||
|
float dist = change.GetLength();
|
||||||
|
dist = Nz::Clamp(dist, -maxChange, maxChange);
|
||||||
|
target = current - change.Normalize() * dist;
|
||||||
|
|
||||||
|
T temp = (currentVelocity + omega * change) * deltaTime.AsSeconds();
|
||||||
|
currentVelocity = (currentVelocity - omega * temp) * exp;
|
||||||
|
T output = target + (change + temp) * exp;
|
||||||
|
|
||||||
|
// Prevent overshooting
|
||||||
|
if (current.SquaredDistance(target) <= current.SquaredDistance(output))
|
||||||
|
{
|
||||||
|
output = originalTo;
|
||||||
|
currentVelocity = (output - originalTo) / deltaTime.AsSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
EditorCameraComponent::EditorCameraComponent()
|
||||||
|
: m_moveSpeed(3.f)
|
||||||
|
, m_smoothSpeed(0.3f)
|
||||||
|
{
|
||||||
|
auto& handler = EditorBaseApplication::Instance()->GetWindow()->GetEventHandler();
|
||||||
|
|
||||||
|
m_onMouseMoved.Connect(handler.OnMouseMoved, [&](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event)
|
||||||
|
{
|
||||||
|
// Gestion de la caméra free-fly (Rotation)
|
||||||
|
float sensitivity = 0.3f; // Sensibilité de la souris
|
||||||
|
|
||||||
|
// On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris
|
||||||
|
m_targetAngles.yaw = m_targetAngles.yaw - event.deltaX * sensitivity;
|
||||||
|
m_targetAngles.yaw.Normalize();
|
||||||
|
|
||||||
|
// Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles
|
||||||
|
m_targetAngles.pitch = Nz::Clamp(m_targetAngles.pitch - event.deltaY * sensitivity, -89.f, 89.f);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorCameraComponent::~EditorCameraComponent()
|
||||||
|
{
|
||||||
|
m_onMouseMoved.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorCameraComponent::Update(Time elapsedTime, NodeComponent& node)
|
||||||
|
{
|
||||||
|
// todo use action mapping
|
||||||
|
Nz::Vector3f delta;
|
||||||
|
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::W))
|
||||||
|
delta += Nz::Vector3f::Forward();
|
||||||
|
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::S))
|
||||||
|
delta += Nz::Vector3f::Backward();
|
||||||
|
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::A))
|
||||||
|
delta += Nz::Vector3f::Left();
|
||||||
|
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D))
|
||||||
|
delta += Nz::Vector3f::Right();
|
||||||
|
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Q))
|
||||||
|
delta += Nz::Vector3f::Up();
|
||||||
|
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::E))
|
||||||
|
delta += Nz::Vector3f::Down();
|
||||||
|
|
||||||
|
auto currentRotation = m_targetAngles.ToQuaternion();
|
||||||
|
m_targetPosition += (currentRotation * delta) * elapsedTime.AsSeconds() * m_moveSpeed;
|
||||||
|
|
||||||
|
auto currentPosition = SmoothDamp(node.GetPosition(), m_targetPosition, m_currentVelocity, m_smoothSpeed, elapsedTime);
|
||||||
|
node.SetPosition(currentPosition);
|
||||||
|
node.SetRotation(currentRotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include <NazaraEditor/Core/Systems/CameraSystem.hpp>
|
||||||
|
#include <NazaraEditor/Core/Components/CameraComponent.hpp>
|
||||||
|
|
||||||
|
#include <Nazara/Utility/Components/NodeComponent.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
EditorCameraSystem::EditorCameraSystem(entt::registry& registry)
|
||||||
|
: m_registry(registry)
|
||||||
|
, m_cameraConstructObserver(registry, entt::collector.group<EditorCameraComponent, NodeComponent>())
|
||||||
|
{
|
||||||
|
m_cameraDestroyConnection = registry.on_destroy<EditorCameraComponent>().connect<&EditorCameraSystem::OnCameraDestroy>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorCameraSystem::~EditorCameraSystem()
|
||||||
|
{
|
||||||
|
m_cameraConstructObserver.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorCameraSystem::Update(Time elapsedTime)
|
||||||
|
{
|
||||||
|
m_cameraConstructObserver.each([&](entt::entity entity) {
|
||||||
|
m_cameraEntities.insert(entity);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (auto entity : m_cameraEntities)
|
||||||
|
{
|
||||||
|
EditorCameraComponent& camera = m_registry.get<EditorCameraComponent>(entity);
|
||||||
|
NodeComponent& transform = m_registry.get<NodeComponent>(entity);
|
||||||
|
|
||||||
|
camera.Update(elapsedTime, transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorCameraSystem::OnCameraDestroy(entt::registry& registry, entt::entity entity)
|
||||||
|
{
|
||||||
|
m_cameraEntities.erase(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue