mirror of
https://github.com/HarbourMasters/2ship2harkinian.git
synced 2024-11-27 00:00:32 +00:00
Item tracker (#707)
* Core tracker code mostly done. * Format * Clean up enums. * Format * Header cleanup * Update * use CVars * format * Add editor to modern menu * format * Fix item tracker cvar loading/saving and add item tracker button for modern menu * update button label --------- Co-authored-by: Archez <archez39@me.com>
This commit is contained in:
parent
d1bbba626d
commit
be70a5a123
@ -21,6 +21,9 @@
|
||||
#include "include/global.h"
|
||||
#include "include/z64audio.h"
|
||||
|
||||
#include "Enhancements/Trackers/ItemTracker.h"
|
||||
#include "Enhancements/Trackers/ItemTrackerSettings.h"
|
||||
|
||||
namespace BenGui {
|
||||
// MARK: - Delegates
|
||||
|
||||
@ -38,6 +41,8 @@ std::shared_ptr<EventLogWindow> mEventLogWindow;
|
||||
std::shared_ptr<BenMenu> mBenMenu;
|
||||
std::shared_ptr<BenInputEditorWindow> mBenInputEditorWindow;
|
||||
std::shared_ptr<Notification::Window> mNotificationWindow;
|
||||
std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||
std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
|
||||
|
||||
void SetupGuiElements() {
|
||||
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
||||
@ -94,6 +99,13 @@ void SetupGuiElements() {
|
||||
|
||||
mEventLogWindow = std::make_shared<EventLogWindow>("gWindows.EventLog", "Event Log", ImVec2(520, 600));
|
||||
gui->AddGuiWindow(mEventLogWindow);
|
||||
|
||||
mItemTrackerWindow = std::make_shared<ItemTrackerWindow>("gWindows.ItemTracker", "Item Tracker");
|
||||
gui->AddGuiWindow(mItemTrackerWindow);
|
||||
|
||||
mItemTrackerSettingsWindow = std::make_shared<ItemTrackerSettingsWindow>("gWindows.ItemTrackerSettings",
|
||||
"Item Tracker Settings", ImVec2(800, 400));
|
||||
gui->AddGuiWindow(mItemTrackerSettingsWindow);
|
||||
gui->SetPadBtnTogglesMenu();
|
||||
|
||||
mNotificationWindow = std::make_shared<Notification::Window>("gWindows.Notifications", "Notifications Window");
|
||||
@ -102,6 +114,9 @@ void SetupGuiElements() {
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
||||
|
||||
gui->RemoveAllGuiWindows();
|
||||
mBenMenuBar = nullptr;
|
||||
mBenMenu = nullptr;
|
||||
mStatsWindow = nullptr;
|
||||
@ -111,9 +126,10 @@ void Destroy() {
|
||||
mCollisionViewerWindow = nullptr;
|
||||
mEventLogWindow = nullptr;
|
||||
mNotificationWindow = nullptr;
|
||||
|
||||
mSaveEditorWindow = nullptr;
|
||||
mHudEditorWindow = nullptr;
|
||||
mActorViewerWindow = nullptr;
|
||||
mItemTrackerWindow = nullptr;
|
||||
mItemTrackerSettingsWindow = nullptr;
|
||||
}
|
||||
} // namespace BenGui
|
||||
|
@ -12,6 +12,9 @@
|
||||
#include "2s2h/DeveloperTools/DeveloperTools.h"
|
||||
#include "HudEditor.h"
|
||||
|
||||
#include "2s2h/Enhancements/Trackers/ItemTracker.h"
|
||||
#include "2s2h/Enhancements/Trackers/ItemTrackerSettings.h"
|
||||
|
||||
extern "C" {
|
||||
#include "z64.h"
|
||||
#include "functions.h"
|
||||
@ -345,6 +348,8 @@ void DrawSettingsMenu() {
|
||||
}
|
||||
|
||||
extern std::shared_ptr<HudEditorWindow> mHudEditorWindow;
|
||||
extern std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||
extern std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
|
||||
|
||||
void DrawEnhancementsMenu() {
|
||||
if (UIWidgets::BeginMenu("Enhancements")) {
|
||||
@ -799,6 +804,15 @@ void DrawEnhancementsMenu() {
|
||||
{ .tooltip = "Enables the Hud Editor window, allowing you to edit your hud" });
|
||||
}
|
||||
|
||||
if (mItemTrackerWindow) {
|
||||
UIWidgets::WindowButton("Item Tracker", "gWindows.ItemTracker", mItemTrackerWindow);
|
||||
}
|
||||
|
||||
if (mItemTrackerSettingsWindow) {
|
||||
UIWidgets::WindowButton("Item Tracker Settings", "gWindows.ItemTrackerSettings",
|
||||
mItemTrackerSettingsWindow);
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
@ -1424,6 +1424,15 @@ void AddEnhancements() {
|
||||
"Enables the HUD Editor window, allowing you to modify your HUD",
|
||||
WIDGET_WINDOW_BUTTON,
|
||||
{ .size = UIWidgets::Sizes::Inline, .windowName = "HUD Editor" } } } } });
|
||||
enhancementsSidebar.push_back(
|
||||
{ "Item Tracker",
|
||||
1,
|
||||
{ // Item Tracker Settings
|
||||
{ { "Popout Item Tracker Settings",
|
||||
"gWindows.ItemTrackerSettings",
|
||||
"",
|
||||
WIDGET_WINDOW_BUTTON,
|
||||
{ .size = UIWidgets::Sizes::Inline, .windowName = "Item Tracker Settings" } } } } });
|
||||
}
|
||||
|
||||
void AddDevTools() {
|
||||
|
506
mm/2s2h/Enhancements/Trackers/ItemTracker.cpp
Normal file
506
mm/2s2h/Enhancements/Trackers/ItemTracker.cpp
Normal file
@ -0,0 +1,506 @@
|
||||
#include "ItemTracker.h"
|
||||
#include "Context.h"
|
||||
#include "config/Config.h"
|
||||
#include "assets/archives/icon_item_static/icon_item_static_yar.h"
|
||||
#include "assets/archives/icon_item_24_static/icon_item_24_static_yar.h"
|
||||
|
||||
#define CFG_TRACKER_ITEM(var) ("ItemTracker." var)
|
||||
|
||||
using namespace Ship;
|
||||
|
||||
ItemTrackerWindow::~ItemTrackerWindow() {
|
||||
auto config = Context::GetInstance()->GetConsoleVariables();
|
||||
|
||||
config->SetFloat(CFG_TRACKER_ITEM("BgColorR"), mBgColor.x);
|
||||
config->SetFloat(CFG_TRACKER_ITEM("BgColorG"), mBgColor.y);
|
||||
config->SetFloat(CFG_TRACKER_ITEM("BgColorB"), mBgColor.z);
|
||||
config->SetFloat(CFG_TRACKER_ITEM("BgColorA"), mBgColor.w);
|
||||
config->SetFloat(CFG_TRACKER_ITEM("IconSize"), mIconSize);
|
||||
config->SetFloat(CFG_TRACKER_ITEM("IconSpacing"), mIconSpacing);
|
||||
config->SetFloat(CFG_TRACKER_ITEM("TextSize"), mTextSize);
|
||||
config->SetFloat(CFG_TRACKER_ITEM("TextOffset"), mTextOffset);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("WindowType"), (int8_t)mWindowType);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("IsDraggable"), mIsDraggable);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("OnlyDrawPaused"), mOnlyDrawPaused);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("DrawCurrentAmmo"), mCapacityModes[ItemTrackerCapacityMode::DrawCurrent]);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("DrawMaxAmmo"), mCapacityModes[ItemTrackerCapacityMode::DrawCurCapacity]);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("DrawMaxCapacity"), mCapacityModes[ItemTrackerCapacityMode::DrawMaxCapacity]);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("InventoryDrawMode"), (int8_t)mItemDrawModes[SECTION_INVENTORY]);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("MasksDrawMode"), (int8_t)mItemDrawModes[SECTION_MASKS]);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("SongsDrawMode"), (int8_t)mItemDrawModes[SECTION_SONGS]);
|
||||
config->SetInteger(CFG_TRACKER_ITEM("DungeonDrawMode"), (int8_t)mItemDrawModes[SECTION_DUNGEON]);
|
||||
|
||||
config->Save();
|
||||
}
|
||||
|
||||
void ItemTrackerWindow::LoadSettings() {
|
||||
auto config = Context::GetInstance()->GetConsoleVariables();
|
||||
|
||||
mCapacityModes.fill(false);
|
||||
|
||||
mBgColor.x = config->GetFloat(CFG_TRACKER_ITEM("BgColorR"), 0.0f);
|
||||
mBgColor.y = config->GetFloat(CFG_TRACKER_ITEM("BgColorG"), 0.0f);
|
||||
mBgColor.z = config->GetFloat(CFG_TRACKER_ITEM("BgColorB"), 0.0f);
|
||||
mBgColor.w = config->GetFloat(CFG_TRACKER_ITEM("BgColorA"), 0.0f);
|
||||
mIconSize = config->GetFloat(CFG_TRACKER_ITEM("IconSize"), 13.0f);
|
||||
mIconSpacing = config->GetFloat(CFG_TRACKER_ITEM("IconSpacing"), 12.0f);
|
||||
mTextSize = config->GetFloat(CFG_TRACKER_ITEM("TextSize"), 13.0f);
|
||||
mTextOffset = config->GetFloat(CFG_TRACKER_ITEM("TextOffset"), 0.0f);
|
||||
mWindowType =
|
||||
(TrackerWindowType)config->GetInteger(CFG_TRACKER_ITEM("WindowType"), (int8_t)TrackerWindowType::Floating);
|
||||
mIsDraggable = config->GetInteger(CFG_TRACKER_ITEM("IsDraggable"), false);
|
||||
mOnlyDrawPaused = config->GetInteger(CFG_TRACKER_ITEM("OnlyDrawPaused"), false);
|
||||
mCapacityModes[ItemTrackerCapacityMode::DrawCurrent] =
|
||||
config->GetInteger(CFG_TRACKER_ITEM("DrawCurrentAmmo"), false);
|
||||
mCapacityModes[ItemTrackerCapacityMode::DrawCurCapacity] =
|
||||
config->GetInteger(CFG_TRACKER_ITEM("DrawMaxAmmo"), false);
|
||||
mCapacityModes[ItemTrackerCapacityMode::DrawMaxCapacity] =
|
||||
config->GetInteger(CFG_TRACKER_ITEM("DrawMaxCapacity"), false);
|
||||
mItemDrawModes[SECTION_INVENTORY] = (ItemTrackerDisplayType)config->GetInteger(
|
||||
CFG_TRACKER_ITEM("InventoryDrawMode"), (int32_t)ItemTrackerDisplayType::Hidden);
|
||||
mItemDrawModes[SECTION_MASKS] = (ItemTrackerDisplayType)config->GetInteger(CFG_TRACKER_ITEM("MasksDrawMode"),
|
||||
(int32_t)ItemTrackerDisplayType::Hidden);
|
||||
mItemDrawModes[SECTION_SONGS] = (ItemTrackerDisplayType)config->GetInteger(CFG_TRACKER_ITEM("SongsDrawMode"),
|
||||
(int32_t)ItemTrackerDisplayType::Hidden);
|
||||
mItemDrawModes[SECTION_DUNGEON] = (ItemTrackerDisplayType)config->GetInteger(
|
||||
CFG_TRACKER_ITEM("DungeonDrawMode"), (int32_t)ItemTrackerDisplayType::Hidden);
|
||||
}
|
||||
|
||||
void ItemTrackerWindow::BeginFloatingWindows(const char* name, ImGuiWindowFlags flags) {
|
||||
ImGuiWindowFlags windowFlags = flags;
|
||||
|
||||
if (windowFlags == 0) {
|
||||
windowFlags |=
|
||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize;
|
||||
}
|
||||
|
||||
if (mWindowType == TrackerWindowType::Floating) {
|
||||
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
||||
windowFlags |= ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar;
|
||||
|
||||
if (!mIsDraggable) {
|
||||
windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove;
|
||||
}
|
||||
}
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, mBgColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
|
||||
ImGui::Begin(name, nullptr, windowFlags);
|
||||
}
|
||||
|
||||
void EndFloatingWindows() {
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static constexpr ImVec4 opaqueTex = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
static constexpr ImVec4 fadedTex = { 0.5f, 0.5f, 0.5f, 0.5f };
|
||||
|
||||
void DrawItem(char* tex, bool drawFaded, float itemSize) {
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(tex), ImVec2(itemSize, itemSize),
|
||||
ImVec2(0, 0), ImVec2(1, 1), drawFaded ? fadedTex : opaqueTex);
|
||||
}
|
||||
|
||||
static constexpr std::array<ImVec4, 5> songInfo = {
|
||||
ImVec4(0.588f, 1.0f, 0.392f, 1.0f), // QUEST_SONG_SONATA
|
||||
ImVec4(1.0f, 0.313f, 0.156f, 1.0f), // QUEST_SONG_LULLABY
|
||||
ImVec4(0.392f, 0.588f, 1.0f, 1.0f), // QUEST_SONG_BOSSA_NOVA
|
||||
ImVec4(1.0f, 0.627f, 0.0f, 1.0f), // QUEST_SONG_ELEGY
|
||||
ImVec4(1.0f, 0.392f, 1.0f, 1.0f), // QUEST_SONG_OATH
|
||||
};
|
||||
|
||||
void ItemTrackerWindow::DrawNote(size_t songIndex, bool drawFaded) {
|
||||
ImVec4 color;
|
||||
// Scale the note to 24*36 from 16*24 because all other items assume 36*36.
|
||||
constexpr float noteTo36scale = 36.0f / 24.0f;
|
||||
|
||||
const float iconScale = mIconSize / 36.0f;
|
||||
|
||||
// Scale the note icon with the rest of the items.
|
||||
const ImVec2 scaledNoteSize(noteTo36scale * 16.0f * iconScale, noteTo36scale * 24.0f * iconScale);
|
||||
|
||||
if (songIndex >= 5) {
|
||||
color = songInfo[songIndex - 5];
|
||||
} else {
|
||||
color = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
if (drawFaded) {
|
||||
color.w = .5f;
|
||||
}
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(gItemIconSongNoteTex),
|
||||
scaledNoteSize, ImVec2(0, 0), ImVec2(1, 1), color);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#include "z64save.h"
|
||||
#include "macros.h"
|
||||
#include "z64.h"
|
||||
extern void* gItemIcons[131];
|
||||
extern uint8_t gItemSlots[77];
|
||||
extern SaveContext gSaveContext;
|
||||
extern u32 gBitFlags[32];
|
||||
extern PlayState* gPlayState;
|
||||
extern u16 gUpgradeCapacities[][4];
|
||||
extern u32 gUpgradeMasks[];
|
||||
extern u8 gUpgradeShifts[];
|
||||
}
|
||||
|
||||
// The textures in gItemIcons aren't in the same order as the subscreen
|
||||
static constexpr std::array<const char*, 24> sMaskTextures = {
|
||||
gItemIconPostmansHatTex, gItemIconAllNightMaskTex, gItemIconBlastMaskTex, gItemIconStoneMaskTex,
|
||||
gItemIconGreatFairyMaskTex, gItemIconDekuMaskTex, gItemIconKeatonMaskTex, gItemIconBremenMaskTex,
|
||||
gItemIconBunnyHoodTex, gItemIconDonGeroMaskTex, gItemIconMaskOfScentsTex, gItemIconGoronMaskTex,
|
||||
gItemIconRomaniMaskTex, gItemIconCircusLeaderMaskTex, gItemIconKafeisMaskTex, gItemIconCouplesMaskTex,
|
||||
gItemIconMaskOfTruthTex, gItemIconZoraMaskTex, gItemIconKamaroMaskTex, gItemIconGibdoMaskTex,
|
||||
gItemIconGaroMaskTex, gItemIconCaptainsHatTex, gItemIconGiantsMaskTex, gItemIconFierceDeityMaskTex,
|
||||
};
|
||||
|
||||
// The songs in the enum are in the wrong order and has the unused songs
|
||||
static constexpr std::array<uint8_t, 10> sSongBits = {
|
||||
QUEST_SONG_TIME, QUEST_SONG_HEALING, QUEST_SONG_EPONA, QUEST_SONG_SOARING, QUEST_SONG_STORMS,
|
||||
QUEST_SONG_SONATA, QUEST_SONG_LULLABY, QUEST_SONG_BOSSA_NOVA, QUEST_SONG_ELEGY, QUEST_SONG_OATH,
|
||||
};
|
||||
|
||||
bool ItemTrackerWindow::HasAmmoCount(int itemId) {
|
||||
switch (itemId) {
|
||||
case ITEM_BOW:
|
||||
case ITEM_BOMB:
|
||||
case ITEM_BOMBCHU:
|
||||
case ITEM_DEKU_STICK:
|
||||
case ITEM_DEKU_NUT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ItemTrackerWindow::AmmoInfo ItemTrackerWindow::GetAmmoInfo(int itemId) {
|
||||
AmmoInfo info;
|
||||
switch (itemId) {
|
||||
case ITEM_BOW:
|
||||
info = { .cur = (uint8_t)AMMO(ITEM_BOW), .curCap = (uint8_t)CUR_CAPACITY(UPG_QUIVER), .maxCap = 50 };
|
||||
break;
|
||||
case ITEM_BOMB:
|
||||
info = { .cur = (uint8_t)AMMO(ITEM_BOMB), .curCap = (uint8_t)CUR_CAPACITY(UPG_BOMB_BAG), .maxCap = 40 };
|
||||
break;
|
||||
case ITEM_BOMBCHU:
|
||||
info = { .cur = (uint8_t)AMMO(ITEM_BOMBCHU), .curCap = (uint8_t)CUR_CAPACITY(UPG_BOMB_BAG), .maxCap = 40 };
|
||||
break;
|
||||
case ITEM_DEKU_STICK:
|
||||
info = { .cur = (uint8_t)AMMO(ITEM_DEKU_STICK),
|
||||
.curCap = (uint8_t)CUR_CAPACITY(UPG_DEKU_STICKS),
|
||||
.maxCap = 30 };
|
||||
break;
|
||||
case ITEM_DEKU_NUT:
|
||||
info = { .cur = (uint8_t)AMMO(ITEM_DEKU_NUT),
|
||||
.curCap = (uint8_t)CUR_CAPACITY(UPG_DEKU_NUTS),
|
||||
.maxCap = 40 };
|
||||
break;
|
||||
default:
|
||||
info = { 0 };
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void ItemTrackerWindow::DrawAmmoCount(int itemId, const ImVec2& iconPos) {
|
||||
// Zeroing 16 bytes is a little more optimized than 10
|
||||
char ammoStr[16] = { 0 };
|
||||
char curStr[4] = { 0 };
|
||||
char curCapStr[4] = { 0 };
|
||||
char maxCapStr[4] = { 0 };
|
||||
AmmoInfo info;
|
||||
|
||||
if (!HasAmmoCount(itemId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
info = GetAmmoInfo(itemId);
|
||||
|
||||
if (mCapacityModes[ItemTrackerCapacityMode::DrawCurrent]) {
|
||||
snprintf(curStr, std::size(curStr), "%d", info.cur);
|
||||
if (mCapacityModes[ItemTrackerCapacityMode::DrawCurCapacity] ||
|
||||
mCapacityModes[ItemTrackerCapacityMode::DrawMaxCapacity]) {
|
||||
strncat(curStr, "/", 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mCapacityModes[ItemTrackerCapacityMode::DrawCurCapacity]) {
|
||||
snprintf(curCapStr, std::size(curStr), "%d", info.curCap);
|
||||
if (mCapacityModes[ItemTrackerCapacityMode::DrawMaxCapacity]) {
|
||||
strncat(curCapStr, "/", 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mCapacityModes[ItemTrackerCapacityMode::DrawMaxCapacity]) {
|
||||
snprintf(maxCapStr, std::size(curStr), "%d", info.maxCap);
|
||||
}
|
||||
|
||||
ImGui::SetWindowFontScale(mTextSize / 13.0f);
|
||||
ImVec2 iconPos2 = ImGui::GetCursorScreenPos();
|
||||
|
||||
snprintf(ammoStr, std::size(ammoStr), "%s%s%s", curStr, curCapStr, maxCapStr);
|
||||
|
||||
float x = iconPos2.x + (mIconSize / 2.0f) - (ImGui::CalcTextSize(ammoStr).x / 2.0f);
|
||||
// Normalize the offset based on the icon being 36x36 to account for larger icons.
|
||||
ImGui::SetCursorScreenPos({ x, iconPos2.y - (mTextOffset / 36.0f) * mIconSize });
|
||||
|
||||
ImGui::Text("%s", ammoStr);
|
||||
}
|
||||
|
||||
int ItemTrackerWindow::DrawItems(int columns, int prevDrawnColumns) {
|
||||
int topPadding = 0;
|
||||
size_t i = 0;
|
||||
// Draw items minus bottles
|
||||
for (; i < 24 - BOTTLE_MAX; i++) {
|
||||
bool drawFaded = false;
|
||||
int row = prevDrawnColumns + (i / columns);
|
||||
int column = i % columns;
|
||||
char* texToDraw;
|
||||
const ImVec2 pos = { (column * (mIconSize + mIconSpacing) + 8.0f),
|
||||
(row * (mIconSize + mIconSpacing)) + 8.0f + topPadding };
|
||||
|
||||
ImGui::SetCursorPos(pos);
|
||||
|
||||
if (gSaveContext.save.saveInfo.inventory.items[i] == ITEM_NONE) {
|
||||
if (column == 5) {
|
||||
// BENTODO these slots can hold multiple items. Something fun to do would be to draw the multitile
|
||||
// design here instead of nothing DrawMultiItem(nullptr, false, row, column);
|
||||
continue;
|
||||
}
|
||||
texToDraw = (char*)gItemIcons[i];
|
||||
drawFaded = true;
|
||||
} else {
|
||||
texToDraw = (char*)gItemIcons[gSaveContext.save.saveInfo.inventory.items[i]];
|
||||
}
|
||||
ImGui::BeginGroup();
|
||||
DrawItem(texToDraw, drawFaded, mIconSize);
|
||||
DrawAmmoCount((int)i, pos);
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
// DrawBottles
|
||||
for (; i < 24; i++) {
|
||||
int row = prevDrawnColumns + (i / columns);
|
||||
int column = i % columns;
|
||||
ImGui::SetCursorPos(ImVec2((column * (mIconSize + mIconSpacing) + 8.0f),
|
||||
(row * (mIconSize + mIconSpacing)) + 8.0f + topPadding));
|
||||
|
||||
if (gSaveContext.save.saveInfo.inventory.items[i] == ITEM_NONE) {
|
||||
DrawItem(const_cast<char*>(gItemIconEmptyBottleTex), true, mIconSize);
|
||||
} else {
|
||||
DrawItem((char*)gItemIcons[gSaveContext.save.saveInfo.inventory.items[i]], false, mIconSize);
|
||||
}
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
int ItemTrackerWindow::DrawMasks(int columns, int prevDrawnColumns) {
|
||||
int topPadding = 0;
|
||||
// Masks
|
||||
for (size_t i = 0; i < 24; i++) {
|
||||
int row = prevDrawnColumns + (i / columns);
|
||||
int column = i % columns;
|
||||
ImGui::SetCursorPos(ImVec2((column * (mIconSize + mIconSpacing) + 8.0f),
|
||||
(row * (mIconSize + mIconSpacing)) + 8.0f + topPadding));
|
||||
|
||||
DrawItem(const_cast<char*>(sMaskTextures[i]), gSaveContext.save.saveInfo.inventory.items[i + 24] == ITEM_NONE,
|
||||
mIconSize);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int RoundDown(int orig, int nearest) {
|
||||
int res = orig % nearest;
|
||||
return orig - res;
|
||||
}
|
||||
|
||||
int ItemTrackerWindow::DrawSongs(int columns, int prevDrawnColumns) {
|
||||
int topPadding = 0;
|
||||
|
||||
for (size_t i = 0; i < sSongBits.size(); i++) {
|
||||
int row = prevDrawnColumns + (i / 5);
|
||||
int column = i % 5;
|
||||
ImGui::SetCursorPos(ImVec2((column * (mIconSize + mIconSpacing) + 8.0f),
|
||||
(row * (mIconSize + mIconSpacing)) + 8.0f + topPadding));
|
||||
|
||||
DrawNote(i, !CHECK_QUEST_ITEM(sSongBits[i]));
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
int ItemTrackerWindow::DrawDungeonItemsVert(int columns, int prevDrawnColumns) {
|
||||
int topPadding = 0;
|
||||
|
||||
// The icon size is based on 36x36.
|
||||
float iconScale = mIconSize / 36.0f;
|
||||
// Yes this does nothing. But for other icon sizes it will.
|
||||
float squareIconSize = iconScale * 36.0f;
|
||||
float rectIconSize = iconScale * 36.0f;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
int row = prevDrawnColumns + (i / columns);
|
||||
int column = i % columns;
|
||||
ImGui::SetCursorPos(ImVec2((column * (squareIconSize + mIconSpacing) + 8.0f),
|
||||
(row * (squareIconSize + mIconSpacing)) + 8.0f + topPadding));
|
||||
DrawItem(static_cast<char*>(gItemIcons[i + ITEM_REMAINS_ODOLWA]), !CHECK_QUEST_ITEM(i), squareIconSize);
|
||||
}
|
||||
|
||||
prevDrawnColumns++;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
int row = prevDrawnColumns + (i / columns);
|
||||
int column = i % columns;
|
||||
ImGui::SetCursorPos(ImVec2((column * (rectIconSize + mIconSpacing) + 8.0f),
|
||||
(row * (rectIconSize + mIconSpacing)) + 8.0f + topPadding));
|
||||
DrawItem(const_cast<char*>(gQuestIconBossKeyTex), !CHECK_DUNGEON_ITEM(DUNGEON_BOSS_KEY, i), rectIconSize);
|
||||
}
|
||||
|
||||
prevDrawnColumns++;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
int row = prevDrawnColumns + (i / columns);
|
||||
int column = i % columns;
|
||||
ImGui::SetCursorPos(ImVec2((column * (rectIconSize + mIconSpacing) + 8.0f),
|
||||
(row * (rectIconSize + mIconSpacing)) + 8.0f + topPadding));
|
||||
DrawItem(const_cast<char*>(gQuestIconCompassTex), !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, i), rectIconSize);
|
||||
}
|
||||
|
||||
prevDrawnColumns++;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
int row = prevDrawnColumns + (i / columns);
|
||||
int column = i % columns;
|
||||
ImGui::SetCursorPos(ImVec2((column * (rectIconSize + mIconSpacing) + 8.0f),
|
||||
(row * (rectIconSize + mIconSpacing)) + 8.0f + topPadding));
|
||||
DrawItem(const_cast<char*>(gQuestIconDungeonMapTex), !CHECK_DUNGEON_ITEM(DUNGEON_MAP, i), rectIconSize);
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
void ItemTrackerWindow::DrawItemsInRows(int columns) {
|
||||
float iconSize = mIconSize;
|
||||
float iconSpacing = mIconSpacing;
|
||||
int topPadding = 0;
|
||||
int mainWindowPos = 0;
|
||||
int advancedBy = 0;
|
||||
|
||||
if (gPlayState == nullptr) {
|
||||
ImGui::Text("Item tracker not available");
|
||||
return;
|
||||
}
|
||||
if (mOnlyDrawPaused && gPlayState->pauseCtx.state == 0) {
|
||||
return;
|
||||
}
|
||||
if (mItemDrawModes[SECTION_INVENTORY] != ItemTrackerDisplayType::Hidden) {
|
||||
if (mItemDrawModes[SECTION_INVENTORY] == ItemTrackerDisplayType::Seperate) {
|
||||
BeginFloatingWindows("Items");
|
||||
}
|
||||
advancedBy = DrawItems(6, mainWindowPos);
|
||||
if (mItemDrawModes[SECTION_INVENTORY] == ItemTrackerDisplayType::Seperate) {
|
||||
EndFloatingWindows();
|
||||
} else {
|
||||
mainWindowPos += advancedBy;
|
||||
}
|
||||
}
|
||||
|
||||
if (mItemDrawModes[SECTION_MASKS] != ItemTrackerDisplayType::Hidden) {
|
||||
int drawPos = mainWindowPos;
|
||||
if (mItemDrawModes[SECTION_MASKS] == ItemTrackerDisplayType::Seperate) {
|
||||
drawPos = 0;
|
||||
BeginFloatingWindows("Masks");
|
||||
}
|
||||
advancedBy = DrawMasks(6, drawPos);
|
||||
if (mItemDrawModes[SECTION_MASKS] == ItemTrackerDisplayType::Seperate) {
|
||||
EndFloatingWindows();
|
||||
} else {
|
||||
mainWindowPos += advancedBy;
|
||||
}
|
||||
}
|
||||
|
||||
if (mItemDrawModes[SECTION_SONGS] != ItemTrackerDisplayType::Hidden) {
|
||||
int drawPos = mainWindowPos;
|
||||
if (mItemDrawModes[SECTION_SONGS] == ItemTrackerDisplayType::Seperate) {
|
||||
drawPos = 0;
|
||||
BeginFloatingWindows("Songs");
|
||||
}
|
||||
advancedBy = DrawSongs(5, drawPos);
|
||||
if (mItemDrawModes[SECTION_SONGS] == ItemTrackerDisplayType::Seperate) {
|
||||
EndFloatingWindows();
|
||||
} else {
|
||||
mainWindowPos += advancedBy;
|
||||
}
|
||||
}
|
||||
|
||||
if (mItemDrawModes[SECTION_DUNGEON] != ItemTrackerDisplayType::Hidden) {
|
||||
int drawPos = mainWindowPos;
|
||||
if (mItemDrawModes[SECTION_DUNGEON] == ItemTrackerDisplayType::Seperate) {
|
||||
drawPos = 0;
|
||||
BeginFloatingWindows("Dungeon Items");
|
||||
}
|
||||
advancedBy = DrawDungeonItemsVert(6, drawPos);
|
||||
if (mItemDrawModes[SECTION_DUNGEON] == ItemTrackerDisplayType::Seperate) {
|
||||
EndFloatingWindows();
|
||||
} else {
|
||||
mainWindowPos += advancedBy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImVec4* ItemTrackerWindow::GetBgColorPtr() {
|
||||
return &mBgColor;
|
||||
}
|
||||
|
||||
float* ItemTrackerWindow::GetIconSizePtr() {
|
||||
return &mIconSize;
|
||||
}
|
||||
|
||||
float* ItemTrackerWindow::GetIconSpacingPtr() {
|
||||
return &mIconSpacing;
|
||||
}
|
||||
|
||||
float* ItemTrackerWindow::GetTextSizePtr() {
|
||||
return &mTextSize;
|
||||
}
|
||||
|
||||
float* ItemTrackerWindow::GetTextOffsetPtr() {
|
||||
return &mTextOffset;
|
||||
}
|
||||
|
||||
TrackerWindowType* ItemTrackerWindow::GetWindowTypePtr() {
|
||||
return &mWindowType;
|
||||
}
|
||||
|
||||
bool* ItemTrackerWindow::GetIsDraggablePtr() {
|
||||
return &mIsDraggable;
|
||||
}
|
||||
|
||||
bool* ItemTrackerWindow::GetOnlyShowPausedPtr() {
|
||||
return &mOnlyDrawPaused;
|
||||
}
|
||||
|
||||
ItemTrackerDisplayType* ItemTrackerWindow::GetDrawModePtr(ItemTrackerSection type) {
|
||||
return &mItemDrawModes[type];
|
||||
}
|
||||
|
||||
bool* ItemTrackerWindow::GetCapacityModePtr(ItemTrackerCapacityMode mode) {
|
||||
return &mCapacityModes[mode];
|
||||
}
|
||||
|
||||
void ItemTrackerWindow::Draw() {
|
||||
if (!IsVisible()) {
|
||||
return;
|
||||
}
|
||||
BeginFloatingWindows("Inventory Items Tracker");
|
||||
DrawItemsInRows();
|
||||
EndFloatingWindows();
|
||||
}
|
||||
void ItemTrackerWindow::InitElement() {
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
void ItemTrackerWindow::DrawElement() {
|
||||
}
|
82
mm/2s2h/Enhancements/Trackers/ItemTracker.h
Normal file
82
mm/2s2h/Enhancements/Trackers/ItemTracker.h
Normal file
@ -0,0 +1,82 @@
|
||||
#include "window/gui/Gui.h"
|
||||
#include "window/gui/GuiWindow.h"
|
||||
#include <array>
|
||||
|
||||
typedef enum class TrackerWindowType : uint8_t {
|
||||
Floating,
|
||||
Window,
|
||||
} TrackerWindowType;
|
||||
|
||||
typedef enum class ItemTrackerDisplayType : int8_t {
|
||||
Hidden,
|
||||
MainWindow,
|
||||
Seperate,
|
||||
} ItemTrackerDisplayType;
|
||||
|
||||
typedef enum {
|
||||
SECTION_INVENTORY,
|
||||
SECTION_MASKS,
|
||||
SECTION_SONGS,
|
||||
SECTION_DUNGEON,
|
||||
SECTION_MAX,
|
||||
} ItemTrackerSection;
|
||||
|
||||
typedef enum {
|
||||
DrawCurrent,
|
||||
DrawCurCapacity,
|
||||
DrawMaxCapacity,
|
||||
DrawCapacityMax,
|
||||
} ItemTrackerCapacityMode;
|
||||
|
||||
class ItemTrackerWindow : public Ship::GuiWindow {
|
||||
typedef struct AmmoInfo {
|
||||
uint8_t cur;
|
||||
uint8_t curCap;
|
||||
uint8_t maxCap;
|
||||
} AmmoInfo;
|
||||
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
~ItemTrackerWindow();
|
||||
void Draw() override;
|
||||
|
||||
ImVec4* GetBgColorPtr();
|
||||
float* GetIconSizePtr();
|
||||
float* GetIconSpacingPtr();
|
||||
float* GetTextSizePtr();
|
||||
float* GetTextOffsetPtr();
|
||||
TrackerWindowType* GetWindowTypePtr();
|
||||
bool* GetIsDraggablePtr();
|
||||
bool* GetOnlyShowPausedPtr();
|
||||
ItemTrackerDisplayType* GetDrawModePtr(ItemTrackerSection type);
|
||||
bool* GetCapacityModePtr(ItemTrackerCapacityMode mode);
|
||||
void LoadSettings();
|
||||
|
||||
protected:
|
||||
void InitElement() override;
|
||||
void DrawElement() override;
|
||||
void UpdateElement() override{};
|
||||
|
||||
private:
|
||||
void BeginFloatingWindows(const char* name, ImGuiWindowFlags flags = 0);
|
||||
void DrawItemsInRows(int columns = 6);
|
||||
int DrawItems(int columns, int startAt);
|
||||
int DrawMasks(int columns, int startAt);
|
||||
int DrawSongs(int columns, int startAt);
|
||||
void DrawNote(size_t songIndex, bool drawFaded);
|
||||
int DrawDungeonItemsVert(int columns, int startAt);
|
||||
void DrawAmmoCount(int itemId, const ImVec2& iconPos);
|
||||
bool HasAmmoCount(int itemId);
|
||||
AmmoInfo GetAmmoInfo(int itemId);
|
||||
|
||||
ImVec4 mBgColor;
|
||||
float mIconSize = 36.0f;
|
||||
float mIconSpacing = 12.0f;
|
||||
float mTextSize = 13.0f;
|
||||
float mTextOffset = 0.0f;
|
||||
TrackerWindowType mWindowType = TrackerWindowType::Floating;
|
||||
bool mIsDraggable = false;
|
||||
bool mOnlyDrawPaused = false;
|
||||
std::array<bool, DrawCapacityMax> mCapacityModes;
|
||||
std::array<ItemTrackerDisplayType, SECTION_MAX> mItemDrawModes;
|
||||
};
|
77
mm/2s2h/Enhancements/Trackers/ItemTrackerSettings.cpp
Normal file
77
mm/2s2h/Enhancements/Trackers/ItemTrackerSettings.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "ItemTrackerSettings.h"
|
||||
#include "ItemTracker.h"
|
||||
#include "../../BenGui/UIWidgets.hpp"
|
||||
|
||||
namespace BenGui {
|
||||
extern std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||
}
|
||||
|
||||
using namespace BenGui;
|
||||
|
||||
void ItemTrackerSettingsWindow::UpdateElement() {
|
||||
}
|
||||
|
||||
void ItemTrackerSettingsWindow::InitElement() {
|
||||
}
|
||||
|
||||
static const char* windowTypes[2] = { "Floating", "Window" };
|
||||
static const char* displayTypes[3] = { "Hidden", "Main Window", "Separate" };
|
||||
static const char* displayModes[2] = { "Always", "Combo Button Hold" };
|
||||
|
||||
void ItemTrackerSettingsWindow::DrawElement() {
|
||||
ImGui::SetNextWindowSize(ImVec2(733, 472), ImGuiCond_FirstUseEver);
|
||||
const UIWidgets::FloatSliderOptions sliderOpts = { .format = "%.0f", .step = 1.0f };
|
||||
|
||||
if (!ImGui::BeginChild("Item Tracker Settings")) {
|
||||
ImGui::EndChild();
|
||||
return;
|
||||
}
|
||||
|
||||
UIWidgets::WindowButton("Show/Hide Item Tracker", "gWindows.ItemTracker", mItemTrackerWindow,
|
||||
{ .size = UIWidgets::Sizes::Inline });
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f });
|
||||
ImGui::BeginTable("itemTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV);
|
||||
ImGui::TableSetupColumn("General settings", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||
ImGui::TableSetupColumn("Section settings", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||
ImGui::TableHeadersRow();
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("BG Color");
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
||||
ImGui::ColorEdit4("BG Color", (float*)mItemTrackerWindow->GetBgColorPtr(),
|
||||
ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_NoLabel);
|
||||
|
||||
UIWidgets::Combobox("Window Type", mItemTrackerWindow->GetWindowTypePtr(), windowTypes);
|
||||
UIWidgets::Checkbox("Enable Dragging", mItemTrackerWindow->GetIsDraggablePtr());
|
||||
UIWidgets::Checkbox("Only enable while paused", mItemTrackerWindow->GetOnlyShowPausedPtr());
|
||||
|
||||
UIWidgets::SliderFloat("Icon size : %.0fpx", mItemTrackerWindow->GetIconSizePtr(), 0.0f, 128.0f, sliderOpts);
|
||||
UIWidgets::SliderFloat("Icon margins : %.0fpx", mItemTrackerWindow->GetIconSpacingPtr(), -5.0f, 50.0f, sliderOpts);
|
||||
UIWidgets::SliderFloat("Text size : %.0fpx", mItemTrackerWindow->GetTextSizePtr(), 1.0f, 30.0f, sliderOpts);
|
||||
UIWidgets::SliderFloat("Text Offset : %0.fpx", mItemTrackerWindow->GetTextOffsetPtr(), 0.0f, 40.0f, sliderOpts);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
UIWidgets::Combobox("Inventory", mItemTrackerWindow->GetDrawModePtr(SECTION_INVENTORY), displayTypes);
|
||||
UIWidgets::Combobox("Masks", mItemTrackerWindow->GetDrawModePtr(SECTION_MASKS), displayTypes);
|
||||
UIWidgets::Combobox("Songs", mItemTrackerWindow->GetDrawModePtr(SECTION_SONGS), displayTypes);
|
||||
UIWidgets::Combobox("Dungeon Items", mItemTrackerWindow->GetDrawModePtr(SECTION_DUNGEON), displayTypes);
|
||||
|
||||
UIWidgets::Checkbox("Draw Current Ammo",
|
||||
mItemTrackerWindow->GetCapacityModePtr(ItemTrackerCapacityMode::DrawCurrent));
|
||||
|
||||
UIWidgets::Checkbox("Draw Current Capacity",
|
||||
mItemTrackerWindow->GetCapacityModePtr(ItemTrackerCapacityMode::DrawCurCapacity));
|
||||
|
||||
UIWidgets::Checkbox("Draw Max Capacity",
|
||||
mItemTrackerWindow->GetCapacityModePtr(ItemTrackerCapacityMode::DrawMaxCapacity));
|
||||
|
||||
ImGui::PopStyleVar(1);
|
||||
ImGui::EndTable();
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
12
mm/2s2h/Enhancements/Trackers/ItemTrackerSettings.h
Normal file
12
mm/2s2h/Enhancements/Trackers/ItemTrackerSettings.h
Normal file
@ -0,0 +1,12 @@
|
||||
#include "window/gui/Gui.h"
|
||||
#include "window/gui/GuiWindow.h"
|
||||
|
||||
class ItemTrackerSettingsWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
protected:
|
||||
void InitElement() override;
|
||||
void DrawElement() override;
|
||||
void UpdateElement() override;
|
||||
};
|
Loading…
Reference in New Issue
Block a user