mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-22 14:23:44 -07:00
Proof of Concept
This commit is contained in:
parent
0ae7f626a1
commit
0683d965e9
5 changed files with 168 additions and 2 deletions
135
soh/soh/Enhancements/mod_menu.cpp
Normal file
135
soh/soh/Enhancements/mod_menu.cpp
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
#include "mod_menu.h"
|
||||||
|
#include "utils/StringHelper.h"
|
||||||
|
#include <libultraship/classes.h>
|
||||||
|
#include "soh/OTRGlobals.h"
|
||||||
|
#include <map>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
std::shared_ptr<Ship::ArchiveManager> GetArchiveManager() {
|
||||||
|
return Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, bool> modFiles;
|
||||||
|
|
||||||
|
bool is_enabled(const std::pair<std::string, bool>& p) {
|
||||||
|
return p.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetEnabledModFiles() {
|
||||||
|
std::map<std::string, bool> enabledMods;
|
||||||
|
|
||||||
|
std::copy_if(modFiles.begin(), modFiles.end(), std::inserter(enabledMods, enabledMods.begin()), is_enabled);
|
||||||
|
|
||||||
|
auto ks = std::views::keys(enabledMods);
|
||||||
|
std::vector<std::string> keys{ ks.begin(), ks.end() };
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_disabled(const std::pair<std::string, bool>& p) {
|
||||||
|
return !p.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetDisabledModFiles() {
|
||||||
|
std::map<std::string, bool> disabledMods;
|
||||||
|
|
||||||
|
std::copy_if(modFiles.begin(), modFiles.end(), std::inserter(disabledMods, disabledMods.begin()), is_disabled);
|
||||||
|
|
||||||
|
auto ks = std::views::keys(disabledMods);
|
||||||
|
std::vector<std::string> keys{ ks.begin(), ks.end() };
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateModFiles() {
|
||||||
|
modFiles.clear();
|
||||||
|
std::string modsPath = Ship::Context::LocateFileAcrossAppDirs("mods", appShortName);
|
||||||
|
if (modsPath.length() > 0 && std::filesystem::exists(modsPath)) {
|
||||||
|
if (std::filesystem::is_directory(modsPath)) {
|
||||||
|
for (const std::filesystem::directory_entry& p : std::filesystem::recursive_directory_iterator(modsPath, std::filesystem::directory_options::follow_directory_symlink)) {
|
||||||
|
std::string extension = p.path().extension().string();
|
||||||
|
if (
|
||||||
|
StringHelper::IEquals(extension, ".otr") ||
|
||||||
|
StringHelper::IEquals(extension, ".mpq") ||
|
||||||
|
StringHelper::IEquals(extension, ".o2r") ||
|
||||||
|
StringHelper::IEquals(extension, ".zip")
|
||||||
|
) {
|
||||||
|
modFiles.emplace(p.path().generic_string(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
std::sort(modFiles.begin(), modFiles.end(), [](const std::string& a, const std::string& b) {
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
a.begin(), a.end(),
|
||||||
|
b.begin(), b.end(),
|
||||||
|
[](char c1, char c2) {
|
||||||
|
return std::tolower(c1) < std::tolower(c2);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModMenuWindow::DrawElement() {
|
||||||
|
if (ImGui::Button("Update")) {
|
||||||
|
UpdateModFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginTable("tableMods", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) {
|
||||||
|
ImGui::TableSetupColumn("Enabled Mods", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||||
|
ImGui::TableSetupColumn("Disabled Mods", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||||
|
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
ImGui::PopItemFlag();
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
if (ImGui::BeginChild("Enabled Mods", ImVec2(0, -8))) {
|
||||||
|
std::vector<std::string> enabledMods = GetEnabledModFiles();
|
||||||
|
if (!enabledMods.empty()) {
|
||||||
|
for (std::string file : enabledMods) {
|
||||||
|
if (ImGui::Button(("Disable##" + file).c_str())) {
|
||||||
|
modFiles[file] = false;
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->RemoveArchive(file);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text(file.c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Text("<None>");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
if (ImGui::BeginChild("Disabled Mods", ImVec2(0, -8))) {
|
||||||
|
std::vector<std::string> disabledMods = GetDisabledModFiles();
|
||||||
|
if (!disabledMods.empty()) {
|
||||||
|
for (std::string file : disabledMods) {
|
||||||
|
if (ImGui::Button(("Enable##" + file).c_str())) {
|
||||||
|
modFiles[file] = true;
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->AddArchive(file);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text(file.c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Text("<None>");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModMenuWindow::InitElement() {
|
||||||
|
UpdateModFiles();
|
||||||
|
}
|
14
soh/soh/Enhancements/mod_menu.h
Normal file
14
soh/soh/Enhancements/mod_menu.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libultraship/libultraship.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
class ModMenuWindow : public Ship::GuiWindow {
|
||||||
|
public:
|
||||||
|
using GuiWindow::GuiWindow;
|
||||||
|
|
||||||
|
void InitElement() override;
|
||||||
|
void DrawElement() override;
|
||||||
|
void UpdateElement() override {};
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -265,7 +265,7 @@ OTRGlobals::OTRGlobals() {
|
||||||
std::string mqPath = Ship::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName);
|
std::string mqPath = Ship::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName);
|
||||||
if (std::filesystem::exists(mqPath)) {
|
if (std::filesystem::exists(mqPath)) {
|
||||||
OTRFiles.push_back(mqPath);
|
OTRFiles.push_back(mqPath);
|
||||||
}
|
}
|
||||||
std::string ootPath = Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName);
|
std::string ootPath = Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName);
|
||||||
if (std::filesystem::exists(ootPath)) {
|
if (std::filesystem::exists(ootPath)) {
|
||||||
OTRFiles.push_back(ootPath);
|
OTRFiles.push_back(ootPath);
|
||||||
|
@ -274,6 +274,7 @@ OTRGlobals::OTRGlobals() {
|
||||||
if (std::filesystem::exists(sohOtrPath)) {
|
if (std::filesystem::exists(sohOtrPath)) {
|
||||||
OTRFiles.push_back(sohOtrPath);
|
OTRFiles.push_back(sohOtrPath);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
std::string patchesPath = Ship::Context::LocateFileAcrossAppDirs("mods", appShortName);
|
std::string patchesPath = Ship::Context::LocateFileAcrossAppDirs("mods", appShortName);
|
||||||
std::vector<std::string> patchOTRs = {};
|
std::vector<std::string> patchOTRs = {};
|
||||||
if (patchesPath.length() > 0 && std::filesystem::exists(patchesPath)) {
|
if (patchesPath.length() > 0 && std::filesystem::exists(patchesPath)) {
|
||||||
|
@ -297,7 +298,9 @@ OTRGlobals::OTRGlobals() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
OTRFiles.insert(OTRFiles.end(), patchOTRs.begin(), patchOTRs.end());
|
OTRFiles.insert(OTRFiles.end(), patchOTRs.begin(), patchOTRs.end());
|
||||||
|
*/
|
||||||
std::unordered_set<uint32_t> ValidHashes = {
|
std::unordered_set<uint32_t> ValidHashes = {
|
||||||
OOT_PAL_MQ,
|
OOT_PAL_MQ,
|
||||||
OOT_NTSC_JP_MQ,
|
OOT_NTSC_JP_MQ,
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "Enhancements/debugger/MessageViewer.h"
|
#include "Enhancements/debugger/MessageViewer.h"
|
||||||
#include "soh/Notification/Notification.h"
|
#include "soh/Notification/Notification.h"
|
||||||
#include "soh/Enhancements/TimeDisplay/TimeDisplay.h"
|
#include "soh/Enhancements/TimeDisplay/TimeDisplay.h"
|
||||||
|
#include "soh/Enhancements/mod_menu.h"
|
||||||
|
|
||||||
bool isBetaQuestEnabled = false;
|
bool isBetaQuestEnabled = false;
|
||||||
|
|
||||||
|
@ -110,6 +111,7 @@ namespace SohGui {
|
||||||
std::shared_ptr<Ship::GuiWindow> mGfxDebuggerWindow;
|
std::shared_ptr<Ship::GuiWindow> mGfxDebuggerWindow;
|
||||||
std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
|
std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
|
||||||
|
|
||||||
|
std::shared_ptr<ModMenuWindow> mModMenuWindow;
|
||||||
std::shared_ptr<AudioEditor> mAudioEditorWindow;
|
std::shared_ptr<AudioEditor> mAudioEditorWindow;
|
||||||
std::shared_ptr<InputViewer> mInputViewer;
|
std::shared_ptr<InputViewer> mInputViewer;
|
||||||
std::shared_ptr<InputViewerSettingsWindow> mInputViewerSettings;
|
std::shared_ptr<InputViewerSettingsWindow> mInputViewerSettings;
|
||||||
|
@ -170,6 +172,8 @@ namespace SohGui {
|
||||||
SPDLOG_ERROR("Could not find input editor window");
|
SPDLOG_ERROR("Could not find input editor window");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mModMenuWindow = std::make_shared<ModMenuWindow>(CVAR_WINDOW("ModMenu"), "Mod Menu", ImVec2(820, 630));
|
||||||
|
gui->AddGuiWindow(mModMenuWindow);
|
||||||
mAudioEditorWindow = std::make_shared<AudioEditor>(CVAR_WINDOW("AudioEditor"), "Audio Editor", ImVec2(820, 630));
|
mAudioEditorWindow = std::make_shared<AudioEditor>(CVAR_WINDOW("AudioEditor"), "Audio Editor", ImVec2(820, 630));
|
||||||
gui->AddGuiWindow(mAudioEditorWindow);
|
gui->AddGuiWindow(mAudioEditorWindow);
|
||||||
mInputViewer = std::make_shared<InputViewer>(CVAR_WINDOW("InputViewer"), "Input Viewer");
|
mInputViewer = std::make_shared<InputViewer>(CVAR_WINDOW("InputViewer"), "Input Viewer");
|
||||||
|
@ -227,8 +231,9 @@ namespace SohGui {
|
||||||
void Destroy() {
|
void Destroy() {
|
||||||
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
||||||
gui->RemoveAllGuiWindows();
|
gui->RemoveAllGuiWindows();
|
||||||
|
|
||||||
mNotificationWindow = nullptr;
|
mNotificationWindow = nullptr;
|
||||||
|
mModMenuWindow = nullptr;
|
||||||
mModalWindow = nullptr;
|
mModalWindow = nullptr;
|
||||||
mAdvancedResolutionSettingsWindow = nullptr;
|
mAdvancedResolutionSettingsWindow = nullptr;
|
||||||
mRandomizerSettingsWindow = nullptr;
|
mRandomizerSettingsWindow = nullptr;
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "Enhancements/timesplits/TimeSplits.h"
|
#include "Enhancements/timesplits/TimeSplits.h"
|
||||||
#include "Enhancements/randomizer/Plandomizer.h"
|
#include "Enhancements/randomizer/Plandomizer.h"
|
||||||
#include "Enhancements/TimeDisplay/TimeDisplay.h"
|
#include "Enhancements/TimeDisplay/TimeDisplay.h"
|
||||||
|
#include "Enhancements/mod_menu.h"
|
||||||
|
|
||||||
// FA icons are kind of wonky, if they worked how I expected them to the "+ 2.0f" wouldn't be needed, but
|
// FA icons are kind of wonky, if they worked how I expected them to the "+ 2.0f" wouldn't be needed, but
|
||||||
// they don't work how I expect them to so I added that because it looked good when I eyeballed it
|
// they don't work how I expect them to so I added that because it looked good when I eyeballed it
|
||||||
|
@ -608,6 +609,7 @@ extern std::shared_ptr<CosmeticsEditorWindow> mCosmeticsEditorWindow;
|
||||||
extern std::shared_ptr<GameplayStatsWindow> mGameplayStatsWindow;
|
extern std::shared_ptr<GameplayStatsWindow> mGameplayStatsWindow;
|
||||||
extern std::shared_ptr<TimeSplitWindow> mTimeSplitWindow;
|
extern std::shared_ptr<TimeSplitWindow> mTimeSplitWindow;
|
||||||
extern std::shared_ptr<TimeDisplayWindow> mTimeDisplayWindow;
|
extern std::shared_ptr<TimeDisplayWindow> mTimeDisplayWindow;
|
||||||
|
extern std::shared_ptr<ModMenuWindow> mModMenuWindow;
|
||||||
|
|
||||||
void DrawEnhancementsMenu() {
|
void DrawEnhancementsMenu() {
|
||||||
if (ImGui::BeginMenu("Enhancements"))
|
if (ImGui::BeginMenu("Enhancements"))
|
||||||
|
@ -1769,6 +1771,13 @@ void DrawEnhancementsMenu() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mModMenuWindow) {
|
||||||
|
if (ImGui::Button(GetWindowButtonText("Mod Menu", CVarGetInteger(CVAR_WINDOW("ModMenu"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
|
||||||
|
mModMenuWindow->ToggleVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PopStyleVar(3);
|
ImGui::PopStyleVar(3);
|
||||||
ImGui::PopStyleColor(1);
|
ImGui::PopStyleColor(1);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue