Subversion Repositories Games.Chess Giants

Rev

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