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