#include "tracker_panel.h" #include #include #include #include "ap_state.h" #include "area_popup.h" #include "game_data.h" #include "global.h" #include "godot_variant.h" #include "ipc_state.h" #include "tracker_config.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; constexpr int PLAYER_SIZE = 96; TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { SetBackgroundStyle(wxBG_STYLE_PAINT); map_image_ = wxImage(GetAbsolutePath("assets/lingo_map.png").c_str(), wxBITMAP_TYPE_PNG); if (!map_image_.IsOk()) { return; } player_image_ = wxImage(GetAbsolutePath("assets/player.png").c_str(), wxBITMAP_TYPE_PNG); if (!player_image_.IsOk()) { return; } for (const MapArea &map_area : GD_GetMapAreas()) { 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() { if (panels_mode_ && !savedata_path_) { solved_panels_ = IPC_GetSolvedPanels(); } for (AreaIndicator &area : areas_) { area.popup->UpdateIndicators(); } Redraw(); } void TrackerPanel::SetPanelsMode() { panels_mode_ = true; } void TrackerPanel::SetSavedataPath(std::string savedata_path) { if (!savedata_path_) { wxButton *refresh_button = new wxButton(this, wxID_ANY, "Refresh", {15, 15}); refresh_button->Bind(wxEVT_BUTTON, &TrackerPanel::OnRefreshSavedata, this); } savedata_path_ = savedata_path; panels_mode_ = true; RefreshSavedata(); } void TrackerPanel::RefreshSavedata() { solved_panels_.clear(); GodotVariant godot_variant = ParseGodotFile(*savedata_path_); for (const GodotVariant &panel_node : godot_variant.AsArray()) { const std::vector &fields = panel_node.AsArray(); if (fields[1].AsBool()) { const std::vector &nodepath = fields[0].AsNodePath(); std::string key = fmt::format("{}/{}", nodepath[3], nodepath[4]); solved_panels_.insert(key); } } UpdateIndicators(); Refresh(); } void TrackerPanel::OnPaint(wxPaintEvent &event) { if (GetSize() != rendered_.GetSize()) { Redraw(); } wxBufferedPaintDC dc(this); dc.DrawBitmap(rendered_, 0, 0); std::optional> player_position; if (IPC_IsConnected()) { player_position = IPC_GetPlayerPosition(); } else { player_position = AP_GetPlayerPosition(); } if (player_position.has_value()) { // 1588, 1194 // 14x14 -> 154x154 double intended_x = 1588.0 + (std::get<0>(*player_position) * (154.0 / 14.0)); double intended_y = 1194.0 + (std::get<1>(*player_position) * (154.0 / 14.0)); int real_x = offset_x_ + scale_x_ * intended_x - scaled_player_.GetWidth() / 2; int real_y = offset_y_ + scale_y_ * intended_y - scaled_player_.GetHeight() / 2; dc.DrawBitmap(scaled_player_, real_x, real_y); } event.Skip(); } void TrackerPanel::OnMouseMove(wxMouseEvent &event) { for (AreaIndicator &area : areas_) { if (area.active && 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::OnRefreshSavedata(wxCommandEvent &event) { RefreshSavedata(); } void TrackerPanel::Redraw() { wxSize panel_size = GetSize(); wxSize image_size = map_image_.GetSize(); int final_x = 0; int final_y = 0; int final_width = panel_size.GetWidth(); int final_height = panel_size.GetHeight(); if (image_size.GetWidth() * panel_size.GetHeight() > panel_size.GetWidth() * image_size.GetHeight()) { final_height = (panel_size.GetWidth() * image_size.GetHeight()) / image_size.GetWidth(); final_y = (panel_size.GetHeight() - final_height) / 2; } else { final_width = (image_size.GetWidth() * panel_size.GetHeight()) / image_size.GetHeight(); final_x = (panel_size.GetWidth() - final_width) / 2; } rendered_ = wxBitmap( m
name: "Daedalus Entrance"
ports {
  name: "DAEDALUS"
  path: "Components/Warps/worldport4"
}