aboutsummaryrefslogtreecommitdiff
path: root/src/game_tab/left_panel/board/BoardCanvas.hpp
blob: a764feebebafcca21bd4467fa630becef722d6bb (plain)
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
#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 >= 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

typedef std::tuple<short, short, short> 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 {
  std::string white, black;
  std::string board;
  std::map<char, std::uint8_t> captures;
  std::vector<std::string> squares_hl;
  std::vector<std::string> 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::string white_player,black_player;
  // Current highlighted squares and arrows:
  std::vector<std::string> squares_hl;
  std::vector<std::string> 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<char, std::uint8_t> 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);
  /// @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);

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);
};