1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
#pragma once
#include "Theme.hpp"
#include "ochess.hpp"
#include <map>
#include <tuple>
#include <utility>
#include <algorithm>
#include <vector>
#include <wx/artprov.h>
#include <wx/dcbuffer.h>
// 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<short, short, short> 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<char, std::uint8_t> captures;
/// @brief Square to highlight (combined to BoardCanvas::squares_hl)
std::vector<Square> squares_hl;
/// @brief Arrow to draw (combined to BoardCanvas::arrows)
std::vector<Arrow> 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<GameState::Square> squares_hl;
/// @brief Current drawn arrows that were drawn with the mouse
std::vector<GameState::Arrow> 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<char, std::uint8_t> 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);
};
|