mirror of
https://gitlab.com/manzerbredes/ochess.git
synced 2025-04-07 02:26:29 +02:00
Debug BoardCanvas DragNDrop and highlight last played move
This commit is contained in:
parent
741dc8a52e
commit
445cc09d01
4 changed files with 92 additions and 72 deletions
4
TODO.md
4
TODO.md
|
@ -6,12 +6,12 @@
|
||||||
- [x] Ask before closing MainWindow/Tabs if anything is not saved
|
- [x] Ask before closing MainWindow/Tabs if anything is not saved
|
||||||
- [x] Disable the save button in GameTab after saving (and re-enable it on new changes)
|
- [x] Disable the save button in GameTab after saving (and re-enable it on new changes)
|
||||||
- [ ] Make PGNGameBase use GotoNextGame() instead of ParseNextGame() in the NextGame() method to improve performance
|
- [ ] Make PGNGameBase use GotoNextGame() instead of ParseNextGame() in the NextGame() method to improve performance
|
||||||
- [ ] Clean and debug DragNDrop in BoardCanvas
|
- [x] Clean and debug DragNDrop in BoardCanvas
|
||||||
|
|
||||||
## Additional Features
|
## Additional Features
|
||||||
- [ ] Add a live evaluation bar to the BoardCanvas
|
- [ ] Add a live evaluation bar to the BoardCanvas
|
||||||
- [x] Be able to draw arrows on the Board
|
- [x] Be able to draw arrows on the Board
|
||||||
- [ ] Highlight the last played move
|
- [x] Highlight the last played move
|
||||||
- [ ] Be able to play against an engine
|
- [ ] Be able to play against an engine
|
||||||
- [ ] Implement full chess engine game analyzer/annotator
|
- [ ] Implement full chess engine game analyzer/annotator
|
||||||
- [ ] Handle .si4 databases
|
- [ ] Handle .si4 databases
|
||||||
|
|
|
@ -107,6 +107,15 @@ void GameTabLeftPanel::Notify(bool skip_animation) {
|
||||||
gs.black=game->GetTag("Black");
|
gs.black=game->GetTag("Black");
|
||||||
gs.mat_black=game->IsCheckmate(true);
|
gs.mat_black=game->IsCheckmate(true);
|
||||||
gs.mat_white=game->IsCheckmate(false);
|
gs.mat_white=game->IsCheckmate(false);
|
||||||
|
if(m){
|
||||||
|
// There should be a valid src_hl or dst_hl ortherwise it explode:
|
||||||
|
std::string src_hl, dst_hl;
|
||||||
|
m->GetAbsoluteMove(src_hl,dst_hl);
|
||||||
|
if(src_hl.size()>0){ // Just in case
|
||||||
|
gs.squares_hl.push_back(src_hl+"d");
|
||||||
|
gs.squares_hl.push_back(dst_hl+"a");
|
||||||
|
}
|
||||||
|
}
|
||||||
if(skip_animation || !animate){
|
if(skip_animation || !animate){
|
||||||
board_canvas->SetupBoard(gs);
|
board_canvas->SetupBoard(gs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ BoardCanvas::BoardCanvas(wxFrame *parent)
|
||||||
color_arrows=wxColour(145, 233, 255);
|
color_arrows=wxColour(145, 233, 255);
|
||||||
is_dragging = false;
|
is_dragging = false;
|
||||||
valid_drag = false;
|
valid_drag = false;
|
||||||
valid_arrow = false;
|
arrow_drag = false;
|
||||||
arrows_offset = t->GetSquaresSizes()/2.5;
|
arrows_offset = t->GetSquaresSizes()/2.5;
|
||||||
// Init animation data
|
// Init animation data
|
||||||
adata.duration=100;
|
adata.duration=100;
|
||||||
|
@ -229,7 +229,8 @@ void BoardCanvas::DrawBoard(wxDC &dc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw highlighted squares
|
// Draw highlighted squares
|
||||||
for(const std::string &s:gs.squares_hl){
|
for(int i=0;i<(gs.squares_hl.size()+squares_hl.size());i++){
|
||||||
|
const std::string &s=i<gs.squares_hl.size() ? gs.squares_hl[i] : squares_hl[i-gs.squares_hl.size()];
|
||||||
std::uint8_t sfile = s[0]-'a';
|
std::uint8_t sfile = s[0]-'a';
|
||||||
std::uint8_t srank = s[1]-'1';
|
std::uint8_t srank = s[1]-'1';
|
||||||
if (!black_side) {
|
if (!black_side) {
|
||||||
|
@ -395,7 +396,8 @@ void BoardCanvas::DrawBoard(wxDC &dc) {
|
||||||
boardY + square_width * 8 + numbers_size.y*2));
|
boardY + square_width * 8 + numbers_size.y*2));
|
||||||
}
|
}
|
||||||
// Draw arrows
|
// Draw arrows
|
||||||
for(const std::string arrow: gs.arrows){
|
for(int i=0;i<(gs.arrows.size()+arrows.size());i++){
|
||||||
|
const std::string &arrow= i<gs.arrows.size() ? gs.arrows[i] : arrows[i-gs.arrows.size()];
|
||||||
std::uint8_t sfile = arrow[0]-'a';
|
std::uint8_t sfile = arrow[0]-'a';
|
||||||
std::uint8_t srank = arrow[1]-'1';
|
std::uint8_t srank = arrow[1]-'1';
|
||||||
std::uint8_t dfile = arrow[2]-'a';
|
std::uint8_t dfile = arrow[2]-'a';
|
||||||
|
@ -427,14 +429,67 @@ void BoardCanvas::DrawBoard(wxDC &dc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoardCanvas::MouseEvent(wxMouseEvent &event) {
|
void BoardCanvas::MouseEvent(wxMouseEvent &event) {
|
||||||
if (!frozen) {
|
// Disable mouse events if BoardCanvas is frozen:
|
||||||
if (event.Dragging()) {
|
if(frozen)
|
||||||
if (valid_drag) {
|
return;
|
||||||
is_dragging = true;
|
|
||||||
Refresh();
|
// Just redraw if a piece is currently being moved:
|
||||||
|
if (event.Dragging() && valid_drag) {
|
||||||
|
is_dragging = true;
|
||||||
|
Refresh();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.LeftDown() || event.RightDown()) {
|
||||||
|
// Start dragging (either piece or arrows drawing)
|
||||||
|
SetFocus();
|
||||||
|
REFRESH_MOUSE_LOCATION();
|
||||||
|
lastClickX = mouseX;
|
||||||
|
lastClickY = mouseY;
|
||||||
|
INIT_CURRENT_SQUARE();
|
||||||
|
if (IsCurrentSquareValid) {
|
||||||
|
active_square.x = file;
|
||||||
|
active_square.y = rank;
|
||||||
|
if(event.LeftDown()){
|
||||||
|
if (gs.board[(7 - rank) * 8 + file] != ' ') {
|
||||||
|
wxLogDebug("Drag start on square (%d,%d)", file, rank);
|
||||||
|
valid_drag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if ((valid_arrow && event.RightUp()) || event.RightDClick()) {
|
else {
|
||||||
valid_arrow=false;
|
wxLogDebug("Arrow start on square (%d,%d)", file, rank);
|
||||||
|
arrow_drag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(event.LeftUp()) {
|
||||||
|
if(valid_drag){
|
||||||
|
// Handle drop
|
||||||
|
REFRESH_MOUSE_LOCATION();
|
||||||
|
INIT_CURRENT_SQUARE();
|
||||||
|
|
||||||
|
if (IsCurrentSquareValid) {
|
||||||
|
wxLogDebug("Drag end on square (%d,%d)", file, rank);
|
||||||
|
/// Play the move
|
||||||
|
wxCommandEvent event(PLAY_MOVE_EVENT, GetId());
|
||||||
|
event.SetEventObject(this);
|
||||||
|
std::string move = ((char)('a' + active_square.x)) +
|
||||||
|
std::to_string(+active_square.y + 1) +
|
||||||
|
((char)('a' + file)) + std::to_string(rank + 1);
|
||||||
|
event.SetString(move);
|
||||||
|
ProcessEvent(event);
|
||||||
|
} else {
|
||||||
|
// If square not valid just redraw (place piece back to its square)
|
||||||
|
Refresh(); // Note that there will be 2 Refresh() this one and the next after clear() of arrows and squares_hl but it is clearer like this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arrows.clear();
|
||||||
|
squares_hl.clear();
|
||||||
|
Refresh();
|
||||||
|
// In any left up, reset dragging variables
|
||||||
|
valid_drag = false;
|
||||||
|
is_dragging = false;
|
||||||
|
} else if(event.RightUp()){
|
||||||
|
if(arrow_drag){
|
||||||
// Handle drop
|
// Handle drop
|
||||||
REFRESH_MOUSE_LOCATION();
|
REFRESH_MOUSE_LOCATION();
|
||||||
INIT_CURRENT_SQUARE();
|
INIT_CURRENT_SQUARE();
|
||||||
|
@ -443,73 +498,28 @@ void BoardCanvas::MouseEvent(wxMouseEvent &event) {
|
||||||
std::to_string(+active_square.y + 1);
|
std::to_string(+active_square.y + 1);
|
||||||
std::string dst=((char)('a' + file)) + std::to_string(rank + 1);
|
std::string dst=((char)('a' + file)) + std::to_string(rank + 1);
|
||||||
if(src!=dst){
|
if(src!=dst){
|
||||||
gs.arrows.push_back(src+dst);
|
arrows.push_back(src+dst);
|
||||||
wxLogDebug("Draw arrow %s",src+dst);
|
wxLogDebug("Draw arrow %s",src+dst);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(std::count(gs.squares_hl.begin(), gs.squares_hl.end(), src)){
|
if(std::count(squares_hl.begin(), squares_hl.end(), src)){
|
||||||
gs.squares_hl.erase(std::remove(gs.squares_hl.begin(), gs.squares_hl.end(), src), gs.squares_hl.end());
|
squares_hl.erase(std::remove(squares_hl.begin(), squares_hl.end(), src), squares_hl.end());
|
||||||
}else{
|
}else{
|
||||||
gs.squares_hl.push_back(src);
|
squares_hl.push_back(src);
|
||||||
wxLogDebug("Highlight square %s",src);
|
wxLogDebug("Highlight square %s",src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (is_dragging) {
|
|
||||||
is_dragging = false;
|
|
||||||
valid_drag = false;
|
|
||||||
// Handle drop
|
|
||||||
REFRESH_MOUSE_LOCATION();
|
|
||||||
INIT_CURRENT_SQUARE();
|
|
||||||
|
|
||||||
if (IsCurrentSquareValid) {
|
|
||||||
wxLogDebug("Drag end on square (%d,%d)", file, rank);
|
|
||||||
/// Play the move
|
|
||||||
wxCommandEvent event(PLAY_MOVE_EVENT, GetId());
|
|
||||||
event.SetEventObject(this);
|
|
||||||
std::string move = ((char)('a' + active_square.x)) +
|
|
||||||
std::to_string(+active_square.y + 1) +
|
|
||||||
((char)('a' + file)) + std::to_string(rank + 1);
|
|
||||||
event.SetString(move);
|
|
||||||
ProcessEvent(event);
|
|
||||||
} else {
|
|
||||||
// If square not valid just redraw (place piece back to its square)
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event.LeftDown() || event.RightDown()) {
|
|
||||||
SetFocus();
|
|
||||||
REFRESH_MOUSE_LOCATION();
|
|
||||||
lastClickX = mouseX;
|
|
||||||
lastClickY = mouseY;
|
|
||||||
INIT_CURRENT_SQUARE();
|
|
||||||
if (IsCurrentSquareValid) {
|
|
||||||
active_square.x = file;
|
|
||||||
active_square.y = rank;
|
|
||||||
if(event.LeftDown()){
|
|
||||||
if (gs.board[(7 - rank) * 8 + file] != ' ') {
|
|
||||||
wxLogDebug("Drag start on square (%d,%d)", file, rank);
|
|
||||||
valid_drag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
wxLogDebug("Arrow start on square (%d,%d)", file, rank);
|
|
||||||
valid_arrow = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(event.LeftUp()){
|
|
||||||
gs.arrows.clear();
|
|
||||||
gs.squares_hl.clear();
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
// In any right up, reset dragging variables
|
||||||
// Let GameTableLeftPanel process mouse wheel events:
|
is_dragging = false;
|
||||||
if (event.GetWheelRotation() != 0) {
|
arrow_drag = false;
|
||||||
event.ResumePropagation(1);event.Skip();
|
} else {
|
||||||
|
// Let GameTableLeftPanel process mouse wheel events:
|
||||||
|
if (event.GetWheelRotation() != 0) {
|
||||||
|
event.ResumePropagation(1);event.Skip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,12 +78,13 @@ class BoardCanvas : public wxPanel {
|
||||||
Theme *t, *t_captures;
|
Theme *t, *t_captures;
|
||||||
wxColour color_arrows;
|
wxColour color_arrows;
|
||||||
int arrows_offset;
|
int arrows_offset;
|
||||||
// Board to draw (char version)
|
|
||||||
std::string board;
|
|
||||||
std::string white_player,black_player;
|
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
|
// Various canvas state variables
|
||||||
bool black_side, is_dragging, valid_drag, valid_arrow, is_black_turn;
|
bool black_side, is_dragging, valid_drag, arrow_drag, is_black_turn;
|
||||||
std::uint32_t boardX, boardY, square_width, piece_width, mouseX, mouseY, lastClickX,
|
std::uint32_t boardX, boardY, square_width, piece_width, mouseX, mouseY, lastClickX,
|
||||||
lastClickY;
|
lastClickY;
|
||||||
wxSize canvas_size;
|
wxSize canvas_size;
|
||||||
|
|
Loading…
Add table
Reference in a new issue