diff --git a/docs/tasks/core.todo b/docs/tasks/core.todo index 800cab7..85906d8 100644 --- a/docs/tasks/core.todo +++ b/docs/tasks/core.todo @@ -10,6 +10,7 @@ Core: ☐ Create log rotation system so that log files do not grow to GB in size... @critical - If file is X MBs, check for file with .old ext and erase if exists, .old to current file and create new log file ☐ Figure out how to represent Unique Entities and entity instances - and how this will work with UUIDs @critical + ☐ Design Entity Template system ✔ Implement generic serialization system @done(22-06-29 18:44) ✔ JSON serializable base class @done(22-06-29 17:41) ✔ JSON implementions should be stubbed out in non-editor builds @done(22-06-29 17:41) @@ -85,8 +86,10 @@ GUI: ✔ Selected files should show up in the text box @done(22-04-18 13:33) Scripting: - ☐ Switch to Wren instead of LUA (https://github.com/wren-lang/wren) @high - ☐ Remove SOL + ✔ Switch to Wren instead of LUA (https://github.com/wren-lang/wren) @high @done(22-11-02 18:56) + ✔ Remove SOL @done(22-11-02 18:56) + + ✔ Script Asset @done(22-11-14 18:19) Script Managment class: ✘ Manage LUA states @cancelled(22-05-13 17:31) @@ -119,7 +122,7 @@ ECS: ✔ BlockOut @done(22-09-08 15:41) ☐ SpriteRenderer ☐ Animation Controller - ☐ Script + ✔ Script @done(22-11-14 18:19) ☐ Audio Listener Physics: ☐ Rigid Body (Box2D) @@ -127,9 +130,9 @@ ECS: World (Lunariums version of a "Scene"): ☐ Add Render layer property to all renderable components - ☐ Implement memento pattern to save the initial state of the world - ☐ Implement running the world and resetting to initial state - ☐ Implement the world without Regions first + ✔ Implement memento pattern to save the initial state of the world @done(22-11-14 18:19) + ✔ Implement running the world and resetting to initial state @done(22-11-14 18:19) + ✔ Implement the world without Regions first @done(22-11-14 18:20) ✔ Serialize world @done(22-07-06 18:33) ✔ JSON @done(22-07-06 18:33) ☐ Binary diff --git a/docs/tasks/editor.todo b/docs/tasks/editor.todo index 8f2bdfc..781bbf1 100644 --- a/docs/tasks/editor.todo +++ b/docs/tasks/editor.todo @@ -1,6 +1,8 @@ Editor: - ☐ Editor Assets need to switch to using UUIDs @critical + ☐ Add pure virtual ShowProperties method to EditorAsset + ✔ Script Editor Asset @done(22-11-14 18:19) + ✔ Editor Assets need to switch to using UUIDs @critical @done(22-11-02 18:51) ✔ Remove Entity @done(22-10-14 18:28) ✔ Remove Component @done(22-10-14 18:28) ✔ Add Entity children @done(22-09-14 15:07) @@ -43,7 +45,7 @@ Editor: ✔ Open existing project @done (2/8/2022, 4:05:42 PM) Content Manager: - ☐ Switch to using LUUIDs for asset ids @critical + ✔ Switch to using LUUIDs for asset ids @critical @done(22-11-02 18:52) ✔ Design interface @done (2/24/2022, 3:15:39 PM) ✔ Generate new content file @done (2/24/2022, 3:16:00 PM) ✔ Load existing contents @done (3/3/2022, 3:16:21 PM) diff --git a/src/run_modes/editor/component_guis.cpp b/src/run_modes/editor/component_guis.cpp index 1fe78fc..209ca39 100644 --- a/src/run_modes/editor/component_guis.cpp +++ b/src/run_modes/editor/component_guis.cpp @@ -8,11 +8,16 @@ #include "component_guis.h" #include +#include #include #include #include #include +#include + +#include + namespace lunarium { namespace editor { ///////////////////////////////////////////////////////////////////// @@ -132,6 +137,44 @@ namespace lunarium { namespace editor ImGui::InputInt("##Render Layer", &comp.RenderLayer, 1, 10); + return remove; + } + + + bool CompGui::RenderScriptComp(ScriptComponent& comp) + { + bool remove = false; + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, ImGui::GetStyle().ItemSpacing.y + 10.0f)); + remove = DrawTitle("Script Component"); + ImGui::PopStyleVar(); + + ImGui::TextUnformatted("Script: "); + ImGui::SameLine(); + + // TODO: Finish Script GUI + // Drag and Drop script asset + // Click to Open Script (editor event?) + // ComboBox to set script + lunarium::editor::Script* pScript = (lunarium::editor::Script*)ContentManager::GetInstance().GetAsset(comp.ScriptID); + std::string preview = (pScript ? pScript->GetScriptFile().filename().string().c_str() : "NOT SET"); + if (ImGui::BeginCombo("Script", preview.c_str())) + { + std::vector assets; + ContentManager::GetInstance().GetAllAssetsByType(assets, AssetType::EATYPE_SCRIPT); + + for (auto iter = assets.begin(); iter != assets.end(); iter++) + { + editor::Script* pScript = (editor::Script*)(*iter); + bool selected = false; + if (ImGui::Selectable(pScript->GetScriptFile().string().c_str(), &selected)) + { + comp.ScriptID = pScript->GetID(); + } + } + + ImGui::EndCombo(); + } + return remove; } }} \ No newline at end of file diff --git a/src/run_modes/editor/component_guis.h b/src/run_modes/editor/component_guis.h index 1b3a9a5..ca5583b 100644 --- a/src/run_modes/editor/component_guis.h +++ b/src/run_modes/editor/component_guis.h @@ -21,6 +21,7 @@ namespace lunarium { namespace editor static bool RenderVelocityComp(VelocityComponent& comp); static bool RenderCameraComp(CameraComponent& comp); static bool RenderBlockOutComp(BlockOutComponent& comp); + static bool RenderScriptComp(ScriptComponent& comp); }; }} diff --git a/src/run_modes/editor/contents/content_manager.cpp b/src/run_modes/editor/contents/content_manager.cpp index 8fe205d..5b81c7a 100644 --- a/src/run_modes/editor/contents/content_manager.cpp +++ b/src/run_modes/editor/contents/content_manager.cpp @@ -21,6 +21,7 @@ // Asset types #include "tile_set.h" #include "world.h" +#include "script.h" namespace lunarium { namespace editor { @@ -222,7 +223,7 @@ namespace lunarium { namespace editor //mNextID = 0; } - void ContentManager::GetAllAssetIDs(std::vector& container) const + void ContentManager::GetAllAssetIDs(std::vector& container) const { container.clear(); for (auto iter = mAssets.begin(); iter != mAssets.end(); iter++) @@ -256,7 +257,7 @@ namespace lunarium { namespace editor } } - EditorAsset* ContentManager::GetAsset(uint64_t id) + EditorAsset* ContentManager::GetAsset(LUUID id) { auto iter = mAssets.find(id); if (iter == mAssets.end()) @@ -268,7 +269,7 @@ namespace lunarium { namespace editor } - OpRes ContentManager::AddGeneratedAsset(EditorAsset* asset, uint64_t& id) + OpRes ContentManager::AddGeneratedAsset(EditorAsset* asset, LUUID& id) { // if (mAssets.find(mNextID) != mAssets.end()) // { @@ -287,7 +288,7 @@ namespace lunarium { namespace editor return OpRes::OK(); } - OpRes ContentManager::ImportFile(std::filesystem::path file, std::filesystem::path to_location, AssetType type, uint64_t& id) + OpRes ContentManager::ImportFile(std::filesystem::path file, std::filesystem::path to_location, AssetType type, LUUID& id) { // if (mAssets.find(mNextID) != mAssets.end()) // { @@ -326,7 +327,7 @@ namespace lunarium { namespace editor return OpRes::OK(); } - void ContentManager::RemoveAsset(uint64_t asset_id) + void ContentManager::RemoveAsset(LUUID asset_id) { auto iter = mAssets.find(asset_id); if (iter == mAssets.end()) @@ -377,6 +378,7 @@ namespace lunarium { namespace editor { case AssetType::EATYPE_TILE_SET: return new TileSet(); case AssetType::EATYPE_WORLD: return new editor::World(); + case AssetType::EATYPE_SCRIPT: return new editor::Script("", ""); // Dummy info will be overwritten default: return nullptr; } diff --git a/src/run_modes/editor/contents/content_manager.h b/src/run_modes/editor/contents/content_manager.h index 6ae9e0e..b1ae6c3 100644 --- a/src/run_modes/editor/contents/content_manager.h +++ b/src/run_modes/editor/contents/content_manager.h @@ -11,6 +11,7 @@ #ifndef CONTENT_MANAGER_H_ #define CONTENT_MANAGER_H_ +#include #include "definitions.h" #include #include @@ -39,20 +40,20 @@ namespace lunarium { namespace editor [[nodiscard]] OpRes Save(); void Unload(); - void GetAllAssetIDs(std::vector& container) const; + void GetAllAssetIDs(std::vector& container) const; void GetAllAssetsByType(std::vector& container, AssetType type) const; void GetAllAssetsInDirectory(std::vector& container, std::filesystem::path dir); // dir should be relative to the asset dir - EditorAsset* GetAsset(uint64_t id); + EditorAsset* GetAsset(LUUID id); /// Add an asset that was generated by the editor (like tile maps or scripts) - [[nodiscard]] OpRes AddGeneratedAsset(EditorAsset* asset, uint64_t& id); + [[nodiscard]] OpRes AddGeneratedAsset(EditorAsset* asset, LUUID& id); /// Import a raw asset file from outside of the project (like image or sound files) /// file: the full path to the raw file /// to_location: the location inside the project's asset directory to import to (this MUST be a relative path starting in the Asset dir) - [[nodiscard]] OpRes ImportFile(std::filesystem::path file, std::filesystem::path to_location, AssetType type, uint64_t& id); - void RemoveAsset(uint64_t asset_id); + [[nodiscard]] OpRes ImportFile(std::filesystem::path file, std::filesystem::path to_location, AssetType type, LUUID& id); + void RemoveAsset(LUUID asset_id); void MoveAsset(EditorAsset* asset, std::filesystem::path to); diff --git a/src/run_modes/editor/contents/definitions.h b/src/run_modes/editor/contents/definitions.h index 2930a9e..2cf372e 100644 --- a/src/run_modes/editor/contents/definitions.h +++ b/src/run_modes/editor/contents/definitions.h @@ -32,6 +32,7 @@ namespace lunarium { namespace editor EATYPE_TILE_SET, EATYPE_TILE_MAP, EATYPE_WORLD, + EATYPE_SCRIPT, }; }} diff --git a/src/run_modes/editor/contents/script.cpp b/src/run_modes/editor/contents/script.cpp index f6c6a35..1880cbf 100644 --- a/src/run_modes/editor/contents/script.cpp +++ b/src/run_modes/editor/contents/script.cpp @@ -8,7 +8,66 @@ #include "script.h" +#include +#include +#include +#include + namespace lunarium { namespace editor { + Script::Script(std::filesystem::path file_location, std::filesystem::path asset_dir) + : EditorAsset(AssetType::EATYPE_SCRIPT) + { + std::ofstream ofs(asset_dir / file_location); + if (!ofs.is_open()) + { + Logger::Warn(Editor::LogCat, "Could not create file %s", (asset_dir / file_location).string().c_str()); + } + + ofs.close(); + ofs.clear(); + + mLocation = file_location; + } + + std::filesystem::path Script::GetScriptFile() + { + return GetFileLocation(); + } + + std::string Script::GetScript() + { + return FileLoaders::LoadTextFile(GetFileLocation()); + } + + OpRes Script::LoadRawFile() + { + return OpRes::OK(); + } + + OpRes Script::Serialize(nlohmann::ordered_json& node) + { + return OpRes::OK(); + } + + OpRes Script::Deserialize(nlohmann::ordered_json& node) + { + return OpRes::OK(); + } + + bool Script::IsValidNode(nlohmann::ordered_json& node) + { + return true; + } + + nlohmann::ordered_json Script::AsJSON() + { + return nlohmann::ordered_json(); + } + + bool Script::DrawProperties() + { + return false; + } }} \ No newline at end of file diff --git a/src/run_modes/editor/contents/script.h b/src/run_modes/editor/contents/script.h index 239baaf..9e8a51b 100644 --- a/src/run_modes/editor/contents/script.h +++ b/src/run_modes/editor/contents/script.h @@ -10,11 +10,25 @@ #include "editor_asset.h" +#include + namespace lunarium { namespace editor { class Script : public EditorAsset { + public: + Script(std::filesystem::path file_location, std::filesystem::path asset_dir); + + OpRes LoadRawFile(); + OpRes Serialize(nlohmann::ordered_json& node); + OpRes Deserialize(nlohmann::ordered_json& node); + bool IsValidNode(nlohmann::ordered_json& node); + nlohmann::ordered_json AsJSON(); + + std::filesystem::path GetScriptFile(); + std::string GetScript(); + bool DrawProperties(); }; }} diff --git a/src/run_modes/editor/editor.cpp b/src/run_modes/editor/editor.cpp index 645f618..0c65071 100644 --- a/src/run_modes/editor/editor.cpp +++ b/src/run_modes/editor/editor.cpp @@ -7,7 +7,6 @@ ******************************************************************************/ #include "editor.h" -#include "editor/contents/editor_asset.h" #include #include @@ -26,6 +25,12 @@ #include "panels/asset_browser.h" #include "panels/editor_console.h" +// Assets +#include "editor/contents/editor_asset.h" +#include "contents/definitions.h" +#include "contents/script.h" +#include "contents/world.h" + // Tools #include "tools/map_editor/map_editor.h" @@ -467,11 +472,40 @@ namespace editor ((PropertiesView*)mPanelManager.GetPanel(mPanels.PropertiesView))->SetSelection(pEnt); } - void Editor::ChangeWorld(lunarium::World* pWorld) + // void Editor::ChangeWorld(lunarium::World* pWorld) + // { + // // TODO: Unload current world, Load new world + // ((WorldTree*)mPanelManager.GetPanel(mPanels.WorldTree))->SetWorld(pWorld); + // ((WorldView*)mPanelManager.GetPanel(mPanels.WorldView))->SetWorld(pWorld); + // } + + + void Editor::OnAssetOpen(EditorAsset* pAsset) { - // TODO: Unload current world, Load new world - ((WorldTree*)mPanelManager.GetPanel(mPanels.WorldTree))->SetWorld(pWorld); - ((WorldView*)mPanelManager.GetPanel(mPanels.WorldView))->SetWorld(pWorld); + switch (pAsset->GetType()) + { + case AssetType::EATYPE_WORLD: + { + // TODO: Unload current world, Load new world + lunarium::World* pWorld = ((editor::World*)pAsset)->GetWorld(); + ((WorldTree*)mPanelManager.GetPanel(mPanels.WorldTree))->SetWorld(pWorld); + ((WorldView*)mPanelManager.GetPanel(mPanels.WorldView))->SetWorld(pWorld); + } + break; + + case AssetType::EATYPE_SCRIPT: + { + // TODO: Hardcoding to open vs code - this should become an editor setting + std::filesystem::path location = mProject.GetAssetDirectory() / pAsset->GetFileLocation(); + + // the open -n can be used to force code to open the file in a new window + std::string command = "code \""; + command.append(location.string()); + command.append("\""); + Logger::Debug(LogCat, "Opening code with command: %s", command.c_str()); + std::system(command.c_str()); + } + } } void Editor::OnAssetSelected(EditorAsset* pAsset) diff --git a/src/run_modes/editor/editor.h b/src/run_modes/editor/editor.h index 267afec..7c4ba72 100644 --- a/src/run_modes/editor/editor.h +++ b/src/run_modes/editor/editor.h @@ -59,7 +59,8 @@ namespace lunarium { namespace editor // Panel events void OnEntitySelect(lunarium::Entity* pEnt); - void ChangeWorld(lunarium::World* pWorld); + //void ChangeWorld(lunarium::World* pWorld); + void OnAssetOpen(EditorAsset* pAsset); void OnAssetSelected(EditorAsset* pAsset); void OnNewAsset(EditorAsset* pAsset); void OnAssetUpdate(EditorAsset* pAsset); diff --git a/src/run_modes/editor/editor_helpers.cpp b/src/run_modes/editor/editor_helpers.cpp index fc68824..1ec3807 100644 --- a/src/run_modes/editor/editor_helpers.cpp +++ b/src/run_modes/editor/editor_helpers.cpp @@ -9,8 +9,10 @@ #include "editor_helpers.h" #include +#include #include #include +#include namespace lunarium { namespace editor { @@ -35,5 +37,30 @@ namespace lunarium { namespace editor Texture* t = Texture::Create(buffer, w, h, format); return t; - } + } + + std::string FileLoaders::LoadTextFile(std::filesystem::path file) + { + std::string contents = ""; + std::ifstream ifs(file.string().c_str()); + if (!ifs.is_open()) + { + Logger::Warn(LogCategory::UTILITIES, "Failed to open file: %s", file.string().c_str()); + return ""; + } + + while (true) + { + std::getline(ifs, contents); + + if (ifs.eof()) break; + + contents += "\n"; + } + + ifs.close(); + ifs.clear(); + + return contents; + } }} \ No newline at end of file diff --git a/src/run_modes/editor/editor_helpers.h b/src/run_modes/editor/editor_helpers.h index 62d8d13..0ba448a 100644 --- a/src/run_modes/editor/editor_helpers.h +++ b/src/run_modes/editor/editor_helpers.h @@ -22,6 +22,7 @@ namespace lunarium { namespace editor { public: static lunarium::Texture* LoadImage(std::filesystem::path file); + static std::string LoadTextFile(std::filesystem::path file); }; }} diff --git a/src/run_modes/editor/panels/asset_browser.cpp b/src/run_modes/editor/panels/asset_browser.cpp index 9a156d0..e932dec 100644 --- a/src/run_modes/editor/panels/asset_browser.cpp +++ b/src/run_modes/editor/panels/asset_browser.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace lunarium @@ -222,7 +223,9 @@ namespace editor if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { // Logger::Info(Editor::LogCat, "Asset double clicked on. Relevant editor should open!"); - HandleAssetDoubleClick((*iter)); + //HandleAssetDoubleClick((*iter)); + + mpEditor->OnAssetOpen((*iter)); } if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) @@ -258,6 +261,11 @@ namespace editor { OpenPopup(PopUp::NEW_WORLD).LogIfFailed(Editor::LogCat); } + + if (ImGui::MenuItem("New Script")) + { + OpenPopup(PopUp::NEW_SCRIPT).LogIfFailed(Editor::LogCat); + } ImGui::EndMenu(); } @@ -323,7 +331,37 @@ namespace editor { auto assets_dir = ab->mpEditor->GetProject()->MakeRelativeToAssets(ab->mSelectedDir); EditorAsset* pAsset = new editor::World(assets_dir / name_buf); - u64 id; + LUUID id; + + ContentManager::GetInstance().AddGeneratedAsset(pAsset, id).LogIfFailed(Editor::LogCat); + stay_open = false; + ImGui::CloseCurrentPopup(); + } + + if (Core::Input().IsKeyDown(KeyCode::ESCAPE, true)) + { + stay_open = false; + ImGui::CloseCurrentPopup(); + } + return stay_open; + }).LogIfFailed(Editor::LogCat); + + // New script asset + AddPopup(PopUp::NEW_SCRIPT, "New Script Name", [](Panel *p) + { + bool stay_open = true; + AssetBrowser* ab = (AssetBrowser*)p; + char name_buf[64] = "New Script"; + ImGui::TextUnformatted("Script Name: "); + ImGui::SameLine(); + if (ImGui::InputText("##Script Name", name_buf, 64, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) + { + auto assets_dir = ab->mpEditor->GetProject()->MakeRelativeToAssets(ab->mSelectedDir); + std::string sname_buf = name_buf; + sname_buf.append(".wren"); + std::filesystem::path location = assets_dir / sname_buf; + EditorAsset* pAsset = new editor::Script(location, ab->mpEditor->GetProject()->GetAssetDirectory()); + LUUID id; ContentManager::GetInstance().AddGeneratedAsset(pAsset, id).LogIfFailed(Editor::LogCat); stay_open = false; @@ -341,14 +379,14 @@ namespace editor - void AssetBrowser::HandleAssetDoubleClick(EditorAsset* pAsset) - { - if (pAsset->GetType() == AssetType::EATYPE_WORLD) - { - World* pAssetWorld = (World*)pAsset; - mpEditor->ChangeWorld(pAssetWorld->GetWorld()); - } - } + // void AssetBrowser::HandleAssetDoubleClick(EditorAsset* pAsset) + // { + // if (pAsset->GetType() == AssetType::EATYPE_WORLD) + // { + // World* pAssetWorld = (World*)pAsset; + // mpEditor->ChangeWorld(pAssetWorld->GetWorld()); + // } + // } } } diff --git a/src/run_modes/editor/panels/asset_browser.h b/src/run_modes/editor/panels/asset_browser.h index 187fff7..bb811c1 100644 --- a/src/run_modes/editor/panels/asset_browser.h +++ b/src/run_modes/editor/panels/asset_browser.h @@ -49,7 +49,7 @@ namespace editor // General Helpers void HandleAssetDrop(std::filesystem::path dir); - void HandleAssetDoubleClick(EditorAsset* pAsset); + //void HandleAssetDoubleClick(EditorAsset* pAsset); private: // POPUP ENUMS @@ -57,6 +57,7 @@ namespace editor { NEW_FOLDER, NEW_WORLD, + NEW_SCRIPT, }; }; diff --git a/src/run_modes/editor/panels/properties_view.cpp b/src/run_modes/editor/panels/properties_view.cpp index b71144e..ff962e4 100644 --- a/src/run_modes/editor/panels/properties_view.cpp +++ b/src/run_modes/editor/panels/properties_view.cpp @@ -68,6 +68,7 @@ namespace lunarium { namespace editor PRESENT_COMP_CHOICE("Velocity Component", VelocityComponent, pv) PRESENT_COMP_CHOICE("Camera Component", CameraComponent, pv) PRESENT_COMP_CHOICE("Block Out Component", BlockOutComponent, pv) + PRESENT_COMP_CHOICE("Script Component", ScriptComponent, pv) if ((ImGui::IsMouseClicked(ImGuiMouseButton_Left) && is_hover < 1)) @@ -187,6 +188,7 @@ namespace lunarium { namespace editor DRAW_COMP_GUI(VelocityComponent, RenderVelocityComp) DRAW_COMP_GUI(CameraComponent, RenderCameraComp) DRAW_COMP_GUI(BlockOutComponent, RenderBlockOutComp) + DRAW_COMP_GUI(ScriptComponent, RenderScriptComp) // After all components rendered if (ImGuiExt::ButtonCentered("Add Component")) diff --git a/src/world/components.h b/src/world/components.h index 2433099..349b2ae 100644 --- a/src/world/components.h +++ b/src/world/components.h @@ -84,6 +84,14 @@ namespace lunarium BlockOutComponent(const BlockOutComponent&) = default; }; + struct ScriptComponent + { + LUUID ScriptID; + + ScriptComponent() = default; + ScriptComponent(const ScriptComponent&) = default; + }; + ///////////////////////////////////////////////////////////////////// // UTILITY COMPONENTS ///////////////////////////////////////////////////////////////////// diff --git a/src/world/entity.cpp b/src/world/entity.cpp index 051ed37..8d47493 100644 --- a/src/world/entity.cpp +++ b/src/world/entity.cpp @@ -268,6 +268,17 @@ namespace lunarium components.emplace_back(blockout); } + if (HasComponent()) + { + + nlohmann::ordered_json script; + ScriptComponent& comp = GetComponent(); + script["type_name"] = "ScriptComponent"; + + script["script_id"] = comp.ScriptID; + components.emplace_back(script); + } + if (HasComponent()) { nlohmann::ordered_json parent; @@ -411,6 +422,13 @@ namespace lunarium AddComponent(Color, Size, layer); } + if ("ScriptComponent" == comp_type_name) + { + LUUID id = comp["script_id"]; + + AddComponent(id); + } + if ("ParentEntityComponent" == comp_type_name) { LUUID parent = comp["UUID"].get();