about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/subway_map.cpp37
-rw-r--r--src/subway_map.h10
2 files changed, 47 insertions, 0 deletions
diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 0aa7df3..230a256 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp
@@ -25,6 +25,13 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
25 return; 25 return;
26 } 26 }
27 27
28 tree_ = std::make_unique<quadtree::Quadtree<int, GetItemBox>>(
29 quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()),
30 static_cast<float>(map_image_.GetHeight())});
31 for (const SubwayItem &subway_item : GD_GetSubwayItems()) {
32 tree_->add(subway_item.id);
33 }
34
28 Redraw(); 35 Redraw();
29 36
30 Bind(wxEVT_PAINT, &SubwayMap::OnPaint, this); 37 Bind(wxEVT_PAINT, &SubwayMap::OnPaint, this);
@@ -47,6 +54,30 @@ void SubwayMap::OnPaint(wxPaintEvent &event) {
47} 54}
48 55
49void SubwayMap::OnMouseMove(wxMouseEvent &event) { 56void SubwayMap::OnMouseMove(wxMouseEvent &event) {
57 int mouse_x = std::clamp(
58 (event.GetX() - render_x_) * map_image_.GetWidth() / render_width_,
59 0, map_image_.GetWidth() - 1);
60 int mouse_y = std::clamp(
61 (event.GetY() - render_y_) * map_image_.GetWidth() / render_width_,
62 0, map_image_.GetHeight() - 1);
63
64 std::vector<int> hovered = tree_->query(
65 {static_cast<float>(mouse_x), static_cast<float>(mouse_y), 2, 2});
66 std::optional<int> new_hovered_item;
67 if (!hovered.empty()) {
68 new_hovered_item = hovered[0];
69 }
70
71 if (new_hovered_item != hovered_item_) {
72 if (new_hovered_item) {
73 wxLogVerbose("Hovered: %d", *new_hovered_item);
74 } else {
75 wxLogVerbose("Un-hovered: %d", *hovered_item_);
76 }
77
78 hovered_item_ = new_hovered_item;
79 }
80
50 event.Skip(); 81 event.Skip();
51} 82}
52 83
@@ -121,3 +152,9 @@ void SubwayMap::Redraw() {
121 } 152 }
122 } 153 }
123} 154}
155
156quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int& id) const {
157 const SubwayItem &subway_item = GD_GetSubwayItem(id);
158 return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y),
159 AREA_ACTUAL_SIZE, AREA_ACTUAL_SIZE};
160}
diff --git a/src/subway_map.h b/src/subway_map.h index e375750..6cb5c63 100644 --- a/src/subway_map.h +++ b/src/subway_map.h
@@ -7,8 +7,12 @@
7#include <wx/wx.h> 7#include <wx/wx.h>
8#endif 8#endif
9 9
10#include <memory>
11#include <optional>
10#include <vector> 12#include <vector>
11 13
14#include <quadtree/Quadtree.h>
15
12class SubwayMap : public wxPanel { 16class SubwayMap : public wxPanel {
13 public: 17 public:
14 SubwayMap(wxWindow *parent); 18 SubwayMap(wxWindow *parent);
@@ -29,7 +33,13 @@ class SubwayMap : public wxPanel {
29 int render_y_ = 0; 33 int render_y_ = 0;
30 int render_width_ = 0; 34 int render_width_ = 0;
31 int render_height_ = 0; 35 int render_height_ = 0;
36
37 struct GetItemBox {
38 quadtree::Box<float> operator()(const int &id) const;
39 };
32 40
41 std::unique_ptr<quadtree::Quadtree<int, GetItemBox>> tree_;
42 std::optional<int> hovered_item_;
33}; 43};
34 44
35#endif /* end of include guard: SUBWAY_MAP_H_BD2D843E */ 45#endif /* end of include guard: SUBWAY_MAP_H_BD2D843E */
s="highlight">
#include "pch.h"
#include "Puzzle.h"

Cell Puzzle::GetCell(int x, int y) const {
    x = Mod(x);
    if (!SafeCell(x, y)) return Cell::Undefined();
    return grid[x][y];
}

Cell::Color Puzzle::GetLine(int x, int y) const {
    return grid[x][y].color;
}

void Puzzle::NewGrid(int newWidth, int newHeight) {
    if (newWidth == 0) {
        assert(false);
        newWidth = width;
        newHeight = height;
    } else {
        // @Cleanup! This should be in the ctor...
        width = 2*newWidth + 1;
        height = 2*newHeight + 1;
    }
    grid.clear();
    grid.resize(width);
    for (int x=0; x<width; x++) grid[x].resize(height);
}

Pos Puzzle::GetSymmetricalPos(int x, int y) const {
    if (symmetry != Symmetry::NONE) {
        if (pillar) {
            x += width/2;
            if (symmetry & Symmetry::X) {
                x = width - x;
            }
        } else {
            if (symmetry & Symmetry::X) {
                x = (width-1) - x;
            }
        }
        if (symmetry & Symmetry::Y) {
            y = (height-1) - y;
        }
    }
    return Pos{x, y};
}

#include "json.hpp"
nlohmann::json newGrid(int width, int height) {
    using namespace nlohmann;

    json grid;
    for (int x=0; x<width; x++) {
        grid[x] = json::array();
        for (int y=0; y<height; y++) {
            if (x%2 == 1 && y%2 == 1) grid[x][y] = json::object();
            else grid[x][y] = {{"type", "line"}, {"color", 0}};
        }
    }
    return grid;
}

std::string Puzzle::Serialize() {
    using namespace nlohmann;

    json puzzle;
    puzzle["grid"] = {};
    for (int x=0; x<width; x++) {
        puzzle["grid"][x] = json::array();
        for (int y=0; y<height; y++) {
            if (x%2 == 1 && y%2 == 1) puzzle["grid"][x][y] = json::object();
            else puzzle["grid"][x][y] = {{"type", "line"}, {"color", 0}};
        }
    }
    puzzle["pillar"] = pillar;
    if (symmetry == Symmetry::X)        puzzle["symmetry"] = {{"x", true},  {"y", false}};
    else if (symmetry == Symmetry::Y)   puzzle["symmetry"] = {{"x", false}, {"y", true}};
    else if (symmetry == Symmetry::XY)  puzzle["symmetry"] = {{"x", true},  {"y", true}};

    for (int x=0; x<width; x++) {
        for (int y=0; y<height; y++) {
            const Cell& cell = grid[x][y];
            json j = puzzle["grid"][x][y];
            if (cell.dot != Cell::Dot::NONE) {
                if (cell.dot == Cell::Dot::BLACK)       j["dot"] = 1;
                if (cell.dot == Cell::Dot::BLUE)        j["dot"] = 2;
                if (cell.dot == Cell::Dot::YELLOW)      j["dot"] = 3;
                if (cell.dot == Cell::Dot::INVISIBLE)   j["dot"] = 4;
            } else if (cell.gap != Cell::Gap::NONE) {
                if (cell.gap == Cell::Gap::BREAK)       j["gap"] = 1;
                if (cell.gap == Cell::Gap::FULL)        j["gap"] = 2;
            } else if (cell.decoration != nullptr) {
                if (cell.decoration->color == Color::Black)         j["color"] = "black";
                else if (cell.decoration->color == Color::Blue)     j["color"] = "blue";
                else if (cell.decoration->color == Color::Cyan)     j["color"] = "cyan";
                else if (cell.decoration->color == Color::Gray)     j["color"] = "gray";
                else if (cell.decoration->color == Color::Green)    j["color"] = "green";
                else if (cell.decoration->color == Color::Orange)   j["color"] = "orange";
                else if (cell.decoration->color == Color::Pink)     j["color"] = "pink";
                else if (cell.decoration->color == Color::Purple)   j["color"] = "purple";
                else if (cell.decoration->color == Color::White)    j["color"] = "white";
                else if (cell.decoration->color == Color::Yellow)   j["color"] = "yellow";

                if (cell.decoration->type == Type::Stone) {
                    j["type"] = "square";
                } else if (cell.decoration->type == Type::Star) {
                    j["type"] = "star";
                } else if (cell.decoration->type == Type::Poly) {
                    j["type"] = "poly";
                    j["polyshape"] = cell.decoration->polyshape;
                } else if (cell.decoration->type == Type::Ylop) {
                    j["type"] = "ylop";
                    j["polyshape"] = cell.decoration->polyshape;
                } else if (cell.decoration->type == Type::Nega) {
                    j["type"] = "nega";
                } else if (cell.decoration->type == Type::Triangle) {
                    j["type"] = "triangle";
                    j["count"] = cell.decoration->count;
                }
            }

            if (cell.start) j["start"] = true;
            if (cell.end != Cell::Dir::NONE) {
                if (cell.end == Cell::Dir::LEFT)        j["end"] = "left";
                else if (cell.end == Cell::Dir::RIGHT)  j["end"] = "right";
                else if (cell.end == Cell::Dir::UP)     j["end"] = "top";
                else if (cell.end == Cell::Dir::DOWN)   j["end"] = "bottom";
            }
            puzzle["grid"][x][y] = j;
        }
    }

    return puzzle.dump();
}

int Puzzle::Mod(int x) const {
    if (!pillar) return x;
    return (x + width * height * 2) % width;
}

bool Puzzle::SafeCell(int x, int y) const {
    if (x < 0 || x >= width) return false;
    if (y < 0 || y >= height) return false;
    return true;
}