#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 <= 7 && rank <= 7; // Do not need to check rank>=0 and file>=0 since unsigned int #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; /** * @brief Drawing buffer and state for 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; /** * @brief Current game state displayed by BoardCanvas */ typedef struct GameState { /// @brief State of an arrow typedef struct Arrow { std::string src,dst; wxColour color=wxNullColour; float scale=1; } Arrow; /// @brief State of an highlighted square typedef struct Square { std::string square; wxColour color=wxNullColour; } Square; std::string white, black; /** * @brief Contains all the board squares with their pieces in the same order as the FEN specification. * * For example, the following board @verbatim "rnb RNB" @endverbatim * contains a black rook on a8, a black knight on b8, a black bishop on c8, a white rook * on a1, a white knight on b1 and a white bishop on c1 */ std::string board; /// @brief When there is a pending promotion, this variable contains the coordinate of the square on which the promotion takes place. std::string promotion; std::map captures; /// @brief Square to highlight (combined to BoardCanvas::squares_hl) std::vector squares_hl; /// @brief Arrow to draw (combined to BoardCanvas::arrows) std::vector arrows; bool is_black_turn; bool mat_black; bool mat_white; bool show_evalbar=false; float eval=0; ClockTime black_time={-1,-1,-1}, white_time={-1,-1,-1}; } GameState; /** * @brief This class draws the chess board (squares, pieces, arrows and every other board related components). * */ class BoardCanvas : public wxPanel { /// @brief Contains the theme for squares and pieces (see Theme) Theme *t; /// @brief Scale down version of BoardCanvas::t for the captured pieces by black and white Theme *t_captures; /// @brief Stores the color of the arrows wxColour color_arrows; /// @brief Offset used for the start point of the arrows (this way, arrows do not completely overlap on the pieces) int arrows_offset; /// @brief Thickness of the arrows std::uint8_t arrow_thickness; /// @brief Player names std::string white_player,black_player; /// @brief Current highlighted squares that were highlighted with the mouse std::vector squares_hl; /// @brief Current drawn arrows that were drawn with the mouse std::vector arrows; // Various canvas state variables bool black_side, is_dragging, valid_drag, arrow_drag, is_black_turn; std::int32_t boardX, boardY, square_width, piece_width, mouseX, mouseY, lastClickX, lastClickY; /// @brief Contains an up to date dimension of the canvas size and its use in various places wxSize canvas_size; /// @brief Used for drag and drop wxPoint active_square; std::map captures; /// @brief Board can be frozen (to preview the board themes in the preference menu for example) bool frozen; bool lock_square_size; /// @brief Current animation state AnimState adata; /// @brief Current board state (contains all the game state) 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 board state BoardCanvas::gs on the given @a wxDC void DrawBoard(wxDC &dc); /// @brief Callback called by wxWidgets to refresh the canvas void OnPaint(wxPaintEvent &event); /// @brief Callback called by wxWidgets to handle mouse events 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); };