Script+System: Allow native scripts from projects, decoupled from engine
This commit is contained in:
@@ -10,9 +10,10 @@
|
||||
#include "inferno/component/transformcomponent.h"
|
||||
#include "inferno/io/input.h"
|
||||
#include "inferno/keycodes.h"
|
||||
#include "inferno/script/cameracontroller.h"
|
||||
|
||||
namespace Inferno {
|
||||
#include "cameracontroller.h"
|
||||
|
||||
namespace example {
|
||||
|
||||
void CameraController::updateOrthographic(float deltaTime)
|
||||
{
|
||||
@@ -20,10 +21,10 @@ void CameraController::updateOrthographic(float deltaTime)
|
||||
|
||||
float cameraRotateSpeed = ROTATE_SPEED * deltaTime;
|
||||
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_Q"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_Q"))) {
|
||||
transform->rotate.z -= cameraRotateSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_E"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_E"))) {
|
||||
transform->rotate.z += cameraRotateSpeed;
|
||||
}
|
||||
|
||||
@@ -39,19 +40,19 @@ void CameraController::updateOrthographic(float deltaTime)
|
||||
float cameraTranslateSpeed = TRANSLATE_SPEED * deltaTime;
|
||||
|
||||
// WASD movement
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_W"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_W"))) {
|
||||
transform->translate.x += -sin(glm::radians(transform->rotate.z)) * cameraTranslateSpeed;
|
||||
transform->translate.y += cos(glm::radians(transform->rotate.z)) * cameraTranslateSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_S"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_S"))) {
|
||||
transform->translate.x -= -sin(glm::radians(transform->rotate.z)) * cameraTranslateSpeed;
|
||||
transform->translate.y -= cos(glm::radians(transform->rotate.z)) * cameraTranslateSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_A"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_A"))) {
|
||||
transform->translate.x -= cos(glm::radians(transform->rotate.z)) * cameraTranslateSpeed;
|
||||
transform->translate.y -= sin(glm::radians(transform->rotate.z)) * cameraTranslateSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_D"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_D"))) {
|
||||
transform->translate.x += cos(glm::radians(transform->rotate.z)) * cameraTranslateSpeed;
|
||||
transform->translate.y += sin(glm::radians(transform->rotate.z)) * cameraTranslateSpeed;
|
||||
}
|
||||
@@ -60,10 +61,10 @@ void CameraController::updateOrthographic(float deltaTime)
|
||||
|
||||
float zoomSpeed = ZOOM_SENSITIVITY * deltaTime;
|
||||
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_EQUAL"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_EQUAL"))) {
|
||||
m_camera->zoomLevel -= zoomSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_MINUS"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_MINUS"))) {
|
||||
m_camera->zoomLevel += zoomSpeed;
|
||||
}
|
||||
m_camera->zoomLevel = std::max(m_camera->zoomLevel, 0.25f);
|
||||
@@ -73,8 +74,8 @@ void CameraController::updateOrthographic(float deltaTime)
|
||||
void CameraController::updatePerspective(float deltaTime)
|
||||
{
|
||||
// Get mouse movement offset compared to last frame
|
||||
float xOffset = Input::getXOffset() * MOUSE_SENSITIVITY;
|
||||
float yOffset = Input::getYOffset() * MOUSE_SENSITIVITY;
|
||||
float xOffset = Inferno::Input::getXOffset() * MOUSE_SENSITIVITY;
|
||||
float yOffset = Inferno::Input::getYOffset() * MOUSE_SENSITIVITY;
|
||||
m_camera->yaw += xOffset;
|
||||
m_camera->pitch += yOffset;
|
||||
|
||||
@@ -107,24 +108,25 @@ void CameraController::updatePerspective(float deltaTime)
|
||||
float cameraSpeed = TRANSLATE_SPEED * deltaTime;
|
||||
|
||||
// WASD movement
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_W"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_W"))) {
|
||||
transform->translate += transform->rotate * cameraSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_S"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_S"))) {
|
||||
transform->translate -= transform->rotate * cameraSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_A"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_A"))) {
|
||||
transform->translate -= glm::normalize(glm::cross(transform->rotate, m_camera->up)) * cameraSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_D"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_D"))) {
|
||||
transform->translate += glm::normalize(glm::cross(transform->rotate, m_camera->up)) * cameraSpeed;
|
||||
}
|
||||
// Up / down movement
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_SPACE"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_SPACE"))) {
|
||||
transform->translate.y += cameraSpeed;
|
||||
}
|
||||
if (Input::isKeyPressed(keyCode("GLFW_KEY_LEFT_SHIFT"))) {
|
||||
if (Inferno::Input::isKeyPressed(Inferno::keyCode("GLFW_KEY_LEFT_SHIFT"))) {
|
||||
transform->translate.y -= cameraSpeed;
|
||||
}
|
||||
}
|
||||
} // namespace Inferno
|
||||
|
||||
} // namespace example
|
||||
@@ -14,20 +14,18 @@
|
||||
#define ZOOM_SENSITIVITY 2.5f
|
||||
#define MOUSE_SENSITIVITY 0.25f
|
||||
|
||||
namespace Inferno {
|
||||
namespace example {
|
||||
|
||||
struct CameraComponent;
|
||||
|
||||
class CameraController final : public NativeScript {
|
||||
class CameraController final : public Inferno::NativeScript {
|
||||
public:
|
||||
virtual void update(float deltaTime) override
|
||||
{
|
||||
m_camera = &getComponent<CameraComponent>();
|
||||
m_camera = &getComponent<Inferno::CameraComponent>();
|
||||
|
||||
if (m_camera->type == CameraType::Orthographic) {
|
||||
if (m_camera->type == Inferno::CameraType::Orthographic) {
|
||||
updateOrthographic(deltaTime);
|
||||
}
|
||||
else if (m_camera->type == CameraType::Perspective) {
|
||||
else if (m_camera->type == Inferno::CameraType::Perspective) {
|
||||
updatePerspective(deltaTime);
|
||||
}
|
||||
}
|
||||
@@ -36,7 +34,9 @@ public:
|
||||
void updatePerspective(float deltaTime);
|
||||
|
||||
private:
|
||||
CameraComponent* m_camera { nullptr };
|
||||
Inferno::CameraComponent* m_camera { nullptr };
|
||||
};
|
||||
|
||||
} // namespace Inferno
|
||||
BIND_NATIVE(CameraController);
|
||||
|
||||
} // namespace example
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ruc/meta/assert.h"
|
||||
#include <string>
|
||||
|
||||
#include "inferno/script/nativescript.h"
|
||||
|
||||
@@ -15,23 +15,15 @@ namespace Inferno {
|
||||
struct NativeScriptComponent {
|
||||
NativeScript* instance { nullptr };
|
||||
|
||||
NativeScript* (*initialize)() { nullptr };
|
||||
NativeScript::InitializeFunction initialize { nullptr };
|
||||
NativeScript::DestroyFunction destroy { nullptr };
|
||||
|
||||
// Dont allow manually setting instance during construction
|
||||
NativeScriptComponent() {}
|
||||
|
||||
template<typename T>
|
||||
void bind()
|
||||
NativeScriptComponent(const std::string& binding)
|
||||
{
|
||||
VERIFY(instance == nullptr, "NativeScript already bound");
|
||||
initialize = []() { return static_cast<NativeScript*>(new T()); };
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
VERIFY(instance, "Attempting to destroy an uninitialized NativeScript");
|
||||
delete instance;
|
||||
instance = nullptr;
|
||||
initialize = NativeScriptBinding::the().initializeBinding(binding);
|
||||
destroy = NativeScriptBinding::the().destroyBinding(binding);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "inferno/component/textareacomponent.h"
|
||||
#include "inferno/component/transformcomponent.h"
|
||||
#include "inferno/scene/scene.h"
|
||||
#include "inferno/script/cameracontroller.h"
|
||||
#include "inferno/script/nativescript.h"
|
||||
#include "inferno/system/camerasystem.h"
|
||||
#include "inferno/system/rendersystem.h"
|
||||
@@ -69,8 +68,7 @@ void Scene::initialize()
|
||||
addComponent<LuaScriptComponent>(camera, cameraScript.at("name").get<std::string>());
|
||||
}
|
||||
else {
|
||||
// TODO: Allow usage of custom camera classes
|
||||
addComponent<NativeScriptComponent>(camera).bind<CameraController>();
|
||||
addComponent<NativeScriptComponent>(camera, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ruc/meta/core.h"
|
||||
#include "ruc/singleton.h"
|
||||
|
||||
#include "inferno/scene/scene.h"
|
||||
|
||||
namespace Inferno {
|
||||
@@ -14,6 +17,9 @@ struct TransformComponent;
|
||||
|
||||
class NativeScript {
|
||||
public:
|
||||
typedef NativeScript* (*InitializeFunction)();
|
||||
typedef void (*DestroyFunction)(NativeScript*);
|
||||
|
||||
virtual ~NativeScript() {}
|
||||
|
||||
protected:
|
||||
@@ -36,4 +42,44 @@ private:
|
||||
friend class ScriptSystem;
|
||||
};
|
||||
|
||||
class NativeScriptBinding final : public ruc::Singleton<NativeScriptBinding> {
|
||||
public:
|
||||
NativeScriptBinding(s) {}
|
||||
virtual ~NativeScriptBinding() {}
|
||||
|
||||
void registerBinding(const std::string& binding,
|
||||
NativeScript::InitializeFunction initialize,
|
||||
NativeScript::DestroyFunction destroy)
|
||||
{
|
||||
m_initializeBindings.emplace(binding, initialize);
|
||||
m_detroyBindings.emplace(binding, destroy);
|
||||
}
|
||||
|
||||
NativeScript::InitializeFunction initializeBinding(const std::string& binding) { return m_initializeBindings[binding]; }
|
||||
NativeScript::DestroyFunction destroyBinding(const std::string& binding) { return m_detroyBindings[binding]; }
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, NativeScript::InitializeFunction> m_initializeBindings;
|
||||
std::unordered_map<std::string, NativeScript::DestroyFunction> m_detroyBindings;
|
||||
};
|
||||
|
||||
} // namespace Inferno
|
||||
|
||||
#define BIND_NATIVE_IMPL(name, struct_name) \
|
||||
struct struct_name { \
|
||||
struct_name() \
|
||||
{ \
|
||||
Inferno::NativeScriptBinding::the().registerBinding( \
|
||||
#name, \
|
||||
[]() -> Inferno::NativeScript* { return static_cast<Inferno::NativeScript*>(new name()); }, \
|
||||
[](Inferno::NativeScript* nativeScript) -> void { \
|
||||
VERIFY(nativeScript, "Attempting to destroy an uninitialized NativeScript"); \
|
||||
delete static_cast<name*>(nativeScript); \
|
||||
nativeScript = nullptr; \
|
||||
}); \
|
||||
} \
|
||||
}; \
|
||||
static struct struct_name struct_name; // NOLINT(clang-diagnostic-unused-function)
|
||||
|
||||
#define BIND_NATIVE(name) \
|
||||
BIND_NATIVE_IMPL(name, CONCAT(__BIND_NATIVE_FUNCTION_, __COUNTER__))
|
||||
|
||||
@@ -92,7 +92,7 @@ void ScriptSystem::cleanup(NativeScriptComponent& nativeScript)
|
||||
{
|
||||
if (nativeScript.instance) {
|
||||
nativeScript.instance->destroy();
|
||||
nativeScript.destroy();
|
||||
nativeScript.destroy(nativeScript.instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user