about summary refs log tree commit diff stats
path: root/src/subway_map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/subway_map.cpp')
-rw-r--r--src/subway_map.cpp127
1 files changed, 52 insertions, 75 deletions
diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 0a250fb..c554b16 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp
@@ -9,6 +9,7 @@
9#include "ap_state.h" 9#include "ap_state.h"
10#include "game_data.h" 10#include "game_data.h"
11#include "global.h" 11#include "global.h"
12#include "report_popup.h"
12#include "tracker_state.h" 13#include "tracker_state.h"
13 14
14constexpr int AREA_ACTUAL_SIZE = 21; 15constexpr int AREA_ACTUAL_SIZE = 21;
@@ -31,14 +32,6 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
31 return; 32 return;
32 } 33 }
33 34
34 unchecked_eye_ =
35 wxBitmap(wxImage(GetAbsolutePath("assets/unchecked.png").c_str(),
36 wxBITMAP_TYPE_PNG)
37 .Scale(32, 32));
38 checked_eye_ = wxBitmap(
39 wxImage(GetAbsolutePath("assets/checked.png").c_str(), wxBITMAP_TYPE_PNG)
40 .Scale(32, 32));
41
42 tree_ = std::make_unique<quadtree::Quadtree<int, GetItemBox>>( 35 tree_ = std::make_unique<quadtree::Quadtree<int, GetItemBox>>(
43 quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()), 36 quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()),
44 static_cast<float>(map_image_.GetHeight())}); 37 static_cast<float>(map_image_.GetHeight())});
@@ -63,6 +56,8 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
63 help_button_ = new wxButton(this, wxID_ANY, "Help"); 56 help_button_ = new wxButton(this, wxID_ANY, "Help");
64 help_button_->Bind(wxEVT_BUTTON, &SubwayMap::OnClickHelp, this); 57 help_button_->Bind(wxEVT_BUTTON, &SubwayMap::OnClickHelp, this);
65 SetUpHelpButton(); 58 SetUpHelpButton();
59
60 report_popup_ = new ReportPopup(this);
66} 61}
67 62
68void SubwayMap::OnConnect() { 63void SubwayMap::OnConnect() {
@@ -202,6 +197,8 @@ void SubwayMap::UpdateIndicators() {
202 } 197 }
203 } 198 }
204 199
200 report_popup_->UpdateIndicators();
201
205 Redraw(); 202 Redraw();
206} 203}
207 204
@@ -310,67 +307,6 @@ void SubwayMap::OnPaint(wxPaintEvent &event) {
310 } 307 }
311 308
312 if (hovered_item_) { 309 if (hovered_item_) {
313 // Note that these requirements are duplicated on OnMouseClick so that it
314 // knows when an item has a hover effect.
315 const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_);
316 std::optional<int> subway_door = GetRealSubwayDoor(subway_item);
317
318 if (subway_door && !GetDoorRequirements(*subway_door).empty()) {
319 const std::map<std::string, bool> &report =
320 GetDoorRequirements(*subway_door);
321
322 int acc_height = 10;
323 int col_width = 0;
324
325 for (const auto &[text, obtained] : report) {
326 wxSize item_extent = dc.GetTextExtent(text);
327 int item_height = std::max(32, item_extent.GetHeight()) + 10;
328 acc_height += item_height;
329
330 if (item_extent.GetWidth() > col_width) {
331 col_width = item_extent.GetWidth();
332 }
333 }
334
335 int item_width = col_width + 10 + 32;
336 int full_width = item_width + 20;
337
338 wxPoint popup_pos =
339 MapPosToRenderPos({subway_item.x + AREA_ACTUAL_SIZE / 2,
340 subway_item.y + AREA_ACTUAL_SIZE / 2});
341
342 if (popup_pos.x + full_width > GetSize().GetWidth()) {
343 popup_pos.x = GetSize().GetWidth() - full_width;
344 }
345 if (popup_pos.y + acc_height > GetSize().GetHeight()) {
346 popup_pos.y = GetSize().GetHeight() - acc_height;
347 }
348
349 dc.SetPen(*wxTRANSPARENT_PEN);
350 dc.SetBrush(*wxBLACK_BRUSH);
351 dc.DrawRectangle(popup_pos, {full_width, acc_height});
352
353 dc.SetFont(GetFont());
354
355 int cur_height = 10;
356
357 for (const auto &[text, obtained] : report) {
358 wxBitmap *eye_ptr = obtained ? &checked_eye_ : &unchecked_eye_;
359
360 dc.DrawBitmap(*eye_ptr, popup_pos + wxPoint{10, cur_height});
361
362 dc.SetTextForeground(obtained ? *wxWHITE : *wxRED);
363 wxSize item_extent = dc.GetTextExtent(text);
364 dc.DrawText(
365 text,
366 popup_pos +
367 wxPoint{10 + 32 + 10,
368 cur_height + (32 - dc.GetFontMetrics().height) / 2});
369
370 cur_height += 10 + 32;
371 }
372 }
373
374 if (networks_.IsItemInNetwork(*hovered_item_)) { 310 if (networks_.IsItemInNetwork(*hovered_item_)) {
375 dc.SetBrush(*wxTRANSPARENT_BRUSH); 311 dc.SetBrush(*wxTRANSPARENT_BRUSH);
376 312
@@ -470,9 +406,7 @@ void SubwayMap::OnMouseMove(wxMouseEvent &event) {
470 } 406 }
471 407
472 if (!sticky_hover_ && actual_hover_ != hovered_item_) { 408 if (!sticky_hover_ && actual_hover_ != hovered_item_) {
473 hovered_item_ = actual_hover_; 409 EvaluateHover();
474
475 Refresh();
476 } 410 }
477 411
478 if (scroll_mode_) { 412 if (scroll_mode_) {
@@ -514,13 +448,11 @@ void SubwayMap::OnMouseClick(wxMouseEvent &event) {
514 if ((subway_door && !GetDoorRequirements(*subway_door).empty()) || 448 if ((subway_door && !GetDoorRequirements(*subway_door).empty()) ||
515 networks_.IsItemInNetwork(*hovered_item_)) { 449 networks_.IsItemInNetwork(*hovered_item_)) {
516 if (actual_hover_ != hovered_item_) { 450 if (actual_hover_ != hovered_item_) {
517 hovered_item_ = actual_hover_; 451 EvaluateHover();
518 452
519 if (!hovered_item_) { 453 if (!hovered_item_) {
520 sticky_hover_ = false; 454 sticky_hover_ = false;
521 } 455 }
522
523 Refresh();
524 } else { 456 } else {
525 sticky_hover_ = !sticky_hover_; 457 sticky_hover_ = !sticky_hover_;
526 } 458 }
@@ -723,6 +655,51 @@ void SubwayMap::EvaluateScroll(wxPoint pos) {
723 SetScrollSpeed(scroll_x, scroll_y); 655 SetScrollSpeed(scroll_x, scroll_y);
724} 656}
725 657
658void SubwayMap::EvaluateHover() {
659 hovered_item_ = actual_hover_;
660
661 if (hovered_item_) {
662 // Note that these requirements are duplicated on OnMouseClick so that it
663 // knows when an item has a hover effect.
664 const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_);
665 std::optional<int> subway_door = GetRealSubwayDoor(subway_item);
666
667 if (subway_door && !GetDoorRequirements(*subway_door).empty()) {
668 report_popup_->SetDoorId(*subway_door);
669
670 wxPoint popupPos =
671 MapPosToRenderPos({subway_item.x + AREA_ACTUAL_SIZE / 2,
672 subway_item.y + AREA_ACTUAL_SIZE / 2});
673
674 report_popup_->SetClientSize(
675 report_popup_->GetVirtualSize().GetWidth(),
676 std::min(GetSize().GetHeight(),
677 report_popup_->GetVirtualSize().GetHeight()));
678
679 if (popupPos.x + report_popup_->GetSize().GetWidth() >
680 GetSize().GetWidth()) {
681 popupPos.x = GetSize().GetWidth() - report_popup_->GetSize().GetWidth();
682 }
683 if (popupPos.y + report_popup_->GetSize().GetHeight() >
684 GetSize().GetHeight()) {
685 popupPos.y =
686 GetSize().GetHeight() - report_popup_->GetSize().GetHeight();
687 }
688 report_popup_->SetPosition(popupPos);
689
690 report_popup_->Show();
691 } else {
692 report_popup_->Reset();
693 report_popup_->Hide();
694 }
695 } else {
696 report_popup_->Reset();
697 report_popup_->Hide();
698 }
699
700 Refresh();
701}
702
726wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { 703wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const {
727 return {static_cast<int>(pos.x * render_width_ * zoom_ / 704 return {static_cast<int>(pos.x * render_width_ * zoom_ /
728 map_image_.GetSize().GetWidth() + 705 map_image_.GetSize().GetWidth() +