win_ent.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1997-2006 Id Software, Inc.
  4. This file is part of Quake 2 Tools source code.
  5. Quake 2 Tools source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake 2 Tools source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Quake 2 Tools source code; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "qe3.h"
  19. #include "entityw.h"
  20. int rgIds[EntLast] = {
  21. IDC_E_LIST,
  22. IDC_E_COMMENT,
  23. IDC_CHECK1,
  24. IDC_CHECK2,
  25. IDC_CHECK3,
  26. IDC_CHECK4,
  27. IDC_CHECK5,
  28. IDC_CHECK6,
  29. IDC_CHECK7,
  30. IDC_CHECK8,
  31. IDC_CHECK9,
  32. IDC_CHECK10,
  33. IDC_CHECK11,
  34. IDC_CHECK12,
  35. IDC_E_PROPS,
  36. IDC_E_0,
  37. IDC_E_45,
  38. IDC_E_90,
  39. IDC_E_135,
  40. IDC_E_180,
  41. IDC_E_225,
  42. IDC_E_270,
  43. IDC_E_315,
  44. IDC_E_UP,
  45. IDC_E_DOWN,
  46. IDC_E_DELPROP,
  47. IDC_STATIC_KEY,
  48. IDC_E_KEY_FIELD,
  49. IDC_STATIC_VALUE,
  50. IDC_E_VALUE_FIELD,
  51. IDC_E_COLOR
  52. };
  53. HWND hwndEnt[EntLast];
  54. int inspector_mode; // W_TEXTURE, W_ENTITY, or W_CONSOLE
  55. qboolean multiple_entities;
  56. entity_t *edit_entity;
  57. HWND CreateTextureWindow (void);
  58. BOOL CALLBACK EntityWndProc(
  59. HWND hwndDlg, // handle to dialog box
  60. UINT uMsg, // message
  61. WPARAM wParam, // first message parameter
  62. LPARAM lParam); // second message parameter
  63. void SizeEntityDlg(int iWidth, int iHeight);
  64. void AddProp(void);
  65. void GetTexMods(void);
  66. LRESULT (CALLBACK* OldFieldWindowProc) (HWND, UINT, WPARAM, LPARAM);
  67. LRESULT (CALLBACK* OldEntityListWindowProc) (HWND, UINT, WPARAM, LPARAM);
  68. /*
  69. =========================
  70. FieldWndProc
  71. Just to handle tab and enter...
  72. =========================
  73. */
  74. BOOL CALLBACK FieldWndProc(
  75. HWND hwnd,
  76. UINT uMsg,
  77. WPARAM wParam,
  78. LPARAM lParam)
  79. {
  80. switch (uMsg)
  81. {
  82. case WM_CHAR:
  83. if (LOWORD(wParam) == VK_TAB)
  84. return FALSE;
  85. if (LOWORD(wParam) == VK_RETURN)
  86. return FALSE;
  87. if (LOWORD(wParam) == VK_ESCAPE)
  88. {
  89. SetFocus (g_qeglobals.d_hwndCamera);
  90. return FALSE;
  91. }
  92. break;
  93. case WM_KEYDOWN:
  94. if (LOWORD(wParam) == VK_TAB)
  95. {
  96. if (hwnd == hwndEnt[EntKeyField])
  97. {
  98. SendMessage (hwndEnt[EntValueField], WM_SETTEXT, 0, (long)"");
  99. SetFocus (hwndEnt[EntValueField]);
  100. }
  101. else
  102. SetFocus (hwndEnt[EntKeyField]);
  103. }
  104. if (LOWORD(wParam) == VK_RETURN)
  105. {
  106. if (hwnd == hwndEnt[EntKeyField])
  107. {
  108. SendMessage (hwndEnt[EntValueField], WM_SETTEXT, 0, (long)"");
  109. SetFocus (hwndEnt[EntValueField]);
  110. }
  111. else
  112. {
  113. AddProp ();
  114. SetFocus (g_qeglobals.d_hwndCamera);
  115. }
  116. }
  117. break;
  118. // case WM_NCHITTEST:
  119. case WM_LBUTTONDOWN:
  120. SetFocus (hwnd);
  121. break;
  122. }
  123. return CallWindowProc (OldFieldWindowProc, hwnd, uMsg, wParam, lParam);
  124. }
  125. /*
  126. =========================
  127. EntityListWndProc
  128. Just to handle enter...
  129. =========================
  130. */
  131. BOOL CALLBACK EntityListWndProc(
  132. HWND hwnd,
  133. UINT uMsg,
  134. WPARAM wParam,
  135. LPARAM lParam)
  136. {
  137. switch (uMsg)
  138. {
  139. case WM_KEYDOWN:
  140. if (LOWORD(wParam) == VK_RETURN)
  141. {
  142. SendMessage ( g_qeglobals.d_hwndEntity,
  143. WM_COMMAND,
  144. (LBN_DBLCLK<<16) + IDC_E_LIST,
  145. 0 );
  146. return 0;
  147. }
  148. break;
  149. }
  150. return CallWindowProc (OldEntityListWindowProc, hwnd, uMsg, wParam, lParam);
  151. }
  152. /*
  153. ================
  154. GetEntityControls
  155. Finds the controls from the dialog and
  156. moves them to the window
  157. ================
  158. */
  159. void GetEntityControls(HWND ghwndEntity)
  160. {
  161. int i;
  162. for (i = 0; i < EntLast; i++)
  163. {
  164. if (i == EntList || i == EntProps || i == EntComment)
  165. continue;
  166. if (i == EntKeyField || i == EntValueField)
  167. continue;
  168. hwndEnt[i] = GetDlgItem(ghwndEntity, rgIds[i]);
  169. if (hwndEnt[i])
  170. SetParent (hwndEnt[i], g_qeglobals.d_hwndEntity );
  171. }
  172. // SetParent apears to not modify some internal state
  173. // on listboxes, so create it from scratch...
  174. hwndEnt[EntList] = CreateWindow ("listbox", NULL,
  175. LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT
  176. | WS_VSCROLL | WS_CHILD | WS_VISIBLE,
  177. 5, 5, 180, 99,
  178. g_qeglobals.d_hwndEntity,
  179. (void *)IDC_E_LIST,
  180. g_qeglobals.d_hInstance,
  181. NULL);
  182. if (!hwndEnt[EntList])
  183. Error ("CreateWindow failed");
  184. hwndEnt[EntProps] = CreateWindow ("listbox", NULL,
  185. LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS
  186. | WS_VSCROLL | WS_CHILD | WS_VISIBLE,
  187. 5, 100, 180, 99,
  188. g_qeglobals.d_hwndEntity,
  189. (void *)IDC_E_PROPS,
  190. g_qeglobals.d_hInstance,
  191. NULL);
  192. if (!hwndEnt[EntProps])
  193. Error ("CreateWindow failed");
  194. hwndEnt[EntComment] = CreateWindow ("edit", NULL,
  195. ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER,
  196. 5, 100, 180, 99,
  197. g_qeglobals.d_hwndEntity,
  198. (void *)IDC_E_COMMENT,
  199. g_qeglobals.d_hInstance,
  200. NULL);
  201. if (!hwndEnt[EntComment])
  202. Error ("CreateWindow failed");
  203. hwndEnt[EntKeyField] = CreateWindow ("edit", NULL,
  204. WS_CHILD | WS_VISIBLE | WS_BORDER,
  205. 5, 100, 180, 99,
  206. g_qeglobals.d_hwndEntity,
  207. (void *)IDC_E_KEY_FIELD,
  208. g_qeglobals.d_hInstance,
  209. NULL);
  210. if (!hwndEnt[EntKeyField])
  211. Error ("CreateWindow failed");
  212. hwndEnt[EntValueField] = CreateWindow ("edit", NULL,
  213. WS_CHILD | WS_VISIBLE | WS_BORDER,
  214. 5, 100, 180, 99,
  215. g_qeglobals.d_hwndEntity,
  216. (void *)IDC_E_VALUE_FIELD,
  217. g_qeglobals.d_hInstance,
  218. NULL);
  219. if (!hwndEnt[EntValueField])
  220. Error ("CreateWindow failed");
  221. g_qeglobals.d_hwndEdit = CreateWindow ("edit", NULL,
  222. ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER,
  223. 5, 100, 180, 99,
  224. g_qeglobals.d_hwndEntity,
  225. (void *)IDC_E_STATUS,
  226. g_qeglobals.d_hInstance,
  227. NULL);
  228. if (!g_qeglobals.d_hwndEdit)
  229. Error ("CreateWindow failed");
  230. g_qeglobals.d_hwndTexture = CreateTextureWindow ();
  231. #if 0
  232. for (i=0 ; i<12 ; i++)
  233. {
  234. hwndEnt[EntCheck1 + i] = CreateWindow ("button", NULL,
  235. BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE,
  236. 5, 100, 180, 99,
  237. entwindow,
  238. (void *)IDC_E_STATUS,
  239. main_instance,
  240. NULL);
  241. if (!hwndEnt[EntCheck1 + i])
  242. Error ("CreateWindow failed");
  243. }
  244. #endif
  245. }
  246. /*
  247. ===============================================================
  248. ENTITY WINDOW
  249. ===============================================================
  250. */
  251. void FillClassList (void)
  252. {
  253. eclass_t *pec;
  254. int iIndex;
  255. SendMessage(hwndEnt[EntList], LB_RESETCONTENT, 0 , 0);
  256. for (pec = eclass ; pec ; pec = pec->next)
  257. {
  258. iIndex = SendMessage(hwndEnt[EntList], LB_ADDSTRING, 0 , (LPARAM)pec->name);
  259. SendMessage(hwndEnt[EntList], LB_SETITEMDATA, iIndex, (LPARAM)pec);
  260. }
  261. }
  262. /*
  263. ==============
  264. WEnt_Create
  265. ==============
  266. */
  267. void WEnt_Create (HINSTANCE hInstance)
  268. {
  269. WNDCLASS wc;
  270. /* Register the camera class */
  271. memset (&wc, 0, sizeof(wc));
  272. wc.style = 0;
  273. wc.lpfnWndProc = (WNDPROC)EntityWndProc;
  274. wc.cbClsExtra = 0;
  275. wc.cbWndExtra = 0;
  276. wc.hInstance = hInstance;
  277. wc.hIcon = 0;
  278. wc.hCursor = LoadCursor (NULL,IDC_ARROW);
  279. wc.hbrBackground = GetStockObject (LTGRAY_BRUSH);
  280. wc.lpszMenuName = NULL;
  281. wc.lpszClassName = ENT_WINDOW_CLASS;
  282. if (!RegisterClass (&wc) )
  283. Error ("RegisterClass: failed");
  284. g_qeglobals.d_hwndEntity = CreateWindow (ENT_WINDOW_CLASS ,
  285. "Entity",
  286. QE3_STYLE ,
  287. 20,
  288. 20,
  289. 100,
  290. 480, // size
  291. g_qeglobals.d_hwndMain, // parent
  292. 0, // no menu
  293. hInstance,
  294. NULL);
  295. if (!g_qeglobals.d_hwndEntity )
  296. Error ("Couldn't create Entity window");
  297. }
  298. /*
  299. ==============
  300. CreateEntityWindow
  301. ==============
  302. */
  303. BOOL CreateEntityWindow(HINSTANCE hInstance)
  304. {
  305. HWND hwndEntityPalette;
  306. inspector_mode = W_ENTITY;
  307. WEnt_Create (hInstance);
  308. hwndEntityPalette = CreateDialog(hInstance, (char *)IDD_ENTITY, g_qeglobals.d_hwndMain, (DLGPROC)NULL);
  309. if (!hwndEntityPalette)
  310. Error ("CreateDialog failed");
  311. GetEntityControls (hwndEntityPalette);
  312. DestroyWindow (hwndEntityPalette);
  313. OldFieldWindowProc = (void *)GetWindowLong (hwndEnt[EntKeyField], GWL_WNDPROC);
  314. SetWindowLong (hwndEnt[EntKeyField], GWL_WNDPROC, (long)FieldWndProc);
  315. SetWindowLong (hwndEnt[EntValueField], GWL_WNDPROC, (long)FieldWndProc);
  316. OldEntityListWindowProc = (void *)GetWindowLong (hwndEnt[EntList], GWL_WNDPROC);
  317. SetWindowLong (hwndEnt[EntList], GWL_WNDPROC, (long)EntityListWndProc);
  318. FillClassList ();
  319. LoadWindowState(g_qeglobals.d_hwndEntity, "EntityWindow");
  320. ShowWindow (g_qeglobals.d_hwndEntity, SW_SHOW);
  321. SetInspectorMode (W_CONSOLE);
  322. return TRUE;
  323. }
  324. /*
  325. ==============
  326. SetInspectorMode
  327. ==============
  328. */
  329. void SetInspectorMode(int iType)
  330. {
  331. RECT rc;
  332. HMENU hMenu = GetMenu( g_qeglobals.d_hwndMain );
  333. // Is the caller asking us to cycle to the next window?
  334. if (iType == -1)
  335. {
  336. if (inspector_mode == W_ENTITY)
  337. iType = W_TEXTURE;
  338. else if (inspector_mode == W_TEXTURE)
  339. iType = W_CONSOLE;
  340. else
  341. iType = W_ENTITY;
  342. }
  343. inspector_mode = iType;
  344. switch(iType)
  345. {
  346. case W_ENTITY:
  347. SetWindowText(g_qeglobals.d_hwndEntity, "Entity");
  348. EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_ENABLED | MF_BYCOMMAND );
  349. break;
  350. case W_TEXTURE:
  351. // title is set by textures.c SetWindowText(g_qeglobals.d_hwndEntity, "Textures");
  352. EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_GRAYED | MF_DISABLED | MF_BYCOMMAND );
  353. break;
  354. case W_CONSOLE:
  355. SetWindowText(g_qeglobals.d_hwndEntity, "Console");
  356. EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_GRAYED | MF_DISABLED | MF_BYCOMMAND );
  357. break;
  358. default:
  359. break;
  360. }
  361. GetWindowRect (g_qeglobals.d_hwndEntity, &rc);
  362. SizeEntityDlg( rc.right - rc.left - 8, rc.bottom - rc.top - 32);
  363. RedrawWindow (g_qeglobals.d_hwndEntity, NULL, NULL, RDW_ERASE | RDW_INVALIDATE
  364. | RDW_ERASENOW | RDW_UPDATENOW | RDW_ALLCHILDREN);
  365. // InvalidateRect(entwindow, NULL, true);
  366. // ShowWindow (entwindow, SW_SHOW);
  367. // UpdateWindow (entwindow);
  368. SetWindowPos( g_qeglobals.d_hwndEntity,
  369. HWND_TOP,
  370. rc.left, rc.top,
  371. rc.right - rc.left, rc.bottom - rc.top,
  372. SWP_NOSIZE | SWP_NOMOVE );
  373. }
  374. // SetKeyValuePairs
  375. //
  376. // Reset the key/value (aka property) listbox and fill it with the
  377. // k/v pairs from the entity being edited.
  378. //
  379. void SetKeyValuePairs (void)
  380. {
  381. epair_t *pep;
  382. RECT rc;
  383. char sz[4096];
  384. if (edit_entity == NULL)
  385. return;
  386. // set key/value pair list
  387. GetWindowRect(hwndEnt[EntProps], &rc);
  388. SendMessage(hwndEnt[EntProps], LB_SETCOLUMNWIDTH, (rc.right - rc.left)/2, 0);
  389. SendMessage(hwndEnt[EntProps], LB_RESETCONTENT, 0, 0);
  390. // Walk through list and add pairs
  391. for (pep = edit_entity->epairs ; pep ; pep = pep->next)
  392. {
  393. // if the key is less than 8 chars, add a tab for alignment
  394. if (strlen(pep->key) > 8)
  395. sprintf (sz, "%s\t%s", pep->key, pep->value);
  396. else
  397. sprintf (sz, "%s\t\t%s", pep->key, pep->value);
  398. SendMessage(hwndEnt[EntProps], LB_ADDSTRING, 0, (LPARAM)sz);
  399. }
  400. }
  401. // SetSpawnFlags
  402. //
  403. // Update the checkboxes to reflect the flag state of the entity
  404. //
  405. void SetSpawnFlags(void)
  406. {
  407. int f;
  408. int i;
  409. int v;
  410. f = atoi(ValueForKey (edit_entity, "spawnflags"));
  411. for (i=0 ; i<12 ; i++)
  412. {
  413. v = !!(f&(1<<i));
  414. SendMessage(hwndEnt[EntCheck1+i], BM_SETCHECK, v, 0);
  415. }
  416. }
  417. // GetSpawnFlags
  418. //
  419. // Update the entity flags to reflect the state of the checkboxes
  420. //
  421. void GetSpawnFlags(void)
  422. {
  423. int f;
  424. int i, v;
  425. char sz[32];
  426. f = 0;
  427. for (i=0 ; i<12 ; i++)
  428. {
  429. v = SendMessage(hwndEnt[EntCheck1+i], BM_GETCHECK, 0, 0);
  430. f |= v<<i;
  431. }
  432. sprintf (sz, "%i", f);
  433. if (multiple_entities)
  434. {
  435. brush_t *b;
  436. for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  437. SetKeyValue(b->owner, "spawnflags", sz);
  438. }
  439. else
  440. SetKeyValue (edit_entity, "spawnflags", sz);
  441. SetKeyValuePairs ();
  442. }
  443. // UpdateSel
  444. //
  445. // Update the listbox, checkboxes and k/v pairs to reflect the new selection
  446. //
  447. BOOL UpdateSel(int iIndex, eclass_t *pec)
  448. {
  449. int i;
  450. brush_t *b;
  451. if (selected_brushes.next == &selected_brushes)
  452. {
  453. edit_entity = world_entity;
  454. multiple_entities = false;
  455. }
  456. else
  457. {
  458. edit_entity = selected_brushes.next->owner;
  459. for (b=selected_brushes.next->next ; b != &selected_brushes ; b=b->next)
  460. {
  461. if (b->owner != edit_entity)
  462. {
  463. multiple_entities = true;
  464. break;
  465. }
  466. }
  467. }
  468. if (iIndex != LB_ERR)
  469. SendMessage(hwndEnt[EntList], LB_SETCURSEL, iIndex, 0);
  470. if (pec == NULL)
  471. return TRUE;
  472. // Set up the description
  473. SendMessage(hwndEnt[EntComment], WM_SETTEXT, 0,
  474. (LPARAM)TranslateString(pec->comments));
  475. for (i=0 ; i<8 ; i++)
  476. {
  477. HWND hwnd = hwndEnt[EntCheck1+i];
  478. if (pec->flagnames[i] && pec->flagnames[i][0] != 0)
  479. {
  480. EnableWindow(hwnd, TRUE);
  481. SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)pec->flagnames[i]);
  482. } else {
  483. // disable check box
  484. SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)" ");
  485. EnableWindow(hwnd, FALSE);
  486. }
  487. }
  488. SetSpawnFlags();
  489. SetKeyValuePairs();
  490. return TRUE;
  491. }
  492. BOOL UpdateEntitySel(eclass_t *pec)
  493. {
  494. int iIndex;
  495. iIndex = (int)SendMessage(hwndEnt[EntList], LB_FINDSTRINGEXACT,
  496. (WPARAM)-1, (LPARAM)pec->name);
  497. return UpdateSel(iIndex, pec);
  498. }
  499. // CreateEntity
  500. //
  501. // Creates a new entity based on the currently selected brush and entity type.
  502. //
  503. void CreateEntity(void)
  504. {
  505. eclass_t *pecNew;
  506. entity_t *petNew;
  507. int i;
  508. HWND hwnd;
  509. char sz[1024];
  510. // check to make sure we have a brush
  511. if (selected_brushes.next == &selected_brushes)
  512. {
  513. MessageBox(g_qeglobals.d_hwndMain, "You must have a selected brush to create an entity"
  514. , "info", 0);
  515. return;
  516. }
  517. // find out what type of entity we are trying to create
  518. hwnd = hwndEnt[EntList];
  519. i = SendMessage(hwndEnt[EntList], LB_GETCURSEL, 0, 0);
  520. if (i < 0)
  521. {
  522. MessageBox(g_qeglobals.d_hwndMain, "You must have a selected class to create an entity"
  523. , "info", 0);
  524. return;
  525. }
  526. SendMessage(hwnd, LB_GETTEXT, i, (LPARAM)sz);
  527. if (!stricmp(sz, "worldspawn"))
  528. {
  529. MessageBox(g_qeglobals.d_hwndMain, "Can't create an entity with worldspawn.", "info", 0);
  530. return;
  531. }
  532. pecNew = Eclass_ForName(sz, false);
  533. // create it
  534. petNew = Entity_Create(pecNew);
  535. if (petNew == NULL)
  536. {
  537. MessageBox(g_qeglobals.d_hwndMain, "Failed to create entity.", "info", 0);
  538. return;
  539. }
  540. if (selected_brushes.next == &selected_brushes)
  541. edit_entity = world_entity;
  542. else
  543. edit_entity = selected_brushes.next->owner;
  544. SetKeyValuePairs();
  545. Select_Deselect ();
  546. Select_Brush (edit_entity->brushes.onext);
  547. }
  548. /*
  549. ===============
  550. AddProp
  551. ===============
  552. */
  553. void AddProp(void)
  554. {
  555. char key[4096];
  556. char value[4096];
  557. if (edit_entity == NULL)
  558. return;
  559. // Get current selection text
  560. SendMessage(hwndEnt[EntKeyField], WM_GETTEXT, sizeof(key)-1, (LPARAM)key);
  561. SendMessage(hwndEnt[EntValueField], WM_GETTEXT, sizeof(value)-1, (LPARAM)value);
  562. if (multiple_entities)
  563. {
  564. brush_t *b;
  565. for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  566. SetKeyValue(b->owner, key, value);
  567. }
  568. else
  569. SetKeyValue(edit_entity, key, value);
  570. // refresh the prop listbox
  571. SetKeyValuePairs();
  572. }
  573. /*
  574. ===============
  575. DelProp
  576. ===============
  577. */
  578. void DelProp(void)
  579. {
  580. char sz[4096];
  581. if (edit_entity == NULL)
  582. return;
  583. // Get current selection text
  584. SendMessage(hwndEnt[EntKeyField], WM_GETTEXT, sizeof(sz)-1, (LPARAM)sz);
  585. if (multiple_entities)
  586. {
  587. brush_t *b;
  588. for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  589. DeleteKey(b->owner, sz);
  590. }
  591. else
  592. DeleteKey(edit_entity, sz);
  593. // refresh the prop listbox
  594. SetKeyValuePairs();
  595. }
  596. /*
  597. ===============
  598. EditProp
  599. ===============
  600. */
  601. void EditProp(void)
  602. {
  603. int i;
  604. HWND hwnd;
  605. char sz[4096];
  606. char *val;
  607. if (edit_entity == NULL)
  608. return;
  609. hwnd = hwndEnt[EntProps];
  610. // Get current selection text
  611. i = SendMessage(hwnd, LB_GETCURSEL, 0, 0);
  612. if (i < 0)
  613. return;
  614. SendMessage(hwnd, LB_GETTEXT, i, (LPARAM)sz);
  615. // strip it down to the key name
  616. for(i=0;sz[i] != '\t';i++)
  617. ;
  618. sz[i] = '\0';
  619. val = sz + i + 1;
  620. if (*val == '\t')
  621. val++;
  622. SendMessage(hwndEnt[EntKeyField], WM_SETTEXT, 0, (LPARAM)sz);
  623. SendMessage(hwndEnt[EntValueField], WM_SETTEXT, 0, (LPARAM)val);
  624. }
  625. HDWP defer;
  626. int col;
  627. void MOVE(HWND e, int x, int y, int w, int h)
  628. {
  629. // defer=DeferWindowPos(defer,e,HWND_TOP,col+(x),y,w,h,SWP_SHOWWINDOW);
  630. // MoveWindow (e, col+x, y, w, h, FALSE);
  631. SetWindowPos (e, HWND_TOP, col+x, y, w, h,
  632. SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOZORDER);
  633. }
  634. /*
  635. ===============
  636. SizeEnitityDlg
  637. Positions all controls so that the active inspector
  638. is displayed correctly and the inactive ones are
  639. off the side
  640. ===============
  641. */
  642. void SizeEntityDlg(int iWidth, int iHeight)
  643. {
  644. int y, x, xCheck, yCheck;
  645. int i, iRow;
  646. int w, h;
  647. if (iWidth < 32 || iHeight < 32)
  648. return;
  649. SendMessage( g_qeglobals.d_hwndEntity, WM_SETREDRAW, 0, 0);
  650. //==========================================
  651. //
  652. // console
  653. //
  654. if (inspector_mode == W_CONSOLE)
  655. col = 0;
  656. else
  657. col = iWidth;
  658. MOVE(g_qeglobals.d_hwndEdit, DlgXBorder, DlgYBorder, iWidth - (2 * DlgXBorder), iHeight - (2 * DlgYBorder) );
  659. //==========================================
  660. //
  661. // texture controls
  662. //
  663. if (inspector_mode == W_TEXTURE)
  664. col = 0;
  665. else
  666. col = iWidth;
  667. MOVE(g_qeglobals.d_hwndTexture, DlgXBorder, DlgYBorder, iWidth - (2 * DlgXBorder), iHeight - (2 * DlgYBorder) );
  668. //==========================================
  669. //
  670. // entity controls
  671. //
  672. if (inspector_mode == W_ENTITY)
  673. col = 0;
  674. else
  675. col = iWidth;
  676. // top half includes the entity list (2/3) and the
  677. // comments (1/3) - 2 gaps, above and below.
  678. y = iHeight/2;
  679. y -= 2 * DlgYBorder;
  680. y = y / 3;
  681. w = iWidth - (2 * DlgXBorder);
  682. MOVE(hwndEnt[EntList], DlgXBorder, DlgYBorder, w, 2 * y);
  683. MOVE(hwndEnt[EntComment],
  684. DlgXBorder, 2 * DlgYBorder + 2 * y,
  685. w, y - (2 * DlgYBorder));
  686. // bottom half includes flags (fixed), k/v pairs,
  687. // and buttons (fixed).
  688. // xCheck = width of a single check box
  689. // yCheck = distance from top of one check to the next
  690. xCheck = (iWidth - (2 * DlgXBorder)) / 3;
  691. yCheck = 20;
  692. x = DlgXBorder;
  693. for (iRow = 0; iRow <= 12; iRow += 4)
  694. {
  695. y = iHeight/2;
  696. for (i = 0; i < 4; i++)
  697. {
  698. MOVE(hwndEnt[EntCheck1 + i + iRow],
  699. x, y, xCheck, yCheck);
  700. y += yCheck;
  701. }
  702. x += xCheck;
  703. }
  704. //
  705. // properties scroll box
  706. //
  707. y = iHeight/2 + 4 * yCheck;
  708. w = iWidth - (2 * DlgXBorder);
  709. h = (iHeight - (yCheck * 5 + 2 * DlgYBorder) ) - y;
  710. MOVE(hwndEnt[EntProps], DlgXBorder, y, w, h);
  711. y += h + DlgYBorder;
  712. //
  713. // key / value fields
  714. //
  715. w = iWidth-(DlgXBorder+45);
  716. MOVE(hwndEnt[EntKeyLabel], DlgXBorder, y, 40, yCheck);
  717. MOVE(hwndEnt[EntKeyField], DlgXBorder+40, y, w, yCheck);
  718. y += yCheck;
  719. MOVE(hwndEnt[EntValueLabel], DlgXBorder, y, 40, yCheck);
  720. MOVE(hwndEnt[EntValueField], DlgXBorder+40, y, w, yCheck);
  721. y += yCheck;
  722. //
  723. // angle check boxes
  724. //
  725. i = y;
  726. x = DlgXBorder;
  727. xCheck = yCheck*2;
  728. MOVE(hwndEnt[EntDir135], x, y, xCheck, yCheck);
  729. y += yCheck;
  730. MOVE(hwndEnt[EntDir180], x, y, xCheck, yCheck);
  731. y += yCheck;
  732. MOVE(hwndEnt[EntDir225], x, y, xCheck, yCheck);
  733. y = i;
  734. x += xCheck;
  735. MOVE(hwndEnt[EntDir90], x, y, xCheck, yCheck);
  736. y += yCheck;
  737. y += yCheck;
  738. MOVE(hwndEnt[EntDir270], x, y, xCheck, yCheck);
  739. y = i;
  740. x += xCheck;
  741. MOVE(hwndEnt[EntDir45], x, y, xCheck, yCheck);
  742. y += yCheck;
  743. MOVE(hwndEnt[EntDir0], x, y, xCheck, yCheck);
  744. y += yCheck;
  745. MOVE(hwndEnt[EntDir315], x, y, xCheck, yCheck);
  746. y = i + yCheck/2;
  747. x += xCheck + xCheck/2;
  748. MOVE(hwndEnt[EntDirUp], x, y, xCheck, yCheck);
  749. y += yCheck;
  750. MOVE(hwndEnt[EntDirDown], x, y, xCheck, yCheck);
  751. y = i;
  752. x += 1.5 * xCheck;
  753. MOVE(hwndEnt[EntDelProp], x, y, xCheck*2, yCheck);
  754. y += yCheck;
  755. SendMessage( g_qeglobals.d_hwndEntity, WM_SETREDRAW, 1, 0);
  756. // InvalidateRect(entwindow, NULL, TRUE);
  757. }
  758. /*
  759. =========================
  760. EntityWndProc
  761. =========================
  762. */
  763. BOOL CALLBACK EntityWndProc(
  764. HWND hwndDlg, // handle to dialog box
  765. UINT uMsg, // message
  766. WPARAM wParam, // first message parameter
  767. LPARAM lParam) // second message parameter
  768. {
  769. RECT rc;
  770. GetClientRect(hwndDlg, &rc);
  771. switch (uMsg)
  772. {
  773. case WM_GETMINMAXINFO:
  774. {
  775. LPMINMAXINFO lpmmi;
  776. lpmmi = (LPMINMAXINFO) lParam;
  777. lpmmi->ptMinTrackSize.x = 320;
  778. lpmmi->ptMinTrackSize.y = 500;
  779. }
  780. return 0;
  781. case WM_WINDOWPOSCHANGING:
  782. {
  783. LPWINDOWPOS lpwp;
  784. lpwp = (LPWINDOWPOS) lParam;
  785. DefWindowProc (hwndDlg, uMsg, wParam, lParam);
  786. lpwp->flags |= SWP_NOCOPYBITS;
  787. SizeEntityDlg(lpwp->cx-8, lpwp->cy-32);
  788. return 0;
  789. }
  790. return 0;
  791. case WM_COMMAND:
  792. switch (LOWORD(wParam)) {
  793. case IDC_E_DELPROP:
  794. DelProp();
  795. SetFocus (g_qeglobals.d_hwndCamera);
  796. break;
  797. case IDC_E_0:
  798. SetKeyValue (edit_entity, "angle", "0");
  799. SetFocus (g_qeglobals.d_hwndCamera);
  800. SetKeyValuePairs ();
  801. break;
  802. case IDC_E_45:
  803. SetKeyValue (edit_entity, "angle", "45");
  804. SetFocus (g_qeglobals.d_hwndCamera);
  805. SetKeyValuePairs ();
  806. break;
  807. case IDC_E_90:
  808. SetKeyValue (edit_entity, "angle", "90");
  809. SetFocus (g_qeglobals.d_hwndCamera);
  810. SetKeyValuePairs ();
  811. break;
  812. case IDC_E_135:
  813. SetKeyValue (edit_entity, "angle", "135");
  814. SetFocus (g_qeglobals.d_hwndCamera);
  815. SetKeyValuePairs ();
  816. break;
  817. case IDC_E_180:
  818. SetKeyValue (edit_entity, "angle", "180");
  819. SetFocus (g_qeglobals.d_hwndCamera);
  820. SetKeyValuePairs ();
  821. break;
  822. case IDC_E_225:
  823. SetKeyValue (edit_entity, "angle", "225");
  824. SetFocus (g_qeglobals.d_hwndCamera);
  825. SetKeyValuePairs ();
  826. break;
  827. case IDC_E_270:
  828. SetKeyValue (edit_entity, "angle", "270");
  829. SetFocus (g_qeglobals.d_hwndCamera);
  830. SetKeyValuePairs ();
  831. break;
  832. case IDC_E_315:
  833. SetKeyValue (edit_entity, "angle", "315");
  834. SetFocus (g_qeglobals.d_hwndCamera);
  835. SetKeyValuePairs ();
  836. break;
  837. case IDC_E_UP:
  838. SetKeyValue (edit_entity, "angle", "-1");
  839. SetFocus (g_qeglobals.d_hwndCamera);
  840. SetKeyValuePairs ();
  841. break;
  842. case IDC_E_DOWN:
  843. SetKeyValue (edit_entity, "angle", "-2");
  844. SetFocus (g_qeglobals.d_hwndCamera);
  845. SetKeyValuePairs ();
  846. break;
  847. case IDC_CHECK1:
  848. case IDC_CHECK2:
  849. case IDC_CHECK3:
  850. case IDC_CHECK4:
  851. case IDC_CHECK5:
  852. case IDC_CHECK6:
  853. case IDC_CHECK7:
  854. case IDC_CHECK8:
  855. case IDC_CHECK9:
  856. case IDC_CHECK10:
  857. case IDC_CHECK11:
  858. case IDC_CHECK12:
  859. GetSpawnFlags();
  860. SetFocus (g_qeglobals.d_hwndCamera);
  861. break;
  862. case IDC_E_PROPS:
  863. switch (HIWORD(wParam))
  864. {
  865. case LBN_SELCHANGE:
  866. EditProp();
  867. return TRUE;
  868. }
  869. break;
  870. case IDC_E_LIST:
  871. switch (HIWORD(wParam)) {
  872. case LBN_SELCHANGE:
  873. {
  874. int iIndex;
  875. eclass_t *pec;
  876. iIndex = SendMessage(hwndEnt[EntList], LB_GETCURSEL, 0, 0);
  877. pec = (eclass_t *)SendMessage(hwndEnt[EntList], LB_GETITEMDATA,
  878. iIndex, 0);
  879. UpdateSel(iIndex, pec);
  880. return TRUE;
  881. break;
  882. }
  883. case LBN_DBLCLK:
  884. CreateEntity ();
  885. SetFocus (g_qeglobals.d_hwndCamera);
  886. break;
  887. }
  888. break;
  889. default:
  890. return DefWindowProc( hwndDlg, uMsg, wParam, lParam );
  891. }
  892. return 0;
  893. }
  894. return DefWindowProc (hwndDlg, uMsg, wParam, lParam);
  895. }