about summary refs log tree commit diff stats
path: root/src/area_popup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/area_popup.cpp')
-rw-r--r--src/area_popup.cpp196
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
36void AreaPopup::UpdateIndicators() { 33void 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
104void 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
186void AreaPopup::OnDPIChanged(wxDPIChangedEvent& event) {
187 LoadIcons();
188 ResetIndicators();
189
190 event.Skip();
191}
192
193void 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}