#include #include "ViewController.h" #include "CollisionChecker.h" #include "ControlBooleanCommand.h" #include "CycleCollisionMethodCommand.h" #include "QuadTreeCollisionChecker.h" #include "Exception.h" #include "KeyboardCode.h" #include "MouseCode.h" #include "ToggleMuseumPauseCommand.h" #include "OpenFileGUICommand.h" #include "StepTileCommand.h" #include "TimeTravelCommand.h" #include "View.h" #include "Museum.h" #include "Pathfinder.h" using namespace std; ViewController::ViewController(Museum & m, View & v) : museum(m), view(v) { } ViewController::~ViewController() { } void ViewController::update() { this->update_size(); this->update_tiles(); if (this->draw_artists) this->update_artists(); if (this->draw_pathfinding) this->update_pathfinding(); if (this->draw_quadtree) this->update_quadtree(); } void ViewController::update_size() { this->view.window_size( this->scale * this->museum.canvas.data.columns, this->scale * this->museum.canvas.data.rows ); } void ViewController::update_tiles() { for (int y = 0; y < this->museum.canvas.data.rows; y++) { for (int x = 0; x < this->museum.canvas.data.columns; x++) { Tile & tile = this->museum.canvas.get_tile({ x, y }); Rectangle rect = { .x = x * scale, .y = y * scale, .width = scale, .height = scale, }; this->view.fill_rect(rect, tile.color); } } } void ViewController::update_artists() { People & people = this->museum.people; for (Artist * artist : people.get_artists()) { Rectangle rect = { .x = artist->data.x * scale, .y = artist->data.y * scale, .width = artist_size, .height = artist_size, }; this->view.fill_rect(rect, artist->color); } } void ViewController::draw_pathfinding_dot(const XY & point, const Color & color) { this->view.fill_rect(center({ .x = point.x * scale, .y = point.y * scale, .width = pathfinding_size, .height = pathfinding_size, }), color); } void ViewController::update_pathfinding() { PathfindingContext & ctx = this->museum.pathfinding; Pathfinder & solver = ctx.get_solver(); for (int y = 0; y < this->museum.canvas.data.rows; y++) { for (int x = 0; x < this->museum.canvas.data.columns; x++) { if (!solver.is_visited({ x, y })) continue; Rectangle rect = { .x = x * scale, .y = y * scale, .width = scale, .height = scale, }; this->view.draw_rect(rect, { 0, 0, 0 }, 2); } } const Pathfinder::Path & solution = solver.get_path(); for (const XY & point : solution) { this->draw_pathfinding_dot(point, { 0, 0, 0 }); } this->draw_pathfinding_dot(ctx.get_start(), { 0xff, 0xff, 0xff }); } void ViewController::update_quadtree_recursive(QuadTreeCollisionChecker * tree) { if (tree == nullptr) return; const Rectangle & tree_boundary = tree->get_boundary(); Rectangle rect = { .x = tree_boundary.x * scale, .y = tree_boundary.y * scale, .width = tree_boundary.width * scale, .height = tree_boundary.height * scale, }; this->view.draw_rect(rect, { .red = 0xff, .green = 0x00, .blue = 0xff, }, 1); this->update_quadtree_recursive(tree->subtree[0].get()); this->update_quadtree_recursive(tree->subtree[1].get()); this->update_quadtree_recursive(tree->subtree[2].get()); this->update_quadtree_recursive(tree->subtree[3].get()); } void ViewController::update_quadtree() { shared_ptr checker = this->museum.collision.get_checker(); auto tree = dynamic_cast(checker.get()); if (tree == nullptr) return; this->update_quadtree_recursive(tree); } void ViewController::ev_keydown(KeyboardCode key) { try { switch (key) { case KEY_SPACE: { ToggleMuseumPauseCommand(this->museum).execute(); break; } case KEY_ENTER: { StepTileCommand(this->museum.canvas, this->mouse_pos).execute(); break; } case KEY_O: { OpenFileGUICommand(this->museum, this->view).execute(); break; } case KEY_A: { ControlBooleanCommand(this->draw_artists).execute(); break; } case KEY_LEFT: { TimeTravelCommand(this->museum, false).execute(); break; } case KEY_RIGHT: { TimeTravelCommand(this->museum, true).execute(); break; } case KEY_C: { CycleCollisionMethodCommand(this->museum).execute(); break; } case KEY_Q: { ControlBooleanCommand(this->draw_quadtree).execute(); break; } default: break; } } catch (Exception & e) { printf("%s\n", e.what()); } } void ViewController::ev_mousedown(MouseCode button) { try { switch (button) { case MOUSE_LEFT: { this->museum.pathfinding.set_start(this->mouse_pos); break; } case MOUSE_RIGHT: { this->museum.pathfinding.set_end(this->mouse_pos); break; } default: break; } } catch (Exception & e) { printf("%s\n", e.what()); } } void ViewController::ev_mousemove(unsigned x, unsigned y) { this->mouse_pos = { .x = static_cast(x / this->scale), .y = static_cast(y / this->scale), }; } Rectangle ViewController::center(Rectangle rect) { rect.x += (scale - rect.width) / 2; rect.y += (scale - rect.height) / 2; return rect; }