about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/area_popup.cpp147
-rw-r--r--src/area_popup.h25
-rw-r--r--src/tracker_frame.cpp16
-rw-r--r--src/tracker_frame.h1
-rw-r--r--src/tracker_panel.cpp15
-rw-r--r--src/tracker_panel.h2
6 files changed, 125 insertions, 81 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}
diff --git a/src/area_popup.h b/src/area_popup.h index 2401e4e..50e10e8 100644 --- a/src/area_popup.h +++ b/src/area_popup.h
@@ -7,13 +7,32 @@
7#include <wx/wx.h> 7#include <wx/wx.h>
8#endif 8#endif
9 9
10#include <vector>
11
10class AreaPopup : public wxScrolledCanvas { 12class AreaPopup : public wxScrolledCanvas {
11 public: 13 public:
12 AreaPopup(wxWindow* parent, int area_id); 14 AreaPopup(wxWindow* parent, int area_id);
13 15
16 void ResetIndicators();
14 void UpdateIndicators(); 17 void UpdateIndicators();
15 18
16 private: 19 private:
20 enum IndicatorType {
21 kLOCATION,
22 kPAINTING,
23 };
24
25 struct IndicatorInfo {
26 // For locations, the id is an index into the map area's locations list.
27 // For paintings, it is a real painting id.
28 int id;
29 IndicatorType type;
30 int y;
31
32 IndicatorInfo(int id, IndicatorType type, int y)
33 : id(id), type(type), y(y) {}
34 };
35
17 void OnPaint(wxPaintEvent& event); 36 void OnPaint(wxPaintEvent& event);
18 void OnDPIChanged(wxDPIChangedEvent& event); 37 void OnDPIChanged(wxDPIChangedEvent& event);
19 38
@@ -26,6 +45,12 @@ class AreaPopup : public wxScrolledCanvas {
26 const wxBitmap* unchecked_owl_; 45 const wxBitmap* unchecked_owl_;
27 const wxBitmap* checked_owl_; 46 const wxBitmap* checked_owl_;
28 47
48 int full_width_ = 0;
49 int full_height_ = 0;
50 wxSize header_extent_;
51
52 std::vector<IndicatorInfo> indicators_;
53
29 wxBitmap rendered_; 54 wxBitmap rendered_;
30}; 55};
31 56
diff --git a/src/tracker_frame.cpp b/src/tracker_frame.cpp index 6a4ab2e..fa68582 100644 --- a/src/tracker_frame.cpp +++ b/src/tracker_frame.cpp
@@ -255,8 +255,9 @@ void TrackerFrame::OnSettings(wxCommandEvent &event) {
255 GetTrackerConfig().track_position = dlg.GetTrackPosition(); 255 GetTrackerConfig().track_position = dlg.GetTrackPosition();
256 GetTrackerConfig().Save(); 256 GetTrackerConfig().Save();
257 257
258 UpdateIndicators( 258 UpdateIndicators(StateUpdate{.cleared_locations = true,
259 StateUpdate{.cleared_locations = true, .player_position = true}); 259 .player_position = true,
260 .changed_settings = true});
260 } 261 }
261} 262}
262 263
@@ -328,7 +329,7 @@ void TrackerFrame::OnSashPositionChanged(wxSplitterEvent& event) {
328} 329}
329 330
330void TrackerFrame::OnStateReset(wxCommandEvent &event) { 331void TrackerFrame::OnStateReset(wxCommandEvent &event) {
331 tracker_panel_->UpdateIndicators(); 332 tracker_panel_->UpdateIndicators(/*reset=*/true);
332 achievements_pane_->UpdateIndicators(); 333 achievements_pane_->UpdateIndicators();
333 items_pane_->ResetIndicators(); 334 items_pane_->ResetIndicators();
334 options_pane_->OnConnect(); 335 options_pane_->OnConnect();
@@ -350,7 +351,7 @@ void TrackerFrame::OnStateChanged(StateChangedEvent &event) {
350 panels_panel_->SetPanelsMode(); 351 panels_panel_->SetPanelsMode();
351 notebook_->AddPage(panels_panel_, "Panels"); 352 notebook_->AddPage(panels_panel_, "Panels");
352 } 353 }
353 panels_panel_->UpdateIndicators(); 354 panels_panel_->UpdateIndicators(/*reset=*/false);
354 if (notebook_->GetSelection() == 2) { 355 if (notebook_->GetSelection() == 2) {
355 Refresh(); 356 Refresh();
356 } 357 }
@@ -361,10 +362,13 @@ void TrackerFrame::OnStateChanged(StateChangedEvent &event) {
361 if (!state.items.empty() || !state.paintings.empty() || 362 if (!state.items.empty() || !state.paintings.empty() ||
362 state.cleared_locations || 363 state.cleared_locations ||
363 (state.hunt_panels && GetTrackerConfig().show_hunt_panels)) { 364 (state.hunt_panels && GetTrackerConfig().show_hunt_panels)) {
364 tracker_panel_->UpdateIndicators(); 365 // TODO: The only real reason to reset tracker_panel during an active
366 // connection is if the hunt panels setting changes. If we remove hunt
367 // panels later, we can get rid of this.
368 tracker_panel_->UpdateIndicators(/*reset=*/state.changed_settings);
365 subway_map_->UpdateIndicators(); 369 subway_map_->UpdateIndicators();
366 if (panels_panel_ != nullptr) { 370 if (panels_panel_ != nullptr) {
367 panels_panel_->UpdateIndicators(); 371 panels_panel_->UpdateIndicators(/*reset=*/false);
368 } 372 }
369 Refresh(); 373 Refresh();
370 } else if (state.player_position && GetTrackerConfig().track_position) { 374 } else if (state.player_position && GetTrackerConfig().track_position) {
diff --git a/src/tracker_frame.h b/src/tracker_frame.h index 7704208..131c7b8 100644 --- a/src/tracker_frame.h +++ b/src/tracker_frame.h
@@ -57,6 +57,7 @@ struct StateUpdate {
57 bool cleared_locations = false; 57 bool cleared_locations = false;
58 bool hunt_panels = false; 58 bool hunt_panels = false;
59 bool player_position = false; 59 bool player_position = false;
60 bool changed_settings = false;
60}; 61};
61 62
62class StateChangedEvent : public wxEvent { 63class StateChangedEvent : public wxEvent {
diff --git a/src/tracker_panel.cpp b/src/tracker_panel.cpp index b4e6697..64e6ab3 100644 --- a/src/tracker_panel.cpp +++ b/src/tracker_panel.cpp
@@ -50,13 +50,19 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
50 Bind(wxEVT_MOTION, &TrackerPanel::OnMouseMove, this); 50 Bind(wxEVT_MOTION, &TrackerPanel::OnMouseMove, this);
51} 51}
52 52
53void TrackerPanel::UpdateIndicators() { 53void TrackerPanel::UpdateIndicators(bool reset) {
54 if (panels_mode_ && !savedata_path_) { 54 if (panels_mode_ && !savedata_path_) {
55 solved_panels_ = IPC_GetSolvedPanels(); 55 solved_panels_ = IPC_GetSolvedPanels();
56 } 56 }
57 57
58 for (AreaIndicator &area : areas_) { 58 if (reset) {
59 area.popup->UpdateIndicators(); 59 for (AreaIndicator &area : areas_) {
60 area.popup->ResetIndicators();
61 }
62 } else {
63 for (AreaIndicator &area : areas_) {
64 area.popup->UpdateIndicators();
65 }
60 } 66 }
61 67
62 Redraw(); 68 Redraw();
@@ -74,6 +80,7 @@ void TrackerPanel::SetSavedataPath(std::string savedata_path) {
74 savedata_path_ = savedata_path; 80 savedata_path_ = savedata_path;
75 panels_mode_ = true; 81 panels_mode_ = true;
76 82
83 UpdateIndicators(/*reset=*/true);
77 RefreshSavedata(); 84 RefreshSavedata();
78} 85}
79 86
@@ -90,7 +97,7 @@ void TrackerPanel::RefreshSavedata() {
90 } 97 }
91 } 98 }
92 99
93 UpdateIndicators(); 100 UpdateIndicators(/*reset=*/false);
94 Refresh(); 101 Refresh();
95} 102}
96 103
diff --git a/src/tracker_panel.h b/src/tracker_panel.h index b7067f5..ae89a35 100644 --- a/src/tracker_panel.h +++ b/src/tracker_panel.h
@@ -17,7 +17,7 @@ class TrackerPanel : public wxPanel {
17 public: 17 public:
18 TrackerPanel(wxWindow *parent); 18 TrackerPanel(wxWindow *parent);
19 19
20 void UpdateIndicators(); 20 void UpdateIndicators(bool reset);
21 21
22 void SetPanelsMode(); 22 void SetPanelsMode();
23 23