1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "tools/edit_gui_common.h"
30 
31 
32 #include "qe3.h"
33 #include "../../renderer/model_local.h"	// for idRenderModelPrt
34 
35 // externs
36 CPtrArray	g_SelectedFaces;
37 CPtrArray	g_SelectedFaceBrushes;
38 CPtrArray	&g_ptrSelectedFaces = g_SelectedFaces;
39 CPtrArray	&g_ptrSelectedFaceBrushes = g_SelectedFaceBrushes;
40 
41 extern void Brush_Resize(brush_t *b, idVec3 vMin, idVec3 vMax);
42 
43 /*
44  =======================================================================================================================
45  =======================================================================================================================
46  */
Test_Ray(const idVec3 & origin,const idVec3 & dir,int flags)47 qertrace_t Test_Ray(const idVec3 &origin, const idVec3 &dir, int flags) {
48 	brush_t		*brush;
49 	face_t		*face;
50 	float		dist;
51 	qertrace_t	t;
52 
53 	memset(&t, 0, sizeof(t));
54 	t.dist = HUGE_DISTANCE*2;
55 
56 	// check for points first
57 	CDragPoint	*drag = PointRay(origin, dir, &dist);
58 	if (drag) {
59 		t.dist = dist;
60 		t.brush = NULL;
61 		t.face = NULL;
62 		t.point = drag;
63 		t.selected = false;
64 		return t;
65 	}
66 
67 	if (flags & SF_CYCLE) {
68 		CPtrArray	array;
69 		brush_t		*pToSelect = (selected_brushes.next != &selected_brushes) ? selected_brushes.next : NULL;
70 		Select_Deselect();
71 
72 		// go through active brushes and accumulate all "hit" brushes
73 		for (brush = active_brushes.next; brush != &active_brushes; brush = brush->next) {
74 			// if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) continue;
75 			if (FilterBrush(brush)) {
76 				continue;
77 			}
78 
79 			if (g_PrefsDlg.m_selectOnlyBrushes) {
80 				if (brush->pPatch || brush->modelHandle > 0) {
81 					continue;
82 				}
83 			}
84 
85 			if (g_PrefsDlg.m_selectNoModels) {
86 				if (brush->modelHandle > 0) {
87 					continue;
88 				}
89 			}
90 
91 			// if (!g_bShowPatchBounds && brush->pPatch) continue;
92 			face = Brush_Ray(origin, dir, brush, &dist, true);
93 
94 			if (face) {
95 				array.Add(brush);
96 			}
97 		}
98 
99 		int nSize = array.GetSize();
100 		if (nSize > 0) {
101 			bool	bFound = false;
102 			for (int i = 0; i < nSize; i++) {
103 				brush_t *b = reinterpret_cast < brush_t * > (array.GetAt(i));
104 
105 				// did we hit the last one selected yet ?
106 				if (b == pToSelect) {
107 					// yes we want to select the next one in the list
108 					int n = (i > 0) ? i - 1 : nSize - 1;
109 					pToSelect = reinterpret_cast < brush_t * > (array.GetAt(n));
110 					bFound = true;
111 					break;
112 				}
113 			}
114 
115 			if (!bFound) {
116 				pToSelect = reinterpret_cast < brush_t * > (array.GetAt(0));
117 			}
118 		}
119 
120 		if (pToSelect) {
121 			face = Brush_Ray(origin, dir, pToSelect, &dist, true);
122 			t.dist = dist;
123 			t.brush = pToSelect;
124 			t.face = face;
125 			t.selected = false;
126 			return t;
127 		}
128 	}
129 
130 	if (!(flags & SF_SELECTED_ONLY)) {
131 		for (brush = active_brushes.next; brush != &active_brushes; brush = brush->next) {
132 			if ((flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) {
133 				continue;
134 			}
135 
136 			if (FilterBrush(brush)) {
137 				continue;
138 			}
139 
140 			if (g_PrefsDlg.m_selectOnlyBrushes) {
141 				if (brush->pPatch || brush->modelHandle > 0) {
142 					continue;
143 				}
144 			}
145 
146 			if (g_PrefsDlg.m_selectNoModels) {
147 				if (brush->modelHandle > 0) {
148 					continue;
149 				}
150 			}
151 
152 			face = Brush_Ray(origin, dir, brush, &dist, true);
153 			if (dist > 0 && dist < t.dist) {
154 				t.dist = dist;
155 				t.brush = brush;
156 				t.face = face;
157 				t.selected = false;
158 			}
159 		}
160 	}
161 
162 	for (brush = selected_brushes.next; brush != &selected_brushes; brush = brush->next) {
163 		if ((flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) {
164 			continue;
165 		}
166 
167 		if (FilterBrush(brush)) {
168 			continue;
169 		}
170 
171 		if (g_PrefsDlg.m_selectOnlyBrushes) {
172 			if (brush->pPatch || brush->modelHandle > 0) {
173 				continue;
174 			}
175 		}
176 
177 		if (g_PrefsDlg.m_selectNoModels) {
178 			if (brush->modelHandle > 0) {
179 				continue;
180 			}
181 		}
182 
183 		face = Brush_Ray(origin, dir, brush, &dist, true);
184 		if (dist > 0 && dist < t.dist) {
185 			t.dist = dist;
186 			t.brush = brush;
187 			t.face = face;
188 			t.selected = true;
189 		}
190 	}
191 
192 	// if entites first, but didn't find any, check regular
193 	if ((flags & SF_ENTITIES_FIRST) && t.brush == NULL) {
194 		return Test_Ray(origin, dir, flags - SF_ENTITIES_FIRST);
195 	}
196 
197 	return t;
198 }
199 
200 extern void	AddSelectablePoint(brush_t *b, idVec3 v, int type, bool priority);
201 extern void	ClearSelectablePoints(brush_t *b);
202 extern idVec3 Brush_TransformedPoint(brush_t *b, const idVec3 &in);
203 
204 /*
205  =======================================================================================================================
206 	Select_Brush
207  =======================================================================================================================
208  */
Select_Brush(brush_t * brush,bool bComplete,bool bStatus)209 void Select_Brush(brush_t *brush, bool bComplete, bool bStatus) {
210 	brush_t		*b;
211 	entity_t	*e;
212 
213 	g_ptrSelectedFaces.RemoveAll();
214 	g_ptrSelectedFaceBrushes.RemoveAll();
215 
216 	// selected_face = NULL;
217 	if (g_qeglobals.d_select_count < MAX_MAP_ENTITIES) {
218 		g_qeglobals.d_select_order[g_qeglobals.d_select_count] = brush;
219 	}
220 
221 	g_qeglobals.d_select_count++;
222 
223 	e = brush->owner;
224 	if (e) {
225 
226 		if ( e == world_entity && radiant_entityMode.GetBool() ) {
227 			return;
228 		}
229 		// select complete entity on first click
230 		if (e != world_entity && bComplete == true) {
231 			for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
232 				if (b->owner == e) {
233 					goto singleselect;
234 				}
235 			}
236 
237 			for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
238 				Brush_RemoveFromList(b);
239 				Brush_AddToList(b, &selected_brushes);
240 			}
241 		}
242 		else
243 		{
244 singleselect:
245 			Brush_RemoveFromList(brush);
246 			Brush_AddToList(brush, &selected_brushes);
247 			UpdateSurfaceDialog();
248 			UpdatePatchInspector();
249 			UpdateLightInspector();
250 		}
251 
252 		if (e->eclass) {
253 			g_Inspectors->UpdateEntitySel(brush->owner->eclass);
254 			if ( radiant_entityMode.GetBool() && e->eclass->nShowFlags & (ECLASS_LIGHT | ECLASS_SPEAKER) ) {
255 				const char *p = ValueForKey(e, "s_shader");
256 				if (p && *p) {
257 					g_Inspectors->mediaDlg.SelectCurrentItem(true, p, CDialogTextures::SOUNDS);
258 				}
259 
260 			}
261 			if ( ( e->eclass->nShowFlags & ECLASS_LIGHT ) && !brush->entityModel ) {
262 				if (brush->pointLight) {
263 					// add center drag point if not at the origin
264 					if (brush->lightCenter[0] || brush->lightCenter[1] || brush->lightCenter[2]) {
265 						AddSelectablePoint(brush, Brush_TransformedPoint(brush, brush->lightCenter), LIGHT_CENTER, false);
266 					}
267 				}
268 				else {
269 					AddSelectablePoint(brush, Brush_TransformedPoint(brush, brush->lightTarget), LIGHT_TARGET, true);
270 					AddSelectablePoint(brush, Brush_TransformedPoint(brush, brush->lightUp), LIGHT_UP, false);
271 					AddSelectablePoint(brush, Brush_TransformedPoint(brush, brush->lightRight), LIGHT_RIGHT, false);
272 					if (brush->startEnd) {
273 						AddSelectablePoint(brush, Brush_TransformedPoint(brush, brush->lightStart), LIGHT_START, false);
274 						AddSelectablePoint(brush, Brush_TransformedPoint(brush, brush->lightEnd), LIGHT_END, false);
275 					}
276 				}
277 				UpdateLightInspector();
278 			}
279 			if (e->eclass->nShowFlags & ECLASS_CAMERAVIEW) {
280 				g_pParentWnd->GetCamera()->UpdateCameraView();
281 			}
282 		}
283 	}
284 
285 	if (bStatus) {
286 		idVec3	vMin, vMax, vSize;
287 		Select_GetBounds(vMin, vMax);
288 		VectorSubtract(vMax, vMin, vSize);
289 
290 		CString strStatus;
291 		strStatus.Format("Selection X:: %.1f  Y:: %.1f  Z:: %.1f", vSize[0], vSize[1], vSize[2]);
292 		g_pParentWnd->SetStatusText(2, strStatus);
293 	}
294 }
295 
296 /*
297  =======================================================================================================================
298 	Select_Ray If the origin is inside a brush, that brush will be ignored.
299  =======================================================================================================================
300  */
Select_Ray(idVec3 origin,idVec3 dir,int flags)301 void Select_Ray(idVec3 origin, idVec3 dir, int flags) {
302 	qertrace_t	t;
303 
304 	t = Test_Ray(origin, dir, flags);
305 
306 	if (!t.brush) {
307 		return;
308 	}
309 
310 	if (flags == SF_SINGLEFACE) {
311 		int		nCount = g_SelectedFaces.GetSize();
312 		bool	bOk = true;
313 		for (int i = 0; i < nCount; i++) {
314 			if (t.face == reinterpret_cast < face_t * > (g_SelectedFaces.GetAt(i))) {
315 				bOk = false;
316 
317 				// need to move remove i'th entry
318 				g_SelectedFaces.RemoveAt(i, 1);
319 				g_SelectedFaceBrushes.RemoveAt(i, 1);
320 				nCount--;
321 			}
322 		}
323 
324 		if (bOk) {
325 			if ( t.selected ) {
326 				face_t *face;
327 
328 				// DeSelect brush
329 				Brush_RemoveFromList(t.brush);
330 				Brush_AddToList(t.brush, &active_brushes);
331 
332 				// Select all brush faces
333 				for ( face = t.brush->brush_faces; face; face = face->next ) {
334 					//Don't add face that was clicked
335 					if ( face != t.face ) {
336 						g_SelectedFaces.Add( face );
337 						g_SelectedFaceBrushes.Add( t.brush );
338 					}
339 				}
340 			} else {
341 				g_SelectedFaces.Add(t.face);
342 				g_SelectedFaceBrushes.Add(t.brush);
343 			}
344 		}
345 
346 		// selected_face = t.face; selected_face_brush = t.brush;
347 		Sys_UpdateWindows(W_ALL);
348 		g_qeglobals.d_select_mode = sel_brush;
349 
350 
351 		//common->Printf("before\n");
352 		//extern void Face_Info_BrushPrimit(face_t *face);
353 		//Face_Info_BrushPrimit(t.face);
354 		//common->Printf("after\n");
355 
356 		//
357 		// Texture_SetTexture requires a brushprimit_texdef fitted to the default width=2
358 		// height=2 texture
359 		//
360 		brushprimit_texdef_t	brushprimit_texdef;
361 		ConvertTexMatWithQTexture(&t.face->brushprimit_texdef, t.face->d_texture, &brushprimit_texdef, NULL);
362 		Texture_SetTexture(&t.face->texdef, &brushprimit_texdef, false, false);
363 		UpdateSurfaceDialog();
364 
365 
366 		return;
367 	}
368 
369 	// move the brush to the other list
370 	g_qeglobals.d_select_mode = sel_brush;
371 
372 	if (t.selected) {
373 		Brush_RemoveFromList(t.brush);
374 		Brush_AddToList(t.brush, &active_brushes);
375 		UpdatePatchInspector();
376 		UpdateSurfaceDialog();
377 
378 		entity_t	*e = t.brush->owner;
379 		if (e->eclass->nShowFlags & ECLASS_LIGHT && !t.brush->entityModel) {
380 			if (t.brush->pointLight) {
381 			}
382 			else {
383 				ClearSelectablePoints(t.brush);
384 			}
385 		}
386 	}
387 	else {
388 		Select_Brush(t.brush, !(GetAsyncKeyState(VK_MENU) & 0x8000));
389 	}
390 
391 	Sys_UpdateWindows(W_ALL);
392 }
393 
394 /*
395  =======================================================================================================================
396  =======================================================================================================================
397  */
Select_Delete(void)398 void Select_Delete(void) {
399 	brush_t *brush;
400 
401 	g_ptrSelectedFaces.RemoveAll();
402 	g_ptrSelectedFaceBrushes.RemoveAll();
403 
404 	// selected_face = NULL;
405 	g_qeglobals.d_select_mode = sel_brush;
406 
407 	g_qeglobals.d_select_count = 0;
408 	g_qeglobals.d_num_move_points = 0;
409 	while (selected_brushes.next != &selected_brushes) {
410 		brush = selected_brushes.next;
411 		if (brush->pPatch) {
412 			// Patch_Delete(brush->nPatchID);
413 			Patch_Delete(brush->pPatch);
414 		}
415 
416 		Brush_Free(brush);
417 	}
418 
419 	// FIXME: remove any entities with no brushes
420 	Sys_UpdateWindows(W_ALL);
421 }
422 
423 /*
424  =======================================================================================================================
425  =======================================================================================================================
426  */
Select_Deselect(bool bDeselectFaces)427 void Select_Deselect(bool bDeselectFaces) {
428 	brush_t *b;
429 
430 	ClearSelectablePoints(NULL);
431 	Patch_Deselect();
432 
433 	g_pParentWnd->ActiveXY()->UndoClear();
434 
435 	g_qeglobals.d_workcount++;
436 	g_qeglobals.d_select_count = 0;
437 	g_qeglobals.d_num_move_points = 0;
438 	b = selected_brushes.next;
439 
440 	if (b == &selected_brushes) {
441 		if (bDeselectFaces) {
442 			g_ptrSelectedFaces.RemoveAll();
443 			g_ptrSelectedFaceBrushes.RemoveAll();
444 
445 			// selected_face = NULL;
446 		}
447 
448 		Sys_UpdateWindows(W_ALL);
449 		return;
450 	}
451 
452 	if (bDeselectFaces) {
453 		g_ptrSelectedFaces.RemoveAll();
454 		g_ptrSelectedFaceBrushes.RemoveAll();
455 
456 		// selected_face = NULL;
457 	}
458 
459 	g_qeglobals.d_select_mode = sel_brush;
460 
461 	// grab top / bottom height for new brushes
462 	if (b->mins[2] < b->maxs[2]) {
463 		g_qeglobals.d_new_brush_bottom = b->mins;
464 		g_qeglobals.d_new_brush_top = b->maxs;
465 	}
466 
467 	selected_brushes.next->prev = &active_brushes;
468 	selected_brushes.prev->next = active_brushes.next;
469 	active_brushes.next->prev = selected_brushes.prev;
470 	active_brushes.next = selected_brushes.next;
471 	selected_brushes.prev = selected_brushes.next = &selected_brushes;
472 
473 	g_pParentWnd->GetCamera()->UpdateCameraView();
474 
475 	Sys_UpdateWindows(W_ALL);
476 }
477 
478 /*
479  =======================================================================================================================
480 	Select_Move
481  =======================================================================================================================
482  */
Select_Move(idVec3 delta,bool bSnap)483 void Select_Move(idVec3 delta, bool bSnap) {
484 	brush_t		*b;
485 
486 	// actually move the selected brushes
487 	bool		updateOrigin = true;
488 	entity_t	*lastOwner = selected_brushes.next->owner;
489 
490 	for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
491 		Brush_Move(b, delta, bSnap, updateOrigin);
492 		if (updateOrigin) {
493 			updateOrigin = false;
494 		}
495 
496 		if (b->next->owner != lastOwner) {
497 			updateOrigin = true;
498 			lastOwner = b->next->owner;
499 		}
500 	}
501 
502 	idVec3	vMin, vMax;
503 	Select_GetBounds(vMin, vMax);
504 
505 	CString strStatus;
506 	strStatus.Format("Origin X:: %.1f  Y:: %.1f  Z:: %.1f", vMin[0], vMax[1], vMax[2]);
507 	g_pParentWnd->SetStatusText(2, strStatus);
508 	g_pParentWnd->GetCamera()->UpdateCameraView();
509 
510 	// Sys_UpdateWindows (W_ALL);
511 }
512 
513 /*
514  =======================================================================================================================
515 	Select_Clone Creates an exact duplicate of the selection in place, then moves the selected brushes off of their old
516 	positions
517  =======================================================================================================================
518  */
Select_Clone(void)519 void Select_Clone(void) {
520 	ASSERT(g_pParentWnd->ActiveXY());
521 	g_bScreenUpdates = false;
522 	g_pParentWnd->ActiveXY()->Copy();
523 	g_pParentWnd->ActiveXY()->Paste();
524 	g_pParentWnd->NudgeSelection(2, g_qeglobals.d_gridsize);
525 	g_pParentWnd->NudgeSelection(3, g_qeglobals.d_gridsize);
526 	g_bScreenUpdates = true;
527 	Sys_UpdateWindows(W_ALL);
528 }
529 
530 /*
531  =======================================================================================================================
532 	Select_SetTexture Timo:: bFitScale to compute scale on the plane and counteract plane / axial plane snapping Timo::
533 	brush primitive texturing the brushprimit_texdef given must be understood as a qtexture_t width=2 height=2 ( HiRes
534 	) Timo:: texture plugin, added an IPluginTexdef* parameter must be casted to an IPluginTexdef! if not NULL, get
535 	->Copy() of it into each face or brush ( and remember to hook ) if NULL, means we have no information, ask for a
536 	default
537  =======================================================================================================================
538  */
Select_SetTexture(texdef_t * texdef,brushprimit_texdef_t * brushprimit_texdef,bool bFitScale,void * pPlugTexdef,bool update)539 void WINAPI Select_SetTexture(texdef_t *texdef,brushprimit_texdef_t	*brushprimit_texdef,bool bFitScale,void *pPlugTexdef,bool update) {
540 	brush_t *b;
541 	int		nCount = g_ptrSelectedFaces.GetSize();
542 	if (nCount > 0) {
543 		Undo_Start("set face textures");
544 		ASSERT(g_ptrSelectedFaces.GetSize() == g_ptrSelectedFaceBrushes.GetSize());
545 		for (int i = 0; i < nCount; i++) {
546 			face_t	*selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
547 			brush_t *selBrush = reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(i));
548 			Undo_AddBrush(selBrush);
549 			SetFaceTexdef(selBrush,selFace,texdef,brushprimit_texdef,bFitScale);
550 			Brush_Build(selBrush, bFitScale);
551 			Undo_EndBrush(selBrush);
552 		}
553 
554 		Undo_End();
555 	}
556 	else if (selected_brushes.next != &selected_brushes) {
557 		Undo_Start("set brush textures");
558 		for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
559 			if (!b->owner->eclass->fixedsize) {
560 				Undo_AddBrush(b);
561 				Brush_SetTexture(b, texdef, brushprimit_texdef, bFitScale);
562 				Undo_EndBrush(b);
563 			} else if (b->owner->eclass->nShowFlags & ECLASS_LIGHT) {
564 				if ( idStr::Cmpn(texdef->name, "lights/", strlen("lights/")) == 0 ) {
565 					SetKeyValue(b->owner, "texture", texdef->name);
566 					g_Inspectors->UpdateEntitySel(b->owner->eclass);
567 					UpdateLightInspector();
568 					Brush_Build(b);
569 				} else {
570 					Undo_AddBrush(b);
571 					Brush_SetTexture(b, texdef, brushprimit_texdef, bFitScale);
572 					Undo_EndBrush(b);
573 				}
574 			}
575 		}
576 
577 		Undo_End();
578 	}
579 
580 	if (update) {
581 		Sys_UpdateWindows(W_ALL);
582 	}
583 }
584 
585 /*
586  =======================================================================================================================
587 	TRANSFORMATIONS
588  =======================================================================================================================
589  */
Select_GetBounds(idVec3 & mins,idVec3 & maxs)590 void Select_GetBounds(idVec3 &mins, idVec3 &maxs) {
591 	brush_t *b;
592 	int		i;
593 
594 	for (i = 0; i < 3; i++) {
595 		mins[i] = 999999;
596 		maxs[i] = -999999;
597 	}
598 
599 	for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
600 		for (i = 0; i < 3; i++) {
601 			if (b->mins[i] < mins[i]) {
602 				mins[i] = b->mins[i];
603 			}
604 
605 			if (b->maxs[i] > maxs[i]) {
606 				maxs[i] = b->maxs[i];
607 			}
608 		}
609 	}
610 }
611 
612 /*
613  =======================================================================================================================
614  =======================================================================================================================
615  */
Select_GetTrueMid(idVec3 & mid)616 void Select_GetTrueMid(idVec3 &mid) {
617 	idVec3	mins, maxs;
618 	Select_GetBounds(mins, maxs);
619 
620 	for (int i = 0; i < 3; i++) {
621 		mid[i] = (mins[i] + ((maxs[i] - mins[i]) / 2));
622 	}
623 }
624 
625 /*
626  =======================================================================================================================
627  =======================================================================================================================
628  */
Select_GetMid(idVec3 & mid)629 void Select_GetMid(idVec3 &mid) {
630 #if 0
631 	Select_GetTrueMid(mid);
632 	return;
633 #else
634 	idVec3	mins, maxs;
635 	int		i;
636 
637 	//if (g_PrefsDlg.m_bNoClamp) {
638 	//	Select_GetTrueMid(mid);
639 	//	return;
640 	//}
641 
642 	Select_GetBounds(mins, maxs);
643 
644 	for (i = 0; i < 3; i++) {
645 		mid[i] = g_qeglobals.d_gridsize * floor(((mins[i] + maxs[i]) * 0.5) / g_qeglobals.d_gridsize);
646 	}
647 #endif
648 }
649 
650 idVec3	select_origin;
651 idMat3	select_matrix;
652 idMat3	select_bmatrix;
653 idRotation select_rotation;
654 bool	select_fliporder;
655 int		select_flipAxis;
656 float	select_orgDeg;
657 
Select_InitializeRotation()658 void Select_InitializeRotation() {
659 	for (brush_t *b = selected_brushes.next; b != &selected_brushes; b = b->next) {
660 		for (face_t *f = b->brush_faces; f; f = f->next) {
661 			for (int i = 0; i < 3; i++) {
662 				f->orgplanepts[i] = f->planepts[i];
663 			}
664 		}
665 	}
666 	select_orgDeg = 0.0;
667 }
668 
Select_FinalizeRotation()669 void Select_FinalizeRotation() {
670 
671 }
672 
Select_OnlyModelsSelected()673 bool Select_OnlyModelsSelected() {
674 	for (brush_t *b = selected_brushes.next; b != &selected_brushes; b = b->next) {
675 		if (!b->modelHandle) {
676 			return false;
677 		}
678 	}
679 	return true;
680 }
681 
OkForRotationKey(brush_t * b)682 bool OkForRotationKey(brush_t *b) {
683 	if (b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN) {
684 		return false;
685 	}
686 
687 	if (stricmp(b->owner->epairs.GetString("name"), b->owner->epairs.GetString("model")) == 0) {
688 		return false;
689 	}
690 
691 	return true;
692 }
693 
694 /*
695 =================
696 VectorRotate3
697 
698 	rotation order is roll - pitch - yaw
699 =================
700 */
VectorRotate3(const idVec3 & vIn,const idVec3 & vRotation,idVec3 & out)701 void VectorRotate3( const idVec3 &vIn, const idVec3 &vRotation, idVec3 &out) {
702 #if 1
703 	int i, nIndex[3][2];
704 	idVec3 vWork, va;
705 
706 	va = vIn;
707 	vWork = va;
708 	nIndex[0][0] = 1; nIndex[0][1] = 2;
709 	nIndex[1][0] = 2; nIndex[1][1] = 0;
710 	nIndex[2][0] = 0; nIndex[2][1] = 1;
711 
712 	for (i = 0; i < 3; i++) {
713 		if ( vRotation[i] != 0.0f ) {
714 			double dAngle = DEG2RAD( vRotation[i] );
715 			double c = cos( dAngle );
716 			double s = sin( dAngle );
717 			vWork[nIndex[i][0]] = va[nIndex[i][0]] * c - va[nIndex[i][1]] * s;
718 			vWork[nIndex[i][1]] = va[nIndex[i][0]] * s + va[nIndex[i][1]] * c;
719 		}
720 		va = vWork;
721 	}
722 	out = vWork;
723 #else
724 	idAngles angles;
725 
726 	angles.pitch = vRotation[1];
727 	angles.yaw = vRotation[2];
728 	angles.roll = vRotation[0];
729 
730 	out = vIn * angles.ToMat3();
731 #endif
732 }
733 
734 /*
735 =================
736 VectorRotate3Origin
737 =================
738 */
VectorRotate3Origin(const idVec3 & vIn,const idVec3 & vRotation,const idVec3 & vOrigin,idVec3 & out)739 void VectorRotate3Origin( const idVec3 &vIn, const idVec3 &vRotation, const idVec3 &vOrigin, idVec3 &out ) {
740 	out = vIn - vOrigin;
741 	VectorRotate3( out, vRotation, out );
742 	out += vOrigin;
743 }
744 
745 /*
746  =======================================================================================================================
747  =======================================================================================================================
748  */
749 extern void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild);
750 
Select_ApplyMatrix(bool bSnap,bool rotateOrigins)751 void Select_ApplyMatrix(bool bSnap, bool rotateOrigins) {
752 	brush_t *b;
753 	face_t	*f;
754 	int		i;
755 	idVec3	temp;
756 	idStr str;
757 	char	text[128];
758 	entity_t *lastOwner = NULL;
759 
760 	for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
761 
762 		bool doBrush = true;
763 		if (!(b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN) && b->owner != lastOwner) {
764 			if (b->modelHandle || b->owner->eclass->nShowFlags & ECLASS_ROTATABLE) {
765 				if (rotateOrigins) {
766 					b->owner->rotation *= select_matrix;
767 					b->owner->origin *= select_rotation;
768 					SetKeyVec3(b->owner, "origin", b->owner->origin);
769 					if (b->trackLightOrigin) {
770 						b->owner->lightRotation *= select_matrix;
771 						b->owner->lightOrigin *= select_rotation;
772 						SetKeyVec3(b->owner, "light_origin", b->owner->lightOrigin);
773 					}
774 				} else {
775 
776 					b->owner->rotation *= select_matrix;
777 					if ( select_fliporder ) {
778 						if ( select_flipAxis == 0 ) {
779 							temp = b->owner->rotation[1];
780 							b->owner->rotation[1] = b->owner->rotation[2];
781 							b->owner->rotation[2] = temp;
782 						} else if ( select_flipAxis == 1 ) {
783 							temp = b->owner->rotation[0];
784 							b->owner->rotation[0] = b->owner->rotation[1];
785 							b->owner->rotation[1] = temp;
786 						} else {
787 							temp = b->owner->rotation[0];
788 							b->owner->rotation[0] = b->owner->rotation[2];
789 							b->owner->rotation[2] = temp;
790 						}
791 					}
792 
793 					if (b->trackLightOrigin) {
794 						b->owner->lightRotation = select_matrix * b->owner->lightRotation;
795 					}
796 				}
797 				b->owner->rotation.OrthoNormalizeSelf();
798 				b->owner->lightRotation.OrthoNormalizeSelf();
799 
800 				if (b->modelHandle) {
801 					idBounds bo, bo2;
802 					bo2.Zero();
803 					if ( dynamic_cast<idRenderModelPrt*>( b->modelHandle ) || dynamic_cast<idRenderModelLiquid*>( b->modelHandle ) ) {
804 						bo2.ExpandSelf( 12.0f );
805 					} else {
806 						bo2 = b->modelHandle->Bounds();
807 					}
808 					bo.FromTransformedBounds(bo2, b->owner->origin, b->owner->rotation);
809 					Brush_Resize(b, bo[0], bo[1]);
810 					doBrush = false;
811 				}
812 				if (b->owner->eclass->fixedsize) {
813 					doBrush = false;
814 				}
815 			} else if (b->owner->eclass->fixedsize && !rotateOrigins) {
816 				doBrush = false;
817 			} else {
818 				b->owner->origin -= select_origin;
819 				b->owner->origin *= select_matrix;
820 				b->owner->origin += select_origin;
821 				sprintf(text, "%i %i %i", (int)b->owner->origin[0], (int)b->owner->origin[1], (int)b->owner->origin[2]);
822 
823 				SetKeyValue(b->owner, "origin", text);
824 			}
825 
826 
827 
828 			if (OkForRotationKey(b)) {
829 				sprintf(str, "%g %g %g %g %g %g %g %g %g",b->owner->rotation[0][0],b->owner->rotation[0][1],b->owner->rotation[0][2],
830 						b->owner->rotation[1][0],b->owner->rotation[1][1],b->owner->rotation[1][2],b->owner->rotation[2][0],
831 						b->owner->rotation[2][1],b->owner->rotation[2][2]);
832 				SetKeyValue(b->owner, "rotation", str);
833 			}
834 
835 			if (b->trackLightOrigin) {
836 				sprintf(str, "%g %g %g %g %g %g %g %g %g",b->owner->lightRotation[0][0],b->owner->lightRotation[0][1],b->owner->lightRotation[0][2],
837 						b->owner->lightRotation[1][0],b->owner->lightRotation[1][1],b->owner->lightRotation[1][2],b->owner->lightRotation[2][0],
838 						b->owner->lightRotation[2][1],b->owner->lightRotation[2][2]);
839 				SetKeyValue(b->owner, "light_rotation", str);
840 			}
841 			DeleteKey(b->owner, "angle");
842 			DeleteKey(b->owner, "angles");
843 		}
844 
845 		if (doBrush) {
846 			for (f = b->brush_faces; f; f = f->next) {
847 				for (i = 0; i < 3; i++) {
848 					f->planepts[i] = ( ((g_bRotateMode) ? f->orgplanepts[i] : f->planepts[i]) - select_origin ) * ((g_bRotateMode) ? select_bmatrix : select_matrix) + select_origin;
849 				}
850 
851 				if ( select_fliporder ) {
852 					VectorCopy(f->planepts[0], temp);
853 					VectorCopy(f->planepts[2], f->planepts[0]);
854 					VectorCopy(temp, f->planepts[2]);
855 				}
856 			}
857 		}
858 
859 		if (b->owner->eclass->fixedsize && b->owner->eclass->entityModel == NULL) {
860 			idVec3 min, max;
861 			if (b->trackLightOrigin) {
862 				min = b->owner->lightOrigin + b->owner->eclass->mins;
863 				max = b->owner->lightOrigin + b->owner->eclass->maxs;
864 			} else {
865 				min = b->owner->origin + b->owner->eclass->mins;
866 				max = b->owner->origin + b->owner->eclass->maxs;
867 			}
868 			Brush_Resize(b, min, max);
869 		} else {
870 			Brush_Build(b, bSnap);
871 		}
872 
873 		if (b->pPatch) {
874 			Patch_ApplyMatrix(b->pPatch, select_origin, select_matrix, bSnap);
875 		}
876 
877 		if ( b->owner->curve ) {
878 			int c = b->owner->curve->GetNumValues();
879 			for ( i = 0; i < c; i++ ) {
880 				idVec3 v = b->owner->curve->GetValue( i );
881 				v -= select_origin;
882 				v *= select_matrix;
883 				v += select_origin;
884 				b->owner->curve->SetValue( i, v );
885 			}
886 		}
887 
888 		lastOwner = b->owner;
889 	}
890 }
891 
892 /*
893  =======================================================================================================================
894  =======================================================================================================================
895  */
RotateFaceTexture(face_t * f,int nAxis,float fDeg)896 void RotateFaceTexture(face_t *f, int nAxis, float fDeg) {
897 	idVec3	p1, p2, p3, rota;
898 	p1[0] = p1[1] = p1[2] = 0;
899 	VectorCopy(p1, p2);
900 	VectorCopy(p1, p3);
901 	VectorCopy(p1, rota);
902 	ComputeAbsolute(f, p1, p2, p3);
903 
904 	rota[nAxis] = fDeg;
905 	VectorRotate3Origin(p1, rota, select_origin, p1);
906 	VectorRotate3Origin(p2, rota, select_origin, p2);
907 	VectorRotate3Origin(p3, rota, select_origin, p3);
908 
909 	idPlane		normal2;
910 	idVec3		vNormal;
911 	vNormal[0] = f->plane[0];
912 	vNormal[1] = f->plane[1];
913 	vNormal[2] = f->plane[2];
914 	VectorRotate3(vNormal, rota, vNormal);
915 	normal2[0] = vNormal[0];
916 	normal2[1] = vNormal[1];
917 	normal2[2] = vNormal[2];
918 	AbsoluteToLocal(normal2, f, p1, p2, p3);
919 }
920 
921 /*
922  =======================================================================================================================
923  =======================================================================================================================
924  */
RotateTextures(int nAxis,float fDeg,idVec3 vOrigin)925 void RotateTextures(int nAxis, float fDeg, idVec3 vOrigin) {
926 	for (brush_t * b = selected_brushes.next; b != &selected_brushes; b = b->next) {
927 		for (face_t * f = b->brush_faces; f; f = f->next) {
928 			if (g_qeglobals.m_bBrushPrimitMode) {
929 				RotateFaceTexture_BrushPrimit(f, nAxis, fDeg, vOrigin);
930 			}
931 			else {
932 				RotateFaceTexture(f, nAxis, fDeg);
933 			}
934 
935 			// ++timo removed that call .. works fine .. ??????? Brush_Build(b, false);
936 		}
937 
938 		Brush_Build(b, false);
939 	}
940 }
941 
942 /*
943  =======================================================================================================================
944  =======================================================================================================================
945  */
Select_ApplyMatrix_BrushPrimit()946 void Select_ApplyMatrix_BrushPrimit() {
947 	for (brush_t * b = selected_brushes.next; b != &selected_brushes; b = b->next) {
948 		for (face_t * f = b->brush_faces; f; f = f->next) {
949 			ApplyMatrix_BrushPrimit(f, select_matrix, select_origin);
950 		}
951 	}
952 }
953 
954 /*
955  =======================================================================================================================
956  =======================================================================================================================
957  */
Select_RotateAxis(int axis,float deg,bool bPaint,bool bMouse)958 void Select_RotateAxis(int axis, float deg, bool bPaint, bool bMouse) {
959 	idVec3	temp;
960 
961 	if (deg == 0) {
962 		return;
963 	}
964 
965 	if (bMouse) {
966 		if (g_qeglobals.flatRotation == 2) {
967 			Select_GetTrueMid(select_origin);
968 		} else {
969 			VectorCopy(g_pParentWnd->ActiveXY()->RotateOrigin(), select_origin);
970 		}
971 	} else {
972 		Select_GetMid(select_origin);
973 	}
974 
975 	select_fliporder = false;
976 
977 	idVec3 vec = vec3_origin;
978 	vec[axis] = 1.0f;
979 
980 	if (g_bRotateMode) {
981 		select_orgDeg += deg;
982 	}
983 
984 	select_rotation.Set( select_origin, vec, deg );
985 	select_matrix = select_rotation.ToMat3();
986 	idRotation rot(select_origin, vec, select_orgDeg);
987 	rot.Normalize360();
988 	select_bmatrix = rot.ToMat3();
989 
990 
991 	if (g_PrefsDlg.m_bRotateLock) {
992 		select_matrix.TransposeSelf();
993 		Select_ApplyMatrix_BrushPrimit();
994 		//RotateTextures(axis, -deg, select_origin);
995 	}
996 
997 	select_matrix.TransposeSelf();
998 	Select_ApplyMatrix( !bMouse, ( g_qeglobals.flatRotation != 0 ) );
999 
1000 	if (bPaint) {
1001 		Sys_UpdateWindows(W_ALL);
1002 	}
1003 }
1004 
1005 /*
1006  =======================================================================================================================
1007  =======================================================================================================================
1008  */
ProjectOnPlane(const idVec3 & normal,float dist,idVec3 & ez,idVec3 & p)1009 void ProjectOnPlane( const idVec3 &normal, float dist, idVec3 &ez, idVec3 &p) {
1010 	if (idMath::Fabs(ez[0]) == 1) {
1011 		p[0] = (dist - normal[1] * p[1] - normal[2] * p[2]) / normal[0];
1012 	}
1013 	else if (idMath::Fabs(ez[1]) == 1) {
1014 		p[1] = (dist - normal[0] * p[0] - normal[2] * p[2]) / normal[1];
1015 	}
1016 	else {
1017 		p[2] = (dist - normal[0] * p[0] - normal[1] * p[1]) / normal[2];
1018 	}
1019 }
1020 
1021 /*
1022  =======================================================================================================================
1023  =======================================================================================================================
1024  */
Back(idVec3 & dir,idVec3 & p)1025 void Back(idVec3 &dir, idVec3 &p) {
1026 	if (idMath::Fabs(dir[0]) == 1) {
1027 		p[0] = 0;
1028 	}
1029 	else if (idMath::Fabs(dir[1]) == 1) {
1030 		p[1] = 0;
1031 	}
1032 	else {
1033 		p[2] = 0;
1034 	}
1035 }
1036 
1037 //
1038 // =======================================================================================================================
1039 //    using scale[0] and scale[1]
1040 // =======================================================================================================================
1041 //
ComputeScale(idVec3 & rex,idVec3 & rey,idVec3 & p,face_t * f)1042 void ComputeScale(idVec3 &rex, idVec3 &rey, idVec3 &p, face_t *f) {
1043 	float	px = DotProduct(rex, p);
1044 	float	py = DotProduct(rey, p);
1045 	px *= f->texdef.scale[0];
1046 	py *= f->texdef.scale[1];
1047 
1048 	idVec3	aux;
1049 	VectorCopy(rex, aux);
1050 	VectorScale(aux, px, aux);
1051 	VectorCopy(aux, p);
1052 	VectorCopy(rey, aux);
1053 	VectorScale(aux, py, aux);
1054 	VectorAdd(p, aux, p);
1055 }
1056 
1057 /*
1058  =======================================================================================================================
1059  =======================================================================================================================
1060  */
ComputeAbsolute(face_t * f,idVec3 & p1,idVec3 & p2,idVec3 & p3)1061 void ComputeAbsolute(face_t *f, idVec3 &p1, idVec3 &p2, idVec3 &p3) {
1062 	idVec3	ex, ey, ez; // local axis base
1063 
1064 #ifdef _DEBUG
1065 	if (g_qeglobals.m_bBrushPrimitMode) {
1066 		common->Printf("Warning : illegal call of ComputeAbsolute in brush primitive mode\n");
1067 	}
1068 #endif
1069 	// compute first local axis base
1070 	TextureAxisFromPlane( f->plane, ex, ey );
1071 	ez = ex.Cross( ey );
1072 
1073 	idVec3	aux;
1074 	VectorCopy(ex, aux);
1075 	VectorScale(aux, -f->texdef.shift[0], aux);
1076 	VectorCopy(aux, p1);
1077 	VectorCopy(ey, aux);
1078 	VectorScale(aux, -f->texdef.shift[1], aux);
1079 	VectorAdd(p1, aux, p1);
1080 	VectorCopy(p1, p2);
1081 	VectorAdd(p2, ex, p2);
1082 	VectorCopy(p1, p3);
1083 	VectorAdd(p3, ey, p3);
1084 	VectorCopy(ez, aux);
1085 	VectorScale(aux, -f->texdef.rotate, aux);
1086 	VectorRotate3(p1, aux, p1);
1087 	VectorRotate3(p2, aux, p2);
1088 	VectorRotate3(p3, aux, p3);
1089 
1090 	// computing rotated local axis base
1091 	idVec3	rex, rey;
1092 	VectorCopy(ex, rex);
1093 	VectorRotate3(rex, aux, rex);
1094 	VectorCopy(ey, rey);
1095 	VectorRotate3(rey, aux, rey);
1096 
1097 	ComputeScale(rex, rey, p1, f);
1098 	ComputeScale(rex, rey, p2, f);
1099 	ComputeScale(rex, rey, p3, f);
1100 
1101 	// project on normal plane along ez assumes plane normal is normalized
1102 	ProjectOnPlane(f->plane.Normal(), -f->plane[3], ez, p1);
1103 	ProjectOnPlane(f->plane.Normal(), -f->plane[3], ez, p2);
1104 	ProjectOnPlane(f->plane.Normal(), -f->plane[3], ez, p3);
1105 };
1106 
1107 /*
1108  =======================================================================================================================
1109  =======================================================================================================================
1110  */
AbsoluteToLocal(const idPlane & normal2,face_t * f,idVec3 & p1,idVec3 & p2,idVec3 & p3)1111 void AbsoluteToLocal( const idPlane &normal2, face_t *f, idVec3 &p1, idVec3 &p2, idVec3 &p3) {
1112 	idVec3	ex, ey, ez;
1113 
1114 #ifdef _DEBUG
1115 	if (g_qeglobals.m_bBrushPrimitMode) {
1116 		common->Printf("Warning : illegal call of AbsoluteToLocal in brush primitive mode\n");
1117 	}
1118 #endif
1119 	// computing new local axis base
1120 	TextureAxisFromPlane( normal2, ex, ey );
1121 	ez = ex.Cross( ey );
1122 
1123 	// projecting back on (ex,ey)
1124 	Back(ez, p1);
1125 	Back(ez, p2);
1126 	Back(ez, p3);
1127 
1128 	idVec3	aux;
1129 
1130 	// rotation
1131 	VectorCopy(p2, aux);
1132 	VectorSubtract(aux, p1, aux);
1133 
1134 	float	x = DotProduct(aux, ex);
1135 	float	y = DotProduct(aux, ey);
1136 	f->texdef.rotate = RAD2DEG( atan2(y, x) );
1137 
1138 	idVec3	rex, rey;
1139 
1140 	// computing rotated local axis base
1141 	VectorCopy(ez, aux);
1142 	VectorScale(aux, f->texdef.rotate, aux);
1143 	VectorCopy(ex, rex);
1144 	VectorRotate3(rex, aux, rex);
1145 	VectorCopy(ey, rey);
1146 	VectorRotate3(rey, aux, rey);
1147 
1148 	// scale
1149 	VectorCopy(p2, aux);
1150 	VectorSubtract(aux, p1, aux);
1151 	f->texdef.scale[0] = DotProduct(aux, rex);
1152 	VectorCopy(p3, aux);
1153 	VectorSubtract(aux, p1, aux);
1154 	f->texdef.scale[1] = DotProduct(aux, rey);
1155 
1156 	// shift only using p1
1157 	x = DotProduct(rex, p1);
1158 	y = DotProduct(rey, p1);
1159 	x /= f->texdef.scale[0];
1160 	y /= f->texdef.scale[1];
1161 
1162 	VectorCopy(rex, p1);
1163 	VectorScale(p1, x, p1);
1164 	VectorCopy(rey, aux);
1165 	VectorScale(aux, y, aux);
1166 	VectorAdd(p1, aux, p1);
1167 	VectorCopy(ez, aux);
1168 	VectorScale(aux, -f->texdef.rotate, aux);
1169 	VectorRotate3(p1, aux, p1);
1170 	f->texdef.shift[0] = -DotProduct(p1, ex);
1171 	f->texdef.shift[1] = -DotProduct(p1, ey);
1172 
1173 	// stored rot is good considering local axis base change it if necessary
1174 	f->texdef.rotate = -f->texdef.rotate;
1175 
1176 	Clamp(f->texdef.shift[0], f->d_texture->GetEditorImage()->uploadWidth);
1177 	Clamp(f->texdef.shift[1], f->d_texture->GetEditorImage()->uploadHeight);
1178 	Clamp(f->texdef.rotate, 360);
1179 }
1180 
1181 /*
1182  =======================================================================================================================
1183  =======================================================================================================================
1184  */
Select_FlipAxis(int axis)1185 void Select_FlipAxis(int axis) {
1186 
1187 	Select_GetMid( select_origin );
1188 
1189 	for ( int i = 0; i < 3; i++) {
1190 		VectorCopy(vec3_origin, select_matrix[i]);
1191 		select_matrix[i][i] = 1;
1192 	}
1193 
1194 	select_matrix[axis][axis] = -1;
1195 
1196 	select_matrix.Identity();
1197 	select_matrix[axis][axis] = -1;
1198 
1199 	select_fliporder = true;
1200 	select_flipAxis = axis;
1201 
1202 	// texture locking
1203 	if (g_PrefsDlg.m_bRotateLock) {
1204 		//
1205 		// axis flipping inverts space orientation, we have to use a general texture
1206 		// locking algorithm instead of the RotateFaceTexture
1207 		//
1208 		if (g_qeglobals.m_bBrushPrimitMode) {
1209 			Select_ApplyMatrix_BrushPrimit();
1210 		}
1211 		else {
1212 			//
1213 			// there's never been flip locking for non BP mode, this would be tricky to write
1214 			// and there's not much interest for it with the coming of BP format what could be
1215 			// done is converting regular to BP, locking, then back to regular :)
1216 			// Sys_FPrintf(SYS_WRN, "WARNING: regular texturing doesn't have texture lock on
1217 			// flipping operations\n");
1218 			//
1219 		}
1220 	}
1221 
1222 	// geometric transformation
1223 	Select_ApplyMatrix(true, false);
1224 	Sys_UpdateWindows(W_ALL);}
1225 
1226 /*
1227  =======================================================================================================================
1228  =======================================================================================================================
1229  */
Select_Scale(float x,float y,float z)1230 void Select_Scale(float x, float y, float z) {
1231 	Select_GetMid(select_origin);
1232 	for (brush_t * b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1233 		for (face_t * f = b->brush_faces; f; f = f->next) {
1234 			for (int i = 0; i < 3; i++) {
1235 				f->planepts[i][0] -= select_origin[0];
1236 				f->planepts[i][1] -= select_origin[1];
1237 				f->planepts[i][2] -= select_origin[2];
1238 				f->planepts[i][0] *= x;
1239 
1240 				//
1241 				// f->planepts[i][0] = floor(f->planepts[i][0] / g_qeglobals.d_gridsize + 0.5) *
1242 				// g_qeglobals.d_gridsize;
1243 				//
1244 				f->planepts[i][1] *= y;
1245 
1246 				//
1247 				// f->planepts[i][1] = floor(f->planepts[i][1] / g_qeglobals.d_gridsize + 0.5) *
1248 				// g_qeglobals.d_gridsize;
1249 				//
1250 				f->planepts[i][2] *= z;
1251 
1252 				//
1253 				// f->planepts[i][2] = floor(f->planepts[i][2] / g_qeglobals.d_gridsize + 0.5) *
1254 				// g_qeglobals.d_gridsize;
1255 				//
1256 				f->planepts[i][0] += select_origin[0];
1257 				f->planepts[i][1] += select_origin[1];
1258 				f->planepts[i][2] += select_origin[2];
1259 			}
1260 		}
1261 
1262 		Brush_Build(b, false);
1263 		if (b->pPatch) {
1264 			idVec3	v;
1265 			v[0] = x;
1266 			v[1] = y;
1267 			v[2] = z;
1268 
1269 			// Patch_Scale(b->nPatchID, select_origin, v);
1270 			Patch_Scale(b->pPatch, select_origin, v);
1271 		}
1272 	}
1273 }
1274 
1275 /*
1276  =======================================================================================================================
1277 	GROUP SELECTIONS
1278  =======================================================================================================================
1279  */
Select_CompleteTall(void)1280 void Select_CompleteTall(void) {
1281 	brush_t *b, *next;
1282 
1283 	// int i;
1284 	idVec3	mins, maxs;
1285 
1286 	if (!QE_SingleBrush()) {
1287 		return;
1288 	}
1289 
1290 	g_qeglobals.d_select_mode = sel_brush;
1291 
1292 	VectorCopy(selected_brushes.next->mins, mins);
1293 	VectorCopy(selected_brushes.next->maxs, maxs);
1294 	Select_Delete();
1295 
1296 	int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
1297 	int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
1298 
1299 	for (b = active_brushes.next; b != &active_brushes; b = next) {
1300 		next = b->next;
1301 
1302 		if ((b->maxs[nDim1] > maxs[nDim1] || b->mins[nDim1] < mins[nDim1]) || (b->maxs[nDim2] > maxs[nDim2] || b->mins[nDim2] < mins[nDim2])) {
1303 			if (!(b->owner->origin[nDim1] > mins[nDim1] && b->owner->origin[nDim1] < maxs[nDim1] && b->owner->origin[nDim2] > mins[nDim2] && b->owner->origin[nDim2] < maxs[nDim2])) {
1304 				continue;
1305 			}
1306 			if (b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN) {
1307 				continue;
1308 			}
1309 		}
1310 
1311 		if (FilterBrush(b)) {
1312 			continue;
1313 		}
1314 
1315 		Brush_RemoveFromList(b);
1316 		Brush_AddToList(b, &selected_brushes);
1317 	}
1318 
1319 	Sys_UpdateWindows(W_ALL);
1320 }
1321 
1322 /*
1323  =======================================================================================================================
1324  =======================================================================================================================
1325  */
Select_PartialTall(void)1326 void Select_PartialTall(void) {
1327 	brush_t *b, *next;
1328 
1329 	// int i;
1330 	idVec3	mins, maxs;
1331 
1332 	if (!QE_SingleBrush()) {
1333 		return;
1334 	}
1335 
1336 	g_qeglobals.d_select_mode = sel_brush;
1337 
1338 	VectorCopy(selected_brushes.next->mins, mins);
1339 	VectorCopy(selected_brushes.next->maxs, maxs);
1340 	Select_Delete();
1341 
1342 	int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
1343 	int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
1344 
1345 	for (b = active_brushes.next; b != &active_brushes; b = next) {
1346 		next = b->next;
1347 
1348 		if
1349 		(
1350 			(b->mins[nDim1] > maxs[nDim1] || b->maxs[nDim1] < mins[nDim1]) ||
1351 			(b->mins[nDim2] > maxs[nDim2] || b->maxs[nDim2] < mins[nDim2])
1352 		) {
1353 			continue;
1354 		}
1355 
1356 		if (FilterBrush(b)) {
1357 			continue;
1358 		}
1359 
1360 		Brush_RemoveFromList(b);
1361 		Brush_AddToList(b, &selected_brushes);
1362 
1363 #if 0
1364 		// old stuff
1365 		for (i = 0; i < 2; i++) {
1366 			if (b->mins[i] > maxs[i] || b->maxs[i] < mins[i]) {
1367 				break;
1368 			}
1369 		}
1370 
1371 		if (i == 2) {
1372 			Brush_RemoveFromList(b);
1373 			Brush_AddToList(b, &selected_brushes);
1374 		}
1375 #endif
1376 	}
1377 
1378 	Sys_UpdateWindows(W_ALL);
1379 }
1380 
1381 /*
1382  =======================================================================================================================
1383  =======================================================================================================================
1384  */
Select_Touching(void)1385 void Select_Touching(void) {
1386 	brush_t *b, *next;
1387 	int		i;
1388 	idVec3	mins, maxs;
1389 
1390 	if (!QE_SingleBrush()) {
1391 		return;
1392 	}
1393 
1394 	g_qeglobals.d_select_mode = sel_brush;
1395 
1396 	VectorCopy(selected_brushes.next->mins, mins);
1397 	VectorCopy(selected_brushes.next->maxs, maxs);
1398 
1399 	for (b = active_brushes.next; b != &active_brushes; b = next) {
1400 		next = b->next;
1401 
1402 		if (FilterBrush(b)) {
1403 			continue;
1404 		}
1405 
1406 		for (i = 0; i < 3; i++) {
1407 			if (b->mins[i] > maxs[i] + 1 || b->maxs[i] < mins[i] - 1) {
1408 				break;
1409 			}
1410 		}
1411 
1412 		if (i == 3) {
1413 			Brush_RemoveFromList(b);
1414 			Brush_AddToList(b, &selected_brushes);
1415 		}
1416 	}
1417 
1418 	Sys_UpdateWindows(W_ALL);
1419 }
1420 
1421 /*
1422  =======================================================================================================================
1423  =======================================================================================================================
1424  */
Select_Inside(void)1425 void Select_Inside(void) {
1426 	brush_t *b, *next;
1427 	int		i;
1428 	idVec3	mins, maxs;
1429 
1430 	if (!QE_SingleBrush()) {
1431 		return;
1432 	}
1433 
1434 	g_qeglobals.d_select_mode = sel_brush;
1435 
1436 	VectorCopy(selected_brushes.next->mins, mins);
1437 	VectorCopy(selected_brushes.next->maxs, maxs);
1438 	Select_Delete();
1439 
1440 	for (b = active_brushes.next; b != &active_brushes; b = next) {
1441 		next = b->next;
1442 
1443 		if (FilterBrush(b)) {
1444 			continue;
1445 		}
1446 
1447 		for (i = 0; i < 3; i++) {
1448 			if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i]) {
1449 				break;
1450 			}
1451 		}
1452 
1453 		if (i == 3) {
1454 			Brush_RemoveFromList(b);
1455 			Brush_AddToList(b, &selected_brushes);
1456 		}
1457 	}
1458 
1459 	Sys_UpdateWindows(W_ALL);
1460 }
1461 
1462 /*
1463  =======================================================================================================================
1464 	Select_Ungroup Turn the currently selected entity back into normal brushes
1465  =======================================================================================================================
1466  */
Select_Ungroup()1467 void Select_Ungroup() {
1468 	int			numselectedgroups;
1469 	entity_t	*e;
1470 	brush_t		*b, *sb;
1471 
1472 	numselectedgroups = 0;
1473 	for (sb = selected_brushes.next; sb != &selected_brushes; sb = sb->next) {
1474 		e = sb->owner;
1475 
1476 		if (!e || e == world_entity) {
1477 			continue;
1478 		}
1479 
1480 		for (b = e->brushes.onext; b != &e->brushes; b = e->brushes.onext) {
1481 			Entity_UnlinkBrush(b);
1482 			Entity_LinkBrush(world_entity, b);
1483 			Brush_Build(b);
1484 			b->owner = world_entity;
1485 		}
1486 
1487 		Entity_Free(e);
1488 		numselectedgroups++;
1489 	}
1490 
1491 	if (numselectedgroups <= 0) {
1492 		Sys_Status("No grouped entities selected.\n");
1493 		return;
1494 	}
1495 
1496 	common->Printf("Ungrouped %d entit%s.\n", numselectedgroups, (numselectedgroups == 1) ? "y" : "ies");
1497 	Sys_UpdateWindows(W_ALL);
1498 }
1499 
1500 /*
1501  =======================================================================================================================
1502  =======================================================================================================================
1503  */
Select_ShiftTexture(float x,float y,bool autoAdjust)1504 void Select_ShiftTexture(float x, float y, bool autoAdjust) {
1505 	brush_t *b;
1506 	face_t	*f;
1507 
1508 	int		nFaceCount = g_ptrSelectedFaces.GetSize();
1509 
1510 	if (selected_brushes.next == &selected_brushes && nFaceCount == 0) {
1511 		return;
1512 	}
1513 
1514 	x = -x;
1515 
1516 	Undo_Start("Select shift textures");
1517 	for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1518 		for (f = b->brush_faces; f; f = f->next) {
1519 			if (g_qeglobals.m_bBrushPrimitMode) {
1520 				// use face normal to compute a true translation
1521 				Select_ShiftTexture_BrushPrimit(f, x, y, autoAdjust);
1522 			}
1523 			else {
1524 				f->texdef.shift[0] += x;
1525 				f->texdef.shift[1] += y;
1526 			}
1527 		}
1528 
1529 		Brush_Build(b);
1530 		if (b->pPatch) {
1531 			// Patch_ShiftTexture(b->nPatchID, x, y);
1532 			Patch_ShiftTexture(b->pPatch, x, y, autoAdjust);
1533 		}
1534 	}
1535 
1536 	if (nFaceCount > 0) {
1537 		for (int i = 0; i < nFaceCount; i++) {
1538 			face_t	*selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
1539 			brush_t *selBrush = reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(i));
1540 			if (g_qeglobals.m_bBrushPrimitMode) {
1541 				//
1542 				// use face normal to compute a true translation Select_ShiftTexture_BrushPrimit(
1543 				// selected_face, x, y ); use camera view to compute texture shift
1544 				//
1545 				Select_ShiftTexture_BrushPrimit(selFace, x, y, autoAdjust);
1546 			}
1547 			else {
1548 				selFace->texdef.shift[0] += x;
1549 				selFace->texdef.shift[1] += y;
1550 			}
1551 
1552 			Brush_Build(selBrush);
1553 		}
1554 	}
1555 
1556 	Undo_End();
1557 	Sys_UpdateWindows(W_CAMERA);
1558 }
1559 
1560 extern void	Face_SetExplicitScale_BrushPrimit(face_t *face, float s, float t);
1561 extern void Face_ScaleTexture_BrushPrimit(face_t *face, float sS, float sT);
1562 
1563 /*
1564  =======================================================================================================================
1565  =======================================================================================================================
1566  */
Select_ScaleTexture(float x,float y,bool update,bool absolute)1567 void Select_ScaleTexture(float x, float y, bool update, bool absolute) {
1568 	brush_t *b;
1569 	face_t	*f;
1570 
1571 	int		nFaceCount = g_ptrSelectedFaces.GetSize();
1572 
1573 	if (selected_brushes.next == &selected_brushes && nFaceCount == 0) {
1574 		return;
1575 	}
1576 
1577 	Undo_Start("Select_SetExplicitScale_BrushPrimit");
1578 	for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1579 		for (f = b->brush_faces; f; f = f->next) {
1580 			if (g_qeglobals.m_bBrushPrimitMode && f->face_winding) {
1581 				if (absolute) {
1582 					Face_SetExplicitScale_BrushPrimit(f, x, y);
1583 				} else {
1584 					Face_ScaleTexture_BrushPrimit(f, x, y);
1585 				}
1586 			}
1587 			else {
1588 				f->texdef.scale[0] += x;
1589 				f->texdef.scale[1] += y;
1590 			}
1591 		}
1592 
1593 		Brush_Build(b);
1594 		if (b->pPatch) {
1595 			Patch_ScaleTexture(b->pPatch, x, y, absolute);
1596 		}
1597 	}
1598 
1599 	if (nFaceCount > 0) {
1600 		for (int i = 0; i < nFaceCount; i++) {
1601 			face_t	*selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
1602 			brush_t *selBrush = reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(i));
1603 			if (g_qeglobals.m_bBrushPrimitMode) {
1604 				if (absolute) {
1605 					Face_SetExplicitScale_BrushPrimit(selFace, x, y);
1606 				} else {
1607 					Face_ScaleTexture_BrushPrimit(selFace, x, y);
1608 				}
1609 			}
1610 			else {
1611 				selFace->texdef.scale[0] += x;
1612 				selFace->texdef.scale[1] += y;
1613 			}
1614 
1615 			Brush_Build(selBrush);
1616 		}
1617 	}
1618 
1619 	Undo_End();
1620 	if (update) {
1621 		Sys_UpdateWindows(W_CAMERA);
1622 	}
1623 }
1624 
1625 extern void Face_RotateTexture_BrushPrimit(face_t *face, float amount, idVec3 origin);
1626 
1627 /*
1628  =======================================================================================================================
1629  =======================================================================================================================
1630  */
Select_RotateTexture(float amt,bool absolute)1631 void Select_RotateTexture(float amt, bool absolute) {
1632 	brush_t *b;
1633 	face_t	*f;
1634 
1635 	int		nFaceCount = g_ptrSelectedFaces.GetSize();
1636 
1637 	if (selected_brushes.next == &selected_brushes && nFaceCount == 0) {
1638 		return;
1639 	}
1640 
1641 	Undo_Start("Select_RotateTexture_BrushPrimit");
1642 	for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1643 		for (f = b->brush_faces; f; f = f->next) {
1644 			if (g_qeglobals.m_bBrushPrimitMode) {
1645 				Face_RotateTexture_BrushPrimit(f, amt, b->owner->origin);
1646 			}
1647 			else {
1648 				f->texdef.rotate += amt;
1649 				f->texdef.rotate = static_cast<int>(f->texdef.rotate) % 360;
1650 			}
1651 		}
1652 
1653 		Brush_Build(b);
1654 		if (b->pPatch) {
1655 			// Patch_RotateTexture(b->nPatchID, amt);
1656 			Patch_RotateTexture(b->pPatch, amt);
1657 		}
1658 	}
1659 
1660 	if (nFaceCount > 0) {
1661 		for (int i = 0; i < nFaceCount; i++) {
1662 			face_t	*selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
1663 			brush_t *selBrush = reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(i));
1664 			if (g_qeglobals.m_bBrushPrimitMode) {
1665 				idVec3 org;
1666 				org.Zero();
1667 				//Face_RotateTexture_BrushPrimit(selFace, amt, selBrush->owner->origin);
1668 				Face_RotateTexture_BrushPrimit(selFace, amt, org);
1669 			}
1670 			else {
1671 				selFace->texdef.rotate += amt;
1672 				selFace->texdef.rotate = static_cast<int>(selFace->texdef.rotate) % 360;
1673 			}
1674 
1675 			Brush_Build(selBrush);
1676 		}
1677 	}
1678 
1679 	Undo_End();
1680 	Sys_UpdateWindows(W_CAMERA);
1681 }
1682 
1683 /*
1684  =======================================================================================================================
1685  =======================================================================================================================
1686  */
FindReplaceTextures(const char * pFind,const char * pReplace,bool bSelected,bool bForce)1687 void FindReplaceTextures(const char *pFind, const char *pReplace, bool bSelected, bool bForce) {
1688 	brush_t *pList = (bSelected) ? &selected_brushes : &active_brushes;
1689 	if (!bSelected) {
1690 		Select_Deselect();
1691 	}
1692 
1693 	for (brush_t * pBrush = pList->next; pBrush != pList; pBrush = pBrush->next) {
1694 		if (pBrush->pPatch) {
1695 			Patch_FindReplaceTexture(pBrush, pFind, pReplace, bForce);
1696 		}
1697 
1698 		for (face_t * pFace = pBrush->brush_faces; pFace; pFace = pFace->next) {
1699 			if (bForce || idStr::Icmp(pFace->texdef.name, pFind) == 0 ) {
1700 				pFace->d_texture = Texture_ForName(pReplace);
1701 
1702 				// strcpy(pFace->texdef.name, pReplace);
1703 				pFace->texdef.SetName(pReplace);
1704 			}
1705 		}
1706 
1707 		Brush_Build(pBrush);
1708 	}
1709 
1710 	Sys_UpdateWindows(W_CAMERA);
1711 }
1712 
1713 /*
1714  =======================================================================================================================
1715  =======================================================================================================================
1716  */
Select_AllOfType()1717 void Select_AllOfType() {
1718 	brush_t		*b, *next;
1719 	entity_t	*e;
1720 	if ((selected_brushes.next == &selected_brushes) || (selected_brushes.next->next != &selected_brushes)) {
1721 		CString strName;
1722 		if (g_ptrSelectedFaces.GetSize() == 0) {
1723 			strName = g_qeglobals.d_texturewin.texdef.name;
1724 		}
1725 		else {
1726 			face_t	*selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(0));
1727 			strName = selFace->texdef.name;
1728 		}
1729 
1730 		Select_Deselect();
1731 		for (b = active_brushes.next; b != &active_brushes; b = next) {
1732 			next = b->next;
1733 
1734 			if (FilterBrush(b)) {
1735 				continue;
1736 			}
1737 
1738 			if (b->pPatch) {
1739 				if ( idStr::Icmp(strName, b->pPatch->d_texture->GetName()) == 0 ) {
1740 					Brush_RemoveFromList(b);
1741 					Brush_AddToList(b, &selected_brushes);
1742 				}
1743 			}
1744 			else {
1745 				for (face_t * pFace = b->brush_faces; pFace; pFace = pFace->next) {
1746 					if ( idStr::Icmp(strName, pFace->texdef.name) == 0 ) {
1747 						Brush_RemoveFromList(b);
1748 						Brush_AddToList(b, &selected_brushes);
1749 					}
1750 				}
1751 			}
1752 		}
1753 
1754 		Sys_UpdateWindows(W_ALL);
1755 		return;
1756 	}
1757 
1758 	b = selected_brushes.next;
1759 	e = b->owner;
1760 	if (e != NULL) {
1761 		if (e != world_entity) {
1762 			CString strName = e->eclass->name;
1763 			idStr strKey, strVal;
1764 			bool	bCriteria = g_Inspectors->GetSelectAllCriteria(strKey, strVal);
1765 			common->Printf("Selecting all %s(s)\n", strName.GetString());
1766 			Select_Deselect();
1767 
1768 			for (b = active_brushes.next; b != &active_brushes; b = next) {
1769 				next = b->next;
1770 
1771 				if (FilterBrush(b)) {
1772 					continue;
1773 				}
1774 
1775 				e = b->owner;
1776 				if (e != NULL) {
1777 					if ( idStr::Icmp(e->eclass->name, strName) == 0 ) {
1778 						bool	doIt = true;
1779 						if (bCriteria) {
1780 							CString str = ValueForKey(e, strKey);
1781 							if (str.CompareNoCase(strVal) != 0) {
1782 								doIt = false;
1783 							}
1784 						}
1785 
1786 						if (doIt) {
1787 							Brush_RemoveFromList(b);
1788 							Brush_AddToList(b, &selected_brushes);
1789 						}
1790 					}
1791 				}
1792 			}
1793 		}
1794 	}
1795 
1796 
1797 	if ( selected_brushes.next && selected_brushes.next->owner ) {
1798 		g_Inspectors->UpdateEntitySel( selected_brushes.next->owner->eclass );
1799 	}
1800 
1801 	Sys_UpdateWindows(W_ALL);
1802 }
1803 
1804 /*
1805  =======================================================================================================================
1806  =======================================================================================================================
1807  */
Select_Reselect()1808 void Select_Reselect() {
1809 	CPtrArray	holdArray;
1810 	brush_t *b;
1811 	for ( b = selected_brushes.next; b && b != &selected_brushes; b = b->next ) {
1812 		holdArray.Add(reinterpret_cast < void * > (b));
1813 	}
1814 
1815 	int n = holdArray.GetSize();
1816 	while (n-- > 0) {
1817 		b = reinterpret_cast < brush_t * > (holdArray.GetAt(n));
1818 		Select_Brush(b);
1819 	}
1820 
1821 	Sys_UpdateWindows(W_ALL);
1822 }
1823 
1824 /*
1825  =======================================================================================================================
1826  =======================================================================================================================
1827  */
Select_FitTexture(float height,float width)1828 void Select_FitTexture(float height, float width) {
1829 	brush_t *b;
1830 	int		nFaceCount = g_ptrSelectedFaces.GetSize();
1831 
1832 	if (selected_brushes.next == &selected_brushes && nFaceCount == 0) {
1833 		return;
1834 	}
1835 
1836 	Undo_Start("Select_FitTexture");
1837 	for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1838 		if (b->pPatch) {
1839 			Patch_FitTexture(b->pPatch, width, height);
1840 		}
1841 		else {
1842 			Brush_FitTexture(b, height, width);
1843 			Brush_Build(b);
1844 		}
1845 	}
1846 
1847 	if (nFaceCount > 0) {
1848 		for (int i = 0; i < nFaceCount; i++) {
1849 			face_t	*selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
1850 			brush_t *selBrush = reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(i));
1851 			Face_FitTexture(selFace, height, width);
1852 			Brush_Build(selBrush);
1853 		}
1854 	}
1855 
1856 	Undo_End();
1857 	Sys_UpdateWindows(W_CAMERA);
1858 }
1859 
1860 /*
1861  =======================================================================================================================
1862  =======================================================================================================================
1863  */
Select_AxialTexture()1864 void Select_AxialTexture() {
1865 }
1866 
1867 /*
1868  =======================================================================================================================
1869  =======================================================================================================================
1870  */
Select_Hide(bool invert)1871 void Select_Hide(bool invert) {
1872 
1873 	if (invert) {
1874 		for (brush_t * b = active_brushes.next; b && b != &active_brushes; b = b->next) {
1875 			b->hiddenBrush = true;
1876 		}
1877 	} else {
1878 		for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
1879 			b->hiddenBrush = true;
1880 		}
1881 	}
1882 	Sys_UpdateWindows(W_ALL);
1883 }
1884 
Select_WireFrame(bool wireFrame)1885 void Select_WireFrame( bool wireFrame ) {
1886 	for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
1887 		b->forceWireFrame = wireFrame;
1888 	}
1889 	Sys_UpdateWindows(W_ALL);
1890 }
1891 
Select_ForceVisible(bool visible)1892 void Select_ForceVisible( bool visible ) {
1893 	for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
1894 		b->forceVisibile = visible;
1895 	}
1896 	Sys_UpdateWindows(W_ALL);
1897 }
1898 
1899 /*
1900  =======================================================================================================================
1901  =======================================================================================================================
1902  */
Select_ShowAllHidden()1903 void Select_ShowAllHidden() {
1904 	brush_t *b;
1905 	for (b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
1906 		b->hiddenBrush = false;
1907 	}
1908 
1909 	for (b = active_brushes.next; b && b != &active_brushes; b = b->next) {
1910 		b->hiddenBrush = false;
1911 	}
1912 
1913 	Sys_UpdateWindows(W_ALL);
1914 }
1915 
1916 /*
1917  =======================================================================================================================
1918 	Select_Invert
1919  =======================================================================================================================
1920  */
Select_Invert(void)1921 void Select_Invert(void) {
1922 	brush_t *next, *prev;
1923 
1924 	Sys_Status("inverting selection...\n");
1925 
1926 	next = active_brushes.next;
1927 	prev = active_brushes.prev;
1928 	if (selected_brushes.next != &selected_brushes) {
1929 		active_brushes.next = selected_brushes.next;
1930 		active_brushes.prev = selected_brushes.prev;
1931 		active_brushes.next->prev = &active_brushes;
1932 		active_brushes.prev->next = &active_brushes;
1933 	}
1934 	else {
1935 		active_brushes.next = &active_brushes;
1936 		active_brushes.prev = &active_brushes;
1937 	}
1938 
1939 	if (next != &active_brushes) {
1940 		selected_brushes.next = next;
1941 		selected_brushes.prev = prev;
1942 		selected_brushes.next->prev = &selected_brushes;
1943 		selected_brushes.prev->next = &selected_brushes;
1944 	}
1945 	else {
1946 		selected_brushes.next = &selected_brushes;
1947 		selected_brushes.prev = &selected_brushes;
1948 	}
1949 
1950 	Sys_UpdateWindows(W_ALL);
1951 
1952 	Sys_Status("done.\n");
1953 }
1954 
1955 /*
1956  =======================================================================================================================
1957 	Select_Name
1958  =======================================================================================================================
1959  */
Select_Name(const char * pName)1960 void Select_Name(const char *pName) {
1961 	if (g_qeglobals.m_bBrushPrimitMode) {
1962 		for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
1963 			Brush_SetEpair(b, "Name", pName);
1964 		}
1965 	}
1966 }
1967 
1968 /*
1969  =======================================================================================================================
1970  =======================================================================================================================
1971  */
Select_CenterOrigin()1972 void Select_CenterOrigin() {
1973 	idVec3	mid;
1974 
1975 	Select_GetTrueMid(mid);
1976 	mid.Snap();
1977 
1978 	brush_t		*b = selected_brushes.next;
1979 	entity_t	*e = b->owner;
1980 	if (e != NULL) {
1981 		if (e != world_entity) {
1982 			char	text[1024];
1983 			sprintf(text, "%i %i %i", (int)mid[0], (int)mid[1], (int)mid[2]);
1984 			SetKeyValue(e, "origin", text);
1985 			VectorCopy(mid, e->origin);
1986 		}
1987 	}
1988 
1989 	Sys_UpdateWindows(W_ALL);
1990 }
1991 
1992 /*
1993  =======================================================================================================================
1994  =======================================================================================================================
1995  */
Select_NumSelectedFaces()1996 int Select_NumSelectedFaces() {
1997 	return g_ptrSelectedFaces.GetSize();
1998 }
1999 
2000 /*
2001  =======================================================================================================================
2002  =======================================================================================================================
2003  */
Select_GetSelectedFace(int index)2004 face_t *Select_GetSelectedFace(int index) {
2005 	assert(index >= 0 && index < Select_NumSelectedFaces());
2006 	return reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(index));
2007 }
2008 
2009 /*
2010  =======================================================================================================================
2011  =======================================================================================================================
2012  */
Select_GetSelectedFaceBrush(int index)2013 brush_t *Select_GetSelectedFaceBrush(int index) {
2014 	assert(index >= 0 && index < Select_NumSelectedFaces());
2015 	return reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(index));
2016 }
2017 
2018 /*
2019  =======================================================================================================================
2020  =======================================================================================================================
2021  */
Select_SetDefaultTexture(const idMaterial * mat,bool fitScale,bool setTexture)2022 void Select_SetDefaultTexture(const idMaterial *mat, bool fitScale, bool setTexture) {
2023 	texdef_t				tex;
2024 	brushprimit_texdef_t	brushprimit_tex;
2025 	memset(&tex, 0, sizeof(tex));
2026 	memset(&brushprimit_tex, 0, sizeof(brushprimit_tex));
2027 	if (g_qeglobals.m_bBrushPrimitMode) {
2028 		// brushprimit fitted to a 2x2 texture
2029 		brushprimit_tex.coords[0][0] = 1.0f;
2030 		brushprimit_tex.coords[1][1] = 1.0f;
2031 	}
2032 	else {
2033 		tex.scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
2034 		tex.scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
2035 	}
2036 
2037 	tex.SetName(mat->GetName());
2038 	Texture_SetTexture(&tex, &brushprimit_tex, fitScale, setTexture);
2039 
2040 	CString strTex;
2041 	strTex.Format
2042 		(
2043 			"%s (%s) W: %i H: %i",
2044 			mat->GetName(),
2045 			mat->GetDescription(),
2046 			mat->GetEditorImage()->uploadWidth,
2047 			mat->GetEditorImage()->uploadHeight
2048 		);
2049 	g_pParentWnd->SetStatusText(3, strTex);
2050 }
2051 
2052 
Select_UpdateTextureName(const char * name)2053 void Select_UpdateTextureName(const char *name) {
2054 	brush_t *b;
2055 	int		nCount = g_ptrSelectedFaces.GetSize();
2056 	if (nCount > 0) {
2057 		Undo_Start("set face texture name");
2058 		ASSERT(g_ptrSelectedFaces.GetSize() == g_ptrSelectedFaceBrushes.GetSize());
2059 		for (int i = 0; i < nCount; i++) {
2060 			face_t	*selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
2061 			brush_t *selBrush = reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(i));
2062 			Undo_AddBrush(selBrush);
2063 			selFace->texdef.SetName(name);
2064 			Brush_Build(selBrush);
2065 			Undo_EndBrush(selBrush);
2066 		}
2067 
2068 		Undo_End();
2069 	}
2070 	else if (selected_brushes.next != &selected_brushes) {
2071 		Undo_Start("set brush textures");
2072 		for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
2073 			if (!b->owner->eclass->fixedsize) {
2074 				Undo_AddBrush(b);
2075 				Brush_SetTextureName(b, name);
2076 				Undo_EndBrush(b);
2077 			} else if (b->owner->eclass->nShowFlags & ECLASS_LIGHT) {
2078 				if ( idStr::Cmpn(name, "lights/", strlen("lights/")) == 0 ) {
2079 					SetKeyValue(b->owner, "texture", name);
2080 					g_Inspectors->UpdateEntitySel(b->owner->eclass);
2081 					UpdateLightInspector();
2082 					Brush_Build(b);
2083 				}
2084 			}
2085 		}
2086 
2087 		Undo_End();
2088 	}
2089 
2090 	Sys_UpdateWindows(W_ALL);
2091 }
2092 
2093 
2094 /*
2095  =======================================================================================================================
2096  =======================================================================================================================
2097  */
Select_FlipTexture(bool y)2098 void Select_FlipTexture(bool y) {
2099 
2100 	int faceCount = g_ptrSelectedFaces.GetSize();
2101 
2102 	Undo_Start("Select_FlipTexture");
2103 	for (brush_t *b = selected_brushes.next; b != &selected_brushes; b = b->next) {
2104 		if (b->pPatch) {
2105 			Patch_FlipTexture(b->pPatch, y);
2106 		} else {
2107 			Brush_FlipTexture_BrushPrimit(b, y);
2108 		}
2109 	}
2110 
2111 	if (faceCount > 0) {
2112 		for (int i = 0; i < faceCount; i++) {
2113 			face_t	*selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
2114 			brush_t *selBrush = reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(i));
2115 			Face_FlipTexture_BrushPrimit(selFace, y);
2116 		}
2117 	}
2118 
2119 	Undo_End();
2120 	Sys_UpdateWindows(W_CAMERA);
2121 }
2122 
2123 
2124 
2125 
2126 /*
2127  =======================================================================================================================
2128 	Select_SetKeyVal
2129 	sets values on non-world entities
2130  =======================================================================================================================
2131  */
Select_SetKeyVal(const char * key,const char * val)2132 void Select_SetKeyVal(const char *key, const char *val) {
2133 	for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
2134 		if (b->owner != world_entity) {
2135 			SetKeyValue(b->owner, key, val, false);
2136 		}
2137 	}
2138 }
2139 
2140 /*
2141  =======================================================================================================================
2142 	Select_CopyPatchTextureCoords( patchMesh_t *p )
2143  =======================================================================================================================
2144  */
Select_CopyPatchTextureCoords(patchMesh_t * p)2145 void Select_CopyPatchTextureCoords( patchMesh_t *p ) {
2146 	for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
2147 		if (b->pPatch) {
2148 			if ( b->pPatch->width <= p->width && b->pPatch->height <= p->height ) {
2149 				for ( int i = 0; i < b->pPatch->width; i ++ ) {
2150 					for ( int j = 0; j < b->pPatch->height; j++ ) {
2151 						b->pPatch->ctrl(i, j).st = p->ctrl(i, j).st;
2152 					}
2153 				}
2154 			}
2155 		}
2156 	}
2157 }
2158 
2159 
2160 /*
2161  =======================================================================================================================
2162 	Select_SetProjectFaceOntoPatch
2163  =======================================================================================================================
2164  */
Select_ProjectFaceOntoPatch(face_t * face)2165 void Select_ProjectFaceOntoPatch( face_t *face ) {
2166 	for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
2167 		if (b->pPatch) {
2168 			EmitBrushPrimitTextureCoordinates(face, NULL, b->pPatch);
2169 			Patch_MakeDirty(b->pPatch);
2170 		}
2171 	}
2172 }
2173 
2174 /*
2175  =======================================================================================================================
2176 	Select_SetPatchFit
2177  =======================================================================================================================
2178  */
2179 extern float Patch_Width(patchMesh_t *p);
2180 extern float Patch_Height(patchMesh_t *p);
Select_SetPatchFit(float dim1,float dim2,float srcWidth,float srcHeight,float rot)2181 void Select_SetPatchFit(float dim1, float dim2, float srcWidth, float srcHeight, float rot) {
2182 	for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
2183 		if (b->pPatch) {
2184 			float w = Patch_Width(b->pPatch);
2185 			float h = Patch_Height(b->pPatch);
2186 			Patch_RotateTexture(b->pPatch, -90 + rot);
2187 			Patch_FitTexture(b->pPatch, dim1 * (w / srcWidth), dim2 * (h / srcHeight));
2188 			Patch_FlipTexture(b->pPatch, true);
2189 		}
2190 	}
2191 }
2192 
Select_SetPatchST(float s1,float t1,float s2,float t2)2193 void Select_SetPatchST(float s1, float t1, float s2, float t2) {
2194 }
2195 
2196 
Select_AllTargets()2197 void Select_AllTargets() {
2198 	for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
2199 		if (b->owner != world_entity) {
2200 			const idKeyValue *kv = b->owner->epairs.MatchPrefix("target", NULL);
2201 			while (kv) {
2202 				entity_t *ent = FindEntity("name", kv->GetValue());
2203 				if (ent) {
2204 					Select_Brush(ent->brushes.onext, true, false);
2205 				}
2206 				kv = b->owner->epairs.MatchPrefix("target", kv);
2207 			}
2208 		}
2209 	}
2210 }