Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down
5 changes: 4 additions & 1 deletion cmake/Dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ FetchContent_Declare(
FetchContent_MakeAvailable(concurrentqueue)

# 4. SDL2 (System installed)
find_package(SDL2 REQUIRED)
find_package(SDL2 REQUIRED)

# 5. Protobuf (System installed)
find_package(Protobuf REQUIRED)
22 changes: 22 additions & 0 deletions include/parser/Parser.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef PARSER_HPP
#define PARSER_HPP

#include <iostream>
#include <memory>
#include <string>

#include "neuronide.pb.h"
#include "scene/SceneAll.hpp"

class Parser {
public:
Parser() = default;

std::shared_ptr<Scene> parse(const std::string& filePath);

private:
static std::shared_ptr<SceneObject> buildSceneObject(const NeuronIDE::SceneObject& protoObj);
static std::unique_ptr<Component> buildComponent(const NeuronIDE::Component& protoComp);
};

#endif // PARSER_HPP
24 changes: 24 additions & 0 deletions include/scene/Scene.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef SCENE_HPP
#define SCENE_HPP

#include <memory>
#include <string>
#include <vector>

#include "SceneObject.hpp"

class Scene {
private:
std::string experimentName;
std::vector<std::shared_ptr<SceneObject>> objects;

public:
void setExperimentName(const std::string& name) { experimentName = name; }

void addObject(std::shared_ptr<SceneObject> obj) { objects.push_back(std::move(obj)); }

const std::string& getExperimentName() const { return experimentName; }
const std::vector<std::shared_ptr<SceneObject>>& getObjects() const { return objects; }
};

#endif // SCENE_HPP
14 changes: 14 additions & 0 deletions include/scene/SceneAll.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef SCENE_ALL_HPP
#define SCENE_ALL_HPP

// 1. Główne struktury danych sceny
Comment thread
MichalSzandar marked this conversation as resolved.
#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
33 changes: 33 additions & 0 deletions include/scene/SceneObject.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef SCENEOBJECT_HPP
#define SCENEOBJECT_HPP

#include <iostream>
#include <memory>
#include <string>
#include <vector>

#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<std::unique_ptr<Component>> 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) {
Copy link
Copy Markdown

@M1KUS3Q M1KUS3Q May 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it should be abstracted in the future, into either just math vectors or a custom better suited Transform type.
For scaffolding its good enough though i think

I would just make the user pass in the transform struct instead of this in-place construction

transform = {posX, posY, width, height, rotation};
}

void addComponent(std::unique_ptr<Component> comp) { components.push_back(std::move(comp)); }
};

#endif // SCENEOBJECT_HPP
20 changes: 20 additions & 0 deletions include/scene/components/BlinkComponent.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef BLINKCOMPONENT_HPP
#define BLINKCOMPONENT_HPP

#include <iostream>

#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
15 changes: 15 additions & 0 deletions include/scene/components/Component.hpp
Original file line number Diff line number Diff line change
@@ -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
51 changes: 51 additions & 0 deletions protoFiles/neuronide.proto
Original file line number Diff line number Diff line change
@@ -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 {
Copy link
Copy Markdown

@M1KUS3Q M1KUS3Q May 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

additional dictionary or something for script parameters? Or are we just expecting each Script passed to be void -> void ?

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;
}
Binary file added protoFiles/tests/test_scene.pb
Binary file not shown.
45 changes: 45 additions & 0 deletions protoFiles/tests/test_scene.pbtxt
Original file line number Diff line number Diff line change
@@ -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
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also validate the .pb files, because no object should ever have 2 components of the same type, we should throw some error.

}

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
}
}
}
20 changes: 16 additions & 4 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
1 change: 0 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <Runtime.hpp>
#include <iostream>

int main(int argc, char* argv[]) {
Runtime::start();
Expand Down
80 changes: 80 additions & 0 deletions src/parser/Parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "parser/Parser.hpp"

#include <google/protobuf/text_format.h> // dla .pbtxt jeśli będzie potrzeba

#include <fstream>
#include <stdexcept>

#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<SceneObject> Parser::buildSceneObject(const NeuronIDE::SceneObject& protoObj) {
auto obj = std::make_shared<SceneObject>(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<Component> Parser::buildComponent(const NeuronIDE::Component& protoComp) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delegate this to the components themselves?
Adding a case here for each component seems wrong when we can just do inheritence.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we can "just do inheritence" here, we could however use map instead of switch case, maybe we could store that map in some seperate ComponentRegistry class.

using CT = NeuronIDE::Component::ComponentTypeCase;

switch (protoComp.component_type_case()) {
// case CT::kRenderer: {
// const auto& ren = protoComp.renderer();
// return std::make_unique<SpriteRenderer>(ren.texture_path(), ren.img_path());
// }

// case CT::kText: {
// const auto& txt = protoComp.text();
// return std::make_unique<TextRenderer>(txt.text(), txt.font_path(),
// txt.font_size());
// }

case CT::kBlinker: {
const auto& bli = protoComp.blinker();
return std::make_unique<BlinkComponent>(bli.blink_frequency_hz());
}

// case CT::kScript: {
// const auto& scr = protoComp.script();
// return std::make_unique<ScriptComponent>(scr.script_path());
// }

default:
return nullptr;
}
}
Loading