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 }