2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
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.
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.
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/>.
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.
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.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
33 #include "../../renderer/model_local.h" // for idRenderModelPrt
36 CPtrArray g_SelectedFaces;
37 CPtrArray g_SelectedFaceBrushes;
38 CPtrArray &g_ptrSelectedFaces = g_SelectedFaces;
39 CPtrArray &g_ptrSelectedFaceBrushes = g_SelectedFaceBrushes;
41 extern void Brush_Resize(brush_t *b, idVec3 vMin, idVec3 vMax);
44 =======================================================================================================================
45 =======================================================================================================================
47 qertrace_t Test_Ray(const idVec3 &origin, const idVec3 &dir, int flags) {
53 memset(&t, 0, sizeof(t));
54 t.dist = HUGE_DISTANCE*2;
56 // check for points first
57 CDragPoint *drag = PointRay(origin, dir, &dist);
67 if (flags & SF_CYCLE) {
69 brush_t *pToSelect = (selected_brushes.next != &selected_brushes) ? selected_brushes.next : NULL;
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)) {
79 if (g_PrefsDlg.m_selectOnlyBrushes) {
80 if (brush->pPatch || brush->modelHandle > 0) {
85 if (g_PrefsDlg.m_selectNoModels) {
86 if (brush->modelHandle > 0) {
91 // if (!g_bShowPatchBounds && brush->pPatch) continue;
92 face = Brush_Ray(origin, dir, brush, &dist, true);
99 int nSize = array.GetSize();
102 for (int i = 0; i < nSize; i++) {
103 brush_t *b = reinterpret_cast < brush_t * > (array.GetAt(i));
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));
116 pToSelect = reinterpret_cast < brush_t * > (array.GetAt(0));
121 face = Brush_Ray(origin, dir, pToSelect, &dist, true);
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) {
136 if (FilterBrush(brush)) {
140 if (g_PrefsDlg.m_selectOnlyBrushes) {
141 if (brush->pPatch || brush->modelHandle > 0) {
146 if (g_PrefsDlg.m_selectNoModels) {
147 if (brush->modelHandle > 0) {
152 face = Brush_Ray(origin, dir, brush, &dist, true);
153 if (dist > 0 && dist < t.dist) {
162 for (brush = selected_brushes.next; brush != &selected_brushes; brush = brush->next) {
163 if ((flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) {
167 if (FilterBrush(brush)) {
171 if (g_PrefsDlg.m_selectOnlyBrushes) {
172 if (brush->pPatch || brush->modelHandle > 0) {
177 if (g_PrefsDlg.m_selectNoModels) {
178 if (brush->modelHandle > 0) {
183 face = Brush_Ray(origin, dir, brush, &dist, true);
184 if (dist > 0 && dist < t.dist) {
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);
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);
205 =======================================================================================================================
207 =======================================================================================================================
209 void Select_Brush(brush_t *brush, bool bComplete, bool bStatus) {
213 g_ptrSelectedFaces.RemoveAll();
214 g_ptrSelectedFaceBrushes.RemoveAll();
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;
221 g_qeglobals.d_select_count++;
226 if ( e == world_entity && radiant_entityMode.GetBool() ) {
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) {
237 for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
238 Brush_RemoveFromList(b);
239 Brush_AddToList(b, &selected_brushes);
245 Brush_RemoveFromList(brush);
246 Brush_AddToList(brush, &selected_brushes);
247 UpdateSurfaceDialog();
248 UpdatePatchInspector();
249 UpdateLightInspector();
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");
257 g_Inspectors->mediaDlg.SelectCurrentItem(true, p, CDialogTextures::SOUNDS);
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);
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);
277 UpdateLightInspector();
279 if (e->eclass->nShowFlags & ECLASS_CAMERAVIEW) {
280 g_pParentWnd->GetCamera()->UpdateCameraView();
286 idVec3 vMin, vMax, vSize;
287 Select_GetBounds(vMin, vMax);
288 VectorSubtract(vMax, vMin, vSize);
291 strStatus.Format("Selection X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]);
292 g_pParentWnd->SetStatusText(2, strStatus);
297 =======================================================================================================================
298 Select_Ray If the origin is inside a brush, that brush will be ignored.
299 =======================================================================================================================
301 void Select_Ray(idVec3 origin, idVec3 dir, int flags) {
304 t = Test_Ray(origin, dir, flags);
310 if (flags == SF_SINGLEFACE) {
311 int nCount = g_SelectedFaces.GetSize();
313 for (int i = 0; i < nCount; i++) {
314 if (t.face == reinterpret_cast < face_t * > (g_SelectedFaces.GetAt(i))) {
317 // need to move remove i'th entry
318 g_SelectedFaces.RemoveAt(i, 1);
319 g_SelectedFaceBrushes.RemoveAt(i, 1);
329 Brush_RemoveFromList(t.brush);
330 Brush_AddToList(t.brush, &active_brushes);
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 );
341 g_SelectedFaces.Add(t.face);
342 g_SelectedFaceBrushes.Add(t.brush);
346 // selected_face = t.face; selected_face_brush = t.brush;
347 Sys_UpdateWindows(W_ALL);
348 g_qeglobals.d_select_mode = sel_brush;
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");
357 // Texture_SetTexture requires a brushprimit_texdef fitted to the default width=2
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();
369 // move the brush to the other list
370 g_qeglobals.d_select_mode = sel_brush;
373 Brush_RemoveFromList(t.brush);
374 Brush_AddToList(t.brush, &active_brushes);
375 UpdatePatchInspector();
376 UpdateSurfaceDialog();
378 entity_t *e = t.brush->owner;
379 if (e->eclass->nShowFlags & ECLASS_LIGHT && !t.brush->entityModel) {
380 if (t.brush->pointLight) {
383 ClearSelectablePoints(t.brush);
388 Select_Brush(t.brush, !(GetAsyncKeyState(VK_MENU) & 0x8000));
391 Sys_UpdateWindows(W_ALL);
395 =======================================================================================================================
396 =======================================================================================================================
398 void Select_Delete(void) {
401 g_ptrSelectedFaces.RemoveAll();
402 g_ptrSelectedFaceBrushes.RemoveAll();
404 // selected_face = NULL;
405 g_qeglobals.d_select_mode = sel_brush;
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;
412 // Patch_Delete(brush->nPatchID);
413 Patch_Delete(brush->pPatch);
419 // FIXME: remove any entities with no brushes
420 Sys_UpdateWindows(W_ALL);
424 =======================================================================================================================
425 =======================================================================================================================
427 void Select_Deselect(bool bDeselectFaces) {
430 ClearSelectablePoints(NULL);
433 g_pParentWnd->ActiveXY()->UndoClear();
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;
440 if (b == &selected_brushes) {
441 if (bDeselectFaces) {
442 g_ptrSelectedFaces.RemoveAll();
443 g_ptrSelectedFaceBrushes.RemoveAll();
445 // selected_face = NULL;
448 Sys_UpdateWindows(W_ALL);
452 if (bDeselectFaces) {
453 g_ptrSelectedFaces.RemoveAll();
454 g_ptrSelectedFaceBrushes.RemoveAll();
456 // selected_face = NULL;
459 g_qeglobals.d_select_mode = sel_brush;
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;
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;
473 g_pParentWnd->GetCamera()->UpdateCameraView();
475 Sys_UpdateWindows(W_ALL);
479 =======================================================================================================================
481 =======================================================================================================================
483 void Select_Move(idVec3 delta, bool bSnap) {
486 // actually move the selected brushes
487 bool updateOrigin = true;
488 entity_t *lastOwner = selected_brushes.next->owner;
490 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
491 Brush_Move(b, delta, bSnap, updateOrigin);
493 updateOrigin = false;
496 if (b->next->owner != lastOwner) {
498 lastOwner = b->next->owner;
503 Select_GetBounds(vMin, vMax);
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();
510 // Sys_UpdateWindows (W_ALL);
514 =======================================================================================================================
515 Select_Clone Creates an exact duplicate of the selection in place, then moves the selected brushes off of their old
517 =======================================================================================================================
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);
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
537 =======================================================================================================================
539 void WINAPI Select_SetTexture(texdef_t *texdef,brushprimit_texdef_t *brushprimit_texdef,bool bFitScale,void *pPlugTexdef,bool update) {
541 int nCount = g_ptrSelectedFaces.GetSize();
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);
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) {
561 Brush_SetTexture(b, texdef, brushprimit_texdef, bFitScale);
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();
571 Brush_SetTexture(b, texdef, brushprimit_texdef, bFitScale);
581 Sys_UpdateWindows(W_ALL);
586 =======================================================================================================================
588 =======================================================================================================================
590 void Select_GetBounds(idVec3 &mins, idVec3 &maxs) {
594 for (i = 0; i < 3; i++) {
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];
605 if (b->maxs[i] > maxs[i]) {
606 maxs[i] = b->maxs[i];
613 =======================================================================================================================
614 =======================================================================================================================
616 void Select_GetTrueMid(idVec3 &mid) {
618 Select_GetBounds(mins, maxs);
620 for (int i = 0; i < 3; i++) {
621 mid[i] = (mins[i] + ((maxs[i] - mins[i]) / 2));
626 =======================================================================================================================
627 =======================================================================================================================
629 void Select_GetMid(idVec3 &mid) {
631 Select_GetTrueMid(mid);
637 //if (g_PrefsDlg.m_bNoClamp) {
638 // Select_GetTrueMid(mid);
642 Select_GetBounds(mins, maxs);
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);
650 idVec3 select_origin;
651 idMat3 select_matrix;
652 idMat3 select_bmatrix;
653 idRotation select_rotation;
654 bool select_fliporder;
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];
669 void Select_FinalizeRotation() {
673 bool Select_OnlyModelsSelected() {
674 for (brush_t *b = selected_brushes.next; b != &selected_brushes; b = b->next) {
675 if (!b->modelHandle) {
682 bool OkForRotationKey(brush_t *b) {
683 if (b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN) {
687 if (stricmp(b->owner->epairs.GetString("name"), b->owner->epairs.GetString("model")) == 0) {
698 rotation order is roll - pitch - yaw
701 void VectorRotate3( const idVec3 &vIn, const idVec3 &vRotation, idVec3 &out) {
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;
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;
726 angles.pitch = vRotation[1];
727 angles.yaw = vRotation[2];
728 angles.roll = vRotation[0];
730 out = vIn * angles.ToMat3();
739 void VectorRotate3Origin( const idVec3 &vIn, const idVec3 &vRotation, const idVec3 &vOrigin, idVec3 &out ) {
741 VectorRotate3( out, vRotation, out );
746 =======================================================================================================================
747 =======================================================================================================================
749 extern void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild);
751 void Select_ApplyMatrix(bool bSnap, bool rotateOrigins) {
758 entity_t *lastOwner = NULL;
760 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
763 if (!(b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN) && b->owner != lastOwner) {
764 if (b->modelHandle || b->owner->eclass->nShowFlags & ECLASS_ROTATABLE) {
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);
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;
787 temp = b->owner->rotation[0];
788 b->owner->rotation[0] = b->owner->rotation[2];
789 b->owner->rotation[2] = temp;
793 if (b->trackLightOrigin) {
794 b->owner->lightRotation = select_matrix * b->owner->lightRotation;
797 b->owner->rotation.OrthoNormalizeSelf();
798 b->owner->lightRotation.OrthoNormalizeSelf();
800 if (b->modelHandle) {
803 if ( dynamic_cast<idRenderModelPrt*>( b->modelHandle ) || dynamic_cast<idRenderModelLiquid*>( b->modelHandle ) ) {
804 bo2.ExpandSelf( 12.0f );
806 bo2 = b->modelHandle->Bounds();
808 bo.FromTransformedBounds(bo2, b->owner->origin, b->owner->rotation);
809 Brush_Resize(b, bo[0], bo[1]);
812 if (b->owner->eclass->fixedsize) {
815 } else if (b->owner->eclass->fixedsize && !rotateOrigins) {
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]);
823 SetKeyValue(b->owner, "origin", text);
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);
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);
841 DeleteKey(b->owner, "angle");
842 DeleteKey(b->owner, "angles");
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;
851 if ( select_fliporder ) {
852 VectorCopy(f->planepts[0], temp);
853 VectorCopy(f->planepts[2], f->planepts[0]);
854 VectorCopy(temp, f->planepts[2]);
859 if (b->owner->eclass->fixedsize && b->owner->eclass->entityModel == NULL) {
861 if (b->trackLightOrigin) {
862 min = b->owner->lightOrigin + b->owner->eclass->mins;
863 max = b->owner->lightOrigin + b->owner->eclass->maxs;
865 min = b->owner->origin + b->owner->eclass->mins;
866 max = b->owner->origin + b->owner->eclass->maxs;
868 Brush_Resize(b, min, max);
870 Brush_Build(b, bSnap);
874 Patch_ApplyMatrix(b->pPatch, select_origin, select_matrix, bSnap);
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 );
884 b->owner->curve->SetValue( i, v );
888 lastOwner = b->owner;
893 =======================================================================================================================
894 =======================================================================================================================
896 void RotateFaceTexture(face_t *f, int nAxis, float fDeg) {
897 idVec3 p1, p2, p3, rota;
898 p1[0] = p1[1] = p1[2] = 0;
901 VectorCopy(p1, rota);
902 ComputeAbsolute(f, p1, p2, p3);
905 VectorRotate3Origin(p1, rota, select_origin, p1);
906 VectorRotate3Origin(p2, rota, select_origin, p2);
907 VectorRotate3Origin(p3, rota, select_origin, p3);
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);
922 =======================================================================================================================
923 =======================================================================================================================
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);
932 RotateFaceTexture(f, nAxis, fDeg);
935 // ++timo removed that call .. works fine .. ??????? Brush_Build(b, false);
938 Brush_Build(b, false);
943 =======================================================================================================================
944 =======================================================================================================================
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);
955 =======================================================================================================================
956 =======================================================================================================================
958 void Select_RotateAxis(int axis, float deg, bool bPaint, bool bMouse) {
966 if (g_qeglobals.flatRotation == 2) {
967 Select_GetTrueMid(select_origin);
969 VectorCopy(g_pParentWnd->ActiveXY()->RotateOrigin(), select_origin);
972 Select_GetMid(select_origin);
975 select_fliporder = false;
977 idVec3 vec = vec3_origin;
981 select_orgDeg += deg;
984 select_rotation.Set( select_origin, vec, deg );
985 select_matrix = select_rotation.ToMat3();
986 idRotation rot(select_origin, vec, select_orgDeg);
988 select_bmatrix = rot.ToMat3();
991 if (g_PrefsDlg.m_bRotateLock) {
992 select_matrix.TransposeSelf();
993 Select_ApplyMatrix_BrushPrimit();
994 //RotateTextures(axis, -deg, select_origin);
997 select_matrix.TransposeSelf();
998 Select_ApplyMatrix( !bMouse, ( g_qeglobals.flatRotation != 0 ) );
1001 Sys_UpdateWindows(W_ALL);
1006 =======================================================================================================================
1007 =======================================================================================================================
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];
1013 else if (idMath::Fabs(ez[1]) == 1) {
1014 p[1] = (dist - normal[0] * p[0] - normal[2] * p[2]) / normal[1];
1017 p[2] = (dist - normal[0] * p[0] - normal[1] * p[1]) / normal[2];
1022 =======================================================================================================================
1023 =======================================================================================================================
1025 void Back(idVec3 &dir, idVec3 &p) {
1026 if (idMath::Fabs(dir[0]) == 1) {
1029 else if (idMath::Fabs(dir[1]) == 1) {
1038 // =======================================================================================================================
1039 // using scale[0] and scale[1]
1040 // =======================================================================================================================
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];
1049 VectorCopy(rex, aux);
1050 VectorScale(aux, px, aux);
1052 VectorCopy(rey, aux);
1053 VectorScale(aux, py, aux);
1054 VectorAdd(p, aux, p);
1058 =======================================================================================================================
1059 =======================================================================================================================
1061 void ComputeAbsolute(face_t *f, idVec3 &p1, idVec3 &p2, idVec3 &p3) {
1062 idVec3 ex, ey, ez; // local axis base
1065 if (g_qeglobals.m_bBrushPrimitMode) {
1066 common->Printf("Warning : illegal call of ComputeAbsolute in brush primitive mode\n");
1069 // compute first local axis base
1070 TextureAxisFromPlane( f->plane, ex, ey );
1071 ez = ex.Cross( ey );
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);
1081 VectorAdd(p2, ex, p2);
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);
1090 // computing rotated local axis base
1092 VectorCopy(ex, rex);
1093 VectorRotate3(rex, aux, rex);
1094 VectorCopy(ey, rey);
1095 VectorRotate3(rey, aux, rey);
1097 ComputeScale(rex, rey, p1, f);
1098 ComputeScale(rex, rey, p2, f);
1099 ComputeScale(rex, rey, p3, f);
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);
1108 =======================================================================================================================
1109 =======================================================================================================================
1111 void AbsoluteToLocal( const idPlane &normal2, face_t *f, idVec3 &p1, idVec3 &p2, idVec3 &p3) {
1115 if (g_qeglobals.m_bBrushPrimitMode) {
1116 common->Printf("Warning : illegal call of AbsoluteToLocal in brush primitive mode\n");
1119 // computing new local axis base
1120 TextureAxisFromPlane( normal2, ex, ey );
1121 ez = ex.Cross( ey );
1123 // projecting back on (ex,ey)
1131 VectorCopy(p2, aux);
1132 VectorSubtract(aux, p1, aux);
1134 float x = DotProduct(aux, ex);
1135 float y = DotProduct(aux, ey);
1136 f->texdef.rotate = RAD2DEG( atan2(y, x) );
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);
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);
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];
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);
1173 // stored rot is good considering local axis base change it if necessary
1174 f->texdef.rotate = -f->texdef.rotate;
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);
1182 =======================================================================================================================
1183 =======================================================================================================================
1185 void Select_FlipAxis(int axis) {
1187 Select_GetMid( select_origin );
1189 for ( int i = 0; i < 3; i++) {
1190 VectorCopy(vec3_origin, select_matrix[i]);
1191 select_matrix[i][i] = 1;
1194 select_matrix[axis][axis] = -1;
1196 select_matrix.Identity();
1197 select_matrix[axis][axis] = -1;
1199 select_fliporder = true;
1200 select_flipAxis = axis;
1203 if (g_PrefsDlg.m_bRotateLock) {
1205 // axis flipping inverts space orientation, we have to use a general texture
1206 // locking algorithm instead of the RotateFaceTexture
1208 if (g_qeglobals.m_bBrushPrimitMode) {
1209 Select_ApplyMatrix_BrushPrimit();
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");
1222 // geometric transformation
1223 Select_ApplyMatrix(true, false);
1224 Sys_UpdateWindows(W_ALL);}
1227 =======================================================================================================================
1228 =======================================================================================================================
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;
1241 // f->planepts[i][0] = floor(f->planepts[i][0] / g_qeglobals.d_gridsize + 0.5) *
1242 // g_qeglobals.d_gridsize;
1244 f->planepts[i][1] *= y;
1247 // f->planepts[i][1] = floor(f->planepts[i][1] / g_qeglobals.d_gridsize + 0.5) *
1248 // g_qeglobals.d_gridsize;
1250 f->planepts[i][2] *= z;
1253 // f->planepts[i][2] = floor(f->planepts[i][2] / g_qeglobals.d_gridsize + 0.5) *
1254 // g_qeglobals.d_gridsize;
1256 f->planepts[i][0] += select_origin[0];
1257 f->planepts[i][1] += select_origin[1];
1258 f->planepts[i][2] += select_origin[2];
1262 Brush_Build(b, false);
1269 // Patch_Scale(b->nPatchID, select_origin, v);
1270 Patch_Scale(b->pPatch, select_origin, v);
1276 =======================================================================================================================
1278 =======================================================================================================================
1280 void Select_CompleteTall(void) {
1286 if (!QE_SingleBrush()) {
1290 g_qeglobals.d_select_mode = sel_brush;
1292 VectorCopy(selected_brushes.next->mins, mins);
1293 VectorCopy(selected_brushes.next->maxs, maxs);
1296 int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
1297 int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
1299 for (b = active_brushes.next; b != &active_brushes; b = next) {
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])) {
1306 if (b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN) {
1311 if (FilterBrush(b)) {
1315 Brush_RemoveFromList(b);
1316 Brush_AddToList(b, &selected_brushes);
1319 Sys_UpdateWindows(W_ALL);
1323 =======================================================================================================================
1324 =======================================================================================================================
1326 void Select_PartialTall(void) {
1332 if (!QE_SingleBrush()) {
1336 g_qeglobals.d_select_mode = sel_brush;
1338 VectorCopy(selected_brushes.next->mins, mins);
1339 VectorCopy(selected_brushes.next->maxs, maxs);
1342 int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
1343 int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
1345 for (b = active_brushes.next; b != &active_brushes; b = next) {
1350 (b->mins[nDim1] > maxs[nDim1] || b->maxs[nDim1] < mins[nDim1]) ||
1351 (b->mins[nDim2] > maxs[nDim2] || b->maxs[nDim2] < mins[nDim2])
1356 if (FilterBrush(b)) {
1360 Brush_RemoveFromList(b);
1361 Brush_AddToList(b, &selected_brushes);
1365 for (i = 0; i < 2; i++) {
1366 if (b->mins[i] > maxs[i] || b->maxs[i] < mins[i]) {
1372 Brush_RemoveFromList(b);
1373 Brush_AddToList(b, &selected_brushes);
1378 Sys_UpdateWindows(W_ALL);
1382 =======================================================================================================================
1383 =======================================================================================================================
1385 void Select_Touching(void) {
1390 if (!QE_SingleBrush()) {
1394 g_qeglobals.d_select_mode = sel_brush;
1396 VectorCopy(selected_brushes.next->mins, mins);
1397 VectorCopy(selected_brushes.next->maxs, maxs);
1399 for (b = active_brushes.next; b != &active_brushes; b = next) {
1402 if (FilterBrush(b)) {
1406 for (i = 0; i < 3; i++) {
1407 if (b->mins[i] > maxs[i] + 1 || b->maxs[i] < mins[i] - 1) {
1413 Brush_RemoveFromList(b);
1414 Brush_AddToList(b, &selected_brushes);
1418 Sys_UpdateWindows(W_ALL);
1422 =======================================================================================================================
1423 =======================================================================================================================
1425 void Select_Inside(void) {
1430 if (!QE_SingleBrush()) {
1434 g_qeglobals.d_select_mode = sel_brush;
1436 VectorCopy(selected_brushes.next->mins, mins);
1437 VectorCopy(selected_brushes.next->maxs, maxs);
1440 for (b = active_brushes.next; b != &active_brushes; b = next) {
1443 if (FilterBrush(b)) {
1447 for (i = 0; i < 3; i++) {
1448 if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i]) {
1454 Brush_RemoveFromList(b);
1455 Brush_AddToList(b, &selected_brushes);
1459 Sys_UpdateWindows(W_ALL);
1463 =======================================================================================================================
1464 Select_Ungroup Turn the currently selected entity back into normal brushes
1465 =======================================================================================================================
1467 void Select_Ungroup() {
1468 int numselectedgroups;
1472 numselectedgroups = 0;
1473 for (sb = selected_brushes.next; sb != &selected_brushes; sb = sb->next) {
1476 if (!e || e == world_entity) {
1480 for (b = e->brushes.onext; b != &e->brushes; b = e->brushes.onext) {
1481 Entity_UnlinkBrush(b);
1482 Entity_LinkBrush(world_entity, b);
1484 b->owner = world_entity;
1488 numselectedgroups++;
1491 if (numselectedgroups <= 0) {
1492 Sys_Status("No grouped entities selected.\n");
1496 common->Printf("Ungrouped %d entit%s.\n", numselectedgroups, (numselectedgroups == 1) ? "y" : "ies");
1497 Sys_UpdateWindows(W_ALL);
1501 =======================================================================================================================
1502 =======================================================================================================================
1504 void Select_ShiftTexture(float x, float y, bool autoAdjust) {
1508 int nFaceCount = g_ptrSelectedFaces.GetSize();
1510 if (selected_brushes.next == &selected_brushes && nFaceCount == 0) {
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);
1524 f->texdef.shift[0] += x;
1525 f->texdef.shift[1] += y;
1531 // Patch_ShiftTexture(b->nPatchID, x, y);
1532 Patch_ShiftTexture(b->pPatch, x, y, autoAdjust);
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) {
1542 // use face normal to compute a true translation Select_ShiftTexture_BrushPrimit(
1543 // selected_face, x, y ); use camera view to compute texture shift
1545 Select_ShiftTexture_BrushPrimit(selFace, x, y, autoAdjust);
1548 selFace->texdef.shift[0] += x;
1549 selFace->texdef.shift[1] += y;
1552 Brush_Build(selBrush);
1557 Sys_UpdateWindows(W_CAMERA);
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);
1564 =======================================================================================================================
1565 =======================================================================================================================
1567 void Select_ScaleTexture(float x, float y, bool update, bool absolute) {
1571 int nFaceCount = g_ptrSelectedFaces.GetSize();
1573 if (selected_brushes.next == &selected_brushes && nFaceCount == 0) {
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) {
1582 Face_SetExplicitScale_BrushPrimit(f, x, y);
1584 Face_ScaleTexture_BrushPrimit(f, x, y);
1588 f->texdef.scale[0] += x;
1589 f->texdef.scale[1] += y;
1595 Patch_ScaleTexture(b->pPatch, x, y, absolute);
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) {
1605 Face_SetExplicitScale_BrushPrimit(selFace, x, y);
1607 Face_ScaleTexture_BrushPrimit(selFace, x, y);
1611 selFace->texdef.scale[0] += x;
1612 selFace->texdef.scale[1] += y;
1615 Brush_Build(selBrush);
1621 Sys_UpdateWindows(W_CAMERA);
1625 extern void Face_RotateTexture_BrushPrimit(face_t *face, float amount, idVec3 origin);
1628 =======================================================================================================================
1629 =======================================================================================================================
1631 void Select_RotateTexture(float amt, bool absolute) {
1635 int nFaceCount = g_ptrSelectedFaces.GetSize();
1637 if (selected_brushes.next == &selected_brushes && nFaceCount == 0) {
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);
1648 f->texdef.rotate += amt;
1649 f->texdef.rotate = static_cast<int>(f->texdef.rotate) % 360;
1655 // Patch_RotateTexture(b->nPatchID, amt);
1656 Patch_RotateTexture(b->pPatch, amt);
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) {
1667 //Face_RotateTexture_BrushPrimit(selFace, amt, selBrush->owner->origin);
1668 Face_RotateTexture_BrushPrimit(selFace, amt, org);
1671 selFace->texdef.rotate += amt;
1672 selFace->texdef.rotate = static_cast<int>(selFace->texdef.rotate) % 360;
1675 Brush_Build(selBrush);
1680 Sys_UpdateWindows(W_CAMERA);
1684 =======================================================================================================================
1685 =======================================================================================================================
1687 void FindReplaceTextures(const char *pFind, const char *pReplace, bool bSelected, bool bForce) {
1688 brush_t *pList = (bSelected) ? &selected_brushes : &active_brushes;
1693 for (brush_t * pBrush = pList->next; pBrush != pList; pBrush = pBrush->next) {
1694 if (pBrush->pPatch) {
1695 Patch_FindReplaceTexture(pBrush, pFind, pReplace, bForce);
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);
1702 // strcpy(pFace->texdef.name, pReplace);
1703 pFace->texdef.SetName(pReplace);
1707 Brush_Build(pBrush);
1710 Sys_UpdateWindows(W_CAMERA);
1714 =======================================================================================================================
1715 =======================================================================================================================
1717 void Select_AllOfType() {
1720 if ((selected_brushes.next == &selected_brushes) || (selected_brushes.next->next != &selected_brushes)) {
1722 if (g_ptrSelectedFaces.GetSize() == 0) {
1723 strName = g_qeglobals.d_texturewin.texdef.name;
1726 face_t *selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(0));
1727 strName = selFace->texdef.name;
1731 for (b = active_brushes.next; b != &active_brushes; b = next) {
1734 if (FilterBrush(b)) {
1739 if ( idStr::Icmp(strName, b->pPatch->d_texture->GetName()) == 0 ) {
1740 Brush_RemoveFromList(b);
1741 Brush_AddToList(b, &selected_brushes);
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);
1754 Sys_UpdateWindows(W_ALL);
1758 b = selected_brushes.next;
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);
1768 for (b = active_brushes.next; b != &active_brushes; b = next) {
1771 if (FilterBrush(b)) {
1777 if ( idStr::Icmp(e->eclass->name, strName) == 0 ) {
1780 CString str = ValueForKey(e, strKey);
1781 if (str.CompareNoCase(strVal) != 0) {
1787 Brush_RemoveFromList(b);
1788 Brush_AddToList(b, &selected_brushes);
1797 if ( selected_brushes.next && selected_brushes.next->owner ) {
1798 g_Inspectors->UpdateEntitySel( selected_brushes.next->owner->eclass );
1801 Sys_UpdateWindows(W_ALL);
1805 =======================================================================================================================
1806 =======================================================================================================================
1808 void Select_Reselect() {
1809 CPtrArray holdArray;
1811 for ( b = selected_brushes.next; b && b != &selected_brushes; b = b->next ) {
1812 holdArray.Add(reinterpret_cast < void * > (b));
1815 int n = holdArray.GetSize();
1817 b = reinterpret_cast < brush_t * > (holdArray.GetAt(n));
1821 Sys_UpdateWindows(W_ALL);
1825 =======================================================================================================================
1826 =======================================================================================================================
1828 void Select_FitTexture(float height, float width) {
1830 int nFaceCount = g_ptrSelectedFaces.GetSize();
1832 if (selected_brushes.next == &selected_brushes && nFaceCount == 0) {
1836 Undo_Start("Select_FitTexture");
1837 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1839 Patch_FitTexture(b->pPatch, width, height);
1842 Brush_FitTexture(b, height, width);
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);
1857 Sys_UpdateWindows(W_CAMERA);
1861 =======================================================================================================================
1862 =======================================================================================================================
1864 void Select_AxialTexture() {
1868 =======================================================================================================================
1869 =======================================================================================================================
1871 void Select_Hide(bool invert) {
1874 for (brush_t * b = active_brushes.next; b && b != &active_brushes; b = b->next) {
1875 b->hiddenBrush = true;
1878 for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
1879 b->hiddenBrush = true;
1882 Sys_UpdateWindows(W_ALL);
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;
1889 Sys_UpdateWindows(W_ALL);
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;
1896 Sys_UpdateWindows(W_ALL);
1900 =======================================================================================================================
1901 =======================================================================================================================
1903 void Select_ShowAllHidden() {
1905 for (b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
1906 b->hiddenBrush = false;
1909 for (b = active_brushes.next; b && b != &active_brushes; b = b->next) {
1910 b->hiddenBrush = false;
1913 Sys_UpdateWindows(W_ALL);
1917 =======================================================================================================================
1919 =======================================================================================================================
1921 void Select_Invert(void) {
1922 brush_t *next, *prev;
1924 Sys_Status("inverting selection...\n");
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;
1935 active_brushes.next = &active_brushes;
1936 active_brushes.prev = &active_brushes;
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;
1946 selected_brushes.next = &selected_brushes;
1947 selected_brushes.prev = &selected_brushes;
1950 Sys_UpdateWindows(W_ALL);
1952 Sys_Status("done.\n");
1956 =======================================================================================================================
1958 =======================================================================================================================
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);
1969 =======================================================================================================================
1970 =======================================================================================================================
1972 void Select_CenterOrigin() {
1975 Select_GetTrueMid(mid);
1978 brush_t *b = selected_brushes.next;
1979 entity_t *e = b->owner;
1981 if (e != world_entity) {
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);
1989 Sys_UpdateWindows(W_ALL);
1993 =======================================================================================================================
1994 =======================================================================================================================
1996 int Select_NumSelectedFaces() {
1997 return g_ptrSelectedFaces.GetSize();
2001 =======================================================================================================================
2002 =======================================================================================================================
2004 face_t *Select_GetSelectedFace(int index) {
2005 assert(index >= 0 && index < Select_NumSelectedFaces());
2006 return reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(index));
2010 =======================================================================================================================
2011 =======================================================================================================================
2013 brush_t *Select_GetSelectedFaceBrush(int index) {
2014 assert(index >= 0 && index < Select_NumSelectedFaces());
2015 return reinterpret_cast < brush_t * > (g_ptrSelectedFaceBrushes.GetAt(index));
2019 =======================================================================================================================
2020 =======================================================================================================================
2022 void Select_SetDefaultTexture(const idMaterial *mat, bool fitScale, bool setTexture) {
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;
2033 tex.scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
2034 tex.scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
2037 tex.SetName(mat->GetName());
2038 Texture_SetTexture(&tex, &brushprimit_tex, fitScale, setTexture);
2043 "%s (%s) W: %i H: %i",
2045 mat->GetDescription(),
2046 mat->GetEditorImage()->uploadWidth,
2047 mat->GetEditorImage()->uploadHeight
2049 g_pParentWnd->SetStatusText(3, strTex);
2053 void Select_UpdateTextureName(const char *name) {
2055 int nCount = g_ptrSelectedFaces.GetSize();
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);
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) {
2075 Brush_SetTextureName(b, name);
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();
2090 Sys_UpdateWindows(W_ALL);
2095 =======================================================================================================================
2096 =======================================================================================================================
2098 void Select_FlipTexture(bool y) {
2100 int faceCount = g_ptrSelectedFaces.GetSize();
2102 Undo_Start("Select_FlipTexture");
2103 for (brush_t *b = selected_brushes.next; b != &selected_brushes; b = b->next) {
2105 Patch_FlipTexture(b->pPatch, y);
2107 Brush_FlipTexture_BrushPrimit(b, y);
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);
2120 Sys_UpdateWindows(W_CAMERA);
2127 =======================================================================================================================
2129 sets values on non-world entities
2130 =======================================================================================================================
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);
2141 =======================================================================================================================
2142 Select_CopyPatchTextureCoords( patchMesh_t *p )
2143 =======================================================================================================================
2145 void Select_CopyPatchTextureCoords( patchMesh_t *p ) {
2146 for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
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;
2161 =======================================================================================================================
2162 Select_SetProjectFaceOntoPatch
2163 =======================================================================================================================
2165 void Select_ProjectFaceOntoPatch( face_t *face ) {
2166 for (brush_t * b = selected_brushes.next; b && b != &selected_brushes; b = b->next) {
2168 EmitBrushPrimitTextureCoordinates(face, NULL, b->pPatch);
2169 Patch_MakeDirty(b->pPatch);
2175 =======================================================================================================================
2177 =======================================================================================================================
2179 extern float Patch_Width(patchMesh_t *p);
2180 extern float Patch_Height(patchMesh_t *p);
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) {
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);
2193 void Select_SetPatchST(float s1, float t1, float s2, float t2) {
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);
2202 entity_t *ent = FindEntity("name", kv->GetValue());
2204 Select_Brush(ent->brushes.onext, true, false);
2206 kv = b->owner->epairs.MatchPrefix("target", kv);