about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/area_popup.cpp119
-rw-r--r--src/area_popup.h11
-rw-r--r--src/eye_indicator.cpp51
-rw-r--r--src/eye_indicator.h30
-rw-r--r--src/game_data.cpp181
-rw-r--r--src/tracker_frame.cpp3
-rw-r--r--src/tracker_panel.cpp10
-rw-r--r--src/version.h2
8 files changed, 193 insertions, 214 deletions
diff --git a/src/area_popup.cpp b/src/area_popup.cpp index 6bbc0cf..9c97d78 100644 --- a/src/area_popup.cpp +++ b/src/area_popup.cpp
@@ -2,73 +2,114 @@
2 2
3#include "ap_state.h" 3#include "ap_state.h"
4#include "game_data.h" 4#include "game_data.h"
5#include "global.h"
5#include "tracker_config.h" 6#include "tracker_config.h"
6#include "tracker_state.h" 7#include "tracker_state.h"
7 8
8AreaPopup::AreaPopup(wxWindow* parent, int area_id) 9AreaPopup::AreaPopup(wxWindow* parent, int area_id)
9 : wxScrolledWindow(parent, wxID_ANY), area_id_(area_id) { 10 : wxScrolledCanvas(parent, wxID_ANY), area_id_(area_id) {
10 const MapArea& map_area = GD_GetMapArea(area_id); 11 unchecked_eye_ =
11 12 wxBitmap(wxImage(GetAbsolutePath("assets/unchecked.png").c_str(),
12 wxFlexGridSizer* section_sizer = new wxFlexGridSizer(2, 10, 10); 13 wxBITMAP_TYPE_PNG)
13 14 .Scale(32, 32));
14 for (const Location& location : map_area.locations) { 15 checked_eye_ = wxBitmap(
15 EyeIndicator* eye_indicator = new EyeIndicator(this); 16 wxImage(GetAbsolutePath("assets/checked.png").c_str(), wxBITMAP_TYPE_PNG)
16 section_sizer->Add(eye_indicator, wxSizerFlags().Expand()); 17 .Scale(32, 32));
17 eye_indicators_.push_back(eye_indicator);
18
19 wxStaticText* section_label = new wxStaticText(this, -1, location.name);
20 section_label->SetForegroundColour(*wxWHITE);
21 section_sizer->Add(
22 section_label,
23 wxSizerFlags().Align(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL));
24 section_labels_.push_back(section_label);
25 }
26
27 wxBoxSizer* top_sizer = new wxBoxSizer(wxVERTICAL);
28
29 wxStaticText* top_label = new wxStaticText(this, -1, map_area.name);
30 top_label->SetForegroundColour(*wxWHITE);
31 top_label->SetFont(top_label->GetFont().Bold());
32 top_sizer->Add(top_label,
33 wxSizerFlags().Center().DoubleBorder(wxUP | wxLEFT | wxRIGHT));
34
35 top_sizer->Add(section_sizer, wxSizerFlags().DoubleBorder(wxALL).Expand());
36 18
37 SetSizerAndFit(top_sizer);
38 SetScrollRate(5, 5); 19 SetScrollRate(5, 5);
39 20
40 SetBackgroundColour(*wxBLACK); 21 SetBackgroundColour(*wxBLACK);
41 Hide(); 22 Hide();
23
24 Bind(wxEVT_PAINT, &AreaPopup::OnPaint, this);
25
26 UpdateIndicators();
42} 27}
43 28
44void AreaPopup::UpdateIndicators() { 29void AreaPopup::UpdateIndicators() {
45 const MapArea& map_area = GD_GetMapArea(area_id_); 30 const MapArea& map_area = GD_GetMapArea(area_id_);
31
32 // Start calculating extents.
33 wxMemoryDC mem_dc;
34 mem_dc.SetFont(GetFont().Bold());
35 wxSize header_extent = mem_dc.GetTextExtent(map_area.name);
36
37 int acc_height = header_extent.GetHeight() + 20;
38 int col_width = 0;
39
40 mem_dc.SetFont(GetFont());
41
42 std::vector<int> real_locations;
43
46 for (int section_id = 0; section_id < map_area.locations.size(); 44 for (int section_id = 0; section_id < map_area.locations.size();
47 section_id++) { 45 section_id++) {
48 const Location& location = map_area.locations.at(section_id); 46 const Location& location = map_area.locations.at(section_id);
49 wxSizer* container_sizer =
50 section_labels_[section_id]->GetContainingSizer();
51 47
52 if (!AP_IsLocationVisible(location.classification) && 48 if (!AP_IsLocationVisible(location.classification) &&
53 !(location.hunt && GetTrackerConfig().show_hunt_panels)) { 49 !(location.hunt && GetTrackerConfig().show_hunt_panels)) {
54 container_sizer->Hide(section_labels_[section_id]);
55 container_sizer->Hide(eye_indicators_[section_id]);
56 continue; 50 continue;
57 } else {
58 container_sizer->Show(section_labels_[section_id]);
59 container_sizer->Show(eye_indicators_[section_id]);
60 } 51 }
61 52
53 real_locations.push_back(section_id);
54
55 wxSize item_extent = mem_dc.GetTextExtent(location.name);
56 int item_height = std::max(32, item_extent.GetHeight()) + 10;
57 acc_height += item_height;
58
59 if (item_extent.GetWidth() > col_width) {
60 col_width = item_extent.GetWidth();
61 }
62 }
63
64 int item_width = col_width + 10 + 32;
65 int full_width = std::max(header_extent.GetWidth(), item_width) + 20;
66
67 Fit();
68 SetVirtualSize(full_width, acc_height);
69
70 rendered_ = wxBitmap(full_width, acc_height);
71 mem_dc.SelectObject(rendered_);
72 mem_dc.SetPen(*wxTRANSPARENT_PEN);
73 mem_dc.SetBrush(*wxBLACK_BRUSH);
74 mem_dc.DrawRectangle({0, 0}, {full_width, acc_height});
75
76 mem_dc.SetFont(GetFont().Bold());
77 mem_dc.SetTextForeground(*wxWHITE);
78 mem_dc.DrawText(map_area.name,
79 {(full_width - header_extent.GetWidth()) / 2, 10});
80
81 int cur_height = header_extent.GetHeight() + 20;
82
83 mem_dc.SetFont(GetFont());
84
85 for (int section_id : real_locations) {
86 const Location& location = map_area.locations.at(section_id);
87
62 bool checked = 88 bool checked =
63 AP_HasCheckedGameLocation(location.ap_location_id) || 89 AP_HasCheckedGameLocation(location.ap_location_id) ||
64 (location.hunt && AP_HasCheckedHuntPanel(location.ap_location_id)); 90 (location.hunt && AP_HasCheckedHuntPanel(location.ap_location_id));
91
92 wxBitmap* eye_ptr = checked ? &checked_eye_ : &unchecked_eye_;
93
94 mem_dc.DrawBitmap(*eye_ptr, {10, cur_height});
95
65 bool reachable = IsLocationReachable(location.ap_location_id); 96 bool reachable = IsLocationReachable(location.ap_location_id);
66 const wxColour* text_color = reachable ? wxWHITE : wxRED; 97 const wxColour* text_color = reachable ? wxWHITE : wxRED;
98 mem_dc.SetTextForeground(*text_color);
67 99
68 section_labels_[section_id]->SetForegroundColour(*text_color); 100 wxSize item_extent = mem_dc.GetTextExtent(location.name);
69 eye_indicators_[section_id]->SetChecked(checked); 101 mem_dc.DrawText(
102 location.name,
103 {10 + 32 + 10, cur_height + (32 - mem_dc.GetFontMetrics().height) / 2});
104
105 cur_height += 10 + 32;
70 } 106 }
107}
108
109void AreaPopup::OnPaint(wxPaintEvent& event) {
110 wxPaintDC dc(this);
111 PrepareDC(dc);
112 dc.DrawBitmap(rendered_, 0, 0);
71 113
72 section_labels_[0]->GetContainingSizer()->Layout(); 114 event.Skip();
73 GetSizer()->Fit(this);
74} 115}
diff --git a/src/area_popup.h b/src/area_popup.h index d5f6a50..00c644d 100644 --- a/src/area_popup.h +++ b/src/area_popup.h
@@ -7,19 +7,20 @@
7#include <wx/wx.h> 7#include <wx/wx.h>
8#endif 8#endif
9 9
10#include "eye_indicator.h" 10class AreaPopup : public wxScrolledCanvas {
11
12class AreaPopup : public wxScrolledWindow {
13 public: 11 public:
14 AreaPopup(wxWindow* parent, int area_id); 12 AreaPopup(wxWindow* parent, int area_id);
15 13
16 void UpdateIndicators(); 14 void UpdateIndicators();
17 15
18 private: 16 private:
17 void OnPaint(wxPaintEvent& event);
18
19 int area_id_; 19 int area_id_;
20 20
21 std::vector<wxStaticText*> section_labels_; 21 wxBitmap unchecked_eye_;
22 std::vector<EyeIndicator*> eye_indicators_; 22 wxBitmap checked_eye_;
23 wxBitmap rendered_;
23}; 24};
24 25
25#endif /* end of include guard: AREA_POPUP_H_03FAC988 */ 26#endif /* end of include guard: AREA_POPUP_H_03FAC988 */
diff --git a/src/eye_indicator.cpp b/src/eye_indicator.cpp deleted file mode 100644 index 61ad780..0000000 --- a/src/eye_indicator.cpp +++ /dev/null
@@ -1,51 +0,0 @@
1#include "eye_indicator.h"
2
3#include "global.h"
4
5EyeIndicator::EyeIndicator(wxWindow* parent) : wxWindow(parent, wxID_ANY) {
6 SetMinSize({32, 32});
7
8 Redraw();
9
10 Bind(wxEVT_PAINT, &EyeIndicator::OnPaint, this);
11}
12
13void EyeIndicator::SetChecked(bool checked) {
14 if (intended_checked_ != checked) {
15 intended_checked_ = checked;
16
17 Redraw();
18 }
19}
20
21const wxImage& EyeIndicator::GetUncheckedImage() {
22 static wxImage* unchecked_image = new wxImage(
23 GetAbsolutePath("assets/unchecked.png").c_str(), wxBITMAP_TYPE_PNG);
24 return *unchecked_image;
25}
26
27const wxImage& EyeIndicator::GetCheckedImage() {
28 static wxImage* checked_image = new wxImage(
29 GetAbsolutePath("assets/checked.png").c_str(), wxBITMAP_TYPE_PNG);
30 return *checked_image;
31}
32
33void EyeIndicator::OnPaint(wxPaintEvent& event) {
34 if (GetSize() != rendered_.GetSize() ||
35 intended_checked_ != rendered_checked_) {
36 Redraw();
37 }
38
39 wxPaintDC dc(this);
40 dc.DrawBitmap(rendered_, 0, 0);
41
42 event.Skip();
43}
44
45void EyeIndicator::Redraw() {
46 rendered_ =
47 wxBitmap((intended_checked_ ? GetCheckedImage() : GetUncheckedImage())
48 .Scale(GetSize().GetWidth(), GetSize().GetHeight(),
49 wxIMAGE_QUALITY_NORMAL));
50 rendered_checked_ = intended_checked_;
51}
diff --git a/src/eye_indicator.h b/src/eye_indicator.h deleted file mode 100644 index e8fd890..0000000 --- a/src/eye_indicator.h +++ /dev/null
@@ -1,30 +0,0 @@
1#ifndef EYE_INDICATOR_H_778150F2
2#define EYE_INDICATOR_H_778150F2
3
4#include <wx/wxprec.h>
5
6#ifndef WX_PRECOMP
7#include <wx/wx.h>
8#endif
9
10class EyeIndicator : public wxWindow {
11 public:
12 EyeIndicator(wxWindow* parent);
13
14 void SetChecked(bool checked);
15
16 private:
17 static const wxImage& GetUncheckedImage();
18 static const wxImage& GetCheckedImage();
19
20 void OnPaint(wxPaintEvent& event);
21
22 void Redraw();
23
24 bool intended_checked_ = false;
25
26 wxBitmap rendered_;
27 bool rendered_checked_ = false;
28};
29
30#endif /* end of include guard: EYE_INDICATOR_H_778150F2 */
diff --git a/src/game_data.cpp b/src/game_data.cpp index 5204262..8f237b0 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp
@@ -98,16 +98,14 @@ struct GameData {
98 98
99 for (const auto &room_it : lingo_config) { 99 for (const auto &room_it : lingo_config) {
100 int room_id = AddOrGetRoom(room_it.first.as<std::string>()); 100 int room_id = AddOrGetRoom(room_it.first.as<std::string>());
101 Room &room_obj = rooms_[room_id];
102 101
103 for (const auto &entrance_it : room_it.second["entrances"]) { 102 for (const auto &entrance_it : room_it.second["entrances"]) {
104 int from_room_id = AddOrGetRoom(entrance_it.first.as<std::string>()); 103 int from_room_id = AddOrGetRoom(entrance_it.first.as<std::string>());
105 Room &from_room_obj = rooms_[from_room_id];
106 104
107 switch (entrance_it.second.Type()) { 105 switch (entrance_it.second.Type()) {
108 case YAML::NodeType::Scalar: { 106 case YAML::NodeType::Scalar: {
109 // This is just "true". 107 // This is just "true".
110 from_room_obj.exits.push_back({.destination_room = room_id}); 108 rooms_[from_room_id].exits.push_back({.destination_room = room_id});
111 break; 109 break;
112 } 110 }
113 case YAML::NodeType::Map: { 111 case YAML::NodeType::Map: {
@@ -115,7 +113,7 @@ struct GameData {
115 exit_obj.destination_room = room_id; 113 exit_obj.destination_room = room_id;
116 114
117 if (entrance_it.second["door"]) { 115 if (entrance_it.second["door"]) {
118 std::string door_room = room_obj.name; 116 std::string door_room = rooms_[room_id].name;
119 if (entrance_it.second["room"]) { 117 if (entrance_it.second["room"]) {
120 door_room = entrance_it.second["room"].as<std::string>(); 118 door_room = entrance_it.second["room"].as<std::string>();
121 } 119 }
@@ -127,7 +125,7 @@ struct GameData {
127 exit_obj.painting = entrance_it.second["painting"].as<bool>(); 125 exit_obj.painting = entrance_it.second["painting"].as<bool>();
128 } 126 }
129 127
130 from_room_obj.exits.push_back(exit_obj); 128 rooms_[from_room_id].exits.push_back(exit_obj);
131 break; 129 break;
132 } 130 }
133 case YAML::NodeType::Sequence: { 131 case YAML::NodeType::Sequence: {
@@ -135,7 +133,7 @@ struct GameData {
135 Exit exit_obj; 133 Exit exit_obj;
136 exit_obj.destination_room = room_id; 134 exit_obj.destination_room = room_id;
137 135
138 std::string door_room = room_obj.name; 136 std::string door_room = rooms_[room_id].name;
139 if (option["room"]) { 137 if (option["room"]) {
140 door_room = option["room"].as<std::string>(); 138 door_room = option["room"].as<std::string>();
141 } 139 }
@@ -146,7 +144,7 @@ struct GameData {
146 exit_obj.painting = option["painting"].as<bool>(); 144 exit_obj.painting = option["painting"].as<bool>();
147 } 145 }
148 146
149 from_room_obj.exits.push_back(exit_obj); 147 rooms_[from_room_id].exits.push_back(exit_obj);
150 } 148 }
151 149
152 break; 150 break;
@@ -162,18 +160,17 @@ struct GameData {
162 160
163 if (room_it.second["panels"]) { 161 if (room_it.second["panels"]) {
164 for (const auto &panel_it : room_it.second["panels"]) { 162 for (const auto &panel_it : room_it.second["panels"]) {
165 int panel_id = 163 int panel_id = AddOrGetPanel(rooms_[room_id].name,
166 AddOrGetPanel(room_obj.name, panel_it.first.as<std::string>()); 164 panel_it.first.as<std::string>());
167 Panel &panel_obj = panels_[panel_id]; 165 rooms_[room_id].panels.push_back(panel_id);
168 room_obj.panels.push_back(panel_id);
169 166
170 if (panel_it.second["colors"]) { 167 if (panel_it.second["colors"]) {
171 if (panel_it.second["colors"].IsScalar()) { 168 if (panel_it.second["colors"].IsScalar()) {
172 panel_obj.colors.push_back(GetColorForString( 169 panels_[panel_id].colors.push_back(GetColorForString(
173 panel_it.second["colors"].as<std::string>())); 170 panel_it.second["colors"].as<std::string>()));
174 } else { 171 } else {
175 for (const auto &color_node : panel_it.second["colors"]) { 172 for (const auto &color_node : panel_it.second["colors"]) {
176 panel_obj.colors.push_back( 173 panels_[panel_id].colors.push_back(
177 GetColorForString(color_node.as<std::string>())); 174 GetColorForString(color_node.as<std::string>()));
178 } 175 }
179 } 176 }
@@ -181,11 +178,11 @@ struct GameData {
181 178
182 if (panel_it.second["required_room"]) { 179 if (panel_it.second["required_room"]) {
183 if (panel_it.second["required_room"].IsScalar()) { 180 if (panel_it.second["required_room"].IsScalar()) {
184 panel_obj.required_rooms.push_back(AddOrGetRoom( 181 panels_[panel_id].required_rooms.push_back(AddOrGetRoom(
185 panel_it.second["required_room"].as<std::string>())); 182 panel_it.second["required_room"].as<std::string>()));
186 } else { 183 } else {
187 for (const auto &rr_node : panel_it.second["required_room"]) { 184 for (const auto &rr_node : panel_it.second["required_room"]) {
188 panel_obj.required_rooms.push_back( 185 panels_[panel_id].required_rooms.push_back(
189 AddOrGetRoom(rr_node.as<std::string>())); 186 AddOrGetRoom(rr_node.as<std::string>()));
190 } 187 }
191 } 188 }
@@ -193,23 +190,22 @@ struct GameData {
193 190
194 if (panel_it.second["required_door"]) { 191 if (panel_it.second["required_door"]) {
195 if (panel_it.second["required_door"].IsMap()) { 192 if (panel_it.second["required_door"].IsMap()) {
196 std::string rd_room = room_obj.name; 193 std::string rd_room = rooms_[room_id].name;
197 if (panel_it.second["required_door"]["room"]) { 194 if (panel_it.second["required_door"]["room"]) {
198 rd_room = 195 rd_room =
199 panel_it.second["required_door"]["room"].as<std::string>(); 196 panel_it.second["required_door"]["room"].as<std::string>();
200 } 197 }
201 198
202 panel_obj.required_doors.push_back(AddOrGetDoor( 199 panels_[panel_id].required_doors.push_back(AddOrGetDoor(
203 rd_room, 200 rd_room,
204 panel_it.second["required_door"]["door"].as<std::string>())); 201 panel_it.second["required_door"]["door"].as<std::string>()));
205 } else { 202 } else {
206 for (const auto &rr_node : panel_it.second["required_door"]) { 203 for (const auto &rr_node : panel_it.second["required_door"]) {
207 std::string rd_room = room_obj.name; 204 std::string rd_room = rooms_[room_id].name;
208 if (rr_node["room"]) { 205 if (rr_node["room"]) {
209 rd_room = rr_node["room"].as<std::string>(); 206 rd_room = rr_node["room"].as<std::string>();
210 } 207 };
211 208 panels_[panel_id].required_doors.push_back(
212 panel_obj.required_doors.push_back(
213 AddOrGetDoor(rd_room, rr_node["door"].as<std::string>())); 209 AddOrGetDoor(rd_room, rr_node["door"].as<std::string>()));
214 } 210 }
215 } 211 }
@@ -217,61 +213,68 @@ struct GameData {
217 213
218 if (panel_it.second["required_panel"]) { 214 if (panel_it.second["required_panel"]) {
219 if (panel_it.second["required_panel"].IsMap()) { 215 if (panel_it.second["required_panel"].IsMap()) {
220 std::string rp_room = room_obj.name; 216 std::string rp_room = rooms_[room_id].name;
221 if (panel_it.second["required_panel"]["room"]) { 217 if (panel_it.second["required_panel"]["room"]) {
222 rp_room = 218 rp_room =
223 panel_it.second["required_panel"]["room"].as<std::string>(); 219 panel_it.second["required_panel"]["room"].as<std::string>();
224 } 220 }
225 221
226 panel_obj.required_panels.push_back(AddOrGetPanel( 222 int rp_id = AddOrGetPanel(
227 rp_room, panel_it.second["required_panel"]["panel"] 223 rp_room,
228 .as<std::string>())); 224 panel_it.second["required_panel"]["panel"].as<std::string>());
225 panels_[panel_id].required_panels.push_back(rp_id);
229 } else { 226 } else {
230 for (const auto &rp_node : panel_it.second["required_panel"]) { 227 for (const auto &rp_node : panel_it.second["required_panel"]) {
231 std::string rp_room = room_obj.name; 228 std::string rp_room = rooms_[room_id].name;
232 if (rp_node["room"]) { 229 if (rp_node["room"]) {
233 rp_room = rp_node["room"].as<std::string>(); 230 rp_room = rp_node["room"].as<std::string>();
234 } 231 }
235 232
236 panel_obj.required_panels.push_back( 233 int rp_id =
237 AddOrGetPanel(rp_room, rp_node["panel"].as<std::string>())); 234 AddOrGetPanel(rp_room, rp_node["panel"].as<std::string>());
235 panels_[panel_id].required_panels.push_back(rp_id);
238 } 236 }
239 } 237 }
240 } 238 }
241 239
242 if (panel_it.second["check"]) { 240 if (panel_it.second["check"]) {
243 panel_obj.check = panel_it.second["check"].as<bool>(); 241 panels_[panel_id].check = panel_it.second["check"].as<bool>();
244 } 242 }
245 243
246 if (panel_it.second["achievement"]) { 244 if (panel_it.second["achievement"]) {
247 panel_obj.achievement = true; 245 panels_[panel_id].achievement = true;
248 panel_obj.achievement_name = 246 panels_[panel_id].achievement_name =
249 panel_it.second["achievement"].as<std::string>(); 247 panel_it.second["achievement"].as<std::string>();
250 248
251 achievement_panels_.push_back(panel_id); 249 achievement_panels_.push_back(panel_id);
252 } 250 }
253 251
254 if (panel_it.second["hunt"]) { 252 if (panel_it.second["hunt"]) {
255 panel_obj.hunt = panel_it.second["hunt"].as<bool>(); 253 panels_[panel_id].hunt = panel_it.second["hunt"].as<bool>();
256 } 254 }
257 255
258 if (panel_it.second["exclude_reduce"]) { 256 if (panel_it.second["exclude_reduce"]) {
259 panel_obj.exclude_reduce = 257 panels_[panel_id].exclude_reduce =
260 panel_it.second["exclude_reduce"].as<bool>(); 258 panel_it.second["exclude_reduce"].as<bool>();
261 } 259 }
262 260
263 if (panel_it.second["non_counting"]) { 261 if (panel_it.second["non_counting"]) {
264 panel_obj.non_counting = panel_it.second["non_counting"].as<bool>(); 262 panels_[panel_id].non_counting =
263 panel_it.second["non_counting"].as<bool>();
265 } 264 }
266 265
267 if (ids_config["panels"] && ids_config["panels"][room_obj.name] && 266 if (ids_config["panels"] &&
268 ids_config["panels"][room_obj.name][panel_obj.name]) { 267 ids_config["panels"][rooms_[room_id].name] &&
269 panel_obj.ap_location_id = 268 ids_config["panels"][rooms_[room_id].name]
270 ids_config["panels"][room_obj.name][panel_obj.name].as<int>(); 269 [panels_[panel_id].name]) {
270 panels_[panel_id].ap_location_id =
271 ids_config["panels"][rooms_[room_id].name]
272 [panels_[panel_id].name]
273 .as<int>();
271 } else { 274 } else {
272 std::ostringstream errmsg; 275 std::ostringstream errmsg;
273 errmsg << "Missing AP location ID for panel " << room_obj.name 276 errmsg << "Missing AP location ID for panel "
274 << " - " << panel_obj.name; 277 << rooms_[room_id].name << " - " << panels_[panel_id].name;
275 TrackerLog(errmsg.str()); 278 TrackerLog(errmsg.str());
276 } 279 }
277 } 280 }
@@ -279,10 +282,9 @@ struct GameData {
279 282
280 if (room_it.second["doors"]) { 283 if (room_it.second["doors"]) {
281 for (const auto &door_it : room_it.second["doors"]) { 284 for (const auto &door_it : room_it.second["doors"]) {
282 int door_id = 285 int door_id = AddOrGetDoor(rooms_[room_id].name,
283 AddOrGetDoor(room_obj.name, door_it.first.as<std::string>()); 286 door_it.first.as<std::string>());
284 door_definition_order_.push_back(door_id); 287 door_definition_order_.push_back(door_id);
285 Door &door_obj = doors_[door_id];
286 288
287 bool has_external_panels = false; 289 bool has_external_panels = false;
288 std::vector<std::string> panel_names; 290 std::vector<std::string> panel_names;
@@ -290,103 +292,117 @@ struct GameData {
290 for (const auto &panel_node : door_it.second["panels"]) { 292 for (const auto &panel_node : door_it.second["panels"]) {
291 if (panel_node.IsScalar()) { 293 if (panel_node.IsScalar()) {
292 panel_names.push_back(panel_node.as<std::string>()); 294 panel_names.push_back(panel_node.as<std::string>());
293 door_obj.panels.push_back( 295 doors_[door_id].panels.push_back(AddOrGetPanel(
294 AddOrGetPanel(room_obj.name, panel_node.as<std::string>())); 296 rooms_[room_id].name, panel_node.as<std::string>()));
295 } else { 297 } else {
296 has_external_panels = true; 298 has_external_panels = true;
297 panel_names.push_back(panel_node["panel"].as<std::string>()); 299 panel_names.push_back(panel_node["panel"].as<std::string>());
298 door_obj.panels.push_back( 300 doors_[door_id].panels.push_back(
299 AddOrGetPanel(panel_node["room"].as<std::string>(), 301 AddOrGetPanel(panel_node["room"].as<std::string>(),
300 panel_node["panel"].as<std::string>())); 302 panel_node["panel"].as<std::string>()));
301 } 303 }
302 } 304 }
303 305
304 if (door_it.second["skip_location"]) { 306 if (door_it.second["skip_location"]) {
305 door_obj.skip_location = door_it.second["skip_location"].as<bool>(); 307 doors_[door_id].skip_location =
308 door_it.second["skip_location"].as<bool>();
306 } 309 }
307 310
308 if (door_it.second["skip_item"]) { 311 if (door_it.second["skip_item"]) {
309 door_obj.skip_item = door_it.second["skip_item"].as<bool>(); 312 doors_[door_id].skip_item = door_it.second["skip_item"].as<bool>();
310 } 313 }
311 314
312 if (door_it.second["event"]) { 315 if (door_it.second["event"]) {
313 door_obj.skip_location = door_it.second["event"].as<bool>(); 316 doors_[door_id].skip_location = door_it.second["event"].as<bool>();
314 door_obj.skip_item = door_it.second["event"].as<bool>(); 317 doors_[door_id].skip_item = door_it.second["event"].as<bool>();
315 door_obj.is_event = door_it.second["event"].as<bool>(); 318 doors_[door_id].is_event = door_it.second["event"].as<bool>();
316 } 319 }
317 320
318 if (door_it.second["item_name"]) { 321 if (door_it.second["item_name"]) {
319 door_obj.item_name = door_it.second["item_name"].as<std::string>(); 322 doors_[door_id].item_name =
323 door_it.second["item_name"].as<std::string>();
320 } else if (!door_it.second["skip_item"] && !door_it.second["event"]) { 324 } else if (!door_it.second["skip_item"] && !door_it.second["event"]) {
321 door_obj.item_name = room_obj.name + " - " + door_obj.name; 325 doors_[door_id].item_name =
326 rooms_[room_id].name + " - " + doors_[door_id].name;
322 } 327 }
323 328
324 if (!door_it.second["skip_item"] && !door_it.second["event"]) { 329 if (!door_it.second["skip_item"] && !door_it.second["event"]) {
325 if (ids_config["doors"] && ids_config["doors"][room_obj.name] && 330 if (ids_config["doors"] &&
326 ids_config["doors"][room_obj.name][door_obj.name] && 331 ids_config["doors"][rooms_[room_id].name] &&
327 ids_config["doors"][room_obj.name][door_obj.name]["item"]) { 332 ids_config["doors"][rooms_[room_id].name]
328 door_obj.ap_item_id = 333 [doors_[door_id].name] &&
329 ids_config["doors"][room_obj.name][door_obj.name]["item"] 334 ids_config["doors"][rooms_[room_id].name][doors_[door_id].name]
330 .as<int>(); 335 ["item"]) {
336 doors_[door_id].ap_item_id =
337 ids_config["doors"][rooms_[room_id].name]
338 [doors_[door_id].name]["item"]
339 .as<int>();
331 } else { 340 } else {
332 std::ostringstream errmsg; 341 std::ostringstream errmsg;
333 errmsg << "Missing AP item ID for door " << room_obj.name << " - " 342 errmsg << "Missing AP item ID for door " << rooms_[room_id].name
334 << door_obj.name; 343 << " - " << doors_[door_id].name;
335 TrackerLog(errmsg.str()); 344 TrackerLog(errmsg.str());
336 } 345 }
337 } 346 }
338 347
339 if (door_it.second["group"]) { 348 if (door_it.second["group"]) {
340 door_obj.group_name = door_it.second["group"].as<std::string>(); 349 doors_[door_id].group_name =
350 door_it.second["group"].as<std::string>();
341 351
342 if (ids_config["door_groups"] && 352 if (ids_config["door_groups"] &&
343 ids_config["door_groups"][door_obj.group_name]) { 353 ids_config["door_groups"][doors_[door_id].group_name]) {
344 door_obj.group_ap_item_id = 354 doors_[door_id].group_ap_item_id =
345 ids_config["door_groups"][door_obj.group_name].as<int>(); 355 ids_config["door_groups"][doors_[door_id].group_name]
356 .as<int>();
346 } else { 357 } else {
347 std::ostringstream errmsg; 358 std::ostringstream errmsg;
348 errmsg << "Missing AP item ID for door group " 359 errmsg << "Missing AP item ID for door group "
349 << door_obj.group_name; 360 << doors_[door_id].group_name;
350 TrackerLog(errmsg.str()); 361 TrackerLog(errmsg.str());
351 } 362 }
352 } 363 }
353 364
354 if (door_it.second["location_name"]) { 365 if (door_it.second["location_name"]) {
355 door_obj.location_name = 366 doors_[door_id].location_name =
356 door_it.second["location_name"].as<std::string>(); 367 door_it.second["location_name"].as<std::string>();
357 } else if (!door_it.second["skip_location"] && 368 } else if (!door_it.second["skip_location"] &&
358 !door_it.second["event"]) { 369 !door_it.second["event"]) {
359 if (has_external_panels) { 370 if (has_external_panels) {
360 std::ostringstream errmsg; 371 std::ostringstream errmsg;
361 errmsg 372 errmsg
362 << room_obj.name << " - " << door_obj.name 373 << rooms_[room_id].name << " - " << doors_[door_id].name
363 << " has panels from other rooms but does not have an " 374 << " has panels from other rooms but does not have an "
364 "explicit " 375 "explicit "
365 "location name and is not marked skip_location or event"; 376 "location name and is not marked skip_location or event";
366 TrackerLog(errmsg.str()); 377 TrackerLog(errmsg.str());
367 } 378 }
368 379
369 door_obj.location_name = 380 doors_[door_id].location_name =
370 room_obj.name + " - " + hatkirby::implode(panel_names, ", "); 381 rooms_[room_id].name + " - " +
382 hatkirby::implode(panel_names, ", ");
371 } 383 }
372 384
373 if (!door_it.second["skip_location"] && !door_it.second["event"]) { 385 if (!door_it.second["skip_location"] && !door_it.second["event"]) {
374 if (ids_config["doors"] && ids_config["doors"][room_obj.name] && 386 if (ids_config["doors"] &&
375 ids_config["doors"][room_obj.name][door_obj.name] && 387 ids_config["doors"][rooms_[room_id].name] &&
376 ids_config["doors"][room_obj.name][door_obj.name]["location"]) { 388 ids_config["doors"][rooms_[room_id].name]
377 door_obj.ap_location_id = 389 [doors_[door_id].name] &&
378 ids_config["doors"][room_obj.name][door_obj.name]["location"] 390 ids_config["doors"][rooms_[room_id].name][doors_[door_id].name]
379 .as<int>(); 391 ["location"]) {
392 doors_[door_id].ap_location_id =
393 ids_config["doors"][rooms_[room_id].name]
394 [doors_[door_id].name]["location"]
395 .as<int>();
380 } else { 396 } else {
381 std::ostringstream errmsg; 397 std::ostringstream errmsg;
382 errmsg << "Missing AP location ID for door " << room_obj.name 398 errmsg << "Missing AP location ID for door "
383 << " - " << door_obj.name; 399 << rooms_[room_id].name << " - " << doors_[door_id].name;
384 TrackerLog(errmsg.str()); 400 TrackerLog(errmsg.str());
385 } 401 }
386 } 402 }
387 403
388 if (door_it.second["include_reduce"]) { 404 if (door_it.second["include_reduce"]) {
389 door_obj.exclude_reduce = 405 doors_[door_id].exclude_reduce =
390 !door_it.second["include_reduce"].as<bool>(); 406 !door_it.second["include_reduce"].as<bool>();
391 } 407 }
392 } 408 }
@@ -402,7 +418,7 @@ struct GameData {
402 painting_exit.id = painting_id; 418 painting_exit.id = painting_id;
403 419
404 if (painting["required_door"]) { 420 if (painting["required_door"]) {
405 std::string rd_room = room_obj.name; 421 std::string rd_room = rooms_[room_id].name;
406 if (painting["required_door"]["room"]) { 422 if (painting["required_door"]["room"]) {
407 rd_room = painting["required_door"]["room"].as<std::string>(); 423 rd_room = painting["required_door"]["room"].as<std::string>();
408 } 424 }
@@ -411,7 +427,7 @@ struct GameData {
411 rd_room, painting["required_door"]["door"].as<std::string>()); 427 rd_room, painting["required_door"]["door"].as<std::string>());
412 } 428 }
413 429
414 room_obj.paintings.push_back(painting_exit); 430 rooms_[room_id].paintings.push_back(painting_exit);
415 } 431 }
416 } 432 }
417 } 433 }
@@ -438,7 +454,8 @@ struct GameData {
438 int door_id = -1; 454 int door_id = -1;
439 455
440 if (stage.IsScalar()) { 456 if (stage.IsScalar()) {
441 door_id = AddOrGetDoor(room_obj.name, stage.as<std::string>()); 457 door_id =
458 AddOrGetDoor(rooms_[room_id].name, stage.as<std::string>());
442 } else { 459 } else {
443 door_id = AddOrGetDoor(stage["room"].as<std::string>(), 460 door_id = AddOrGetDoor(stage["room"].as<std::string>(),
444 stage["door"].as<std::string>()); 461 stage["door"].as<std::string>());
diff --git a/src/tracker_frame.cpp b/src/tracker_frame.cpp index 4e3a8a8..a8c1063 100644 --- a/src/tracker_frame.cpp +++ b/src/tracker_frame.cpp
@@ -30,8 +30,6 @@ TrackerFrame::TrackerFrame()
30 30
31 AP_SetTrackerFrame(this); 31 AP_SetTrackerFrame(this);
32 32
33 SetSize(1280, 728);
34
35 wxMenu *menuFile = new wxMenu(); 33 wxMenu *menuFile = new wxMenu();
36 menuFile->Append(ID_CONNECT, "&Connect"); 34 menuFile->Append(ID_CONNECT, "&Connect");
37 menuFile->Append(ID_SETTINGS, "&Settings"); 35 menuFile->Append(ID_SETTINGS, "&Settings");
@@ -70,6 +68,7 @@ TrackerFrame::TrackerFrame()
70 top_sizer->Add(tracker_panel_, wxSizerFlags().Expand().Proportion(3)); 68 top_sizer->Add(tracker_panel_, wxSizerFlags().Expand().Proportion(3));
71 69
72 SetSizerAndFit(top_sizer); 70 SetSizerAndFit(top_sizer);
71 SetSize(1280, 728);
73 72
74 if (!GetTrackerConfig().asked_to_check_for_updates) { 73 if (!GetTrackerConfig().asked_to_check_for_updates) {
75 GetTrackerConfig().asked_to_check_for_updates = true; 74 GetTrackerConfig().asked_to_check_for_updates = true;
diff --git a/src/tracker_panel.cpp b/src/tracker_panel.cpp index 81cb595..3102110 100644 --- a/src/tracker_panel.cpp +++ b/src/tracker_panel.cpp
@@ -35,11 +35,11 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
35} 35}
36 36
37void TrackerPanel::UpdateIndicators() { 37void TrackerPanel::UpdateIndicators() {
38 Redraw();
39
40 for (AreaIndicator &area : areas_) { 38 for (AreaIndicator &area : areas_) {
41 area.popup->UpdateIndicators(); 39 area.popup->UpdateIndicators();
42 } 40 }
41
42 Redraw();
43} 43}
44 44
45void TrackerPanel::OnPaint(wxPaintEvent &event) { 45void TrackerPanel::OnPaint(wxPaintEvent &event) {
@@ -178,8 +178,10 @@ void TrackerPanel::Redraw() {
178 int popup_y = 178 int popup_y =
179 final_y + map_area.map_y * final_width / image_size.GetWidth(); 179 final_y + map_area.map_y * final_width / image_size.GetWidth();
180 180
181 area.popup->SetMaxSize(panel_size); 181 area.popup->SetClientSize(
182 area.popup->GetSizer()->Fit(area.popup); 182 area.popup->GetVirtualSize().GetWidth(),
183 std::min(panel_size.GetHeight(),
184 area.popup->GetVirtualSize().GetHeight()));
183 185
184 if (popup_x + area.popup->GetSize().GetWidth() > panel_size.GetWidth()) { 186 if (popup_x + area.popup->GetSize().GetWidth() > panel_size.GetWidth()) {
185 popup_x = panel_size.GetWidth() - area.popup->GetSize().GetWidth(); 187 popup_x = panel_size.GetWidth() - area.popup->GetSize().GetWidth();
diff --git a/src/version.h b/src/version.h index ed5efaa..e9c8264 100644 --- a/src/version.h +++ b/src/version.h
@@ -35,6 +35,6 @@ std::ostream& operator<<(std::ostream& out, const Version& ver) {
35 return out << "v" << ver.major << "." << ver.minor << "." << ver.revision; 35 return out << "v" << ver.major << "." << ver.minor << "." << ver.revision;
36} 36}
37 37
38constexpr const Version kTrackerVersion = Version(0, 6, 2); 38constexpr const Version kTrackerVersion = Version(0, 6, 4);
39 39
40#endif /* end of include guard: VERSION_H_C757E53C */ \ No newline at end of file 40#endif /* end of include guard: VERSION_H_C757E53C */ \ No newline at end of file