diff options
Diffstat (limited to 'src/area_popup.cpp')
-rw-r--r-- | src/area_popup.cpp | 196 |
1 files changed, 111 insertions, 85 deletions
diff --git a/src/area_popup.cpp b/src/area_popup.cpp index 8d6487e..c95e492 100644 --- a/src/area_popup.cpp +++ b/src/area_popup.cpp | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "ap_state.h" | 7 | #include "ap_state.h" |
8 | #include "game_data.h" | 8 | #include "game_data.h" |
9 | #include "global.h" | 9 | #include "global.h" |
10 | #include "icons.h" | ||
10 | #include "tracker_config.h" | 11 | #include "tracker_config.h" |
11 | #include "tracker_panel.h" | 12 | #include "tracker_panel.h" |
12 | #include "tracker_state.h" | 13 | #include "tracker_state.h" |
@@ -15,60 +16,54 @@ AreaPopup::AreaPopup(wxWindow* parent, int area_id) | |||
15 | : wxScrolledCanvas(parent, wxID_ANY), area_id_(area_id) { | 16 | : wxScrolledCanvas(parent, wxID_ANY), area_id_(area_id) { |
16 | SetBackgroundStyle(wxBG_STYLE_PAINT); | 17 | SetBackgroundStyle(wxBG_STYLE_PAINT); |
17 | 18 | ||
18 | unchecked_eye_ = | 19 | LoadIcons(); |
19 | wxBitmap(wxImage(GetAbsolutePath("assets/unchecked.png").c_str(), | ||
20 | wxBITMAP_TYPE_PNG) | ||
21 | .Scale(32, 32)); | ||
22 | checked_eye_ = wxBitmap( | ||
23 | wxImage(GetAbsolutePath("assets/checked.png").c_str(), wxBITMAP_TYPE_PNG) | ||
24 | .Scale(32, 32)); | ||
25 | 20 | ||
21 | // TODO: This is slow on high-DPI screens. | ||
26 | SetScrollRate(5, 5); | 22 | SetScrollRate(5, 5); |
27 | 23 | ||
28 | SetBackgroundColour(*wxBLACK); | 24 | SetBackgroundColour(*wxBLACK); |
29 | Hide(); | 25 | Hide(); |
30 | 26 | ||
31 | Bind(wxEVT_PAINT, &AreaPopup::OnPaint, this); | 27 | Bind(wxEVT_PAINT, &AreaPopup::OnPaint, this); |
28 | Bind(wxEVT_DPI_CHANGED, &AreaPopup::OnDPIChanged, this); | ||
32 | 29 | ||
33 | UpdateIndicators(); | 30 | ResetIndicators(); |
34 | } | 31 | } |
35 | 32 | ||
36 | void AreaPopup::UpdateIndicators() { | 33 | void AreaPopup::ResetIndicators() { |
34 | indicators_.clear(); | ||
35 | |||
37 | const MapArea& map_area = GD_GetMapArea(area_id_); | 36 | const MapArea& map_area = GD_GetMapArea(area_id_); |
37 | wxFont the_font = GetFont().Scale(GetDPIScaleFactor()); | ||
38 | TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent()); | ||
38 | 39 | ||
39 | // Start calculating extents. | 40 | // Start calculating extents. |
40 | wxMemoryDC mem_dc; | 41 | wxMemoryDC mem_dc; |
41 | mem_dc.SetFont(GetFont().Bold()); | 42 | mem_dc.SetFont(the_font.Bold()); |
42 | wxSize header_extent = mem_dc.GetTextExtent(map_area.name); | 43 | header_extent_ = mem_dc.GetTextExtent(map_area.name); |
43 | 44 | ||
44 | int acc_height = header_extent.GetHeight() + 20; | 45 | int acc_height = header_extent_.GetHeight() + FromDIP(20); |
45 | int col_width = 0; | 46 | int col_width = 0; |
46 | 47 | ||
47 | mem_dc.SetFont(GetFont()); | 48 | mem_dc.SetFont(the_font); |
48 | |||
49 | TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent()); | ||
50 | |||
51 | std::vector<int> real_locations; | ||
52 | 49 | ||
53 | for (int section_id = 0; section_id < map_area.locations.size(); | 50 | for (int section_id = 0; section_id < map_area.locations.size(); |
54 | section_id++) { | 51 | section_id++) { |
55 | const Location& location = map_area.locations.at(section_id); | 52 | const Location& location = map_area.locations.at(section_id); |
56 | 53 | if ((!AP_IsLocationVisible(location.classification) || | |
57 | if (tracker_panel->IsPanelsMode()) { | 54 | IsLocationPostgame(location.ap_location_id)) && |
58 | if (!location.single_panel) { | 55 | !(location.hunt && |
59 | continue; | 56 | GetTrackerConfig().visible_panels == TrackerConfig::kHUNT_PANELS) && |
60 | } | 57 | !(location.single_panel && |
61 | } else { | 58 | GetTrackerConfig().visible_panels == TrackerConfig::kALL_PANELS)) { |
62 | if (!AP_IsLocationVisible(location.classification) && | 59 | continue; |
63 | !(location.hunt && GetTrackerConfig().show_hunt_panels)) { | ||
64 | continue; | ||
65 | } | ||
66 | } | 60 | } |
67 | 61 | ||
68 | real_locations.push_back(section_id); | 62 | indicators_.emplace_back(section_id, kLOCATION, acc_height); |
69 | 63 | ||
70 | wxSize item_extent = mem_dc.GetTextExtent(location.name); | 64 | wxSize item_extent = mem_dc.GetTextExtent(location.name); |
71 | int item_height = std::max(32, item_extent.GetHeight()) + 10; | 65 | int item_height = |
66 | std::max(FromDIP(32), item_extent.GetHeight()) + FromDIP(10); | ||
72 | acc_height += item_height; | 67 | acc_height += item_height; |
73 | 68 | ||
74 | if (item_extent.GetWidth() > col_width) { | 69 | if (item_extent.GetWidth() > col_width) { |
@@ -76,11 +71,18 @@ void AreaPopup::UpdateIndicators() { | |||
76 | } | 71 | } |
77 | } | 72 | } |
78 | 73 | ||
79 | if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) { | 74 | if (AP_IsPaintingShuffle()) { |
80 | for (int painting_id : map_area.paintings) { | 75 | for (int painting_id : map_area.paintings) { |
76 | if (IsPaintingPostgame(painting_id)) { | ||
77 | continue; | ||
78 | } | ||
79 | |||
80 | indicators_.emplace_back(painting_id, kPAINTING, acc_height); | ||
81 | |||
81 | const PaintingExit& painting = GD_GetPaintingExit(painting_id); | 82 | const PaintingExit& painting = GD_GetPaintingExit(painting_id); |
82 | wxSize item_extent = mem_dc.GetTextExtent(painting.internal_id); // TODO: Replace with a friendly name. | 83 | wxSize item_extent = mem_dc.GetTextExtent(painting.display_name); |
83 | int item_height = std::max(32, item_extent.GetHeight()) + 10; | 84 | int item_height = |
85 | std::max(FromDIP(32), item_extent.GetHeight()) + FromDIP(10); | ||
84 | acc_height += item_height; | 86 | acc_height += item_height; |
85 | 87 | ||
86 | if (item_extent.GetWidth() > col_width) { | 88 | if (item_extent.GetWidth() > col_width) { |
@@ -89,80 +91,86 @@ void AreaPopup::UpdateIndicators() { | |||
89 | } | 91 | } |
90 | } | 92 | } |
91 | 93 | ||
92 | int item_width = col_width + 10 + 32; | 94 | int item_width = col_width + FromDIP(10 + 32); |
93 | int full_width = std::max(header_extent.GetWidth(), item_width) + 20; | 95 | full_width_ = std::max(header_extent_.GetWidth(), item_width) + FromDIP(20); |
96 | full_height_ = acc_height; | ||
94 | 97 | ||
95 | Fit(); | 98 | Fit(); |
96 | SetVirtualSize(full_width, acc_height); | 99 | SetVirtualSize(full_width_, full_height_); |
100 | |||
101 | UpdateIndicators(); | ||
102 | } | ||
103 | |||
104 | void AreaPopup::UpdateIndicators() { | ||
105 | const MapArea& map_area = GD_GetMapArea(area_id_); | ||
106 | wxFont the_font = GetFont().Scale(GetDPIScaleFactor()); | ||
107 | TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent()); | ||
108 | |||
109 | rendered_ = wxBitmap(full_width_, full_height_); | ||
97 | 110 | ||
98 | rendered_ = wxBitmap(full_width, acc_height); | 111 | wxMemoryDC mem_dc; |
99 | mem_dc.SelectObject(rendered_); | 112 | mem_dc.SelectObject(rendered_); |
100 | mem_dc.SetPen(*wxTRANSPARENT_PEN); | 113 | mem_dc.SetPen(*wxTRANSPARENT_PEN); |
101 | mem_dc.SetBrush(*wxBLACK_BRUSH); | 114 | mem_dc.SetBrush(*wxBLACK_BRUSH); |
102 | mem_dc.DrawRectangle({0, 0}, {full_width, acc_height}); | 115 | mem_dc.DrawRectangle({0, 0}, {full_width_, full_height_}); |
103 | 116 | ||
104 | mem_dc.SetFont(GetFont().Bold()); | 117 | mem_dc.SetFont(the_font.Bold()); |
105 | mem_dc.SetTextForeground(*wxWHITE); | 118 | mem_dc.SetTextForeground(*wxWHITE); |
106 | mem_dc.DrawText(map_area.name, | 119 | mem_dc.DrawText(map_area.name, |
107 | {(full_width - header_extent.GetWidth()) / 2, 10}); | 120 | {(full_width_ - header_extent_.GetWidth()) / 2, FromDIP(10)}); |
108 | 121 | ||
109 | int cur_height = header_extent.GetHeight() + 20; | 122 | mem_dc.SetFont(the_font); |
110 | 123 | ||
111 | mem_dc.SetFont(GetFont()); | 124 | for (const IndicatorInfo& indicator : indicators_) { |
125 | switch (indicator.type) { | ||
126 | case kLOCATION: { | ||
127 | const Location& location = map_area.locations.at(indicator.id); | ||
112 | 128 | ||
113 | for (int section_id : real_locations) { | 129 | bool checked = false; |
114 | const Location& location = map_area.locations.at(section_id); | 130 | if (IsLocationWinCondition(location)) { |
131 | checked = AP_HasReachedGoal(); | ||
132 | } else { | ||
133 | checked = AP_HasCheckedGameLocation(location.ap_location_id) || | ||
134 | (location.single_panel && | ||
135 | AP_IsPanelSolved( | ||
136 | GD_GetPanel(*location.single_panel).solve_index)); | ||
137 | } | ||
115 | 138 | ||
116 | bool checked = false; | 139 | const wxBitmap* eye_ptr = checked ? checked_eye_ : unchecked_eye_; |
117 | if (IsLocationWinCondition(location)) { | ||
118 | checked = AP_HasReachedGoal(); | ||
119 | } else if (tracker_panel->IsPanelsMode()) { | ||
120 | const Panel& panel = GD_GetPanel(*location.single_panel); | ||
121 | if (panel.non_counting) { | ||
122 | checked = AP_HasCheckedGameLocation(location.ap_location_id); | ||
123 | } else { | ||
124 | checked = tracker_panel->GetSolvedPanels().contains(panel.nodepath); | ||
125 | } | ||
126 | } else { | ||
127 | checked = | ||
128 | AP_HasCheckedGameLocation(location.ap_location_id) || | ||
129 | (location.hunt && AP_HasCheckedHuntPanel(location.ap_location_id)); | ||
130 | } | ||
131 | |||
132 | wxBitmap* eye_ptr = checked ? &checked_eye_ : &unchecked_eye_; | ||
133 | 140 | ||
134 | mem_dc.DrawBitmap(*eye_ptr, {10, cur_height}); | 141 | mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), indicator.y}); |
135 | 142 | ||
136 | bool reachable = IsLocationReachable(location.ap_location_id); | 143 | bool reachable = IsLocationReachable(location.ap_location_id); |
137 | const wxColour* text_color = reachable ? wxWHITE : wxRED; | 144 | const wxColour* text_color = reachable ? wxWHITE : wxRED; |
138 | mem_dc.SetTextForeground(*text_color); | 145 | mem_dc.SetTextForeground(*text_color); |
139 | 146 | ||
140 | wxSize item_extent = mem_dc.GetTextExtent(location.name); | 147 | wxSize item_extent = mem_dc.GetTextExtent(location.name); |
141 | mem_dc.DrawText( | 148 | mem_dc.DrawText( |
142 | location.name, | 149 | location.name, |
143 | {10 + 32 + 10, cur_height + (32 - mem_dc.GetFontMetrics().height) / 2}); | 150 | {FromDIP(10 + 32 + 10), |
144 | 151 | indicator.y + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2}); | |
145 | cur_height += 10 + 32; | ||
146 | } | ||
147 | 152 | ||
148 | if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) { | 153 | break; |
149 | for (int painting_id : map_area.paintings) { | 154 | } |
150 | const PaintingExit& painting = GD_GetPaintingExit(painting_id); | 155 | case kPAINTING: { |
156 | const PaintingExit& painting = GD_GetPaintingExit(indicator.id); | ||
151 | 157 | ||
152 | bool reachable = IsPaintingReachable(painting_id); | 158 | bool reachable = IsPaintingReachable(indicator.id); |
153 | const wxColour* text_color = reachable ? wxWHITE : wxRED; | 159 | const wxColour* text_color = reachable ? wxWHITE : wxRED; |
154 | mem_dc.SetTextForeground(*text_color); | 160 | mem_dc.SetTextForeground(*text_color); |
155 | 161 | ||
156 | bool checked = reachable && AP_IsPaintingChecked(painting.internal_id); | 162 | bool checked = reachable && AP_IsPaintingChecked(painting.internal_id); |
157 | wxBitmap* eye_ptr = checked ? &checked_eye_ : &unchecked_eye_; | 163 | const wxBitmap* eye_ptr = checked ? checked_owl_ : unchecked_owl_; |
158 | mem_dc.DrawBitmap(*eye_ptr, {10, cur_height}); | 164 | mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), indicator.y}); |
159 | 165 | ||
160 | wxSize item_extent = mem_dc.GetTextExtent(painting.internal_id); // TODO: Replace with friendly name. | 166 | wxSize item_extent = mem_dc.GetTextExtent(painting.display_name); |
161 | mem_dc.DrawText(painting.internal_id, | 167 | mem_dc.DrawText( |
162 | {10 + 32 + 10, | 168 | painting.display_name, |
163 | cur_height + (32 - mem_dc.GetFontMetrics().height) / 2}); | 169 | {FromDIP(10 + 32 + 10), |
170 | indicator.y + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2}); | ||
164 | 171 | ||
165 | cur_height += 10 + 32; | 172 | break; |
173 | } | ||
166 | } | 174 | } |
167 | } | 175 | } |
168 | } | 176 | } |
@@ -174,3 +182,21 @@ void AreaPopup::OnPaint(wxPaintEvent& event) { | |||
174 | 182 | ||
175 | event.Skip(); | 183 | event.Skip(); |
176 | } | 184 | } |
185 | |||
186 | void AreaPopup::OnDPIChanged(wxDPIChangedEvent& event) { | ||
187 | LoadIcons(); | ||
188 | ResetIndicators(); | ||
189 | |||
190 | event.Skip(); | ||
191 | } | ||
192 | |||
193 | void AreaPopup::LoadIcons() { | ||
194 | unchecked_eye_ = GetTheIconCache().GetIcon("assets/unchecked.png", | ||
195 | FromDIP(wxSize{32, 32})); | ||
196 | checked_eye_ = | ||
197 | GetTheIconCache().GetIcon("assets/checked.png", FromDIP(wxSize{32, 32})); | ||
198 | unchecked_owl_ = | ||
199 | GetTheIconCache().GetIcon("assets/owl.png", FromDIP(wxSize{32, 32})); | ||
200 | checked_owl_ = GetTheIconCache().GetIcon("assets/checked_owl.png", | ||
201 | FromDIP(wxSize{32, 32})); | ||
202 | } | ||