diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d1028c..6806370 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y cmake clang-format clang-tidy libsdl2-dev + sudo apt-get install -y cmake clang-format clang-tidy libsdl2-dev protobuf-compiler - name: Check Code Formatting run: | diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index 0c2b475..bce5c33 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -28,4 +28,7 @@ FetchContent_Declare( FetchContent_MakeAvailable(concurrentqueue) # 4. SDL2 (System installed) -find_package(SDL2 REQUIRED) \ No newline at end of file +find_package(SDL2 REQUIRED) + +# 5. Protobuf (System installed) +find_package(Protobuf REQUIRED) diff --git a/include/parser/Parser.hpp b/include/parser/Parser.hpp new file mode 100644 index 0000000..a6f509e --- /dev/null +++ b/include/parser/Parser.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_HPP +#define PARSER_HPP + +#include +#include +#include + +#include "neuronide.pb.h" +#include "scene/SceneAll.hpp" + +class Parser { + public: + Parser() = default; + + std::shared_ptr parse(const std::string& filePath); + + private: + static std::shared_ptr buildSceneObject(const NeuronIDE::SceneObject& protoObj); + static std::unique_ptr buildComponent(const NeuronIDE::Component& protoComp); +}; + +#endif // PARSER_HPP \ No newline at end of file diff --git a/include/scene/Scene.hpp b/include/scene/Scene.hpp new file mode 100644 index 0000000..8aeee55 --- /dev/null +++ b/include/scene/Scene.hpp @@ -0,0 +1,24 @@ +#ifndef SCENE_HPP +#define SCENE_HPP + +#include +#include +#include + +#include "SceneObject.hpp" + +class Scene { + private: + std::string experimentName; + std::vector> objects; + + public: + void setExperimentName(const std::string& name) { experimentName = name; } + + void addObject(std::shared_ptr obj) { objects.push_back(std::move(obj)); } + + const std::string& getExperimentName() const { return experimentName; } + const std::vector>& getObjects() const { return objects; } +}; + +#endif // SCENE_HPP \ No newline at end of file diff --git a/include/scene/SceneAll.hpp b/include/scene/SceneAll.hpp new file mode 100644 index 0000000..058318b --- /dev/null +++ b/include/scene/SceneAll.hpp @@ -0,0 +1,14 @@ +#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 new file mode 100644 index 0000000..20c5424 --- /dev/null +++ b/include/scene/SceneObject.hpp @@ -0,0 +1,33 @@ +#ifndef SCENEOBJECT_HPP +#define SCENEOBJECT_HPP + +#include +#include +#include +#include + +#include "components/Component.hpp" + +class SceneObject { + public: + std::string name; + bool isVisible = true; + + struct Transform { + double posX = 0, posY = 0, width = 0, height = 0, rotation = 0; + } transform; + + std::vector> components; + + SceneObject(std::string n, bool visible = true) : name(std::move(n)), isVisible(visible) { + std::cout << " [SceneObject] Utworzono obiekt: " << name << "\n"; + } + + void setTransform(double posX, double posY, double width, double height, double rotation) { + transform = {posX, posY, width, height, rotation}; + } + + void addComponent(std::unique_ptr comp) { components.push_back(std::move(comp)); } +}; + +#endif // SCENEOBJECT_HPP \ No newline at end of file diff --git a/include/scene/components/BlinkComponent.hpp b/include/scene/components/BlinkComponent.hpp new file mode 100644 index 0000000..0964343 --- /dev/null +++ b/include/scene/components/BlinkComponent.hpp @@ -0,0 +1,20 @@ +#ifndef BLINKCOMPONENT_HPP +#define BLINKCOMPONENT_HPP + +#include + +#include "Component.hpp" + +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; } + + private: + double blinkFrequencyHz = 0.0; +}; + +#endif // BLINKCOMPONENT_HPP \ No newline at end of file diff --git a/include/scene/components/Component.hpp b/include/scene/components/Component.hpp new file mode 100644 index 0000000..1b15b63 --- /dev/null +++ b/include/scene/components/Component.hpp @@ -0,0 +1,15 @@ +#ifndef COMPONENT_HPP +#define COMPONENT_HPP + +class Component { + public: + Component() = default; + virtual ~Component() = default; + + Component(const Component&) = default; + Component(Component&&) = default; + Component& operator=(const Component&) = default; + Component& operator=(Component&&) = default; +}; + +#endif // COMPONENT_HPP \ No newline at end of file diff --git a/protoFiles/neuronide.proto b/protoFiles/neuronide.proto new file mode 100644 index 0000000..24e15a3 --- /dev/null +++ b/protoFiles/neuronide.proto @@ -0,0 +1,51 @@ +syntax = "proto3"; + +package NeuronIDE; + +message SpriteRenderer { + string texture_path = 1; + string img_path = 2; +} + +message TextRenderer { + string text = 1; + string font_path = 2; + uint32 font_size = 3; +} + +message BlinkComponent { + double blink_frequency_hz = 1; +} + +message ScriptComponent { + string script_path = 1; +} + +message Transform { + double x = 1; + double y = 2; + double width = 3; + double height = 4; + double rotation = 5; +} + +message Component { + oneof component_type { + SpriteRenderer renderer = 1; + TextRenderer text = 2; + BlinkComponent blinker = 3; + ScriptComponent script = 4; + } +} + +message SceneObject { + string name = 1; + bool is_visible = 2; + Transform transform = 3; + repeated Component components = 4; +} + +message Scene { + string project_name = 1; + repeated SceneObject scene_objects = 2; +} \ No newline at end of file diff --git a/protoFiles/tests/test_scene.pb b/protoFiles/tests/test_scene.pb new file mode 100644 index 0000000..73e8e4e Binary files /dev/null and b/protoFiles/tests/test_scene.pb differ diff --git a/protoFiles/tests/test_scene.pbtxt b/protoFiles/tests/test_scene.pbtxt new file mode 100644 index 0000000..84ab0ed --- /dev/null +++ b/protoFiles/tests/test_scene.pbtxt @@ -0,0 +1,45 @@ +project_name: "Moj Pierwszy Eksperyment" + +scene_objects { + name: "Gracz" + is_visible: true + + transform { + x: 100.0 + y: 200.0 + width: 64.0 + height: 64.0 + rotation: 0.0 + } + + components { + blinker { + blink_frequency_hz: 1.5 + } + } + + components { + blinker { + blink_frequency_hz: 3 + } + } +} + +scene_objects { + name: "Napis Powitalny" + is_visible: true + + transform { + x: 400.0 + y: 50.0 + width: 300.0 + height: 100.0 + rotation: 0.0 + } + + components { + blinker { + blink_frequency_hz: 5 + } + } +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 854e2c8..81c6b44 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,12 +1,24 @@ -add_library(runtime_core Runtime.cpp) -target_include_directories(runtime_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) +protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/../protoFiles/neuronide.proto) -target_link_libraries(runtime_core PUBLIC +add_library(runtime_core + Runtime.cpp + parser/Parser.cpp + ${PROTO_SRCS} + ${PROTO_HDRS} +) + +target_include_directories(runtime_core SYSTEM PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../include + ${CMAKE_CURRENT_BINARY_DIR} + ${SDL2_INCLUDE_DIRS} +) + +target_link_libraries(runtime_core PUBLIC lsl concurrentqueue + protobuf::libprotobuf ${SDL2_LIBRARIES} ) -target_include_directories(runtime_core PUBLIC ${SDL2_INCLUDE_DIRS}) add_executable(NeuronIDE main.cpp) target_link_libraries(NeuronIDE PRIVATE runtime_core) \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1ddb7e1..1b85885 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,4 @@ #include -#include int main(int argc, char* argv[]) { Runtime::start(); diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp new file mode 100644 index 0000000..bd7a77d --- /dev/null +++ b/src/parser/Parser.cpp @@ -0,0 +1,80 @@ +#include "parser/Parser.hpp" + +#include // dla .pbtxt jeśli będzie potrzeba + +#include +#include + +#include "neuronide.pb.h" +#include "scene/SceneAll.hpp" + +std::shared_ptr<::Scene> Parser::parse(const std::string& filePath) { + NeuronIDE::Scene protoScene; + + std::ifstream file(filePath, std::ios::binary); + if (!file.is_open()) { + throw std::runtime_error("Parser: cannot open file: " + filePath); + } + + if (!protoScene.ParseFromIstream(&file)) { + throw std::runtime_error("Parser: failed to parse protobuf from: " + filePath); + } + + auto scene = std::make_shared<::Scene>(); + scene->setExperimentName(protoScene.project_name()); + + for (const auto& protoObj : protoScene.scene_objects()) { + auto obj = buildSceneObject(protoObj); + scene->addObject(std::move(obj)); + } + + return scene; +} + +std::shared_ptr Parser::buildSceneObject(const NeuronIDE::SceneObject& protoObj) { + auto obj = std::make_shared(protoObj.name(), protoObj.is_visible()); + + if (protoObj.has_transform()) { + const auto& tra = protoObj.transform(); + obj->setTransform(tra.x(), tra.y(), tra.width(), tra.height(), tra.rotation()); + } + + for (const auto& protoComp : protoObj.components()) { + auto comp = buildComponent(protoComp); + if (comp) { + obj->addComponent(std::move(comp)); + } + } + + return obj; +} + +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; + } +} \ No newline at end of file