OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4ConsoleWin32.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, 2003, Matthes Bender
5  * Copyright (c) 2004, Peter Wortmann
6  * Copyright (c) 2005-2007, G√ľnther Brammer
7  * Copyright (c) 2005, 2007, Sven Eberhardt
8  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
9  *
10  * Distributed under the terms of the ISC license; see accompanying file
11  * "COPYING" for details.
12  *
13  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
14  * See accompanying file "TRADEMARK" for details.
15  *
16  * To redistribute this file separately, substitute the full license texts
17  * for the above references.
18  */
19 
20 #include "C4Include.h"
21 #include "editor/C4Console.h"
22 
24 #include "editor/C4ConsoleGUI.h"
25 #include "graphics/C4DrawGL.h"
26 #include "landscape/C4Landscape.h"
27 #include "object/C4Object.h"
28 #include "player/C4PlayerList.h"
29 #include "landscape/C4Texture.h"
30 #include "C4Version.h"
31 #include "game/C4Viewport.h"
32 #include "platform/StdRegistry.h"
33 #include "lib/StdColors.h"
34 #include "landscape/C4Sky.h"
35 
37 #include <mmsystem.h>
38 #include <commdlg.h>
39 #include "res/resource.h"
40 #define GetWideLPARAM(c) reinterpret_cast<LPARAM>(static_cast<wchar_t*>(GetWideChar(c)))
41 
42 inline StdStrBuf::wchar_t_holder LoadResStrW(const char *id) { return GetWideChar(LoadResStr(id)); }
43 
44 bool SetMenuItemText(HMENU hMenu, WORD id, const char *szText);
45 
46 bool AddMenuItem(C4ConsoleGUI *console, HMENU hMenu, DWORD dwID, const char *szString, bool fEnabled)
47 {
48  if (!console->Active) return false;
49  MENUITEMINFOW minfo;
50  ZeroMem(&minfo,sizeof(minfo));
51  minfo.cbSize = sizeof(minfo);
52  minfo.fMask = MIIM_ID | MIIM_TYPE | MIIM_DATA | MIIM_STATE;
53  minfo.fType = MFT_STRING;
54  minfo.wID = dwID;
55  StdBuf td = GetWideCharBuf(szString);
56  minfo.dwTypeData = getMBufPtr<wchar_t>(td);
57  minfo.cch = wcslen(minfo.dwTypeData);
58  if (!fEnabled) minfo.fState|=MFS_GRAYED;
59  return !!InsertMenuItemW(hMenu,0,false,&minfo);
60 }
61 
63 {
64 public:
65  BOOL RegisterConsoleWindowClass(HINSTANCE hInst);
66  bool AddMenuItem(HMENU hMenu, DWORD dwID, const char *szString, bool fEnabled=true);
68  HBITMAP hbmMouse;
69  HBITMAP hbmMouse2;
70  HBITMAP hbmCursor;
71  HBITMAP hbmCursor2;
72  HBITMAP hbmBrush;
73  HBITMAP hbmBrush2;
74  HBITMAP hbmPlay;
75  HBITMAP hbmPlay2;
76  HBITMAP hbmHalt;
77  HBITMAP hbmHalt2;
87  int console_default_width, console_default_height; // default (and minimum) console window size
88  int console_margin; // margins between controls and from window borders
89  int console_wide_margin; // larger margins around some console buttons
90  int console_button_height; // height of buttons and the three control rows in the console
91  int console_ok_button_width; // width of OK button to enter script commands (everyone just presses enter anyway...)
92  int console_status_width; // width of frame counter and time/FPS display status boxes
93 
94  State(C4ConsoleGUI *console)
95  {
96  hbmMouse=nullptr;
97  hbmMouse2=nullptr;
98  hbmCursor=nullptr;
99  hbmCursor2=nullptr;
100  hbmBrush=nullptr;
101  hbmBrush2=nullptr;
102  hbmPlay=nullptr;
103  hbmPlay2=nullptr;
104  hbmHalt=nullptr;
105  hbmHalt2=nullptr;
106  hPropertyDlg=nullptr;
107  MenuIndexFile = 0;
108  MenuIndexPlayer = 1;
109  MenuIndexViewport = 2;
110  MenuIndexNet = -1;
111  MenuIndexHelp = 3;
112  property_dlg_inputarea_height = 0;
113  property_dlg_margin = 0;
114  property_dlg_okbutton_width = 0;
115  console_handle = nullptr;
116  console_default_width = 0;
117  console_default_height = 0;
118  console_margin = 0;
119  console_wide_margin = 0;
120  console_button_height = 0;
121  console_ok_button_width = 0;
122  console_status_width = 0;
123  }
124 
126  {
127  if (hbmMouse) DeleteObject(hbmMouse);
128  if (hbmMouse2) DeleteObject(hbmMouse2);
129  if (hbmCursor) DeleteObject(hbmCursor);
130  if (hbmCursor2) DeleteObject(hbmCursor2);
131  if (hbmBrush) DeleteObject(hbmBrush);
132  if (hbmBrush2) DeleteObject(hbmBrush2);
133  if (hbmPlay) DeleteObject(hbmPlay);
134  if (hbmPlay2) DeleteObject(hbmPlay2);
135  if (hbmHalt) DeleteObject(hbmHalt);
136  if (hbmHalt2) DeleteObject(hbmHalt2);
137  }
138 
139  void CreateBitmaps(C4AbstractApp *application)
140  {
141  HINSTANCE instance = application->GetInstance();
142  hbmMouse=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_MOUSE));
143  hbmMouse2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_MOUSE2));
144  hbmCursor=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_CURSOR));
145  hbmCursor2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_CURSOR2));
146  hbmBrush=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_BRUSH));
147  hbmBrush2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_BRUSH2));
148  hbmPlay=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_PLAY));
149  hbmPlay2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_PLAY2));
150  hbmHalt=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_HALT));
151  hbmHalt2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_HALT2));
152  }
153 
154  void UpdateMenuText(C4ConsoleGUI &console, HMENU hMenu)
155  {
156  HMENU hSubMenu;
157  if (!console.Active) return;
158  // File
159  ModifyMenuW(hMenu,MenuIndexFile,MF_BYPOSITION | MF_STRING,0,LoadResStrW("IDS_MNU_FILE"));
160  hSubMenu = GetSubMenu(hMenu,MenuIndexFile);
161  SetMenuItemText(hSubMenu,IDM_FILE_OPEN,LoadResStr("IDS_MNU_OPEN"));
162  SetMenuItemText(hSubMenu,IDM_FILE_OPENWPLRS,LoadResStr("IDS_MNU_OPENWPLRS"));
163  SetMenuItemText(hSubMenu,IDM_FILE_RECORD,LoadResStr("IDS_MNU_RECORD"));
164  SetMenuItemText(hSubMenu,IDM_FILE_SAVE,LoadResStr("IDS_MNU_SAVESCENARIO"));
165  SetMenuItemText(hSubMenu,IDM_FILE_SAVEAS,LoadResStr("IDS_MNU_SAVESCENARIOAS"));
166  SetMenuItemText(hSubMenu,IDM_FILE_SAVEGAMEAS,LoadResStr("IDS_MNU_SAVEGAMEAS"));
167  SetMenuItemText(hSubMenu,IDM_FILE_CLOSE,LoadResStr("IDS_MNU_CLOSE"));
168  SetMenuItemText(hSubMenu,IDM_FILE_QUIT,LoadResStr("IDS_MNU_QUIT"));
169  // Player
170  ModifyMenuW(hMenu,MenuIndexPlayer,MF_BYPOSITION | MF_STRING,0,LoadResStrW("IDS_MNU_PLAYER"));
171  hSubMenu = GetSubMenu(hMenu,MenuIndexPlayer);
172  SetMenuItemText(hSubMenu,IDM_PLAYER_JOIN,LoadResStr("IDS_MNU_JOIN"));
173  // Viewport
174  ModifyMenuW(hMenu,MenuIndexViewport,MF_BYPOSITION | MF_STRING,0,LoadResStrW("IDS_MNU_VIEWPORT"));
175  hSubMenu = GetSubMenu(hMenu,MenuIndexViewport);
176  SetMenuItemText(hSubMenu,IDM_VIEWPORT_NEW,LoadResStr("IDS_MNU_NEW"));
177  // Help
178  hSubMenu = GetSubMenu(hMenu,MenuIndexHelp);
179  SetMenuItemText(hSubMenu,IDM_HELP_ABOUT,LoadResStr("IDS_MENU_ABOUT"));
180  }
181 
183  {
184  // Find out desired sizes and margins of elements used in property dialogue.
185  // Just remember initial layout.
186  // This is easier than getting all values from Windows metrics definitions.
187  RECT client_rc = { 0,0,252,101 }, button_rc = { 207,182,254,202 };
188  ::GetClientRect(hPropertyDlg, &client_rc);
189  HWND button = ::GetDlgItem(hPropertyDlg, IDOK);
190  ::GetWindowRect(button, &button_rc);
191  property_dlg_inputarea_height = button_rc.bottom - button_rc.top;
192  property_dlg_margin = 1; // hardcoded. The elements are actually placed quite poorly in the .rc, cannot derive from it
193  property_dlg_okbutton_width = button_rc.right - button_rc.left;
194  }
195 
197  {
198  // Positions unknown?
199  if (!property_dlg_inputarea_height) return;
200  // Reposition all child elements after size of property dialogue has changed
201  RECT rc = { 0,0,0,0 };
202  if (!::GetClientRect(hPropertyDlg, &rc)) return;
203  int y0 = rc.bottom - property_dlg_margin - property_dlg_inputarea_height;
204  // Output text box
205  ::SetWindowPos(::GetDlgItem(hPropertyDlg, IDC_EDITOUTPUT), nullptr,
206  property_dlg_margin,
207  property_dlg_margin,
208  rc.right - 2* property_dlg_margin,
209  y0 - 2* property_dlg_margin,
210  SWP_NOOWNERZORDER | SWP_NOZORDER);
211  // Input ComboBox
212  ::SetWindowPos(::GetDlgItem(hPropertyDlg, IDC_COMBOINPUT), nullptr,
213  property_dlg_margin,
214  y0,
215  rc.right - property_dlg_okbutton_width - 3*property_dlg_margin,
216  property_dlg_inputarea_height,
217  SWP_NOOWNERZORDER | SWP_NOZORDER);
218  // OK button
219  ::SetWindowPos(::GetDlgItem(hPropertyDlg, IDOK), nullptr,
220  rc.right - property_dlg_margin - property_dlg_okbutton_width,
221  y0,
222  property_dlg_okbutton_width,
223  property_dlg_inputarea_height,
224  SWP_NOOWNERZORDER | SWP_NOZORDER);
225  }
226 
228  {
229  // Find out desired sizes and margins of elements used in console dialogue.
230  // Just remember initial layout.
231  // This is easier than getting all values from Windows metrics definitions.
232  RECT console_rc = { 0,0,356,252 };
233  ::GetWindowRect(console_handle, &console_rc);
234  console_default_width = console_rc.right - console_rc.left;
235  console_default_height = console_rc.bottom - console_rc.top;
236  console_margin = 1; // hardcoded margins
237  console_wide_margin = 3;
238  RECT button_rc = { 288,180,350,200 };
239  ::GetWindowRect(::GetDlgItem(console_handle, IDOK), &button_rc);
240  console_button_height = button_rc.bottom - button_rc.top;
241  console_ok_button_width = button_rc.right - button_rc.left;
242  RECT status_rc = { 222,205,350,223 };
243  ::GetWindowRect(::GetDlgItem(console_handle, IDC_STATICTIME), &status_rc);
244  console_status_width = status_rc.right - status_rc.left;
245  }
246 
248  {
249  // Positions unknown?
250  if (!console_default_width) return;
251  // Reposition all child elements after size of console dialogue has changed
252  RECT rc = { 0,0,0,0 };
253  if (!::GetClientRect(console_handle, &rc)) return;
254  int y0 = rc.bottom - console_margin * 3 - console_button_height * 3;
255  int y1 = rc.bottom - console_margin * 2 - console_button_height * 2;
256  int y2 = rc.bottom - console_margin * 1 - console_button_height * 1;
257  int x0 = rc.right - console_margin - console_button_height;
258  // Output text box
259  ::SetWindowPos(::GetDlgItem(console_handle, IDC_EDITOUTPUT), nullptr,
260  console_margin,
261  0,
262  x0 - console_margin - console_wide_margin,
263  y0 - console_margin,
264  SWP_NOOWNERZORDER | SWP_NOZORDER);
265  // Input ComboBox
266  ::SetWindowPos(::GetDlgItem(console_handle, IDC_COMBOINPUT), nullptr,
267  console_margin,
268  y0,
269  rc.right - console_ok_button_width - console_margin * 3,
270  console_button_height,
271  SWP_NOOWNERZORDER | SWP_NOZORDER);
272  // Input OK button
273  ::SetWindowPos(::GetDlgItem(console_handle, IDOK), nullptr,
274  rc.right - console_margin - console_ok_button_width,
275  y0,
276  console_ok_button_width,
277  console_button_height,
278  SWP_NOOWNERZORDER | SWP_NOZORDER);
279  // Frame status bar
280  ::SetWindowPos(::GetDlgItem(console_handle, IDC_STATICFRAME), nullptr,
281  console_margin,
282  y1,
283  console_status_width,
284  console_button_height,
285  SWP_NOOWNERZORDER | SWP_NOZORDER);
286  // Play button
287  ::SetWindowPos(::GetDlgItem(console_handle, IDC_BUTTONPLAY), nullptr,
288  console_margin + console_status_width + console_wide_margin,
289  y1,
290  console_button_height,
291  console_button_height,
292  SWP_NOOWNERZORDER | SWP_NOZORDER);
293  // Halt button
294  ::SetWindowPos(::GetDlgItem(console_handle, IDC_BUTTONHALT), nullptr,
295  console_margin + console_status_width + console_wide_margin * 2 + console_button_height,
296  y1,
297  console_button_height,
298  console_button_height,
299  SWP_NOOWNERZORDER | SWP_NOZORDER);
300  // Time/FPS status bar
301  ::SetWindowPos(::GetDlgItem(console_handle, IDC_STATICTIME), nullptr,
302  rc.right - console_margin - console_status_width,
303  y1,
304  console_status_width,
305  console_button_height,
306  SWP_NOOWNERZORDER | SWP_NOZORDER);
307  // Main status bar
308  ::SetWindowPos(::GetDlgItem(console_handle, IDC_STATICCURSOR), nullptr,
309  console_margin,
310  y2,
311  rc.right - 2* console_margin,
312  console_button_height,
313  SWP_NOOWNERZORDER | SWP_NOZORDER);
314  // Tool buttons
315  ::SetWindowPos(::GetDlgItem(console_handle, IDC_BUTTONMODEPLAY), nullptr,
316  x0,
317  console_margin,
318  console_button_height,
319  console_button_height,
320  SWP_NOOWNERZORDER | SWP_NOZORDER);
321  ::SetWindowPos(::GetDlgItem(console_handle, IDC_BUTTONMODEEDIT), nullptr,
322  x0,
323  console_margin * 2 + console_button_height,
324  console_button_height,
325  console_button_height,
326  SWP_NOOWNERZORDER | SWP_NOZORDER);
327  ::SetWindowPos(::GetDlgItem(console_handle, IDC_BUTTONMODEDRAW), nullptr,
328  x0,
329  console_margin * 3 + console_button_height * 2,
330  console_button_height,
331  console_button_height,
332  SWP_NOOWNERZORDER | SWP_NOZORDER);
333  }
334 };
335 
336 void C4ConsoleGUI::UpdateMenuText(HMENU hMenu) { state->UpdateMenuText(*this, hMenu); }
337 
338 static void ClearDlg(HWND &handle)
339 {
340  if (handle)
341  DestroyWindow(handle);
342  handle = nullptr;
343 }
344 
345 INT_PTR CALLBACK ConsoleDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
346 {
347  switch (Msg)
348  {
349  //------------------------------------------------------------------------------------------------------------
350  case WM_ACTIVATEAPP:
351  Application.Active = wParam != 0;
352  return true;
353  //------------------------------------------------------------------------------------------------------------
354  case WM_DESTROY:
355  StoreWindowPosition(hDlg, "Main", Config.GetSubkeyPath("Console"), true);
356  Application.Quit();
357  return true;
358  //------------------------------------------------------------------------------------------------------------
359  case WM_CLOSE:
360  Console.Close();
361  return true;
362  //------------------------------------------------------------------------------------------------------------
363  case MM_MCINOTIFY:
364  if (wParam == MCI_NOTIFY_SUCCESSFUL)
366  return true;
367  //------------------------------------------------------------------------------------------------------------
368  case WM_INITDIALOG:
369  Console.Active = true;
370  SendMessage(hDlg, DM_SETDEFID, (WPARAM)IDOK, (LPARAM)0);
371  Console.UpdateMenuText(GetMenu(hDlg));
372  return true;
373  //------------------------------------------------------------------------------------------------------------
374  case WM_COMMAND:
375  // Evaluate command
376  switch (LOWORD(wParam))
377  {
378  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
379  case IDOK:
380  // IDC_COMBOINPUT to Console.In()
381  wchar_t buffer[16000];
382  GetDlgItemTextW(hDlg, IDC_COMBOINPUT, buffer, 16000);
383  if (buffer[0])
384  {
385  StdStrBuf in_char(buffer);
387  ::Console.In(in_char.getData());
389  }
390  return true;
391  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
392  case IDC_BUTTONHALT:
393  Console.DoHalt();
394  return true;
395  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
396  case IDC_BUTTONPLAY:
397  Console.DoPlay();
398  return true;
399  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
400  case IDC_BUTTONMODEPLAY:
402  return true;
403  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
404  case IDC_BUTTONMODEEDIT:
406  return true;
407  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
408  case IDC_BUTTONMODEDRAW:
410  return true;
411  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
412  case IDM_FILE_QUIT: Console.FileQuit(); return true;
413  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
414  case IDM_FILE_SAVEAS: Console.FileSaveAs(false); return true;
415  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
416  case IDM_FILE_SAVE: Console.FileSave(); return true;
417  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
418  case IDM_FILE_SAVEGAMEAS: Console.FileSaveAs(true); return true;
419  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
420  case IDM_FILE_OPEN: Console.FileOpen(); return true;
421  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
422  case IDM_FILE_RECORD: Console.FileRecord(); return true;
423  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
424  case IDM_FILE_OPENWPLRS: Console.FileOpenWPlrs(); return true;
425  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
426  case IDM_FILE_CLOSE: Console.FileClose(); return true;
427  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
428  case IDM_HELP_ABOUT: Console.HelpAbout(); return true;
429  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
430  case IDM_PLAYER_JOIN: Console.PlayerJoin(); return true;
431  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
432  case IDM_VIEWPORT_NEW: Console.ViewportNew(); return true;
433  }
434  // New player viewport
435  if (Inside((int)LOWORD(wParam), IDM_VIEWPORT_NEW1, IDM_VIEWPORT_NEW2))
436  {
437  ::Viewports.CreateViewport(LOWORD(wParam) - IDM_VIEWPORT_NEW1);
438  return true;
439  }
440  // Remove player
441  if (Inside((int)LOWORD(wParam), IDM_PLAYER_QUIT1, IDM_PLAYER_QUIT2))
442  {
443  C4Player *plr = ::Players.Get(LOWORD(wParam) - IDM_PLAYER_QUIT1);
444  if (!plr) return true;
446  return true;
447  }
448  // Remove client
449  if (Inside((int)LOWORD(wParam), IDM_NET_CLIENT1, IDM_NET_CLIENT2))
450  {
451  if (!::Control.isCtrlHost()) return false;
452  Game.Clients.CtrlRemove(Game.Clients.getClientByID(LOWORD(wParam) - IDM_NET_CLIENT1), LoadResStr("IDS_MSG_KICKBYMENU"));
453  return true;
454  }
455  return false;
456  //------------------------------------------------------------------------------------------------------------
457  case WM_USER_LOG:
458  if (SEqual2((const char *)lParam, "IDS_"))
459  Log(LoadResStr((const char *)lParam));
460  else
461  Log((const char *)lParam);
462  return false;
463  //------------------------------------------------------------------------------------------------------------
464  case WM_COPYDATA:
465  {
466  COPYDATASTRUCT* pcds = reinterpret_cast<COPYDATASTRUCT *>(lParam);
467  if (pcds->dwData == WM_USER_RELOADFILE)
468  {
469  // get path, ensure proper termination
470  const char *szPath = reinterpret_cast<const char *>(pcds->lpData);
471  if (szPath[pcds->cbData - 1]) break;
472  // reload
473  Game.ReloadFile(szPath);
474  }
475  return false;
476  }
477  //------------------------------------------------------------------------------------------------------------
478  case WM_INPUTLANGCHANGE:
480  break;
481  //------------------------------------------------------------------------------------------------------------
482  // Resizing
483  case WM_GETMINMAXINFO:
484  // Window may not become smaller than initial size
485  if (Console.state && Console.state->console_default_width)
486  {
487  MINMAXINFO *info = reinterpret_cast<MINMAXINFO *>(lParam);
488  info->ptMinTrackSize.x = Console.state->console_default_width;
489  info->ptMinTrackSize.y = Console.state->console_default_height;
490  }
491  return 0;
492  case WM_SIZING: Console.state->ConsoleUpdateSize(); break;
493  case WM_WINDOWPOSCHANGED:
494  {
495  const WINDOWPOS *data = reinterpret_cast<const WINDOWPOS *>(lParam);
496  if (data && !(data->flags & SWP_NOSIZE)) Console.state->ConsoleUpdateSize();
497  break;
498  }
499  }
500  return false;
501 }
502 
503 class C4ToolsDlg::State: public C4ConsoleGUI::InternalState<class C4ToolsDlg>
504 {
505 public:
506  HWND hDialog;
508  friend INT_PTR CALLBACK ToolsDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
510  HBITMAP hbmLine,hbmLine2;
511  HBITMAP hbmRect,hbmRect2;
512  HBITMAP hbmFill,hbmFill2;
514  HBITMAP hbmDynamic;
515  HBITMAP hbmStatic;
516  HBITMAP hbmExact;
517 
518  State(C4ToolsDlg *toolsDlg): C4ConsoleGUI::InternalState<class C4ToolsDlg>(toolsDlg), hDialog(0),
519  hbmBrush(0), hbmBrush2(0),
520  hbmLine(0), hbmLine2(0),
521  hbmRect(0), hbmRect2(0),
522  hbmFill(0), hbmFill2(0),
523  hbmPicker(0), hbmPicker2(0),
524  hbmDynamic(0),
525  hbmStatic(0),
526  hbmExact(0)
527  {
528  pPreviewWindow = nullptr;
529  }
530 
531  void LoadBitmaps(HINSTANCE instance)
532  {
533  if (!hbmBrush) hbmBrush=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_BRUSH));
534  if (!hbmLine) hbmLine=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_LINE));
535  if (!hbmRect) hbmRect=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_RECT));
536  if (!hbmFill) hbmFill=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_FILL));
537  if (!hbmPicker) hbmPicker=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_PICKER));
538  if (!hbmBrush2) hbmBrush2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_BRUSH2));
539  if (!hbmLine2) hbmLine2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_LINE2));
540  if (!hbmRect2) hbmRect2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_RECT2));
541  if (!hbmFill2) hbmFill2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_FILL2));
542  if (!hbmPicker2) hbmPicker2=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_PICKER2));
543  if (!hbmDynamic) hbmDynamic=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_DYNAMIC));
544  if (!hbmStatic) hbmStatic=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_STATIC));
545  if (!hbmExact) hbmExact=(HBITMAP)LoadBitmapW(instance,MAKEINTRESOURCEW(IDB_EXACT));
546  }
547 
549  {
550  Clear();
551  }
552 
553  void Clear()
554  {
555  // Unload bitmaps
556  if (hbmBrush) { DeleteObject(hbmBrush); hbmBrush = 0; }
557  if (hbmLine) { DeleteObject(hbmLine); hbmLine = 0; }
558  if (hbmRect) { DeleteObject(hbmRect); hbmRect = 0; }
559  if (hbmFill) { DeleteObject(hbmFill); hbmFill = 0; }
560  if (hbmPicker) { DeleteObject(hbmPicker); hbmPicker = 0; }
561  if (hbmBrush2) { DeleteObject(hbmBrush2); hbmBrush2 = 0; }
562  if (hbmLine2) { DeleteObject(hbmLine2); hbmLine2 = 0; }
563  if (hbmRect2) { DeleteObject(hbmRect2); hbmRect2 = 0; }
564  if (hbmFill2) { DeleteObject(hbmFill2); hbmFill2 = 0; }
565  if (hbmPicker2) { DeleteObject(hbmPicker2); hbmPicker2 = 0; }
566  if (hbmDynamic) { DeleteObject(hbmDynamic); hbmDynamic = 0; }
567  if (hbmStatic) { DeleteObject(hbmStatic); hbmStatic = 0; }
568  if (hbmExact) { DeleteObject(hbmExact); hbmExact = 0; }
569  if (pPreviewWindow)
570  {
571  delete pPreviewWindow;
572  pPreviewWindow = nullptr;
573  }
574  if (hDialog) DestroyWindow(hDialog); hDialog=nullptr;
575  }
576 
577  void Default()
578  {
579  GetOwner()->ModeBack = true;
580  }
581 
582 };
583 
584 #include <commctrl.h>
585 INT_PTR CALLBACK ToolsDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
586 {
587  int32_t iValue;
588  switch (Msg)
589  {
590  //----------------------------------------------------------------------------------------------
591  case WM_CLOSE:
593  break;
594  //----------------------------------------------------------------------------------------------
595  case WM_DESTROY:
596  StoreWindowPosition(hDlg, "Tools", Config.GetSubkeyPath("Console"), false);
597  break;
598  //----------------------------------------------------------------------------------------------
599  case WM_INITDIALOG:
600  return true;
601  //----------------------------------------------------------------------------------------------
602  case WM_PAINT:
603  PostMessage(hDlg,WM_USER,0,0); // For user paint
604  return false;
605  //----------------------------------------------------------------------------------------------
606  case WM_USER:
608  return true;
609  //----------------------------------------------------------------------------------------------
610  case WM_VSCROLL:
611  switch (LOWORD(wParam))
612  {
613  case SB_THUMBTRACK: case SB_THUMBPOSITION:
614  iValue=HIWORD(wParam);
616  break;
617  case SB_PAGEUP: case SB_PAGEDOWN:
618  case SB_LINEUP: case SB_LINEDOWN:
619  iValue=SendDlgItemMessage(hDlg,IDC_SLIDERGRADE,TBM_GETPOS,0,0);
621  break;
622  }
623  return true;
624  //----------------------------------------------------------------------------------------------
625  case WM_COMMAND:
626  // Evaluate command
627  switch (LOWORD(wParam))
628  {
629  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
630  case IDOK:
631  return true;
632  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
635  return true;
636  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
639  return true;
640  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
641  case IDC_BUTTONMODEEXACT:
643  return true;
644  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
645  case IDC_BUTTONBRUSH:
647  return true;
648  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
649  case IDC_BUTTONLINE:
651  return true;
652  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
653  case IDC_BUTTONRECT:
655  return true;
656  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
657  case IDC_BUTTONFILL:
659  return true;
660  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
661  case IDC_BUTTONPICKER:
663  return true;
664  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
667  switch (HIWORD(wParam))
668  {
669  case CBN_SELCHANGE:
670  {
671  // New material or texture selected. Get selection string
672  wchar_t str[100];
673  WORD idCombo = LOWORD(wParam);
674  int32_t cursel = SendDlgItemMessage(hDlg, idCombo, CB_GETCURSEL, 0, 0);
675  SendDlgItemMessage(hDlg, idCombo, CB_GETLBTEXT, cursel, (LPARAM)str);
676  // Convert to ascii
677  StdStrBuf str_buf(str);
678  const char *astr = str_buf.getData();
679  // Update appropriate setting in drawing tool
680  switch (idCombo)
681  {
682  case IDC_COMBOFGMATERIAL: Console.ToolsDlg.SetMaterial(astr); break;
683  case IDC_COMBOFGTEXTURE: Console.ToolsDlg.SetTexture(astr); break;
686  }
687  }
688  return true;
689  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
690  }
691  }
692  return false;
693  //----------------------------------------------------------------------------------------
694  }
695  return false;
696 }
697 
698 INT_PTR CALLBACK PropertyDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
699 {
700  switch (Msg)
701  {
702  //------------------------------------------------------------------------------------------------
703  case WM_CLOSE:
705  break;
706  //------------------------------------------------------------------------------------------------
707  case WM_DESTROY:
708  StoreWindowPosition(hDlg, "Property", Config.GetSubkeyPath("Console"), true);
709  break;
710  //------------------------------------------------------------------------------------------------
711  case WM_INITDIALOG:
712  SendMessage(hDlg,DM_SETDEFID,(WPARAM)IDOK,(LPARAM)0);
713  return true;
714  //------------------------------------------------------------------------------------------------
715  // Callbacks during/after window resizing
716  case WM_SIZING: Console.state->PropertyDlgUpdateSize(); break;
717  case WM_WINDOWPOSCHANGED:
718  {
719  const WINDOWPOS *data = reinterpret_cast<const WINDOWPOS *>(lParam);
720  if (data && !(data->flags & SWP_NOSIZE)) Console.state->PropertyDlgUpdateSize();
721  break;
722  }
723  //------------------------------------------------------------------------------------------------
724  case WM_COMMAND:
725  // Evaluate command
726  switch (LOWORD(wParam))
727  {
728  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
729  case IDOK:
730  // IDC_COMBOINPUT to Console.EditCursor.In()
731  wchar_t buffer[16000];
732  GetDlgItemTextW(hDlg,IDC_COMBOINPUT,buffer,16000);
733  if (buffer[0])
734  Console.EditCursor.In(StdStrBuf(buffer).getData());
735  return true;
736  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
737  case IDC_BUTTONRELOADDEF:
738  {
740  if (pObj)
741  Game.ReloadDef(pObj->id);
742  return true;
743  }
744  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
745  }
746  return false;
747  //-----------------------------------------------------------------------------------------------
748  }
749  return false;
750 }
751 
752 void C4ConsoleGUI::Win32KeepDialogsFloating(HWND hwnd)
753 {
754  if (!hwnd)
755  hwnd = hWindow;
756  if (Console.state->hPropertyDlg)
757  SetWindowLongPtr(Console.state->hPropertyDlg, GWLP_HWNDPARENT, reinterpret_cast<LONG_PTR>(hwnd));
758  if (Console.ToolsDlg.state->hDialog)
759  SetWindowLongPtr(Console.ToolsDlg.state->hDialog, GWLP_HWNDPARENT, reinterpret_cast<LONG_PTR>(hwnd));
760 }
761 
762 bool C4ConsoleGUI::Win32DialogMessageHandling(MSG *msg)
763 {
764  return (hWindow && IsDialogMessage(hWindow,msg)) || (Console.state->hPropertyDlg && IsDialogMessage(Console.state->hPropertyDlg,msg));
765 }
766 
767 void C4ConsoleGUI::SetCursor(Cursor cursor)
768 {
769  ::SetCursor(LoadCursor(0,IDC_WAIT));
770 }
771 
772 bool C4ConsoleGUI::UpdateModeCtrls(int iMode)
773 {
774  if (!Active)
775  return false;
776 
777  SendDlgItemMessage(hWindow,IDC_BUTTONMODEPLAY,BM_SETSTATE,(iMode==C4CNS_ModePlay),0);
778  UpdateWindow(GetDlgItem(hWindow,IDC_BUTTONMODEPLAY));
779  SendDlgItemMessage(hWindow,IDC_BUTTONMODEEDIT,BM_SETSTATE,(iMode==C4CNS_ModeEdit),0);
780  UpdateWindow(GetDlgItem(hWindow,IDC_BUTTONMODEEDIT));
781  SendDlgItemMessage(hWindow,IDC_BUTTONMODEDRAW,BM_SETSTATE,(iMode==C4CNS_ModeDraw),0);
782  UpdateWindow(GetDlgItem(hWindow,IDC_BUTTONMODEDRAW));
783  return true;
784 }
785 
787 {
788  hWindow = CreateDialog(application->GetInstance(), MAKEINTRESOURCE(IDD_CONSOLE), nullptr, ConsoleDlgProc);
789  if (!hWindow)
790  {
791  wchar_t * lpMsgBuf;
792  FormatMessage(
793  FORMAT_MESSAGE_ALLOCATE_BUFFER |
794  FORMAT_MESSAGE_FROM_SYSTEM |
795  FORMAT_MESSAGE_IGNORE_INSERTS,
796  nullptr,
797  GetLastError(),
798  0,
799  (wchar_t *)&lpMsgBuf, // really.
800  0,
801  nullptr);
802  Log(FormatString("Error creating dialog window: %s", StdStrBuf(lpMsgBuf).getData()).getData());
803  // Free the buffer.
804  LocalFree(lpMsgBuf);
805  return false;
806  }
807  // Remember metrics
808  state->console_handle = hWindow;
809  state->ConsoleInitLayout();
810  // Restore window position
811  RestoreWindowPosition(hWindow, "Main", Config.GetSubkeyPath("Console"));
812  // Set icon
813  SendMessage(hWindow,WM_SETICON,ICON_BIG,(LPARAM)LoadIcon(application->GetInstance(),MAKEINTRESOURCE(IDI_00_C4X)));
814  SendMessage(hWindow,WM_SETICON,ICON_SMALL,(LPARAM)LoadIcon(application->GetInstance(),MAKEINTRESOURCE(IDI_00_C4X)));
815  // Set text
816  SetTitle(LoadResStr("IDS_CNS_CONSOLE"));
817  // Load bitmaps
818  state->CreateBitmaps(application);
819  // Enable controls
820  UpdateHaltCtrls(true);
823  // Show window and set focus
824  ShowWindow(hWindow,SW_SHOWNORMAL);
825  UpdateWindow(hWindow);
826  SetFocus(hWindow);
827  ShowCursor(true);
828  renderwnd = hWindow;
829  // Success
830  return true;
831 }
832 
834 {
835 }
836 
837 void C4ConsoleGUI::DoEnableControls(bool fEnable)
838 {
839  // Set button images (edit modes & halt controls)
840  SendDlgItemMessage(hWindow,IDC_BUTTONMODEPLAY,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)(fEnable ? state->hbmMouse : state->hbmMouse2));
841  SendDlgItemMessage(hWindow,IDC_BUTTONMODEEDIT,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((fEnable && Editing) ? state->hbmCursor : state->hbmCursor2));
842  SendDlgItemMessage(hWindow,IDC_BUTTONMODEDRAW,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((fEnable && Editing) ? state->hbmBrush : state->hbmBrush2));
843  SendDlgItemMessage(hWindow,IDC_BUTTONPLAY,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)(::Network.isLobbyActive() || fEnable ? state->hbmPlay : state->hbmPlay2));
844  SendDlgItemMessage(hWindow,IDC_BUTTONHALT,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)(::Network.isLobbyActive() || fEnable ? state->hbmHalt : state->hbmHalt2));
845 
846  // OK
847  EnableWindow( GetDlgItem(hWindow,IDOK), fEnable);
848 
849  // Halt controls
850  EnableWindow(GetDlgItem(hWindow,IDC_BUTTONPLAY), ::Network.isLobbyActive() || fEnable);
851  EnableWindow(GetDlgItem(hWindow,IDC_BUTTONHALT), ::Network.isLobbyActive() || fEnable);
852 
853  // Edit modes
854  EnableWindow(GetDlgItem(hWindow,IDC_BUTTONMODEPLAY),(fEnable));
855  EnableWindow(GetDlgItem(hWindow,IDC_BUTTONMODEEDIT),(fEnable && Editing));
856  EnableWindow(GetDlgItem(hWindow,IDC_BUTTONMODEDRAW),(fEnable && Editing));
857 
858  // Console input
859  EnableWindow(GetDlgItem(hWindow,IDC_COMBOINPUT), fEnable);
860 
861  // File menu
862  // C4Network2 will have to handle that cases somehow (TODO: test)
863  EnableMenuItem(GetMenu(hWindow),IDM_FILE_OPEN, MF_BYCOMMAND | MF_ENABLED );
864  EnableMenuItem(GetMenu(hWindow),IDM_FILE_OPENWPLRS, MF_BYCOMMAND | MF_ENABLED );
865  EnableMenuItem(GetMenu(hWindow),IDM_FILE_RECORD, MF_BYCOMMAND | ((Game.IsRunning && ::Control.IsRuntimeRecordPossible()) ? MF_ENABLED : MF_GRAYED));
866  EnableMenuItem(GetMenu(hWindow),IDM_FILE_SAVEGAMEAS, MF_BYCOMMAND | ((fEnable && ::Players.GetCount()) ? MF_ENABLED : MF_GRAYED));
867  EnableMenuItem(GetMenu(hWindow),IDM_FILE_SAVE, MF_BYCOMMAND | (fEnable ? MF_ENABLED : MF_GRAYED));
868  EnableMenuItem(GetMenu(hWindow),IDM_FILE_SAVEAS, MF_BYCOMMAND | (fEnable ? MF_ENABLED : MF_GRAYED));
869  EnableMenuItem(GetMenu(hWindow),IDM_FILE_CLOSE, MF_BYCOMMAND | (fEnable ? MF_ENABLED : MF_GRAYED));
870 
871  // Player & viewport menu
872  EnableMenuItem(GetMenu(hWindow),IDM_PLAYER_JOIN, MF_BYCOMMAND | ((fEnable && Editing) ? MF_ENABLED : MF_GRAYED));
873  EnableMenuItem(GetMenu(hWindow),IDM_VIEWPORT_NEW, MF_BYCOMMAND | (fEnable ? MF_ENABLED : MF_GRAYED));
874 }
875 
876 bool C4ConsoleGUI::DoUpdateHaltCtrls(bool fHalt)
877 {
878  SendDlgItemMessage(hWindow,IDC_BUTTONPLAY,BM_SETSTATE,!fHalt,0);
879  UpdateWindow(GetDlgItem(hWindow,IDC_BUTTONPLAY));
880  SendDlgItemMessage(hWindow,IDC_BUTTONHALT,BM_SETSTATE,fHalt,0);
881  UpdateWindow(GetDlgItem(hWindow,IDC_BUTTONHALT));
882  return true;
883 }
884 
885 void C4ConsoleGUI::Out(const char* message)
886 {
887  if (!Active) return;
888  if (!message || !*message) return;
889  int len,len2,lines; wchar_t *buffer, *buffer2;
890  len = 65000;//SendDlgItemMessage(hWindow,IDC_EDITOUTPUT,EM_LINELENGTH,(WPARAM)0,(LPARAM)0);
891  StdBuf messageW = GetWideCharBuf(message);
892  len2 = len+std::min<int32_t>(messageW.getSize()/sizeof(wchar_t)+2, 5000);
893  buffer = new wchar_t [len2];
894  buffer[0]=0;
895  GetDlgItemTextW(hWindow,IDC_EDITOUTPUT,buffer,len);
896  if (buffer[0]) wcscat(buffer, L"\r\n");
897  wcsncat(buffer,getBufPtr<wchar_t>(messageW),len2-wcslen(buffer)-1);
898  if (wcslen(buffer) > 60000) buffer2 = buffer + wcslen(buffer) - 60000; else buffer2 = buffer; // max log length: Otherwise, discard beginning
899  SetDlgItemTextW(hWindow,IDC_EDITOUTPUT,buffer2);
900  delete [] buffer;
901  lines = SendDlgItemMessage(hWindow,IDC_EDITOUTPUT,EM_GETLINECOUNT,(WPARAM)0,(LPARAM)0);
902  SendDlgItemMessage(hWindow,IDC_EDITOUTPUT,EM_LINESCROLL,(WPARAM)0,(LPARAM)lines);
903  UpdateWindow(hWindow);
904 }
905 
907 {
908  SetDlgItemTextW(hWindow,IDC_EDITOUTPUT,L"");
909  SendDlgItemMessage(hWindow,IDC_EDITOUTPUT,EM_LINESCROLL,(WPARAM)0,0);
910  UpdateWindow(hWindow);
911  return true;
912 }
913 
914 void C4ConsoleGUI::SetCaptionToFileName(const char* file_name)
915 {
916 }
917 
919 {
920  if (!Active)
921  return;
922  int dialog_item;
923  switch (type)
924  {
925  case CONSOLE_Cursor:
926  dialog_item = IDC_STATICCURSOR;
927  break;
929  dialog_item = IDC_STATICFRAME;
930  break;
931  case CONSOLE_TimeFPS:
932  dialog_item = IDC_STATICTIME;
933  break;
934  default:
935  assert(false);
936  return;
937  }
938  SetDlgItemTextW(hWindow,dialog_item,text.GetWideChar());
939  UpdateWindow(GetDlgItem(hWindow,dialog_item));
940 }
941 
942 bool C4ConsoleGUI::Message(const char *message, bool query)
943 {
944  return (IDOK==MessageBoxW(hWindow,GetWideChar(message),ADDL(C4ENGINECAPTION),query ? (MB_OKCANCEL | MB_ICONEXCLAMATION) : MB_ICONEXCLAMATION));
945 }
946 
948 {
949  EnableMenuItem(GetMenu(hWindow),IDM_FILE_RECORD, MF_BYCOMMAND | MF_GRAYED);
950 }
951 
953 {
954  StdStrBuf strMessage; strMessage.Format("%s %s\n\n%s", C4ENGINECAPTION, C4VERSION, copyright.getData());
955  MessageBoxW(nullptr, strMessage.GetWideChar(), ADDL(C4ENGINECAPTION), MB_ICONINFORMATION | MB_TASKMODAL);
956 }
957 
958 bool C4ConsoleGUI::FileSelect(StdStrBuf *sFilename, const char * szFilter, DWORD dwFlags, bool fSave)
959 {
960  enum { ArbitraryMaximumLength = 4096 };
961  wchar_t buffer[ArbitraryMaximumLength];
962  sFilename->ReplaceChar('/', '\\'); // GetSaveFileNameW has trouble with forward slashes
963  wcsncpy(buffer, sFilename->GetWideChar(), ArbitraryMaximumLength - 1);
964  buffer[ArbitraryMaximumLength - 1] = 0;
965  OPENFILENAMEW ofn;
966  ZeroMem(&ofn,sizeof(ofn));
967  ofn.lStructSize=sizeof(ofn);
968  ofn.hwndOwner=hWindow;
969  const char * s = szFilter;
970  while (*s) s = s + strlen(s) + 1;
971  s++;
972  int n = s - szFilter;
973  int len = MultiByteToWideChar(CP_UTF8, 0, szFilter, n, nullptr, 0);
974  StdBuf filt;
975  filt.SetSize(len * sizeof(wchar_t));
976  MultiByteToWideChar(CP_UTF8, 0, szFilter, n, getMBufPtr<wchar_t>(filt), len );
977  ofn.lpstrFilter=getMBufPtr<wchar_t>(filt);
978  ofn.lpstrFile=buffer;
979  ofn.nMaxFile=ArbitraryMaximumLength;
980  ofn.Flags=dwFlags;
981 
982  bool fResult;
983  size_t l = GetCurrentDirectoryW(0,0);
984  wchar_t *wd = new wchar_t[l];
985  GetCurrentDirectoryW(l,wd);
986  if (fSave)
987  fResult = !!GetSaveFileNameW(&ofn);
988  else
989  fResult = !!GetOpenFileNameW(&ofn);
990  // Reset working directory to exe path as Windows file dialog might have changed it
991  SetCurrentDirectoryW(wd);
992  delete[] wd;
993  len = WideCharToMultiByte(CP_UTF8, 0, buffer, ArbitraryMaximumLength, nullptr, 0, 0, 0);
994  sFilename->SetLength(len - 1);
995  WideCharToMultiByte(CP_UTF8, 0, buffer, ArbitraryMaximumLength, sFilename->getMData(), sFilename->getSize(), 0, 0);
996  return fResult;
997 }
998 
1000 {
1001  AddMenuItem(this, GetSubMenu(GetMenu(hWindow),state->MenuIndexViewport),IDM_VIEWPORT_NEW1+player->Number,player_text.getData(), true);
1002 }
1003 
1004 void C4ConsoleGUI::AddKickPlayerMenuItem(C4Player *player, StdStrBuf& player_text, bool enabled)
1005 {
1006  AddMenuItem(this, GetSubMenu(GetMenu(hWindow),state->MenuIndexPlayer),IDM_PLAYER_QUIT1+player->Number,player_text.getData(),(!::Network.isEnabled() || ::Network.isHost()) && Editing);
1007 }
1008 
1010 {
1011  if (!InsertMenuW(GetMenu(hWindow),state->MenuIndexHelp,MF_BYPOSITION | MF_POPUP,(UINT_PTR)CreateMenu(),LoadResStrW("IDS_MNU_NET"))) return;
1012  state->MenuIndexNet=state->MenuIndexHelp;
1013  state->MenuIndexHelp++;
1014  DrawMenuBar(hWindow);
1015 }
1016 
1018 {
1019  if (state->MenuIndexNet<0) return;
1020  DeleteMenu(GetMenu(hWindow),state->MenuIndexNet,MF_BYPOSITION);
1021  state->MenuIndexNet=-1;
1022  state->MenuIndexHelp--;
1023  DrawMenuBar(hWindow);
1024 }
1025 
1026 void C4ConsoleGUI::AddNetMenuItemForPlayer(int32_t client_id, const char *text, C4ConsoleGUI::ClientOperation op)
1027 {
1028  AddMenuItem(this, GetSubMenu(GetMenu(hWindow),state->MenuIndexNet), IDM_NET_CLIENT1+Game.Clients.getLocalID(), text, true);
1029 }
1030 
1032 {
1033  HMENU hMenu = GetSubMenu(GetMenu(hWindow),state->MenuIndexViewport);
1034  while (DeleteMenu(hMenu,1,MF_BYPOSITION));
1035 }
1036 
1038 {
1039  if (Console.ToolsDlg.state)
1040  Console.ToolsDlg.state->Clear();
1041 }
1042 
1044 {
1045  if (state->hPropertyDlg) return true;
1046  HWND hDialog = CreateDialog(Application.GetInstance(),
1047  MAKEINTRESOURCE(IDD_PROPERTIES),
1048  Console.hWindow,
1049  PropertyDlgProc);
1050  if (!hDialog) return false;
1051  state->hPropertyDlg = hDialog;
1052  // Remember initial layout
1053  state->PropertyDlgInitLayout();
1054  // Set text
1055  SetWindowTextW(hDialog,LoadResStrW("IDS_DLG_PROPERTIES"));
1056  // Enable controls
1057  EnableWindow( GetDlgItem(hDialog,IDOK), Editing );
1058  EnableWindow( GetDlgItem(hDialog,IDC_COMBOINPUT), Editing );
1059  EnableWindow( GetDlgItem(hDialog,IDC_BUTTONRELOADDEF), Editing );
1060  // Show window
1061  RestoreWindowPosition(hDialog, "Property", Config.GetSubkeyPath("Console"));
1062  SetWindowPos(hDialog,hWindow,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE);
1063  ShowWindow(hDialog,SW_SHOWNOACTIVATE);
1064  return true;
1065 }
1066 
1068 {
1069  ::ClearDlg(state->hPropertyDlg);
1070 }
1071 
1072 static void SetComboItems(HWND hCombo, std::list<const char*> &items)
1073 {
1074  for (std::list<const char*>::iterator it = items.begin(); it != items.end(); it++)
1075  {
1076  if (!*it)
1077  SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)L"----------");
1078  else
1079  SendMessage(hCombo,CB_ADDSTRING,0,GetWideLPARAM(*it));
1080  }
1081 }
1082 
1083 void C4ConsoleGUI::PropertyDlgUpdate(C4EditCursorSelection &rSelection, bool force_function_update)
1084 {
1085  HWND hDialog = state->hPropertyDlg;
1086  if (!hDialog) return;
1087  int iLine = SendDlgItemMessage(hDialog,IDC_EDITOUTPUT,EM_GETFIRSTVISIBLELINE,(WPARAM)0,(LPARAM)0);
1088  SetDlgItemTextW(hDialog,IDC_EDITOUTPUT,rSelection.GetDataString().GetWideChar());
1089  SendDlgItemMessage(hDialog,IDC_EDITOUTPUT,EM_LINESCROLL,(WPARAM)0,(LPARAM)iLine);
1090  UpdateWindow(GetDlgItem(hDialog,IDC_EDITOUTPUT));
1091 
1092  if (PropertyDlgObject == rSelection.GetObject() && !force_function_update) return;
1093  PropertyDlgObject = rSelection.GetObject();
1094 
1095  std::list<const char *> functions = ::Console.GetScriptSuggestions(PropertyDlgObject, C4Console::MRU_Object);
1096 
1097  HWND hCombo = GetDlgItem(state->hPropertyDlg, IDC_COMBOINPUT);
1098  wchar_t szLastText[500+1];
1099  // Remember old window text
1100  GetWindowTextW(hCombo, szLastText, 500);
1101  // Clear
1102  SendMessage(hCombo, CB_RESETCONTENT, 0, 0);
1103 
1104  SetComboItems(GetDlgItem(state->hPropertyDlg,IDC_COMBOINPUT), functions);
1105 
1106  // Restore
1107  SetWindowTextW(hCombo, szLastText);
1108 }
1109 
1110 void C4ConsoleGUI::SetInputFunctions(std::list<const char*> &functions)
1111 {
1112  HWND hCombo = GetDlgItem(hWindow, IDC_COMBOINPUT);
1113  SendMessage(hCombo, CB_RESETCONTENT, 0, 0);
1114  SetComboItems(hCombo, functions);
1115 }
1116 
1118 {
1119  if (!Active) return;
1120  HMENU hMenu = GetSubMenu(GetMenu(hWindow),state->MenuIndexPlayer);
1121  while (DeleteMenu(hMenu,1,MF_BYPOSITION));
1122 }
1123 
1124 /*
1125 void C4ConsoleGUI::ClearPropertyDlg(C4PropertyDlg *dlg)
1126 {
1127  if (dlg->state->hDialog) DestroyWindow(PropertyDlg.hDialog); PropertyDlg.hDialog=nullptr;
1128 }
1129 */
1130 
1131 // Wrapper window around preview control: Used to create GL context and target surface
1133 {
1134 public:
1135  C4ConsoleGUIPreviewWindow(HWND hwndControl)
1136  {
1137  Init(C4Window::WindowKind::W_Control, &Application, nullptr, nullptr);
1138  this->hWindow = this->renderwnd = hwndControl;
1139  pSurface = new C4Surface(&Application, this);
1140  }
1141 
1143  {
1144  delete pSurface;
1145  }
1146 
1147  virtual void Close() {}
1148 };
1149 
1151 {
1152  if (dlg->state->hDialog) return true;
1153  dlg->state->hDialog = CreateDialog(Application.GetInstance(),
1154  MAKEINTRESOURCE(IDD_TOOLS),
1155  Console.hWindow,
1156  ToolsDlgProc);
1157  if (!dlg->state->hDialog) return false;
1158  // Set text
1159  SetWindowTextW(dlg->state->hDialog,LoadResStrW("IDS_DLG_TOOLS"));
1160  SetDlgItemTextW(dlg->state->hDialog,IDC_STATICMATERIAL,LoadResStrW("IDS_CTL_MATERIAL"));
1161  SetDlgItemTextW(dlg->state->hDialog,IDC_STATICTEXTURE,LoadResStrW("IDS_CTL_TEXTURE"));
1162  SetDlgItemTextW(dlg->state->hDialog, IDC_STATICFOREGROUND, LoadResStrW("IDS_CTL_FOREGROUND"));
1163  SetDlgItemTextW(dlg->state->hDialog, IDC_STATICBACKGROUND, LoadResStrW("IDS_CTL_BACKGROUND"));
1164  // Load bitmaps if necessary
1165  dlg->state->LoadBitmaps(Application.GetInstance());
1166  // create target ctx for OpenGL rendering
1167  if (pDraw && !dlg->state->pPreviewWindow)
1168  {
1169  dlg->state->pPreviewWindow = new C4ConsoleGUIPreviewWindow(GetDlgItem(dlg->state->hDialog, IDC_PREVIEW));
1170  }
1171  // Show window
1172  RestoreWindowPosition(dlg->state->hDialog, "Tools", Config.GetSubkeyPath("Console"));
1173  SetWindowPos(dlg->state->hDialog,Console.hWindow,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE);
1174  ShowWindow(dlg->state->hDialog,SW_SHOWNOACTIVATE);
1175  return true;
1176 }
1177 
1179 {
1180  // All foreground materials
1181  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOFGMATERIAL,CB_ADDSTRING,0,GetWideLPARAM(C4TLS_MatSky));
1182  for (int32_t cnt = 0; cnt < ::MaterialMap.Num; cnt++)
1183  {
1184  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOFGMATERIAL, CB_ADDSTRING, 0, GetWideLPARAM(::MaterialMap.Map[cnt].Name));
1185  }
1186  // Background materials: True background materials first; then the "funny" stuff
1187  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOBGMATERIAL, CB_ADDSTRING, 0, GetWideLPARAM(C4TLS_MatSky));
1188  for (int32_t cnt = 0; cnt < ::MaterialMap.Num; cnt++)
1189  {
1190  if (::MaterialMap.Map[cnt].Density == C4M_Background)
1191  {
1192  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOBGMATERIAL, CB_ADDSTRING, 0, GetWideLPARAM(::MaterialMap.Map[cnt].Name));
1193  }
1194  }
1195  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOBGMATERIAL, CB_ADDSTRING, 0, (LPARAM)L"----------");
1196  for (int32_t cnt = 0; cnt < ::MaterialMap.Num; cnt++)
1197  {
1198  if (::MaterialMap.Map[cnt].Density != C4M_Background)
1199  {
1200  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOBGMATERIAL, CB_ADDSTRING, 0, GetWideLPARAM(::MaterialMap.Map[cnt].Name));
1201  }
1202  }
1203  // Select current materials
1204  SendDlgItemMessage(dlg->state->hDialog,IDC_COMBOFGMATERIAL,CB_SELECTSTRING,0,GetWideLPARAM(dlg->Material));
1205  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOBGMATERIAL, CB_SELECTSTRING, 0, GetWideLPARAM(dlg->BackMaterial));
1206 }
1207 
1209 {
1210  HWND hDialog = state->hDialog;
1211  int32_t Tool = this->Tool;
1212  SendDlgItemMessage(hDialog,IDC_BUTTONBRUSH,BM_SETSTATE,(Tool==C4TLS_Brush),0);
1213  UpdateWindow(GetDlgItem(hDialog,IDC_BUTTONBRUSH));
1214  SendDlgItemMessage(hDialog,IDC_BUTTONLINE,BM_SETSTATE,(Tool==C4TLS_Line),0);
1215  UpdateWindow(GetDlgItem(hDialog,IDC_BUTTONLINE));
1216  SendDlgItemMessage(hDialog,IDC_BUTTONRECT,BM_SETSTATE,(Tool==C4TLS_Rect),0);
1217  UpdateWindow(GetDlgItem(hDialog,IDC_BUTTONRECT));
1218  SendDlgItemMessage(hDialog,IDC_BUTTONFILL,BM_SETSTATE,(Tool==C4TLS_Fill),0);
1219  UpdateWindow(GetDlgItem(hDialog,IDC_BUTTONFILL));
1220  SendDlgItemMessage(hDialog,IDC_BUTTONPICKER,BM_SETSTATE,(Tool==C4TLS_Picker),0);
1221  UpdateWindow(GetDlgItem(hDialog,IDC_BUTTONPICKER));
1222 }
1223 
1224 void C4ConsoleGUI::ToolsDlgSelectTexture(C4ToolsDlg *dlg, const char *texture)
1225 {
1226  SendDlgItemMessage(dlg->state->hDialog,IDC_COMBOFGTEXTURE,CB_SELECTSTRING,0,GetWideLPARAM(texture));
1227 }
1228 
1229 void C4ConsoleGUI::ToolsDlgSelectMaterial(C4ToolsDlg *dlg, const char *material)
1230 {
1231  SendDlgItemMessage(dlg->state->hDialog,IDC_COMBOFGMATERIAL,CB_SELECTSTRING,0,GetWideLPARAM(material));
1232 }
1233 
1234 void C4ConsoleGUI::ToolsDlgSelectBackTexture(C4ToolsDlg *dlg, const char *texture)
1235 {
1236  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOBGTEXTURE, CB_SELECTSTRING, 0, GetWideLPARAM(texture));
1237 }
1238 
1239 void C4ConsoleGUI::ToolsDlgSelectBackMaterial(C4ToolsDlg *dlg, const char *material)
1240 {
1241  SendDlgItemMessage(dlg->state->hDialog, IDC_COMBOBGMATERIAL, CB_SELECTSTRING, 0, GetWideLPARAM(material));
1242 }
1243 
1245 {
1246  // Refill foreground and background combo boxes in dlg
1247  WORD boxes[2] = { IDC_COMBOFGTEXTURE, IDC_COMBOBGTEXTURE };
1248  const char *materials[2] = { Material, BackMaterial };
1249  const char *textures[2] = { Texture, BackTexture };
1250  for (int i = 0; i < 2; ++i)
1251  {
1252  WORD box = boxes[i];
1253  const char *material = materials[i];
1254  const char *texture = textures[i];
1255  // clear previous
1256  SendDlgItemMessage(state->hDialog, box, CB_RESETCONTENT, 0, (LPARAM)0);
1257  // bottom-most: any invalid textures
1258  bool fAnyEntry = false; int32_t cnt; const char *szTexture;
1260  for (cnt = 0; (szTexture = ::TextureMap.GetTexture(cnt)); cnt++)
1261  {
1262  if (!::TextureMap.GetIndex(material, szTexture, false))
1263  {
1264  // hide normal maps from texture selection
1265  // theoretically, they could be used for drawing but they clutter the list and they don't look good
1266  if (!WildcardMatch("*_NRM", szTexture))
1267  {
1268  fAnyEntry = true;
1269  SendDlgItemMessage(state->hDialog, box, CB_INSERTSTRING, 0, GetWideLPARAM(szTexture));
1270  }
1271  }
1272  }
1273  // separator
1274  if (fAnyEntry)
1275  {
1276  SendDlgItemMessage(state->hDialog, box, CB_INSERTSTRING, 0, (LPARAM)L"-------");
1277  }
1278 
1279  // atop: valid textures
1280  for (cnt = 0; (szTexture = ::TextureMap.GetTexture(cnt)); cnt++)
1281  {
1282  // Current material-texture valid? Always valid for exact mode
1283  if (::TextureMap.GetIndex(material, szTexture, false) || ::Landscape.GetMode() == LandscapeMode::Exact)
1284  {
1285  SendDlgItemMessage(state->hDialog, box, CB_INSERTSTRING, 0, GetWideLPARAM(szTexture));
1286  }
1287  }
1288  // reselect current
1289  SendDlgItemMessage(state->hDialog, box, CB_SELECTSTRING, -1, GetWideLPARAM(texture));
1290  }
1291 }
1292 
1294 {
1295  if (!state->hDialog || !state->pPreviewWindow) return;
1296 
1297  C4Surface * sfcPreview = state->pPreviewWindow->pSurface;
1298  if (!sfcPreview) return;
1299 
1300  int32_t iPrvWdt,iPrvHgt;
1301  RECT rect;
1302 
1303  GetClientRect(GetDlgItem(state->hDialog,IDC_PREVIEW),&rect);
1304 
1305  iPrvWdt=rect.right-rect.left;
1306  iPrvHgt=rect.bottom-rect.top;
1307 
1308  if (!sfcPreview->UpdateSize(iPrvWdt, iPrvHgt)) return;
1309  sfcPreview->NoClip();
1310  if (!pDraw->PrepareRendering(sfcPreview)) return;
1311 
1312  // fill bg
1313  pDraw->DrawBoxDw(sfcPreview,0,0,iPrvWdt-1,iPrvHgt-1,C4RGB(0xa0,0xa0,0xa0));
1314  BYTE bCol = 0;
1315  C4Pattern Pattern;
1316  // Sky material: sky as pattern only
1318  {
1319  Pattern.Set(::Landscape.GetSky().Surface, 0);
1320  }
1321  // Material-Texture
1322  else
1323  {
1325  // Get/Create TexMap entry
1326  BYTE iTex = ::TextureMap.GetIndex(Material, Texture, true);
1327  if (iTex)
1328  {
1329  // Define texture pattern
1330  const C4TexMapEntry *pTex = ::TextureMap.GetEntry(iTex);
1331  // Security
1332  if (pTex)
1333  {
1334  // Set drawing pattern
1335  Pattern = pTex->GetPattern();
1336  }
1337  }
1338  }
1339  if (IsWindowEnabled(GetDlgItem(state->hDialog,IDC_PREVIEW)))
1340  pDraw->DrawPatternedCircle( sfcPreview,
1341  iPrvWdt/2,iPrvHgt/2,
1342  Grade,
1343  bCol, Pattern, *::Landscape.GetPal());
1344 
1345  sfcPreview->PageFlip();
1346 }
1347 
1349 {
1350  if (!state->hDialog) return;
1351  HWND hwndTrack = GetDlgItem(state->hDialog,IDC_SLIDERGRADE);
1352  SendMessage(hwndTrack,TBM_SETPAGESIZE,0,(LPARAM)5);
1353  SendMessage(hwndTrack,TBM_SETLINESIZE,0,(LPARAM)1);
1354  SendMessage(hwndTrack,TBM_SETRANGE,(WPARAM)false,
1355  (LPARAM) MAKELONG(C4TLS_GradeMin,C4TLS_GradeMax));
1356  SendMessage(hwndTrack,TBM_SETPOS,(WPARAM)true,(LPARAM)C4TLS_GradeMax-Grade);
1357  UpdateWindow(hwndTrack);
1358 }
1359 
1361 {
1362  if (!state->hDialog) return false;
1363  SetFocus(GetDlgItem(state->hDialog,IDC_COMBOFGMATERIAL));
1364  SendDlgItemMessage(state->hDialog,IDC_COMBOFGMATERIAL,CB_SHOWDROPDOWN,true,0);
1365  return true;
1366 }
1367 
1369 {
1370  if (!state->hDialog) return false;
1371  SetFocus(GetDlgItem(state->hDialog,IDC_COMBOFGTEXTURE));
1372  SendDlgItemMessage(state->hDialog,IDC_COMBOFGTEXTURE,CB_SHOWDROPDOWN,true,0);
1373  return true;
1374 }
1375 
1377 {
1378  // not using IFT
1379 }
1380 
1382 {
1383  LandscapeMode iMode = ::Landscape.GetMode();
1384  // Dynamic: enable only if dynamic anyway
1385  SendDlgItemMessage(state->hDialog,IDC_BUTTONMODEDYNAMIC,BM_SETSTATE,(iMode==LandscapeMode::Dynamic),0);
1386  EnableWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODEDYNAMIC),(iMode==LandscapeMode::Dynamic));
1387  UpdateWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODEDYNAMIC));
1388  // Static: enable only if map available
1389  SendDlgItemMessage(state->hDialog,IDC_BUTTONMODESTATIC,BM_SETSTATE,(iMode==LandscapeMode::Static),0);
1390  EnableWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODESTATIC),(::Landscape.HasMap()));
1391  UpdateWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODESTATIC));
1392  // Exact: enable always
1393  SendDlgItemMessage(state->hDialog,IDC_BUTTONMODEEXACT,BM_SETSTATE,(iMode==LandscapeMode::Exact),0);
1394  UpdateWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODEEXACT));
1395  // Set dialog caption
1396  SetWindowTextW(state->hDialog,LoadResStrW(iMode==LandscapeMode::Dynamic ? "IDS_DLG_DYNAMIC" : iMode==LandscapeMode::Static ? "IDS_DLG_STATIC" : "IDS_DLG_EXACT"));
1397 }
1398 
1399 
1401 {
1402  HWND hDialog = state->hDialog;
1403  LandscapeMode iLandscapeMode = ::Landscape.GetMode();
1404  // Set bitmap buttons
1405  SendDlgItemMessage(hDialog,IDC_BUTTONBRUSH,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Static) ? state->hbmBrush : state->hbmBrush2));
1406  SendDlgItemMessage(hDialog,IDC_BUTTONLINE,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Static) ? state->hbmLine : state->hbmLine2));
1407  SendDlgItemMessage(hDialog,IDC_BUTTONRECT,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Static) ? state->hbmRect : state->hbmRect2));
1408  SendDlgItemMessage(hDialog,IDC_BUTTONFILL,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Exact) ? state->hbmFill : state->hbmFill2));
1409  SendDlgItemMessage(hDialog,IDC_BUTTONPICKER,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Static) ? state->hbmPicker : state->hbmPicker2));
1410  SendDlgItemMessage(hDialog,IDC_BUTTONMODEDYNAMIC,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)state->hbmDynamic);
1411  SendDlgItemMessage(hDialog,IDC_BUTTONMODESTATIC,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)state->hbmStatic);
1412  SendDlgItemMessage(hDialog,IDC_BUTTONMODEEXACT,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)state->hbmExact);
1413  // Enable drawing controls
1414  EnableWindow(GetDlgItem(hDialog,IDC_BUTTONBRUSH),(iLandscapeMode>=LandscapeMode::Static));
1415  EnableWindow(GetDlgItem(hDialog,IDC_BUTTONLINE),(iLandscapeMode>=LandscapeMode::Static));
1416  EnableWindow(GetDlgItem(hDialog,IDC_BUTTONRECT),(iLandscapeMode>=LandscapeMode::Static));
1417  EnableWindow(GetDlgItem(hDialog,IDC_BUTTONFILL),(iLandscapeMode>=LandscapeMode::Exact));
1418  EnableWindow(GetDlgItem(hDialog,IDC_BUTTONPICKER),(iLandscapeMode>=LandscapeMode::Static));
1419  EnableWindow(GetDlgItem(hDialog,IDC_COMBOFGMATERIAL),(iLandscapeMode>=LandscapeMode::Static));
1420  EnableWindow(GetDlgItem(hDialog,IDC_COMBOFGTEXTURE),(iLandscapeMode>=LandscapeMode::Static) && !SEqual(Material,C4TLS_MatSky));
1421  EnableWindow(GetDlgItem(hDialog,IDC_COMBOBGMATERIAL), (iLandscapeMode >= LandscapeMode::Static) && !SEqual(Material, C4TLS_MatSky));
1422  EnableWindow(GetDlgItem(hDialog, IDC_COMBOBGTEXTURE), (iLandscapeMode >= LandscapeMode::Static) && !SEqual(Material, C4TLS_MatSky) && !SEqual(BackMaterial, C4TLS_MatSky));
1423  EnableWindow(GetDlgItem(hDialog,IDC_STATICMATERIAL),(iLandscapeMode>=LandscapeMode::Static));
1424  EnableWindow(GetDlgItem(hDialog,IDC_STATICTEXTURE),(iLandscapeMode>=LandscapeMode::Static) && !SEqual(Material,C4TLS_MatSky));
1425  EnableWindow(GetDlgItem(hDialog,IDC_STATICFOREGROUND), (iLandscapeMode >= LandscapeMode::Static));
1426  EnableWindow(GetDlgItem(hDialog,IDC_STATICBACKGROUND), (iLandscapeMode >= LandscapeMode::Static));
1427  EnableWindow(GetDlgItem(hDialog,IDC_SLIDERGRADE),(iLandscapeMode>=LandscapeMode::Static));
1428  EnableWindow(GetDlgItem(hDialog,IDC_PREVIEW),(iLandscapeMode>=LandscapeMode::Static));
1429 
1431 }
1432 
1433 #include "editor/C4ConsoleGUICommon.h"
bool FileSaveAs(bool fSaveGame, bool export_packed=false)
Definition: C4Console.cpp:274
#define IDC_STATICTEXTURE
Definition: resource.h:50
const char * getData() const
Definition: StdBuf.h:450
C4EditCursor EditCursor
Definition: C4Console.h:90
#define IDD_TOOLS
Definition: resource.h:67
void LoadBitmaps(HINSTANCE instance)
void EnableControls(bool fEnable)
Definition: C4ConsoleGUI.h:144
bool IsRunning
Definition: C4Game.h:141
#define IDB_HALT2
Definition: resource.h:14
#define IDC_STATICMATERIAL
Definition: resource.h:49
#define IDI_00_C4X
Definition: resource.h:69
#define IDM_NET_CLIENT2
Definition: C4Console.h:36
INT_PTR CALLBACK ConsoleDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
#define IDC_BUTTONRECT
Definition: resource.h:38
C4Config Config
Definition: C4Config.cpp:837
#define IDC_COMBOBGMATERIAL
Definition: resource.h:62
Definition: StdBuf.h:37
bool SetGrade(int32_t iGrade)
Definition: C4ToolsDlg.cpp:165
bool SetMode(int32_t iMode)
C4ID id
Definition: C4Object.h:108
#define WM_USER_RELOADFILE
bool In(const char *szText)
#define IDB_PICKER
Definition: resource.h:19
C4Console Console
Definition: C4Globals.cpp:45
bool isHost() const
Definition: C4Network2.h:209
#define IDM_FILE_QUIT
Definition: resource.h:84
#define IDD_CONSOLE
Definition: resource.h:65
class C4Surface * Surface
Definition: C4Sky.h:53
void SetCaptionToFileName(const char *file_name)
Definition: C4Console.cpp:694
bool PopMaterial()
Definition: C4Console.cpp:708
bool isCtrlHost() const
Definition: C4GameControl.h:99
C4Game Game
Definition: C4Globals.cpp:52
int32_t Number
Definition: C4Player.h:88
void HelpAbout()
Definition: C4Console.cpp:454
#define IDB_FILL
Definition: resource.h:11
bool isLobbyActive() const
Definition: C4Network2.h:204
#define IDB_PICKER2
Definition: resource.h:20
StdStrBuf::wchar_t_holder GetWideChar(const char *utf8, bool double_null_terminate=false)
INT_PTR CALLBACK ToolsDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
const char * GetSubkeyPath(const char *strSubkey)
Definition: C4Config.cpp:717
void DeleteConsoleWindow()
Definition: C4Console.cpp:683
C4ToolsDlg ToolsDlg
Definition: C4Console.h:88
C4Surface * pSurface
Definition: C4Window.h:279
void ToolsDlgSelectMaterial(C4ToolsDlg *dlg, const char *material)
Definition: C4Console.cpp:700
#define IDB_MOUSE
Definition: resource.h:17
C4Material * Map
Definition: C4Material.h:171
void ToolsDlgSelectBackTexture(C4ToolsDlg *dlg, const char *texture)
Definition: C4Console.cpp:703
void UpdateMenuText(C4ConsoleGUI &console, HMENU hMenu)
C4Window * pPreviewWindow
void SetTitle(const char *Title)
Definition: C4AppT.cpp:112
void Add(C4PacketType eType, C4ControlPacket *pCtrl)
Definition: C4Control.h:82
#define IDC_BUTTONPLAY
Definition: resource.h:37
friend INT_PTR CALLBACK ToolsDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
#define IDB_RECT2
Definition: resource.h:24
void RegisterRecentInput(const char *input, RecentScriptInputLists section)
Definition: C4Console.cpp:644
#define IDC_BUTTONFILL
Definition: resource.h:27
bool HasMap() const
#define IDC_COMBOBGTEXTURE
Definition: resource.h:63
void ToolsDlgInitMaterialCtrls(class C4ToolsDlg *dlg)
Definition: C4Console.cpp:698
uint8_t BYTE
bool DoUpdateHaltCtrls(bool fHalt)
Definition: C4Console.cpp:686
#define IDM_PLAYER_QUIT1
Definition: C4Console.h:37
C4EditCursorSelection & GetSelection()
Definition: C4EditCursor.h:105
void DoHalt()
Definition: C4Console.cpp:105
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:181
#define IDB_PLAY2
Definition: resource.h:22
C4TextureMap TextureMap
Definition: C4Texture.cpp:580
#define IDM_PLAYER_QUIT2
Definition: C4Console.h:38
#define WM_USER_LOG
C4ConsoleGUIPreviewWindow(HWND hwndControl)
#define IDM_FILE_SAVEGAMEAS
Definition: resource.h:87
virtual void OnKeyboardLayoutChanged()
#define IDC_STATICTIME
Definition: resource.h:51
void SetTexture(const char *szTexture)
Definition: C4ToolsDlg.cpp:70
int GetCount() const
bool FileClose()
Definition: C4Console.cpp:387
#define IDB_MOUSE2
Definition: resource.h:18
const C4TexMapEntry * GetEntry(int32_t iIndex) const
Definition: C4Texture.h:85
Definition: C4Texture.h:48
#define IDC_EDITOUTPUT
Definition: resource.h:44
const int C4CNS_ModeEdit
Definition: C4Console.h:31
#define IDM_PLAYER_JOIN
Definition: resource.h:89
void CtrlRemove(const C4Client *pClient, const char *szReason)
Definition: C4Client.cpp:350
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:97
#define IDM_NET_CLIENT1
Definition: C4Console.h:35
void PropertyDlgUpdate(class C4EditCursorSelection &rSelection, bool force_function_update)
Definition: C4Console.cpp:692
bool PropertyDlgOpen()
Definition: C4Console.cpp:690
size_t getSize() const
Definition: StdBuf.h:109
void SetSize(size_t inSize)
Definition: StdBuf.h:212
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
int32_t GetIndex(const char *szMaterial, const char *szTexture, bool fAddIfNotExist=true, const char *szErrorIfFailed=nullptr)
Definition: C4Texture.cpp:423
char * getMData()
Definition: StdBuf.h:451
#define IDM_VIEWPORT_NEW2
Definition: C4Console.h:40
#define IDC_BUTTONPICKER
Definition: resource.h:36
#define IDM_FILE_OPEN
Definition: resource.h:82
void UpdateInputCtrl()
Definition: C4Console.cpp:486
#define IDC_STATICCURSOR
Definition: resource.h:47
const int32_t C4TLS_Rect
Definition: C4ToolsDlg.h:30
int32_t Grade
Definition: C4ToolsDlg.h:54
const C4Pattern & GetPattern() const
Definition: C4Texture.h:64
C4Object * GetObject(int32_t index=0) const
virtual bool PrepareRendering(C4Surface *sfcToSurface)=0
char Texture[C4M_MaxName+1]
Definition: C4ToolsDlg.h:57
void ClearNetMenu()
Definition: C4Console.cpp:673
void ToolsDlgSelectTexture(C4ToolsDlg *dlg, const char *texture)
Definition: C4Console.cpp:701
C4Player * Get(int iPlayer) const
#define IDC_BUTTONMODEDRAW
Definition: resource.h:30
#define IDM_VIEWPORT_NEW
Definition: resource.h:93
void ShowAboutWithCopyright(StdStrBuf &copyright)
Definition: C4Console.cpp:697
virtual void Quit()
#define IDB_CURSOR2
Definition: resource.h:8
#define IDB_BRUSH
Definition: resource.h:5
BOOL RegisterConsoleWindowClass(HINSTANCE hInst)
C4Network2 Network
Definition: C4Globals.cpp:53
bool UpdateSize(int wdt, int hgt)
Definition: C4Surface.cpp:311
bool Active
Definition: C4App.h:63
char Name[C4M_MaxName+1]
Definition: C4Material.h:91
const int32_t C4TLS_Picker
Definition: C4ToolsDlg.h:32
#define IDM_FILE_OPENWPLRS
Definition: resource.h:83
C4Object * PropertyDlgObject
Definition: C4ConsoleGUI.h:165
int32_t getLocalID() const
Definition: C4Client.h:171
bool PageFlip(C4Rect *pSrcRt=nullptr, C4Rect *pDstRt=nullptr)
Definition: C4Surface.cpp:320
bool SetMenuItemText(HMENU hMenu, WORD id, const char *szText)
void DoPlay()
Definition: C4Console.cpp:100
C4GameControl Control
C4Landscape Landscape
#define IDC_PREVIEW
Definition: resource.h:45
#define IDC_BUTTONMODEEXACT
Definition: resource.h:33
void DrawBoxDw(C4Surface *sfcDest, int iX1, int iY1, int iX2, int iY2, DWORD dwClr)
Definition: C4Draw.cpp:849
static C4ControlPlayerAction * Eliminate(const C4Player *source)
Definition: C4Control.cpp:574
#define IDM_HELP_ABOUT
Definition: resource.h:88
const int C4CNS_ModePlay
Definition: C4Console.h:30
char Material[C4M_MaxName+1]
Definition: C4ToolsDlg.h:56
#define IDC_STATICBACKGROUND
Definition: resource.h:61
C4Control Input
Definition: C4GameControl.h:66
C4PlayerList Players
const int32_t C4TLS_GradeMin
Definition: C4ToolsDlg.h:36
class C4Sky & GetSky()
void ViewportNew()
Definition: C4Console.cpp:461
bool IsRuntimeRecordPossible() const
void Out(const char *message)
Definition: C4Console.cpp:689
C4Draw * pDraw
Definition: C4Draw.cpp:45
#define IDB_LINE
Definition: resource.h:15
const int C4CNS_ModeDraw
Definition: C4Console.h:33
bool ReloadDef(C4ID id)
Definition: C4Game.cpp:2019
#define C4RGB(r, g, b)
Definition: StdColors.h:28
const int32_t C4TLS_GradeMax
Definition: C4ToolsDlg.h:35
int32_t Num
Definition: C4Material.h:170
#define IDB_HALT
Definition: resource.h:13
void CreateBitmaps(C4AbstractApp *application)
bool ReloadFile(const char *szPath)
Definition: C4Game.cpp:2002
bool In(const char *szText)
Definition: C4Console.cpp:70
#define IDB_FILL2
Definition: resource.h:12
void SetBackMaterial(const char *szMaterial)
Definition: C4ToolsDlg.cpp:105
bool AddMenuItem(C4ConsoleGUI *console, HMENU hMenu, DWORD dwID, const char *szString, bool fEnabled)
bool isEnabled() const
Definition: C4Network2.h:203
bool CreateViewport(int32_t iPlayer, bool fSilent=false)
Definition: C4Viewport.cpp:920
void ToolsDlgSelectBackMaterial(C4ToolsDlg *dlg, const char *material)
Definition: C4Console.cpp:702
int ReplaceChar(char cOld, char cNew)
Definition: StdBuf.cpp:343
State(C4ConsoleGUI *console)
LandscapeMode GetMode() const
std::list< const char * > GetScriptSuggestions(class C4PropList *target, RecentScriptInputLists section) const
Definition: C4Console.cpp:627
void InitGradeCtrl()
Definition: C4Console.cpp:706
bool Message(const char *message, bool query)
Definition: C4Console.cpp:688
bool FileOpenWPlrs()
Definition: C4Console.cpp:348
#define IDM_FILE_SAVE
Definition: resource.h:85
void AddNetMenuItemForPlayer(int32_t client_id, const char *text, C4ConsoleGUI::ClientOperation co)
Definition: C4Console.cpp:669
bool FileRecord()
Definition: C4Console.cpp:399
int32_t Density
Definition: C4Material.h:94
#define IDC_BUTTONLINE
Definition: resource.h:29
void UpdateIFTControls()
Definition: C4Console.cpp:710
void AddKickPlayerMenuItem(C4Player *player, StdStrBuf &player_text, bool enabled)
Definition: C4Console.cpp:667
bool ModeBack
Definition: C4ToolsDlg.h:58
bool ToolsDlgOpen(class C4ToolsDlg *dlg)
Definition: C4Console.cpp:699
#define IDB_DYNAMIC
Definition: resource.h:9
bool SetLandscapeMode(LandscapeMode iMode, bool flat_chunk_shapes, bool fThroughControl=false)
Definition: C4ToolsDlg.cpp:180
LandscapeMode
Definition: C4Landscape.h:30
bool FileOpen(const char *filename=nullptr, bool host_in_network=false)
Definition: C4Console.cpp:324
void ClearViewportMenu()
Definition: C4Console.cpp:675
#define IDM_FILE_SAVEAS
Definition: resource.h:86
int32_t Get(const char *szMaterial)
Definition: C4Material.cpp:362
void NeedPreviewUpdate()
Definition: C4Console.cpp:707
C4ViewportList Viewports
Definition: C4Viewport.cpp:841
const char * GetTexture(int32_t iIndex)
Definition: C4Texture.cpp:503
const int32_t C4TLS_Brush
Definition: C4ToolsDlg.h:28
#define IDC_STATICFRAME
Definition: resource.h:48
#define IDC_BUTTONBRUSH
Definition: resource.h:26
C4Client * getClientByID(int32_t iID) const
Definition: C4Client.cpp:217
void SetBackTexture(const char *szTexture)
Definition: C4ToolsDlg.cpp:115
#define ADDL(s)
StdBuf GetWideCharBuf(const char *utf8)
#define IDB_LINE2
Definition: resource.h:16
#define IDC_BUTTONMODESTATIC
Definition: resource.h:35
#define IDM_VIEWPORT_NEW1
Definition: C4Console.h:39
size_t getSize() const
Definition: StdBuf.h:452
bool UpdateModeCtrls(int iMode)
Definition: C4Console.cpp:704
void UpdateToolCtrls()
Definition: C4Console.cpp:713
#define IDC_COMBOFGTEXTURE
Definition: resource.h:42
const int32_t C4TLS_Fill
Definition: C4ToolsDlg.h:31
void UpdateLandscapeModeCtrls()
Definition: C4Console.cpp:711
void RecordingEnabled()
Definition: C4Console.cpp:693
#define IDC_BUTTONMODEEDIT
Definition: resource.h:32
bool CreateConsoleWindow(C4AbstractApp *application)
Definition: C4Console.cpp:676
#define IDC_COMBOINPUT
Definition: resource.h:40
#define IDC_SLIDERGRADE
Definition: resource.h:46
#define IDC_BUTTONHALT
Definition: resource.h:28
#define IDB_STATIC
Definition: resource.h:25
bool WildcardMatch(const char *szWildcard, const char *szString)
Definition: StdFile.cpp:384
bool UpdateHaltCtrls(bool fHalt)
Definition: C4ConsoleGUI.h:153
bool PopTextures()
Definition: C4Console.cpp:709
C4MaterialMap MaterialMap
Definition: C4Material.cpp:970
CStdPalette * GetPal() const
bool Active
Definition: C4Window.h:278
bool Log(const char *szMessage)
Definition: C4Log.cpp:195
bool FileSave()
Definition: C4Console.cpp:267
bool SEqual2(const char *szStr1, const char *szStr2)
Definition: Standard.cpp:168
C4ClientList & Clients
Definition: C4Game.h:71
char BackMaterial[C4M_MaxName+1]
Definition: C4ToolsDlg.h:59
BYTE Mat2PixColDefault(int32_t mat)
Definition: C4Material.h:237
void SetInputFunctions(std::list< const char * > &functions)
Definition: C4Console.cpp:696
bool FileSelect(StdStrBuf *sFilename, const char *szFilter, DWORD dwFlags, bool fSave)
Definition: C4Console.cpp:687
virtual C4Window * Init(WindowKind windowKind, C4AbstractApp *pApp, const char *Title, const C4Rect *size)
Definition: C4AppT.cpp:107
bool ClearLog()
Definition: C4Console.cpp:672
bool Set(class C4Surface *sfcSource, int iZoom=0)
Definition: C4Draw.cpp:117
bool FileQuit()
Definition: C4Console.cpp:448
void AddMenuItemForPlayer(C4Player *player, StdStrBuf &player_text)
Definition: C4Console.cpp:668
#define IDC_BUTTONMODEDYNAMIC
Definition: resource.h:31
void ToolsDlgClose()
Definition: C4Console.cpp:671
void DoEnableControls(bool fEnable)
Definition: C4Console.cpp:685
#define C4TLS_MatSky
Definition: C4ToolsDlg.h:39
void SetLength(size_t iLength)
Definition: StdBuf.h:517
#define IDB_CURSOR
Definition: resource.h:7
bool AddMenuItem(HMENU hMenu, DWORD dwID, const char *szString, bool fEnabled=true)
void DrawPatternedCircle(C4Surface *sfcDest, int x, int y, int r, BYTE col, C4Pattern &Pattern, CStdPalette &rPal)
Definition: C4Draw.cpp:678
void AddNetMenu()
Definition: C4Console.cpp:670
#define IDB_PLAY
Definition: resource.h:21
#define IDC_BUTTONMODEPLAY
Definition: resource.h:34
void DisplayInfoText(InfoTextType type, StdStrBuf &text)
Definition: C4Console.cpp:684
std::enable_if< std::is_pod< T >::value >::type ZeroMem(T *lpMem, size_t dwSize)
Definition: Standard.h:63
#define GetWideLPARAM(c)
StdStrBuf::wchar_t_holder LoadResStrW(const char *id)
#define IDB_EXACT
Definition: resource.h:10
#define IDM_FILE_CLOSE
Definition: resource.h:81
#define IDB_RECT
Definition: resource.h:23
char BackTexture[C4M_MaxName+1]
Definition: C4ToolsDlg.h:60
void ClearPlayerMenu()
Definition: C4Console.cpp:674
virtual void Close()
Definition: C4Console.cpp:442
const int32_t C4TLS_Line
Definition: C4ToolsDlg.h:29
uint32_t DWORD
INT_PTR CALLBACK PropertyDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
#define IDC_COMBOFGMATERIAL
Definition: resource.h:41
bool SetTool(int32_t iTool, bool fTemp)
Definition: C4ToolsDlg.cpp:42
#define s
bool Inside(T ival, U lbound, V rbound)
Definition: Standard.h:45
void NoClip()
Definition: C4Surface.cpp:160
void SetCursor(Cursor cursor)
Definition: C4Console.cpp:695
#define IDD_PROPERTIES
Definition: resource.h:66
#define IDM_FILE_RECORD
Definition: resource.h:98
StdStrBuf GetDataString() const
const int32_t C4M_Background
Definition: C4Constants.h:176
C4Application Application
Definition: C4Globals.cpp:44
uint16_t WORD
void SetMaterial(const char *szMaterial)
Definition: C4ToolsDlg.cpp:59
State(C4ToolsDlg *toolsDlg)
void UpdateTextures()
Definition: C4Console.cpp:712
#define IDC_BUTTONRELOADDEF
Definition: resource.h:39
int32_t Tool
Definition: C4ToolsDlg.h:53
#define IDB_BRUSH2
Definition: resource.h:6
#define IDC_STATICFOREGROUND
Definition: resource.h:60
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:277
void PlayerJoin()
Definition: C4Console.cpp:518
void EnableControls()
Definition: C4Console.cpp:705
void PropertyDlgClose()
Definition: C4Console.cpp:691
C4MusicSystem MusicSystem
Definition: C4Application.h:41