16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-21 22:59:19 +02:00

ECS System WIP

This commit is contained in:
2026-04-07 23:40:03 +02:00
parent f6db9978d2
commit 8e9fd9225f
30 changed files with 1133 additions and 242 deletions

View File

@@ -37,6 +37,9 @@ http://mozilla.org/MPL/2.0/.
#include <discord_rpc.h>
#endif
#include "entitysystem/SceneManager.h"
#include "entitysystem/scenes/GameScene.h"
#include <chrono>
#include "utilities/translation.h"
@@ -452,6 +455,8 @@ bool eu07_application::is_client() const
int eu07_application::run()
{
auto frame{0};
sceneManager.SetScene(std::make_unique<GameScene>());
// main application loop
while (!glfwWindowShouldClose(m_windows.front()) && !m_modestack.empty())
{
@@ -474,6 +479,9 @@ int eu07_application::run()
double frameStartTime = Timer::GetTime();
float dt = (float) Timer::GetDeltaTime();
sceneManager.Update(dt);
if (m_modes[m_modestack.top()]->is_command_processor())
{
// active mode is doing real calculations (e.g. drivermode)

View File

@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
#pragma once
#include "application/applicationmode.h"
#include "entitysystem/SceneManager.h"
#include "scripting/PyInt.h"
#include "network/manager.h"
#include "utilities/headtrack.h"
@@ -38,6 +39,7 @@ public:
run();
// issues request for a worker thread to perform specified task. returns: true if task was scheduled
SceneManager sceneManager;
#ifdef WITH_DISCORD_RPC
void DiscordRPCService(); // discord rich presence service function (runs as separate thread)
#endif

View File

@@ -19,6 +19,9 @@ http://mozilla.org/MPL/2.0/.
#include "utilities/translation.h"
#include "application/application.h"
#include "application/editormode.h"
#include "entitysystem/ECScene.h"
#include "entitysystem/components/BasicComponents.h"
#include "entitysystem/components/RenderComponents.h"
#include "imgui/imgui_impl_glfw.h"
@@ -383,6 +386,10 @@ void ui_layer::render()
render_menu();
render_quit_widget();
render_hierarchy();
if (auto* scene = Application.sceneManager.CurrentScene())
{
render_entity_hierarchy(scene->World());
}
// template method implementation
render_();
@@ -470,7 +477,171 @@ void ui_layer::render_hierarchy(){
ImGui::End();
}
void ui_layer::render_entity_hierarchy(ECWorld& world)
{
ImGui::SetNextWindowSize(ImVec2(900, 500), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(STR_C("Entity Hierarchy"), &m_entity_hierarchy))
{
ImGui::End();
return;
}
const float left_panel_width = 280.0f;
ImGui::BeginChild("entity_list_panel", ImVec2(left_panel_width, 0), true);
ImGui::Text("Registered entities: %zu", world.GetEntityCount());
ImGui::Separator();
for (auto entity : world.GetEntities())
{
char buf[64];
std::snprintf(buf, sizeof(buf), "Entity %u", static_cast<unsigned>(entity));
const bool selected = (m_selected_entity == entity);
if (ImGui::Selectable(buf, selected))
{
m_selected_entity = entity;
}
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Entity ID: %u", static_cast<unsigned>(entity));
}
}
ImGui::EndChild();
ImGui::SameLine();
ImGui::BeginChild("entity_inspector_panel", ImVec2(0, 0), true);
if (m_selected_entity == entt::null)
{
ImGui::TextDisabled("No entity selected");
ImGui::EndChild();
ImGui::End();
return;
}
if (!world.IsAlive(m_selected_entity))
{
ImGui::TextDisabled("Selected entity is no longer valid");
ImGui::EndChild();
ImGui::End();
return;
}
ImGui::Text("Selected entity: %u", static_cast<unsigned>(m_selected_entity));
ImGui::Separator();
// Identification
if (auto* id = world.GetComponent<ECSComponent::Identification>(m_selected_entity))
{
if (ImGui::CollapsingHeader("Identification", ImGuiTreeNodeFlags_DefaultOpen))
{
char nameBuffer[256];
std::snprintf(nameBuffer, sizeof(nameBuffer), "%s", id->Name.ToString().c_str());
if (ImGui::InputText("Name", nameBuffer, sizeof(nameBuffer)))
{
id->Name = nameBuffer;
}
}
}
// Transform
if (auto* transform = world.GetComponent<ECSComponent::Transform>(m_selected_entity))
{
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen))
{
float pos[3] = { static_cast<float>(transform->Position.x), static_cast<float>(transform->Position.y), static_cast<float>(transform->Position.z) };
if(ImGui::DragFloat3("Position", pos, 0.1f)){
}
ImGui::DragFloat3("Rotation",
&transform->Rotation.x, 0.1, -360.0, 360.0);
ImGui::DragFloat3("Scale",
&transform->Scale.x, 0.01, 0.0, 100000.0);
}
}
// Velocity
if (auto* velocity = world.GetComponent<ECSComponent::Velocity>(m_selected_entity))
{
if (ImGui::CollapsingHeader("Velocity", ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::DragFloat3("Value",
&velocity->Value.x, 0.1);
if (ImGui::Button("Stop"))
{
velocity->Value = glm::dvec3(0.0);
}
}
}
// LODController
if (auto* lod = world.GetComponent<ECSComponent::LODController>(m_selected_entity))
{
if (ImGui::CollapsingHeader("LODController", ImGuiTreeNodeFlags_DefaultOpen))
{
float range_min = lod->RangeMin;
float range_max = lod->RangeMax;
ImGui::DragFloat("Range Min", &range_min, 0.1, 0.0, 100000.0);
ImGui::DragFloat("Range Max", &range_max, 0.1, 0.0, 100000.0);
}
}
// Sound
if(auto* sound = world.GetComponent<ECSComponent::SoundComponent>(m_selected_entity)){
if(ImGui::CollapsingHeader("Sound", ImGuiTreeNodeFlags_DefaultOpen)){
ImGui::Text("Sound file: %s", sound->sound.name().c_str());
ImGui::DragFloat("Volume", &sound->volume, 0.01f, 0.0f, 1.0f);
ImGui::DragFloat("Pitch", &sound->pitch, 0.01f, 0.0f, 2.0f);
ImGui::Checkbox("Looping", &sound->loop);
ImGui::Checkbox("Playing", &sound->isPlaying);
ImGui::Checkbox("Play On Start", &sound->playOnStart);
}
}
// MeshRenderer
if(auto* mesh_renderer = world.GetComponent<ECSComponent::MeshRenderer>(m_selected_entity))
{
if (ImGui::CollapsingHeader("MeshRenderer", ImGuiTreeNodeFlags_DefaultOpen))
{
//ImGui::Text("Mesh: %s", mesh_renderer->meshHandle.ToString().c_str());
ImGui::Checkbox("Visible", &mesh_renderer->visible);
}
}
// SpotLight
if (auto* light = world.GetComponent<ECSComponent::SpotLight>(m_selected_entity))
{
if (ImGui::CollapsingHeader("SpotLight", ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::Checkbox("Enabled", &light->Enabled);
ImGui::ColorEdit3("Color", &light->Color.x);
ImGui::DragFloat("Intensity", &light->Intensity, 0.1f, 0.0f, 100.0f);
ImGui::DragFloat("Range", &light->Range, 0.5f, 0.0f, 500.0f);
ImGui::DragFloat("Inner Angle", &light->InnerAngle, 0.1f, 0.0f, light->OuterAngle);
ImGui::DragFloat("Outer Angle", &light->OuterAngle, 0.1f, light->InnerAngle, 90.0f);
ImGui::Checkbox("Cast Shadows", &light->CastShadows);
}
}
ImGui::EndChild();
ImGui::End();
}
void ui_layer::set_cursor(int const Mode)
{
glfwSetInputMode(m_window, GLFW_CURSOR, Mode);

View File

@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
#include <string>
#include "model/Texture.h"
#include "widgets/popup.h"
#include "entitysystem/ECWorld.h"
// GuiLayer -- basic user interface class. draws requested information on top of openGL screen
@@ -148,6 +149,7 @@ protected:
void render_menu();
void render_quit_widget();
void render_hierarchy();
void render_entity_hierarchy(ECWorld& world);
// draws a quad between coordinates x,y and z,w with uv-coordinates spanning 0-1
void quad( glm::vec4 const &Coordinates, glm::vec4 const &Color );
// members
@@ -161,4 +163,6 @@ protected:
bool m_imgui_demo = false;
bool m_editor_hierarchy = false;
bool m_editor_change_history = false;
entt::entity m_selected_entity = entt::null;
bool m_entity_hierarchy = true;
};