about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2023-05-03 12:43:16 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2023-05-03 12:43:16 -0400
commit02c331f4e766558bba580d5b7db883357be005d5 (patch)
tree16e8fd4a48c1951e0dd7785295fcbe62b9669880
parent47e59ea969c775bea316b1a910c845a7c8482091 (diff)
downloadlingo-ap-tracker-02c331f4e766558bba580d5b7db883357be005d5.tar.gz
lingo-ap-tracker-02c331f4e766558bba580d5b7db883357be005d5.tar.bz2
lingo-ap-tracker-02c331f4e766558bba580d5b7db883357be005d5.zip
Changes to make it work better on Windows
AreaWindows are now no longer separate controls but are instead just painted onto the TrackerPanel. This lets us avoid the complexity of z-ordering with sibling controls. We can also use the mouse motion event to display and hide the popups, which conveniently doesn't fire when the mouse is over a popup, so the popup won't hide until you mouse off of the window AND popup.
-rw-r--r--CMakeLists.txt1
-rw-r--r--area_window.cpp68
-rw-r--r--area_window.h38
-rw-r--r--eye_indicator.cpp2
-rw-r--r--tracker_frame.cpp2
-rw-r--r--tracker_panel.cpp117
-rw-r--r--tracker_panel.h15
7 files changed, 100 insertions, 143 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index fea5d7d..5d616e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -34,7 +34,6 @@ add_executable(lingo_ap_tracker
34 tracker_frame.cpp 34 tracker_frame.cpp
35 tracker_panel.cpp 35 tracker_panel.cpp
36 game_data.cpp 36 game_data.cpp
37 area_window.cpp
38 area_popup.cpp 37 area_popup.cpp
39 ap_state.cpp 38 ap_state.cpp
40 connection_dialog.cpp 39 connection_dialog.cpp
diff --git a/area_window.cpp b/area_window.cpp deleted file mode 100644 index fded223..0000000 --- a/area_window.cpp +++ /dev/null
@@ -1,68 +0,0 @@
1#include "area_window.h"
2
3#include <iostream>
4
5#include "ap_state.h"
6#include "game_data.h"
7#include "tracker_state.h"
8
9AreaWindow::AreaWindow(wxWindow* parent, int area_id, AreaPopup* popup)
10 : wxWindow(parent, wxID_ANY), area_id_(area_id), popup_(popup) {
11 SetSize(EFFECTIVE_SIZE, EFFECTIVE_SIZE);
12
13 Redraw();
14
15 Bind(wxEVT_PAINT, &AreaWindow::OnPaint, this);
16 Bind(wxEVT_ENTER_WINDOW, &AreaWindow::OnEnterWindow, this);
17 Bind(wxEVT_LEAVE_WINDOW, &AreaWindow::OnLeaveWindow, this);
18}
19
20void AreaWindow::UpdateIndicators() { Redraw(); }
21
22void AreaWindow::OnPaint(wxPaintEvent& event) {
23 if (GetSize() != rendered_.GetSize()) {
24 Redraw();
25 }
26
27 wxPaintDC dc(this);
28 dc.DrawBitmap(rendered_, 0, 0);
29}
30
31void AreaWindow::OnEnterWindow(wxMouseEvent& event) { popup_->Show(); }
32
33void AreaWindow::OnLeaveWindow(wxMouseEvent& event) { popup_->Hide(); }
34
35void AreaWindow::Redraw() {
36 const wxBrush* brush_color = wxGREY_BRUSH;
37
38 const MapArea& map_area = GetGameData().GetMapArea(area_id_);
39 bool has_reachable_unchecked = false;
40 bool has_unreachable_unchecked = false;
41 for (int section_id = 0; section_id < map_area.locations.size();
42 section_id++) {
43 if (!GetAPState().HasCheckedGameLocation(area_id_, section_id)) {
44 if (GetTrackerState().IsLocationReachable(area_id_, section_id)) {
45 has_reachable_unchecked = true;
46 } else {
47 has_unreachable_unchecked = true;
48 }
49 }
50 }
51
52 if (has_reachable_unchecked && has_unreachable_unchecked) {
53 brush_color = wxYELLOW_BRUSH;
54 } else if (has_reachable_unchecked) {
55 brush_color = wxGREEN_BRUSH;
56 } else if (has_unreachable_unchecked) {
57 brush_color = wxRED_BRUSH;
58 }
59
60 int actual_border_size = GetSize().GetWidth() * BORDER_SIZE / EFFECTIVE_SIZE;
61
62 rendered_ = wxBitmap(GetSize());
63 wxMemoryDC dc;
64 dc.SelectObject(rendered_);
65 dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size));
66 dc.SetBrush(*brush_color);
67 dc.DrawRectangle({0, 0}, GetSize());
68}
diff --git a/area_window.h b/area_window.h deleted file mode 100644 index 3e7c001..0000000 --- a/area_window.h +++ /dev/null
@@ -1,38 +0,0 @@
1#ifndef AREA_WINDOW_H_C2653ACF
2#define AREA_WINDOW_H_C2653ACF
3
4#include <wx/wxprec.h>
5
6#ifndef WX_PRECOMP
7#include <wx/wx.h>
8#endif
9
10#include "area_popup.h"
11
12class AreaWindow : public wxWindow {
13 public:
14 static constexpr int ACTUAL_SIZE = 64;
15 static constexpr int BORDER_SIZE = 5;
16 static constexpr int EFFECTIVE_SIZE = ACTUAL_SIZE + BORDER_SIZE * 2;
17
18 AreaWindow(wxWindow* parent, int area_id, AreaPopup* popup);
19
20 int GetAreaId() const { return area_id_; }
21
22 AreaPopup* GetPopup() { return popup_; }
23
24 void UpdateIndicators();
25
26 private:
27 void OnPaint(wxPaintEvent& event);
28 void OnEnterWindow(wxMouseEvent& event);
29 void OnLeaveWindow(wxMouseEvent& event);
30
31 void Redraw();
32
33 int area_id_;
34 wxBitmap rendered_;
35 AreaPopup* popup_;
36};
37
38#endif /* end of include guard: AREA_WINDOW_H_C2653ACF */
diff --git a/eye_indicator.cpp b/eye_indicator.cpp index c490589..03e234e 100644 --- a/eye_indicator.cpp +++ b/eye_indicator.cpp
@@ -36,6 +36,8 @@ void EyeIndicator::OnPaint(wxPaintEvent& event) {
36 36
37 wxPaintDC dc(this); 37 wxPaintDC dc(this);
38 dc.DrawBitmap(rendered_, 0, 0); 38 dc.DrawBitmap(rendered_, 0, 0);
39
40 event.Skip();
39} 41}
40 42
41void EyeIndicator::Redraw() { 43void EyeIndicator::Redraw() {
diff --git a/tracker_frame.cpp b/tracker_frame.cpp index 237433a..37a8281 100644 --- a/tracker_frame.cpp +++ b/tracker_frame.cpp
@@ -10,7 +10,7 @@ wxDEFINE_EVENT(STATE_CHANGED, wxCommandEvent);
10wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent); 10wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent);
11 11
12TrackerFrame::TrackerFrame() 12TrackerFrame::TrackerFrame()
13 : wxFrame(nullptr, wxID_ANY, "Lingo Archipelago Tracker") { 13 : wxFrame(nullptr, wxID_ANY, "Lingo Archipelago Tracker", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) {
14 ::wxInitAllImageHandlers(); 14 ::wxInitAllImageHandlers();
15 15
16 GetAPState().SetTrackerFrame(this); 16 GetAPState().SetTrackerFrame(this);
diff --git a/tracker_panel.cpp b/tracker_panel.cpp index 1aa7dcf..73cac41 100644 --- a/tracker_panel.cpp +++ b/tracker_panel.cpp
@@ -1,7 +1,13 @@
1#include "tracker_panel.h" 1#include "tracker_panel.h"
2 2
3#include "ap_state.h"
3#include "area_popup.h" 4#include "area_popup.h"
4#include "game_data.h" 5#include "game_data.h"
6#include "tracker_state.h"
7
8constexpr int AREA_ACTUAL_SIZE = 64;
9constexpr int AREA_BORDER_SIZE = 5;
10constexpr int AREA_EFFECTIVE_SIZE = AREA_ACTUAL_SIZE + AREA_BORDER_SIZE * 2;
5 11
6TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { 12TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
7 map_image_ = wxImage("assets/lingo_map.png", wxBITMAP_TYPE_PNG); 13 map_image_ = wxImage("assets/lingo_map.png", wxBITMAP_TYPE_PNG);
@@ -10,30 +16,26 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
10 } 16 }
11 17
12 for (const MapArea &map_area : GetGameData().GetMapAreas()) { 18 for (const MapArea &map_area : GetGameData().GetMapAreas()) {
13 AreaPopup *area_popup = new AreaPopup(this, map_area.id); 19 AreaIndicator area;
14 area_popup->SetPosition({0, 0}); 20 area.area_id = map_area.id;
15 area_popup->Raise(); 21
16 area_popups_.push_back(area_popup); 22 area.popup = new AreaPopup(this, map_area.id);
17 23 area.popup->SetPosition({0, 0});
18 AreaWindow *area_window = new AreaWindow(this, map_area.id, area_popup); 24
19 area_window->Lower(); 25 areas_.push_back(area);
20 area_windows_.push_back(area_window);
21 } 26 }
22 27
23 Redraw(); 28 Redraw();
24 29
25 Bind(wxEVT_PAINT, &TrackerPanel::OnPaint, this); 30 Bind(wxEVT_PAINT, &TrackerPanel::OnPaint, this);
31 Bind(wxEVT_MOTION, &TrackerPanel::OnMouseMove, this);
26} 32}
27 33
28void TrackerPanel::UpdateIndicators() { 34void TrackerPanel::UpdateIndicators() {
29 Redraw(); 35 Redraw();
30 36
31 for (AreaWindow *area_window : area_windows_) { 37 for (AreaIndicator& area : areas_) {
32 area_window->UpdateIndicators(); 38 area.popup->UpdateIndicators();
33 }
34
35 for (AreaPopup *area_popup : area_popups_) {
36 area_popup->UpdateIndicators();
37 } 39 }
38} 40}
39 41
@@ -44,6 +46,21 @@ void TrackerPanel::OnPaint(wxPaintEvent &event) {
44 46
45 wxPaintDC dc(this); 47 wxPaintDC dc(this);
46 dc.DrawBitmap(rendered_, 0, 0); 48 dc.DrawBitmap(rendered_, 0, 0);
49
50 event.Skip();
51}
52
53void TrackerPanel::OnMouseMove(wxMouseEvent &event) {
54 for (AreaIndicator &area : areas_) {
55 if (area.real_x1 <= event.GetX() && event.GetX() < area.real_x2 &&
56 area.real_y1 <= event.GetY() && event.GetY() < area.real_y2) {
57 area.popup->Show();
58 } else {
59 area.popup->Hide();
60 }
61 }
62
63 event.Skip();
47} 64}
48 65
49void TrackerPanel::Redraw() { 66void TrackerPanel::Redraw() {
@@ -70,30 +87,66 @@ void TrackerPanel::Redraw() {
70 map_image_.Scale(final_width, final_height, wxIMAGE_QUALITY_NORMAL) 87 map_image_.Scale(final_width, final_height, wxIMAGE_QUALITY_NORMAL)
71 .Size(panel_size, {final_x, final_y}, 0, 0, 0)); 88 .Size(panel_size, {final_x, final_y}, 0, 0, 0));
72 89
73 for (AreaWindow *area_window : area_windows_) { 90 wxMemoryDC dc;
74 const MapArea &map_area = 91 dc.SelectObject(rendered_);
75 GetGameData().GetMapArea(area_window->GetAreaId()); 92
93 for (AreaIndicator& area : areas_) {
94 const wxBrush *brush_color = wxGREY_BRUSH;
95
96 const MapArea &map_area = GetGameData().GetMapArea(area.area_id);
97 bool has_reachable_unchecked = false;
98 bool has_unreachable_unchecked = false;
99 for (int section_id = 0; section_id < map_area.locations.size();
100 section_id++) {
101 if (!GetAPState().HasCheckedGameLocation(area.area_id,
102 section_id)) {
103 if (GetTrackerState().IsLocationReachable(area.area_id,
104 section_id)) {
105 has_reachable_unchecked = true;
106 } else {
107 has_unreachable_unchecked = true;
108 }
109 }
110 }
111
112 if (has_reachable_unchecked && has_unreachable_unchecked) {
113 brush_color = wxYELLOW_BRUSH;
114 } else if (has_reachable_unchecked) {
115 brush_color = wxGREEN_BRUSH;
116 } else if (has_unreachable_unchecked) {
117 brush_color = wxRED_BRUSH;
118 }
119
76 int real_area_size = 120 int real_area_size =
77 final_width * AreaWindow::EFFECTIVE_SIZE / image_size.GetWidth(); 121 final_width * AREA_EFFECTIVE_SIZE / image_size.GetWidth();
78 area_window->SetSize({real_area_size, real_area_size}); 122 int actual_border_size =
79 area_window->SetPosition({ 123 real_area_size * AREA_BORDER_SIZE / AREA_EFFECTIVE_SIZE;
80 final_x + (map_area.map_x - (AreaWindow::EFFECTIVE_SIZE / 2)) * 124 int real_area_x =
81 final_width / image_size.GetWidth(), 125 final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) *
82 final_y + (map_area.map_y - (AreaWindow::EFFECTIVE_SIZE / 2)) * 126 final_width / image_size.GetWidth();
83 final_width / image_size.GetWidth(), 127 int real_area_y =
84 }); 128 final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) *
85 129 final_width / image_size.GetWidth();
86 AreaPopup *area_popup = area_window->GetPopup(); 130
131 dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size));
132 dc.SetBrush(*brush_color);
133 dc.DrawRectangle({real_area_x, real_area_y}, {real_area_size, real_area_size});
134
135 area.real_x1 = real_area_x;
136 area.real_x2 = real_area_x + real_area_size;
137 area.real_y1 = real_area_y;
138 area.real_y2 = real_area_y + real_area_size;
139
87 int popup_x = 140 int popup_x =
88 final_x + map_area.map_x * final_width / image_size.GetWidth(); 141 final_x + map_area.map_x * final_width / image_size.GetWidth();
89 int popup_y = 142 int popup_y =
90 final_y + map_area.map_y * final_width / image_size.GetWidth(); 143 final_y + map_area.map_y * final_width / image_size.GetWidth();
91 if (popup_x + area_popup->GetSize().GetWidth() > panel_size.GetWidth()) { 144 if (popup_x + area.popup->GetSize().GetWidth() > panel_size.GetWidth()) {
92 popup_x = panel_size.GetWidth() - area_popup->GetSize().GetWidth(); 145 popup_x = panel_size.GetWidth() - area.popup->GetSize().GetWidth();
93 } 146 }
94 if (popup_y + area_popup->GetSize().GetHeight() > panel_size.GetHeight()) { 147 if (popup_y + area.popup->GetSize().GetHeight() > panel_size.GetHeight()) {
95 popup_y = panel_size.GetHeight() - area_popup->GetSize().GetHeight(); 148 popup_y = panel_size.GetHeight() - area.popup->GetSize().GetHeight();
96 } 149 }
97 area_popup->SetPosition({popup_x, popup_y}); 150 area.popup->SetPosition({popup_x, popup_y});
98 } 151 }
99} 152}
diff --git a/tracker_panel.h b/tracker_panel.h index 20d4f92..a871f90 100644 --- a/tracker_panel.h +++ b/tracker_panel.h
@@ -7,7 +7,7 @@
7#include <wx/wx.h> 7#include <wx/wx.h>
8#endif 8#endif
9 9
10#include "area_window.h" 10class AreaPopup;
11 11
12class TrackerPanel : public wxPanel { 12class TrackerPanel : public wxPanel {
13 public: 13 public:
@@ -16,15 +16,24 @@ class TrackerPanel : public wxPanel {
16 void UpdateIndicators(); 16 void UpdateIndicators();
17 17
18 private: 18 private:
19 struct AreaIndicator {
20 int area_id = -1;
21 AreaPopup *popup = nullptr;
22 int real_x1 = 0;
23 int real_y1 = 0;
24 int real_x2 = 0;
25 int real_y2 = 0;
26 };
27
19 void OnPaint(wxPaintEvent &event); 28 void OnPaint(wxPaintEvent &event);
29 void OnMouseMove(wxMouseEvent &event);
20 30
21 void Redraw(); 31 void Redraw();
22 32
23 wxImage map_image_; 33 wxImage map_image_;
24 wxBitmap rendered_; 34 wxBitmap rendered_;
25 35
26 std::vector<AreaWindow *> area_windows_; 36 std::vector<AreaIndicator> areas_;
27 std::vector<AreaPopup *> area_popups_;
28}; 37};
29 38
30#endif /* end of include guard: TRACKER_PANEL_H_D675A54D */ 39#endif /* end of include guard: TRACKER_PANEL_H_D675A54D */