diff --git a/include/parser/Parser.hpp b/include/parser/Parser.hpp index a6f509e..d19fb98 100644 --- a/include/parser/Parser.hpp +++ b/include/parser/Parser.hpp @@ -5,8 +5,14 @@ #include #include -#include "neuronide.pb.h" -#include "scene/SceneAll.hpp" +class Scene; +class SceneObject; +class Component; + +namespace NeuronIDE { +class SceneObject; +class Component; +} // namespace NeuronIDE class Parser { public: diff --git a/include/scene/Scene.hpp b/include/scene/Scene.hpp index 8aeee55..77c6be5 100644 --- a/include/scene/Scene.hpp +++ b/include/scene/Scene.hpp @@ -5,7 +5,7 @@ #include #include -#include "SceneObject.hpp" +class SceneObject; class Scene { private: diff --git a/include/scene/SceneAll.hpp b/include/scene/SceneAll.hpp deleted file mode 100644 index 058318b..0000000 --- a/include/scene/SceneAll.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SCENE_ALL_HPP -#define SCENE_ALL_HPP - -// 1. Główne struktury danych sceny -#include "Scene.hpp" -#include "SceneObject.hpp" - -// 2. Interfejs komponentu -#include "components/Component.hpp" - -// 3. Wszystkie konkretne komponenty -#include "components/BlinkComponent.hpp" - -#endif // SCENE_ALL_HPP \ No newline at end of file diff --git a/include/scene/SceneObject.hpp b/include/scene/SceneObject.hpp index 20c5424..bf6ef92 100644 --- a/include/scene/SceneObject.hpp +++ b/include/scene/SceneObject.hpp @@ -6,7 +6,7 @@ #include #include -#include "components/Component.hpp" +class Component; class SceneObject { public: @@ -19,15 +19,11 @@ class SceneObject { std::vector> components; - SceneObject(std::string n, bool visible = true) : name(std::move(n)), isVisible(visible) { - std::cout << " [SceneObject] Utworzono obiekt: " << name << "\n"; - } + SceneObject(std::string n, bool visible = true); - void setTransform(double posX, double posY, double width, double height, double rotation) { - transform = {posX, posY, width, height, rotation}; - } + void setTransform(Transform t); - void addComponent(std::unique_ptr comp) { components.push_back(std::move(comp)); } + void addComponent(std::unique_ptr comp); }; #endif // SCENEOBJECT_HPP \ No newline at end of file diff --git a/include/scene/components/BlinkComponent.hpp b/include/scene/components/BlinkComponent.hpp index 0964343..59816b2 100644 --- a/include/scene/components/BlinkComponent.hpp +++ b/include/scene/components/BlinkComponent.hpp @@ -2,16 +2,23 @@ #define BLINKCOMPONENT_HPP #include +#include #include "Component.hpp" +namespace NeuronIDE { +class Component; +} + class BlinkComponent : public Component { public: BlinkComponent(double freq) : blinkFrequencyHz(freq) { std::cout << " + [BlinkComponent] Utworzono z czestotliwoscia: " << blinkFrequencyHz << "Hz\n"; } - void setFrequency(double freq) { blinkFrequencyHz = freq; } + void setFrequency(double freq); + + static std::unique_ptr createBlinker(const NeuronIDE::Component& protoComp); private: double blinkFrequencyHz = 0.0; diff --git a/include/scene/components/ComponentRegistry.hpp b/include/scene/components/ComponentRegistry.hpp new file mode 100644 index 0000000..d6ac0fe --- /dev/null +++ b/include/scene/components/ComponentRegistry.hpp @@ -0,0 +1,52 @@ +#ifndef COMPONENTREGISTRY_HPP +#define COMPONENTREGISTRY_HPP + +#include +#include +#include + +class Component; +namespace NeuronIDE { +class Component; +} + +using ComponentCreatorFunc = std::function(const NeuronIDE::Component&)>; + +class ComponentRegistry { + public: + ComponentRegistry(const ComponentRegistry&) = delete; + ComponentRegistry& operator=(const ComponentRegistry&) = delete; + + ComponentRegistry(ComponentRegistry&&) = delete; + ComponentRegistry& operator=(ComponentRegistry&&) = delete; + + static ComponentRegistry& instance() { + static ComponentRegistry instance; + return instance; + } + + void registerCreator(int typeId, ComponentCreatorFunc creator); + + std::unique_ptr build(const NeuronIDE::Component& protoComp); + + private: + ComponentRegistry() = default; + + std::unordered_map creators; +}; + +#define COMPONENT_REGISTRATION_CONCAT_IMPL(x, y) x##y +#define COMPONENT_REGISTRATION_CONCAT(x, y) COMPONENT_REGISTRATION_CONCAT_IMPL(x, y) + +#define REGISTER_COMPONENT(typeId, creatorFunc) \ + namespace { \ + struct COMPONENT_REGISTRATION_CONCAT(ComponentRegistrar_, __LINE__) { \ + COMPONENT_REGISTRATION_CONCAT(ComponentRegistrar_, __LINE__)() { \ + ComponentRegistry::instance().registerCreator(static_cast(typeId), creatorFunc);\ + } \ + }; \ + static COMPONENT_REGISTRATION_CONCAT(ComponentRegistrar_, __LINE__) \ + COMPONENT_REGISTRATION_CONCAT(global_registrar_, __LINE__); \ + } + +#endif // COMPONENTREGISTRY_HPP \ No newline at end of file diff --git a/protoFiles/tests/test_scene.pb b/protoFiles/tests/test_scene.pb index 73e8e4e..ed6cd4c 100644 Binary files a/protoFiles/tests/test_scene.pb and b/protoFiles/tests/test_scene.pb differ diff --git a/protoFiles/tests/test_scene.pbtxt b/protoFiles/tests/test_scene.pbtxt index 84ab0ed..e2781cf 100644 --- a/protoFiles/tests/test_scene.pbtxt +++ b/protoFiles/tests/test_scene.pbtxt @@ -17,12 +17,6 @@ scene_objects { blink_frequency_hz: 1.5 } } - - components { - blinker { - blink_frequency_hz: 3 - } - } } scene_objects { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 81c6b44..ced725f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,11 @@ protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/../protoFiles/neuronide.proto) -add_library(runtime_core +add_library(runtime_core OBJECT Runtime.cpp - parser/Parser.cpp + parser/Parser.cpp + scene/components/ComponentRegistry.cpp + scene/components/BlinkComponent.cpp + scene/SceneObject.cpp ${PROTO_SRCS} ${PROTO_HDRS} ) diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp index bd7a77d..79de0bc 100644 --- a/src/parser/Parser.cpp +++ b/src/parser/Parser.cpp @@ -1,14 +1,16 @@ #include "parser/Parser.hpp" -#include // dla .pbtxt jeśli będzie potrzeba - #include #include +#include #include "neuronide.pb.h" -#include "scene/SceneAll.hpp" +#include "scene/Scene.hpp" +#include "scene/SceneObject.hpp" +#include "scene/components/Component.hpp" +#include "scene/components/ComponentRegistry.hpp" -std::shared_ptr<::Scene> Parser::parse(const std::string& filePath) { +std::shared_ptr Parser::parse(const std::string& filePath) { NeuronIDE::Scene protoScene; std::ifstream file(filePath, std::ios::binary); @@ -36,10 +38,20 @@ std::shared_ptr Parser::buildSceneObject(const NeuronIDE::SceneObje if (protoObj.has_transform()) { const auto& tra = protoObj.transform(); - obj->setTransform(tra.x(), tra.y(), tra.width(), tra.height(), tra.rotation()); + obj->setTransform({tra.x(), tra.y(), tra.width(), tra.height(), tra.rotation()}); } + std::unordered_set seenComponentTypes; + for (const auto& protoComp : protoObj.components()) { + int typeId = static_cast(protoComp.component_type_case()); + + if (seenComponentTypes.find(typeId) != seenComponentTypes.end()) { + throw std::runtime_error("Parser: duplicate component type in object '" + + protoObj.name() + "'."); + } + seenComponentTypes.insert(typeId); + auto comp = buildComponent(protoComp); if (comp) { obj->addComponent(std::move(comp)); @@ -50,31 +62,5 @@ std::shared_ptr Parser::buildSceneObject(const NeuronIDE::SceneObje } std::unique_ptr Parser::buildComponent(const NeuronIDE::Component& protoComp) { - using CT = NeuronIDE::Component::ComponentTypeCase; - - switch (protoComp.component_type_case()) { - // case CT::kRenderer: { - // const auto& ren = protoComp.renderer(); - // return std::make_unique(ren.texture_path(), ren.img_path()); - // } - - // case CT::kText: { - // const auto& txt = protoComp.text(); - // return std::make_unique(txt.text(), txt.font_path(), - // txt.font_size()); - // } - - case CT::kBlinker: { - const auto& bli = protoComp.blinker(); - return std::make_unique(bli.blink_frequency_hz()); - } - - // case CT::kScript: { - // const auto& scr = protoComp.script(); - // return std::make_unique(scr.script_path()); - // } - - default: - return nullptr; - } + return ComponentRegistry::instance().build(protoComp); } \ No newline at end of file diff --git a/src/scene/SceneObject.cpp b/src/scene/SceneObject.cpp new file mode 100644 index 0000000..06d7dae --- /dev/null +++ b/src/scene/SceneObject.cpp @@ -0,0 +1,15 @@ +#include "scene/SceneObject.hpp" + +#include + +#include "scene/components/Component.hpp" + +SceneObject::SceneObject(std::string n, bool visible) : name(std::move(n)), isVisible(visible) { + std::cout << " [SceneObject] Utworzono obiekt: " << name << "\n"; +} + +void SceneObject::setTransform(Transform t) { transform = t; } + +void SceneObject::addComponent(std::unique_ptr comp) { + components.push_back(std::move(comp)); +} \ No newline at end of file diff --git a/src/scene/components/BlinkComponent.cpp b/src/scene/components/BlinkComponent.cpp new file mode 100644 index 0000000..3830efa --- /dev/null +++ b/src/scene/components/BlinkComponent.cpp @@ -0,0 +1,12 @@ +#include "scene/components/BlinkComponent.hpp" + +#include "neuronide.pb.h" +#include "scene/components/ComponentRegistry.hpp" + +void BlinkComponent::setFrequency(double freq) { blinkFrequencyHz = freq; } + +std::unique_ptr BlinkComponent::createBlinker(const NeuronIDE::Component& protoComp) { + return std::make_unique(protoComp.blinker().blink_frequency_hz()); +} + +REGISTER_COMPONENT(NeuronIDE::Component::kBlinker, BlinkComponent::createBlinker) \ No newline at end of file diff --git a/src/scene/components/ComponentRegistry.cpp b/src/scene/components/ComponentRegistry.cpp new file mode 100644 index 0000000..52faf24 --- /dev/null +++ b/src/scene/components/ComponentRegistry.cpp @@ -0,0 +1,27 @@ +#include "scene/components/ComponentRegistry.hpp" + +#include +#include + +#include "neuronide.pb.h" +#include "scene/components/Component.hpp" + +void ComponentRegistry::registerCreator(int typeId, ComponentCreatorFunc creator) { + if (creators.find(typeId) != creators.end()) { + throw std::runtime_error("Creator for this typeId is already registered."); + } + creators[typeId] = std::move(creator); +} + +std::unique_ptr ComponentRegistry::build(const NeuronIDE::Component& protoComp) { + auto activeCase = protoComp.component_type_case(); + + int typeId = static_cast(activeCase); + + auto it = creators.find(typeId); + if (it != creators.end()) { + return it->second(protoComp); + } + + return nullptr; +} \ No newline at end of file