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