From b29e39966a0647ddb77f4141ca2454d2e767780c Mon Sep 17 00:00:00 2001 From: Ben McAvoy Date: Mon, 4 Nov 2024 20:02:22 +0000 Subject: [PATCH] feat: dynamic data on gameobjects at runtime --- .editorconfig | 4 ++++ README.md | 5 ++++- engine/include/jenjin/datastore.h | 15 +++++++++++++++ engine/include/jenjin/gameobject.h | 9 +++++++-- engine/include/jenjin/luamanager.h | 4 ++++ engine/src/datastore.cpp | 23 +++++++++++++++++++++++ engine/src/editor/editor.cpp | 8 ++++++-- engine/src/luamanager.cpp | 29 ++++++++++++++++++++++++++++- megasource | 2 +- 9 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 .editorconfig create mode 100644 engine/include/jenjin/datastore.h create mode 100644 engine/src/datastore.cpp diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..26cf8e7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.{cpp,h,hpp}] +indent_style = space +indent_size = 2 +tab_width = 2 diff --git a/README.md b/README.md index 046d5e5..fd3f168 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,13 @@ Come back later, sorry! Jenjin is not ready for real usage. - [x] Transparency on sprites - [x] Icons everywhere - [x] Code editor in the editor +- [x] Dynamic data attached to game objects at runtime - [ ] Improved meshing algorithm that gives same input meshes all one mesh reference instead of making multiple mesh references and data for them. -- [ ] Dynamic data attached to game objects at runtime - [ ] Hierarchy and `.Parent` in Lua along with `workspace` (e.g. `Workspace.MyGameObject.Parent` == `Workspace`) +- [ ] Console window in the editor showing output from the engine - [ ] Autocompletion in the editor +- [ ] Allow user to create UI from Lua +- [ ] Better Explorer, allowing right click and creation of new scripts if on the scripts context menu ## TODO (Future) - [ ] Serialization/Deserialization of scenes to better formats diff --git a/engine/include/jenjin/datastore.h b/engine/include/jenjin/datastore.h new file mode 100644 index 0000000..ab2780e --- /dev/null +++ b/engine/include/jenjin/datastore.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#include +#include + +namespace Jenjin { +struct DataStore { + std::unordered_map entries; + + void DynamicSet(std::string key, sol::stack_object value); + sol::object DynamicGet(std::string key); +}; +} // namespace Jenjin diff --git a/engine/include/jenjin/gameobject.h b/engine/include/jenjin/gameobject.h index bdaf6d8..6b6cb7c 100644 --- a/engine/include/jenjin/gameobject.h +++ b/engine/include/jenjin/gameobject.h @@ -1,10 +1,13 @@ #pragma once +#include "jenjin/datastore.h" #include "jenjin/mesh.h" #include #include +#include + #include namespace Jenjin { @@ -32,6 +35,8 @@ class GameObject { bool mixColor = false; + DataStore dataStore; + // TODO: hierarchy #ifdef false GameObject *parent = nullptr; @@ -43,14 +48,14 @@ class GameObject { glm::vec2 GetPosition() { return transform.position; } glm::vec2 GetScale() { return transform.scale; } float GetRotation() { return transform.rotation; } - glm::vec3 GetColor() { return color; } + glm::vec3 GetColor() { return color; } // Setters void SetName(std::string name) { this->name = name; } void SetPosition(glm::vec2 position) { transform.position = position; } void SetScale(glm::vec2 scale) { transform.scale = scale; } void SetRotation(float rotation) { transform.rotation = rotation; } - void SetColor(glm::vec3 color) { this->color = color; } + void SetColor(glm::vec3 color) { this->color = color; } // Pointer getters std::string *GetNamePointer() { return &name; } diff --git a/engine/include/jenjin/luamanager.h b/engine/include/jenjin/luamanager.h index 5ab131e..9fbc616 100644 --- a/engine/include/jenjin/luamanager.h +++ b/engine/include/jenjin/luamanager.h @@ -1,5 +1,7 @@ #pragma once +#include "jenjin/datastore.h" + #include #include #include @@ -28,6 +30,8 @@ class LuaManager { // Getters sol::state *GetLuaState() { return &lua; } + DataStore dataStore; + private: sol::state lua; diff --git a/engine/src/datastore.cpp b/engine/src/datastore.cpp new file mode 100644 index 0000000..5d3029e --- /dev/null +++ b/engine/src/datastore.cpp @@ -0,0 +1,23 @@ +#include "jenjin/datastore.h" + +using namespace Jenjin; + +void DataStore::DynamicSet(std::string key, sol::stack_object value) { + auto it = entries.find(key); + if (it == entries.cend()) { + entries.insert(it, {std::move(key), std::move(value)}); + } else { + std::pair &kvp = *it; + sol::object &entry = kvp.second; + entry = sol::object(std::move(value)); + } +} + +sol::object DataStore::DynamicGet(std::string key) { + auto it = entries.find(key); + if (it == entries.cend()) { + return sol::lua_nil; + } + + return it->second; +} diff --git a/engine/src/editor/editor.cpp b/engine/src/editor/editor.cpp index 94ee1fc..51a246a 100644 --- a/engine/src/editor/editor.cpp +++ b/engine/src/editor/editor.cpp @@ -194,7 +194,7 @@ void Manager::viewport(Jenjin::Scene *scene) { } ImGui::GetWindowDrawList()->AddImage( - (void *)(intptr_t)renderTexture, ImVec2(ImGui::GetCursorScreenPos()), + (ImTextureID)renderTexture, ImVec2(ImGui::GetCursorScreenPos()), ImVec2(ImGui::GetCursorScreenPos().x + size.x, ImGui::GetCursorScreenPos().y + size.y), ImVec2(0, 1), ImVec2(1, 0)); @@ -537,11 +537,15 @@ void Manager::code(Jenjin::Scene *scene) { // TODO: completions on tab if (ImGui::InputTextMultiline("##Code", codeBuffer, sizeof(codeBuffer), ImVec2(ImGui::GetWindowWidth() - 20, - ImGui::GetWindowHeight() - 40 - 32), + ImGui::GetWindowHeight() - 40 - 32 - 24), ImGuiInputTextFlags_AllowTabInput)) { showUnsaved = true; } + ImGui::BeginChild("InfoChild", ImVec2(0, 0), true); + ImGui::Text("%s", codeFile); + ImGui::EndChild(); + ImGui::End(); } diff --git a/engine/src/luamanager.cpp b/engine/src/luamanager.cpp index c1bc275..ff1ea95 100644 --- a/engine/src/luamanager.cpp +++ b/engine/src/luamanager.cpp @@ -365,7 +365,20 @@ void Bindings(LuaManager *lm, sol::state &lua) { &GameObject::SetScale, "SetRotation", &GameObject::SetRotation, "GetColor", &GameObject::GetColor, "SetColor", &GameObject::SetColor, "Translate", &GameObject::Translate, "Scale", &GameObject::Scale, - "Rotate", &GameObject::Rotate); + "Rotate", &GameObject::Rotate, + + sol::meta_function::index, + [](GameObject &gobj, const std::string &key) { + return gobj.dataStore.DynamicGet(key); + }, + + sol::meta_function::new_index, + [](GameObject &gobj, const std::string &key, sol::stack_object value) { + gobj.dataStore.DynamicSet(key, std::move(value)); + }, + + sol::meta_function::length, + [](GameObject &gobj) { return gobj.dataStore.entries.size(); }); lua.new_usertype( "Transform", @@ -431,6 +444,20 @@ void Bindings(LuaManager *lm, sol::state &lua) { } }); + // Globals table (this->dataStore), it needs to be bound to a `globals` + // variable in the lua script and have a metatable that allows indexing and + // new indexing of the table + lua.new_usertype( + "DataStore", sol::no_constructor, sol::meta_function::index, + [](DataStore &ds, const std::string &key) { return ds.DynamicGet(key); }, + sol::meta_function::new_index, + [](DataStore &ds, const std::string &key, sol::stack_object value) { + ds.DynamicSet(key, std::move(value)); + }, + sol::meta_function::length, + [](DataStore &ds) { return ds.entries.size(); }); + lua.set("globals", lm->dataStore); + auto helpers_tb = lua.create_named_table("helpers"); helpers_tb.set_function( "CreateQuad", [&]() { return Jenjin::Helpers::CreateQuad(2.0f, 2.0f); }); diff --git a/megasource b/megasource index a9f6cc7..733ce8a 160000 --- a/megasource +++ b/megasource @@ -1 +1 @@ -Subproject commit a9f6cc787d03e03ba66aa8ccc678478a43bc1924 +Subproject commit 733ce8a4a3d4e120bf044bc2389a7468be5316d4