Skip to content

Commit 52a4132

Browse files
authored
Merge pull request #2221 from gwdevhub/claude/issue-2218-20260607-2128
fix: hero build edits now persist and allow re-adding deleted slots
2 parents bce06df + 67dcb22 commit 52a4132

4 files changed

Lines changed: 112 additions & 101 deletions

File tree

GWToolboxdll/Utils/TeamBuild.cpp

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ void TeamBuild::Load() const
595595
// ------------------------------------------------------------
596596
// Player-builds layout (BuildsWindow style)
597597
// ------------------------------------------------------------
598-
void TeamBuild::DrawPlayerBuildsContent(bool& builds_changed, bool editable)
598+
void TeamBuild::DrawPlayerBuildsContent(bool& builds_modified, bool editable)
599599
{
600600
const float font_scale = ImGui::FontScale();
601601
const auto row_height = ImGui::CalcTextSize(" ").y * 2.f;
@@ -609,8 +609,8 @@ void TeamBuild::DrawPlayerBuildsContent(bool& builds_changed, bool editable)
609609
const auto* me = GW::Agents::GetControlledCharacter();
610610
const auto player_profession = me ? static_cast<GW::Constants::Profession>(me->primary) : GW::Constants::Profession::None;
611611

612-
bool tmp = builds_changed;
613-
builds_changed = false;
612+
bool tmp = builds_modified;
613+
builds_modified = false;
614614

615615
for (size_t j = 0; j < builds.size(); j++) {
616616
Build& build = builds[j];
@@ -736,7 +736,7 @@ void TeamBuild::DrawPlayerBuildsContent(bool& builds_changed, bool editable)
736736
editing_build_idx_--;
737737
builds.erase(builds.begin() + static_cast<ptrdiff_t>(j));
738738
ResetEncodedCache();
739-
builds_changed = true;
739+
builds_modified = true;
740740
ImGui::EndPopup();
741741
ImGui::PopID();
742742
break;
@@ -771,15 +771,15 @@ void TeamBuild::DrawPlayerBuildsContent(bool& builds_changed, bool editable)
771771
}
772772
ImGui::Unindent();
773773
ImGui::PopID();
774-
if (builds_changed) break;
774+
if (builds_modified) break;
775775
}
776776

777-
builds_changed |= tmp;
777+
builds_modified |= tmp;
778778

779779
ImGui::Spacing();
780780

781781
if (editable) {
782-
if (ImGui::Checkbox("Show numbers", &show_numbers)) builds_changed = true;
782+
ImGui::Checkbox("Show numbers", &show_numbers);
783783
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Prefix build names with their index when sending to chat");
784784

785785
ImGui::SameLine();
@@ -789,15 +789,15 @@ void TeamBuild::DrawPlayerBuildsContent(bool& builds_changed, bool editable)
789789
builds.emplace_back("", "");
790790
ResetEncodedCache();
791791
editing_build_idx_ = static_cast<int>(builds.size()) - 1;
792-
builds_changed = true;
792+
builds_modified = true;
793793
}
794794
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add another build row");
795795
}
796796
}
797797
// ------------------------------------------------------------
798798
// Hero-builds layout (HeroBuildsWindow style)
799799
// ------------------------------------------------------------
800-
void TeamBuild::DrawHeroBuildsContent(bool& builds_changed, bool editable)
800+
void TeamBuild::DrawHeroBuildsContent(bool& builds_modified, bool editable)
801801
{
802802
const float font_scale = ImGui::FontScale();
803803
const auto row_height = ImGui::CalcTextSize(" ").y * 2.f;
@@ -811,8 +811,8 @@ void TeamBuild::DrawHeroBuildsContent(bool& builds_changed, bool editable)
811811
const auto* me = GW::Agents::GetControlledCharacter();
812812
const auto player_profession = me ? static_cast<GW::Constants::Profession>(me->primary) : GW::Constants::Profession::None;
813813

814-
bool tmp = builds_changed;
815-
builds_changed = false;
814+
bool tmp = builds_modified;
815+
builds_modified = false;
816816

817817
size_t player_idx = builds.size();
818818
for (size_t j = 0; j < builds.size(); ++j) {
@@ -957,7 +957,7 @@ void TeamBuild::DrawHeroBuildsContent(bool& builds_changed, bool editable)
957957
if (ImGui::MenuItem(ICON_FA_ARROW_UP " Move up")) {
958958
std::swap(builds[j - 1], builds[j]);
959959
ResetEncodedCache();
960-
builds_changed = true;
960+
builds_modified = true;
961961
ImGui::EndPopup();
962962
ImGui::Unindent();
963963
ImGui::PopID();
@@ -968,7 +968,7 @@ void TeamBuild::DrawHeroBuildsContent(bool& builds_changed, bool editable)
968968
if (ImGui::MenuItem(ICON_FA_ARROW_DOWN " Move down")) {
969969
std::swap(builds[j], builds[j + 1]);
970970
ResetEncodedCache();
971-
builds_changed = true;
971+
builds_modified = true;
972972
ImGui::EndPopup();
973973
ImGui::Unindent();
974974
ImGui::PopID();
@@ -986,7 +986,7 @@ void TeamBuild::DrawHeroBuildsContent(bool& builds_changed, bool editable)
986986
editing_build_idx_--;
987987
builds.erase(builds.begin() + static_cast<ptrdiff_t>(j));
988988
ResetEncodedCache();
989-
builds_changed = true;
989+
builds_modified = true;
990990
ImGui::EndPopup();
991991
ImGui::Unindent();
992992
ImGui::PopID();
@@ -1016,7 +1016,6 @@ void TeamBuild::DrawHeroBuildsContent(bool& builds_changed, bool editable)
10161016
)) {
10171017
build.hero_id = (combo_idx >= 0 && combo_idx < static_cast<int>(sorted_heroes.size())) ? sorted_heroes[combo_idx] : HeroID::NoHero;
10181018
ResetEncodedCache();
1019-
builds_changed = true;
10201019
}
10211020
ImGui::PopItemWidth();
10221021

@@ -1025,7 +1024,6 @@ void TeamBuild::DrawHeroBuildsContent(bool& builds_changed, bool editable)
10251024
const auto* panel_icon = reinterpret_cast<const char*>(build.show_panel ? ICON_FA_EYE : ICON_FA_EYE_SLASH);
10261025
if (ImGui::Button(panel_icon, icon_btn_size)) {
10271026
build.show_panel = !build.show_panel;
1028-
builds_changed = true;
10291027
}
10301028
if (ImGui::IsItemHovered()) ImGui::SetTooltip(build.show_panel ? "Hero panel: Show" : "Hero panel: Hide");
10311029

@@ -1120,19 +1118,40 @@ void TeamBuild::DrawHeroBuildsContent(bool& builds_changed, bool editable)
11201118
ImGui::Unindent();
11211119
if (editing) ImGui::Spacing();
11221120
ImGui::PopID();
1123-
if (builds_changed) break;
1121+
if (builds_modified) break;
11241122
}
11251123

1126-
builds_changed |= tmp;
1124+
builds_modified |= tmp;
11271125

11281126
ImGui::Spacing();
1127+
1128+
if (editable) {
1129+
const bool has_player_slot = player_idx < builds.size();
1130+
if (!has_player_slot && builds.size() < 8) {
1131+
if (ImGui::Button("Add Player Slot")) {
1132+
builds.insert(builds.begin(), Build("", "", HeroID::NoHero, 0, 1));
1133+
ResetEncodedCache();
1134+
builds_modified = true;
1135+
}
1136+
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a player build slot");
1137+
ImGui::SameLine();
1138+
}
1139+
if (builds.size() < 8) {
1140+
if (ImGui::Button("Add Hero Slot")) {
1141+
builds.push_back(Build("", "", HeroID::NoHero, 0, 1));
1142+
ResetEncodedCache();
1143+
builds_modified = true;
1144+
}
1145+
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a hero build slot");
1146+
}
1147+
}
11291148
}
11301149

11311150
// ------------------------------------------------------------
11321151
// DrawEditWindow
11331152
// ------------------------------------------------------------
11341153

1135-
bool TeamBuild::DrawEditWindow(size_t index, std::vector<TeamBuild>& all_builds, bool& builds_changed)
1154+
bool TeamBuild::DrawEditWindow(size_t index, std::vector<TeamBuild>& all_builds, bool& builds_modified)
11361155
{
11371156
const auto winname = std::format("{}###teambuild_{}", name, ui_id);
11381157
ImGui::SetNextWindowCenter(ImGuiCond_FirstUseEver);
@@ -1149,33 +1168,33 @@ bool TeamBuild::DrawEditWindow(size_t index, std::vector<TeamBuild>& all_builds,
11491168
}
11501169

11511170
if (has_hero_slots) {
1152-
builds_changed |= ImGui::InputText("Hero Build Name", name, 128);
1153-
builds_changed |= ImGui::InputText("Group", group, 128);
1171+
ImGui::InputText("Hero Build Name", name, 128);
1172+
ImGui::InputText("Group", group, 128);
11541173
if (ImGui::IsItemHovered()) {
11551174
ImGui::SetTooltip("Assign to a group. Builds sharing a group name are shown together under a collapsible header.");
11561175
}
1157-
DrawHeroBuildsContent(builds_changed);
1176+
DrawHeroBuildsContent(builds_modified);
11581177
}
11591178
else {
11601179
ImGui::PushItemWidth(-120.f);
1161-
builds_changed |= ImGui::InputText("Build Name", name, 128);
1180+
ImGui::InputText("Build Name", name, 128);
11621181
ImGui::PopItemWidth();
1163-
DrawPlayerBuildsContent(builds_changed);
1182+
DrawPlayerBuildsContent(builds_modified);
11641183
}
11651184

11661185
ImGui::Spacing();
11671186

11681187
// Teambuild reordering and deletion
11691188
if (ImGui::Button("Up") && index > 0) {
11701189
std::swap(all_builds[index - 1], all_builds[index]);
1171-
builds_changed = true;
1190+
builds_modified = true;
11721191
}
11731192
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Move the teambuild up in the list");
11741193

11751194
ImGui::SameLine();
11761195
if (ImGui::Button("Down") && index + 1 < all_builds.size()) {
11771196
std::swap(all_builds[index], all_builds[index + 1]);
1178-
builds_changed = true;
1197+
builds_modified = true;
11791198
}
11801199
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Move the teambuild down in the list");
11811200

@@ -1186,7 +1205,7 @@ bool TeamBuild::DrawEditWindow(size_t index, std::vector<TeamBuild>& all_builds,
11861205
cpy.edit_open = true;
11871206
edit_open = false;
11881207
all_builds.push_back(std::move(cpy));
1189-
builds_changed = true;
1208+
builds_modified = true;
11901209
ImGui::End();
11911210
return false;
11921211
}
@@ -1196,7 +1215,7 @@ bool TeamBuild::DrawEditWindow(size_t index, std::vector<TeamBuild>& all_builds,
11961215
bool deleted = false;
11971216
if (ImGui::ConfirmButton("Delete", &deleted, "Delete Teambuild?\n\nAre you sure?\nThis operation cannot be undone.\n\n")) {
11981217
all_builds.erase(all_builds.begin() + static_cast<ptrdiff_t>(index));
1199-
builds_changed = true;
1218+
builds_modified = true;
12001219
ImGui::End();
12011220
return false;
12021221
}
@@ -1206,9 +1225,7 @@ bool TeamBuild::DrawEditWindow(size_t index, std::vector<TeamBuild>& all_builds,
12061225
ImGui::SameLine();
12071226
ImGui::PushItemWidth(110.f);
12081227
constexpr const char* modes[] = {"Don't change", "Normal Mode", "Hard Mode"};
1209-
if (ImGui::Combo("Mode", &mode, modes, 3)) {
1210-
builds_changed = true;
1211-
}
1228+
ImGui::Combo("Mode", &mode, modes, 3);
12121229
ImGui::PopItemWidth();
12131230

12141231
ImGui::SameLine(ImGui::GetContentRegionAvail().x + ImGui::GetCursorPosX() - 40);
@@ -1258,7 +1275,7 @@ bool TeamBuild::DrawEditWindow(size_t index, std::vector<TeamBuild>& all_builds,
12581275
// ------------------------------------------------------------
12591276
// DrawDetachedWindow
12601277
// ------------------------------------------------------------
1261-
void TeamBuild::DrawDetachedWindow(std::vector<TeamBuild>& hero_builds, bool& builds_changed)
1278+
void TeamBuild::DrawDetachedWindow(std::vector<TeamBuild>& hero_builds, bool& builds_modified)
12621279
{
12631280
if (!edit_open) return;
12641281
const auto winname = std::format("{}###detached_{}", name, ui_id);
@@ -1275,9 +1292,9 @@ void TeamBuild::DrawDetachedWindow(std::vector<TeamBuild>& hero_builds, bool& bu
12751292
}
12761293

12771294
if (has_hero_slots)
1278-
DrawHeroBuildsContent(builds_changed, false);
1295+
DrawHeroBuildsContent(builds_modified, false);
12791296
else
1280-
DrawPlayerBuildsContent(builds_changed, false);
1297+
DrawPlayerBuildsContent(builds_modified, false);
12811298

12821299
// ---- Bottom buttons (detached-specific) ----
12831300
if (has_hero_slots) {
@@ -1290,7 +1307,7 @@ void TeamBuild::DrawDetachedWindow(std::vector<TeamBuild>& hero_builds, bool& bu
12901307
copy.edit_open = false;
12911308
if (copy.has_hero_slots) {
12921309
hero_builds.push_back(std::move(copy));
1293-
builds_changed = true;
1310+
builds_modified = true;
12941311
}
12951312
else {
12961313
BuildsWindow::Instance().AddTeambuild(std::move(copy));

GWToolboxdll/Utils/TeamBuild.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,19 @@ struct TeamBuild {
9595
//
9696
// index – position of this TeamBuild in all_builds.
9797
// all_builds – the owning vector; may be modified (reorder / delete).
98-
// builds_changed – set true when any data is modified.
98+
// builds_modified – set true when the vector is structurally modified (invalidates iterators).
9999
//
100100
// Returns false when this teambuild was deleted (erased from all_builds).
101101
bool DrawEditWindow(
102102
size_t index,
103103
std::vector<TeamBuild>& all_builds,
104-
bool& builds_changed
104+
bool& builds_modified
105105
);
106106

107107
// Draw a read-only detached window for a teambuild received via chat link.
108-
// hero_builds / builds_changed are the HeroBuildsWindow-owned list used by
108+
// hero_builds / builds_modified are the HeroBuildsWindow-owned list used by
109109
// the "Add to My Builds" button.
110-
void DrawDetachedWindow(std::vector<TeamBuild>& hero_builds, bool& builds_changed);
110+
void DrawDetachedWindow(std::vector<TeamBuild>& hero_builds, bool& builds_modified);
111111

112112
// Provide the 2×2 sprite sheet used to render the disabled-skill overlay.
113113
// Call once from HeroBuildsWindow::Initialize().
@@ -136,7 +136,7 @@ struct TeamBuild {
136136
// Returns the encoded wstring, computing and caching it on first call.
137137
const std::wstring& GetEncoded() const;
138138

139-
void DrawPlayerBuildsContent(bool& builds_changed, bool editable = true);
139+
void DrawPlayerBuildsContent(bool& builds_modified, bool editable = true);
140140

141-
void DrawHeroBuildsContent(bool& builds_changed, bool editable = true);
141+
void DrawHeroBuildsContent(bool& builds_modified, bool editable = true);
142142
};

GWToolboxdll/Windows/BuildsWindow.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,6 @@ namespace {
609609

610610
void SaveToFile()
611611
{
612-
if (!(builds_changed || GWToolbox::SettingsFolderChanged()))
613-
return;
614612
if (inifile == nullptr) {
615613
inifile = new ToolboxIni();
616614
}

0 commit comments

Comments
 (0)