diff options
Diffstat (limited to 'src/subway_map.cpp')
-rw-r--r-- | src/subway_map.cpp | 293 |
1 files changed, 157 insertions, 136 deletions
diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 0a250fb..55ac411 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp | |||
@@ -9,12 +9,28 @@ | |||
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 | ||
14 | constexpr int AREA_ACTUAL_SIZE = 21; | 15 | constexpr int AREA_ACTUAL_SIZE = 21; |
15 | constexpr int OWL_ACTUAL_SIZE = 32; | 16 | constexpr int OWL_ACTUAL_SIZE = 32; |
17 | constexpr int PAINTING_RADIUS = 9; // the actual circles on the map are radius 11 | ||
18 | constexpr int PAINTING_EXIT_RADIUS = 6; | ||
16 | 19 | ||
17 | enum class ItemDrawType { kNone, kBox, kOwl }; | 20 | enum class ItemDrawType { kNone, kBox, kOwl, kOwlExit }; |
21 | |||
22 | namespace { | ||
23 | |||
24 | wxPoint GetSubwayItemMapCenter(const SubwayItem &subway_item) { | ||
25 | if (subway_item.painting) { | ||
26 | return {subway_item.x, subway_item.y}; | ||
27 | } else { | ||
28 | return {subway_item.x + AREA_ACTUAL_SIZE / 2, | ||
29 | subway_item.y + AREA_ACTUAL_SIZE / 2}; | ||
30 | } | ||
31 | } | ||
32 | |||
33 | } // namespace | ||
18 | 34 | ||
19 | SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | 35 | SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { |
20 | SetBackgroundStyle(wxBG_STYLE_PAINT); | 36 | SetBackgroundStyle(wxBG_STYLE_PAINT); |
@@ -31,14 +47,6 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
31 | return; | 47 | return; |
32 | } | 48 | } |
33 | 49 | ||
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>>( | 50 | tree_ = std::make_unique<quadtree::Quadtree<int, GetItemBox>>( |
43 | quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()), | 51 | quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()), |
44 | static_cast<float>(map_image_.GetHeight())}); | 52 | static_cast<float>(map_image_.GetHeight())}); |
@@ -57,12 +65,14 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
57 | Bind(wxEVT_LEFT_DOWN, &SubwayMap::OnMouseClick, this); | 65 | Bind(wxEVT_LEFT_DOWN, &SubwayMap::OnMouseClick, this); |
58 | Bind(wxEVT_TIMER, &SubwayMap::OnTimer, this); | 66 | Bind(wxEVT_TIMER, &SubwayMap::OnTimer, this); |
59 | 67 | ||
60 | zoom_slider_ = new wxSlider(this, wxID_ANY, 0, 0, 8, {15, 15}); | 68 | zoom_slider_ = new wxSlider(this, wxID_ANY, 0, 0, 8, FromDIP(wxPoint{15, 15})); |
61 | zoom_slider_->Bind(wxEVT_SLIDER, &SubwayMap::OnZoomSlide, this); | 69 | zoom_slider_->Bind(wxEVT_SLIDER, &SubwayMap::OnZoomSlide, this); |
62 | 70 | ||
63 | help_button_ = new wxButton(this, wxID_ANY, "Help"); | 71 | help_button_ = new wxButton(this, wxID_ANY, "Help"); |
64 | help_button_->Bind(wxEVT_BUTTON, &SubwayMap::OnClickHelp, this); | 72 | help_button_->Bind(wxEVT_BUTTON, &SubwayMap::OnClickHelp, this); |
65 | SetUpHelpButton(); | 73 | SetUpHelpButton(); |
74 | |||
75 | report_popup_ = new ReportPopup(this); | ||
66 | } | 76 | } |
67 | 77 | ||
68 | void SubwayMap::OnConnect() { | 78 | void SubwayMap::OnConnect() { |
@@ -73,11 +83,11 @@ void SubwayMap::OnConnect() { | |||
73 | std::map<std::string, std::vector<int>> exits; | 83 | std::map<std::string, std::vector<int>> exits; |
74 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { | 84 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { |
75 | if (AP_HasEarlyColorHallways() && | 85 | if (AP_HasEarlyColorHallways() && |
76 | subway_item.special == "starting_room_paintings") { | 86 | subway_item.special == "early_color_hallways") { |
77 | entrances["early_ch"].push_back(subway_item.id); | 87 | entrances["early_ch"].push_back(subway_item.id); |
78 | } | 88 | } |
79 | 89 | ||
80 | if (AP_IsPaintingShuffle() && !subway_item.paintings.empty()) { | 90 | if (AP_IsPaintingShuffle() && subway_item.painting) { |
81 | continue; | 91 | continue; |
82 | } | 92 | } |
83 | 93 | ||
@@ -174,6 +184,8 @@ void SubwayMap::OnConnect() { | |||
174 | } | 184 | } |
175 | 185 | ||
176 | checked_paintings_.clear(); | 186 | checked_paintings_.clear(); |
187 | |||
188 | UpdateIndicators(); | ||
177 | } | 189 | } |
178 | 190 | ||
179 | void SubwayMap::UpdateIndicators() { | 191 | void SubwayMap::UpdateIndicators() { |
@@ -202,6 +214,8 @@ void SubwayMap::UpdateIndicators() { | |||
202 | } | 214 | } |
203 | } | 215 | } |
204 | 216 | ||
217 | report_popup_->UpdateIndicators(); | ||
218 | |||
205 | Redraw(); | 219 | Redraw(); |
206 | } | 220 | } |
207 | 221 | ||
@@ -255,6 +269,9 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
255 | SetZoomPos({zoom_x_, zoom_y_}); | 269 | SetZoomPos({zoom_x_, zoom_y_}); |
256 | 270 | ||
257 | SetUpHelpButton(); | 271 | SetUpHelpButton(); |
272 | |||
273 | zoom_slider_->SetSize(FromDIP(15), FromDIP(15), wxDefaultCoord, | ||
274 | wxDefaultCoord, wxSIZE_AUTO); | ||
258 | } | 275 | } |
259 | 276 | ||
260 | wxBufferedPaintDC dc(this); | 277 | wxBufferedPaintDC dc(this); |
@@ -310,67 +327,6 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
310 | } | 327 | } |
311 | 328 | ||
312 | if (hovered_item_) { | 329 | 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_)) { | 330 | if (networks_.IsItemInNetwork(*hovered_item_)) { |
375 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | 331 | dc.SetBrush(*wxTRANSPARENT_BRUSH); |
376 | 332 | ||
@@ -378,10 +334,8 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
378 | const SubwayItem &item1 = GD_GetSubwayItem(node.entry); | 334 | const SubwayItem &item1 = GD_GetSubwayItem(node.entry); |
379 | const SubwayItem &item2 = GD_GetSubwayItem(node.exit); | 335 | const SubwayItem &item2 = GD_GetSubwayItem(node.exit); |
380 | 336 | ||
381 | wxPoint item1_pos = MapPosToRenderPos( | 337 | wxPoint item1_pos = MapPosToRenderPos(GetSubwayItemMapCenter(item1)); |
382 | {item1.x + AREA_ACTUAL_SIZE / 2, item1.y + AREA_ACTUAL_SIZE / 2}); | 338 | wxPoint item2_pos = MapPosToRenderPos(GetSubwayItemMapCenter(item2)); |
383 | wxPoint item2_pos = MapPosToRenderPos( | ||
384 | {item2.x + AREA_ACTUAL_SIZE / 2, item2.y + AREA_ACTUAL_SIZE / 2}); | ||
385 | 339 | ||
386 | int left = std::min(item1_pos.x, item2_pos.x); | 340 | int left = std::min(item1_pos.x, item2_pos.x); |
387 | int top = std::min(item1_pos.y, item2_pos.y); | 341 | int top = std::min(item1_pos.y, item2_pos.y); |
@@ -470,9 +424,7 @@ void SubwayMap::OnMouseMove(wxMouseEvent &event) { | |||
470 | } | 424 | } |
471 | 425 | ||
472 | if (!sticky_hover_ && actual_hover_ != hovered_item_) { | 426 | if (!sticky_hover_ && actual_hover_ != hovered_item_) { |
473 | hovered_item_ = actual_hover_; | 427 | EvaluateHover(); |
474 | |||
475 | Refresh(); | ||
476 | } | 428 | } |
477 | 429 | ||
478 | if (scroll_mode_) { | 430 | if (scroll_mode_) { |
@@ -514,13 +466,11 @@ void SubwayMap::OnMouseClick(wxMouseEvent &event) { | |||
514 | if ((subway_door && !GetDoorRequirements(*subway_door).empty()) || | 466 | if ((subway_door && !GetDoorRequirements(*subway_door).empty()) || |
515 | networks_.IsItemInNetwork(*hovered_item_)) { | 467 | networks_.IsItemInNetwork(*hovered_item_)) { |
516 | if (actual_hover_ != hovered_item_) { | 468 | if (actual_hover_ != hovered_item_) { |
517 | hovered_item_ = actual_hover_; | 469 | EvaluateHover(); |
518 | 470 | ||
519 | if (!hovered_item_) { | 471 | if (!hovered_item_) { |
520 | sticky_hover_ = false; | 472 | sticky_hover_ = false; |
521 | } | 473 | } |
522 | |||
523 | Refresh(); | ||
524 | } else { | 474 | } else { |
525 | sticky_hover_ = !sticky_hover_; | 475 | sticky_hover_ = !sticky_hover_; |
526 | } | 476 | } |
@@ -571,11 +521,12 @@ void SubwayMap::OnClickHelp(wxCommandEvent &event) { | |||
571 | "your mouse. Click again to stop.\nHover over a door to see the " | 521 | "your mouse. Click again to stop.\nHover over a door to see the " |
572 | "requirements to open it.\nHover over a warp or active painting to see " | 522 | "requirements to open it.\nHover over a warp or active painting to see " |
573 | "what it is connected to.\nFor one-way connections, there will be a " | 523 | "what it is connected to.\nFor one-way connections, there will be a " |
574 | "circle at the exit.\nIn painting shuffle, paintings that have not " | 524 | "circle at the exit.\nCircles represent paintings.\nA red circle means " |
575 | "yet been checked will not show their connections.\nA green shaded owl " | 525 | "that the painting is locked by a door.\nA blue circle means painting " |
576 | "means that there is a painting entrance there.\nA red shaded owl means " | 526 | "shuffle is enabled and the painting has not been checked yet.\nA black " |
577 | "that there are only painting exits there.\nClick on a door or " | 527 | "circle means the painting is not a warp.\nA green circle means that the " |
578 | "warp to make the popup stick until you click again.", | 528 | "painting is a warp.\nPainting exits will be indicated with an X.\nClick " |
529 | "on a door or warp to make the popup stick until you click again.", | ||
579 | "Subway Map Help"); | 530 | "Subway Map Help"); |
580 | } | 531 | } |
581 | 532 | ||
@@ -592,20 +543,32 @@ void SubwayMap::Redraw() { | |||
592 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { | 543 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { |
593 | ItemDrawType draw_type = ItemDrawType::kNone; | 544 | ItemDrawType draw_type = ItemDrawType::kNone; |
594 | const wxBrush *brush_color = wxGREY_BRUSH; | 545 | const wxBrush *brush_color = wxGREY_BRUSH; |
595 | std::optional<wxColour> shade_color; | ||
596 | std::optional<int> subway_door = GetRealSubwayDoor(subway_item); | 546 | std::optional<int> subway_door = GetRealSubwayDoor(subway_item); |
597 | 547 | ||
598 | if (AP_HasEarlyColorHallways() && | 548 | if (AP_HasEarlyColorHallways() && |
599 | subway_item.special == "starting_room_paintings") { | 549 | subway_item.special == "early_color_hallways") { |
600 | draw_type = ItemDrawType::kOwl; | 550 | draw_type = ItemDrawType::kOwl; |
601 | shade_color = wxColour(0, 255, 0, 128); | 551 | brush_color = wxGREEN_BRUSH; |
552 | } else if (subway_item.special == "starting_room_overhead") { | ||
553 | // Do not draw. | ||
554 | } else if (AP_IsColorShuffle() && subway_item.special && | ||
555 | subway_item.special->starts_with("color_")) { | ||
556 | std::string color_name = subway_item.special->substr(6); | ||
557 | LingoColor lingo_color = GetLingoColorForString(color_name); | ||
558 | int color_item_id = GD_GetItemIdForColor(lingo_color); | ||
559 | |||
560 | draw_type = ItemDrawType::kBox; | ||
561 | if (AP_HasItemSafe(color_item_id)) { | ||
562 | brush_color = wxGREEN_BRUSH; | ||
563 | } else { | ||
564 | brush_color = wxRED_BRUSH; | ||
565 | } | ||
602 | } else if (subway_item.special == "sun_painting") { | 566 | } else if (subway_item.special == "sun_painting") { |
603 | if (!AP_IsPilgrimageEnabled()) { | 567 | if (!AP_IsPilgrimageEnabled()) { |
568 | draw_type = ItemDrawType::kOwl; | ||
604 | if (IsDoorOpen(*subway_item.door)) { | 569 | if (IsDoorOpen(*subway_item.door)) { |
605 | draw_type = ItemDrawType::kOwl; | 570 | brush_color = wxGREEN_BRUSH; |
606 | shade_color = wxColour(0, 255, 0, 128); | ||
607 | } else { | 571 | } else { |
608 | draw_type = ItemDrawType::kBox; | ||
609 | brush_color = wxRED_BRUSH; | 572 | brush_color = wxRED_BRUSH; |
610 | } | 573 | } |
611 | } | 574 | } |
@@ -619,41 +582,28 @@ void SubwayMap::Redraw() { | |||
619 | } else { | 582 | } else { |
620 | brush_color = wxRED_BRUSH; | 583 | brush_color = wxRED_BRUSH; |
621 | } | 584 | } |
622 | } else if (!subway_item.paintings.empty()) { | 585 | } else if (subway_item.painting) { |
623 | if (AP_IsPaintingShuffle()) { | 586 | if (subway_door && !IsDoorOpen(*subway_door)) { |
624 | bool has_checked_painting = false; | 587 | draw_type = ItemDrawType::kOwl; |
625 | bool has_unchecked_painting = false; | 588 | brush_color = wxRED_BRUSH; |
626 | bool has_mapped_painting = false; | 589 | } else if (AP_IsPaintingShuffle()) { |
627 | bool has_codomain_painting = false; | 590 | if (!checked_paintings_.count(*subway_item.painting)) { |
628 | |||
629 | for (const std::string &painting_id : subway_item.paintings) { | ||
630 | if (checked_paintings_.count(painting_id)) { | ||
631 | has_checked_painting = true; | ||
632 | |||
633 | if (painting_mapping.count(painting_id)) { | ||
634 | has_mapped_painting = true; | ||
635 | } else if (AP_IsPaintingMappedTo(painting_id)) { | ||
636 | has_codomain_painting = true; | ||
637 | } | ||
638 | } else { | ||
639 | has_unchecked_painting = true; | ||
640 | } | ||
641 | } | ||
642 | |||
643 | if (has_unchecked_painting || has_mapped_painting || | ||
644 | has_codomain_painting) { | ||
645 | draw_type = ItemDrawType::kOwl; | 591 | draw_type = ItemDrawType::kOwl; |
646 | 592 | brush_color = wxBLUE_BRUSH; | |
647 | if (has_checked_painting) { | 593 | } else if (painting_mapping.count(*subway_item.painting)) { |
648 | if (has_mapped_painting) { | 594 | draw_type = ItemDrawType::kOwl; |
649 | shade_color = wxColour(0, 255, 0, 128); | 595 | brush_color = wxGREEN_BRUSH; |
650 | } else { | 596 | } else if (AP_IsPaintingMappedTo(*subway_item.painting)) { |
651 | shade_color = wxColour(255, 0, 0, 128); | 597 | draw_type = ItemDrawType::kOwlExit; |
652 | } | 598 | brush_color = wxGREEN_BRUSH; |
653 | } | ||
654 | } | 599 | } |
655 | } else if (subway_item.HasWarps()) { | 600 | } else if (subway_item.HasWarps()) { |
656 | draw_type = ItemDrawType::kOwl; | 601 | brush_color = wxGREEN_BRUSH; |
602 | if (!subway_item.exits.empty()) { | ||
603 | draw_type = ItemDrawType::kOwlExit; | ||
604 | } else { | ||
605 | draw_type = ItemDrawType::kOwl; | ||
606 | } | ||
657 | } | 607 | } |
658 | } else if (subway_door) { | 608 | } else if (subway_door) { |
659 | draw_type = ItemDrawType::kBox; | 609 | draw_type = ItemDrawType::kBox; |
@@ -673,21 +623,40 @@ void SubwayMap::Redraw() { | |||
673 | if (draw_type == ItemDrawType::kBox) { | 623 | if (draw_type == ItemDrawType::kBox) { |
674 | gcdc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); | 624 | gcdc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); |
675 | gcdc.SetBrush(*brush_color); | 625 | gcdc.SetBrush(*brush_color); |
676 | gcdc.DrawRectangle(real_area_pos, {real_area_size, real_area_size}); | 626 | |
677 | } else if (draw_type == ItemDrawType::kOwl) { | 627 | if (subway_item.tilted) { |
678 | wxBitmap owl_bitmap = wxBitmap(owl_image_.Scale( | 628 | constexpr int AREA_TILTED_SIDE = |
679 | real_area_size, real_area_size, wxIMAGE_QUALITY_BILINEAR)); | 629 | static_cast<int>(AREA_ACTUAL_SIZE / 1.41421356237); |
680 | gcdc.DrawBitmap(owl_bitmap, real_area_pos); | 630 | const wxPoint poly_points[] = {{AREA_TILTED_SIDE, 0}, |
681 | 631 | {2 * AREA_TILTED_SIDE, AREA_TILTED_SIDE}, | |
682 | if (shade_color) { | 632 | {AREA_TILTED_SIDE, 2 * AREA_TILTED_SIDE}, |
683 | gcdc.SetBrush(wxBrush(*shade_color)); | 633 | {0, AREA_TILTED_SIDE}}; |
634 | gcdc.DrawPolygon(4, poly_points, subway_item.x, subway_item.y); | ||
635 | } else { | ||
684 | gcdc.DrawRectangle(real_area_pos, {real_area_size, real_area_size}); | 636 | gcdc.DrawRectangle(real_area_pos, {real_area_size, real_area_size}); |
685 | } | 637 | } |
638 | } else if (draw_type == ItemDrawType::kOwl || draw_type == ItemDrawType::kOwlExit) { | ||
639 | gcdc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); | ||
640 | gcdc.SetBrush(*brush_color); | ||
641 | gcdc.DrawCircle(real_area_pos, PAINTING_RADIUS); | ||
642 | |||
643 | if (draw_type == ItemDrawType::kOwlExit) { | ||
644 | gcdc.DrawLine(subway_item.x - PAINTING_EXIT_RADIUS, | ||
645 | subway_item.y - PAINTING_EXIT_RADIUS, | ||
646 | subway_item.x + PAINTING_EXIT_RADIUS, | ||
647 | subway_item.y + PAINTING_EXIT_RADIUS); | ||
648 | gcdc.DrawLine(subway_item.x + PAINTING_EXIT_RADIUS, | ||
649 | subway_item.y - PAINTING_EXIT_RADIUS, | ||
650 | subway_item.x - PAINTING_EXIT_RADIUS, | ||
651 | subway_item.y + PAINTING_EXIT_RADIUS); | ||
652 | } | ||
686 | } | 653 | } |
687 | } | 654 | } |
688 | } | 655 | } |
689 | 656 | ||
690 | void SubwayMap::SetUpHelpButton() { | 657 | void SubwayMap::SetUpHelpButton() { |
658 | help_button_->SetSize(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, | ||
659 | wxDefaultCoord, wxSIZE_AUTO); | ||
691 | help_button_->SetPosition({ | 660 | help_button_->SetPosition({ |
692 | GetSize().GetWidth() - help_button_->GetSize().GetWidth() - 15, | 661 | GetSize().GetWidth() - help_button_->GetSize().GetWidth() - 15, |
693 | 15, | 662 | 15, |
@@ -723,6 +692,51 @@ void SubwayMap::EvaluateScroll(wxPoint pos) { | |||
723 | SetScrollSpeed(scroll_x, scroll_y); | 692 | SetScrollSpeed(scroll_x, scroll_y); |
724 | } | 693 | } |
725 | 694 | ||
695 | void SubwayMap::EvaluateHover() { | ||
696 | hovered_item_ = actual_hover_; | ||
697 | |||
698 | if (hovered_item_) { | ||
699 | // Note that these requirements are duplicated on OnMouseClick so that it | ||
700 | // knows when an item has a hover effect. | ||
701 | const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); | ||
702 | std::optional<int> subway_door = GetRealSubwayDoor(subway_item); | ||
703 | |||
704 | if (subway_door && !GetDoorRequirements(*subway_door).empty()) { | ||
705 | report_popup_->SetDoorId(*subway_door); | ||
706 | |||
707 | wxPoint popupPos = | ||
708 | MapPosToRenderPos({subway_item.x + AREA_ACTUAL_SIZE / 2, | ||
709 | subway_item.y + AREA_ACTUAL_SIZE / 2}); | ||
710 | |||
711 | report_popup_->SetClientSize( | ||
712 | report_popup_->GetVirtualSize().GetWidth(), | ||
713 | std::min(GetSize().GetHeight(), | ||
714 | report_popup_->GetVirtualSize().GetHeight())); | ||
715 | |||
716 | if (popupPos.x + report_popup_->GetSize().GetWidth() > | ||
717 | GetSize().GetWidth()) { | ||
718 | popupPos.x = GetSize().GetWidth() - report_popup_->GetSize().GetWidth(); | ||
719 | } | ||
720 | if (popupPos.y + report_popup_->GetSize().GetHeight() > | ||
721 | GetSize().GetHeight()) { | ||
722 | popupPos.y = | ||
723 | GetSize().GetHeight() - report_popup_->GetSize().GetHeight(); | ||
724 | } | ||
725 | report_popup_->SetPosition(popupPos); | ||
726 | |||
727 | report_popup_->Show(); | ||
728 | } else { | ||
729 | report_popup_->Reset(); | ||
730 | report_popup_->Hide(); | ||
731 | } | ||
732 | } else { | ||
733 | report_popup_->Reset(); | ||
734 | report_popup_->Hide(); | ||
735 | } | ||
736 | |||
737 | Refresh(); | ||
738 | } | ||
739 | |||
726 | wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { | 740 | wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { |
727 | return {static_cast<int>(pos.x * render_width_ * zoom_ / | 741 | return {static_cast<int>(pos.x * render_width_ * zoom_ / |
728 | map_image_.GetSize().GetWidth() + | 742 | map_image_.GetSize().GetWidth() + |
@@ -812,6 +826,13 @@ std::optional<int> SubwayMap::GetRealSubwayDoor(const SubwayItem subway_item) { | |||
812 | 826 | ||
813 | quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int &id) const { | 827 | quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int &id) const { |
814 | const SubwayItem &subway_item = GD_GetSubwayItem(id); | 828 | const SubwayItem &subway_item = GD_GetSubwayItem(id); |
815 | return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y), | 829 | if (subway_item.painting) { |
816 | AREA_ACTUAL_SIZE, AREA_ACTUAL_SIZE}; | 830 | return {static_cast<float>(subway_item.x) - PAINTING_RADIUS, |
831 | static_cast<float>(subway_item.y) - PAINTING_RADIUS, | ||
832 | PAINTING_RADIUS * 2, PAINTING_RADIUS * 2}; | ||
833 | } else { | ||
834 | return {static_cast<float>(subway_item.x), | ||
835 | static_cast<float>(subway_item.y), AREA_ACTUAL_SIZE, | ||
836 | AREA_ACTUAL_SIZE}; | ||
837 | } | ||
817 | } | 838 | } |