diff --git a/src/inferno/script/cameracontroller.cpp b/example/src/cameracontroller.cpp similarity index 74% rename from src/inferno/script/cameracontroller.cpp rename to example/src/cameracontroller.cpp index ec4281d..a1f2a77 100644 --- a/src/inferno/script/cameracontroller.cpp +++ b/example/src/cameracontroller.cpp @@ -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 diff --git a/src/inferno/script/cameracontroller.h b/example/src/cameracontroller.h similarity index 59% rename from src/inferno/script/cameracontroller.h rename to example/src/cameracontroller.h index 4b9ba28..8965a57 100644 --- a/src/inferno/script/cameracontroller.h +++ b/example/src/cameracontroller.h @@ -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(); + m_camera = &getComponent(); - 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 diff --git a/src/inferno/component/nativescriptcomponent.h b/src/inferno/component/nativescriptcomponent.h index 74ef6de..47becb9 100644 --- a/src/inferno/component/nativescriptcomponent.h +++ b/src/inferno/component/nativescriptcomponent.h @@ -6,7 +6,7 @@ #pragma once -#include "ruc/meta/assert.h" +#include #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 - void bind() - { - VERIFY(instance == nullptr, "NativeScript already bound"); - initialize = []() { return static_cast(new T()); }; - } - - void destroy() + NativeScriptComponent(const std::string& binding) { - VERIFY(instance, "Attempting to destroy an uninitialized NativeScript"); - delete instance; - instance = nullptr; + initialize = NativeScriptBinding::the().initializeBinding(binding); + destroy = NativeScriptBinding::the().destroyBinding(binding); } }; diff --git a/src/inferno/scene/scene.cpp b/src/inferno/scene/scene.cpp index b227ff9..6e67240 100644 --- a/src/inferno/scene/scene.cpp +++ b/src/inferno/scene/scene.cpp @@ -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(camera, cameraScript.at("name").get()); } else { - // TODO: Allow usage of custom camera classes - addComponent(camera).bind(); + addComponent(camera, name); } } } diff --git a/src/inferno/script/nativescript.h b/src/inferno/script/nativescript.h index b39ffaf..f89d54f 100644 --- a/src/inferno/script/nativescript.h +++ b/src/inferno/script/nativescript.h @@ -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 { +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 m_initializeBindings; + std::unordered_map 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(new name()); }, \ + [](Inferno::NativeScript* nativeScript) -> void { \ + VERIFY(nativeScript, "Attempting to destroy an uninitialized NativeScript"); \ + delete static_cast(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__)) diff --git a/src/inferno/system/scriptsystem.cpp b/src/inferno/system/scriptsystem.cpp index 0b08e77..6fdade0 100644 --- a/src/inferno/system/scriptsystem.cpp +++ b/src/inferno/system/scriptsystem.cpp @@ -92,7 +92,7 @@ void ScriptSystem::cleanup(NativeScriptComponent& nativeScript) { if (nativeScript.instance) { nativeScript.instance->destroy(); - nativeScript.destroy(); + nativeScript.destroy(nativeScript.instance); } }