Subversion Repositories Games.Chess Giants

Rev

Rev 124 | Rev 136 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
// window_main.cpp
2
 
3
#include "../common.h"
4
 
5
 
21 pmbaty 6
// global variables used in this module only
7
static wchar_t folder_path[MAX_PATH];
8
 
9
 
1 pmbaty 10
// prototypes of local functions
11
static bool Button_IsHovered (guibutton_t *button, int gui_x, int gui_y);
12
static bool Button_UpdateHoverState (guibutton_t *button, int gui_x, int gui_y);
13
 
14
 
15
LRESULT CALLBACK WindowProc_Main (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam)
16
{
17
   // this is the main message handler for the program
18
 
19
   static wchar_t fen_string[128];
20
   static char selectable_parts[14] = "PRNBQK kqbnrp";
21
   static int prevgui_x = 0;
22
   static int prevgui_y = 0;
3 pmbaty 23
   static bool ctrl_pressed = false;
1 pmbaty 24
   static bool rbutton_pushed = false;
25
 
26
   unsigned short wParam_hiword;
27
   unsigned short wParam_loword;
28
   int prev_hovered_position[2];
29
   player_t *current_player;
30
   player_t *opposite_player;
31
   player_t *local_player;
32
   player_t *remote_player;
33
   ccreply_t *entered_ccreply;
34
   boardmove_t *current_move;
35
   float board_x;
36
   float board_y;
37
   int gui_x;
38
   int gui_y;
39
   int line;
40
   int column;
41
   int index_line;
42
   int index_column;
43
   int part_index;
44
   int part_color;
24 pmbaty 45
   int viewer_index;
124 pmbaty 46
   RECT rect;
1 pmbaty 47
 
48
   // filter out the commonly used message values
49
   wParam_hiword = HIWORD (wParam);
50
   wParam_loword = LOWORD (wParam);
51
 
124 pmbaty 52
   // get current and opposite players and see if we're online
53
   current_player = Player_GetCurrent ();
54
   opposite_player = Player_GetOpposite ();
55
   remote_player = Player_FindByType (PLAYER_INTERNET);
56
 
1 pmbaty 57
   ////////////////////////////////////////////////////////////////////////////////////////////////
58
   // has the window just been fired up ?
59
   if (message == WM_CREATE)
60
   {
61
      the_scene.gui.is_entering_text = false; // we are NOT entering text yet
62
 
63
      // call the default window message processing function to keep things going
64
      return (DefWindowProc (hWnd, message, wParam, lParam));
65
   }
66
 
67
   ////////////////////////////////////////////////////////////////////////////////////////////////
124 pmbaty 68
   // else is the window being resized ?
69
   else if ((message == WM_SIZE) || (message == WM_WINDOWPOSCHANGED))
70
   {
71
      GetWindowRect (hMainWnd, &rect); // grab the current window size and update the options accordingly
72
      options.want_maximized = (rect.right - rect.left > GetSystemMetrics (SM_CXMAXIMIZED) * 90 / 100) && (rect.bottom - rect.top > GetSystemMetrics (SM_CYMAXIMIZED) * 80 / 100);
73
      if (!options.want_maximized)
74
      {
75
         options.window_width = max (rect.right - rect.left, 640); // min window width
76
         options.window_height = max (rect.bottom - rect.top, 480); // min window height (only save them when the window is not maximized)
77
      }
78
 
79
      return (0); // don't let Windows do the default processing on this message
80
   }
81
 
82
   ////////////////////////////////////////////////////////////////////////////////////////////////
1 pmbaty 83
   // else have we clicked on the close button ?
84
   else if (message == WM_CLOSE)
85
   {
124 pmbaty 86
      if ((the_board.game_state == STATE_PLAYING) && ((the_board.move_count > 1) || (remote_player != NULL)))
119 pmbaty 87
         DialogBox_Quit (); // if a game has started OR if we are online against somebody, ask for confirmation
1 pmbaty 88
      else
89
         is_dialogbox_quit_validated = true; // if game hasn't started yet, quit without question
90
 
91
      return (0); // don't let Windows do the default processing on this message
92
   }
93
 
94
   ////////////////////////////////////////////////////////////////////////////////////////////////
95
   // else is the user closing its session OR the window is being destroyed ?
96
   else if ((message == WM_QUERYENDSESSION) || (message == WM_ENDSESSION) || (message == WM_DESTROY))
97
      terminate_everything = true; // suicide (for some reason, PostQuitMessage() is unreliable !?)
98
 
21 pmbaty 99
   /////////////////
100
   // MENU EVENTS //
101
   /////////////////
102
 
103
   ///////////////
104
   // menu command
1 pmbaty 105
   else if (message == WM_COMMAND)
106
   {
124 pmbaty 107
      // ANY menu choice makes the "new game" / "open game" front GUI button disappear
108
      GUIBUTTON_DISABLE (the_scene.gui.newgamebutton);
109
      GUIBUTTON_DISABLE (the_scene.gui.opengamebutton);
110
 
1 pmbaty 111
      // game menu, new game
112
      if (wParam_loword == MENUID_GAME_NEWGAME)
113
      {
114
         if ((the_board.game_state == STATE_PLAYING) && (the_board.move_count > 1))
115
            DialogBox_Resign (); // if a game is playing, ask to resign first
116
         else
117
            DialogBox_NewGame (); // game not started yet, show the new game dialog box
118
      }
119
 
120
      // game menu, setup start position
121
      else if (wParam_loword == MENUID_GAME_SETUPPOSITION)
122
      {
123
         if ((the_board.game_state == STATE_PLAYING) && (the_board.move_count > 1))
124
            DialogBox_Resign (); // if a game is playing, ask to resign first
125
         else
126
         {
127
            current_move = &the_board.moves[0]; // quick access to start move
128
            memset (&current_move->slots, 0, sizeof (current_move->slots)); // erase all slots
129
 
130
            the_board.game_state = STATE_SETUPPOSITION; // game not started yet, enter board setup mode
131
            the_board.reevaluate = true; // evaluate board again
132
 
133
            // display the "please choose start position" phrase in the middle of the screen
134
            Scene_SetText (&the_scene.gui.central_text, 50.0f, 50.0f, -1, ALIGN_CENTER, ALIGN_CENTER, ALIGN_CENTER, centermsg_fontindex, RGBA_TO_RGBACOLOR (255, 255, 255, 191),
135
                           999999.0f, true, LOCALIZE (L"SetupMode"));
136
            the_scene.gui.partspick_selectedpart = ' '; // no selected part yet
137
            the_scene.update = true; // and update the 3D scene
138
         }
139
      }
140
 
141
      // game menu, load game
142
      else if (wParam_loword == MENUID_GAME_LOAD)
143
         DialogBox_Load (); // fire up the load dialog box
144
 
145
      // game menu, save game
146
      else if (wParam_loword == MENUID_GAME_SAVE)
147
      {
148
         if (save_pathname[0] != 0)
149
            is_dialogbox_save_validated = true; // if the filename is known, save it directly
150
         else
119 pmbaty 151
            DialogBox_Save (false); // else fire up the save dialog box
1 pmbaty 152
      }
153
 
154
      // game menu, save as
155
      else if (wParam_loword == MENUID_GAME_SAVEAS)
119 pmbaty 156
         DialogBox_Save (false); // fire up the save dialog box
1 pmbaty 157
 
158
      // game menu, save position as
159
      else if (wParam_loword == MENUID_GAME_SAVEPOSITIONAS)
160
         DialogBox_SavePosition (); // fire up the save position dialog box
161
 
75 pmbaty 162
      // game menu, pause
163
      else if (wParam_loword == MENUID_GAME_PAUSE)
164
      {
165
         is_paused ^= true; // toggle game pause state on/off
166
         CheckMenuItem (GetMenu (hWnd), MENUID_GAME_PAUSE, (is_paused ? MF_CHECKED : MF_UNCHECKED)); // highlight the menu entry as necessary
167
         the_board.reevaluate = true; // evaluate board again
168
      }
169
 
1 pmbaty 170
      // game menu, resign
171
      else if (wParam_loword == MENUID_GAME_RESIGN)
172
         DialogBox_Resign (); // if a game has started, ask for confirmation
173
 
174
      // game menu, statistics (stats are only available in online mode)
175
      else if (wParam_loword == MENUID_GAME_STATISTICS)
176
      {
177
         local_player = Player_FindByType (PLAYER_HUMAN);
178
         if (local_player != NULL)
179
            PlayerCard_FindOrCreate (local_player->name); // display player's own player card
180
      }
181
 
182
      // game menu, options
183
      else if (wParam_loword == MENUID_GAME_OPTIONS)
184
         DialogBox_Options (); // fire up the options dialog box
185
 
186
      // game menu, quit
187
      else if (wParam_loword == MENUID_GAME_QUIT)
188
      {
124 pmbaty 189
         if ((the_board.game_state == STATE_PLAYING) && ((the_board.move_count > 1) || (remote_player != NULL)))
119 pmbaty 190
            DialogBox_Quit (); // if a game has started OR if we are online against somebody, ask for confirmation
1 pmbaty 191
         else
192
            is_dialogbox_quit_validated = true; // if game hasn't started yet, quit without question
193
      }
194
 
195
      // chessboard menu, suggest move
196
      else if (wParam_loword == MENUID_CHESSBOARD_SUGGESTMOVE)
197
         the_board.players[current_viewer].wants_hint = true; // remember this player wants a hint
198
 
199
      // chessboard menu, cancel last move
200
      else if (wParam_loword == MENUID_CHESSBOARD_CANCELLASTMOVE)
201
         the_board.players[current_viewer].wants_cancel = true; // remember this player wants to cancel his last move
202
 
203
      // chessboard menu, comment move
204
      else if (wParam_loword == MENUID_CHESSBOARD_COMMENTMOVE)
205
         DialogBox_Comment (); // fire up the comment dialog box
206
 
207
      // chessboard menu, go to move
208
      else if (wParam_loword == MENUID_CHESSBOARD_GOTOMOVE)
209
         DialogBox_GoToMove (); // fire up the go to move dialog box
210
 
211
      // chessboard menu, swap sides
212
      else if (wParam_loword == MENUID_CHESSBOARD_SWAPSIDES)
213
         the_board.want_playerswap = true; // remember board sides are to be swapped
214
 
75 pmbaty 215
      // chessboard menu, rename players
216
      else if (wParam_loword == MENUID_CHESSBOARD_RENAMESIDES)
217
         DialogBox_RenameSides(); // fire up the rename sides dialog box
218
 
1 pmbaty 219
      // chessboard menu, beginning of game
220
      else if (wParam_loword == MENUID_CHESSBOARD_BEGINNINGOFGAME)
221
      {
222
         the_board.viewed_move = 0; // enter view mode and go to the beginning of the game
116 pmbaty 223
         Audio_PlaySound (SOUNDTYPE_CLICK, 0.0f, 0.0f, 0.04f); // make a click sound at the center of the board
1 pmbaty 224
         the_board.reevaluate = true; // evaluate board again
225
      }
226
 
227
      // chessboard menu, previous move (only if arrow is enabled)
228
      else if ((wParam_loword == MENUID_CHESSBOARD_PREVIOUSMOVE) && (the_scene.gui.larrow.state != 0))
229
      {
230
         the_board.viewed_move--; // enter view mode and go back one move
116 pmbaty 231
         Audio_PlaySound (SOUNDTYPE_CLICK, 0.0f, 0.0f, 0.04f); // make a click sound at the center of the board
1 pmbaty 232
         the_board.reevaluate = true; // evaluate board again
233
      }
234
 
235
      // chessboard menu, next move (only if arrow is enabled)
236
      else if ((wParam_loword == MENUID_CHESSBOARD_NEXTMOVE) && (the_scene.gui.rarrow.state != 0))
237
      {
238
         the_board.viewed_move++; // enter view mode and go forward one move
116 pmbaty 239
         Audio_PlaySound (SOUNDTYPE_CLICK, 0.0f, 0.0f, 0.04f); // make a click sound at the center of the board
1 pmbaty 240
         the_board.reevaluate = true; // evaluate board again
241
      }
242
 
243
      // chessboard menu, current state of game
244
      else if (wParam_loword == MENUID_CHESSBOARD_CURRENTSTATEOFGAME)
245
      {
246
         the_board.viewed_move = the_board.move_count - 1; // enter view mode and go to the current state of the game
116 pmbaty 247
         Audio_PlaySound (SOUNDTYPE_CLICK, 0.0f, 0.0f, 0.04f); // make a click sound at the center of the board
1 pmbaty 248
         the_board.reevaluate = true; // evaluate board again
249
      }
250
 
251
      // chessboard menu, top view
252
      else if (wParam_loword == MENUID_CHESSBOARD_TOPVIEW)
253
      {
24 pmbaty 254
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
255
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
256
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
257
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
258
                || (viewer_index == current_viewer))
259
            {
25 pmbaty 260
               the_board.players[viewer_index].view_pitch = 89.99f;
24 pmbaty 261
               the_board.players[viewer_index].view_yaw = (current_viewer == COLOR_BLACK ? 90.0f : -90.0f);
262
               the_board.players[viewer_index].view_distance = 58.0f;
263
            }
1 pmbaty 264
      }
265
 
266
      // chessboard menu, default view
267
      else if (wParam_loword == MENUID_CHESSBOARD_DEFAULTVIEW)
268
      {
24 pmbaty 269
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
270
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
271
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
272
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
273
                || (viewer_index == current_viewer))
274
            {
275
               the_board.players[viewer_index].view_pitch = 55.0f;
276
               the_board.players[viewer_index].view_yaw = (current_viewer == COLOR_BLACK ? 90.0f : -90.0f);
277
               the_board.players[viewer_index].view_distance = 70.0f;
278
            }
1 pmbaty 279
      }
280
 
281
      // chessboard menu, reset view
282
      else if (wParam_loword == MENUID_CHESSBOARD_RESETVIEW)
283
      {
24 pmbaty 284
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
285
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
286
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
287
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
288
                || (viewer_index == current_viewer))
289
            {
290
               the_board.players[viewer_index].view_pitch = the_board.players[current_viewer].custom_pitch;
291
               the_board.players[viewer_index].view_yaw = the_board.players[current_viewer].custom_yaw;
292
               the_board.players[viewer_index].view_distance = the_board.players[current_viewer].custom_distance;
293
            }
1 pmbaty 294
      }
295
 
296
      // chessboard menu, zoom in
297
      else if (wParam_loword == MENUID_CHESSBOARD_ZOOMIN)
298
      {
299
         // scroll up & save this as the new custom distance
300
         the_board.players[current_viewer].view_distance = max (48.0f, the_board.players[current_viewer].view_distance - 2.0f);
301
         the_board.players[current_viewer].custom_distance = the_board.players[current_viewer].view_distance;
302
         the_scene.update = true; // update the 3D scene
303
      }
304
 
305
      // chessboard menu, zoom out
306
      else if (wParam_loword == MENUID_CHESSBOARD_ZOOMOUT)
307
      {
308
         // scroll down & save this as the new custom distance
309
         the_board.players[current_viewer].view_distance = min (100.0f, the_board.players[current_viewer].view_distance + 2.0f);
310
         the_board.players[current_viewer].custom_distance = the_board.players[current_viewer].view_distance;
311
         the_scene.update = true; // update the 3D scene
312
      }
313
 
314
      // chessboard menu, change appearance
315
      else if (wParam_loword == MENUID_CHESSBOARD_CHANGEAPPEARANCE)
316
         DialogBox_ChangeAppearance ();
317
 
318
      // chessboard menu, display windows desktop
319
      else if (wParam_loword == MENUID_CHESSBOARD_DISPLAYWINDOWSDESKTOP)
320
         ShowWindow (hWnd, SW_MINIMIZE);
321
 
322
      // internet menu, show online players
323
      else if (wParam_loword == MENUID_INTERNET_SHOWONLINEPLAYERS)
324
         Window_Opponents ();
325
 
326
      // internet menu, show sought games
327
      else if (wParam_loword == MENUID_INTERNET_SHOWSOUGHTGAMES)
328
         Window_Sought ();
329
 
330
      // internet menu, seek game
331
      else if (wParam_loword == MENUID_INTERNET_SEEKGAME)
332
         DialogBox_SendSeek ();
333
 
334
      // internet menu, chatter channels
335
      else if (wParam_loword == MENUID_INTERNET_CHATTERCHANNELS)
336
         Window_ChatterChannels ();
337
 
338
      // internet menu, enter chat text
339
      else if (wParam_loword == MENUID_INTERNET_ENTERCHATTEXT)
340
         PostMessage (hWnd, WM_CHAR, L' ', 0); // emulate a space bar hit
341
 
342
      // internet menu, display player card
343
      else if (wParam_loword == MENUID_INTERNET_DISPLAYPLAYERCARD)
344
         DialogBox_PlayerInfoName ();
345
 
346
      // internet menu, display your card
347
      else if (wParam_loword == MENUID_INTERNET_DISPLAYYOURCARD)
348
      {
349
         local_player = Player_FindByType (PLAYER_HUMAN);
350
         if (local_player != NULL)
351
            PlayerCard_FindOrCreate (local_player->name); // display player's own player card
352
      }
353
 
354
      // internet menu, MOTD
355
      else if (wParam_loword == MENUID_INTERNET_MOTD)
356
         Window_MOTD ();
357
 
358
      // help menu, help
359
      else if (wParam_loword == MENUID_HELP_HELP)
29 pmbaty 360
      {
59 pmbaty 361
         swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\Chess Giants (%s).html", app_path, languages[language_id].name);
362
         if (_waccess (folder_path, 0) != 0)
363
            swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\Chess Giants (English).html", app_path);
29 pmbaty 364
         ShellExecute (NULL, L"open", folder_path, NULL, NULL, SW_MAXIMIZE); // fire up the help file
365
      }
1 pmbaty 366
 
367
      // help menu, get chess games
368
      else if (wParam_loword == MENUID_HELP_GETCHESSGAMES)
369
         ShellExecute (NULL, L"open", L"http://www.chessgames.com", NULL, NULL, SW_MAXIMIZE); // fire up the browser
370
 
21 pmbaty 371
      // help menu, add/modify visual themes
372
      else if (wParam_loword == MENUID_HELP_ADDMODIFYVISUALTHEMES)
373
      {
374
         swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\themes", app_path);
375
         ShellExecute (NULL, L"open", folder_path, NULL, NULL, SW_SHOWNORMAL); // fire up Windows Explorer
376
      }
377
 
50 pmbaty 378
      // help menu, add/modify engines
379
      else if (wParam_loword == MENUID_HELP_ADDMODIFYENGINES)
380
      {
381
         swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\engines", app_path);
382
         ShellExecute (NULL, L"open", folder_path, NULL, NULL, SW_SHOWNORMAL); // fire up Windows Explorer
383
      }
384
 
21 pmbaty 385
      // help menu, add/modify translations
386
      else if (wParam_loword == MENUID_HELP_ADDMODIFYTRANSLATIONS)
387
      {
388
         swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\data\\languages", app_path);
389
         ShellExecute (NULL, L"open", folder_path, NULL, NULL, SW_SHOWNORMAL); // fire up Windows Explorer
390
      }
391
 
1 pmbaty 392
      // help menu, about
393
      else if (wParam_loword == MENUID_HELP_ABOUT)
394
         DialogBox_About (); // show the About dialog box
395
 
396
      // call the default window message processing function to keep things going
397
      return (DefWindowProc (hWnd, message, wParam, lParam));
398
   }
399
 
3 pmbaty 400
   /////////////////////////////////////////////////////
401
   // ctrl key press or release (while not in animation)
402
   else if ((message == WM_KEYDOWN) && (wParam == VK_CONTROL) && (animation_endtime + 1.0f < current_time))
403
   {
404
      ctrl_pressed = true; // remember the ctrl key is pressed
405
 
406
      // call the default window message processing function to keep things going
407
      return (DefWindowProc (hWnd, message, wParam, lParam));
408
   }
409
   else if ((message == WM_KEYUP) && (wParam == VK_CONTROL) && (animation_endtime + 1.0f < current_time))
410
   {
411
      ctrl_pressed = false; // remember the ctrl key is released
412
      rbutton_pushed = false; // remember button is released
413
      the_scene.update = true; // update the 3D scene
414
 
415
      // call the default window message processing function to keep things going
416
      return (DefWindowProc (hWnd, message, wParam, lParam));
417
   }
418
 
21 pmbaty 419
   //////////////////
420
   // MOUSE EVENTS //
421
   //////////////////
422
 
1 pmbaty 423
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 424
   // left mouse button push
425
   else if (message == WM_LBUTTONDOWN)
3 pmbaty 426
   {
21 pmbaty 427
      // are we in animation OR are mouse commands NOT allowed ?
428
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
429
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
430
 
124 pmbaty 431
      // are we in board closeup mode OR are we online AND do we NOT have the right to select anything ?
432
      if (((current_distance == CLOSEUP_VIEW_DISTANCE) && (current_pitch == CLOSEUP_VIEW_PITCH))
433
          || ((remote_player != NULL) && !remote_player->is_in_game))
434
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default window message processing function to keep things going
435
 
3 pmbaty 436
      // is the ctrl key pressed (emulates a right click) ?
437
      if (ctrl_pressed)
438
      {
439
         prevgui_x = GET_X_LPARAM (lParam); // remember mouse coordinates
440
         prevgui_y = GET_Y_LPARAM (lParam);
441
 
442
         // if we click something, stop moving the table immediately
443
 
24 pmbaty 444
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
445
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
446
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
447
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
448
                || (viewer_index == current_viewer))
449
            {
450
               the_board.players[viewer_index].view_pitch = current_pitch;
451
               the_board.players[viewer_index].view_yaw = current_yaw;
452
            }
453
 
3 pmbaty 454
         rbutton_pushed = true; // remember button is clicked
455
      }
456
 
457
      // call the default window message processing function to keep things going
458
      return (DefWindowProc (hWnd, message, wParam, lParam));
459
   }
460
 
461
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 462
   // left mouse button release
463
   else if (message == WM_LBUTTONUP)
1 pmbaty 464
   {
21 pmbaty 465
      // are we in animation OR are mouse commands NOT allowed ?
466
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
467
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
468
 
3 pmbaty 469
      // is the ctrl key pressed (emulates a right click) ?
470
      if (ctrl_pressed)
471
      {
472
         rbutton_pushed = false; // remember button is released
473
         the_scene.update = true; // update the 3D scene
474
 
475
         // call the default window message processing function to keep things going
476
         return (DefWindowProc (hWnd, message, wParam, lParam));
477
      }
478
 
1 pmbaty 479
      prevgui_x = GET_X_LPARAM (lParam); // remember mouse coordinates
480
      prevgui_y = GET_Y_LPARAM (lParam);
481
 
482
      // get mouse coordinates
483
      gui_x = GET_X_LPARAM (lParam);
484
      gui_y = GET_Y_LPARAM (lParam);
485
 
124 pmbaty 486
      // is the "new game" button displayed AND is the mouse hovering it ?
487
      if ((the_scene.gui.newgamebutton.state != 0) && Button_IsHovered (&the_scene.gui.newgamebutton, gui_x, gui_y))
488
      {
489
         GUIBUTTON_DISABLE (the_scene.gui.newgamebutton); // hide the "new game" button
490
         GUIBUTTON_DISABLE (the_scene.gui.opengamebutton); // hide the "open game" button
491
         DialogBox_NewGame (); // fire up the "new game" dialog box
492
      }
1 pmbaty 493
 
124 pmbaty 494
      // is the "open game" button displayed AND is the mouse hovering it ?
495
      if ((the_scene.gui.opengamebutton.state != 0) && Button_IsHovered (&the_scene.gui.opengamebutton, gui_x, gui_y))
496
      {
497
         GUIBUTTON_DISABLE (the_scene.gui.newgamebutton); // hide the "new game" button
498
         GUIBUTTON_DISABLE (the_scene.gui.opengamebutton); // hide the "open game" button
499
         DialogBox_Load (); // fire up the "open game" dialog box
500
      }
1 pmbaty 501
 
502
      // is the chat button displayed AND is the mouse hovering it ?
503
      if ((the_scene.gui.chatbutton.state != 0) && Button_IsHovered (&the_scene.gui.chatbutton, gui_x, gui_y))
504
      {
505
         // find or create the corresponding interlocutor structure and fire it up
124 pmbaty 506
         if (remote_player != NULL)
507
            Interlocutor_FindOrCreate (remote_player->name);
1 pmbaty 508
      }
509
 
510
      // is the games button displayed AND is the mouse hovering it ?
511
      if ((the_scene.gui.gamesbutton.state != 0) && Button_IsHovered (&the_scene.gui.gamesbutton, gui_x, gui_y))
512
         Window_Sought (); // if so, display the sought games window
513
 
514
      // is the people button displayed AND is the mouse hovering it ?
515
      if ((the_scene.gui.peoplebutton.state != 0) && Button_IsHovered (&the_scene.gui.peoplebutton, gui_x, gui_y))
516
         Window_Opponents (); // if so, display the opponents window
517
 
124 pmbaty 518
      // are we in board closeup mode OR are we online AND do we NOT have the right to select anything ?
519
      if (((current_distance == CLOSEUP_VIEW_DISTANCE) && (current_pitch == CLOSEUP_VIEW_PITCH))
520
          || ((remote_player != NULL) && !remote_player->is_in_game))
521
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default window message processing function to keep things going
522
 
523
      // is the left arrow displayed AND is the mouse hovering it ?
524
      if ((the_scene.gui.larrow.state != 0) && Button_IsHovered (&the_scene.gui.larrow, gui_x, gui_y))
525
         SendMessage (hWnd, WM_COMMAND, MENUID_CHESSBOARD_PREVIOUSMOVE, NULL); // send a "previous move" event
526
 
527
      // is the right arrow displayed AND is the mouse hovering it ?
528
      if ((the_scene.gui.rarrow.state != 0) && Button_IsHovered (&the_scene.gui.rarrow, gui_x, gui_y))
529
         SendMessage (hWnd, WM_COMMAND, MENUID_CHESSBOARD_NEXTMOVE, NULL); // send a "next move" event
530
 
1 pmbaty 531
      // is the parts selection line displayed AND is the mouse anywhere near it ?
532
      if (the_scene.gui.is_partspick_displayed && Render_IsMouseInBox (gui_x, gui_y, 0.0f, 0.0f, 100.0f, 11.0f))
533
      {
534
         // for each selectable part, if the mouse is on it, mark it as selected
535
         for (part_index = 0; part_index < 13; part_index++)
536
            if (Render_IsMouseInBox (gui_x, gui_y, part_index * (100.0f / 13.0f), 0, 100.0f / 13.0f, 11.0f))
537
            {
538
               the_scene.gui.partspick_selectedpart = selectable_parts[part_index]; // mark it as selected
116 pmbaty 539
               Audio_PlaySound (SOUNDTYPE_CLICK, 0.0f, 0.0f, 0.04f); // make a click sound at the center of the board
1 pmbaty 540
               break; // no need to search further if one selection was found
541
            }
542
      }
543
 
544
      // if we are not allowed to select anything, don't even try
75 pmbaty 545
      if (is_paused || (current_player->type != PLAYER_HUMAN) || (the_board.viewed_move != the_board.move_count - 1)
1 pmbaty 546
          || ((remote_player != NULL) && !remote_player->is_in_game))
547
      {
548
         the_scene.update = true; // update the 3D scene
549
 
550
         // call the default window message processing function to keep things going
551
         return (DefWindowProc (hWnd, message, wParam, lParam));
552
      }
553
 
554
      // it's a single click. The user clicked on a square.
555
 
556
      // figure out the coordinates on table
557
      Render_MouseToFloor (gui_x, gui_y, &board_x, &board_y);
558
 
559
      // translate them to board coordinates
560
      the_board.hovered_position[0] = (int) floor ((20.0f - board_y) / 5.0f);
561
      the_board.hovered_position[1] = 7 - (int) floor ((20.0f - board_x) / 5.0f);
562
      highlight_endtime = 0; // stop highlighting anything
563
 
564
      // if it's outside the table, end the job
565
      if (!IS_VALID_POSITION (the_board.hovered_position))
566
      {
567
         the_scene.update = true; // update the 3D scene
568
 
569
         // call the default window message processing function to keep things going
570
         return (DefWindowProc (hWnd, message, wParam, lParam));
571
      }
572
 
573
      // we clicked a valid slot on the table
574
 
575
      current_move = &the_board.moves[the_board.viewed_move]; // quick access to current move
576
 
577
      ///////////////////////////////////
578
      // are we in parts placement mode ?
579
      if (the_board.game_state == STATE_SETUPPOSITION)
580
      {
581
         // quick access to line and column
582
         line = the_board.hovered_position[0];
583
         column = the_board.hovered_position[1];
584
 
585
         // figure out the color of the part we are placing
586
         if (the_scene.gui.partspick_selectedpart == tolower (the_scene.gui.partspick_selectedpart))
587
            part_color = COLOR_BLACK; // black color
588
         else
589
            part_color = COLOR_WHITE; // white color
590
 
591
         // are we erasing a king ? if so, replace it at its default location
592
         if ((current_move->slots[line][column].part == PART_KING) && (current_move->slots[line][column].color == COLOR_BLACK)
593
             && (the_scene.gui.partspick_selectedpart != 'k'))
594
         {
595
            // is it ALREADY the king's default location ? if so, give up
596
            if ((line == 7) && (column == 4))
597
            {
116 pmbaty 598
               Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f); // play the "illegal move" sound
1 pmbaty 599
               return (DefWindowProc (hWnd, message, wParam, lParam)); // call the default window message proc
600
            }
601
 
602
            Move_SetSlot (current_move, 7, 4, COLOR_BLACK, PART_KING); // replace black king
603
         }
604
         else if ((current_move->slots[line][column].part == PART_KING) && (current_move->slots[line][column].color == COLOR_WHITE)
605
                  && (the_scene.gui.partspick_selectedpart != 'K'))
606
         {
607
            // is it ALREADY the king's default location ? if so, give up
608
            if ((line == 0) && (column == 4))
609
            {
116 pmbaty 610
               Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f); // play the "illegal move" sound
1 pmbaty 611
               return (DefWindowProc (hWnd, message, wParam, lParam)); // call the default window message proc
612
            }
613
 
614
            Move_SetSlot (current_move, 0, 4, COLOR_WHITE, PART_KING); // replace white king
615
         }
616
 
617
         // place the selected part on the board
618
         if (tolower (the_scene.gui.partspick_selectedpart) == 'p')
619
            Move_SetSlot (current_move, line, column, part_color, PART_PAWN); // pawn
620
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'r')
621
            Move_SetSlot (current_move, line, column, part_color, PART_ROOK); // rook
622
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'n')
623
            Move_SetSlot (current_move, line, column, part_color, PART_KNIGHT); // knight
624
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'b')
625
            Move_SetSlot (current_move, line, column, part_color, PART_BISHOP); // bishop
626
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'q')
627
            Move_SetSlot (current_move, line, column, part_color, PART_QUEEN); // queen
628
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'k')
629
         {
630
            // parse the board for other kings of the same color and erase them
631
            for (index_line = 0; index_line < 8; index_line++)
632
               for (index_column = 0; index_column < 8; index_column++)
633
                  if ((current_move->slots[index_line][index_column].color == part_color)
634
                      && (current_move->slots[index_line][index_column].part == PART_KING))
635
                     memset (&current_move->slots[index_line][index_column], 0, sizeof (boardslot_t)); // erase this slot
636
 
637
            Move_SetSlot (current_move, line, column, part_color, PART_KING); // king
638
         }
639
         else
640
            Move_SetSlot (current_move, line, column, 0, PART_NONE); // no part
641
 
642
         // figure out which sound to play
643
         if (the_scene.gui.partspick_selectedpart != ' ')
116 pmbaty 644
            Audio_PlaySound (SOUNDTYPE_MOVE, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f); // play a move sound when placing a part
1 pmbaty 645
 
646
         the_scene.update = true; // update the 3D scene
647
 
648
         // call the default window message processing function to keep things going
649
         return (DefWindowProc (hWnd, message, wParam, lParam));
650
      }
651
      // end of parts placement mode
652
      //////////////////////////////
653
 
654
      // does a selection NOT exist yet ?
655
      if (!IS_VALID_POSITION (the_board.selected_position))
656
      {
657
         // is there a selectable part at this location ?
658
         if ((current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].part != PART_NONE)
659
            && (current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].color == Board_ColorToMove (&the_board)))
660
         {
661
            // mark the selected position as selected (and remember it)
662
            the_board.selected_position[0] = the_board.hovered_position[0];
663
            the_board.selected_position[1] = the_board.hovered_position[1];
664
         }
665
 
666
         the_scene.update = true; // update the 3D scene
667
 
668
         // call the default window message processing function to keep things going
669
         return (DefWindowProc (hWnd, message, wParam, lParam));
670
      }
671
 
672
      // a selection exists already
673
 
674
      // is it the slot that was previously selected ? (i.e, user wants to "unselect" it)
675
      if ((the_board.hovered_position[0] == the_board.selected_position[0]) && (the_board.hovered_position[1] == the_board.selected_position[1]))
676
      {
677
         // forget the selected position
678
         the_board.selected_position[0] = -1;
679
         the_board.selected_position[1] = -1;
680
 
681
         the_scene.update = true; // update the 3D scene
682
 
683
         // call the default window message processing function to keep things going
684
         return (DefWindowProc (hWnd, message, wParam, lParam));
685
      }
686
 
687
      // else is it another part of the same color ? (i.e, user wants to change the part he selected)
688
      else if ((current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].part != PART_NONE)
689
               && (current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].color == Board_ColorToMove (&the_board)))
690
      {
691
         // mark the selected position as selected (and remember it)
692
         the_board.selected_position[0] = the_board.hovered_position[0];
693
         the_board.selected_position[1] = the_board.hovered_position[1];
694
 
695
         the_scene.update = true; // update the 3D scene
696
 
697
         // call the default window message processing function to keep things going
698
         return (DefWindowProc (hWnd, message, wParam, lParam));
699
      }
700
 
701
      // else is it a possible move ?
702
      else if ((current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].flags & FLAG_POSSIBLEMOVE)
703
               || (current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].flags & FLAG_TAKEABLE))
704
      {
705
         // are we in check after the move ? (FIXME: call EP version of this func for en passant moves)
706
         if (Move_IsColorInCheckAfterTestMove (current_move, the_board.selected_position[0], the_board.selected_position[1], the_board.hovered_position[0], the_board.hovered_position[1], Board_ColorToMove (&the_board)))
707
         {
116 pmbaty 708
            Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE, 17.5f - (7 - the_board.hovered_position[1]) * 5.0f, 17.5f - the_board.hovered_position[0] * 5.0f, 0.04f); // play the "illegal move" sound
1 pmbaty 709
 
710
            the_scene.update = true; // update the 3D scene
711
 
712
            // call the default window message processing function to keep things going
713
            return (DefWindowProc (hWnd, message, wParam, lParam));
714
         }
715
 
716
         ////////////////////
717
         // movement is valid
718
 
719
         // do it
720
         Board_AppendMove (&the_board, the_board.selected_position[0], the_board.selected_position[1], the_board.hovered_position[0], the_board.hovered_position[1], PART_NONE, NULL);
721
         current_move = &the_board.moves[the_board.move_count - 1]; // update current move pointer
722
 
723
         // are we in internet mode ?
724
         if (remote_player != NULL)
725
            the_board.reevaluate = false; // if so, don't reevaluate the board yet, let the server do it
726
 
727
         // was it a pawn being promoted ? if so, display the dialog box and wait for the reply
728
         if ((current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].part == PART_PAWN)
729
             && ((the_board.hovered_position[0] == 0) || (the_board.hovered_position[0] == 7)))
730
            DialogBox_PawnPromotion (); // display the pawn promotion dialog box
731
 
732
         // else it was a normal move
733
         else
734
         {
735
            Board_SetSelectedAndHovered (&the_board, -1, -1, -1, -1); // forget the hovered and selected positions
736
            the_board.has_playerchanged = true; // and switch players
737
         }
738
 
739
         the_scene.update = true; // update the 3D scene
740
         animation_endtime = current_time + ANIMATION_DURATION; // play animation now
741
 
742
         // call the default window message processing function to keep things going
743
         return (DefWindowProc (hWnd, message, wParam, lParam));
744
      }
745
 
746
      // else it's another location
747
 
116 pmbaty 748
      Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE, 17.5f - (7 - the_board.hovered_position[1]) * 5.0f, 17.5f - the_board.hovered_position[0] * 5.0f, 0.04f); // play the "illegal move" sound
1 pmbaty 749
 
750
      the_scene.update = true; // update the 3D scene
751
 
752
      // call the default window message processing function to keep things going
753
      return (DefWindowProc (hWnd, message, wParam, lParam));
754
   }
755
 
756
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 757
   // right mouse button push
758
   else if (message == WM_RBUTTONDOWN)
1 pmbaty 759
   {
21 pmbaty 760
      // are we in animation OR are mouse commands NOT allowed ?
761
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
762
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
763
 
1 pmbaty 764
      prevgui_x = GET_X_LPARAM (lParam); // remember mouse coordinates
765
      prevgui_y = GET_Y_LPARAM (lParam);
766
 
767
      // if we click something, stop moving the table immediately
768
 
24 pmbaty 769
      // cycle through both players and change their view angles EXCEPT the opponent if he's human
770
      for (viewer_index = 0; viewer_index < 2; viewer_index++)
771
         if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
772
               || (the_board.players[viewer_index].type == PLAYER_INTERNET)
773
               || (viewer_index == current_viewer))
774
         {
775
            the_board.players[viewer_index].view_pitch = current_pitch;
776
            the_board.players[viewer_index].view_yaw = current_yaw;
777
         }
778
 
1 pmbaty 779
      rbutton_pushed = true; // remember button is clicked
780
 
781
      // call the default window message processing function to keep things going
782
      return (DefWindowProc (hWnd, message, wParam, lParam));
783
   }
784
 
785
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 786
   // right mouse button release
787
   else if (message == WM_RBUTTONUP)
1 pmbaty 788
   {
21 pmbaty 789
      // are we in animation OR are mouse commands NOT allowed ?
790
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
791
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
792
 
1 pmbaty 793
      rbutton_pushed = false; // remember button is released
794
      the_scene.update = true; // update the 3D scene
795
 
796
      // call the default window message processing function to keep things going
797
      return (DefWindowProc (hWnd, message, wParam, lParam));
798
   }
799
 
21 pmbaty 800
   ////////////////////////////////////////////////////////////////////////////////////////////////
1 pmbaty 801
   // left mouse button DOUBLE-click
21 pmbaty 802
   else if (message == WM_LBUTTONDBLCLK)
1 pmbaty 803
   {
21 pmbaty 804
      // are we in animation OR are mouse commands NOT allowed ?
805
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
806
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
807
 
1 pmbaty 808
      // get mouse coordinates
809
      gui_x = GET_X_LPARAM (lParam);
810
      gui_y = GET_Y_LPARAM (lParam);
811
 
812
      // are we in game and did we click the move comments area ?
813
      if ((the_board.game_state >= STATE_PLAYING) && (the_board.viewed_move > 0) && Render_IsMouseInBox (gui_x, gui_y, 10.0f, 0.0f, 80.0f, 10.0f))
814
      {
815
         DialogBox_Comment (); // fire up the comment dialog box
816
         return (DefWindowProc (hWnd, message, wParam, lParam)); // call the default window message processing function to keep things going
817
      }
21 pmbaty 818
 
819
      // call the default window message processing function to keep things going
820
      return (DefWindowProc (hWnd, message, wParam, lParam));
1 pmbaty 821
   }
822
 
823
   ////////////////////////////////////////////////////////////////////////////////////////////////
824
   // mouse move (while not in animation)
21 pmbaty 825
   else if (message == WM_MOUSEMOVE)
1 pmbaty 826
   {
21 pmbaty 827
      // are we in animation OR are mouse commands NOT allowed ?
828
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
829
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
830
 
1 pmbaty 831
      // get mouse coordinates
832
      gui_x = GET_X_LPARAM (lParam);
833
      gui_y = GET_Y_LPARAM (lParam);
834
 
835
      // handle button update status
836
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.larrow, gui_x, gui_y);
837
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.rarrow, gui_x, gui_y);
124 pmbaty 838
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.newgamebutton, gui_x, gui_y);
839
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.opengamebutton, gui_x, gui_y);
1 pmbaty 840
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.chatbutton, gui_x, gui_y);
841
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.gamesbutton, gui_x, gui_y);
842
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.peoplebutton, gui_x, gui_y);
843
 
124 pmbaty 844
      // are we in board closeup mode OR are we online AND do we NOT have the right to select anything ?
845
      if (((current_distance == CLOSEUP_VIEW_DISTANCE) && (current_pitch == CLOSEUP_VIEW_PITCH))
846
          || ((remote_player != NULL) && !remote_player->is_in_game))
1 pmbaty 847
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default window message processing function to keep things going
848
 
849
      // is the parts selection line displayed AND is the mouse anywhere in it ?
850
      if (the_scene.gui.is_partspick_displayed && Render_IsMouseInBox (gui_x, gui_y, 0.0f, 0.0f, 100.0f, 11.0f))
851
      {
852
         // for each selectable part...
853
         for (part_index = 0; part_index < 13; part_index++)
854
         {
855
            // is the mouse hovering it ?
856
            if (Render_IsMouseInBox (gui_x, gui_y, part_index * (100.0f / 13.0f), 0, 100.0f / 13.0f, 11.0f))
857
            {
858
               // was it NOT hovered before ?
859
               if (the_scene.gui.partspick_hoveredpart != selectable_parts[part_index])
860
               {
861
                  the_scene.gui.partspick_hoveredpart = selectable_parts[part_index]; // mark it as hovered
862
                  the_scene.update = true; // update the scene
863
               }
864
            }
865
 
866
            // else was it hovered before ?
867
            else if (the_scene.gui.partspick_hoveredpart == selectable_parts[part_index])
868
            {
869
               the_scene.gui.partspick_hoveredpart = 0; // clear the hovered part
870
               the_scene.update = true; // update the scene
871
            }
872
         }
873
      }
874
      else
875
         the_scene.gui.partspick_hoveredpart = 0; // clear the hovered part
876
 
877
      // if right button was clicked, compute new pitch and yaw
878
      if (rbutton_pushed)
879
      {
24 pmbaty 880
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
881
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
882
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
883
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
884
                || (viewer_index == current_viewer))
885
            {
886
               the_board.players[viewer_index].view_pitch += (gui_y - prevgui_y) * 0.3f;
124 pmbaty 887
               if (the_board.players[viewer_index].view_pitch < MIN_VIEW_PITCH)
888
                  the_board.players[viewer_index].view_pitch = MIN_VIEW_PITCH; // wrap angles around so that they
889
               if (the_board.players[viewer_index].view_pitch > MAX_VIEW_PITCH)
890
                  the_board.players[viewer_index].view_pitch = MAX_VIEW_PITCH; // stay in the min-max pitch bounds
1 pmbaty 891
 
24 pmbaty 892
               the_board.players[viewer_index].view_yaw += (gui_x - prevgui_x) * 0.3f;
893
               the_board.players[viewer_index].view_yaw = WrapAngle (the_board.players[viewer_index].view_yaw);
1 pmbaty 894
 
24 pmbaty 895
               // save these as the new custom angles
896
               the_board.players[viewer_index].custom_pitch = the_board.players[viewer_index].view_pitch;
897
               the_board.players[viewer_index].custom_yaw = the_board.players[viewer_index].view_yaw;
1 pmbaty 898
 
24 pmbaty 899
               // when moving the table around, jump to ideal angles immediately
900
               current_pitch = the_board.players[viewer_index].view_pitch;
901
               current_yaw = the_board.players[viewer_index].view_yaw;
902
            }
1 pmbaty 903
 
904
         the_scene.update = true; // button was clicked, update the 3D scene
905
      }
906
 
907
      // else it's just the mouse wandering around ; have we the right to select something ?
908
      else if ((the_board.viewed_move == the_board.move_count - 1) && (current_player->type == PLAYER_HUMAN) && (highlight_endtime < current_time))
909
      {
910
         // save the old positions
911
         prev_hovered_position[0] = the_board.hovered_position[0];
912
         prev_hovered_position[1] = the_board.hovered_position[1];
913
 
914
         // figure out the coordinates on table
915
         Render_MouseToFloor (gui_x, gui_y, &board_x, &board_y);
916
 
917
         // translate them to board coordinates
918
         the_board.hovered_position[0] = (int) floor ((20.0f - board_y) / 5.0f);
919
         the_board.hovered_position[1] = 7 - (int) floor ((20.0f - board_x) / 5.0f);
920
 
921
         // do they differ from last time ?
922
         if ((the_board.hovered_position[0] != prev_hovered_position[0]) || (the_board.hovered_position[1] != prev_hovered_position[1]))
923
            the_scene.update = true; // if so, update scene
924
      }
925
 
926
      // has the user the right to leave a command AND is there no comment yet ?
927
      if ((the_board.game_state >= STATE_PLAYING) && (the_board.viewed_move > 0)
928
          && ((the_board.moves[the_board.viewed_move].comment == NULL) || (the_board.moves[the_board.viewed_move].comment[0] == 0)))
929
      {
930
         // is the mouse above the comments zone ? if so, display a dimmed hint text
931
         if (Render_IsMouseInBox (gui_x, gui_y, 30.0f, 0.0f, 40.0f, 10.0f))
932
         {
933
            if (!the_scene.gui.comment_text.is_displayed)
934
            {
935
               Scene_SetText (&the_scene.gui.comment_text, 50.0f, 5.0f, 40.0f, ALIGN_CENTER, ALIGN_CENTER, ALIGN_LEFT, chat_fontindex, RGBA_TO_RGBACOLOR (255, 255, 255, 127), 999999.0f, false, LOCALIZE (L"DoubleClickToEnterComment"));
936
               the_scene.update = true; // and update the scene
937
            }
938
         }
939
         else
940
         {
941
            if (the_scene.gui.comment_text.is_displayed)
942
            {
943
               the_scene.gui.comment_text.is_displayed = false; // if not, erase the hint text
944
               the_scene.update = true; // and update the scene
945
            }
946
         }
947
      }
948
 
949
      // remember these coordinates for next time
950
      prevgui_x = gui_x;
951
      prevgui_y = gui_y;
952
 
953
      // call the default window message processing function to keep things going
954
      return (DefWindowProc (hWnd, message, wParam, lParam));
955
   }
956
 
957
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 958
   // mouse scroll
959
   else if (message == WM_MOUSEWHEEL)
1 pmbaty 960
   {
21 pmbaty 961
      // are we in animation OR are mouse commands NOT allowed ?
962
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
963
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
964
 
124 pmbaty 965
      // are we in board closeup mode OR are we online AND do we NOT have the right to select anything ?
966
      if (((current_distance == CLOSEUP_VIEW_DISTANCE) && (current_pitch == CLOSEUP_VIEW_PITCH))
967
          || ((remote_player != NULL) && !remote_player->is_in_game))
1 pmbaty 968
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default window message processing function to keep things going
969
 
970
      // scroll up / scroll down ?
971
      if (GET_WHEEL_DELTA_WPARAM (wParam) > 0)
124 pmbaty 972
         the_board.players[current_viewer].view_distance = max (MIN_VIEW_DISTANCE, the_board.players[current_viewer].view_distance - 2.0f);
1 pmbaty 973
      else if (GET_WHEEL_DELTA_WPARAM (wParam) < 0)
124 pmbaty 974
         the_board.players[current_viewer].view_distance = min (MAX_VIEW_DISTANCE, the_board.players[current_viewer].view_distance + 2.0f);
1 pmbaty 975
 
976
      // save this as the new custom distance
977
      the_board.players[current_viewer].custom_distance = the_board.players[current_viewer].view_distance;
978
 
979
      // when moving the table around, jump to ideal angles immediately
980
      current_distance = the_board.players[current_viewer].view_distance;
981
 
982
      the_scene.update = true; // update the 3D scene
983
 
984
      // call the default window message processing function to keep things going
985
      return (DefWindowProc (hWnd, message, wParam, lParam));
986
   }
987
 
988
   ////////////////////////////////////////////////////////////////////////////////////////////////
989
   // keyboard release
990
   else if (message == WM_CHAR)
991
   {
992
      // are we in position setup mode ?
993
      if (the_board.game_state == STATE_SETUPPOSITION)
994
      {
995
         // is it the enter key ? if so, exit setup mode and start playing
996
         if (wParam == L'\r')
997
         {
998
            current_move = &the_board.moves[the_board.viewed_move]; // quick access to current move
999
 
124 pmbaty 1000
            // make sure there is at least one king of each color (i.e. two kings)
1001
            part_index = 0;
1002
            for (line = 0; line < 8; line++)
1003
               for (column = 0; column < 8; column++)
1004
                  if (current_move->slots[line][column].part == PART_KING)
1005
                     part_index++; // there's one king more on this board
1006
            if (part_index != 2)
1007
               return (DefWindowProc (hWnd, message, wParam, lParam)); // when at least one king is missing, we just can't leave edition mode
1008
 
1 pmbaty 1009
            // (in)validate the castling positions
1010
            if ((current_move->slots[0][0].color == COLOR_WHITE) && (current_move->slots[0][0].part == PART_ROOK)
1011
                && (current_move->slots[0][4].color == COLOR_WHITE) && (current_move->slots[0][4].part == PART_KING))
1012
               current_move->sides[COLOR_WHITE].longcastle_allowed = true; // white castling queenside allowed
1013
            else
1014
               current_move->sides[COLOR_WHITE].longcastle_allowed = false; // white castling queenside no longer possible
1015
            if ((current_move->slots[0][7].color == COLOR_WHITE) && (current_move->slots[0][7].part == PART_ROOK)
1016
                && (current_move->slots[0][4].color == COLOR_WHITE) && (current_move->slots[0][4].part == PART_KING))
1017
               current_move->sides[COLOR_WHITE].shortcastle_allowed = true; // white castling kingside allowed
1018
            else
1019
               current_move->sides[COLOR_WHITE].shortcastle_allowed = false; // white castling kingside no longer possible
1020
            if ((current_move->slots[7][0].color == COLOR_BLACK) && (current_move->slots[7][0].part == PART_ROOK)
1021
                && (current_move->slots[7][4].color == COLOR_BLACK) && (current_move->slots[7][4].part == PART_KING))
1022
               current_move->sides[COLOR_BLACK].longcastle_allowed = true; // white castling queenside allowed
1023
            else
1024
               current_move->sides[COLOR_BLACK].longcastle_allowed = false; // white castling queenside no longer possible
1025
            if ((current_move->slots[7][7].color == COLOR_BLACK) && (current_move->slots[7][7].part == PART_ROOK)
1026
                && (current_move->slots[7][4].color == COLOR_BLACK) && (current_move->slots[7][4].part == PART_KING))
1027
               current_move->sides[COLOR_BLACK].shortcastle_allowed = true; // white castling kingside allowed
1028
            else
1029
               current_move->sides[COLOR_BLACK].shortcastle_allowed = false; // white castling kingside no longer possible
1030
 
1031
            current_move->color = COLOR_BLACK; // so that game starts with white
1032
 
1033
            // validate this board in Forsyth-Edwards Notation and reset it
1034
            Move_DescribeInFEN (current_move);
1035
            wcscpy_s (fen_string, WCHAR_SIZEOF (fen_string), current_move->fen_string); // have a copy of fen string
1036
            Board_Reset (&the_board, fen_string);
1037
 
1038
            the_board.game_state = STATE_PLAYING; // start the game now
1039
            the_board.reevaluate = true; // evaluate board again
1040
 
1041
            the_scene.gui.central_text.disappear_time = current_time + 1.0f; // fade out help text now (FIXME: ugly)
1042
            the_scene.update = true; // update the 3D scene
1043
 
1044
            // call the default window message processing function to keep things going
1045
            return (DefWindowProc (hWnd, message, wParam, lParam));
1046
         }
1047
      }
1048
 
1049
      // else are we in internet mode ?
124 pmbaty 1050
      else if (remote_player != NULL)
1 pmbaty 1051
      {
1052
         entered_ccreply = &the_scene.gui.entered_ccreply; // quick access to entered ccreply
1053
         local_player = Player_FindByType (PLAYER_HUMAN); // quick access to local player
1054
         if (local_player == NULL)
1055
            return (DefWindowProc (hWnd, message, wParam, lParam)); // theoretically impossible condition, but better be sure
1056
         if (selected_chatterchannel == NULL)
1057
            return (DefWindowProc (hWnd, message, wParam, lParam)); // theoretically impossible condition, but better be sure
1058
 
1059
         // are we NOT entering text yet ?
1060
         if (!the_scene.gui.is_entering_text)
1061
         {
1062
            // is it the space bar ?
1063
            if (wParam == L' ')
1064
            {
1065
               the_scene.gui.is_entering_text = true; // remember we are entering text
1066
 
1067
               // reset the entered text buffer
1068
               entered_ccreply->text = (wchar_t *) SAFE_malloc (1, sizeof (wchar_t), false);
1069
               entered_ccreply->text[0] = 0; // only the null terminator will fit
1070
               entered_ccreply->text_length = 0; // and set its length to zero
1071
            }
1072
         }
1073
 
1074
         // else we are currently in text entering mode
1075
         else
1076
         {
1077
            // is the typed character a printable character ?
1078
            if (iswprint (wParam))
1079
            {
1080
               // if so, reallocate space in the typed buffer (include null terminator)
1081
               entered_ccreply->text = (wchar_t *) SAFE_realloc (entered_ccreply->text, entered_ccreply->text_length + 1, entered_ccreply->text_length + 1 + 1, sizeof (wchar_t), false);
1082
               swprintf_s (&entered_ccreply->text[entered_ccreply->text_length], 1 + 1, L"%c", wParam); // append character
1083
               entered_ccreply->text_length++; // buffer holds now one character more
1084
            }
1085
 
1086
            // else is the typed character a backspace AND is there text to erase ?
1087
            else if ((wParam == 0x08) && (entered_ccreply->text_length > 0))
1088
            {
1089
               // if so, reallocate space in the typed buffer (include null terminator)
1090
               entered_ccreply->text = (wchar_t *) SAFE_realloc (entered_ccreply->text, entered_ccreply->text_length + 1, entered_ccreply->text_length + 1 - 1, sizeof (wchar_t), false);
1091
               entered_ccreply->text[entered_ccreply->text_length - 1] = 0; // backspace, delete one character
1092
               entered_ccreply->text_length--; // buffer holds now one character less
1093
            }
1094
 
1095
            // else is the typed character the escape key ?
1096
            else if (wParam == 0x1b)
1097
            {
1098
               SAFE_free ((void **) &entered_ccreply->text); // reset the entered text buffer
1099
               entered_ccreply->text_length = 0; // and set its length to zero
1100
               the_scene.gui.is_entering_text = false; // and exit from the text entering mode
1101
            }
1102
 
1103
            // else is the typed character the enter key ?
1104
            else if (wParam == 0x0d)
1105
               the_scene.gui.is_entering_text = false; // enter, exit from the text entering mode (this will validate our reply)
1106
 
1107
            // else it's an illegal character
1108
            else
116 pmbaty 1109
               Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE, 0.0f, 0.0f, 0.04f); // illegal character, beep the illegal move sound at the center of the board
1 pmbaty 1110
         }
1111
 
1112
         the_scene.update = true; // update the 3D scene
1113
 
1114
         // call the default window message processing function to keep things going
1115
         return (DefWindowProc (hWnd, message, wParam, lParam));
1116
      }
1117
   }
1118
 
1119
   ////////////////////////////////////////////////////////////////////////////////////////////////
1120
   // mouse move outside the window
1121
   else if (message == WM_NCMOUSEMOVE)
1122
   {
1123
      rbutton_pushed = false; // remember right button is released
1124
 
1125
      // call the default window message processing function to keep things going
1126
      return (DefWindowProc (hWnd, message, wParam, lParam));
1127
   }
1128
 
1129
   ////////////////////////////////////////////////////////////////////////////////////////////////
1130
   // window repaint
1131
   else if (message == WM_PAINT)
1132
   {
1133
      the_scene.update = true; // update the 3D scene
1134
 
1135
      // call the default window message processing function to keep things going
1136
      return (DefWindowProc (hWnd, message, wParam, lParam));
1137
   }
1138
 
1139
   // call the default window message processing function to keep things going
1140
   return (DefWindowProc (hWnd, message, wParam, lParam));
1141
}
1142
 
1143
 
1144
static bool Button_IsHovered (guibutton_t *button, int gui_x, int gui_y)
1145
{
1146
   // handy wrapper that returns whether a particular GUI button is hovered when the mouse is at the given coordinates
1147
 
1148
   return (Render_IsMouseInBox (gui_x, gui_y, button->left, button->top, button->width, button->height));
1149
}
1150
 
1151
 
1152
static bool Button_UpdateHoverState (guibutton_t *button, int gui_x, int gui_y)
1153
{
1154
   // this function updates the hover state of a GUI button, and returns TRUE if the
1155
   // scene needs to be updated, FALSE otherwise.
1156
 
1157
   // is the button displayed ?
1158
   if (button->state != 0)
1159
   {
1160
      // is the mouse hovering it ?
1161
      if (Render_IsMouseInBox (gui_x, gui_y, button->left, button->top, button->width, button->height))
1162
      {
1163
         // was it NOT hovered before ?
1164
         if (button->state != 2)
1165
         {
1166
            button->state = 2; // mark it as hovered
1167
            return (true); // return TRUE so as to update the scene
1168
         }
1169
      }
1170
 
1171
      // else was it hovered before ?
1172
      else if (button->state == 2)
1173
      {
1174
         button->state = 1; // else mark it as not hovered
1175
         return (true); // return TRUE so as to update the scene
1176
      }
1177
   }
1178
 
1179
   return (false); // no need to update the scene
1180
}