SELECT.CPP (40721B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 // select.c 23 #include "stdafx.h" 24 #include "qe3.h" 25 26 27 // externs 28 CPtrArray g_SelectedFaces; 29 CPtrArray g_SelectedFaceBrushes; 30 CPtrArray& g_ptrSelectedFaces = g_SelectedFaces; 31 CPtrArray& g_ptrSelectedFaceBrushes = g_SelectedFaceBrushes; 32 33 34 void clearSelection() { 35 g_qeglobals.d_select_mode = sel_brush; 36 g_qeglobals.selectObject = NULL; 37 } 38 39 /* 40 =========== 41 Test_Ray 42 =========== 43 */ 44 #define DIST_START 999999 45 trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags) 46 { 47 brush_t *brush; 48 face_t *face; 49 float dist; 50 trace_t t; 51 52 memset (&t, 0, sizeof(t)); 53 t.dist = DIST_START; 54 55 if (flags & SF_CYCLE) 56 { 57 CPtrArray array; 58 brush_t *pToSelect = (selected_brushes.next != &selected_brushes) ? selected_brushes.next : NULL; 59 Select_Deselect(); 60 61 // go through active brushes and accumulate all "hit" brushes 62 for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next) 63 { 64 //if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) 65 // continue; 66 67 if (FilterBrush (brush)) 68 continue; 69 70 if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush) 71 continue; 72 73 if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush ) 74 continue; 75 76 //if (!g_bShowPatchBounds && brush->patchBrush) 77 // continue; 78 79 face = Brush_Ray (origin, dir, brush, &dist); 80 81 if (face) 82 { 83 if ( brush->terrainBrush ) 84 { 85 Terrain_Ray( origin, dir, brush, &dist ); 86 if( dist == 0 ) 87 { 88 // didn't actually hit the terrain 89 continue; 90 } 91 } 92 array.Add(brush); 93 } 94 } 95 96 int nSize = array.GetSize(); 97 if (nSize > 0) 98 { 99 bool bFound = false; 100 for (int i = 0; i < nSize; i++) 101 { 102 brush_t *b = reinterpret_cast<brush_t*>(array.GetAt(i)); 103 // did we hit the last one selected yet ? 104 if (b == pToSelect) 105 { 106 // yes we want to select the next one in the list 107 int n = (i > 0) ? i-1 : nSize-1; 108 pToSelect = reinterpret_cast<brush_t*>(array.GetAt(n)); 109 bFound = true; 110 break; 111 } 112 } 113 if (!bFound) 114 pToSelect = reinterpret_cast<brush_t*>(array.GetAt(0)); 115 } 116 if (pToSelect) 117 { 118 face = Brush_Ray (origin, dir, pToSelect, &dist); 119 if ( pToSelect->terrainBrush ) 120 { 121 t.terraface = Terrain_Ray( origin, dir, pToSelect, &dist ); 122 } 123 124 t.dist = dist; 125 t.brush = pToSelect; 126 t.face = face; 127 t.selected = false; 128 return t; 129 } 130 } 131 132 if (! (flags & SF_SELECTED_ONLY) ) 133 { 134 for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next) 135 { 136 if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) 137 continue; 138 139 if (FilterBrush (brush)) 140 continue; 141 142 if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush) 143 continue; 144 145 if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush ) 146 continue; 147 148 //if (!g_bShowPatchBounds && brush->patchBrush) 149 // continue; 150 151 face = Brush_Ray (origin, dir, brush, &dist); 152 if ( face ) { 153 if ( brush->terrainBrush ) 154 { 155 t.terraface = Terrain_Ray( origin, dir, brush, &dist ); 156 } 157 } 158 if (dist > 0 && dist < t.dist) 159 { 160 t.dist = dist; 161 t.brush = brush; 162 t.face = face; 163 t.selected = false; 164 } 165 } 166 } 167 168 169 for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) 170 { 171 if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) 172 continue; 173 174 if (FilterBrush (brush)) 175 continue; 176 177 if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush) 178 continue; 179 180 if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush ) 181 continue; 182 183 face = Brush_Ray (origin, dir, brush, &dist); 184 if ( face ) { 185 if ( brush->terrainBrush ) 186 { 187 t.terraface = Terrain_Ray( origin, dir, brush, &dist ); 188 } 189 } 190 if (dist > 0 && dist < t.dist) 191 { 192 t.dist = dist; 193 t.brush = brush; 194 t.face = face; 195 t.selected = true; 196 } 197 } 198 199 // if entites first, but didn't find any, check regular 200 201 if ( (flags & SF_ENTITIES_FIRST) && t.brush == NULL) 202 return Test_Ray (origin, dir, flags - SF_ENTITIES_FIRST); 203 204 return t; 205 206 } 207 208 209 /* 210 ============ 211 Select_Brush 212 213 ============ 214 */ 215 void Select_Brush (brush_t *brush, bool bComplete, bool bStatus) 216 { 217 brush_t *b; 218 entity_t *e; 219 220 g_ptrSelectedFaces.RemoveAll(); 221 g_ptrSelectedFaceBrushes.RemoveAll(); 222 //selected_face = NULL; 223 if (g_qeglobals.d_select_count < 2) 224 g_qeglobals.d_select_order[g_qeglobals.d_select_count] = brush; 225 g_qeglobals.d_select_count++; 226 227 //if (brush->patchBrush) 228 // Patch_Select(brush->nPatchID); 229 230 e = brush->owner; 231 if (e) 232 { 233 // select complete entity on first click 234 if (e != world_entity && bComplete == true) 235 { 236 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 237 if (b->owner == e) 238 goto singleselect; 239 for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext) 240 { 241 Brush_RemoveFromList (b); 242 Brush_AddToList (b, &selected_brushes); 243 } 244 } 245 else 246 { 247 singleselect: 248 Brush_RemoveFromList (brush); 249 Brush_AddToList (brush, &selected_brushes); 250 UpdateSurfaceDialog(); 251 UpdatePatchInspector(); 252 } 253 254 if (e->eclass) 255 { 256 UpdateEntitySel(brush->owner->eclass); 257 } 258 } 259 if (bStatus) 260 { 261 vec3_t vMin, vMax, vSize; 262 Select_GetBounds (vMin, vMax); 263 VectorSubtract(vMax, vMin, vSize); 264 CString strStatus; 265 strStatus.Format("Selection X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]); 266 g_pParentWnd->SetStatusText(2, strStatus); 267 } 268 } 269 270 271 /* 272 ============ 273 Select_Ray 274 275 If the origin is inside a brush, that brush will be ignored. 276 ============ 277 */ 278 void Select_Ray (vec3_t origin, vec3_t dir, int flags) 279 { 280 trace_t t; 281 282 t = Test_Ray (origin, dir, flags); 283 if (!t.brush) 284 return; 285 286 if (flags == SF_SINGLEFACE) 287 { 288 int nCount = g_SelectedFaces.GetSize(); 289 bool bOk = true; 290 for (int i = 0; i < nCount; i++) 291 { 292 if (t.face == reinterpret_cast<face_t*>(g_SelectedFaces.GetAt(i))) 293 { 294 bOk = false; 295 // need to move remove i'th entry 296 g_SelectedFaces.RemoveAt(i, 1); 297 g_SelectedFaceBrushes.RemoveAt(i, 1); 298 } 299 } 300 if (bOk) 301 { 302 g_SelectedFaces.Add(t.face); 303 g_SelectedFaceBrushes.Add(t.brush); 304 } 305 //selected_face = t.face; 306 //selected_face_brush = t.brush; 307 Sys_UpdateWindows (W_ALL); 308 clearSelection(); 309 // Texture_SetTexture requires a brushprimit_texdef fitted to the default width=2 height=2 texture 310 brushprimit_texdef_t brushprimit_texdef; 311 ConvertTexMatWithQTexture ( &t.face->brushprimit_texdef, t.face->d_texture, &brushprimit_texdef, NULL ); 312 Texture_SetTexture ( &t.face->texdef, &brushprimit_texdef, false, GETPLUGINTEXDEF(t.face), false ); 313 UpdateSurfaceDialog(); 314 return; 315 } 316 317 // move the brush to the other list 318 319 clearSelection(); 320 321 if (t.selected) 322 { 323 Brush_RemoveFromList (t.brush); 324 Brush_AddToList (t.brush, &active_brushes); 325 UpdatePatchInspector(); 326 } 327 else 328 { 329 Select_Brush (t.brush, !(GetKeyState(VK_MENU) & 0x8000)); 330 } 331 332 Sys_UpdateWindows (W_ALL); 333 } 334 335 336 void Select_Delete (void) 337 { 338 brush_t *brush; 339 340 g_ptrSelectedFaces.RemoveAll(); 341 g_ptrSelectedFaceBrushes.RemoveAll(); 342 //selected_face = NULL; 343 344 clearSelection(); 345 346 g_qeglobals.d_select_count = 0; 347 g_qeglobals.d_num_move_points = 0; 348 while (selected_brushes.next != &selected_brushes) 349 { 350 brush = selected_brushes.next; 351 if (brush->patchBrush) 352 { 353 //Patch_Delete(brush->nPatchID); 354 Patch_Delete(brush->pPatch); 355 } 356 if (brush->terrainBrush) 357 { 358 Terrain_Delete(brush->pTerrain ); 359 } 360 361 Brush_Free (brush); 362 } 363 364 // FIXME: remove any entities with no brushes 365 366 Sys_UpdateWindows (W_ALL); 367 } 368 369 void Select_Deselect (bool bDeselectFaces) 370 { 371 brush_t *b; 372 373 Patch_Deselect(); 374 375 g_pParentWnd->ActiveXY()->UndoClear(); 376 377 g_qeglobals.d_workcount++; 378 g_qeglobals.d_select_count = 0; 379 g_qeglobals.d_num_move_points = 0; 380 b = selected_brushes.next; 381 382 if (b == &selected_brushes) 383 { 384 if (bDeselectFaces) 385 { 386 g_ptrSelectedFaces.RemoveAll(); 387 g_ptrSelectedFaceBrushes.RemoveAll(); 388 //selected_face = NULL; 389 } 390 Sys_UpdateWindows (W_ALL); 391 return; 392 } 393 394 if (bDeselectFaces) 395 { 396 g_ptrSelectedFaces.RemoveAll(); 397 g_ptrSelectedFaceBrushes.RemoveAll(); 398 //selected_face = NULL; 399 } 400 401 clearSelection(); 402 403 // grab top / bottom height for new brushes 404 if (b->mins[2] < b->maxs[2]) 405 { 406 g_qeglobals.d_new_brush_bottom_z = b->mins[2]; 407 g_qeglobals.d_new_brush_top_z = b->maxs[2]; 408 } 409 410 selected_brushes.next->prev = &active_brushes; 411 selected_brushes.prev->next = active_brushes.next; 412 active_brushes.next->prev = selected_brushes.prev; 413 active_brushes.next = selected_brushes.next; 414 selected_brushes.prev = selected_brushes.next = &selected_brushes; 415 416 Sys_UpdateWindows (W_ALL); 417 } 418 419 /* 420 ============ 421 Select_Move 422 ============ 423 */ 424 void Select_Move (vec3_t delta, bool bSnap) 425 { 426 brush_t *b; 427 428 429 // actually move the selected brushes 430 for (b = selected_brushes.next ; b != &selected_brushes ; b=b->next) 431 Brush_Move (b, delta, bSnap); 432 433 vec3_t vMin, vMax; 434 Select_GetBounds (vMin, vMax); 435 CString strStatus; 436 strStatus.Format("Origin X:: %.1f Y:: %.1f Z:: %.1f", vMin[0], vMax[1], vMax[2]); 437 g_pParentWnd->SetStatusText(2, strStatus); 438 439 // Sys_UpdateWindows (W_ALL); 440 } 441 442 /* 443 ============ 444 Select_Clone 445 446 Creates an exact duplicate of the selection in place, then moves 447 the selected brushes off of their old positions 448 ============ 449 */ 450 void Select_Clone (void) 451 { 452 #if 1 453 ASSERT(g_pParentWnd->ActiveXY()); 454 g_bScreenUpdates = false; 455 g_pParentWnd->ActiveXY()->Copy(); 456 g_pParentWnd->ActiveXY()->Paste(); 457 g_pParentWnd->NudgeSelection(2, g_qeglobals.d_gridsize); 458 g_pParentWnd->NudgeSelection(3, g_qeglobals.d_gridsize); 459 g_bScreenUpdates = true; 460 Sys_UpdateWindows(W_ALL); 461 #else 462 463 brush_t *b, *b2, *n, *next, *next2; 464 vec3_t delta; 465 entity_t *e; 466 467 g_qeglobals.d_workcount++; 468 clearSelection(); 469 470 delta[0] = g_qeglobals.d_gridsize; 471 delta[1] = g_qeglobals.d_gridsize; 472 delta[2] = 0; 473 474 for (b=selected_brushes.next ; b != &selected_brushes ; b=next) 475 { 476 next = b->next; 477 // if the brush is a world brush, handle simply 478 if (b->owner == world_entity) 479 { 480 n = Brush_Clone (b); 481 Brush_AddToList (n, &active_brushes); 482 Entity_LinkBrush (world_entity, n); 483 Brush_Build( n ); 484 Brush_Move (b, delta); 485 continue; 486 } 487 488 e = Entity_Clone (b->owner); 489 // clear the target / targetname 490 DeleteKey (e, "target"); 491 DeleteKey (e, "targetname"); 492 493 // if the brush is a fixed size entity, create a new entity 494 if (b->owner->eclass->fixedsize) 495 { 496 n = Brush_Clone (b); 497 Brush_AddToList (n, &active_brushes); 498 Entity_LinkBrush (e, n); 499 Brush_Build( n ); 500 Brush_Move (b, delta); 501 continue; 502 } 503 504 // brush is a complex entity, grab all the other ones now 505 506 next = &selected_brushes; 507 508 for ( b2 = b ; b2 != &selected_brushes ; b2=next2) 509 { 510 next2 = b2->next; 511 if (b2->owner != b->owner) 512 { 513 if (next == &selected_brushes) 514 next = b2; 515 continue; 516 } 517 518 // move b2 to the start of selected_brushes, 519 // so it won't be hit again 520 Brush_RemoveFromList (b2); 521 Brush_AddToList (b2, &selected_brushes); 522 523 n = Brush_Clone (b2); 524 Brush_AddToList (n, &active_brushes); 525 Entity_LinkBrush (e, n); 526 Brush_Build( n ); 527 Brush_Move (b2, delta, true); 528 } 529 530 } 531 Sys_UpdateWindows (W_ALL); 532 #endif 533 } 534 535 536 537 /* 538 ============ 539 Select_SetTexture 540 Timo : bFitScale to compute scale on the plane and counteract plane / axial plane snapping 541 Timo : brush primitive texturing 542 the brushprimit_texdef given must be understood as a qtexture_t width=2 height=2 ( HiRes ) 543 Timo : texture plugin, added an IPluginTexdef* parameter 544 must be casted to an IPluginTexdef! 545 if not NULL, get ->Copy() of it into each face or brush ( and remember to hook ) 546 if NULL, means we have no information, ask for a default 547 ============ 548 */ 549 void WINAPI Select_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, void* pPlugTexdef ) 550 { 551 brush_t *b; 552 int nCount = g_ptrSelectedFaces.GetSize(); 553 if (nCount > 0) 554 { 555 Undo_Start("set face textures"); 556 ASSERT(g_ptrSelectedFaces.GetSize() == g_ptrSelectedFaceBrushes.GetSize()); 557 for (int i = 0; i < nCount; i++) 558 { 559 face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i)); 560 brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i)); 561 Undo_AddBrush(selBrush); 562 SetFaceTexdef (selBrush, selFace, texdef, brushprimit_texdef, bFitScale, static_cast<IPluginTexdef *>(pPlugTexdef) ); 563 Brush_Build(selBrush, bFitScale); 564 Undo_EndBrush(selBrush); 565 } 566 Undo_End(); 567 } 568 else if (selected_brushes.next != &selected_brushes) 569 { 570 Undo_Start("set brush textures"); 571 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 572 if (!b->owner->eclass->fixedsize) 573 { 574 Undo_AddBrush(b); 575 Brush_SetTexture (b, texdef, brushprimit_texdef, bFitScale, static_cast<IPluginTexdef *>(pPlugTexdef) ); 576 Undo_EndBrush(b); 577 } 578 Undo_End(); 579 } 580 Sys_UpdateWindows (W_ALL); 581 } 582 583 584 /* 585 ================================================================ 586 587 TRANSFORMATIONS 588 589 ================================================================ 590 */ 591 592 void Select_GetBounds (vec3_t mins, vec3_t maxs) 593 { 594 brush_t *b; 595 int i; 596 597 for (i=0 ; i<3 ; i++) 598 { 599 mins[i] = 99999; 600 maxs[i] = -99999; 601 } 602 603 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 604 for (i=0 ; i<3 ; i++) 605 { 606 if (b->mins[i] < mins[i]) 607 mins[i] = b->mins[i]; 608 if (b->maxs[i] > maxs[i]) 609 maxs[i] = b->maxs[i]; 610 } 611 } 612 613 614 void Select_GetTrueMid (vec3_t mid) 615 { 616 vec3_t mins, maxs; 617 Select_GetBounds (mins, maxs); 618 619 for (int i=0 ; i<3 ; i++) 620 mid[i] = (mins[i] + ((maxs[i] - mins[i]) / 2)); 621 } 622 623 624 void Select_GetMid (vec3_t mid) 625 { 626 vec3_t mins, maxs; 627 int i; 628 629 if (g_PrefsDlg.m_bNoClamp) 630 { 631 Select_GetTrueMid(mid); 632 return; 633 } 634 635 Select_GetBounds (mins, maxs); 636 637 for (i=0 ; i<3 ; i++) 638 mid[i] = g_qeglobals.d_gridsize*floor ( ( (mins[i] + maxs[i])*0.5 )/g_qeglobals.d_gridsize ); 639 640 } 641 642 vec3_t select_origin; 643 vec3_t select_matrix[3]; 644 qboolean select_fliporder; 645 646 void Select_ApplyMatrix (bool bSnap, bool bRotation, int nAxis, float fDeg) 647 { 648 brush_t *b; 649 face_t *f; 650 int i, j; 651 vec3_t temp; 652 653 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 654 { 655 for (f=b->brush_faces ; f ; f=f->next) 656 { 657 for (i=0 ; i<3 ; i++) 658 { 659 VectorSubtract (f->planepts[i], select_origin, temp); 660 for (j=0 ; j<3 ; j++) 661 f->planepts[i][j] = DotProduct(temp, select_matrix[j]) + select_origin[j]; 662 } 663 if (select_fliporder) 664 { 665 VectorCopy (f->planepts[0], temp); 666 VectorCopy (f->planepts[2], f->planepts[0]); 667 VectorCopy (temp, f->planepts[2]); 668 } 669 } 670 671 if(b->owner->eclass->fixedsize) 672 { 673 if (bRotation && b->owner->md3Class) 674 { 675 b->owner->vRotation[nAxis] += fDeg; 676 } 677 } 678 679 Brush_Build(b, bSnap); 680 681 if (b->patchBrush) 682 { 683 //Patch_ApplyMatrix(b->nPatchID, select_origin, select_matrix); 684 Patch_ApplyMatrix(b->pPatch, select_origin, select_matrix, bSnap); 685 } 686 687 if (b->terrainBrush) 688 { 689 Terrain_ApplyMatrix(b->pTerrain, select_origin, select_matrix, bSnap); 690 } 691 692 } 693 } 694 695 void ProjectOnPlane(vec3_t& normal,float dist,vec3_t& ez, vec3_t& p) 696 { 697 if (fabs(ez[0]) == 1) 698 p[0] = (dist - normal[1] * p[1] - normal[2] * p[2]) / normal[0]; 699 else if (fabs(ez[1]) == 1) 700 p[1] = (dist - normal[0] * p[0] - normal[2] * p[2]) / normal[1]; 701 else 702 p[2] = (dist - normal[0] * p[0] - normal[1] * p[1]) / normal[2]; 703 } 704 705 void Back(vec3_t& dir, vec3_t& p) 706 { 707 if (fabs(dir[0]) == 1) 708 p[0] = 0; 709 else if (fabs(dir[1]) == 1) 710 p[1] = 0; 711 else p[2] = 0; 712 } 713 714 715 716 // using scale[0] and scale[1] 717 void ComputeScale(vec3_t& rex, vec3_t& rey, vec3_t& p, face_t* f) 718 { 719 float px = DotProduct(rex, p); 720 float py = DotProduct(rey, p); 721 px *= f->texdef.scale[0]; 722 py *= f->texdef.scale[1]; 723 vec3_t aux; 724 VectorCopy(rex, aux); 725 VectorScale(aux, px, aux); 726 VectorCopy(aux, p); 727 VectorCopy(rey, aux); 728 VectorScale(aux, py, aux); 729 VectorAdd(p, aux, p); 730 } 731 732 void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3) 733 { 734 vec3_t ex,ey,ez; // local axis base 735 736 #ifdef _DEBUG 737 if (g_qeglobals.m_bBrushPrimitMode) 738 Sys_Printf("Warning : illegal call of ComputeAbsolute in brush primitive mode\n"); 739 #endif 740 741 // compute first local axis base 742 TextureAxisFromPlane(&f->plane, ex, ey); 743 CrossProduct(ex, ey, ez); 744 745 vec3_t aux; 746 VectorCopy(ex, aux); 747 VectorScale(aux, -f->texdef.shift[0], aux); 748 VectorCopy(aux, p1); 749 VectorCopy(ey, aux); 750 VectorScale(aux, -f->texdef.shift[1], aux); 751 VectorAdd(p1, aux, p1); 752 VectorCopy(p1, p2); 753 VectorAdd(p2, ex, p2); 754 VectorCopy(p1, p3); 755 VectorAdd(p3, ey, p3); 756 VectorCopy(ez, aux); 757 VectorScale(aux, -f->texdef.rotate, aux); 758 VectorRotate(p1, aux, p1); 759 VectorRotate(p2, aux, p2); 760 VectorRotate(p3, aux, p3); 761 // computing rotated local axis base 762 vec3_t rex,rey; 763 VectorCopy(ex, rex); 764 VectorRotate(rex, aux, rex); 765 VectorCopy(ey, rey); 766 VectorRotate(rey, aux, rey); 767 768 ComputeScale(rex,rey,p1,f); 769 ComputeScale(rex,rey,p2,f); 770 ComputeScale(rex,rey,p3,f); 771 772 // project on normal plane 773 // along ez 774 // assumes plane normal is normalized 775 ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p1); 776 ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p2); 777 ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p3); 778 }; 779 780 781 void AbsoluteToLocal(plane_t normal2, face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3) 782 { 783 vec3_t ex,ey,ez; 784 785 #ifdef _DEBUG 786 if (g_qeglobals.m_bBrushPrimitMode) 787 Sys_Printf("Warning : illegal call of AbsoluteToLocal in brush primitive mode\n"); 788 #endif 789 790 // computing new local axis base 791 TextureAxisFromPlane(&normal2, ex, ey); 792 CrossProduct(ex, ey, ez); 793 794 // projecting back on (ex,ey) 795 Back(ez,p1); 796 Back(ez,p2); 797 Back(ez,p3); 798 799 vec3_t aux; 800 // rotation 801 VectorCopy(p2, aux); 802 VectorSubtract(aux, p1,aux); 803 804 float x = DotProduct(aux,ex); 805 float y = DotProduct(aux,ey); 806 f->texdef.rotate = 180 * atan2(y,x) / Q_PI; 807 808 vec3_t rex,rey; 809 // computing rotated local axis base 810 VectorCopy(ez, aux); 811 VectorScale(aux, f->texdef.rotate, aux); 812 VectorCopy(ex, rex); 813 VectorRotate(rex, aux, rex); 814 VectorCopy(ey, rey); 815 VectorRotate(rey, aux, rey); 816 817 // scale 818 VectorCopy(p2, aux); 819 VectorSubtract(aux, p1, aux); 820 f->texdef.scale[0] = DotProduct(aux, rex); 821 VectorCopy(p3, aux); 822 VectorSubtract(aux, p1, aux); 823 f->texdef.scale[1] = DotProduct(aux, rey); 824 825 // shift 826 // only using p1 827 x = DotProduct(rex,p1); 828 y = DotProduct(rey,p1); 829 x /= f->texdef.scale[0]; 830 y /= f->texdef.scale[1]; 831 832 VectorCopy(rex, p1); 833 VectorScale(p1, x, p1); 834 VectorCopy(rey, aux); 835 VectorScale(aux, y, aux); 836 VectorAdd(p1, aux, p1); 837 VectorCopy(ez, aux); 838 VectorScale(aux, -f->texdef.rotate, aux); 839 VectorRotate(p1, aux, p1); 840 f->texdef.shift[0] = -DotProduct(p1, ex); 841 f->texdef.shift[1] = -DotProduct(p1, ey); 842 843 // stored rot is good considering local axis base 844 // change it if necessary 845 f->texdef.rotate = -f->texdef.rotate; 846 847 Clamp(f->texdef.shift[0], f->d_texture->width); 848 Clamp(f->texdef.shift[1], f->d_texture->height); 849 Clamp(f->texdef.rotate, 360); 850 851 } 852 853 void RotateFaceTexture(face_t* f, int nAxis, float fDeg) 854 { 855 vec3_t p1,p2,p3, rota; 856 p1[0] = p1[1] = p1[2] = 0; 857 VectorCopy(p1, p2); 858 VectorCopy(p1, p3); 859 VectorCopy(p1, rota); 860 ComputeAbsolute(f, p1, p2, p3); 861 862 rota[nAxis] = fDeg; 863 VectorRotate(p1, rota, select_origin, p1); 864 VectorRotate(p2, rota, select_origin, p2); 865 VectorRotate(p3, rota, select_origin, p3); 866 867 plane_t normal2; 868 vec3_t vNormal; 869 vNormal[0] = f->plane.normal[0]; 870 vNormal[1] = f->plane.normal[1]; 871 vNormal[2] = f->plane.normal[2]; 872 VectorRotate(vNormal, rota, vNormal); 873 normal2.normal[0] = vNormal[0]; 874 normal2.normal[1] = vNormal[1]; 875 normal2.normal[2] = vNormal[2]; 876 AbsoluteToLocal(normal2, f, p1, p2 ,p3); 877 878 } 879 880 void RotateTextures(int nAxis, float fDeg, vec3_t vOrigin) 881 { 882 for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 883 { 884 for (face_t* f=b->brush_faces ; f ; f=f->next) 885 { 886 if (g_qeglobals.m_bBrushPrimitMode) 887 RotateFaceTexture_BrushPrimit( f, nAxis, fDeg, vOrigin ); 888 else 889 RotateFaceTexture(f, nAxis, fDeg); 890 //++timo removed that call .. works fine .. ??????? 891 // Brush_Build(b, false); 892 } 893 Brush_Build(b, false); 894 } 895 } 896 897 898 void Select_FlipAxis (int axis) 899 { 900 int i; 901 902 Select_GetMid (select_origin); 903 for (i=0 ; i<3 ; i++) 904 { 905 VectorCopy (vec3_origin, select_matrix[i]); 906 select_matrix[i][i] = 1; 907 } 908 select_matrix[axis][axis] = -1; 909 910 select_fliporder = true; 911 Select_ApplyMatrix (true, false, 0, 0); 912 Sys_UpdateWindows (W_ALL); 913 } 914 915 916 void Select_Scale(float x, float y, float z) 917 { 918 Select_GetMid (select_origin); 919 for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 920 { 921 for (face_t* f=b->brush_faces ; f ; f=f->next) 922 { 923 for (int i=0 ; i<3 ; i++) 924 { 925 f->planepts[i][0] -= select_origin[0]; 926 f->planepts[i][1] -= select_origin[1]; 927 f->planepts[i][2] -= select_origin[2]; 928 f->planepts[i][0] *= x; 929 //f->planepts[i][0] = floor(f->planepts[i][0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 930 931 f->planepts[i][1] *= y; 932 //f->planepts[i][1] = floor(f->planepts[i][1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 933 934 f->planepts[i][2] *= z; 935 //f->planepts[i][2] = floor(f->planepts[i][2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 936 937 f->planepts[i][0] += select_origin[0]; 938 f->planepts[i][1] += select_origin[1]; 939 f->planepts[i][2] += select_origin[2]; 940 } 941 } 942 Brush_Build(b, false); 943 if (b->patchBrush) 944 { 945 vec3_t v; 946 v[0] = x; 947 v[1] = y; 948 v[2] = z; 949 //Patch_Scale(b->nPatchID, select_origin, v); 950 Patch_Scale(b->pPatch, select_origin, v); 951 } 952 if (b->terrainBrush) 953 { 954 vec3_t v; 955 v[0] = x; 956 v[1] = y; 957 v[2] = z; 958 Terrain_Scale(b->pTerrain, select_origin, v); 959 } 960 } 961 } 962 963 void Select_RotateAxis (int axis, float deg, bool bPaint, bool bMouse) 964 { 965 vec3_t temp; 966 int i, j; 967 vec_t c, s; 968 969 if (deg == 0) 970 { 971 //Sys_Printf("0 deg\n"); 972 return; 973 } 974 975 if (bMouse) 976 { 977 VectorCopy(g_pParentWnd->ActiveXY()->RotateOrigin(), select_origin); 978 } 979 else 980 { 981 Select_GetMid (select_origin); 982 } 983 984 select_fliporder = false; 985 986 if (deg == 90) 987 { 988 for (i=0 ; i<3 ; i++) 989 { 990 VectorCopy (vec3_origin, select_matrix[i]); 991 select_matrix[i][i] = 1; 992 } 993 i = (axis+1)%3; 994 j = (axis+2)%3; 995 VectorCopy (select_matrix[i], temp); 996 VectorCopy (select_matrix[j], select_matrix[i]); 997 VectorSubtract (vec3_origin, temp, select_matrix[j]); 998 } 999 else 1000 { 1001 deg = -deg; 1002 if (deg == -180.0) 1003 { 1004 c = -1; 1005 s = 0; 1006 } 1007 else if (deg == -270.0) 1008 { 1009 c = 0; 1010 s = -1; 1011 } 1012 else 1013 { 1014 c = cos(deg * Q_PI / 180.0); 1015 s = sin(deg * Q_PI / 180.0); 1016 } 1017 1018 for (i=0 ; i<3 ; i++) 1019 { 1020 VectorCopy (vec3_origin, select_matrix[i]); 1021 select_matrix[i][i] = 1; 1022 } 1023 1024 switch (axis) 1025 { 1026 case 0: 1027 select_matrix[1][1] = c; 1028 select_matrix[1][2] = -s; 1029 select_matrix[2][1] = s; 1030 select_matrix[2][2] = c; 1031 break; 1032 case 1: 1033 select_matrix[0][0] = c; 1034 select_matrix[0][2] = s; 1035 select_matrix[2][0] = -s; 1036 select_matrix[2][2] = c; 1037 break; 1038 case 2: 1039 select_matrix[0][0] = c; 1040 select_matrix[0][1] = -s; 1041 select_matrix[1][0] = s; 1042 select_matrix[1][1] = c; 1043 break; 1044 } 1045 } 1046 1047 if (g_PrefsDlg.m_bRotateLock) 1048 RotateTextures(axis, deg, select_origin); 1049 Select_ApplyMatrix(!bMouse, true, axis, deg); 1050 1051 if (bPaint) 1052 Sys_UpdateWindows (W_ALL); 1053 } 1054 1055 /* 1056 ================================================================ 1057 1058 GROUP SELECTIONS 1059 1060 ================================================================ 1061 */ 1062 1063 void Select_CompleteTall (void) 1064 { 1065 brush_t *b, *next; 1066 //int i; 1067 vec3_t mins, maxs; 1068 1069 if (!QE_SingleBrush ()) 1070 return; 1071 1072 clearSelection(); 1073 1074 VectorCopy (selected_brushes.next->mins, mins); 1075 VectorCopy (selected_brushes.next->maxs, maxs); 1076 Select_Delete (); 1077 1078 int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0; 1079 int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2; 1080 1081 for (b=active_brushes.next ; b != &active_brushes ; b=next) 1082 { 1083 next = b->next; 1084 1085 if ( (b->maxs[nDim1] > maxs[nDim1] || b->mins[nDim1] < mins[nDim1]) 1086 || (b->maxs[nDim2] > maxs[nDim2] || b->mins[nDim2] < mins[nDim2]) ) 1087 continue; 1088 1089 if (FilterBrush (b)) 1090 continue; 1091 1092 Brush_RemoveFromList (b); 1093 Brush_AddToList (b, &selected_brushes); 1094 #if 0 1095 // old stuff 1096 for (i=0 ; i<2 ; i++) 1097 if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i]) 1098 break; 1099 if (i == 2) 1100 { 1101 Brush_RemoveFromList (b); 1102 Brush_AddToList (b, &selected_brushes); 1103 } 1104 #endif 1105 } 1106 Sys_UpdateWindows (W_ALL); 1107 } 1108 1109 void Select_PartialTall (void) 1110 { 1111 brush_t *b, *next; 1112 //int i; 1113 vec3_t mins, maxs; 1114 1115 if (!QE_SingleBrush ()) 1116 return; 1117 1118 clearSelection(); 1119 1120 VectorCopy (selected_brushes.next->mins, mins); 1121 VectorCopy (selected_brushes.next->maxs, maxs); 1122 Select_Delete (); 1123 1124 int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0; 1125 int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2; 1126 1127 for (b=active_brushes.next ; b != &active_brushes ; b=next) 1128 { 1129 next = b->next; 1130 1131 if ( (b->mins[nDim1] > maxs[nDim1] || b->maxs[nDim1] < mins[nDim1]) 1132 || (b->mins[nDim2] > maxs[nDim2] || b->maxs[nDim2] < mins[nDim2]) ) 1133 continue; 1134 1135 if (FilterBrush (b)) 1136 continue; 1137 1138 Brush_RemoveFromList (b); 1139 Brush_AddToList (b, &selected_brushes); 1140 1141 1142 #if 0 1143 // old stuff 1144 for (i=0 ; i<2 ; i++) 1145 if (b->mins[i] > maxs[i] || b->maxs[i] < mins[i]) 1146 break; 1147 if (i == 2) 1148 { 1149 Brush_RemoveFromList (b); 1150 Brush_AddToList (b, &selected_brushes); 1151 } 1152 #endif 1153 } 1154 Sys_UpdateWindows (W_ALL); 1155 } 1156 1157 void Select_Touching (void) 1158 { 1159 brush_t *b, *next; 1160 int i; 1161 vec3_t mins, maxs; 1162 1163 if (!QE_SingleBrush ()) 1164 return; 1165 1166 clearSelection(); 1167 1168 VectorCopy (selected_brushes.next->mins, mins); 1169 VectorCopy (selected_brushes.next->maxs, maxs); 1170 1171 for (b=active_brushes.next ; b != &active_brushes ; b=next) 1172 { 1173 next = b->next; 1174 1175 if (FilterBrush (b)) 1176 continue; 1177 1178 for (i=0 ; i<3 ; i++) 1179 if (b->mins[i] > maxs[i]+1 || b->maxs[i] < mins[i]-1) 1180 break; 1181 1182 if (i == 3) 1183 { 1184 Brush_RemoveFromList (b); 1185 Brush_AddToList (b, &selected_brushes); 1186 } 1187 } 1188 Sys_UpdateWindows (W_ALL); 1189 } 1190 1191 void Select_Inside (void) 1192 { 1193 brush_t *b, *next; 1194 int i; 1195 vec3_t mins, maxs; 1196 1197 if (!QE_SingleBrush ()) 1198 return; 1199 1200 clearSelection(); 1201 1202 VectorCopy (selected_brushes.next->mins, mins); 1203 VectorCopy (selected_brushes.next->maxs, maxs); 1204 Select_Delete (); 1205 1206 for (b=active_brushes.next ; b != &active_brushes ; b=next) 1207 { 1208 next = b->next; 1209 1210 if (FilterBrush (b)) 1211 continue; 1212 1213 for (i=0 ; i<3 ; i++) 1214 if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i]) 1215 break; 1216 if (i == 3) 1217 { 1218 Brush_RemoveFromList (b); 1219 Brush_AddToList (b, &selected_brushes); 1220 } 1221 } 1222 Sys_UpdateWindows (W_ALL); 1223 } 1224 1225 /* 1226 ============= 1227 Select_Ungroup 1228 1229 Turn the currently selected entity back into normal brushes 1230 ============= 1231 */ 1232 void Select_Ungroup(void) 1233 { 1234 int numselectedgroups; 1235 entity_t *e; 1236 brush_t *b, *sb; 1237 1238 numselectedgroups = 0; 1239 for (sb = selected_brushes.next; sb != &selected_brushes; sb = sb->next) 1240 { 1241 e = sb->owner; 1242 1243 if (!e || e == world_entity || e->eclass->fixedsize) 1244 { 1245 continue; 1246 } 1247 1248 for (b = e->brushes.onext; b != &e->brushes; b = e->brushes.onext) 1249 { 1250 //Brush_RemoveFromList (b); 1251 //Brush_AddToList (b, &active_brushes); 1252 Entity_UnlinkBrush (b); 1253 Entity_LinkBrush (world_entity, b); 1254 Brush_Build( b ); 1255 b->owner = world_entity; 1256 } 1257 Entity_Free (e); 1258 numselectedgroups++; 1259 } 1260 1261 if (numselectedgroups <= 0) 1262 { 1263 Sys_Printf("No grouped entities selected.\n"); 1264 return; 1265 } 1266 Sys_Printf("Ungrouped %d entit%s.\n", numselectedgroups, (numselectedgroups == 1)?"y":"ies"); 1267 Sys_UpdateWindows (W_ALL); 1268 } 1269 1270 1271 /* 1272 ==================== 1273 Select_MakeStructural 1274 ==================== 1275 */ 1276 void Select_MakeStructural (void) 1277 { 1278 brush_t *b; 1279 face_t *f; 1280 1281 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 1282 for (f=b->brush_faces ; f ; f=f->next) 1283 f->texdef.contents &= ~CONTENTS_DETAIL; 1284 Select_Deselect (); 1285 Sys_UpdateWindows (W_ALL); 1286 } 1287 1288 void Select_MakeDetail (void) 1289 { 1290 brush_t *b; 1291 face_t *f; 1292 1293 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 1294 for (f=b->brush_faces ; f ; f=f->next) 1295 f->texdef.contents |= CONTENTS_DETAIL; 1296 Select_Deselect (); 1297 Sys_UpdateWindows (W_ALL); 1298 } 1299 1300 void Select_ShiftTexture(int x, int y) 1301 { 1302 brush_t *b; 1303 face_t *f; 1304 1305 int nFaceCount = g_ptrSelectedFaces.GetSize(); 1306 1307 if(selected_brushes.next == &selected_brushes && nFaceCount == 0) 1308 return; 1309 1310 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 1311 { 1312 for (f=b->brush_faces ; f ; f=f->next) 1313 { 1314 if (g_qeglobals.m_bBrushPrimitMode) 1315 { 1316 // use face normal to compute a true translation 1317 Select_ShiftTexture_BrushPrimit( f, x, y ); 1318 } 1319 else 1320 { 1321 f->texdef.shift[0] += x; 1322 f->texdef.shift[1] += y; 1323 } 1324 } 1325 Brush_Build(b); 1326 if (b->patchBrush) 1327 { 1328 //Patch_ShiftTexture(b->nPatchID, x, y); 1329 Patch_ShiftTexture(b->pPatch, x, y); 1330 } 1331 } 1332 1333 if (nFaceCount > 0) 1334 { 1335 for (int i = 0; i < nFaceCount; i++) 1336 { 1337 face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i)); 1338 brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i)); 1339 if (g_qeglobals.m_bBrushPrimitMode) 1340 { 1341 1342 // use face normal to compute a true translation 1343 // Select_ShiftTexture_BrushPrimit( selected_face, x, y ); 1344 // use camera view to compute texture shift 1345 g_pParentWnd->GetCamera()->ShiftTexture_BrushPrimit( selFace, x, y ); 1346 } 1347 else 1348 { 1349 selFace->texdef.shift[0] += x; 1350 selFace->texdef.shift[1] += y; 1351 } 1352 Brush_Build(selBrush); 1353 } 1354 } 1355 1356 Sys_UpdateWindows (W_CAMERA); 1357 } 1358 1359 void Select_ScaleTexture(int x, int y) 1360 { 1361 brush_t *b; 1362 face_t *f; 1363 1364 int nFaceCount = g_ptrSelectedFaces.GetSize(); 1365 1366 if(selected_brushes.next == &selected_brushes && nFaceCount == 0) 1367 { 1368 return; 1369 } 1370 1371 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 1372 { 1373 for (f=b->brush_faces ; f ; f=f->next) 1374 { 1375 if (g_qeglobals.m_bBrushPrimitMode) 1376 { 1377 // apply same scale as the spinner button of the surface inspector 1378 float shift[2]; 1379 float rotate; 1380 float scale[2]; 1381 brushprimit_texdef_t bp; 1382 // compute normalized texture matrix 1383 ConvertTexMatWithQTexture( &f->brushprimit_texdef, f->d_texture, &bp, NULL ); 1384 // compute fake shift scale rot 1385 TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale ); 1386 // update 1387 scale[0]+=static_cast<float>(x)*0.1; 1388 scale[1]+=static_cast<float>(y)*0.1; 1389 // compute new normalized texture matrix 1390 FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords ); 1391 // apply to face texture matrix 1392 ConvertTexMatWithQTexture( &bp, NULL, &f->brushprimit_texdef, f->d_texture ); 1393 } 1394 else 1395 { 1396 f->texdef.scale[0] += x; 1397 f->texdef.scale[1] += y; 1398 } 1399 } 1400 Brush_Build(b); 1401 if (b->patchBrush) 1402 { 1403 Patch_ScaleTexture(b->pPatch, x, y); 1404 } 1405 } 1406 1407 if (nFaceCount > 0) 1408 { 1409 for (int i = 0; i < nFaceCount; i++) 1410 { 1411 face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i)); 1412 brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i)); 1413 if (g_qeglobals.m_bBrushPrimitMode) 1414 { 1415 float shift[2]; 1416 float rotate; 1417 float scale[2]; 1418 brushprimit_texdef_t bp; 1419 ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &bp, NULL ); 1420 TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale ); 1421 scale[0]+=static_cast<float>(x)*0.1; 1422 scale[1]+=static_cast<float>(y)*0.1; 1423 FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords ); 1424 ConvertTexMatWithQTexture( &bp, NULL, &selFace->brushprimit_texdef, selFace->d_texture ); 1425 } 1426 else 1427 { 1428 selFace->texdef.scale[0] += x; 1429 selFace->texdef.scale[1] += y; 1430 } 1431 Brush_Build(selBrush); 1432 } 1433 } 1434 1435 Sys_UpdateWindows (W_CAMERA); 1436 } 1437 1438 void Select_RotateTexture(int amt) 1439 { 1440 brush_t *b; 1441 face_t *f; 1442 1443 int nFaceCount = g_ptrSelectedFaces.GetSize(); 1444 1445 if(selected_brushes.next == &selected_brushes && nFaceCount == 0) 1446 { 1447 return; 1448 } 1449 1450 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 1451 { 1452 for (f=b->brush_faces ; f ; f=f->next) 1453 { 1454 if (g_qeglobals.m_bBrushPrimitMode) 1455 { 1456 // apply same scale as the spinner button of the surface inspector 1457 float shift[2]; 1458 float rotate; 1459 float scale[2]; 1460 brushprimit_texdef_t bp; 1461 // compute normalized texture matrix 1462 ConvertTexMatWithQTexture( &f->brushprimit_texdef, f->d_texture, &bp, NULL ); 1463 // compute fake shift scale rot 1464 TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale ); 1465 // update 1466 rotate += amt; 1467 // compute new normalized texture matrix 1468 FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords ); 1469 // apply to face texture matrix 1470 ConvertTexMatWithQTexture( &bp, NULL, &f->brushprimit_texdef, f->d_texture ); 1471 } 1472 else 1473 { 1474 f->texdef.rotate += amt; 1475 f->texdef.rotate = static_cast<int>(f->texdef.rotate) % 360; 1476 } 1477 } 1478 Brush_Build(b); 1479 if (b->patchBrush) 1480 { 1481 //Patch_RotateTexture(b->nPatchID, amt); 1482 Patch_RotateTexture(b->pPatch, amt); 1483 } 1484 } 1485 1486 if (nFaceCount > 0) 1487 { 1488 for (int i = 0; i < nFaceCount; i++) 1489 { 1490 face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i)); 1491 brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i)); 1492 if (g_qeglobals.m_bBrushPrimitMode) 1493 { 1494 float shift[2]; 1495 float rotate; 1496 float scale[2]; 1497 brushprimit_texdef_t bp; 1498 ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &bp, NULL ); 1499 TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale ); 1500 rotate += amt; 1501 FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords ); 1502 ConvertTexMatWithQTexture( &bp, NULL, &selFace->brushprimit_texdef, selFace->d_texture ); 1503 } 1504 else 1505 { 1506 selFace->texdef.rotate += amt; 1507 selFace->texdef.rotate = static_cast<int>(selFace->texdef.rotate) % 360; 1508 } 1509 Brush_Build(selBrush); 1510 } 1511 } 1512 1513 Sys_UpdateWindows (W_CAMERA); 1514 } 1515 1516 1517 void FindReplaceTextures(const char* pFind, const char* pReplace, bool bSelected, bool bForce) 1518 { 1519 brush_t* pList = (bSelected) ? &selected_brushes : &active_brushes; 1520 if (!bSelected) 1521 { 1522 Select_Deselect(); 1523 } 1524 1525 for (brush_t* pBrush = pList->next ; pBrush != pList; pBrush = pBrush->next) 1526 { 1527 if (pBrush->patchBrush) 1528 { 1529 Patch_FindReplaceTexture(pBrush, pFind, pReplace, bForce); 1530 } 1531 1532 if (pBrush->terrainBrush) 1533 { 1534 Terrain_FindReplaceTexture(pBrush->pTerrain, pFind, pReplace, bForce); 1535 } 1536 for (face_t* pFace = pBrush->brush_faces; pFace; pFace = pFace->next) 1537 { 1538 if(bForce || strcmpi(pFace->texdef.name, pFind) == 0) 1539 { 1540 pFace->d_texture = Texture_ForName(pReplace); 1541 //strcpy(pFace->texdef.name, pReplace); 1542 pFace->texdef.SetName(pReplace); 1543 } 1544 } 1545 Brush_Build(pBrush); 1546 } 1547 Sys_UpdateWindows (W_CAMERA); 1548 } 1549 1550 1551 void Select_AllOfType() 1552 { 1553 brush_t *b, *next; 1554 entity_t *e; 1555 if ( (selected_brushes.next == &selected_brushes) 1556 || (selected_brushes.next->next != &selected_brushes) ) 1557 { 1558 1559 CString strName; 1560 if (g_ptrSelectedFaces.GetSize() == 0) 1561 { 1562 strName = g_qeglobals.d_texturewin.texdef.name; 1563 } 1564 else 1565 { 1566 face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0)); 1567 strName = selFace->texdef.name; 1568 } 1569 1570 Select_Deselect(); 1571 for (b=active_brushes.next ; b != &active_brushes ; b=next) 1572 { 1573 next = b->next; 1574 1575 if (FilterBrush (b)) 1576 continue; 1577 1578 if (b->patchBrush) 1579 { 1580 if (strcmpi(strName, b->pPatch->d_texture->name) == 0) 1581 { 1582 Brush_RemoveFromList (b); 1583 Brush_AddToList (b, &selected_brushes); 1584 } 1585 } 1586 else 1587 { 1588 for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next) 1589 { 1590 if (strcmpi(strName, pFace->texdef.name) == 0) 1591 { 1592 Brush_RemoveFromList (b); 1593 Brush_AddToList (b, &selected_brushes); 1594 } 1595 } 1596 } 1597 } 1598 Sys_UpdateWindows(W_ALL); 1599 return; 1600 } 1601 1602 1603 b = selected_brushes.next; 1604 e = b->owner; 1605 1606 if (e != NULL) 1607 { 1608 if (e != world_entity) 1609 { 1610 CString strName = e->eclass->name; 1611 CString strKey, strVal; 1612 bool bCriteria = GetSelectAllCriteria(strKey, strVal); 1613 Sys_Printf("Selecting all %s(s)\n", strName); 1614 Select_Deselect(); 1615 1616 for (b=active_brushes.next ; b != &active_brushes ; b=next) 1617 { 1618 next = b->next; 1619 1620 if (FilterBrush (b)) 1621 continue; 1622 1623 e = b->owner; 1624 if (e != NULL) 1625 { 1626 if (strcmpi(e->eclass->name, strName) == 0) 1627 { 1628 bool doIt = true; 1629 if (bCriteria) { 1630 CString str = ValueForKey (e, strKey); 1631 if (str.CompareNoCase(strVal) != 0) { 1632 doIt = false; 1633 } 1634 } 1635 if (doIt) { 1636 Brush_RemoveFromList (b); 1637 Brush_AddToList (b, &selected_brushes); 1638 } 1639 } 1640 } 1641 } 1642 } 1643 } 1644 Sys_UpdateWindows (W_ALL); 1645 1646 } 1647 1648 void Select_Reselect() 1649 { 1650 CPtrArray holdArray; 1651 for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) 1652 { 1653 holdArray.Add(reinterpret_cast<void*>(b)); 1654 } 1655 1656 int n = holdArray.GetSize(); 1657 while (n-- > 0) 1658 { 1659 b = reinterpret_cast<brush_t*>(holdArray.GetAt(n)); 1660 Select_Brush(b); 1661 } 1662 Sys_UpdateWindows (W_ALL); 1663 } 1664 1665 1666 void Select_FitTexture(int nHeight, int nWidth) 1667 { 1668 brush_t *b; 1669 1670 int nFaceCount = g_ptrSelectedFaces.GetSize(); 1671 1672 if(selected_brushes.next == &selected_brushes && nFaceCount == 0) 1673 return; 1674 1675 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 1676 { 1677 Brush_FitTexture(b, nHeight, nWidth); 1678 Brush_Build(b); 1679 } 1680 1681 if (nFaceCount > 0) 1682 { 1683 for (int i = 0; i < nFaceCount; i++) 1684 { 1685 face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i)); 1686 brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i)); 1687 Face_FitTexture(selFace, nHeight, nWidth); 1688 Brush_Build(selBrush); 1689 } 1690 } 1691 1692 Sys_UpdateWindows (W_CAMERA); 1693 } 1694 1695 void Select_AxialTexture() 1696 { 1697 1698 } 1699 1700 void Select_Hide() 1701 { 1702 for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) 1703 { 1704 b->hiddenBrush = true; 1705 } 1706 Sys_UpdateWindows (W_ALL); 1707 } 1708 1709 void Select_ShowAllHidden() 1710 { 1711 brush_t* b; 1712 for (b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) 1713 { 1714 b->hiddenBrush = false; 1715 } 1716 for (b=active_brushes.next ; b && b != &active_brushes ; b=b->next) 1717 { 1718 b->hiddenBrush = false; 1719 } 1720 Sys_UpdateWindows (W_ALL); 1721 } 1722 1723 1724 /* 1725 ============ 1726 Select_Invert 1727 ============ 1728 */ 1729 void Select_Invert(void) 1730 { 1731 brush_t *next, *prev; 1732 1733 Sys_Printf("inverting selection...\n"); 1734 1735 next = active_brushes.next; 1736 prev = active_brushes.prev; 1737 if (selected_brushes.next != &selected_brushes) 1738 { 1739 active_brushes.next = selected_brushes.next; 1740 active_brushes.prev = selected_brushes.prev; 1741 active_brushes.next->prev = &active_brushes; 1742 active_brushes.prev->next = &active_brushes; 1743 } 1744 else 1745 { 1746 active_brushes.next = &active_brushes; 1747 active_brushes.prev = &active_brushes; 1748 } 1749 if (next != &active_brushes) 1750 { 1751 selected_brushes.next = next; 1752 selected_brushes.prev = prev; 1753 selected_brushes.next->prev = &selected_brushes; 1754 selected_brushes.prev->next = &selected_brushes; 1755 } 1756 else 1757 { 1758 selected_brushes.next = &selected_brushes; 1759 selected_brushes.prev = &selected_brushes; 1760 } 1761 1762 Sys_UpdateWindows(W_ALL); 1763 1764 Sys_Printf("done.\n"); 1765 } 1766 1767 1768 /* 1769 =========== 1770 Select_Name 1771 =========== 1772 */ 1773 void Select_Name(const char *pName) 1774 { 1775 if (g_qeglobals.m_bBrushPrimitMode) 1776 { 1777 for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) 1778 { 1779 Brush_SetEpair(b, "Name", pName); 1780 } 1781 } 1782 } 1783 1784 /* 1785 ================= 1786 Select_AddToGroup 1787 add selected brushes to a group, update the tree 1788 ================= 1789 */ 1790 void Select_AddToGroup(const char *pName) 1791 { 1792 if (g_qeglobals.m_bBrushPrimitMode) 1793 { 1794 for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) 1795 { 1796 Brush_SetEpair(b, "group", pName); 1797 Group_AddToProperGroup(b); 1798 } 1799 } 1800 }