diff options
| author | Star Rauchenberger <fefferburbia@gmail.com> | 2024-05-18 20:33:16 -0400 |
|---|---|---|
| committer | Star Rauchenberger <fefferburbia@gmail.com> | 2024-05-18 20:33:16 -0400 |
| commit | c87281384f716c8ca2f57bb8ea65d6d01bb06fae (patch) | |
| tree | ceb0fe8482c4822f7d8cf2554166afec812f6b7e | |
| parent | 4e95da4dbb105042bbaf41b7384c73506c86a61e (diff) | |
| download | lingo-ap-tracker-c87281384f716c8ca2f57bb8ea65d6d01bb06fae.tar.gz lingo-ap-tracker-c87281384f716c8ca2f57bb8ea65d6d01bb06fae.tar.bz2 lingo-ap-tracker-c87281384f716c8ca2f57bb8ea65d6d01bb06fae.zip | |
Zoom in and scroll subway map
| -rw-r--r-- | src/subway_map.cpp | 171 | ||||
| -rw-r--r-- | src/subway_map.h | 15 |
2 files changed, 151 insertions, 35 deletions
| diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 5a4be4b..b02c616 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp | |||
| @@ -12,11 +12,7 @@ | |||
| 12 | constexpr int AREA_ACTUAL_SIZE = 21; | 12 | constexpr int AREA_ACTUAL_SIZE = 21; |
| 13 | constexpr int OWL_ACTUAL_SIZE = 32; | 13 | constexpr int OWL_ACTUAL_SIZE = 32; |
| 14 | 14 | ||
| 15 | enum class ItemDrawType { | 15 | enum class ItemDrawType { kNone, kBox, kOwl }; |
| 16 | kNone, | ||
| 17 | kBox, | ||
| 18 | kOwl | ||
| 19 | }; | ||
| 20 | 16 | ||
| 21 | SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | 17 | SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { |
| 22 | SetBackgroundStyle(wxBG_STYLE_PAINT); | 18 | SetBackgroundStyle(wxBG_STYLE_PAINT); |
| @@ -50,8 +46,13 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
| 50 | 46 | ||
| 51 | Redraw(); | 47 | Redraw(); |
| 52 | 48 | ||
| 49 | scroll_timer_ = new wxTimer(this); | ||
| 50 | |||
| 53 | Bind(wxEVT_PAINT, &SubwayMap::OnPaint, this); | 51 | Bind(wxEVT_PAINT, &SubwayMap::OnPaint, this); |
| 54 | Bind(wxEVT_MOTION, &SubwayMap::OnMouseMove, this); | 52 | Bind(wxEVT_MOTION, &SubwayMap::OnMouseMove, this); |
| 53 | Bind(wxEVT_MOUSEWHEEL, &SubwayMap::OnMouseScroll, this); | ||
| 54 | Bind(wxEVT_LEAVE_WINDOW, &SubwayMap::OnMouseLeave, this); | ||
| 55 | Bind(wxEVT_TIMER, &SubwayMap::OnTimer, this); | ||
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | void SubwayMap::OnConnect() { | 58 | void SubwayMap::OnConnect() { |
| @@ -67,7 +68,8 @@ void SubwayMap::OnConnect() { | |||
| 67 | tagged[tag].push_back(subway_item.id); | 68 | tagged[tag].push_back(subway_item.id); |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | if (!AP_IsSunwarpShuffle() && subway_item.sunwarp && subway_item.sunwarp->type != SubwaySunwarpType::kFinal) { | 71 | if (!AP_IsSunwarpShuffle() && subway_item.sunwarp && |
| 72 | subway_item.sunwarp->type != SubwaySunwarpType::kFinal) { | ||
| 71 | std::ostringstream tag; | 73 | std::ostringstream tag; |
| 72 | tag << "sunwarp" << subway_item.sunwarp->dots; | 74 | tag << "sunwarp" << subway_item.sunwarp->dots; |
| 73 | 75 | ||
| @@ -108,7 +110,7 @@ void SubwayMap::UpdateIndicators() { | |||
| 108 | } | 110 | } |
| 109 | 111 | ||
| 110 | void SubwayMap::UpdateSunwarp(SubwaySunwarp from_sunwarp, | 112 | void SubwayMap::UpdateSunwarp(SubwaySunwarp from_sunwarp, |
| 111 | SubwaySunwarp to_sunwarp) { | 113 | SubwaySunwarp to_sunwarp) { |
| 112 | networks_.AddLink(GD_GetSubwayItemForSunwarp(from_sunwarp), | 114 | networks_.AddLink(GD_GetSubwayItemForSunwarp(from_sunwarp), |
| 113 | GD_GetSubwayItemForSunwarp(to_sunwarp)); | 115 | GD_GetSubwayItemForSunwarp(to_sunwarp)); |
| 114 | } | 116 | } |
| @@ -119,7 +121,9 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 119 | } | 121 | } |
| 120 | 122 | ||
| 121 | wxBufferedPaintDC dc(this); | 123 | wxBufferedPaintDC dc(this); |
| 122 | dc.DrawBitmap(rendered_, 0, 0); | 124 | dc.SetBackground(*wxWHITE_BRUSH); |
| 125 | dc.Clear(); | ||
| 126 | dc.DrawBitmap(rendered_, zoom_x_, zoom_y_); | ||
| 123 | 127 | ||
| 124 | if (hovered_item_) { | 128 | if (hovered_item_) { |
| 125 | const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); | 129 | const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); |
| @@ -139,7 +143,7 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 139 | col_width = item_extent.GetWidth(); | 143 | col_width = item_extent.GetWidth(); |
| 140 | } | 144 | } |
| 141 | } | 145 | } |
| 142 | 146 | ||
| 143 | int item_width = col_width + 10 + 32; | 147 | int item_width = col_width + 10 + 32; |
| 144 | int full_width = item_width + 20; | 148 | int full_width = item_width + 20; |
| 145 | 149 | ||
| @@ -162,7 +166,7 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 162 | 166 | ||
| 163 | int cur_height = 10; | 167 | int cur_height = 10; |
| 164 | 168 | ||
| 165 | for (const auto& [text, obtained] : report) { | 169 | for (const auto &[text, obtained] : report) { |
| 166 | wxBitmap *eye_ptr = obtained ? &unchecked_eye_ : &checked_eye_; | 170 | wxBitmap *eye_ptr = obtained ? &unchecked_eye_ : &checked_eye_; |
| 167 | 171 | ||
| 168 | dc.DrawBitmap(*eye_ptr, popup_pos + wxPoint{10, cur_height}); | 172 | dc.DrawBitmap(*eye_ptr, popup_pos + wxPoint{10, cur_height}); |
| @@ -191,7 +195,7 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 191 | {item1.x + AREA_ACTUAL_SIZE / 2, item1.y + AREA_ACTUAL_SIZE / 2}); | 195 | {item1.x + AREA_ACTUAL_SIZE / 2, item1.y + AREA_ACTUAL_SIZE / 2}); |
| 192 | wxPoint item2_pos = MapPosToRenderPos( | 196 | wxPoint item2_pos = MapPosToRenderPos( |
| 193 | {item2.x + AREA_ACTUAL_SIZE / 2, item2.y + AREA_ACTUAL_SIZE / 2}); | 197 | {item2.x + AREA_ACTUAL_SIZE / 2, item2.y + AREA_ACTUAL_SIZE / 2}); |
| 194 | 198 | ||
| 195 | int left = std::min(item1_pos.x, item2_pos.x); | 199 | int left = std::min(item1_pos.x, item2_pos.x); |
| 196 | int top = std::min(item1_pos.y, item2_pos.y); | 200 | int top = std::min(item1_pos.y, item2_pos.y); |
| 197 | int right = std::max(item1_pos.x, item2_pos.x); | 201 | int right = std::max(item1_pos.x, item2_pos.x); |
| @@ -242,11 +246,11 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 242 | } | 246 | } |
| 243 | 247 | ||
| 244 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4)); | 248 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4)); |
| 245 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2, | 249 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, |
| 246 | start, end); | 250 | halfheight * 2, start, end); |
| 247 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); | 251 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); |
| 248 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2, | 252 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, |
| 249 | start, end); | 253 | halfheight * 2, start, end); |
| 250 | } | 254 | } |
| 251 | } | 255 | } |
| 252 | } | 256 | } |
| @@ -257,7 +261,7 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 257 | 261 | ||
| 258 | void SubwayMap::OnMouseMove(wxMouseEvent &event) { | 262 | void SubwayMap::OnMouseMove(wxMouseEvent &event) { |
| 259 | wxPoint mouse_pos = RenderPosToMapPos(event.GetPosition()); | 263 | wxPoint mouse_pos = RenderPosToMapPos(event.GetPosition()); |
| 260 | 264 | ||
| 261 | std::vector<int> hovered = tree_->query( | 265 | std::vector<int> hovered = tree_->query( |
| 262 | {static_cast<float>(mouse_pos.x), static_cast<float>(mouse_pos.y), 2, 2}); | 266 | {static_cast<float>(mouse_pos.x), static_cast<float>(mouse_pos.y), 2, 2}); |
| 263 | std::optional<int> new_hovered_item; | 267 | std::optional<int> new_hovered_item; |
| @@ -271,9 +275,65 @@ void SubwayMap::OnMouseMove(wxMouseEvent &event) { | |||
| 271 | Refresh(); | 275 | Refresh(); |
| 272 | } | 276 | } |
| 273 | 277 | ||
| 278 | int scroll_x; | ||
| 279 | int scroll_y; | ||
| 280 | if (event.GetPosition().x < GetSize().GetWidth() / 9) { | ||
| 281 | scroll_x = 20; | ||
| 282 | } else if (event.GetPosition().x < GetSize().GetWidth() / 6) { | ||
| 283 | scroll_x = 5; | ||
| 284 | } else if (event.GetPosition().x > 8 * GetSize().GetWidth() / 9) { | ||
| 285 | scroll_x = -20; | ||
| 286 | } else if (event.GetPosition().x > 5 * GetSize().GetWidth() / 6) { | ||
| 287 | scroll_x = -5; | ||
| 288 | } else { | ||
| 289 | scroll_x = 0; | ||
| 290 | } | ||
| 291 | if (event.GetPosition().y < GetSize().GetHeight() / 9) { | ||
| 292 | scroll_y = 20; | ||
| 293 | } else if (event.GetPosition().y < GetSize().GetHeight() / 6) { | ||
| 294 | scroll_y = 5; | ||
| 295 | } else if (event.GetPosition().y > 8 * GetSize().GetHeight() / 9) { | ||
| 296 | scroll_y = -20; | ||
| 297 | } else if (event.GetPosition().y > 5 * GetSize().GetHeight() / 6) { | ||
| 298 | scroll_y = -5; | ||
| 299 | } else { | ||
| 300 | scroll_y = 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | SetScrollSpeed(scroll_x, scroll_y); | ||
| 304 | |||
| 274 | event.Skip(); | 305 | event.Skip(); |
| 275 | } | 306 | } |
| 276 | 307 | ||
| 308 | void SubwayMap::OnMouseScroll(wxMouseEvent &event) { | ||
| 309 | double new_zoom = zoom_; | ||
| 310 | if (event.GetWheelRotation() > 0) { | ||
| 311 | new_zoom = std::min(3.0, zoom_ + 0.25); | ||
| 312 | } else { | ||
| 313 | new_zoom = std::max(1.0, zoom_ - 0.25); | ||
| 314 | } | ||
| 315 | |||
| 316 | if (zoom_ != new_zoom) { | ||
| 317 | wxPoint map_pos = RenderPosToMapPos(event.GetPosition()); | ||
| 318 | zoom_ = new_zoom; | ||
| 319 | |||
| 320 | wxPoint virtual_pos = MapPosToVirtualPos(map_pos); | ||
| 321 | SetZoomPos(-(virtual_pos - event.GetPosition())); | ||
| 322 | |||
| 323 | Redraw(); | ||
| 324 | Refresh(); | ||
| 325 | } | ||
| 326 | |||
| 327 | event.Skip(); | ||
| 328 | } | ||
| 329 | |||
| 330 | void SubwayMap::OnMouseLeave(wxMouseEvent &event) { SetScrollSpeed(0, 0); } | ||
| 331 | |||
| 332 | void SubwayMap::OnTimer(wxTimerEvent &event) { | ||
| 333 | SetZoomPos({zoom_x_ + scroll_x_, zoom_y_ + scroll_y_}); | ||
| 334 | Refresh(); | ||
| 335 | } | ||
| 336 | |||
| 277 | void SubwayMap::Redraw() { | 337 | void SubwayMap::Redraw() { |
| 278 | wxSize panel_size = GetSize(); | 338 | wxSize panel_size = GetSize(); |
| 279 | wxSize image_size = map_image_.GetSize(); | 339 | wxSize image_size = map_image_.GetSize(); |
| @@ -294,10 +354,10 @@ void SubwayMap::Redraw() { | |||
| 294 | render_x_ = (panel_size.GetWidth() - render_width_) / 2; | 354 | render_x_ = (panel_size.GetWidth() - render_width_) / 2; |
| 295 | } | 355 | } |
| 296 | 356 | ||
| 297 | rendered_ = wxBitmap( | 357 | rendered_ = wxBitmap(map_image_.Scale( |
| 298 | map_image_ | 358 | render_width_ * zoom_, render_height_ * zoom_, wxIMAGE_QUALITY_BILINEAR)); |
| 299 | .Scale(render_width_, render_height_, wxIMAGE_QUALITY_BILINEAR) | 359 | |
| 300 | .Size(panel_size, {render_x_, render_y_}, 255, 255, 255)); | 360 | SetZoomPos({zoom_x_, zoom_y_}); |
| 301 | 361 | ||
| 302 | wxMemoryDC dc; | 362 | wxMemoryDC dc; |
| 303 | dc.SelectObject(rendered_); | 363 | dc.SelectObject(rendered_); |
| @@ -353,10 +413,10 @@ void SubwayMap::Redraw() { | |||
| 353 | } | 413 | } |
| 354 | } | 414 | } |
| 355 | 415 | ||
| 356 | wxPoint real_area_pos = MapPosToRenderPos({subway_item.x, subway_item.y}); | 416 | wxPoint real_area_pos = MapPosToVirtualPos({subway_item.x, subway_item.y}); |
| 357 | 417 | ||
| 358 | int real_area_size = | 418 | int real_area_size = |
| 359 | render_width_ * | 419 | render_width_ * zoom_ * |
| 360 | (draw_type == ItemDrawType::kOwl ? OWL_ACTUAL_SIZE : AREA_ACTUAL_SIZE) / | 420 | (draw_type == ItemDrawType::kOwl ? OWL_ACTUAL_SIZE : AREA_ACTUAL_SIZE) / |
| 361 | image_size.GetWidth(); | 421 | image_size.GetWidth(); |
| 362 | if (real_area_size == 0) { | 422 | if (real_area_size == 0) { |
| @@ -366,32 +426,73 @@ void SubwayMap::Redraw() { | |||
| 366 | if (draw_type == ItemDrawType::kBox) { | 426 | if (draw_type == ItemDrawType::kBox) { |
| 367 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); | 427 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); |
| 368 | dc.SetBrush(*brush_color); | 428 | dc.SetBrush(*brush_color); |
| 369 | dc.DrawRectangle(real_area_pos, | 429 | dc.DrawRectangle(real_area_pos, {real_area_size, real_area_size}); |
| 370 | {real_area_size, real_area_size}); | ||
| 371 | } else if (draw_type == ItemDrawType::kOwl) { | 430 | } else if (draw_type == ItemDrawType::kOwl) { |
| 372 | wxBitmap owl_bitmap = wxBitmap( | 431 | wxBitmap owl_bitmap = wxBitmap(owl_image_.Scale( |
| 373 | owl_image_.Scale(real_area_size, real_area_size, | 432 | real_area_size, real_area_size, wxIMAGE_QUALITY_BILINEAR)); |
| 374 | wxIMAGE_QUALITY_BILINEAR)); | ||
| 375 | dc.DrawBitmap(owl_bitmap, real_area_pos); | 433 | dc.DrawBitmap(owl_bitmap, real_area_pos); |
| 376 | } | 434 | } |
| 377 | } | 435 | } |
| 378 | } | 436 | } |
| 379 | 437 | ||
| 380 | |||
| 381 | wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { | 438 | wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { |
| 382 | return {pos.x * render_width_ / map_image_.GetSize().GetWidth() + render_x_, | 439 | return {static_cast<int>(pos.x * render_width_ * zoom_ / |
| 383 | pos.y * render_width_ / map_image_.GetSize().GetWidth() + render_y_}; | 440 | map_image_.GetSize().GetWidth() + |
| 441 | zoom_x_), | ||
| 442 | static_cast<int>(pos.y * render_width_ * zoom_ / | ||
| 443 | map_image_.GetSize().GetWidth() + | ||
| 444 | zoom_y_)}; | ||
| 445 | } | ||
| 446 | |||
| 447 | wxPoint SubwayMap::MapPosToVirtualPos(wxPoint pos) const { | ||
| 448 | return {static_cast<int>(pos.x * render_width_ * zoom_ / | ||
| 449 | map_image_.GetSize().GetWidth()), | ||
| 450 | static_cast<int>(pos.y * render_width_ * zoom_ / | ||
| 451 | map_image_.GetSize().GetWidth())}; | ||
| 384 | } | 452 | } |
| 385 | 453 | ||
| 386 | wxPoint SubwayMap::RenderPosToMapPos(wxPoint pos) const { | 454 | wxPoint SubwayMap::RenderPosToMapPos(wxPoint pos) const { |
| 387 | return { | 455 | return { |
| 388 | std::clamp((pos.x - render_x_) * map_image_.GetWidth() / render_width_, 0, | 456 | std::clamp(static_cast<int>((pos.x - zoom_x_) * map_image_.GetWidth() / |
| 389 | map_image_.GetWidth() - 1), | 457 | render_width_ / zoom_), |
| 390 | std::clamp((pos.y - render_y_) * map_image_.GetWidth() / render_width_, 0, | 458 | 0, map_image_.GetWidth() - 1), |
| 391 | map_image_.GetHeight() - 1)}; | 459 | std::clamp(static_cast<int>((pos.y - zoom_y_) * map_image_.GetWidth() / |
| 460 | render_width_ / zoom_), | ||
| 461 | 0, map_image_.GetHeight() - 1)}; | ||
| 462 | } | ||
| 463 | |||
| 464 | void SubwayMap::SetZoomPos(wxPoint pos) { | ||
| 465 | if (render_width_ * zoom_ <= GetSize().GetWidth()) { | ||
| 466 | zoom_x_ = (GetSize().GetWidth() - render_width_ * zoom_) / 2; | ||
| 467 | } else { | ||
| 468 | zoom_x_ = std::clamp( | ||
| 469 | pos.x, GetSize().GetWidth() - static_cast<int>(render_width_ * zoom_), | ||
| 470 | 0); | ||
| 471 | } | ||
| 472 | if (render_height_ * zoom_ <= GetSize().GetHeight()) { | ||
| 473 | zoom_y_ = (GetSize().GetHeight() - render_height_ * zoom_) / 2; | ||
| 474 | } else { | ||
| 475 | zoom_y_ = std::clamp( | ||
| 476 | pos.y, GetSize().GetHeight() - static_cast<int>(render_height_ * zoom_), | ||
| 477 | 0); | ||
| 478 | } | ||
| 479 | } | ||
| 480 | |||
| 481 | void SubwayMap::SetScrollSpeed(int scroll_x, int scroll_y) { | ||
| 482 | bool should_timer = (scroll_x != 0 || scroll_y != 0); | ||
| 483 | if (should_timer != scroll_timer_->IsRunning()) { | ||
| 484 | if (should_timer) { | ||
| 485 | scroll_timer_->Start(1000 / 60); | ||
| 486 | } else { | ||
| 487 | scroll_timer_->Stop(); | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | scroll_x_ = scroll_x; | ||
| 492 | scroll_y_ = scroll_y; | ||
| 392 | } | 493 | } |
| 393 | 494 | ||
| 394 | quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int& id) const { | 495 | quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int &id) const { |
| 395 | const SubwayItem &subway_item = GD_GetSubwayItem(id); | 496 | const SubwayItem &subway_item = GD_GetSubwayItem(id); |
| 396 | return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y), | 497 | return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y), |
| 397 | AREA_ACTUAL_SIZE, AREA_ACTUAL_SIZE}; | 498 | AREA_ACTUAL_SIZE, AREA_ACTUAL_SIZE}; |
| diff --git a/src/subway_map.h b/src/subway_map.h index 0d26d0b..9b0b43f 100644 --- a/src/subway_map.h +++ b/src/subway_map.h | |||
| @@ -29,12 +29,19 @@ class SubwayMap : public wxPanel { | |||
| 29 | private: | 29 | private: |
| 30 | void OnPaint(wxPaintEvent &event); | 30 | void OnPaint(wxPaintEvent &event); |
| 31 | void OnMouseMove(wxMouseEvent &event); | 31 | void OnMouseMove(wxMouseEvent &event); |
| 32 | void OnMouseScroll(wxMouseEvent &event); | ||
| 33 | void OnMouseLeave(wxMouseEvent &event); | ||
| 34 | void OnTimer(wxTimerEvent &event); | ||
| 32 | 35 | ||
| 33 | void Redraw(); | 36 | void Redraw(); |
| 34 | 37 | ||
| 35 | wxPoint MapPosToRenderPos(wxPoint pos) const; | 38 | wxPoint MapPosToRenderPos(wxPoint pos) const; |
| 39 | wxPoint MapPosToVirtualPos(wxPoint pos) const; | ||
| 36 | wxPoint RenderPosToMapPos(wxPoint pos) const; | 40 | wxPoint RenderPosToMapPos(wxPoint pos) const; |
| 37 | 41 | ||
| 42 | void SetZoomPos(wxPoint pos); | ||
| 43 | void SetScrollSpeed(int scroll_x, int scroll_y); | ||
| 44 | |||
| 38 | wxImage map_image_; | 45 | wxImage map_image_; |
| 39 | wxImage owl_image_; | 46 | wxImage owl_image_; |
| 40 | wxBitmap unchecked_eye_; | 47 | wxBitmap unchecked_eye_; |
| @@ -46,6 +53,14 @@ class SubwayMap : public wxPanel { | |||
| 46 | int render_width_ = 0; | 53 | int render_width_ = 0; |
| 47 | int render_height_ = 0; | 54 | int render_height_ = 0; |
| 48 | 55 | ||
| 56 | double zoom_ = 1.0; | ||
| 57 | int zoom_x_ = 0; // in render space | ||
| 58 | int zoom_y_ = 0; | ||
| 59 | |||
| 60 | wxTimer* scroll_timer_; | ||
| 61 | int scroll_x_ = 0; | ||
| 62 | int scroll_y_ = 0; | ||
| 63 | |||
| 49 | struct GetItemBox { | 64 | struct GetItemBox { |
| 50 | quadtree::Box<float> operator()(const int &id) const; | 65 | quadtree::Box<float> operator()(const int &id) const; |
| 51 | }; | 66 | }; |
