about summary refs log tree commit diff stats
path: root/src/area_popup.cpp
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2025-03-10 12:45:14 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2025-03-10 12:45:14 -0400
commit79424e86dd7aa28c1b25868d86fa8ebffc801593 (patch)
treeebbc23fb998f14d69e638ce8b973b5a7da0b46c6 /src/area_popup.cpp
parentd3457700075fab2dac25bcff2775b7ae5a436a28 (diff)
downloadlingo-ap-tracker-79424e86dd7aa28c1b25868d86fa8ebffc801593.tar.gz
lingo-ap-tracker-79424e86dd7aa28c1b25868d86fa8ebffc801593.tar.bz2
lingo-ap-tracker-79424e86dd7aa28c1b25868d86fa8ebffc801593.zip
Optimized AreaPopup indicators
The list of indicators and the size of the window are calculated only when necessary (new connection, DPI changed, or hunt panel settings changed) and otherwise all we do is redraw the image.
Diffstat (limited to 'src/area_popup.cpp')
-rw-r--r--src/area_popup.cpp147
1 files changed, 77 insertions, 70 deletions
diff --git a/src/area_popup.cpp b/src/area_popup.cpp index d7f45b6..a8e6004 100644 --- a/src/area_popup.cpp +++ b/src/area_popup.cpp
@@ -27,28 +27,26 @@ AreaPopup::AreaPopup(wxWindow* parent, int area_id)
27 Bind(wxEVT_PAINT, &AreaPopup::OnPaint, this); 27 Bind(wxEVT_PAINT, &AreaPopup::OnPaint, this);
28 Bind(wxEVT_DPI_CHANGED, &AreaPopup::OnDPIChanged, this); 28 Bind(wxEVT_DPI_CHANGED, &AreaPopup::OnDPIChanged, this);
29 29
30 UpdateIndicators(); 30 ResetIndicators();
31} 31}
32 32
33void AreaPopup::UpdateIndicators() { 33void AreaPopup::ResetIndicators() {
34 const MapArea& map_area = GD_GetMapArea(area_id_); 34 indicators_.clear();
35 35
36 const MapArea& map_area = GD_GetMapArea(area_id_);
36 wxFont the_font = GetFont().Scale(GetDPIScaleFactor()); 37 wxFont the_font = GetFont().Scale(GetDPIScaleFactor());
38 TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent());
37 39
38 // Start calculating extents. 40 // Start calculating extents.
39 wxMemoryDC mem_dc; 41 wxMemoryDC mem_dc;
40 mem_dc.SetFont(the_font.Bold()); 42 mem_dc.SetFont(the_font.Bold());
41 wxSize header_extent = mem_dc.GetTextExtent(map_area.name); 43 header_extent_ = mem_dc.GetTextExtent(map_area.name);
42 44
43 int acc_height = header_extent.GetHeight() + FromDIP(20); 45 int acc_height = header_extent_.GetHeight() + FromDIP(20);
44 int col_width = 0; 46 int col_width = 0;
45 47
46 mem_dc.SetFont(the_font); 48 mem_dc.SetFont(the_font);
47 49
48 TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent());
49
50 std::vector<int> real_locations;
51
52 for (int section_id = 0; section_id < map_area.locations.size(); 50 for (int section_id = 0; section_id < map_area.locations.size();
53 section_id++) { 51 section_id++) {
54 const Location& location = map_area.locations.at(section_id); 52 const Location& location = map_area.locations.at(section_id);
@@ -67,7 +65,7 @@ void AreaPopup::UpdateIndicators() {
67 } 65 }
68 } 66 }
69 67
70 real_locations.push_back(section_id); 68 indicators_.emplace_back(section_id, kLOCATION, acc_height);
71 69
72 wxSize item_extent = mem_dc.GetTextExtent(location.name); 70 wxSize item_extent = mem_dc.GetTextExtent(location.name);
73 int item_height = 71 int item_height =
@@ -85,6 +83,8 @@ void AreaPopup::UpdateIndicators() {
85 continue; 83 continue;
86 } 84 }
87 85
86 indicators_.emplace_back(painting_id, kPAINTING, acc_height);
87
88 const PaintingExit& painting = GD_GetPaintingExit(painting_id); 88 const PaintingExit& painting = GD_GetPaintingExit(painting_id);
89 wxSize item_extent = mem_dc.GetTextExtent(painting.display_name); 89 wxSize item_extent = mem_dc.GetTextExtent(painting.display_name);
90 int item_height = 90 int item_height =
@@ -98,84 +98,91 @@ void AreaPopup::UpdateIndicators() {
98 } 98 }
99 99
100 int item_width = col_width + FromDIP(10 + 32); 100 int item_width = col_width + FromDIP(10 + 32);
101 int full_width = std::max(header_extent.GetWidth(), item_width) + FromDIP(20); 101 full_width_ = std::max(header_extent_.GetWidth(), item_width) + FromDIP(20);
102 full_height_ = acc_height;
102 103
103 Fit(); 104 Fit();
104 SetVirtualSize(full_width, acc_height); 105 SetVirtualSize(full_width_, full_height_);
106
107 UpdateIndicators();
108}
109
110void AreaPopup::UpdateIndicators() {
111 const MapArea& map_area = GD_GetMapArea(area_id_);
112 wxFont the_font = GetFont().Scale(GetDPIScaleFactor());
113 TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent());
114
115 rendered_ = wxBitmap(full_width_, full_height_);
105 116
106 rendered_ = wxBitmap(full_width, acc_height); 117 wxMemoryDC mem_dc;
107 mem_dc.SelectObject(rendered_); 118 mem_dc.SelectObject(rendered_);
108 mem_dc.SetPen(*wxTRANSPARENT_PEN); 119 mem_dc.SetPen(*wxTRANSPARENT_PEN);
109 mem_dc.SetBrush(*wxBLACK_BRUSH); 120 mem_dc.SetBrush(*wxBLACK_BRUSH);
110 mem_dc.DrawRectangle({0, 0}, {full_width, acc_height}); 121 mem_dc.DrawRectangle({0, 0}, {full_width_, full_height_});
111 122
112 mem_dc.SetFont(the_font.Bold()); 123 mem_dc.SetFont(the_font.Bold());
113 mem_dc.SetTextForeground(*wxWHITE); 124 mem_dc.SetTextForeground(*wxWHITE);
114 mem_dc.DrawText(map_area.name, 125 mem_dc.DrawText(map_area.name,
115 {(full_width - header_extent.GetWidth()) / 2, FromDIP(10)}); 126 {(full_width_ - header_extent_.GetWidth()) / 2, FromDIP(10)});
116
117 int cur_height = header_extent.GetHeight() + FromDIP(20);
118 127
119 mem_dc.SetFont(the_font); 128 mem_dc.SetFont(the_font);
120 129
121 for (int section_id : real_locations) { 130 for (const IndicatorInfo& indicator : indicators_) {
122 const Location& location = map_area.locations.at(section_id); 131 switch (indicator.type) {
123 132 case kLOCATION: {
124 bool checked = false; 133 const Location& location = map_area.locations.at(indicator.id);
125 if (IsLocationWinCondition(location)) { 134
126 checked = AP_HasReachedGoal(); 135 bool checked = false;
127 } else if (tracker_panel->IsPanelsMode()) { 136 if (IsLocationWinCondition(location)) {
128 const Panel& panel = GD_GetPanel(*location.single_panel); 137 checked = AP_HasReachedGoal();
129 if (panel.non_counting) { 138 } else if (tracker_panel->IsPanelsMode()) {
130 checked = AP_HasCheckedGameLocation(location.ap_location_id); 139 const Panel& panel = GD_GetPanel(*location.single_panel);
131 } else { 140 if (panel.non_counting) {
132 checked = tracker_panel->GetSolvedPanels().contains(panel.nodepath); 141 checked = AP_HasCheckedGameLocation(location.ap_location_id);
142 } else {
143 checked = tracker_panel->GetSolvedPanels().contains(panel.nodepath);
144 }
145 } else {
146 checked = AP_HasCheckedGameLocation(location.ap_location_id) ||
147 (location.hunt &&
148 AP_HasCheckedHuntPanel(location.ap_location_id));
149 }
150
151 const wxBitmap* eye_ptr = checked ? checked_eye_ : unchecked_eye_;
152
153 mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), indicator.y});
154
155 bool reachable = IsLocationReachable(location.ap_location_id);
156 const wxColour* text_color = reachable ? wxWHITE : wxRED;
157 mem_dc.SetTextForeground(*text_color);
158
159 wxSize item_extent = mem_dc.GetTextExtent(location.name);
160 mem_dc.DrawText(
161 location.name,
162 {FromDIP(10 + 32 + 10),
163 indicator.y + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2});
164
165 break;
133 } 166 }
134 } else { 167 case kPAINTING: {
135 checked = 168 const PaintingExit& painting = GD_GetPaintingExit(indicator.id);
136 AP_HasCheckedGameLocation(location.ap_location_id) ||
137 (location.hunt && AP_HasCheckedHuntPanel(location.ap_location_id));
138 }
139
140 const wxBitmap* eye_ptr = checked ? checked_eye_ : unchecked_eye_;
141 169
142 mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), cur_height}); 170 bool reachable = IsPaintingReachable(indicator.id);
171 const wxColour* text_color = reachable ? wxWHITE : wxRED;
172 mem_dc.SetTextForeground(*text_color);
143 173
144 bool reachable = IsLocationReachable(location.ap_location_id); 174 bool checked = reachable && AP_IsPaintingChecked(painting.internal_id);
145 const wxColour* text_color = reachable ? wxWHITE : wxRED; 175 const wxBitmap* eye_ptr = checked ? checked_owl_ : unchecked_owl_;
146 mem_dc.SetTextForeground(*text_color); 176 mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), indicator.y});
147 177
148 wxSize item_extent = mem_dc.GetTextExtent(location.name); 178 wxSize item_extent = mem_dc.GetTextExtent(painting.display_name);
149 mem_dc.DrawText( 179 mem_dc.DrawText(
150 location.name, 180 painting.display_name,
151 {FromDIP(10 + 32 + 10), 181 {FromDIP(10 + 32 + 10),
152 cur_height + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2}); 182 indicator.y + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2});
153
154 cur_height += FromDIP(10 + 32);
155 }
156 183
157 if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) { 184 break;
158 for (int painting_id : map_area.paintings) {
159 if (IsPaintingPostgame(painting_id)) {
160 continue;
161 } 185 }
162
163 const PaintingExit& painting = GD_GetPaintingExit(painting_id);
164
165 bool reachable = IsPaintingReachable(painting_id);
166 const wxColour* text_color = reachable ? wxWHITE : wxRED;
167 mem_dc.SetTextForeground(*text_color);
168
169 bool checked = reachable && AP_IsPaintingChecked(painting.internal_id);
170 const wxBitmap* eye_ptr = checked ? checked_owl_ : unchecked_owl_;
171 mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), cur_height});
172
173 wxSize item_extent = mem_dc.GetTextExtent(painting.display_name);
174 mem_dc.DrawText(painting.display_name,
175 {FromDIP(10 + 32 + 10),
176 cur_height + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2});
177
178 cur_height += FromDIP(10 + 32);
179 } 186 }
180 } 187 }
181} 188}
@@ -190,7 +197,7 @@ void AreaPopup::OnPaint(wxPaintEvent& event) {
190 197
191void AreaPopup::OnDPIChanged(wxDPIChangedEvent& event) { 198void AreaPopup::OnDPIChanged(wxDPIChangedEvent& event) {
192 LoadIcons(); 199 LoadIcons();
193 UpdateIndicators(); 200 ResetIndicators();
194 201
195 event.Skip(); 202 event.Skip();
196} 203}