A script can now be attached to any number of entities at once

dev
Joey Pollack 3 years ago
parent 060bfcf6c9
commit d75f37d575

@ -7,10 +7,14 @@ Build System:
✔ Modify .sh scripts to recognize the noeditor flag @done (1/25/2022, 3:59:23 PM) ✔ Modify .sh scripts to recognize the noeditor flag @done (1/25/2022, 3:59:23 PM)
Core: Core:
☐ Update console gui system to store the full message meta-data so that filters can be applied @High
☐ Create log rotation system so that log files do not grow to GB in size... @critical ☐ 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 - 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 ☐ Figure out how to represent Unique Entities and entity instances - and how this will work with UUIDs @critical
☐ Design Entity Template system ☐ Design Entity Template system
☐ Add log settings to the state file
✔ Implement generic serialization system @done(22-06-29 18:44) ✔ Implement generic serialization system @done(22-06-29 18:44)
✔ JSON serializable base class @done(22-06-29 17:41) ✔ 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) ✔ JSON implementions should be stubbed out in non-editor builds @done(22-06-29 17:41)
@ -27,7 +31,6 @@ Core:
✔ assets @done(22-05-17 14:27) ✔ assets @done(22-05-17 14:27)
✔ gui @done(22-05-17 14:27) ✔ gui @done(22-05-17 14:27)
✔ Replace the File Browser (imgui) class with the NFD library (https://github.com/btzy/nativefiledialog-extended) @high @done(22-05-23 16:00) ✔ Replace the File Browser (imgui) class with the NFD library (https://github.com/btzy/nativefiledialog-extended) @high @done(22-05-23 16:00)
☐ Add log settings to the state file
✔ Refactor log system to use separate log level methods instead of passing log level @done(22-05-12 16:46) ✔ Refactor log system to use separate log level methods instead of passing log level @done(22-05-12 16:46)
✔ Add log level options to config script @done(22-05-12 16:46) ✔ Add log level options to config script @done(22-05-12 16:46)
✔ Add run modes (Editor, Game, Test) to state file @done (9/15/2021, 7:27:03 PM) ✔ Add run modes (Editor, Game, Test) to state file @done (9/15/2021, 7:27:03 PM)
@ -35,15 +38,19 @@ Core:
✔ Read the window size and position on shutdown and write these to the state file @done (2/8/2022, 4:39:37 PM) ✔ Read the window size and position on shutdown and write these to the state file @done (2/8/2022, 4:39:37 PM)
Physics: Physics:
☐ Joint Component to allow parent/child entities to both use the physics system @high
☐ Come up with a way to wrap Box2D into an API @low
✔ Research Box2D as a possible physics library @done (10/27/2021, 7:40:44 PM) ✔ Research Box2D as a possible physics library @done (10/27/2021, 7:40:44 PM)
✔ Add Box2D to the project as an external library @done (10/27/2021, 7:40:46 PM) ✔ Add Box2D to the project as an external library @done (10/27/2021, 7:40:46 PM)
✔ Add a scene to the tester to test Box2D usage @done (10/28/2021, 2:42:45 PM) ✔ Add a scene to the tester to test Box2D usage @done (10/28/2021, 2:42:45 PM)
☐ Come up with a way to wrap Box2D into an API
☐ Joint Component to allow parent/child entities to both use the physics system
Scripting: Scripting:
☐ Add a Log methods to the CoreAPI ☐ Add Entity class to wrap entity id values
- Foreign class that stores the entity id values and gives access to
- foreign methods for interacting with that entity (getting components/scripts)
✔ Add a Log methods to the CoreAPI @done(23-01-11 15:24)
✔ Allow scripts to interact (calling methods in other scripts) @done(23-01-10 16:54) ✔ Allow scripts to interact (calling methods in other scripts) @done(23-01-10 16:54)
- In order for a script to be registered with the World API it MUST - In order for a script to be registered with the World API it MUST
@ -56,11 +63,16 @@ Scripting:
✔ Script Asset @done(22-11-14 18:19) ✔ Script Asset @done(22-11-14 18:19)
Script Managment class: Script State class:
✔ Allow for running script class objects @done(23-01-11 15:28)
✔ Allow for running raw code snippets (with module importing made easy) @done(23-01-11 15:29)
✔ Wrapper methods for registering foreign classes and methods @done(23-01-11 15:29)
✔ Wrapper methods for getting handles to classes @done(23-01-11 15:29)
✘ Manage LUA states @cancelled(22-05-13 17:31) ✘ Manage LUA states @cancelled(22-05-13 17:31)
☐ Initialize new scripts ✘ Initialize new scripts @cancelled(23-01-11 15:28)
☐ Run given script with given state ✘ Run given script with given state @cancelled(23-01-11 15:28)
☐ Add any generated errors to the Script object ✘ Add any generated errors to the Script object @cancelled(23-01-11 15:28)
Interface Class (Core API): Interface Class (Core API):
☐ Provide Methods that give access to the C++ code ☐ Provide Methods that give access to the C++ code
@ -71,8 +83,9 @@ Audio:
☐ Design Audio API ☐ Design Audio API
Assets: Assets:
☐ Document Index.Dat and the AssetIndex class
✔ Internal Asset Manager @high @done (1/25/2022, 3:58:20 PM) ✔ Internal Asset Manager @high @done (1/25/2022, 3:58:20 PM)
☐ Document Index.Dat and the AssetIndex class
✔ Move the GenerateFont method from internal_font.h into data_manager.h @done(22-06-29 17:42) ✔ Move the GenerateFont method from internal_font.h into data_manager.h @done(22-06-29 17:42)
Types: Types:
@ -156,7 +169,7 @@ ECS:
✔ Single UUID @done(22-06-01 14:01) ✔ Single UUID @done(22-06-01 14:01)
✔ Functionality for adding/working with components (through EnTT) @done(22-06-01 14:01) ✔ Functionality for adding/working with components (through EnTT) @done(22-06-01 14:01)
☐ Serialize ☐ Serialize
☐ JSON ✔ JSON @done(23-01-11 15:35)
☐ Binary ☐ Binary
Components: Components:
@ -171,11 +184,12 @@ ECS:
✔ Script @done(22-11-14 18:19) ✔ Script @done(22-11-14 18:19)
☐ Audio Listener ☐ Audio Listener
Physics: Physics:
☐ Rigid Body (Box2D) ☐ Joint Component
☐ Box Collider (Box2D) ✔ Rigid Body (Box2D) @done(23-01-11 15:35)
✔ Collider (Box2D) @done(23-01-11 15:35)
World (Lunariums version of a "Scene"): World (Lunariums version of a "Scene"):
Add Render layer property to all renderable components Add Render layer property to all renderable components @done(23-01-11 15:35)
✔ Implement memento pattern to save the initial state of the world @done(22-11-14 18:19) ✔ 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 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) ✔ Implement the world without Regions first @done(22-11-14 18:20)

@ -1,7 +1,11 @@
Editor: Editor:
☐ Add ability to browse and restore trashed assets @High
☐ Add button to flip image assets vertically
☐ Design a custom editor style @low
☐ Save and unload world data when a new world is selected
✔ Generate boiler-plate code when a new script is created @critical @done(23-01-11 13:49) ✔ Generate boiler-plate code when a new script is created @critical @done(23-01-11 13:49)
✔ Add pure virtual ShowProperties method to EditorAsset @done(22-11-28 20:11) ✔ Add pure virtual ShowProperties method to EditorAsset @done(22-11-28 20:11)
✔ Script Editor Asset @done(22-11-14 18:19) ✔ Script Editor Asset @done(22-11-14 18:19)
✔ Editor Assets need to switch to using UUIDs @critical @done(22-11-02 18:51) ✔ Editor Assets need to switch to using UUIDs @critical @done(22-11-02 18:51)
@ -10,9 +14,6 @@ Editor:
✔ Add Entity children @done(22-09-14 15:07) ✔ Add Entity children @done(22-09-14 15:07)
✔ Entity Parent/Child hierarchy system @done(22-09-14 15:07) ✔ Entity Parent/Child hierarchy system @done(22-09-14 15:07)
✔ Give Entities a name property separate from the tag component @done(22-09-14 15:06) ✔ Give Entities a name property separate from the tag component @done(22-09-14 15:06)
☐ Add button to flip image assets vertically
☐ Design a custom editor style @low
☐ Save and unload world data when a new world is selected
✔ Load the selected world when double clicked on in the asset browser @done(22-07-05 14:29) ✔ Load the selected world when double clicked on in the asset browser @done(22-07-05 14:29)
✔ Asset Location MUST be relative to the project root directory @critical @done(22-05-20 18:35) ✔ Asset Location MUST be relative to the project root directory @critical @done(22-05-20 18:35)
✔ Switch to NFD dialogs @done(22-05-20 18:35) ✔ Switch to NFD dialogs @done(22-05-20 18:35)
@ -24,8 +25,7 @@ Editor:
✔ Turn World into an editor asset that can be created @done(22-07-05 14:04) ✔ Turn World into an editor asset that can be created @done(22-07-05 14:04)
✔ Store entities in the World object @done(22-07-06 17:53) ✔ Store entities in the World object @done(22-07-06 17:53)
✔ Implement Saving/loading the World asset @done(22-07-06 17:53) ✔ Implement Saving/loading the World asset @done(22-07-06 17:53)
☐ Test the Asset Trashing system @high ✔ Test the Asset Trashing system @high @done(23-01-11 15:22)
☐ Add ability to browse and restore trashed assets
✔ Figure out how to make game asset types integrate with editor asset types @critical @done(22-06-27 13:32) ✔ Figure out how to make game asset types integrate with editor asset types @critical @done(22-06-27 13:32)
- Probably just wrap the game object in an EditorAsset object if needed - Probably just wrap the game object in an EditorAsset object if needed

@ -46,7 +46,7 @@ namespace lunarium
Console::Console(const char* name, PanelDockZone dock_zone, bool isOpen, int window_flags) Console::Console(const char* name, PanelDockZone dock_zone, bool isOpen, int window_flags)
: Panel(name, dock_zone, isOpen, window_flags), : Panel(name, dock_zone, isOpen, window_flags),
mbNewCommand(false), mRecalledCommand(-1), mIsFocused(false), mListener(nullptr), mbNewCommand(false), mRecalledCommand(-1), mIsFocused(false), mListener(nullptr),
mbOglDebug(false), mbInfoVerbose(false), mpListener(nullptr), mInputWindowHeight(20) mbOglDebug(false), mbInfoVerbose(false), mbInfoDebug(false), mpListener(nullptr), mInputWindowHeight(20)
{ {
memset(mBuffer, 0, CONSOLE_BUFFER_SIZE); memset(mBuffer, 0, CONSOLE_BUFFER_SIZE);
mpListener = Logger::GetInstance()->AddListener(new GuiListener(this)); mpListener = Logger::GetInstance()->AddListener(new GuiListener(this));
@ -76,6 +76,12 @@ namespace lunarium
} }
void Console::SetDebugFlag(bool flag)
{
mbInfoDebug = flag;
}
void Console::ClearMessageHistory() void Console::ClearMessageHistory()
{ {
mMsgHistory.clear(); mMsgHistory.clear();
@ -105,7 +111,8 @@ namespace lunarium
{ {
if ((mMsgHistory[i].find("[GRAPHICS INTERNAL DEBUG]") != std::string::npos && !mbOglDebug) if ((mMsgHistory[i].find("[GRAPHICS INTERNAL DEBUG]") != std::string::npos && !mbOglDebug)
|| (mMsgHistory[i].find("[TRACE]") != std::string::npos && !mbInfoVerbose)) || (mMsgHistory[i].find("[TRACE]") != std::string::npos && !mbInfoVerbose)
|| (mMsgHistory[i].find("[DEBUG]") != std::string::npos && !mbInfoDebug))
{ {
continue; continue;
} }

@ -53,6 +53,7 @@ namespace lunarium
void SetOGLDebugFlag(bool flag); void SetOGLDebugFlag(bool flag);
void SetVerboseFlag(bool flag); void SetVerboseFlag(bool flag);
void SetDebugFlag(bool flag);
private: private:
// INPUT COMMAND STUFF // INPUT COMMAND STUFF
@ -71,6 +72,7 @@ namespace lunarium
GuiListener* mListener; GuiListener* mListener;
bool mbOglDebug; bool mbOglDebug;
bool mbInfoVerbose; bool mbInfoVerbose;
bool mbInfoDebug;
private: private:
void CheckFocus(); void CheckFocus();

@ -349,6 +349,7 @@ namespace lunarium { namespace editor
void ContentManager::MoveAsset(EditorAsset* asset, std::filesystem::path to) void ContentManager::MoveAsset(EditorAsset* asset, std::filesystem::path to)
{ {
std::filesystem::path from = mpProject->GetAssetDirectory() / asset->GetFileLocation(); std::filesystem::path from = mpProject->GetAssetDirectory() / asset->GetFileLocation();
to /= asset->GetFileLocation().filename();
// Not all assets will have files associated with them // Not all assets will have files associated with them
if (std::filesystem::exists(from)) if (std::filesystem::exists(from))

@ -53,6 +53,9 @@ namespace lunarium { namespace editor
/// file: the full path to the raw file /// 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) /// 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, LUUID& id); [[nodiscard]] OpRes ImportFile(std::filesystem::path file, std::filesystem::path to_location, AssetType type, LUUID& id);
/// @brief Trashes an asset
/// @param asset_id the UUID of the asset to trash
void RemoveAsset(LUUID asset_id); void RemoveAsset(LUUID asset_id);
void MoveAsset(EditorAsset* asset, std::filesystem::path to); void MoveAsset(EditorAsset* asset, std::filesystem::path to);

@ -19,6 +19,12 @@ namespace lunarium { namespace editor
Script::Script(std::filesystem::path file_location, std::filesystem::path asset_dir) Script::Script(std::filesystem::path file_location, std::filesystem::path asset_dir)
: EditorAsset(AssetType::EATYPE_SCRIPT) : EditorAsset(AssetType::EATYPE_SCRIPT)
{ {
// This is an existing script and data will be set later
// NOTE: Kind of hacky...
if (file_location.string().size() < 1 && asset_dir.string().size() < 1)
return;
std::string full_path = (asset_dir / file_location).string(); std::string full_path = (asset_dir / file_location).string();
if (!std::filesystem::exists(full_path)) if (!std::filesystem::exists(full_path))

@ -534,6 +534,12 @@ namespace editor
} }
} }
} }
void Editor::OnAssetTrash(EditorAsset* pAsset)
{
ContentManager::GetInstance().RemoveAsset(pAsset->GetID());
}
void Editor::OnAssetSelected(EditorAsset* pAsset) void Editor::OnAssetSelected(EditorAsset* pAsset)
{ {

@ -62,6 +62,7 @@ namespace lunarium { namespace editor
void OnEntitySelect(lunarium::Entity* pEnt); void OnEntitySelect(lunarium::Entity* pEnt);
//void ChangeWorld(lunarium::World* pWorld); //void ChangeWorld(lunarium::World* pWorld);
void OnAssetOpen(EditorAsset* pAsset); void OnAssetOpen(EditorAsset* pAsset);
void OnAssetTrash(EditorAsset* pAsset);
void OnAssetSelected(EditorAsset* pAsset); void OnAssetSelected(EditorAsset* pAsset);
void OnNewAsset(EditorAsset* pAsset); void OnNewAsset(EditorAsset* pAsset);
void OnAssetUpdate(EditorAsset* pAsset); void OnAssetUpdate(EditorAsset* pAsset);

@ -27,7 +27,7 @@ namespace editor
{ {
AssetBrowser::AssetBrowser(std::filesystem::path dir, Editor* pEditor) AssetBrowser::AssetBrowser(std::filesystem::path dir, Editor* pEditor)
: Panel("Asset Browser", PanelDockZone::DDZ_BOTTOM, true, (ImGuiWindowFlags)ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar), : Panel("Asset Browser", PanelDockZone::DDZ_BOTTOM, true, (ImGuiWindowFlags)ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar),
mAssetDirectory(dir), mpEditor(pEditor), mSyncTree(false) mAssetDirectory(dir), mpEditor(pEditor), mSyncTree(false), mpHoveredAsset(nullptr), mbMenusOpen(false)
{ {
DefinePopups(); DefinePopups();
} }
@ -229,6 +229,9 @@ namespace editor
for (auto iter = assets.begin(); iter != assets.end(); iter++) for (auto iter = assets.begin(); iter != assets.end(); iter++)
{ {
if ((*iter)->GetIsTrashed())
continue;
if (ImGui::Selectable((*iter)->GetFileLocation().stem().string().c_str())) if (ImGui::Selectable((*iter)->GetFileLocation().stem().string().c_str()))
{ {
// Show properties if this is new selection (meaning wasn't selected last frame) // Show properties if this is new selection (meaning wasn't selected last frame)
@ -252,10 +255,11 @@ namespace editor
mpEditor->OnAssetOpen((*iter)); mpEditor->OnAssetOpen((*iter));
} }
if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) if (ImGui::IsItemHovered() && ImGui::IsItemClicked(ImGuiMouseButton_Right))
{ {
// TODO: CONTEXT MENU FOR ITEMS - Test Removing/Trashing // Change context menu to apply to the hovered asset
mpHoveredAsset = (*iter);
} }
} }
@ -271,53 +275,82 @@ namespace editor
// CONTEXT MENUS // CONTEXT MENUS
void AssetBrowser::DoContentContextMenu() void AssetBrowser::DoContentContextMenu()
{ {
if (ImGui::BeginPopupContextWindow(0, 1, false)) if (ImGui::BeginPopupContextWindow(0, ImGuiPopupFlags_MouseButtonRight))
{ {
if (ImGui::Button("New Folder")) if (mpHoveredAsset)
{ {
//mNewFolder = true; mbMenusOpen = true;
OpenPopup(PopUp::NEW_FOLDER).LogIfFailed(Editor::LogCat); DoHoveredContextMenu();
} }
else
{
DoEmptySpaceContextMenu();
}
// TODO: Buttons for creating/importing new assets
ImGui::EndPopup();
}
else if (mbMenusOpen)
{
mbMenusOpen = false;
mpHoveredAsset = nullptr;
}
}
void AssetBrowser::DoHoveredContextMenu()
{
if (ImGui::Button("Trash Asset"))
{
mpEditor->OnAssetTrash(mpHoveredAsset);
ImGui::CloseCurrentPopup();
mpHoveredAsset = nullptr;
}
}
void AssetBrowser::DoEmptySpaceContextMenu()
{
if (ImGui::Button("New Folder"))
{
// mNewFolder = true;
OpenPopup(PopUp::NEW_FOLDER).LogIfFailed(Editor::LogCat);
}
if (ImGui::BeginMenu("New Asset")) if (ImGui::BeginMenu("New Asset"))
{
if (ImGui::MenuItem("New World"))
{ {
if (ImGui::MenuItem("New World")) OpenPopup(PopUp::NEW_WORLD).LogIfFailed(Editor::LogCat);
{ }
OpenPopup(PopUp::NEW_WORLD).LogIfFailed(Editor::LogCat);
}
if (ImGui::MenuItem("New Script")) if (ImGui::MenuItem("New Script"))
{ {
OpenPopup(PopUp::NEW_SCRIPT).LogIfFailed(Editor::LogCat); OpenPopup(PopUp::NEW_SCRIPT).LogIfFailed(Editor::LogCat);
}
ImGui::EndMenu();
} }
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Import Asset")) if (ImGui::BeginMenu("Import Asset"))
{
if (ImGui::MenuItem("Image"))
{ {
if (ImGui::MenuItem("Image")) std::filesystem::path outPath;
{
std::filesystem::path outPath;
// prepare filters for the dialog // prepare filters for the dialog
FileSystem::FilterItem filterItem[3] = {{"Image file", "png"}, {"Image File", "jpg"}, {"Image File", "jpeg"}}; FileSystem::FilterItem filterItem[3] = {{"Image file", "png"}, {"Image File", "jpg"}, {"Image File", "jpeg"}};
// show the dialog // show the dialog
FileSystem::DialogResult result = FileSystem::OpenFileDialog(outPath, filterItem, 3); FileSystem::DialogResult result = FileSystem::OpenFileDialog(outPath, filterItem, 3);
if (result == FileSystem::DialogResult::OK) if (result == FileSystem::DialogResult::OK)
{ {
Logger::Info(Editor::LogCat, "Importing asset: %s", outPath.string().c_str()); Logger::Info(Editor::LogCat, "Importing asset: %s", outPath.string().c_str());
LUUID id = 0; LUUID id = 0;
ContentManager::GetInstance().ImportFile(outPath, mSelectedDir / outPath.filename(), ContentManager::GetInstance().ImportFile(outPath, mSelectedDir / outPath.filename(),
AssetType::EATYPE_IMAGE, id).LogIfFailed(Editor::LogCat); AssetType::EATYPE_IMAGE, id)
} .LogIfFailed(Editor::LogCat);
} }
ImGui::EndMenu();
} }
ImGui::EndMenu();
// TODO: Buttons for creating/importing new assets
ImGui::EndPopup();
} }
} }
@ -344,66 +377,75 @@ namespace editor
{ {
// New Folder // New Folder
AddPopup(PopUp::NEW_FOLDER, "New Folder Name", [](Panel *p) AddPopup(PopUp::NEW_FOLDER, "New Folder Name", [](Panel *p)
{
bool stay_open = true;
AssetBrowser* ab = (AssetBrowser*)p;
char name_buf[64] = "New Folder";
ImGui::TextUnformatted("Folder Name: ");
ImGui::SameLine();
if (ImGui::InputText("##Folder Name", name_buf, 64, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue))
{ {
bool stay_open = true; std::filesystem::create_directory(ab->mSelectedDir / name_buf);
AssetBrowser* ab = (AssetBrowser*)p; stay_open = false;
char name_buf[64] = "New Folder"; ImGui::CloseCurrentPopup();
ImGui::TextUnformatted("Folder Name: "); }
ImGui::SameLine();
if (ImGui::InputText("##Folder Name", name_buf, 64, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue))
{
std::filesystem::create_directory(ab->mSelectedDir / name_buf);
stay_open = false;
ImGui::CloseCurrentPopup();
}
if (Core::Input().IsKeyDown(KeyCode::ESCAPE, true)) if (Core::Input().IsKeyDown(KeyCode::ESCAPE, true))
{ {
stay_open = false; stay_open = false;
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
return stay_open; return stay_open;
}).LogIfFailed(Editor::LogCat); }).LogIfFailed(Editor::LogCat);
// New World // New World
AddPopup(PopUp::NEW_WORLD, "New World Name", [](Panel *p) AddPopup(PopUp::NEW_WORLD, "New World Name", [](Panel *p)
{
bool stay_open = true;
AssetBrowser* ab = (AssetBrowser*)p;
char name_buf[64] = "New World";
ImGui::TextUnformatted("World Name: ");
ImGui::SameLine();
if (ImGui::InputText("##World Name", name_buf, 64, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue))
{ {
bool stay_open = true; auto assets_dir = ab->mpEditor->GetProject()->MakeRelativeToAssets(ab->mSelectedDir);
AssetBrowser* ab = (AssetBrowser*)p; EditorAsset* pAsset = new editor::World(assets_dir / name_buf);
char name_buf[64] = "New World"; LUUID id;
ImGui::TextUnformatted("World Name: ");
ImGui::SameLine(); ContentManager::GetInstance().AddGeneratedAsset(pAsset, id).LogIfFailed(Editor::LogCat);
if (ImGui::InputText("##World Name", name_buf, 64, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) stay_open = false;
{ ImGui::CloseCurrentPopup();
auto assets_dir = ab->mpEditor->GetProject()->MakeRelativeToAssets(ab->mSelectedDir); }
EditorAsset* pAsset = new editor::World(assets_dir / name_buf);
LUUID id;
ContentManager::GetInstance().AddGeneratedAsset(pAsset, id).LogIfFailed(Editor::LogCat);
stay_open = false;
ImGui::CloseCurrentPopup();
}
if (Core::Input().IsKeyDown(KeyCode::ESCAPE, true)) if (Core::Input().IsKeyDown(KeyCode::ESCAPE, true))
{ {
stay_open = false; stay_open = false;
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
return stay_open; return stay_open;
}).LogIfFailed(Editor::LogCat); }).LogIfFailed(Editor::LogCat);
// New script asset // New script asset
AddPopup(PopUp::NEW_SCRIPT, "New Script Name", [](Panel *p) 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))
{ {
bool stay_open = true; auto assets_dir = ab->mpEditor->GetProject()->MakeRelativeToAssets(ab->mSelectedDir);
AssetBrowser* ab = (AssetBrowser*)p; std::string sname_buf = name_buf;
char name_buf[64] = "New Script"; if (sname_buf.find(' ')!= std::string::npos)
ImGui::TextUnformatted("Script Name: "); {
ImGui::SameLine(); // This does not show up
if (ImGui::InputText("##Script Name", name_buf, 64, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) ImGui::BeginTooltip();
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Script names can not contain spaces!");
ImGui::EndTooltip();
}
else
{ {
auto assets_dir = ab->mpEditor->GetProject()->MakeRelativeToAssets(ab->mSelectedDir);
std::string sname_buf = name_buf;
sname_buf.append(".wren"); sname_buf.append(".wren");
std::filesystem::path location = assets_dir / sname_buf; std::filesystem::path location = assets_dir / sname_buf;
EditorAsset* pAsset = new editor::Script(location, ab->mpEditor->GetProject()->GetAssetDirectory()); EditorAsset* pAsset = new editor::Script(location, ab->mpEditor->GetProject()->GetAssetDirectory());
@ -413,14 +455,21 @@ namespace editor
stay_open = false; stay_open = false;
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
}
ImGui::SameLine();
if (ImGui::Button("X"))
{
stay_open = false;
ImGui::CloseCurrentPopup();
}
if (Core::Input().IsKeyDown(KeyCode::ESCAPE, true)) if (Core::Input().IsKeyDown(KeyCode::ESCAPE, true))
{ {
stay_open = false; stay_open = false;
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
return stay_open; return stay_open;
}).LogIfFailed(Editor::LogCat); }).LogIfFailed(Editor::LogCat);
} }

@ -36,6 +36,7 @@ namespace editor
std::filesystem::path mSelectedDir; std::filesystem::path mSelectedDir;
Editor* mpEditor; Editor* mpEditor;
bool mSyncTree; bool mSyncTree;
EditorAsset* mpHoveredAsset;
private: private:
void DefinePopups(); void DefinePopups();
@ -45,7 +46,10 @@ namespace editor
void DoContentArea(ImVec2 wind_size); void DoContentArea(ImVec2 wind_size);
// Context menus // Context menus
bool mbMenusOpen;
void DoContentContextMenu(); void DoContentContextMenu();
void DoHoveredContextMenu();
void DoEmptySpaceContextMenu();
// General Helpers // General Helpers
void HandleAssetDrop(std::filesystem::path dir); void HandleAssetDrop(std::filesystem::path dir);
@ -59,6 +63,7 @@ namespace editor
NEW_WORLD, NEW_WORLD,
NEW_SCRIPT, NEW_SCRIPT,
IMPORT_IMAGE, IMPORT_IMAGE,
TRASH_ASSET,
}; };
}; };

@ -15,7 +15,7 @@ namespace lunarium { namespace editor
{ {
EditorConsole::EditorConsole() EditorConsole::EditorConsole()
: Console("Console", PanelDockZone::DDZ_BOTTOM, true, (ImGuiWindowFlags)ImGuiWindowFlags_NoCollapse), : Console("Console", PanelDockZone::DDZ_BOTTOM, true, (ImGuiWindowFlags)ImGuiWindowFlags_NoCollapse),
mGraphicsDebug(false), mInfoVerbose(false) mGraphicsDebug(false), mInfoVerbose(false), mInfoDebug(false)
{ {
} }
@ -62,6 +62,13 @@ namespace lunarium { namespace editor
ImGui::SameLine(); ImGui::SameLine();
if (ImGuiExt::CheckBoxLeft("Info Debug", &mInfoDebug))
{
SetVerboseFlag(mInfoDebug);
}
ImGui::SameLine();
if (ImGui::Button("Clear")) if (ImGui::Button("Clear"))
{ {
ClearMessageHistory(); ClearMessageHistory();

@ -26,6 +26,7 @@ namespace lunarium { namespace editor
void DoToolBar(); void DoToolBar();
bool mGraphicsDebug; bool mGraphicsDebug;
bool mInfoVerbose; bool mInfoVerbose;
bool mInfoDebug;
}; };
}} }}

@ -16,6 +16,7 @@
#include <world/components.h> #include <world/components.h>
#include <editor/contents/editor_asset.h> #include <editor/contents/editor_asset.h>
#include <editor/component_guis.h> #include <editor/component_guis.h>
#include <utils/helpers.h>
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// MACROS MACROS // MACROS MACROS
@ -161,6 +162,22 @@ namespace lunarium { namespace editor
{ {
LUUID id = mpSelectedEntity->GetUUID(); LUUID id = mpSelectedEntity->GetUUID();
ImGui::Text("UUID: %llu", (u64)id); ImGui::Text("UUID: %llu", (u64)id);
if (ImGui::BeginPopupContextWindow())
{
if (ImGui::Button("Copy UUID"))
{
ImGui::SetClipboardText(std::to_string(id).c_str());
ImGui::CloseCurrentPopup();
}
if (ImGui::IsKeyDown(ImGuiKey_Escape))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
char buffer[256] = { 0 }; char buffer[256] = { 0 };
strcpy(buffer, mpSelectedEntity->GetName().c_str()); strcpy(buffer, mpSelectedEntity->GetName().c_str());
ImGui::Text("Name:"); ImGui::Text("Name:");

@ -41,6 +41,10 @@ namespace lunarium
// Register Methods // Register Methods
sman.RegisterForeignMethod({"CoreAPI", "Core", true, "IsKeyDown(_)", (ForeignMethod)&CoreAPI::IsKeyDown}); sman.RegisterForeignMethod({"CoreAPI", "Core", true, "IsKeyDown(_)", (ForeignMethod)&CoreAPI::IsKeyDown});
sman.RegisterForeignMethod({"CoreAPI", "Core", true, "LogInfo(_)", (ForeignMethod)&CoreAPI::LogInfo});
sman.RegisterForeignMethod({"CoreAPI", "Core", true, "LogWarning(_)", (ForeignMethod)&CoreAPI::LogWarning});
sman.RegisterForeignMethod({"CoreAPI", "Core", true, "LogError(_)", (ForeignMethod)&CoreAPI::LogError});
sman.RegisterForeignMethod({"CoreAPI", "Core", true, "LogDebug(_)", (ForeignMethod)&CoreAPI::LogDebug});
// Generate Code // Generate Code
std::string keys_script = GenerateWrenKeyCodes(); std::string keys_script = GenerateWrenKeyCodes();
@ -89,18 +93,18 @@ namespace lunarium
Core::MainWindow().Resize(w, h); Core::MainWindow().Resize(w, h);
} }
void CoreAPI::Log(int level, const char* msg) // void CoreAPI::Log(int level, const char* msg)
{ // {
switch (level) // switch (level)
{ // {
case LogLevel::FATAL_ERROR: { Logger::Fatal(mpInstance->mCat, msg); break; } // case LogLevel::FATAL_ERROR: { Logger::Fatal(mpInstance->mCat, msg); break; }
case LogLevel::ERROR: { Logger::Error(mpInstance->mCat, msg); break; } // case LogLevel::ERROR: { Logger::Error(mpInstance->mCat, msg); break; }
case LogLevel::WARNING: { Logger::Warn(mpInstance->mCat, msg); break; } // case LogLevel::WARNING: { Logger::Warn(mpInstance->mCat, msg); break; }
case LogLevel::INFO: { Logger::Info(mpInstance->mCat, msg); break; } // case LogLevel::INFO: { Logger::Info(mpInstance->mCat, msg); break; }
case LogLevel::DEBUG: { Logger::Debug(mpInstance->mCat, msg); break; } // case LogLevel::DEBUG: { Logger::Debug(mpInstance->mCat, msg); break; }
default: { Logger::Trace(mpInstance->mCat, msg); break; } // default: { Logger::Trace(mpInstance->mCat, msg); break; }
} // }
} // }
void CoreAPI::IsKeyDown(WrenVM* vm) void CoreAPI::IsKeyDown(WrenVM* vm)
{ {
@ -108,4 +112,29 @@ namespace lunarium
bool result = Core::Input().IsKeyDown((KeyCode)key_code, true); bool result = Core::Input().IsKeyDown((KeyCode)key_code, true);
wrenSetSlotBool(vm, 0, result); wrenSetSlotBool(vm, 0, result);
} }
void CoreAPI::LogInfo(WrenVM* vm)
{
std::string msg = wrenGetSlotString(vm, 1);
Logger::Info(mpInstance->mCat, msg.c_str());
}
void CoreAPI::LogWarning(WrenVM* vm)
{
std::string msg = wrenGetSlotString(vm, 1);
Logger::Warn(mpInstance->mCat, msg.c_str());
}
void CoreAPI::LogError(WrenVM* vm)
{
std::string msg = wrenGetSlotString(vm, 1);
Logger::Error(mpInstance->mCat, msg.c_str());
}
void CoreAPI::LogDebug(WrenVM* vm)
{
std::string msg = wrenGetSlotString(vm, 1);
Logger::Debug(mpInstance->mCat, msg.c_str());
}
} }

@ -47,7 +47,10 @@ namespace lunarium
public: // API public: // API
static void SetWindowSize(int w, int h); static void SetWindowSize(int w, int h);
static void Log(int level, const char* msg); static void LogInfo(WrenVM* vm);
static void LogWarning(WrenVM* vm);
static void LogError(WrenVM* vm);
static void LogDebug(WrenVM* vm);
static void IsKeyDown(WrenVM* vm); static void IsKeyDown(WrenVM* vm);

@ -31,4 +31,16 @@ foreign class BlockOutComponent {
// Returns the size as a list: [width, height] // Returns the size as a list: [width, height]
foreign GetSize() foreign GetSize()
foreign SetSize(w, h) foreign SetSize(w, h)
} }
// foreign class RigidBodyComponent {
// construct new(entity_id) {}
// }
// foreign class CollisionComponent {
// construct new(entity_id) {}
// }

@ -10,4 +10,8 @@ import "KeyCodes" for KeyCodes
class Core { class Core {
foreign static IsKeyDown(key) foreign static IsKeyDown(key)
foreign static LogInfo(msg)
foreign static LogWarning(msg)
foreign static LogError(msg)
foreign static LogDebug(msg)
} }

@ -7,7 +7,7 @@
******************************************************************************/ ******************************************************************************/
import "Components" for VelocityComponent, BlockOutComponent import "Components" for VelocityComponent, BlockOutComponent
import "CoreAPI" for CoreAPI import "CoreAPI" for Core
// Manages all of the EntityBehaviors // Manages all of the EntityBehaviors
class WorldInterface { class WorldInterface {
@ -25,6 +25,8 @@ class WorldInterface {
__ScriptObjects[entity_id][script_name] = script_class.new(entity_id) __ScriptObjects[entity_id][script_name] = script_class.new(entity_id)
//System.print("Registered script: %(script_name) to entity: %(entity_id)") //System.print("Registered script: %(script_name) to entity: %(entity_id)")
var msg = "Registered script: %(script_name) to entity: %(entity_id)"
Core.LogDebug(msg)
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////

@ -21,6 +21,7 @@ namespace lunarium
WrenState WorldAPI::mScriptState; WrenState WorldAPI::mScriptState;
World* WorldAPI::mpWorld = nullptr; World* WorldAPI::mpWorld = nullptr;
WorldAPI::ScriptEventHandles WorldAPI::mEventHandles; WorldAPI::ScriptEventHandles WorldAPI::mEventHandles;
std::vector<std::string> WorldAPI::mAlreadyRanScripts;
OpRes WorldAPI::Initialize(World* pWorld) OpRes WorldAPI::Initialize(World* pWorld)
{ {
@ -65,6 +66,7 @@ namespace lunarium
void WorldAPI::Shutdown() void WorldAPI::Shutdown()
{ {
mAlreadyRanScripts.clear();
mpWorld = nullptr; mpWorld = nullptr;
} }
@ -76,26 +78,22 @@ namespace lunarium
void WorldAPI::RegisterScript(LUUID entity, WrenScript& script) void WorldAPI::RegisterScript(LUUID entity, WrenScript& script)
{ {
mScriptState.RunScript(&script); // Need to check if script was already run.
// // Get Handle to script class type to use as second paraneter to RegisterScript // In that case skip running and just make a new instance for this entity
// WrenHandle* pScriptClass = mScriptState.GetWrenClassHandle("WorldInterface", script.GetScriptName()); // This allows multiple entities to have their own instances of the same script
// std::vector<WrenParameter> params;
// WrenParameter p;
// p.Type = WrenParamType::WPT_STR;
// p.As.String = std::to_string(entity).c_str();
// params.push_back(p);
// p.As.String = script.GetScriptName().c_str();
// params.push_back(p);
// p.Type = WrenParamType::WPT_HANDLE;
// p.As.Handle = pScriptClass;
// params.push_back(p);
// mScriptState.CallWrenMethod(mEventHandles.mWIRegisterScriptMethod, mEventHandles.mWIHandle, params, "WorldInterface.entity_id, script_name, script_class");
std::string script_class = script.GetScriptName(); std::string script_class = script.GetScriptName();
std::vector<WrenState::Import> modules_to_load;
if (!ScriptAlreadyRan(script.GetScriptName()))
{
mScriptState.RunScript(&script);
mAlreadyRanScripts.push_back(script.GetScriptName());
modules_to_load.push_back({"WorldInterface", "WorldInterface"});
modules_to_load.push_back({ script_class, script_class });
}
std::string module_name = "Register_" + script_class; std::string module_name = "Register_" + script_class;
std::string code = "WorldInterface.RegisterScript(\"" + std::to_string(entity) + "\", \"" + script_class + "\", " + script_class + ")"; std::string code = "WorldInterface.RegisterScript(\"" + std::to_string(entity) + "\", \"" + script_class + "\", " + script_class + ")";
mScriptState.RunSnippet(module_name, {{"WorldInterface", "WorldInterface"}, { script_class, script_class }}, code); mScriptState.RunSnippet(module_name, modules_to_load, code);
} }
void WorldAPI::InvokeEvent(Event e, ...) void WorldAPI::InvokeEvent(Event e, ...)
@ -118,6 +116,18 @@ namespace lunarium
} }
} }
bool WorldAPI::ScriptAlreadyRan(std::string name)
{
for (auto iter : mAlreadyRanScripts)
{
if (iter == name)
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// SCRIPT API // SCRIPT API
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////

@ -14,6 +14,8 @@
#include <scripting/wren_script.h> #include <scripting/wren_script.h>
#include <utils/op_res.h> #include <utils/op_res.h>
#include <vector>
namespace lunarium namespace lunarium
{ {
class WorldAPI class WorldAPI
@ -53,11 +55,14 @@ namespace lunarium
// Foreign classes // Foreign classes
private: // HELPERS
static bool ScriptAlreadyRan(std::string name);
private: private:
static WrenState mScriptState; static WrenState mScriptState;
static World* mpWorld; static World* mpWorld;
static ScriptEventHandles mEventHandles; static ScriptEventHandles mEventHandles;
static std::vector<std::string> mAlreadyRanScripts;
}; };
} }

@ -42,6 +42,21 @@ namespace lunarium
return glsl_version; return glsl_version;
} }
void System::CopyToClipboard(std::string data)
{
#ifdef WIN32
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, data.size() + 1);
memcpy(GlobalLock(hMem), data.c_str(), data.size() + 1);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
#else
#endif // WIN32
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// FILE SYSTEM FUNCTIONS // FILE SYSTEM FUNCTIONS
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

@ -23,6 +23,7 @@ namespace lunarium
public: public:
static Sizei GetScreenResolution(); static Sizei GetScreenResolution();
static std::string GetGLSLVersionString(); static std::string GetGLSLVersionString();
static void CopyToClipboard(std::string data);
}; };
class FileSystem class FileSystem

@ -14,19 +14,6 @@ namespace lunarium
std::mt19937_64 UUID::mt64(time(nullptr)); std::mt19937_64 UUID::mt64(time(nullptr));
LUUID UUID::GetNewID() LUUID UUID::GetNewID()
{ {
// This is kind of hacky. Should probably try to remove the need for null ids.
// LUUID id = 0;
// while (0 == id)
// {
// id = mt64();
// }
// return id;
return mt64(); return mt64();
} }
// LUUID UUID::GetNullID()
// {
// return 0;
// }
} }

@ -479,6 +479,29 @@ namespace lunarium
Deserialize(state.State).LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to deserialize the world state"); Deserialize(state.State).LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to deserialize the world state");
} }
/////////////////////////////////////////////////////////////////////
// PHYSICS CALLBACKS
/////////////////////////////////////////////////////////////////////
void World::BeginContact(b2Contact* contact)
{
}
void World::EndContact(b2Contact* contact)
{
}
void World::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
}
void World::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
{
}
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// SERIALIZING // SERIALIZING
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////

@ -52,7 +52,7 @@ namespace lunarium
int Index; int Index;
}; };
class World : public JSONSerializable class World : public JSONSerializable, b2ContactListener
{ {
public: public:
struct Region struct Region
@ -105,6 +105,13 @@ namespace lunarium
float GetPhysicsScaleFactor() const; float GetPhysicsScaleFactor() const;
void SetPhysicsScaleFactor(float factor); void SetPhysicsScaleFactor(float factor);
// Physics Callbacks
void BeginContact(b2Contact* contact);
void EndContact(b2Contact* contact);
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
// Serializing // Serializing
[[nodiscard]] virtual OpRes Serialize(nlohmann::ordered_json& node); [[nodiscard]] virtual OpRes Serialize(nlohmann::ordered_json& node);
[[nodiscard]] virtual OpRes Deserialize(nlohmann::ordered_json& node); [[nodiscard]] virtual OpRes Deserialize(nlohmann::ordered_json& node);
@ -112,6 +119,7 @@ namespace lunarium
[[nodiscard]] virtual nlohmann::ordered_json AsJSON(); [[nodiscard]] virtual nlohmann::ordered_json AsJSON();
private: private:
LUUID mUUID; LUUID mUUID;
std::string mName; std::string mName;

Loading…
Cancel
Save