#pragma once #include "Theme.hpp" #include "ochess.hpp" #include #include #include #include #include #include #include // Local events wxDECLARE_EVENT(PLAY_MOVE_EVENT, wxCommandEvent); #define REFRESH_MOUSE_LOCATION() \ { \ const wxPoint pt = wxGetMousePosition(); \ mouseX = pt.x - this->GetScreenPosition().x; \ mouseY = pt.y - this->GetScreenPosition().y; \ } #define INIT_CURRENT_SQUARE() \ std::uint32_t file = 7 - (mouseX - boardX) / square_width; \ std::uint32_t rank = (mouseY - boardY) / square_width; \ if (!black_side) { \ file = 7 - file; \ rank = 7 - rank; \ } \ bool IsCurrentSquareValid = file >= 0 && file <= 7 && rank >= 0 && rank <= 7; #define MOUSE_ON(x, y, width, height) \ (mouseX >= (x) && mouseX <= ((x) + (width)) && mouseY >= (y) && \ mouseY <= ((y) + (height))) #define CAPTURE_FACTOR 0.35 #define SQUARE_NUM_PADDING 5 #define DEFAULT_ARROW(SRC,DST) {(SRC),(DST),wxNullColour,1} #define DEFAULT_SQUARE(SQUARE) {(SQUARE),wxNullColour} typedef std::tuple ClockTime; // Drawing buffer (ANIMATIONS) typedef struct AnimState { /// @brief Temporary buffer to reduce latency wxBitmap *buffer; /// @brief Should animation be played on refresh? bool animate; /// @brief Current animated frame int frame; /// @brief Total number of frames for the animation int frames; /// @brief Animation durations (in ms) int duration,duration_fast; /// @brief Animation FPS std::uint8_t fps; /// @brief Current animated piece char piece_moved; /// @brief Starting point of the animated piece wxPoint src; /// @brief Translation vector of the animated piece wxPoint transVect; } AnimState; typedef struct GameState { typedef struct Arrow { std::string src,dst; wxColour color=wxNullColour; float scale=1; } Arrow; typedef struct Square { std::string square; wxColour color=wxNullColour; } Square; std::string white, black; std::string board; std::map captures; std::vector squares_hl; std::vector arrows; bool is_black_turn; bool mat_black; bool mat_white; ClockTime black_time={-1,-1,-1}, white_time={-1,-1,-1}; } GameState; class BoardCanvas : public wxPanel { // *t is theme for board+pieces and // *t_captures is theme for captured pieces (scale down version of t) Theme *t, *t_captures; wxColour color_arrows; int arrows_offset; std::uint8_t arrow_thickness; std::string white_player,black_player; // Current highlighted squares and arrows: std::vector squares_hl; std::vector arrows; // Various canvas state variables bool black_side, is_dragging, valid_drag, arrow_drag, is_black_turn; std::uint32_t boardX, boardY, square_width, piece_width, mouseX, mouseY, lastClickX, lastClickY; wxSize canvas_size; wxPoint active_square; std::map captures; bool frozen,lock_square_size; // Current animation state AnimState adata; GameState gs; /// @brief Draw an arrow from a source point to a destination point on DC void DrawArrow(wxDC &dc, int xsrc, int ysrc, int xdst, int ydst, std::uint8_t thickness=50); /// @brief Draw an arrow with a L shape (such as knight moves) void DrawLArrow(wxDC &dc, int xsrc, int ysrc, int xdst, int ydst, bool flip=false, std::uint8_t thickness=50); public: BoardCanvas(wxFrame *parent); BoardCanvas(wxFrame *parent,std::uint32_t square_width, bool frozen); ~BoardCanvas(); void ApplyPreferences(); /// @brief Draw current state of the board (GameState) on the given wxDC void DrawBoard(wxDC &dc); void OnPaint(wxPaintEvent &event); void MouseEvent(wxMouseEvent &event); /// @brief Zomm in/out on the canvas void Zoom(std::int32_t zoom); /// @brief Change between black side and white side void Swap(); /// @brief Display a position on the canvas void SetupBoard(const GameState &new_gs); /// @brief Animate a piece front src to dst from current position void Animate(const GameState &new_gs, const std::string &src, const std::string &dst,bool faster); /// @brief Setup clock on displayed on the canvas void SetClockTime(short hours, short min, short sec, bool IsBlack); };