From 02c331f4e766558bba580d5b7db883357be005d5 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Wed, 3 May 2023 12:43:16 -0400 Subject: 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. --- CMakeLists.txt | 1 - area_window.cpp | 68 ------------------------------- area_window.h | 38 ------------------ eye_indicator.cpp | 2 + tracker_frame.cpp | 2 +- tracker_panel.cpp | 117 +++++++++++++++++++++++++++++++++++++++--------------- tracker_panel.h | 15 +++++-- 7 files changed, 100 insertions(+), 143 deletions(-) delete mode 100644 area_window.cpp delete mode 100644 area_window.h 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 tracker_frame.cpp tracker_panel.cpp game_data.cpp - area_window.cpp area_popup.cpp ap_state.cpp 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 @@ -#include "area_window.h" - -#include - -#include "ap_state.h" -#include "game_data.h" -#include "tracker_state.h" - -AreaWindow::AreaWindow(wxWindow* parent, int area_id, AreaPopup* popup) - : wxWindow(parent, wxID_ANY), area_id_(area_id), popup_(popup) { - SetSize(EFFECTIVE_SIZE, EFFECTIVE_SIZE); - - Redraw(); - - Bind(wxEVT_PAINT, &AreaWindow::OnPaint, this); - Bind(wxEVT_ENTER_WINDOW, &AreaWindow::OnEnterWindow, this); - Bind(wxEVT_LEAVE_WINDOW, &AreaWindow::OnLeaveWindow, this); -} - -void AreaWindow::UpdateIndicators() { Redraw(); } - -void AreaWindow::OnPaint(wxPaintEvent& event) { - if (GetSize() != rendered_.GetSize()) { - Redraw(); - } - - wxPaintDC dc(this); - dc.DrawBitmap(rendered_, 0, 0); -} - -void AreaWindow::OnEnterWindow(wxMouseEvent& event) { popup_->Show(); } - -void AreaWindow::OnLeaveWindow(wxMouseEvent& event) { popup_->Hide(); } - -void AreaWindow::Redraw() { - const wxBrush* brush_color = wxGREY_BRUSH; - - const MapArea& map_area = GetGameData().GetMapArea(area_id_); - bool has_reachable_unchecked = false; - bool has_unreachable_unchecked = false; - for (int section_id = 0; section_id < map_area.locations.size(); - section_id++) { - if (!GetAPState().HasCheckedGameLocation(area_id_, section_id)) { - if (GetTrackerState().IsLocationReachable(area_id_, section_id)) { - has_reachable_unchecked = true; - } else { - has_unreachable_unchecked = true; - } - } - } - - if (has_reachable_unchecked && has_unreachable_unchecked) { - brush_color = wxYELLOW_BRUSH; - } else if (has_reachable_unchecked) { - brush_color = wxGREEN_BRUSH; - } else if (has_unreachable_unchecked) { - brush_color = wxRED_BRUSH; - } - - int actual_border_size = GetSize().GetWidth() * BORDER_SIZE / EFFECTIVE_SIZE; - - rendered_ = wxBitmap(GetSize()); - wxMemoryDC dc; - dc.SelectObject(rendered_); - dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size)); - dc.SetBrush(*brush_color); - dc.DrawRectangle({0, 0}, GetSize()); -} 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 @@ -#ifndef AREA_WINDOW_H_C2653ACF -#define AREA_WINDOW_H_C2653ACF - -#include - -#ifndef WX_PRECOMP -#include -#endif - -#include "area_popup.h" - -class AreaWindow : public wxWindow { - public: - static constexpr int ACTUAL_SIZE = 64; - static constexpr int BORDER_SIZE = 5; - static constexpr int EFFECTIVE_SIZE = ACTUAL_SIZE + BORDER_SIZE * 2; - - AreaWindow(wxWindow* parent, int area_id, AreaPopup* popup); - - int GetAreaId() const { return area_id_; } - - AreaPopup* GetPopup() { return popup_; } - - void UpdateIndicators(); - - private: - void OnPaint(wxPaintEvent& event); - void OnEnterWindow(wxMouseEvent& event); - void OnLeaveWindow(wxMouseEvent& event); - - void Redraw(); - - int area_id_; - wxBitmap rendered_; - AreaPopup* popup_; -}; - -#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) { wxPaintDC dc(this); dc.DrawBitmap(rendered_, 0, 0); + + event.Skip(); } void 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); wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent); TrackerFrame::TrackerFrame() - : wxFrame(nullptr, wxID_ANY, "Lingo Archipelago Tracker") { + : wxFrame(nullptr, wxID_ANY, "Lingo Archipelago Tracker", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) { ::wxInitAllImageHandlers(); 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 @@ #include "tracker_panel.h" +#include "ap_state.h" #include "area_popup.h" #include "game_data.h" +#include "tracker_state.h" + +constexpr int AREA_ACTUAL_SIZE = 64; +constexpr int AREA_BORDER_SIZE = 5; +constexpr int AREA_EFFECTIVE_SIZE = AREA_ACTUAL_SIZE + AREA_BORDER_SIZE * 2; TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { map_image_ = wxImage("assets/lingo_map.png", wxBITMAP_TYPE_PNG); @@ -10,30 +16,26 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { } for (const MapArea &map_area : GetGameData().GetMapAreas()) { - AreaPopup *area_popup = new AreaPopup(this, map_area.id); - area_popup->SetPosition({0, 0}); - area_popup->Raise(); - area_popups_.push_back(area_popup); - - AreaWindow *area_window = new AreaWindow(this, map_area.id, area_popup); - area_window->Lower(); - area_windows_.push_back(area_window); + AreaIndicator area; + area.area_id = map_area.id; + + area.popup = new AreaPopup(this, map_area.id); + area.popup->SetPosition({0, 0}); + + areas_.push_back(area); } Redraw(); Bind(wxEVT_PAINT, &TrackerPanel::OnPaint, this); + Bind(wxEVT_MOTION, &TrackerPanel::OnMouseMove, this); } void TrackerPanel::UpdateIndicators() { Redraw(); - for (AreaWindow *area_window : area_windows_) { - area_window->UpdateIndicators(); - } - - for (AreaPopup *area_popup : area_popups_) { - area_popup->UpdateIndicators(); + for (AreaIndicator& area : areas_) { + area.popup->UpdateIndicators(); } } @@ -44,6 +46,21 @@ void TrackerPanel::OnPaint(wxPaintEvent &event) { wxPaintDC dc(this); dc.DrawBitmap(rendered_, 0, 0); + + event.Skip(); +} + +void TrackerPanel::OnMouseMove(wxMouseEvent &event) { + for (AreaIndicator &area : areas_) { + if (area.real_x1 <= event.GetX() && event.GetX() < area.real_x2 && + area.real_y1 <= event.GetY() && event.GetY() < area.real_y2) { + area.popup->Show(); + } else { + area.popup->Hide(); + } + } + + event.Skip(); } void TrackerPanel::Redraw() { @@ -70,30 +87,66 @@ void TrackerPanel::Redraw() { map_image_.Scale(final_width, final_height, wxIMAGE_QUALITY_NORMAL) .Size(panel_size, {final_x, final_y}, 0, 0, 0)); - for (AreaWindow *area_window : area_windows_) { - const MapArea &map_area = - GetGameData().GetMapArea(area_window->GetAreaId()); + wxMemoryDC dc; + dc.SelectObject(rendered_); + + for (AreaIndicator& area : areas_) { + const wxBrush *brush_color = wxGREY_BRUSH; + + const MapArea &map_area = GetGameData().GetMapArea(area.area_id); + bool has_reachable_unchecked = false; + bool has_unreachable_unchecked = false; + for (int section_id = 0; section_id < map_area.locations.size(); + section_id++) { + if (!GetAPState().HasCheckedGameLocation(area.area_id, + section_id)) { + if (GetTrackerState().IsLocationReachable(area.area_id, + section_id)) { + has_reachable_unchecked = true; + } else { + has_unreachable_unchecked = true; + } + } + } + + if (has_reachable_unchecked && has_unreachable_unchecked) { + brush_color = wxYELLOW_BRUSH; + } else if (has_reachable_unchecked) { + brush_color = wxGREEN_BRUSH; + } else if (has_unreachable_unchecked) { + brush_color = wxRED_BRUSH; + } + int real_area_size = - final_width * AreaWindow::EFFECTIVE_SIZE / image_size.GetWidth(); - area_window->SetSize({real_area_size, real_area_size}); - area_window->SetPosition({ - final_x + (map_area.map_x - (AreaWindow::EFFECTIVE_SIZE / 2)) * - final_width / image_size.GetWidth(), - final_y + (map_area.map_y - (AreaWindow::EFFECTIVE_SIZE / 2)) * - final_width / image_size.GetWidth(), - }); - - AreaPopup *area_popup = area_window->GetPopup(); + final_width * AREA_EFFECTIVE_SIZE / image_size.GetWidth(); + int actual_border_size = + real_area_size * AREA_BORDER_SIZE / AREA_EFFECTIVE_SIZE; + int real_area_x = + final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) * + final_width / image_size.GetWidth(); + int real_area_y = + final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) * + final_width / image_size.GetWidth(); + + dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size)); + dc.SetBrush(*brush_color); + dc.DrawRectangle({real_area_x, real_area_y}, {real_area_size, real_area_size}); + + area.real_x1 = real_area_x; + area.real_x2 = real_area_x + real_area_size; + area.real_y1 = real_area_y; + area.real_y2 = real_area_y + real_area_size; + int popup_x = final_x + map_area.map_x * final_width / image_size.GetWidth(); int popup_y = final_y + map_area.map_y * final_width / image_size.GetWidth(); - if (popup_x + area_popup->GetSize().GetWidth() > panel_size.GetWidth()) { - popup_x = panel_size.GetWidth() - area_popup->GetSize().GetWidth(); + if (popup_x + area.popup->GetSize().GetWidth() > panel_size.GetWidth()) { + popup_x = panel_size.GetWidth() - area.popup->GetSize().GetWidth(); } - if (popup_y + area_popup->GetSize().GetHeight() > panel_size.GetHeight()) { - popup_y = panel_size.GetHeight() - area_popup->GetSize().GetHeight(); + if (popup_y + area.popup->GetSize().GetHeight() > panel_size.GetHeight()) { + popup_y = panel_size.GetHeight() - area.popup->GetSize().GetHeight(); } - area_popup->SetPosition({popup_x, popup_y}); + area.popup->SetPosition({popup_x, popup_y}); } } 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 @@ #include #endif -#include "area_window.h" +class AreaPopup; class TrackerPanel : public wxPanel { public: @@ -16,15 +16,24 @@ class TrackerPanel : public wxPanel { void UpdateIndicators(); private: + struct AreaIndicator { + int area_id = -1; + AreaPopup *popup = nullptr; + int real_x1 = 0; + int real_y1 = 0; + int real_x2 = 0; + int real_y2 = 0; + }; + void OnPaint(wxPaintEvent &event); + void OnMouseMove(wxMouseEvent &event); void Redraw(); wxImage map_image_; wxBitmap rendered_; - std::vector area_windows_; - std::vector area_popups_; + std::vector areas_; }; #endif /* end of include guard: TRACKER_PANEL_H_D675A54D */ -- cgit 1.4.1