diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index ebfe6a4..0445e0d 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -9,7 +9,7 @@ "${PLUGIN_SDK_DIR}/plugin_sa/*", "${PLUGIN_SDK_DIR}/plugin_sa/game_sa/*", "${PLUGIN_SDK_DIR}/shared/*", - "${PLUGIN_SDK_DIR}/shared/game/*", + "${PLUGIN_SDK_DIR}/shared/game/*" ], "defines": [ "_DEBUG", diff --git a/resource/MapEditor/json/favourites.json b/resource/MapEditor/json/favourites.json index 29e46bb..b330353 100644 --- a/resource/MapEditor/json/favourites.json +++ b/resource/MapEditor/json/favourites.json @@ -1,5 +1,5 @@ { - "All": { + "Custom": { "1344 - CJ_Dumpster2": "1344", "5490 - laeroad25": "5490", "6136 - gaz15_law": "6136" diff --git a/src/d3dhook.cpp b/src/d3dhook.cpp index e3c37ac..ffa3dbd 100644 --- a/src/d3dhook.cpp +++ b/src/d3dhook.cpp @@ -60,7 +60,7 @@ void D3dHook::ProcessFrame(void* ptr) ImVec2 size(screen::GetScreenWidth(), screen::GetScreenHeight()); if ((fScreenSize.x != size.x && fScreenSize.y != size.y) || FontMgr::IsReloadNeeded()) { - if (gRenderer == Render_DirectX9) + if (gRenderer == eRenderer::DirectX9) { ImGui_ImplDX9_InvalidateDeviceObjects(); } @@ -85,7 +85,7 @@ void D3dHook::ProcessFrame(void* ptr) } ImGui_ImplWin32_NewFrame(); - if (gRenderer == Render_DirectX9) + if (gRenderer == eRenderer::DirectX9) { ImGui_ImplDX9_NewFrame(); } @@ -104,7 +104,7 @@ void D3dHook::ProcessFrame(void* ptr) ImGui::EndFrame(); ImGui::Render(); - if (gRenderer == Render_DirectX9) + if (gRenderer == eRenderer::DirectX9) { ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); } @@ -122,7 +122,7 @@ void D3dHook::ProcessFrame(void* ptr) patch::Nop(0x00531155, 5); // shift trigger fix #endif - if (gRenderer == Render_DirectX9) + if (gRenderer == eRenderer::DirectX9) { ImGui_ImplDX9_Init(reinterpret_cast(ptr)); } @@ -216,7 +216,6 @@ void D3dHook::ProcessMouse() } else { - patch::SetUChar(BY_GAME(0x6194A0, 0x6020A0, 0x580D20), BY_GAME(0xE9, 0x53, 0x53)); #ifdef GTASA patch::SetRaw(0x541DD7, (char*)"\xE8\xE4\xD5\xFF\xFF", 5); @@ -256,7 +255,7 @@ bool D3dHook::InjectHook(void *pCallback) */ if (init(kiero::RenderType::D3D9) == kiero::Status::Success) { - gRenderer = Render_DirectX9; + gRenderer = eRenderer::DirectX9; kiero::bind(16, (void**)&oReset, hkReset); kiero::bind(42, (void**)&oEndScene, hkEndScene); pCallbackFunc = pCallback; @@ -267,7 +266,7 @@ bool D3dHook::InjectHook(void *pCallback) if (init(kiero::RenderType::D3D11) == kiero::Status::Success) { - gRenderer = Render_DirectX11; + gRenderer = eRenderer::DirectX11; kiero::bind(8, (void**)&oPresent, hkPresent); pCallbackFunc = pCallback; hookInjected = true; diff --git a/src/dllmain.cpp b/src/dllmain.cpp index bc58406..c037a9b 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -6,12 +6,14 @@ void EditorThread(void* param) { ObjManager::Init(); Updater::CheckUpdate(); - /* - Wait for game init - Doing it like this doesn't prevent you to attach debugger - */ + + /* + Wait for game init + Sleep() bugs when debugger is attached + */ static bool gameStarted = false; - Events::processScriptsEvent +=[]{ + Events::initGameEvent +=[] + { gameStarted = true; }; diff --git a/src/editor.cpp b/src/editor.cpp index 3513fe4..fc4bb24 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -9,44 +9,27 @@ #include #include "filemgr.h" +bool Editor::IsOpen() +{ + return m_bOpened; +} + void Editor::Init() { - D3dHook::InjectHook(&DrawWindow); + D3dHook::InjectHook(&Draw); ApplyStyle(); Updater::CheckUpdate(); // Load config data - Interface::m_bAutoSave = gConfig.GetValue("editor.autoSave", true); - Interface::m_bAutoTpToLoc = gConfig.GetValue("editor.autoTpToLoc", false); - Interface::m_bAutoSnapToGround = gConfig.GetValue("editor.autoSnap", true); - Interface::m_bShowInfoMenu = gConfig.GetValue("editor.showInfoMenu", true); - Interface::m_bFramerate = gConfig.GetValue("editor.showFPS", false); - ObjManager::m_bDrawBoundingBox = gConfig.GetValue("editor.drawBoundingBox", true); - ObjManager::m_bDrawAxisLines = gConfig.GetValue("editor.drawAxisLines", true); - Viewport::m_bShowHoverMenu = gConfig.GetValue("editor.showHoverMenu", true); - Interface::m_bWelcomeScreenDisplayed = gConfig.GetValue("editor.welcomeDisplayed", false); - Viewport::m_nMul = gConfig.GetValue("editor.moveSpeed", 1.0f); + Viewport::m_nMoveSpeed = gConfig.GetValue("editor.moveSpeed", 1.0f); FontMgr::SetMultiplier(gConfig.GetValue("editor.fontMul", 1.0f)); - - if (!Interface::m_bWelcomeScreenDisplayed) - { - Interface::m_bShowPopup = true; - Interface::m_popupTitle = "Map Editor"; - Interface::m_pPopupFunc = Interface::WelcomeMenu; - Interface::m_bWelcomeScreenDisplayed = true; - gConfig.SetValue("editor.welcomeDisplayed", Interface::m_bWelcomeScreenDisplayed); - } + Interface::Init(); Events::processScriptsEvent += []() { - if (Editor::m_bShowEditor) - { - Viewport::Process(); - } - if (toggleUIKey.Pressed()) { - Editor::m_bShowGUI = !Editor::m_bShowGUI; + Interface::Interface::m_bShowGUI = !Interface::Interface::m_bShowGUI; } if (copyHoveredObjName.Pressed()) @@ -56,11 +39,11 @@ void Editor::Init() CHud::SetHelpMessage("Copied to clipboard", false, false, false); } - if (editorOpenKey.Pressed() && !Interface::m_bIsInputLocked) + if (editorOpenKey.Pressed() && !Interface::m_bInputLocked) { - Editor::m_bShowEditor = !Editor::m_bShowEditor; + m_bOpened = !m_bOpened; - if (Editor::m_bShowEditor) + if (m_bOpened) { if (Interface::m_bAutoTpToLoc) { @@ -84,45 +67,32 @@ void Editor::Init() Events::shutdownRwEvent += []() { - gConfig.WriteToDisk(); + gConfig.WriteToDisk(); }; }; void Editor::Cleanup() { - Viewport::m_eViewportMode = EDIT_MODE; - Interface::Browser::m_bShown = false; - Interface::Browser::m_bShowNextFrame = false; D3dHook::SetMouseState(false); gConfig.WriteToDisk(); - Viewport::Shutdown(); + Viewport::Cleanup(); } -void Editor::DrawWindow() +void Editor::Draw() { static bool bTriedtoHideCursor; if (!FrontEndMenuManager.m_bMenuActive) { - if (Editor::m_bShowEditor) + if (m_bOpened) { - if (Viewport::m_eViewportMode == EDIT_MODE) + if (Viewport::m_eState == eViewportState::Edit) { D3dHook::SetMouseState(true); bTriedtoHideCursor = false; } - Interface::m_bIsInputLocked = false; + Interface::m_bInputLocked = false; - if (m_bShowGUI) - { - Interface::DrawMainMenuBar(); - Viewport::DrawOverlay(); - Viewport::ProcessSelectedObjectInputs(); - Interface::DrawPopupMenu(); - Interface::DrawInfoMenu(); - Viewport::DrawHoverMenu(); - } - - if (Interface::m_bAutoSave && ObjManager::m_pVecEntities.size() > 0) + if (Interface::m_bAutoSave && ObjManager::m_pPlacedObjs.size() > 0) { static size_t timer = CTimer::m_snTimeInMilliseconds; size_t curTimer = CTimer::m_snTimeInMilliseconds; @@ -133,6 +103,8 @@ void Editor::DrawWindow() timer = curTimer; } } + Interface::Process(); + Viewport::Process(); } } else diff --git a/src/editor.h b/src/editor.h index 3b10b3b..3e178a5 100644 --- a/src/editor.h +++ b/src/editor.h @@ -5,16 +5,15 @@ class Editor { private: static void ApplyStyle(); + static inline bool m_bOpened; // Is the editor being shown public: - static inline bool m_bShowEditor; - static inline bool m_bShowGUI = true; Editor() = delete; Editor(Editor&) = delete; static void Init(); - static void CheckForUpdate(); - static void DrawWindow(); + static bool IsOpen(); + static void Draw(); static void Cleanup(); }; \ No newline at end of file diff --git a/src/filemgr.cpp b/src/filemgr.cpp index 2368837..bbeffa7 100644 --- a/src/filemgr.cpp +++ b/src/filemgr.cpp @@ -46,7 +46,7 @@ void FileMgr::ImportIDE(std::string path, bool logImports) } ObjManager::m_vecModelNames.push_back({dirEntry.path().stem().string(), std::move(temp)}); - ObjManager::totalIDELinesLoaded++; + ObjManager::m_nTotalIDELine++; } } } @@ -80,7 +80,7 @@ void FileMgr::ImportIPL(std::string fileName, bool logImports) gLog << "Pasing line: " << line << std::endl; } - int hObj; + int hObj; Command(model); Command(); Command(model, pos.x, pos.y, pos.z, &hObj); @@ -108,7 +108,7 @@ void FileMgr::ImportIPL(std::string fileName, bool logImports) // Setting quat messes with z coord? Command(hObj, pos.x, pos.y, pos.z); Command(model); - ObjManager::m_pVecEntities.push_back(CPools::GetObject(hObj)); + ObjManager::m_pPlacedObjs.push_back(CPools::GetObject(hObj)); } } CHud::SetHelpMessage("IPL imported", false, false, false); @@ -119,7 +119,7 @@ void FileMgr::ExportIPL(const char* fileName) std::fstream file; file.open(std::string(PLUGIN_PATH((char*)"MapEditor/")) + fileName, std::ios::out); file << "# Generated using Map Editor by Grinch_\ninst" << std::endl; - for (CObject *pObj : ObjManager::m_pVecEntities) + for (CObject *pObj : ObjManager::m_pPlacedObjs) { int model = pObj->m_nModelIndex; auto &data = ObjManager::m_objData.Get(pObj); diff --git a/src/fontmgr.h b/src/fontmgr.h index e2a94c7..1fa8490 100644 --- a/src/fontmgr.h +++ b/src/fontmgr.h @@ -15,7 +15,7 @@ class FontMgr }; static inline std::vector m_vecFonts; static inline bool m_bMulChangedExternal; - + public: FontMgr() = delete; FontMgr(FontMgr&) = delete; diff --git a/src/interface.cpp b/src/interface.cpp index 001b489..03c4b6a 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -13,27 +13,7 @@ #include #include -size_t Interface::Browser::GetSelected() -{ - return m_nSelected; -} - -void Interface::Browser::SetSelected(int modelId) -{ - /* - Check if the model is available first! - If not set model to -1 - */ - if (modelId > 0 && Command(modelId)) - { - CStreaming::RequestModel(modelId, PRIORITY_REQUEST); - CStreaming::LoadAllRequestedModels(true); - } - - m_nSelected = Command(modelId) ? modelId : NULL; -} - -void Interface::SearchContextMenu(std::string& root, std::string& key, std::string& value) +void ContextMenu_Search(std::string& root, std::string& key, std::string& value) { if (ImGui::MenuItem("Add to favourites")) { @@ -46,33 +26,13 @@ void Interface::SearchContextMenu(std::string& root, std::string& key, std::stri if (ImGui::MenuItem("Copy")) { - Viewport::COPY_MODEL::m_nModel = std::stoi(value); + ObjManager::ClipBoard::m_nModel = std::stoi(value); CHud::SetHelpMessage("Object Copied", false, false, false); }; } -void Interface::ProcessContextMenu() -{ - if (m_contextMenu.function != nullptr) - { - if (ImGui::BeginPopupContextWindow("TMenu")) - { - ImGui::Text(m_contextMenu.key.c_str()); - ImGui::Separator(); - m_contextMenu.function(m_contextMenu.rootKey, m_contextMenu.key, m_contextMenu.value); - - if (ImGui::MenuItem("Close")) - { - m_contextMenu.function = nullptr; - } - - ImGui::EndPopup(); - } - } -} - -void Interface::ImportMenu() +void ImportPopup() { std::filesystem::path path = PLUGIN_PATH((char*)"/MapEditor/"); if (std::filesystem::exists(path)) @@ -86,23 +46,24 @@ void Interface::ImportMenu() ImGui::Dummy(ImVec2(0, 20)); static std::string selectedFileName = ""; + static bool logImports; ImGui::Checkbox("Log imports", &logImports); Widgets::ShowTooltip("Logs imports line by line in MapEditor.log.\nEnable this if the game crashes while importing\nand you want to know the error line.\n\nNote: Has performance impact!"); if (ImGui::Button("Import IPL", Utils::GetSize(2))) { FileMgr::ImportIPL(selectedFileName.c_str(), logImports); - m_bShowPopup = false; + Interface::m_PopupMenu.m_bShow = false; } ImGui::SameLine(); if (ImGui::Button("Clear placed objects", Utils::GetSize(2))) { - for (auto &pObj : ObjManager::m_pVecEntities) + for (auto &pObj : ObjManager::m_pPlacedObjs) { pObj->Remove(); } ObjManager::m_pSelected = nullptr; - ObjManager::m_pVecEntities.clear(); + ObjManager::m_pPlacedObjs.clear(); CHud::SetHelpMessage("Current objects cleared", false, false, false); } ImGui::Spacing(); @@ -131,7 +92,7 @@ void Interface::ImportMenu() } } -void Interface::ExportMenu() +void ExportPopup() { ImGui::Spacing(); ImGui::Text("Notes,"); @@ -144,7 +105,7 @@ void Interface::ExportMenu() ImGui::InputTextWithHint("File name##Buffer", "ProjectProps.ipl", buffer, ARRAYSIZE(buffer)); if (ImGui::IsItemActive()) { - m_bIsInputLocked = true; + Interface::m_bInputLocked = true; } ImGui::Spacing(); if (ImGui::Button("Export IPL", Utils::GetSize())) @@ -154,104 +115,66 @@ void Interface::ExportMenu() strcpy(buffer, "ProjectProps.ipl"); } FileMgr::ExportIPL(buffer); - m_bShowPopup = false; + Interface::m_PopupMenu.m_bShow = false; } } -void Interface::WelcomeMenu() + +void UpdateFoundPopup() { - ImGui::Spacing(); - if (ImGui::Button("Discord", ImVec2(Utils::GetSize(3)))) + if (ImGui::Button("Discord server", ImVec2(Utils::GetSize(2)))) { ShellExecute(NULL, "open", DISCORD_INVITE, NULL, NULL, SW_SHOWNORMAL); } ImGui::SameLine(); - if (ImGui::Button("Controls", Utils::GetSize(3))) - { - m_popupTitle = "Controls"; - m_pPopupFunc = EditorControls; - } - ImGui::SameLine(); - if (ImGui::Button("About page", Utils::GetSize(3))) + if (ImGui::Button("Downlod page", Utils::GetSize(2))) { - m_popupTitle = "About"; - m_pPopupFunc = AboutEditorMenu; + ShellExecute(NULL, "open", "https://github.com/user-grinch/Map-Editor/", NULL, NULL, SW_SHOWNORMAL); } - ImGui::Dummy(ImVec2(0, 20)); - if (ImGui::BeginChild("WelcomeScreen")) - { - Widgets::CenterdText("Welcome to Map Editor"); - Widgets::CenterdText(std::string("v") + EDITOR_VERSION); - Widgets::CenterdText(std::string("(") + BUILD_NUMBER + ")"); - ImGui::Dummy(ImVec2(0, 10)); + ImGui::Spacing(); + Widgets::CenterdText("Current version: " EDITOR_VERSION); + Widgets::CenterdText("Latest version: " + Updater::GetUpdateVersion()); + ImGui::Dummy(ImVec2(0,20)); - ImGui::TextWrapped("Click on the `Controls` button to get started. If you have suggestions let me know on Discord."); - ImGui::Dummy(ImVec2(0, 10)); - ImGui::TextWrapped("Before you go ahead and spam me with bug reports, keep in mind this is a alpha release, not even beta! Do some reasearch if the bug was already reported or not. Try on a FRESH GAME first. I'm NOT fixing bugs with X camera mod or Y graphics mod."); - ImGui::Dummy(ImVec2(0, 10)); - ImGui::TextWrapped("Partial modloader support has been implemented. Create a folder called 'MapEditor' in modloader folder and put your map mods there."); - ImGui::Dummy(ImVec2(0, 30)); - ImGui::Text("Please note,"); - ImGui::TextWrapped("1. You are NOT allowed to reupload this modifiction."); - ImGui::TextWrapped("2. If you're posting it somewhere, link to the official source."); - ImGui::TextWrapped("3. This can be ignored by getting permission from the author."); - ImGui::Dummy(ImVec2(0, 10)); - Widgets::CenterdText("Copyright Grinch_ 2021-2022. All rights reserved"); - ImGui::EndChild(); - } + ImGui::TextWrapped("A newer version of Map Editor is available with,"); + ImGui::Text("1. New features\n2. Bug fixes\n3. Improvements"); + ImGui::Spacing(); + ImGui::TextWrapped("Click on the `Download page` button and follow the instructions there to update."); } -void Interface::QuickObjectCreateMenu() +void AboutEditorPopup() { - static int modelId = DEFAULT_MODEL_ID; - static std::string modelName = ObjManager::FindNameFromModel(modelId); - - ImGui::Text("Name: %s", modelName.c_str()); - if (ImGui::InputInt("Model", &modelId)) - { - modelName = ObjManager::FindNameFromModel(modelId); - } - if (KeyPressed(VK_RETURN)) - { - goto create_object; - } - - ImGui::Spacing(); - if (ImGui::Button("Create", Utils::GetSize(2))) + if (ImGui::Button("Discord server", ImVec2(Utils::GetSize(2)))) { -create_object: - int hObj; - Command(modelId); - Command(); - Command(modelId, Viewport::m_vecWorldPos.x, - Viewport::m_vecWorldPos.y, Viewport::m_vecWorldPos.z, &hObj); - Command(modelId); - - CObject *pEntity = CPools::GetObject(hObj); - auto &data = ObjManager::m_objData.Get(pEntity); - data.m_modelName = modelName; - - ObjManager::m_pVecEntities.push_back(pEntity); - ObjManager::m_pSelected = pEntity; - - Interface::m_bShowPopup = false; + ShellExecute(NULL, "open", DISCORD_INVITE, NULL, NULL, SW_SHOWNORMAL); } ImGui::SameLine(); - if (ImGui::Button("Find models", Utils::GetSize(2))) + if (ImGui::Button("Check update", Utils::GetSize(2))) { - ShellExecute(NULL, "open", "https://dev.prineside.com/en/gtasa_samp_model_id/", NULL, NULL, SW_SHOWNORMAL); + Updater::CheckUpdate(); } ImGui::Spacing(); - if (ImGui::Button("Open object browser", Utils::GetSize())) - { - Viewport::m_eViewportMode = OBJECT_VIEW_MODE; - Interface::m_bShowPopup = false; - Interface::m_bShowPopup = false; - Interface::Browser::m_bShowNextFrame = true; - } + ImGui::Columns(2, NULL, false); + ImGui::Text(EDITOR_NAME); + ImGui::Text("Version: %s", EDITOR_VERSION); + ImGui::Dummy(ImVec2(0.0f, 20.0f)); + ImGui::Text("Credits:"); + ImGui::Text("1. Plugin SDK"); + ImGui::Text("3. ImGui"); + ImGui::NextColumn(); + ImGui::Text("Author: Grinch_"); + ImGui::Text("Build: %s", BUILD_NUMBER); + ImGui::Dummy(ImVec2(0.0f, 20.0f)); + ImGui::Text("-"); + ImGui::Text("2. MTA"); + ImGui::Columns(1); + ImGui::Dummy(ImVec2(0.0f, 20.0f)); + ImGui::TextWrapped("You are not allowed to reupload this modification without explicit permission from the author! You have to link to the official source."); + ImGui::Dummy(ImVec2(0.0f, 30.0f)); + Widgets::CenterdText("Copyright Grinch_ 2021-2022. All rights reserved"); } -void Interface::EditorControls() +void ControlsPopup() { if (ImGui::BeginChild("Controls")) { @@ -423,48 +346,116 @@ void Interface::EditorControls() } } -void Interface::AboutEditorMenu() +void WelcomePopup() { - if (ImGui::Button("Discord server", ImVec2(Utils::GetSize(2)))) + ImGui::Spacing(); + if (ImGui::Button("Discord", ImVec2(Utils::GetSize(3)))) { ShellExecute(NULL, "open", DISCORD_INVITE, NULL, NULL, SW_SHOWNORMAL); } ImGui::SameLine(); - if (ImGui::Button("Check update", Utils::GetSize(2))) + if (ImGui::Button("Controls", Utils::GetSize(3))) { - Updater::CheckUpdate(); + Interface::m_PopupMenu.m_Title = "Controls"; + Interface::m_PopupMenu.m_pFunc = ControlsPopup; + } + ImGui::SameLine(); + if (ImGui::Button("About page", Utils::GetSize(3))) + { + Interface::m_PopupMenu.m_Title = "About"; + Interface::m_PopupMenu.m_pFunc = AboutEditorPopup; + } + ImGui::Dummy(ImVec2(0, 20)); + if (ImGui::BeginChild("WelcomeScreen")) + { + Widgets::CenterdText("Welcome to Map Editor"); + Widgets::CenterdText(std::string("v") + EDITOR_VERSION); + Widgets::CenterdText(std::string("(") + BUILD_NUMBER + ")"); + ImGui::Dummy(ImVec2(0, 10)); + + ImGui::TextWrapped("Click on the `Controls` button to get started. If you have suggestions let me know on Discord."); + ImGui::Dummy(ImVec2(0, 10)); + ImGui::TextWrapped("Before you go ahead and spam me with bug reports, keep in mind this is a alpha release, not even beta! Do some reasearch if the bug was already reported or not. Try on a FRESH GAME first. I'm NOT fixing bugs with X camera mod or Y graphics mod."); + ImGui::Dummy(ImVec2(0, 10)); + ImGui::TextWrapped("Partial modloader support has been implemented. Create a folder called 'MapEditor' in modloader folder and put your map mods there."); + ImGui::Dummy(ImVec2(0, 30)); + ImGui::Text("Please note,"); + ImGui::TextWrapped("1. You are NOT allowed to reupload this modifiction."); + ImGui::TextWrapped("2. If you're posting it somewhere, link to the official source."); + ImGui::TextWrapped("3. This can be ignored by getting permission from the author."); + ImGui::Dummy(ImVec2(0, 10)); + Widgets::CenterdText("Copyright Grinch_ 2021-2022. All rights reserved"); + ImGui::EndChild(); + } +} + + +void Interface::Init() +{ + m_bAutoSave = gConfig.GetValue("editor.autoSave", true); + m_bAutoTpToLoc = gConfig.GetValue("editor.autoTpToLoc", false); + m_bAutoSnapToGround = gConfig.GetValue("editor.autoSnap", true); + m_bDrawAxisLines = gConfig.GetValue("editor.drawAxisLines", true); + m_bDrawBoundingBox = gConfig.GetValue("editor.drawBoundingBox", true); + m_bShowFPS = gConfig.GetValue("editor.showFPS", false); + m_bShowHoverMenu = gConfig.GetValue("editor.showHoverMenu", true); + m_bShowSidepanel = gConfig.GetValue("editor.showInfoMenu", true); + m_bWelcomeShown = gConfig.GetValue("editor.welcomeDisplayed", false); + + if (!m_bWelcomeShown) + { + m_PopupMenu.m_bShow = true; + m_PopupMenu.m_Title = "Map Editor"; + m_PopupMenu.m_pFunc = WelcomePopup; + m_bWelcomeShown = true; + gConfig.SetValue("editor.welcomeDisplayed", m_bWelcomeShown); + } +} + +void Interface::Process() +{ + if (m_bShowGUI) + { + DrawMainMenuBar(); + DrawPopupMenu(); + DrawSidepanel(); + } +} + +void Interface::DrawContextMenu() +{ + if (m_ContextMenu.m_bShow) + { + if (ImGui::BeginPopupContextWindow("ContextMenu")) + { + if (m_ContextMenu.m_Key != "") + { + ImGui::Text(m_ContextMenu.m_Key.c_str()); + ImGui::Separator(); + } + + m_ContextMenu.m_pFunc(m_ContextMenu.m_Root, m_ContextMenu.m_Key, m_ContextMenu.m_Val); + + if (ImGui::MenuItem("Close")) + { + m_ContextMenu.m_bShow = false; + } + + ImGui::EndPopup(); + } } - ImGui::Spacing(); - ImGui::Columns(2, NULL, false); - ImGui::Text(EDITOR_NAME); - ImGui::Text("Version: %s", EDITOR_VERSION); - ImGui::Dummy(ImVec2(0.0f, 20.0f)); - ImGui::Text("Credits:"); - ImGui::Text("1. Plugin SDK"); - ImGui::Text("3. ImGui"); - ImGui::NextColumn(); - ImGui::Text("Author: Grinch_"); - ImGui::Text("Build: %s", BUILD_NUMBER); - ImGui::Dummy(ImVec2(0.0f, 20.0f)); - ImGui::Text("-"); - ImGui::Text("2. MTA"); - ImGui::Columns(1); - ImGui::Dummy(ImVec2(0.0f, 20.0f)); - ImGui::TextWrapped("You are not allowed to reupload this modification without explicit permission from the author! You have to link to the official source."); - ImGui::Dummy(ImVec2(0.0f, 30.0f)); - Widgets::CenterdText("Copyright Grinch_ 2021-2022. All rights reserved"); } void Interface::DrawPopupMenu() { if (Updater::IsUpdateAvailable()) { - m_bShowPopup = true; - m_popupTitle = "Update available!"; - m_pPopupFunc = UpdateFoundMenu; + m_PopupMenu.m_bShow = true; + m_PopupMenu.m_Title = "Update available!"; + m_PopupMenu.m_pFunc = UpdateFoundPopup; } - if (!m_bShowPopup) + if (!m_PopupMenu.m_bShow) { return; } @@ -475,20 +466,20 @@ void Interface::DrawPopupMenu() ImGui::SetNextWindowSizeConstraints(ImVec2(screen::GetScreenWidth()/4, screen::GetScreenHeight()/1.95), // manually tested ImVec2(screen::GetScreenWidth()/4, screen::GetScreenHeight()/1.95)); - ImGui::SetNextWindowPos(ImVec2((Viewport::m_fViewportSize.x - prevSize.x)/2, - (Viewport::m_fViewportSize.y - prevSize.y)/2), ImGuiCond_Always); - if (ImGui::Begin(m_popupTitle.c_str(), &m_bShowPopup, flags)) + ImVec2 size = Viewport::GetSize(); + ImGui::SetNextWindowPos(ImVec2((size.x - prevSize.x)/2, (size.y - prevSize.y)/2), ImGuiCond_Always); + if (ImGui::Begin(m_PopupMenu.m_Title.c_str(), &m_PopupMenu.m_bShow, flags)) { - if (m_pPopupFunc) + if (m_PopupMenu.m_pFunc) { - m_pPopupFunc(); + m_PopupMenu.m_pFunc(); } prevSize = ImGui::GetWindowSize(); ImGui::End(); } // Reset state on window close - if (Updater::IsUpdateAvailable() && !m_pPopupFunc) + if (Updater::IsUpdateAvailable() && !m_PopupMenu.m_pFunc) { Updater::ResetUpdaterState(); } @@ -502,7 +493,7 @@ void Interface::DrawMainMenuBar() ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); - if(Viewport::m_eViewportMode == EDIT_MODE) + if(Viewport::m_eState == eViewportState::Edit) { ImGui::Text("Edit Mode"); } @@ -513,8 +504,8 @@ void Interface::DrawMainMenuBar() ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); - - if (Interface::m_bFramerate) + + if (Interface::m_bShowFPS) { ImGui::Text("Framerate: %0.1f", ImGui::GetIO().Framerate); ImGui::Spacing(); @@ -526,15 +517,15 @@ void Interface::DrawMainMenuBar() { if (ImGui::MenuItem("Export")) { - m_bShowPopup = true; - m_popupTitle = "Export to IPL"; - m_pPopupFunc = ExportMenu; + m_PopupMenu.m_bShow = true; + m_PopupMenu.m_Title = "Export to IPL"; + m_PopupMenu.m_pFunc = ExportPopup; } if (ImGui::MenuItem("Import")) { - m_bShowPopup = true; - m_popupTitle = "Import from IPL"; - m_pPopupFunc = ImportMenu; + m_PopupMenu.m_bShow = true; + m_PopupMenu.m_Title = "Import from IPL"; + m_PopupMenu.m_pFunc = ImportPopup; } ImGui::EndMenu(); } @@ -565,7 +556,7 @@ void Interface::DrawMainMenuBar() { patch::SetRaw(0x52CF10, (char*)"\x56\x8B", 2); } - } + } if (ImGui::MenuItem("No pedstrain", NULL, &bNoPeds)) { if (bNoPeds) @@ -661,25 +652,25 @@ void Interface::DrawMainMenuBar() } if (ImGui::BeginMenu("View")) { - if (ImGui::MenuItem("Axis lines", NULL, &ObjManager::m_bDrawAxisLines)) + if (ImGui::MenuItem("Axis lines", NULL, &m_bDrawAxisLines)) { - gConfig.SetValue("editor.drawAxisLines", ObjManager::m_bDrawAxisLines); + gConfig.SetValue("editor.drawAxisLines", m_bDrawAxisLines); } - if (ImGui::MenuItem("Bounding box", NULL, &ObjManager::m_bDrawBoundingBox)) + if (ImGui::MenuItem("Bounding box", NULL, &m_bDrawBoundingBox)) { - gConfig.SetValue("editor.drawBoundingBox", ObjManager::m_bDrawBoundingBox); + gConfig.SetValue("editor.drawBoundingBox", m_bDrawBoundingBox); } - if (ImGui::MenuItem("Framerate", NULL, &Interface::m_bFramerate)) + if (ImGui::MenuItem("Framerate", NULL, &m_bShowFPS)) { - gConfig.SetValue("editor.showFPS", Interface::m_bFramerate); + gConfig.SetValue("editor.showFPS", m_bShowFPS); } - if (ImGui::MenuItem("Hover tooltip", NULL, &Viewport::m_bShowHoverMenu)) + if (ImGui::MenuItem("Hover tooltip", NULL, &m_bShowHoverMenu)) { - gConfig.SetValue("editor.showHoverMenu", Viewport::m_bShowHoverMenu); + gConfig.SetValue("editor.showHoverMenu", m_bShowHoverMenu); } - if (ImGui::MenuItem("Info panel", NULL, &m_bShowInfoMenu)) + if (ImGui::MenuItem("Info panel", NULL, &m_bShowSidepanel)) { - gConfig.SetValue("editor.showInfoMenu", m_bShowInfoMenu); + gConfig.SetValue("editor.showInfoMenu", m_bShowSidepanel); } ImGui::EndMenu(); } @@ -687,22 +678,22 @@ void Interface::DrawMainMenuBar() { if (ImGui::MenuItem("Welcome screen", NULL)) { - m_bShowPopup = true; - m_popupTitle = "Map Editor"; - m_pPopupFunc = WelcomeMenu; + m_PopupMenu.m_bShow = true; + m_PopupMenu.m_Title = "Map Editor"; + m_PopupMenu.m_pFunc = WelcomePopup; } if (ImGui::MenuItem("Controls", NULL)) { - m_bShowPopup = true; - m_popupTitle = "Map Editor Controls"; - m_pPopupFunc = EditorControls; + m_PopupMenu.m_bShow = true; + m_PopupMenu.m_Title = "Map Editor Controls"; + m_PopupMenu.m_pFunc = ControlsPopup; } if (ImGui::MenuItem("About Map Editor", NULL)) { - m_bShowPopup = true; - m_popupTitle = "About"; - m_pPopupFunc = AboutEditorMenu; + m_PopupMenu.m_bShow = true; + m_PopupMenu.m_Title = "About"; + m_PopupMenu.m_pFunc = AboutEditorPopup; } ImGui::EndMenu(); } @@ -710,9 +701,9 @@ void Interface::DrawMainMenuBar() } } -void Interface::DrawInfoMenu() +void Interface::DrawSidepanel() { - if (!m_bShowInfoMenu) + if (!m_bShowSidepanel) { return; } @@ -853,13 +844,13 @@ void Interface::DrawInfoMenu() if (ImGui::CollapsingHeader("Random rotations")) { - ImGui::Checkbox("Enable", &ObjManager::bRandomRot); + ImGui::Checkbox("Enable", &Interface::m_bRandomRot); Widgets::ShowTooltip("Places objects with random rotations in given range"); ImGui::Spacing(); - ImGui::InputFloat2("Rot X##RR", ObjManager::randomRotX); - ImGui::InputFloat2("Rot Y##RR", ObjManager::randomRotY); - ImGui::InputFloat2("Rot Z##RR", ObjManager::randomRotZ); + ImGui::InputFloat2("Rot X##RR", &Interface::m_RandomRotX[0]); + ImGui::InputFloat2("Rot Y##RR", &Interface::m_RandomRotY[0]); + ImGui::InputFloat2("Rot Z##RR", &Interface::m_RandomRotZ[0]); ImGui::Spacing(); ImGui::Separator(); @@ -884,19 +875,19 @@ void Interface::DrawInfoMenu() Viewport::SetCameraPosn(pos); } ImGui::Spacing(); - if (ImGui::SliderFloat("Zoom", &Viewport::m_fFOV, 10.0f, 115.0f)) + if (ImGui::SliderFloat("Zoom", &Viewport::Viewport::m_fFOV, 10.0f, 115.0f)) { - TheCamera.LerpFOV(TheCamera.FindCamFOV(), Viewport::m_fFOV, 250, true); + TheCamera.LerpFOV(TheCamera.FindCamFOV(), Viewport::Viewport::m_fFOV, 250, true); Command(true); } - if (ImGui::SliderInt("Move speed", &Viewport::m_nMul, 1, 10)) + if (ImGui::SliderInt("Move speed", &Viewport::m_nMoveSpeed, 1, 10)) { - gConfig.SetValue("editor.moveSpeed", Viewport::m_nMul); + gConfig.SetValue("editor.moveSpeed", Viewport::m_nMoveSpeed); } ImGui::Spacing(); ImGui::Separator(); } - + ImGui::EndChild(); } ImGui::EndTabItem(); @@ -915,7 +906,7 @@ void Interface::DrawInfoMenu() static ImGuiTextFilter filter; ImGui::Spacing(); - if (ObjManager::m_pVecEntities.size() == 0) + if (ObjManager::m_pPlacedObjs.size() == 0) { ImGui::TextWrapped("You haven't placed any objects yet!"); } @@ -923,15 +914,15 @@ void Interface::DrawInfoMenu() { if (ImGui::Button("Remove All", Utils::GetSize(bShowAnyway ? 2 : 1))) { - for (auto &pObj : ObjManager::m_pVecEntities) + for (auto &pObj : ObjManager::m_pPlacedObjs) { pObj->Remove(); } ObjManager::m_pSelected = nullptr; - ObjManager::m_pVecEntities.clear(); + ObjManager::m_pPlacedObjs.clear(); } - if (ObjManager::m_pVecEntities.size() > 500) + if (ObjManager::m_pPlacedObjs.size() > 500) { if (bShowAnyway) { @@ -954,19 +945,19 @@ void Interface::DrawInfoMenu() } ImGui::Spacing(); - if (ObjManager::m_pVecEntities.size() < 500 || bShowAnyway) + if (ObjManager::m_pPlacedObjs.size() < 500 || bShowAnyway) { filter.Draw("Search"); if (ImGui::IsItemActive()) { - m_bIsInputLocked = true; + m_bInputLocked = true; } ImGui::Spacing(); if (ImGui::BeginChild("Objects child")) { - for (size_t i = 0; i < ObjManager::m_pVecEntities.size(); i++) + for (size_t i = 0; i < ObjManager::m_pPlacedObjs.size(); i++) { - CObject *pObj = ObjManager::m_pVecEntities[i]; + CObject *pObj = ObjManager::m_pPlacedObjs[i]; auto &data = ObjManager::m_objData.Get(pObj); if (data.m_modelName == "") @@ -1005,17 +996,17 @@ void Interface::DrawInfoMenu() if(ImGui::BeginTabItem("Favourites")) { ImGui::Spacing(); - Widgets::DrawJSON(m_favData, - [](std::string& root, std::string& key, std::string& value) + Widgets::DrawJSON(m_favData, m_ContextMenu, + [](std::string& root, std::string& key, std::string& value) { - Viewport::COPY_MODEL::m_nModel = std::stoi(value); + ObjManager::ClipBoard::m_nModel = std::stoi(value); CHud::SetHelpMessage("Object Copied", false, false, false); }, [](std::string& root, std::string& key, std::string& value) { if (ImGui::MenuItem("Copy")) { - Viewport::COPY_MODEL::m_nModel = std::stoi(value); + ObjManager::ClipBoard::m_nModel = std::stoi(value); CHud::SetHelpMessage("Object Copied", false, false, false); } if (ImGui::MenuItem("Remove")) @@ -1050,12 +1041,12 @@ void Interface::DrawInfoMenu() ImGui::InputTextWithHint("Location", "Groove Street", m_nLocationBuffer, IM_ARRAYSIZE(m_nLocationBuffer)); if (ImGui::IsItemActive()) { - m_bIsInputLocked = true; + m_bInputLocked = true; } ImGui::InputTextWithHint("Coordinates", "x, y, z", m_nInputBuffer, IM_ARRAYSIZE(m_nInputBuffer)); if (ImGui::IsItemActive()) { - m_bIsInputLocked = true; + m_bInputLocked = true; } ImGui::Spacing(); if (ImGui::Button("Insert current coord", Utils::GetSize(2))) @@ -1071,7 +1062,7 @@ void Interface::DrawInfoMenu() } ImGui::Spacing(); } - Widgets::DrawJSON(m_locData, + Widgets::DrawJSON(m_locData, m_ContextMenu, [](std::string& root, std::string& key, std::string& loc) { try @@ -1104,16 +1095,15 @@ void Interface::DrawInfoMenu() } } }); - ProcessContextMenu(); ImGui::EndTabItem(); } //---------------------------------------------------- // Browser if(ImGui::BeginTabItem("Browser", NULL, - Browser::m_bShowNextFrame ? ImGuiTabItemFlags_SetSelected : NULL)) + Viewport::Browser::m_bShowNextFrame ? ImGuiTabItemFlags_SetSelected : NULL)) { - Browser::m_bShowNextFrame = false; - Browser::m_bShown = true; + Viewport::Browser::m_bShowNextFrame = false; + Viewport::Browser::m_bShown = true; static ImGuiTextFilter IplFilter; static ImGuiTextFilter totalFilter; static std::vector iplList; @@ -1130,32 +1120,27 @@ void Interface::DrawInfoMenu() } static std::string selected = iplList[0]; ImGui::Spacing(); - ImGui::Text("Total IDEs loaded: %d", iplCount); - ImGui::Text("Total models loaded: %d", ObjManager::totalIDELinesLoaded); + ImGui::Text("Total IPLs loaded: %d", iplCount); + ImGui::Text("Total models loaded: %d", ObjManager::m_nTotalIDELine); ImGui::Spacing(); - ImGui::Checkbox("Auto rotate", &Viewport::m_bObjBrowserAutoRot); - ImGui::SliderFloat("Render scale", &Viewport::m_nRenderScale, 0.0f, 5.0f); + ImGui::Checkbox("Auto rotate", &Viewport::Browser::m_bAutoRot); + ImGui::SliderFloat("Render scale", &Viewport::Browser::m_fScale, 0.0f, 5.0f); ImGui::Spacing(); if (ImGui::Button("Copy render object", Utils::GetSize())) { - Viewport::COPY_MODEL::m_nModel = Browser::GetSelected(); + ObjManager::ClipBoard::m_nModel = Viewport::Browser::GetSelected(); CHud::SetHelpMessage("Object Copied", false, false, false); } ImGui::Spacing(); if(ImGui::BeginTabBar("Broweser Tab", ImGuiTabBarFlags_NoTooltip)) { - if (ImGui::IsMouseClicked(1)) - { - m_contextMenu.function = nullptr; - } - if(ImGui::BeginTabItem("IPL search")) { ImGui::Spacing(); IplFilter.Draw("Search"); if(ImGui::IsItemActive()) { - m_bIsInputLocked = true; + m_bInputLocked = true; } if (Widgets::ListBoxStr("IDE", iplList, selected)) @@ -1179,18 +1164,17 @@ void Interface::DrawInfoMenu() { if (ImGui::MenuItem(text.c_str())) { - Interface::Browser::SetSelected(data.first); + Viewport::Browser::SetSelected(data.first); } if (ImGui::IsItemClicked(1)) { - Interface::m_contextMenu.function = SearchContextMenu; - Interface::m_contextMenu.rootKey = ""; - Interface::m_contextMenu.key = data.second; - Interface::m_contextMenu.value = std::to_string(data.first); + m_ContextMenu.m_pFunc = ContextMenu_Search; + m_ContextMenu.m_Key = data.second; + m_ContextMenu.m_Val = std::to_string(data.first); } } } - ProcessContextMenu(); + DrawContextMenu(); ImGui::EndChild(); } ImGui::EndTabItem(); @@ -1204,7 +1188,7 @@ void Interface::DrawInfoMenu() totalFilter.Draw("##Search"); if(ImGui::IsItemActive()) { - m_bIsInputLocked = true; + m_bInputLocked = true; } if (KeyPressed(VK_RETURN)) { @@ -1236,17 +1220,16 @@ void Interface::DrawInfoMenu() std::string text = std::to_string(data.first) + " - " + data.second; if (ImGui::MenuItem(text.c_str())) { - Interface::Browser::SetSelected(data.first); + Viewport::Browser::SetSelected(data.first); } if (ImGui::IsItemClicked(1)) { - Interface::m_contextMenu.function = SearchContextMenu; - Interface::m_contextMenu.rootKey = ""; - Interface::m_contextMenu.key = data.second; - Interface::m_contextMenu.value = std::to_string(data.first); + m_ContextMenu.m_pFunc = ContextMenu_Search; + m_ContextMenu.m_Key = data.second; + m_ContextMenu.m_Val = std::to_string(data.first); } } - ProcessContextMenu(); + DrawContextMenu(); ImGui::EndChild(); } ImGui::EndTabItem(); @@ -1254,16 +1237,16 @@ void Interface::DrawInfoMenu() if(ImGui::BeginTabItem("Favourites")) { ImGui::Spacing(); - Widgets::DrawJSON(m_favData, + Widgets::DrawJSON(m_favData, m_ContextMenu, [](std::string& root, std::string& key, std::string& model) { - Interface::Browser::SetSelected((size_t)std::stoi(model)); + Viewport::Viewport::Browser::SetSelected((size_t)std::stoi(model)); }, [](std::string& root, std::string& key, std::string& value) { if (ImGui::MenuItem("Copy")) { - Viewport::COPY_MODEL::m_nModel = std::stoi(value); + ObjManager::ClipBoard::m_nModel = std::stoi(value); CHud::SetHelpMessage("Object Copied", false, false, false); } if (ImGui::MenuItem("Remove")) @@ -1280,33 +1263,13 @@ void Interface::DrawInfoMenu() } else { - Browser::m_bShowNextFrame = false; + Viewport::Browser::m_bShown = false; } // --------------------------------------------------- ImGui::EndTabBar(); } ImGui::End(); } + DrawContextMenu(); } -void Interface::UpdateFoundMenu() -{ - if (ImGui::Button("Discord server", ImVec2(Utils::GetSize(2)))) - { - ShellExecute(NULL, "open", DISCORD_INVITE, NULL, NULL, SW_SHOWNORMAL); - } - ImGui::SameLine(); - if (ImGui::Button("Downlod page", Utils::GetSize(2))) - { - ShellExecute(NULL, "open", "https://github.com/user-grinch/Map-Editor/", NULL, NULL, SW_SHOWNORMAL); - } - ImGui::Spacing(); - Widgets::CenterdText("Current version: " EDITOR_VERSION_NUMBER); - Widgets::CenterdText("Latest version: " + Updater::GetUpdateVersion()); - ImGui::Dummy(ImVec2(0,20)); - - ImGui::TextWrapped("A newer version of Map Editor is available with,"); - ImGui::Text("1. New features\n2. Bug fixes\n3. Improvements"); - ImGui::Spacing(); - ImGui::TextWrapped("Click on the `Download page` button and follow the instructions there to update."); -} \ No newline at end of file diff --git a/src/interface.h b/src/interface.h index c70569b..7cd3d70 100644 --- a/src/interface.h +++ b/src/interface.h @@ -1,66 +1,53 @@ #pragma once #include "pch.h" -#define DEFAULT_MODEL_ID 620 - class Interface { private: static inline ResourceStore m_locData{ "locations", eResourceType::TYPE_TEXT }; - struct ContextMenuData - { - std::function function; - std::string key; - std::string rootKey; - std::string value; - }; - static inline bool logImports; + + // Draws the top black bar contains menu options + static void DrawMainMenuBar(); + + // Draws the object specific right side pnael + static void DrawSidepanel(); + + // Draws the popups at the center of the screen + static void DrawPopupMenu(); public: static inline bool m_bAutoSave = true; - static inline bool m_bAutoTpToLoc = false; + static inline bool m_bAutoTpToLoc; static inline bool m_bAutoSnapToGround; - static inline bool m_bFramerate = false; - static inline bool m_bWelcomeScreenDisplayed; - static inline bool m_bShowInfoMenu; // right hand menu - static inline ContextMenuData m_contextMenu; + static inline bool m_bDrawAxisLines; + static inline bool m_bDrawBoundingBox; // bouding box around selected objects + static inline bool m_bInputLocked; + static inline bool m_bShowFPS; + static inline bool m_bShowGUI = true; + static inline bool m_bShowHoverMenu; // object hoverer tooltip ( shows model id & model name ) + static inline bool m_bShowSidepanel; + static inline bool m_bWelcomeShown; + static inline bool m_bRandomRot; // places objects randomly + static inline float m_RandomRotX[2], m_RandomRotY[2], m_RandomRotZ[2]; // min max rotations + + static inline ContextMenu m_ContextMenu; // right click context menu + static inline PopupMenu m_PopupMenu; // center screen popup menus static inline ResourceStore m_favData{ "favourites", eResourceType::TYPE_TEXT }; - static inline bool m_bShowPopup; - static inline std::string m_popupTitle; - static inline std::function m_pPopupFunc; - static inline bool m_bIsInputLocked; // Input locked by some imgui widgets - - static struct Browser - { - private: - static inline size_t m_nSelected = NULL; - - public: - static inline bool m_bShowNextFrame; - static inline bool m_bShown; - - static size_t GetSelected(); - static void SetSelected(int modelId); - }; + Interface() = delete; Interface(Interface&) = delete; + + // Initiazes stuff for MapEditor open + static void Init(); - static void DrawMainMenuBar(); - static void DrawInfoMenu(); - static void DrawPopupMenu(); - static void ImportMenu(); - static void ExportMenu(); - static void SettingsMenu(); + // Needs to be called each frame + static void Process(); - // Custom popup menu codes - static void QuickObjectCreateMenu(); - static void AboutEditorMenu(); - static void WelcomeMenu(); - static void EditorControls(); - static void UpdateFoundMenu(); + // Cleans stuff on MapEditor exit + static void Cleanup(); - static void ProcessContextMenu(); - static void SearchContextMenu(std::string& root, std::string& key, std::string& value); + // process right click context menu + static void DrawContextMenu(); }; diff --git a/src/objmanager.cpp b/src/objmanager.cpp index d92c3bb..2f3db99 100644 --- a/src/objmanager.cpp +++ b/src/objmanager.cpp @@ -5,6 +5,7 @@ #include #include #include "filemgr.h" +#include "interface.h" /* * Part of the source is taken from DrawColsSA by Sergeanur @@ -28,7 +29,7 @@ float ObjManager::GetBoundingBoxGroundZ(CObject *pObj) CVector max = pColModel->m_boundBox.m_vecMax; CVector workVec = min; - + workVec.x = max.x; workVec.y = max.y; CVector ground = *matrix * workVec; @@ -36,95 +37,19 @@ float ObjManager::GetBoundingBoxGroundZ(CObject *pObj) return ground.z; } -void ObjManager::DrawColModel(const CMatrix& matrix, const CColModel& colModel) -{ - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)true); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)true); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); - - if (m_bDrawBoundingBox) - { - CVector min = colModel.m_boundBox.m_vecMin; - CVector max = colModel.m_boundBox.m_vecMax; - - CVector workVec = min; - CVector v1 = matrix * workVec; - - workVec.z = max.z; - CVector v2 = matrix * workVec; - - workVec = min; - workVec.x = max.x; - CVector v3 = matrix * workVec; - - workVec = min; - workVec.y = max.y; - CVector v4 = matrix * workVec; - - workVec = min; - workVec.y = max.y; - workVec.z = max.z; - CVector v5 = matrix * workVec; - - workVec = min; - workVec.x = max.x; - workVec.z = max.z; - CVector v6 = matrix * workVec; - - workVec = min; - workVec.x = max.x; - workVec.y = max.y; - CVector v7 = matrix * workVec; - - workVec = max; - CVector v8 = matrix * workVec; - - RenderLineWithClipping(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v1.x, v1.y, v1.z, v3.x, v3.y, v3.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v1.x, v1.y, v1.z, v4.x, v4.y, v4.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v5.x, v5.y, v5.z, v2.x, v2.y, v2.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v5.x, v5.y, v5.z, v8.x, v8.y, v8.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v5.x, v5.y, v5.z, v4.x, v4.y, v4.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v6.x, v6.y, v6.z, v2.x, v2.y, v2.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v6.x, v6.y, v6.z, v8.x, v8.y, v8.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v6.x, v6.y, v6.z, v3.x, v3.y, v3.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v7.x, v7.y, v7.z, v8.x, v8.y, v8.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v7.x, v7.y, v7.z, v3.x, v3.y, v3.z, 0xFFFFFFFF, 0xFFFFFFFF); - RenderLineWithClipping(v7.x, v7.y, v7.z, v4.x, v4.y, v4.z, 0xFFFFFFFF, 0xFFFFFFFF); - } - - if (ObjManager::m_pSelected && m_bDrawAxisLines) - { - static float length = 300.0f; - RwV3d pos = ObjManager::m_pSelected->GetPosition().ToRwV3d(); - - RenderLineWithClipping(pos.x - length, pos.y, pos.z, pos.x + length, pos.y, pos.z, 0xFF0000FF, 0xFF0000FF); - RenderLineWithClipping(pos.x, pos.y - length, pos.z, pos.x, pos.y + length, pos.z, 0x00FF00FF, 0x00FF00FF); - RenderLineWithClipping(pos.x, pos.y, pos.z - length, pos.x, pos.y, pos.z + length, 0x0000FFFF, 0x0000FFFF); - } - - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)false); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)true); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)true); -} - void ObjManager::Init() { // --------------------------------------------------- // optimizations m_vecModelNames.reserve(50); - m_pVecEntities.reserve(100); + m_pPlacedObjs.reserve(100); // --------------------------------------------------- // highlight selected object CdeclEvent , PRIORITY_AFTER, ArgPickNone, void()>renderEffects; renderEffects +=[]() { - HighlightSelectedObj(m_pSelected); + HighlightObject(m_pSelected); }; // --------------------------------------------------- @@ -164,12 +89,12 @@ void ObjManager::Init() float unk; sscanf(str, "%d %s %s %f %d", &model, dffName, txdName, &unk, &unk2); tempVec.push_back({model, std::string(dffName)}); - totalIDELinesLoaded++; + m_nTotalIDELine++; } }; - + // Modloader - // We're only loading from ModLoader/MapEditor directory. + // We're only loading from ModLoader/MapEditor directory. FileMgr::ImportIDE(PLUGIN_PATH((char*)"\\modloader\\MapEditor\\")); // --------------------------------------------------- } @@ -189,9 +114,9 @@ std::string ObjManager::FindNameFromModel(int model) return "dummy"; } -void ObjManager::HighlightSelectedObj(CObject *pObj) +void ObjManager::HighlightObject(CObject *pObj) { - if (!pObj || !Editor::m_bShowEditor) + if (!pObj || !Editor::IsOpen()) { return; } @@ -214,7 +139,78 @@ void ObjManager::HighlightSelectedObj(CObject *pObj) return; } - DrawColModel(*matrix, *pColModel); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)true); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)true); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); + + if (Interface::m_bDrawBoundingBox) + { + CVector min = pColModel->m_boundBox.m_vecMin; + CVector max = pColModel->m_boundBox.m_vecMax; + + CVector workVec = min; + CVector v1 = *matrix * workVec; + + workVec.z = max.z; + CVector v2 = *matrix * workVec; + + workVec = min; + workVec.x = max.x; + CVector v3 = *matrix * workVec; + + workVec = min; + workVec.y = max.y; + CVector v4 = *matrix * workVec; + + workVec = min; + workVec.y = max.y; + workVec.z = max.z; + CVector v5 = *matrix * workVec; + + workVec = min; + workVec.x = max.x; + workVec.z = max.z; + CVector v6 = *matrix * workVec; + + workVec = min; + workVec.x = max.x; + workVec.y = max.y; + CVector v7 = *matrix * workVec; + + workVec = max; + CVector v8 = *matrix * workVec; + + RenderLineWithClipping(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v1.x, v1.y, v1.z, v3.x, v3.y, v3.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v1.x, v1.y, v1.z, v4.x, v4.y, v4.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v5.x, v5.y, v5.z, v2.x, v2.y, v2.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v5.x, v5.y, v5.z, v8.x, v8.y, v8.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v5.x, v5.y, v5.z, v4.x, v4.y, v4.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v6.x, v6.y, v6.z, v2.x, v2.y, v2.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v6.x, v6.y, v6.z, v8.x, v8.y, v8.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v6.x, v6.y, v6.z, v3.x, v3.y, v3.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v7.x, v7.y, v7.z, v8.x, v8.y, v8.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v7.x, v7.y, v7.z, v3.x, v3.y, v3.z, 0xFFFFFFFF, 0xFFFFFFFF); + RenderLineWithClipping(v7.x, v7.y, v7.z, v4.x, v4.y, v4.z, 0xFFFFFFFF, 0xFFFFFFFF); + } + + if (ObjManager::m_pSelected && Interface::m_bDrawAxisLines) + { + static float length = 300.0f; + RwV3d pos = ObjManager::m_pSelected->GetPosition().ToRwV3d(); + + RenderLineWithClipping(pos.x - length, pos.y, pos.z, pos.x + length, pos.y, pos.z, 0xFF0000FF, 0xFF0000FF); + RenderLineWithClipping(pos.x, pos.y - length, pos.z, pos.x, pos.y + length, pos.z, 0x00FF00FF, 0x00FF00FF); + RenderLineWithClipping(pos.x, pos.y, pos.z - length, pos.x, pos.y, pos.z + length, 0x0000FFFF, 0x0000FFFF); + } + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)false); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)true); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)true); } void ObjManager::ExData::SetRotation(CVector rot, bool quat) diff --git a/src/objmanager.h b/src/objmanager.h index a95410e..8b7b634 100644 --- a/src/objmanager.h +++ b/src/objmanager.h @@ -43,36 +43,35 @@ class ObjManager } }; + // Draws bounding box & axis lines to the object + static void HighlightObject(CObject *pObj); + public: /* * Vector for stories entity model names * Format: model = dffName */ static inline std::vector>>> m_vecModelNames; - static inline int totalIDELinesLoaded; - static inline bool m_bDrawBoundingBox; - static inline bool m_bDrawAxisLines; - - /* - * Currently selected entity - * Points to nullptr if none is selected - */ - static inline CObject* m_pSelected; - static inline std::vector m_pVecEntities; // Vector of currently places entities + static inline std::vector m_pPlacedObjs; // Vector of currently placed entities static inline ObjectExtendedData m_objData; // Used to store extended data for each entity - static inline bool bRandomRot; // places objects randomly - static inline float randomRotX[2], randomRotY[2], randomRotZ[2]; // min max rotations + static inline CObject* m_pSelected; // Currently selected entity, Points to nullptr if none is selected + static inline int m_nTotalIDELine; // Total number of ide lines + struct ClipBoard + { + static inline int m_nModel; + static inline CVector m_vecRot; + }; ObjManager() = delete; ObjManager(ObjManager&) = delete; + + // Initializes obj manager stuff static void Init(); - static void HighlightSelectedObj(CObject *pObj); + + // Returns object name from it's model static std::string FindNameFromModel(int model); - static void DrawColModel(const CMatrix& matrix, const CColModel& colModel); - /* - * Returns the bottom Z bounding box coordinates - */ + // Returns the bottom Z bounding box coordinates static float GetBoundingBoxGroundZ(CObject *pObj); }; \ No newline at end of file diff --git a/src/pch.h b/src/pch.h index 35bb035..75e89f0 100644 --- a/src/pch.h +++ b/src/pch.h @@ -42,14 +42,29 @@ #include "../depend/imgui/imgui.h" using namespace plugin; +typedef std::function f_Arg3; -enum eRenderer +enum class eRenderer { - Render_DirectX9, - Render_DirectX11, - Render_Unknown + DirectX9, + DirectX11, + Unknown }; -static eRenderer gRenderer = Render_Unknown; +struct ContextMenu +{ + bool m_bShow; + f_Arg3 m_pFunc; + std::string m_Root, m_Key, m_Val; +}; + +struct PopupMenu +{ + bool m_bShow; + std::string m_Title; + std::function m_pFunc; +}; + +static eRenderer gRenderer = eRenderer::Unknown; extern std::ofstream gLog; extern CJson gConfig; diff --git a/src/version.h b/src/version.h index 9b0c36c..e8cfe40 100644 --- a/src/version.h +++ b/src/version.h @@ -3,4 +3,4 @@ #define EDITOR_VERSION_NUMBER "0.9" #define EDITOR_VERSION EDITOR_VERSION_NUMBER"-alpha" #define BUILD_NUMBER "20220306" -#define EDITOR_TITLE EDITOR_NAME " v" EDITOR_VERSION_NUMBER +#define EDITOR_TITLE EDITOR_NAME " v" EDITOR_VERSION diff --git a/src/viewport.cpp b/src/viewport.cpp index b3735a4..16a9db1 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -12,8 +12,85 @@ #include #include +#define PLAYER_Z_OFFSET 0.0f +#define MOUSE_FACTOR_X 13.0f +#define MOUSE_FACTOR_Y 6.0f + + +// Backups for restoring later on editor exit +static BYTE m_bHudState; +static BYTE m_bRadarState; +static bool m_bNeverWanted; + + + +size_t Viewport::Browser::GetSelected() +{ + return m_nSelectedID; +} + +void Viewport::Browser::SetSelected(int modelId) +{ + /* + Check if the model is available first! + If not set model to -1 + */ + if (modelId > 0 && Command(modelId)) + { + CStreaming::RequestModel(modelId, PRIORITY_REQUEST); + CStreaming::LoadAllRequestedModels(true); + } + + m_nSelectedID = Command(modelId) ? modelId : NULL; +} + +ImVec2 Viewport::GetSize() +{ + return m_fSize; +} + +// Thanks junior & Júlio César +void Viewport::Browser::LoadModel(size_t model, RpClump *&pClump, RpAtomic *&pAtomic, RwFrame *&pFrame) +{ + pClump = nullptr; + pAtomic = nullptr; + pFrame = nullptr; + + if (!Command(model)) + { + CStreaming::RequestModel(model, PRIORITY_REQUEST); + CStreaming::LoadAllRequestedModels(true); + } + + CBaseModelInfo* modelInfo = CModelInfo::GetModelInfo(model); + int rwModelType = modelInfo->GetRwModelType(); + if (rwModelType == 1) + { + RpAtomic *atomic = (RpAtomic *)modelInfo->m_pRwObject; + if (atomic) + { + modelInfo->AddRef(); + + pFrame = RwFrameCreate(); + pAtomic = RpAtomicClone(atomic); + RpAtomicSetFrame(pAtomic, pFrame); + } + } + else + { + pClump = (RpClump*)modelInfo->m_pRwObject; + if (pClump) + { + modelInfo->AddRef(); + pClump = (RpClump *)reinterpret_cast(modelInfo)->CreateInstance(); + } + } +} + void Viewport::Init() { + static CVector tMouse; + CPlayerPed *pPlayer = FindPlayerPed(); int hPlayer = CPools::GetPedRef(pPlayer); CVector pos = pPlayer->GetPosition(); @@ -31,8 +108,8 @@ void Viewport::Init() Command(hPlayer, false); Command(hPlayer, false); - m_fTotalMouse.x = pPlayer->GetHeading(); - m_fTotalMouse.y = 0; + m_fMousePos.x = pPlayer->GetHeading(); + m_fMousePos.y = 0; pos.z -= PLAYER_Z_OFFSET; pPlayer->SetPosn(pos); CWorld::Remove(pPlayer); @@ -45,13 +122,18 @@ void Viewport::Init() Call<0x4396C0>(); } + m_bInitialized = true; +} + +void Viewport::Browser::Process() +{ static bool bEventsInjected; if (!bEventsInjected) { Events::drawingEvent += []() { - if (Interface::Browser::m_bShown) + if (m_bShown) { // ------------------------------------------------- /* @@ -66,66 +148,52 @@ void Viewport::Init() CRect pos(0.0f, 0.0f, width, height); CSprite2d::DrawRect(pos, CRGBA(0, 0, 0, 255)); // ------------------------------------------------- - RenderObjectBrowserModel(); + RenderModel(); } }; bEventsInjected = true; } - m_bInitialized = true; -} - -// Thanks junior & Júlio César -void Viewport::LoadNewClump(int model, RpClump *&pClump, RpAtomic *&pAtomic, RwFrame *&pFrame) -{ - pClump = nullptr; - pAtomic = nullptr; - pFrame = nullptr; - - if (!Command(model)) + // Change object browser values if it's active + if (m_bShown && m_eState == eViewportState::View) { - CStreaming::RequestModel(model, PRIORITY_REQUEST); - CStreaming::LoadAllRequestedModels(true); - } + CVector mouseDelta; + Command(&mouseDelta.x, &mouseDelta.y); + m_fRot.y += mouseDelta.y / MOUSE_FACTOR_Y; - CBaseModelInfo* modelInfo = CModelInfo::GetModelInfo(model); - int rwModelType = modelInfo->GetRwModelType(); - if (rwModelType == 1) - { - RpAtomic *atomic = (RpAtomic *)modelInfo->m_pRwObject; - if (atomic) + if (!m_bAutoRot) { - modelInfo->AddRef(); + m_fRot.x += mouseDelta.x / MOUSE_FACTOR_X; + } - pFrame = RwFrameCreate(); - pAtomic = RpAtomicClone(atomic); - RpAtomicSetFrame(pAtomic, pFrame); + if (CPad::NewMouseControllerState.wheelUp) + { + m_fScale += 0.05f; + m_fScale = m_fScale > 5.0f ? 5.0f : m_fScale; } - } - else - { - pClump = (RpClump*)modelInfo->m_pRwObject; - if (pClump) + + if (CPad::NewMouseControllerState.wheelDown) { - modelInfo->AddRef(); - pClump = (RpClump *)reinterpret_cast(modelInfo)->CreateInstance(); + m_fScale -= 0.05f; + m_fScale = m_fScale < 0.0f ? 0.0f : m_fScale; } + return; } } -void Viewport::RenderObjectBrowserModel() +void Viewport::Browser::RenderModel() { static RpClump *pRpClump; static RwFrame *pRwFrame; static RpAtomic *pRpAtomic; static size_t loadedModelId = NULL; - size_t modelId = Interface::Browser::GetSelected(); + size_t modelId = GetSelected(); if (!modelId) { return; } - + if (loadedModelId != modelId) { CBaseModelInfo *modelInfo = (CBaseModelInfo *)CModelInfo::GetModelInfo(loadedModelId); @@ -134,14 +202,16 @@ void Viewport::RenderObjectBrowserModel() if (pRpAtomic) RpAtomicDestroy(pRpAtomic); if (pRwFrame) RwFrameDestroy(pRwFrame); Command(loadedModelId); - LoadNewClump(modelId, pRpClump, pRpAtomic, pRwFrame); + LoadModel(modelId, pRpClump, pRpAtomic, pRwFrame); loadedModelId = modelId; } static float rotation = 0.0f; static RwRGBAReal AmbientColor = { 1.0f, 1.0f, 1.0f, 1.0f }; static RwV3d pos = { 0.f, 0.05f, 2.0f }; - RwV3d size = { 0.1f*m_nRenderScale, 0.1f*m_nRenderScale,0.1f*m_nRenderScale}; + + float f = m_fScale * 0.1f; + RwV3d size = {f, f, f}; static RwV3d axis1 = { 1.0f, 0.0f, 0.0f }; static RwV3d axis2 = { 0.0f, 0.0f, 1.0f }; static UINT32 timer = 0; @@ -151,7 +221,7 @@ void Viewport::RenderObjectBrowserModel() pRwFrame = (RwFrame*)pRpClump->object.parent; } - if (m_bObjBrowserAutoRot && (CTimer::m_snTimeInMilliseconds - timer > 7)) + if (m_bAutoRot && (CTimer::m_snTimeInMilliseconds - timer > 7)) { rotation += 1.0f; if (rotation > 360.0f) @@ -167,8 +237,8 @@ void Viewport::RenderObjectBrowserModel() RwFrameTransform(pRwFrame, &GetObjectParent (&Scene.m_pRwCamera->object.object)->modelling, rwCOMBINEREPLACE); RwFrameTranslate(pRwFrame, &pos, rwCOMBINEPRECONCAT); RwFrameScale(pRwFrame, &size, rwCOMBINEPRECONCAT); - RwFrameRotate(pRwFrame, &axis1, -90.0f + m_vecRenderRot.y, rwCOMBINEPRECONCAT); - RwFrameRotate(pRwFrame, &axis2, rotation + + m_vecRenderRot.x, rwCOMBINEPRECONCAT); + RwFrameRotate(pRwFrame, &axis1, -90.0f + m_fRot.y, rwCOMBINEPRECONCAT); + RwFrameRotate(pRwFrame, &axis2, rotation + + m_fRot.x, rwCOMBINEPRECONCAT); RwFrameUpdateObjects(pRwFrame); SetAmbientColours(&AmbientColor); @@ -184,20 +254,19 @@ void Viewport::RenderObjectBrowserModel() void Viewport::SetCameraPosn(const CVector &pos) { - m_fCameraPos = pos; + m_fCamPos = pos; /* * Since we're actually setting the player's position, * we need to add the offset to it */ - m_fCameraPos.z -= PLAYER_Z_OFFSET; - m_bCameraPosWasUpdated = true; + m_fCamPos.z -= PLAYER_Z_OFFSET; + m_bCamUpdated = true; } void Viewport::DrawHoverMenu() { - if (!m_bShowHoverMenu || m_eViewportMode != EDIT_MODE - || !m_bBeingHovered || Interface::Browser::m_bShown) + if (!Interface::m_bShowHoverMenu || m_eState != eViewportState::Edit || !m_bHovered || Browser::m_bShown) { return; } @@ -238,194 +307,7 @@ void Viewport::DrawHoverMenu() } } -void Viewport::Process() -{ - if (!m_bInitialized) - { - Init(); - } - - // ------------------------------------------------- - // vars - int delta = (CTimer::m_snTimeInMillisecondsNonClipped - - CTimer::m_snPreviousTimeInMillisecondsNonClipped); - - int ratio = 1 / (1 + (delta * m_nMul)); - int speed = m_nMul + m_nMul * ratio * delta; - - CPlayerPed* pPlayer = FindPlayerPed(-1); - int hPlayer = CPools::GetPedRef(pPlayer); - CVector pos = pPlayer->GetPosition(); - // ------------------------------------------------- - // Check if camera position was updated externally - // If it was then change to new values - if (m_bCameraPosWasUpdated) - { - pos = m_fCameraPos; - m_bCameraPosWasUpdated = false; - } - - if (Interface::m_bIsInputLocked) - { - return; - } - - if (viewportSwitchKey.Pressed()) - { - if(m_eViewportMode == EDIT_MODE) - { - m_eViewportMode = VIEW_MODE; - D3dHook::SetMouseState(false); - } - else - { - D3dHook::SetMouseState(true); - m_eViewportMode = EDIT_MODE; - } - m_bShowContextMenu = false; - } - - // Change object browser values if it's active - if (Interface::Browser::m_bShown - && Viewport::m_eViewportMode == VIEW_MODE) - { - CVector mouseDelta; - Command(&mouseDelta.x, &mouseDelta.y); - m_vecRenderRot.y += mouseDelta.y / MOUSE_FACTOR_Y; - - if (!m_bObjBrowserAutoRot) - { - m_vecRenderRot.x += mouseDelta.x / MOUSE_FACTOR_X; - } - - if (CPad::NewMouseControllerState.wheelUp) - { - m_nRenderScale += 0.05f; - if (m_nRenderScale > 5.0f) - { - m_nRenderScale = 5.0f; - } - } - - if (CPad::NewMouseControllerState.wheelDown) - { - m_nRenderScale -= 0.05f; - - if (m_nRenderScale < 0.0f) - { - m_nRenderScale = 0.0f; - } - } - return; - } - - if (KeyPressed(VK_LSHIFT)) - { - speed *= 2; - } - - if(m_eViewportMode == VIEW_MODE) - { - CVector mouseDelta; - Command(&mouseDelta.x, &mouseDelta.y); - m_fTotalMouse.x -= mouseDelta.x / MOUSE_FACTOR_X; - m_fTotalMouse.y += mouseDelta.y / MOUSE_FACTOR_Y; - } - - if (m_fTotalMouse.x > 360.0f) - { - m_fTotalMouse.x -= 360.0f; - } - - if (m_fTotalMouse.x < 0.0f) - { - m_fTotalMouse.x += 360.0f; - } - - if (m_fTotalMouse.y > 150) - { - m_fTotalMouse.y = 150; - } - - if (m_fTotalMouse.y < -150) - { - m_fTotalMouse.y = -150; - } - - if (KeyPressed(VK_RCONTROL)) - { - speed /= 2; - } - - if (KeyPressed(VK_RSHIFT)) - { - speed *= 2; - } - - if (KeyPressed(VK_KEY_W) || KeyPressed(VK_KEY_S)) - { - if (KeyPressed(VK_KEY_S)) - { - speed *= -1; - } - - float angle; - Command(hPlayer, &angle); - angle += 5.0f; // fix camera being slightly off - pos.x += speed * cos(angle * 3.14159f / 180.0f); - pos.y += speed * sin(angle * 3.14159f / 180.0f); - pos.z += speed * 2 * sin(m_fTotalMouse.y / 3 * 3.14159f / 180.0f); - } - - if (KeyPressed(VK_KEY_A) || KeyPressed(VK_KEY_D)) - { - if (KeyPressed(VK_KEY_A)) - { - speed *= -1; - } - - float angle; - Command(hPlayer, &angle); - angle -= 90; - - pos.x += speed * cos(angle * 3.14159f / 180.0f); - pos.y += speed * sin(angle * 3.14159f / 180.0f); - } - - // ------------------------------------------------- - // Calcualte the zoom here - if (Viewport::m_eViewportMode == VIEW_MODE) - { - if (CPad::NewMouseControllerState.wheelUp) - { - if (m_fFOV > 10.0f) - { - m_fFOV -= 2.0f; - } - - TheCamera.LerpFOV(TheCamera.FindCamFOV(), m_fFOV, 250, true); - Command(true); - } - - if (CPad::NewMouseControllerState.wheelDown) - { - if (m_fFOV < 115.0f) - { - m_fFOV += 2.0f; - } - - TheCamera.LerpFOV(TheCamera.FindCamFOV(), m_fFOV, 250, true); - Command(true); - } - } - // ------------------------------------------------- - - Command(hPlayer, m_fTotalMouse.x); - Command(hPlayer, 0.0, 0.0, PLAYER_Z_OFFSET, 90.0, 0.0, m_fTotalMouse.y, 0.0, 2); - pPlayer->SetPosn(pos); -} - -void Viewport::Shutdown() +void Viewport::Cleanup() { CPlayerPed *pPlayer = FindPlayerPed(-1); CEntity* pPlayerEntity = FindPlayerEntity(-1); @@ -453,6 +335,9 @@ void Viewport::Shutdown() Call<0x4396C0>(); } + Viewport::m_eState = eViewportState::Edit; + Viewport::Browser::m_bShown = false; + Viewport::Browser::m_bShowNextFrame = false; m_bInitialized = false; } @@ -475,11 +360,6 @@ static void my_PerspectiveFOV(float fov, float aspect, float _near, float _far, void Viewport::DrawOverlay() { - if (ImGui::IsMouseClicked(1)) - { - m_bShowContextMenu = true; - } - // ------------------------------------------------- /* * Calculations for pos & size of viewport @@ -494,12 +374,12 @@ void Viewport::DrawOverlay() ImGui::SetNextWindowBgAlpha(0.0f); // and ofcource it needs to be transarent ImGui::SetNextWindowPos(ImVec2(0.0f, frameHeight)); - m_fViewportSize = ImVec2(width-menuWidth, height - frameHeight); - ImGui::SetNextWindowSize(m_fViewportSize); + m_fSize = ImVec2(width-menuWidth, height - frameHeight); + ImGui::SetNextWindowSize(m_fSize); if (ImGui::Begin("ViewPort", NULL, flags)) { - m_bBeingHovered = ImGui::IsWindowHovered(); + m_bHovered = ImGui::IsWindowHovered(); // if (ObjManager::m_pSelected) // { @@ -516,23 +396,69 @@ void Viewport::DrawOverlay() // } // TODO: do popup menu checks here? - if (m_bShowContextMenu) - { - ProcessContextMenu(); - } + Interface::DrawContextMenu(); ImGui::End(); } } +static void QuickObjectCreatePopup() +{ + static int modelId = 620; + static std::string modelName = ObjManager::FindNameFromModel(modelId); + + ImGui::Text("Name: %s", modelName.c_str()); + if (ImGui::InputInt("Model", &modelId)) + { + modelName = ObjManager::FindNameFromModel(modelId); + } + if (KeyPressed(VK_RETURN)) + { + goto create_object; + } + + ImGui::Spacing(); + if (ImGui::Button("Create", Utils::GetSize(2))) + { +create_object: + int hObj; + Command(modelId); + Command(); + Command(modelId, Viewport::m_fWorldPos.x, + Viewport::m_fWorldPos.y, Viewport::m_fWorldPos.z, &hObj); + Command(modelId); + + CObject *pEntity = CPools::GetObject(hObj); + auto &data = ObjManager::m_objData.Get(pEntity); + data.m_modelName = modelName; + + ObjManager::m_pPlacedObjs.push_back(pEntity); + ObjManager::m_pSelected = pEntity; + + Interface::m_PopupMenu.m_bShow = false; + } + ImGui::SameLine(); + if (ImGui::Button("Find models", Utils::GetSize(2))) + { + ShellExecute(NULL, "open", "https://dev.prineside.com/en/gtasa_samp_model_id/", NULL, NULL, SW_SHOWNORMAL); + } + ImGui::Spacing(); + if (ImGui::Button("Open object browser", Utils::GetSize())) + { + Viewport::m_eState = eViewportState::Browser; + Interface::m_PopupMenu.m_bShow = false; + Viewport::Browser::m_bShowNextFrame = true; + } +} + static void ContextMenu_NewObject() { CEntity *pEntity; - if (Utils::TraceEntity(pEntity, Viewport::m_vecWorldPos)) + if (Utils::TraceEntity(pEntity, Viewport::m_fWorldPos)) { - Interface::m_bShowPopup = true; - Interface::m_pPopupFunc = Interface::QuickObjectCreateMenu; - Interface::m_popupTitle = "Quick object creator"; + Interface::m_PopupMenu.m_bShow = true; + Interface::m_PopupMenu.m_pFunc = QuickObjectCreatePopup; + Interface::m_PopupMenu.m_Title = "Quick object creator"; } } @@ -550,9 +476,9 @@ static void ContextMenu_Copy() { if (Viewport::m_HoveredEntity) { - Viewport::COPY_MODEL::m_nModel = Viewport::m_HoveredEntity->m_nModelIndex; + ObjManager::ClipBoard::m_nModel = Viewport::m_HoveredEntity->m_nModelIndex; - CVector &rot = Viewport::COPY_MODEL::m_vecRot; + CVector &rot = ObjManager::ClipBoard::m_vecRot; // Store rotation CallMethod<0x59A840, int>((int)Viewport::m_HoveredEntity->GetMatrix(), &rot.x, &rot.y, &rot.z, 0); //void __thiscall CMatrix::ConvertToEulerAngles(CMatrix *this, float *pX, float *pY, float *pZ, unsigned int flags) @@ -571,36 +497,36 @@ static void ContextMenu_Copy() static void ContextMenu_Paste() { - if (!Viewport::COPY_MODEL::m_nModel) + if (!ObjManager::ClipBoard::m_nModel) { return; } CEntity *pEntity; CVector pos; - if (Command(Viewport::COPY_MODEL::m_nModel) + if (Command(ObjManager::ClipBoard::m_nModel) && Utils::TraceEntity(pEntity, pos)) { int hObj; - Command(Viewport::COPY_MODEL::m_nModel); + Command(ObjManager::ClipBoard::m_nModel); Command(); - Command(Viewport::COPY_MODEL::m_nModel, pos.x, pos.y, pos.z, &hObj); - Command(Viewport::COPY_MODEL::m_nModel); + Command(ObjManager::ClipBoard::m_nModel, pos.x, pos.y, pos.z, &hObj); + Command(ObjManager::ClipBoard::m_nModel); CObject *pEntity = CPools::GetObject(hObj); auto &data = ObjManager::m_objData.Get(pEntity); - data.m_modelName = ObjManager::FindNameFromModel(Viewport::COPY_MODEL::m_nModel); + data.m_modelName = ObjManager::FindNameFromModel(ObjManager::ClipBoard::m_nModel); - if (ObjManager::bRandomRot) + if (Interface::m_bRandomRot) { - Viewport::COPY_MODEL::m_vecRot.x = Random(ObjManager::randomRotX[0], ObjManager::randomRotX[1]); - Viewport::COPY_MODEL::m_vecRot.y = Random(ObjManager::randomRotY[0], ObjManager::randomRotY[1]); - Viewport::COPY_MODEL::m_vecRot.z = Random(ObjManager::randomRotZ[0], ObjManager::randomRotZ[1]); + ObjManager::ClipBoard::m_vecRot.x = Random(Interface::m_RandomRotX[0], Interface::m_RandomRotX[1]); + ObjManager::ClipBoard::m_vecRot.y = Random(Interface::m_RandomRotY[0], Interface::m_RandomRotY[1]); + ObjManager::ClipBoard::m_vecRot.z = Random(Interface::m_RandomRotZ[0], Interface::m_RandomRotZ[1]); } - - data.SetRotation(Viewport::COPY_MODEL::m_vecRot); - ObjManager::m_pVecEntities.push_back(pEntity); + data.SetRotation(ObjManager::ClipBoard::m_vecRot); + + ObjManager::m_pPlacedObjs.push_back(pEntity); ObjManager::m_pSelected = pEntity; } } @@ -610,72 +536,235 @@ static void ContextMenu_Delete() if (ObjManager::m_pSelected) { ObjManager::m_pSelected->Remove(); - ObjManager::m_pVecEntities.erase(std::remove(ObjManager::m_pVecEntities.begin(), - ObjManager::m_pVecEntities.end(), ObjManager::m_pSelected), ObjManager::m_pVecEntities.end()); + ObjManager::m_pPlacedObjs.erase(std::remove(ObjManager::m_pPlacedObjs.begin(), + ObjManager::m_pPlacedObjs.end(), ObjManager::m_pSelected), ObjManager::m_pPlacedObjs.end()); ObjManager::m_pSelected = nullptr; } } -void Viewport::ProcessContextMenu() +void ContextMenu_Viewport(std::string& root, std::string& key, std::string& value) +{ + if (Viewport::Browser::m_bShown || Viewport::m_eState != eViewportState::Edit) + { + return; + } + + if (ImGui::MenuItem("New object")) + { + ContextMenu_NewObject(); + } + + if (ImGui::MenuItem("Add to favourites")) + { + int model = Viewport::m_HoveredEntity->m_nModelIndex; + std::string keyName = std::to_string(model) + " - " + ObjManager::FindNameFromModel(model); + Interface::m_favData.m_pJson->m_Data["All"][keyName] = std::to_string(model); + Interface::m_favData.m_pJson->WriteToDisk(); + CHud::SetHelpMessage("Added to favourites", false, false, false); + Interface::m_ContextMenu.m_bShow = false; + } + ImGui::Separator(); + if (ImGui::MenuItem("Snap to ground")) + { + ContextMenu_SnapToGround(); + Interface::m_ContextMenu.m_bShow = false; + } + + if (ImGui::MenuItem("Copy")) + { + ContextMenu_Copy(); + Interface::m_ContextMenu.m_bShow = false; + } + + if (ImGui::MenuItem("Paste")) + { + ContextMenu_Paste(); + Interface::m_ContextMenu.m_bShow = false; + } + + if (ImGui::MenuItem("Delete")) + { + ContextMenu_Delete(); + Interface::m_ContextMenu.m_bShow = false; + } + ImGui::Separator(); +} + + +void Viewport::Process() { - if (Interface::Browser::m_bShown || m_eViewportMode != EDIT_MODE) + if (!m_bInitialized) + { + Init(); + } + + if (Interface::m_bShowGUI) + { + Viewport::DrawOverlay(); + Viewport::ProcessInputs(); + Viewport::DrawHoverMenu(); + + if (Viewport::m_bHovered && ImGui::IsMouseClicked(1)) + { + Interface::m_ContextMenu.m_bShow = true; + Interface::m_ContextMenu.m_pFunc = ContextMenu_Viewport; + Interface::m_ContextMenu.m_Root = ""; + Interface::m_ContextMenu.m_Key = ""; + Interface::m_ContextMenu.m_Val = ""; + } + } + + Browser::Process(); + + // ------------------------------------------------- + // vars + int delta = (CTimer::m_snTimeInMillisecondsNonClipped - + CTimer::m_snPreviousTimeInMillisecondsNonClipped); + + int ratio = 1 / (1 + (delta * m_nMoveSpeed)); + int speed = m_nMoveSpeed + m_nMoveSpeed * ratio * delta; + + CPlayerPed* pPlayer = FindPlayerPed(-1); + int hPlayer = CPools::GetPedRef(pPlayer); + CVector pos = pPlayer->GetPosition(); + // ------------------------------------------------- + // Check if camera position was updated externally + // If it was then change to new values + if (m_bCamUpdated) + { + pos = m_fCamPos; + m_bCamUpdated = false; + } + + if (Interface::m_bInputLocked) { return; } - if (ImGui::BeginPopupContextWindow("ContextMenu")) + if (viewportSwitchKey.Pressed()) { - if (ImGui::MenuItem("New object")) + if(m_eState == eViewportState::Edit) { - ContextMenu_NewObject(); - m_bShowContextMenu = false; + m_eState = eViewportState::View; + D3dHook::SetMouseState(false); + } + else + { + D3dHook::SetMouseState(true); + m_eState = eViewportState::Edit; } - if (ImGui::MenuItem("Add to favourites")) + } + + if (KeyPressed(VK_LSHIFT)) + { + speed *= 2; + } + + // Temp fix for a camera rotation bug switching from Edit -> View + // Skipping 2 frames to fix this issue for now + // TODO: FIX + static size_t skippedFrames; + if(m_eState == eViewportState::View) + { + if (skippedFrames > 1) { - int model = Viewport::m_HoveredEntity->m_nModelIndex; - std::string keyName = std::to_string(model) + " - " + ObjManager::FindNameFromModel(model); - Interface::m_favData.m_pJson->m_Data["All"][keyName] = std::to_string(model); - Interface::m_favData.m_pJson->WriteToDisk(); - CHud::SetHelpMessage("Added to favourites", false, false, false); - m_bShowContextMenu = false; + CVector mouseDelta; + Command(&mouseDelta.x, &mouseDelta.y); + m_fMousePos.x -= mouseDelta.x / MOUSE_FACTOR_X; + m_fMousePos.y += mouseDelta.y / MOUSE_FACTOR_Y; } - ImGui::Separator(); - if (ImGui::MenuItem("Snap to ground")) + else { - ContextMenu_SnapToGround(); - m_bShowContextMenu = false; + ++skippedFrames; } + } + else + { + skippedFrames = 0; + } + + m_fMousePos.x -= m_fMousePos.x > 360.0f ? 360.0f : 0.0f; + m_fMousePos.x += m_fMousePos.x < 0.0f ? 360.0f : 0.0f; + m_fMousePos.y += m_fMousePos.y > 150.0f ? 150.0f : 0.0f; + m_fMousePos.y += m_fMousePos.y < -150.0f ? -150.0f : 0.0f; + + if (KeyPressed(VK_RCONTROL)) + { + speed /= 2; + } - if (ImGui::MenuItem("Copy")) + if (KeyPressed(VK_RSHIFT)) + { + speed *= 2; + } + + if (KeyPressed(VK_KEY_W) || KeyPressed(VK_KEY_S)) + { + if (KeyPressed(VK_KEY_S)) { - ContextMenu_Copy(); - m_bShowContextMenu = false; + speed *= -1; } - if (ImGui::MenuItem("Paste")) + float angle; + Command(hPlayer, &angle); + angle += 5.0f; // fix camera being slightly off + pos.x += speed * cos(angle * 3.14159f / 180.0f); + pos.y += speed * sin(angle * 3.14159f / 180.0f); + pos.z += speed * 2 * sin(m_fMousePos.y / 3 * 3.14159f / 180.0f); + } + + if (KeyPressed(VK_KEY_A) || KeyPressed(VK_KEY_D)) + { + if (KeyPressed(VK_KEY_A)) { - ContextMenu_Paste(); - m_bShowContextMenu = false; + speed *= -1; } - if (ImGui::MenuItem("Delete")) + float angle; + Command(hPlayer, &angle); + angle -= 90; + + pos.x += speed * cos(angle * 3.14159f / 180.0f); + pos.y += speed * sin(angle * 3.14159f / 180.0f); + } + + // ------------------------------------------------- + // Calcualte the zoom here + if (Viewport::m_eState == eViewportState::View) + { + if (CPad::NewMouseControllerState.wheelUp) { - ContextMenu_Delete(); - m_bShowContextMenu = false; + if (m_fFOV > 10.0f) + { + m_fFOV -= 2.0f; + } + + TheCamera.LerpFOV(TheCamera.FindCamFOV(), m_fFOV, 250, true); + Command(true); } - ImGui::Separator(); - if (ImGui::MenuItem("Close")) + + if (CPad::NewMouseControllerState.wheelDown) { - m_bShowContextMenu = false; + if (m_fFOV < 115.0f) + { + m_fFOV += 2.0f; + } + + TheCamera.LerpFOV(TheCamera.FindCamFOV(), m_fFOV, 250, true); + Command(true); } - ImGui::EndPopup(); } + // ------------------------------------------------- + + Command(hPlayer, m_fMousePos.x); + Command(hPlayer, 0.0, 0.0, PLAYER_Z_OFFSET, 90.0, 0.0, m_fMousePos.y, 0.0, 2); + pPlayer->SetPosn(pos); } -void Viewport::ProcessSelectedObjectInputs() +void Viewport::ProcessInputs() { - if (!m_bBeingHovered) + if (!m_bHovered) { return; } @@ -690,7 +779,7 @@ void Viewport::ProcessSelectedObjectInputs() if (Utils::TraceEntity(pEntity, pos)) { ObjManager::m_pSelected = nullptr; - for (auto &ent : ObjManager::m_pVecEntities) + for (auto &ent : ObjManager::m_pPlacedObjs) { if (ent == pEntity) { @@ -706,13 +795,13 @@ void Viewport::ProcessSelectedObjectInputs() static int hObj = NULL; static CVector off; // offset between the mouse and the object pivot - if (!(Interface::m_bShowPopup && m_bShowContextMenu)) + if (!(Interface::m_PopupMenu.m_bShow && Interface::m_ContextMenu.m_bShow)) { // ------------------------------------------------- // X, Y, Z axis movement // TODO: Z axis is kinda buggy - if (!Interface::Browser::m_bShown) + if (!Browser::m_bShown) { static bool bObjectBeingDragged; @@ -767,7 +856,7 @@ void Viewport::ProcessSelectedObjectInputs() // Z axis movement ImGuiIO &io = ImGui::GetIO(); float wheel = io.MouseWheel; - if (wheel && ObjManager::m_pSelected && Viewport::m_eViewportMode == EDIT_MODE) + if (wheel && ObjManager::m_pSelected && Viewport::m_eState == eViewportState::Edit) { if (KeyPressed(VK_LCONTROL)) { @@ -796,7 +885,7 @@ void Viewport::ProcessSelectedObjectInputs() } - if (!Interface::m_bIsInputLocked) + if (!Interface::m_bInputLocked) { // ------------------------------------------------- // Context menu shortcuts diff --git a/src/viewport.h b/src/viewport.h index bba835b..4d9e00f 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -1,64 +1,86 @@ #pragma once #include "plugin.h" -#define PLAYER_Z_OFFSET 0.0f -#define MOUSE_FACTOR_X 13.0f -#define MOUSE_FACTOR_Y 6.0f -enum VIEWPORT_STATE +enum class eViewportState { - EDIT_MODE, - VIEW_MODE, - OBJECT_VIEW_MODE, + Edit, + View, + Browser, }; class Viewport { private: - static inline bool m_bInitialized; - static inline CVector m_fTotalMouse; // stores the mouse position - static inline BYTE m_bHudState; // backup for Shutdown() - static inline BYTE m_bRadarState; // backup for Shutdown() - static inline bool m_bNeverWanted; // backup for Shutdown() + static inline bool m_bInitialized; // Is the viewport init done + static inline ImVec2 m_fSize; // Size of the viewport + static inline CVector m_fMousePos; // Mouse position in the viewport // To allow updating camera position externally - static inline CVector m_fCameraPos; - static inline bool m_bCameraPosWasUpdated; + static inline CVector m_fCamPos; + static inline bool m_bCamUpdated; - static void LoadNewClump(int model, RpClump *&pClump, RpAtomic *&pAtomic, RwFrame *&pFrame); - static void RenderObjectBrowserModel(); + // Processes the right click context menu + static void DrawContextMenu(); + + // The object hover menu. Shows object model, name & type + static void DrawHoverMenu(); + + // Creates a transparent layer over the viewport + // Used for inputs and context menu creation + static void DrawOverlay(); + + // Processes input for the currently selected object + // TODO: Should be in ObjManager class? + static void ProcessInputs(); public: - static inline float m_nRenderScale = 1.0f; // ObjectBrowser object render scale - static inline bool m_bShowContextMenu; - static inline bool m_bShowHoverMenu; // tooltup menu showing info on hover - static inline bool m_bBeingHovered; - static inline VIEWPORT_STATE m_eViewportMode = EDIT_MODE; - static inline int m_nMul = 1; // movement speed multiplier for viewport realted controls - static inline float m_fFOV = 70.0f; // camera field of view - static inline CVector m_vecWorldPos; - static inline CEntity *m_HoveredEntity; - static inline CVector m_vecRenderRot; - static inline bool m_bObjBrowserAutoRot; - static inline ImVec2 m_fViewportSize; - struct COPY_MODEL + static inline eViewportState m_eState = eViewportState::Edit; + static inline bool m_bHovered; // Is mouse hovering viewport + static inline CEntity *m_HoveredEntity; // Currently hovered entity + static inline int m_nMoveSpeed = 1; // movement speed multiplier controls + static inline float m_fFOV = 70.0f; + static inline CVector m_fWorldPos; // cursor world position + + struct Browser { - static inline int m_nModel; - static inline CVector m_vecRot; + private: + static inline size_t m_nSelectedID = NULL; // Selected model id + static inline CVector m_fRot; // rotation of the rendering object + + // Loads model + // TODO: Need some fail checks + static void LoadModel(size_t model, RpClump *&pClump, RpAtomic *&pAtomic, RwFrame *&pFrame); + + // Renders the model in viewport + static void RenderModel(); + public: + static inline bool m_bShowNextFrame; // Should the browser be shown next frame + static inline bool m_bShown; // Is the browser being shown + static inline bool m_bAutoRot; // Auto rotate object in browser + + static inline float m_fScale = 1.0f; // ObjectBrowser object render scale + + static size_t GetSelected(); + static void Process(); + static void SetSelected(int modelId); }; Viewport() = delete; Viewport(Viewport&) = delete; + + // Initiazes stuff for MapEditor open static void Init(); - static void DrawHoverMenu(); - /* - * Creates a transparent overlay over the viewport - * Used for inputs and context menu creation - */ - static void DrawOverlay(); + + // Needs to be called each frame static void Process(); - static void ProcessContextMenu(); - static void ProcessSelectedObjectInputs(); + + // Cleans stuff on MapEditor exit + static void Cleanup(); + + // Returns the size of the viewport + static ImVec2 GetSize(); + + // Allows changing camera position externally static void SetCameraPosn(const CVector &pos); - static void Shutdown(); }; \ No newline at end of file diff --git a/src/widgets.cpp b/src/widgets.cpp index 6edb8a1..f8180cc 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -34,19 +34,15 @@ bool Widgets::ListBoxStr(const char* label, std::vector& all_items, return rtn; } -void Widgets::DrawJSON(ResourceStore& data, - std::function func_left_click, - std::function func_right_click) +void Widgets::DrawJSON(ResourceStore& data, ContextMenu& context, f_Arg3 func_left_click, f_Arg3 func_right_click) { ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() / 2 - 5); ListBoxStr("##Categories", data.m_Categories, data.m_Selected); ImGui::SameLine(); data.m_Filter.Draw("##Filter"); - if (ImGui::IsItemActive()) - { - Interface::m_bIsInputLocked = true; - } + + Interface::m_bInputLocked = ImGui::IsItemActive(); if (strlen(data.m_Filter.InputBuf) == 0) { ImDrawList* drawlist = ImGui::GetWindowDrawList(); @@ -82,17 +78,35 @@ void Widgets::DrawJSON(ResourceStore& data, if (ImGui::IsItemClicked(1) && func_right_click != nullptr) { - Interface::m_contextMenu.function = func_right_click; - Interface::m_contextMenu.rootKey = root.key(); - Interface::m_contextMenu.key = name; - Interface::m_contextMenu.value = _data.value(); + context.m_bShow = true; + context.m_pFunc = func_right_click; + context.m_Root = root.key(); + context.m_Key = name; + context.m_Val = _data.value(); } } } } } - Interface::ProcessContextMenu(); + // context menu + if (context.m_bShow) + { + if (ImGui::BeginPopupContextWindow("TMenu")) + { + ImGui::Text(context.m_Key.c_str()); + ImGui::Separator(); + + context.m_pFunc(context.m_Root, context.m_Key, context.m_Val); + + if (ImGui::MenuItem("Close")) + { + context.m_bShow = false; + } + + ImGui::EndPopup(); + } + } ImGui::EndChild(); } diff --git a/src/widgets.h b/src/widgets.h index 4be590b..3f0b20a 100644 --- a/src/widgets.h +++ b/src/widgets.h @@ -5,25 +5,12 @@ class Widgets { -private: - struct JsonPopUpData - { - std::function function; - std::string key; - std::string rootKey; - std::string value; - }; - public: - static inline JsonPopUpData jsonPopup; - Widgets() = delete;; Widgets(Widgets&) = delete; static void CenterdText(const std::string& text); static bool ListBoxStr(const char* label, std::vector& all_items, std::string& selected); - static void DrawJSON(ResourceStore& data, - std::function func_left_click, - std::function func_right_click); + static void DrawJSON(ResourceStore& data, ContextMenu& context, f_Arg3 func_left_click, f_Arg3 func_right_click); static void ShowTooltip(const char* text); }; \ No newline at end of file diff --git a/tools/FormatCode.bat b/tools/FormatCode.bat index dff0aa1..72a5836 100644 --- a/tools/FormatCode.bat +++ b/tools/FormatCode.bat @@ -1,2 +1,2 @@ -start tools/AStyle.exe --style=allman -n --recursive src/*.cpp src/*.h +start tools/AStyle.exe -n --recursive src/*.cpp src/*.h \ No newline at end of file