From 8ad881fed6e388f7a254350532ce58552ef47a1d Mon Sep 17 00:00:00 2001
From: Star Rauchenberger <fefferburbia@gmail.com>
Date: Tue, 11 Mar 2025 17:19:54 -0400
Subject: New subway map paintings

---
 src/subway_map.cpp | 134 +++++++++++++++++++++++++++++------------------------
 1 file changed, 74 insertions(+), 60 deletions(-)

(limited to 'src/subway_map.cpp')

diff --git a/src/subway_map.cpp b/src/subway_map.cpp
index 9a35eef..f00f03f 100644
--- a/src/subway_map.cpp
+++ b/src/subway_map.cpp
@@ -14,8 +14,23 @@
 
 constexpr int AREA_ACTUAL_SIZE = 21;
 constexpr int OWL_ACTUAL_SIZE = 32;
+constexpr int PAINTING_RADIUS = 9; // the actual circles on the map are radius 11
+constexpr int PAINTING_EXIT_RADIUS = 6;
 
-enum class ItemDrawType { kNone, kBox, kOwl };
+enum class ItemDrawType { kNone, kBox, kOwl, kOwlExit };
+
+namespace {
+
+wxPoint GetSubwayItemMapCenter(const SubwayItem &subway_item) {
+  if (subway_item.painting) {
+    return {subway_item.x, subway_item.y};
+  } else {
+    return {subway_item.x + AREA_ACTUAL_SIZE / 2,
+            subway_item.y + AREA_ACTUAL_SIZE / 2};
+  }
+}
+
+}  // namespace
 
 SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
   SetBackgroundStyle(wxBG_STYLE_PAINT);
@@ -68,11 +83,11 @@ void SubwayMap::OnConnect() {
   std::map<std::string, std::vector<int>> exits;
   for (const SubwayItem &subway_item : GD_GetSubwayItems()) {
     if (AP_HasEarlyColorHallways() &&
-        subway_item.special == "starting_room_paintings") {
+        subway_item.special == "early_color_hallways") {
       entrances["early_ch"].push_back(subway_item.id);
     }
 
-    if (AP_IsPaintingShuffle() && !subway_item.paintings.empty()) {
+    if (AP_IsPaintingShuffle() && subway_item.painting) {
       continue;
     }
 
@@ -319,10 +334,8 @@ void SubwayMap::OnPaint(wxPaintEvent &event) {
         const SubwayItem &item1 = GD_GetSubwayItem(node.entry);
         const SubwayItem &item2 = GD_GetSubwayItem(node.exit);
 
-        wxPoint item1_pos = MapPosToRenderPos(
-            {item1.x + AREA_ACTUAL_SIZE / 2, item1.y + AREA_ACTUAL_SIZE / 2});
-        wxPoint item2_pos = MapPosToRenderPos(
-            {item2.x + AREA_ACTUAL_SIZE / 2, item2.y + AREA_ACTUAL_SIZE / 2});
+        wxPoint item1_pos = MapPosToRenderPos(GetSubwayItemMapCenter(item1));
+        wxPoint item2_pos = MapPosToRenderPos(GetSubwayItemMapCenter(item2));
 
         int left = std::min(item1_pos.x, item2_pos.x);
         int top = std::min(item1_pos.y, item2_pos.y);
@@ -508,11 +521,12 @@ void SubwayMap::OnClickHelp(wxCommandEvent &event) {
       "your mouse. Click again to stop.\nHover over a door to see the "
       "requirements to open it.\nHover over a warp or active painting to see "
       "what it is connected to.\nFor one-way connections, there will be a "
-      "circle at the exit.\nIn painting shuffle, paintings that have not "
-      "yet been checked will not show their connections.\nA green shaded owl "
-      "means that there is a painting entrance there.\nA red shaded owl means "
-      "that there are only painting exits there.\nClick on a door or "
-      "warp to make the popup stick until you click again.",
+      "circle at the exit.\nCircles represent paintings.\nA red circle means "
+      "that the painting is locked by a door.\nA blue circle means painting "
+      "shuffle is enabled and the painting has not been checked yet.\nA black "
+      "circle means the painting is not a warp.\nA green circle means that the "
+      "painting is a warp.\nPainting exits will be indicated with an X.\nClick "
+      "on a door or warp to make the popup stick until you click again.",
       "Subway Map Help");
 }
 
@@ -529,20 +543,20 @@ void SubwayMap::Redraw() {
   for (const SubwayItem &subway_item : GD_GetSubwayItems()) {
     ItemDrawType draw_type = ItemDrawType::kNone;
     const wxBrush *brush_color = wxGREY_BRUSH;
-    std::optional<wxColour> shade_color;
     std::optional<int> subway_door = GetRealSubwayDoor(subway_item);
 
     if (AP_HasEarlyColorHallways() &&
-        subway_item.special == "starting_room_paintings") {
+        subway_item.special == "early_color_hallways") {
       draw_type = ItemDrawType::kOwl;
-      shade_color = wxColour(0, 255, 0, 128);
+      brush_color = wxGREEN_BRUSH;
+    } else if (subway_item.special == "starting_room_overhead") {
+      // Do not draw.
     } else if (subway_item.special == "sun_painting") {
       if (!AP_IsPilgrimageEnabled()) {
+        draw_type = ItemDrawType::kOwl;
         if (IsDoorOpen(*subway_item.door)) {
-          draw_type = ItemDrawType::kOwl;
-          shade_color = wxColour(0, 255, 0, 128);
+          brush_color = wxGREEN_BRUSH;
         } else {
-          draw_type = ItemDrawType::kBox;
           brush_color = wxRED_BRUSH;
         }
       }
@@ -556,41 +570,28 @@ void SubwayMap::Redraw() {
       } else {
         brush_color = wxRED_BRUSH;
       }
-    } else if (!subway_item.paintings.empty()) {
-      if (AP_IsPaintingShuffle()) {
-        bool has_checked_painting = false;
-        bool has_unchecked_painting = false;
-        bool has_mapped_painting = false;
-        bool has_codomain_painting = false;
-
-        for (const std::string &painting_id : subway_item.paintings) {
-          if (checked_paintings_.count(painting_id)) {
-            has_checked_painting = true;
-
-            if (painting_mapping.count(painting_id)) {
-              has_mapped_painting = true;
-            } else if (AP_IsPaintingMappedTo(painting_id)) {
-              has_codomain_painting = true;
-            }
-          } else {
-            has_unchecked_painting = true;
-          }
-        }
-
-        if (has_unchecked_painting || has_mapped_painting ||
-            has_codomain_painting) {
+    } else if (subway_item.painting) {
+      if (subway_door && !IsDoorOpen(*subway_door)) {
+        draw_type = ItemDrawType::kOwl;
+        brush_color = wxRED_BRUSH;
+      } else if (AP_IsPaintingShuffle()) {
+        if (!checked_paintings_.count(*subway_item.painting)) {
           draw_type = ItemDrawType::kOwl;
-
-          if (has_checked_painting) {
-            if (has_mapped_painting) {
-              shade_color = wxColour(0, 255, 0, 128);
-            } else {
-              shade_color = wxColour(255, 0, 0, 128);
-            }
-          }
+          brush_color = wxBLUE_BRUSH;
+        } else if (painting_mapping.count(*subway_item.painting)) {
+          draw_type = ItemDrawType::kOwl;
+          brush_color = wxGREEN_BRUSH;
+        } else if (AP_IsPaintingMappedTo(*subway_item.painting)) {
+          draw_type = ItemDrawType::kOwlExit;
+          brush_color = wxGREEN_BRUSH;
         }
       } else if (subway_item.HasWarps()) {
-        draw_type = ItemDrawType::kOwl;
+        brush_color = wxGREEN_BRUSH;
+        if (!subway_item.exits.empty()) {
+          draw_type = ItemDrawType::kOwlExit;
+        } else {
+          draw_type = ItemDrawType::kOwl;
+        }
       }
     } else if (subway_door) {
       draw_type = ItemDrawType::kBox;
@@ -611,14 +612,20 @@ void SubwayMap::Redraw() {
       gcdc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1));
       gcdc.SetBrush(*brush_color);
       gcdc.DrawRectangle(real_area_pos, {real_area_size, real_area_size});
-    } else if (draw_type == ItemDrawType::kOwl) {
-      wxBitmap owl_bitmap = wxBitmap(owl_image_.Scale(
-          real_area_size, real_area_size, wxIMAGE_QUALITY_BILINEAR));
-      gcdc.DrawBitmap(owl_bitmap, real_area_pos);
-
-      if (shade_color) {
-        gcdc.SetBrush(wxBrush(*shade_color));
-        gcdc.DrawRectangle(real_area_pos, {real_area_size, real_area_size});
+    } else if (draw_type == ItemDrawType::kOwl || draw_type == ItemDrawType::kOwlExit) {
+      gcdc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1));
+      gcdc.SetBrush(*brush_color);
+      gcdc.DrawCircle(real_area_pos, PAINTING_RADIUS);
+
+      if (draw_type == ItemDrawType::kOwlExit) {
+        gcdc.DrawLine(subway_item.x - PAINTING_EXIT_RADIUS,
+                      subway_item.y - PAINTING_EXIT_RADIUS,
+                      subway_item.x + PAINTING_EXIT_RADIUS,
+                      subway_item.y + PAINTING_EXIT_RADIUS);
+        gcdc.DrawLine(subway_item.x + PAINTING_EXIT_RADIUS,
+                      subway_item.y - PAINTING_EXIT_RADIUS,
+                      subway_item.x - PAINTING_EXIT_RADIUS,
+                      subway_item.y + PAINTING_EXIT_RADIUS);
       }
     }
   }
@@ -796,6 +803,13 @@ std::optional<int> SubwayMap::GetRealSubwayDoor(const SubwayItem subway_item) {
 
 quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int &id) const {
   const SubwayItem &subway_item = GD_GetSubwayItem(id);
-  return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y),
-          AREA_ACTUAL_SIZE, AREA_ACTUAL_SIZE};
+  if (subway_item.painting) {
+    return {static_cast<float>(subway_item.x) - PAINTING_RADIUS,
+            static_cast<float>(subway_item.y) - PAINTING_RADIUS,
+            PAINTING_RADIUS * 2, PAINTING_RADIUS * 2};
+  } else {
+    return {static_cast<float>(subway_item.x),
+            static_cast<float>(subway_item.y), AREA_ACTUAL_SIZE,
+            AREA_ACTUAL_SIZE};
+  }
 }
-- 
cgit 1.4.1