2 BobToolz plugin for GtkRadiant
3 Copyright (C) 2001 Gordon Biggans
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "funchandlers.h"
21 #include "globaldefs.h"
23 #if GDEF_COMPILER_MSVC
24 #pragma warning(disable : 4786)
27 #include "dialogs/dialogs-gtk.h"
40 #include "DVisDrawer.h"
41 #include "DTrainDrawer.h"
44 #include "ScriptParser.h"
45 #include "DTreePlanter.h"
61 std::list<Str> exclusionList; // whole brush exclusion
62 std::list<Str> exclusionList_Face; // single face exclusion
64 bool el1Loaded = false;
65 bool el2Loaded = false;
66 bool clrLst1Loaded = false;
67 bool clrLst2Loaded = false;
69 DBobView* g_PathView = NULL;
70 DVisDrawer* g_VisView = NULL;
71 DTrainDrawer* g_TrainView = NULL;
72 DTreePlanter* g_TreePlanter = NULL;
75 //========================//
76 // Helper Functions //
77 //========================//
83 el1Loaded = LoadExclusionList( GetFilename( buffer, "bt/bt-el1.txt" ), &exclusionList );
86 el2Loaded = LoadExclusionList( GetFilename( buffer, "bt/bt-el2.txt" ), &exclusionList_Face );
91 //========================//
93 //========================//
96 UndoableCommand undo( "bobToolz.intersect" );
99 if ( DoIntersectBox( &rs ) == eIDCANCEL ) {
103 if ( rs.nBrushOptions == BRUSH_OPT_SELECTED ) {
104 if ( GlobalSelectionSystem().countSelected() < 2 ) {
105 //DoMessageBox("Invalid number of brushes selected, choose at least 2", "Error", eMB_OK);
106 globalErrorStream() << "bobToolz Intersect: Invalid number of brushes selected, choose at least 2.\n";
112 switch ( rs.nBrushOptions )
114 case BRUSH_OPT_SELECTED:
117 world.LoadFromEntity( GlobalRadiant().getMapWorldEntity(), false );
118 world.LoadSelectedBrushes();
121 case BRUSH_OPT_WHOLE_MAP:
123 world.LoadFromEntity( GlobalRadiant().getMapWorldEntity(), false );
127 world.RemoveNonCheckBrushes( &exclusionList, rs.bUseDetail );
130 if ( rs.bDuplicateOnly ) {
131 pbSelectList = world.BuildDuplicateList();
134 pbSelectList = world.BuildIntersectList();
137 world.SelectBrushes( pbSelectList );
138 int brushCount = GlobalSelectionSystem().countSelected();
139 globalOutputStream() << "bobToolz Intersect: " << brushCount << " intersecting brushes found.\n";
140 delete[] pbSelectList;
148 UndoableCommand undo( "bobToolz.polygons" );
149 // ensure we have something selected
150 if ( GlobalSelectionSystem().countSelected() != 1 ) {
151 //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
152 globalErrorStream() << "bobToolz Polygons: Invalid number of brushes selected, choose 1 only.\n";
157 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
158 if ( !Node_isBrush( instance.path().top() ) ) {
159 //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
160 globalErrorStream() << "bobToolz Polygons: No brush selected, select ONLY one brush.\n";
163 // ask user for type, size, etc....
164 if ( DoPolygonBox( &rs ) == eIDOK ) {
171 VectorSubtract( instance.worldAABB().origin, instance.worldAABB().extents, vMin );
172 VectorAdd( instance.worldAABB().origin, instance.worldAABB().extents, vMax );
174 Path_deleteTop( instance.path() );
178 poly.BuildInversePrism( vMin, vMax, rs.nSides, rs.bAlignTop );
182 if ( rs.bUseBorder ) {
183 poly.BuildBorderedPrism( vMin, vMax, rs.nSides, rs.nBorderWidth, rs.bAlignTop );
186 poly.BuildRegularPrism( vMin, vMax, rs.nSides, rs.bAlignTop );
196 UndoableCommand undo( "bobToolz.fixBrushes" );
200 int count = world.FixBrushes();
202 globalOutputStream() << "bobToolz FixBrushes: " << count << " invalid/duplicate planes removed.\n";
205 void DoResetTextures(){
206 UndoableCommand undo( "bobToolz.resetTextures" );
207 static ResetTextureRS rs;
210 if ( 1 /*g_SelectedFaceTable.m_pfnGetSelectedFaceCount() != 1*/ ) {
215 texName = GetCurrentTexture();
216 strcpy( rs.textureName, GetCurrentTexture() );
219 EMessageBoxReturn ret;
220 if ( ( ret = DoResetTextureBox( &rs ) ) == eIDCANCEL ) {
224 if ( rs.bResetTextureName ) {
225 texName = rs.textureName;
228 if ( ret == eIDOK ) {
230 world.LoadSelectedBrushes();
231 world.ResetTextures( texName, rs.fScale, rs.fShift, rs.rotation, rs.newTextureName,
232 rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation, true );
237 world.LoadAll( true );
238 world.ResetTextures( texName, rs.fScale, rs.fShift, rs.rotation, rs.newTextureName,
239 rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation );
243 void DoBuildStairs(){
244 UndoableCommand undo( "bobToolz.buildStairs" );
247 strcpy( rs.mainTexture, GetCurrentTexture() );
249 // ensure we have something selected
250 if ( GlobalSelectionSystem().countSelected() != 1 ) {
251 //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
252 globalErrorStream() << "bobToolz BuildStairs: Invalid number of brushes selected, choose 1 only.\n";
256 // ask user for type, size, etc....
257 if ( DoBuildStairsBox( &rs ) == eIDOK ) {
261 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
262 VectorSubtract( instance.worldAABB().origin, instance.worldAABB().extents, vMin );
263 VectorAdd( instance.worldAABB().origin, instance.worldAABB().extents, vMax );
268 VectorSubtract( vMax, vMin, size );
270 if ( ( (int)size[2] % rs.stairHeight ) != 0 ) {
271 // stairs must fit evenly into brush
272 //DoMessageBox("Invalid stair height\nHeight of block must be divisable by stair height", "Error", eMB_OK);
273 globalErrorStream() << "bobToolz BuildStairs: Invalid stair height. Height of block must be divisable by stair height.\n";
278 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
279 Path_deleteTop( instance.path() );
283 int numSteps = (int)size[2] / rs.stairHeight;
285 if ( rs.style == STYLE_CORNER ) {
286 BuildCornerStairs( vMin, vMax, numSteps, rs.mainTexture, rs.riserTexture );
291 // Get Step Dimensions
292 float stairHeight = (float)rs.stairHeight;
294 if ( ( rs.direction == MOVE_EAST ) || ( rs.direction == MOVE_WEST ) ) {
295 stairWidth = ( size[0] ) / numSteps;
298 stairWidth = ( size[1] ) / numSteps;
302 // Build Base For Stair (bob's style)
303 if ( rs.style == STYLE_BOB ) {
304 Build_Wedge( rs.direction, vMin, vMax, true );
308 // Set First Step Starting Position
309 vMax[2] = vMin[2] + stairHeight;
310 SetInitialStairPos( rs.direction, vMin, vMax, stairWidth );
314 for ( int i = 0; i < numSteps; i++ )
316 if ( rs.style == STYLE_BOB ) {
317 Build_StairStep_Wedge( rs.direction, vMin, vMax, rs.mainTexture, rs.riserTexture, rs.bUseDetail );
319 else if ( rs.style == STYLE_ORIGINAL ) {
320 Build_StairStep( vMin, vMax, rs.mainTexture, rs.riserTexture, rs.direction );
323 // get step into next position
324 MoveBlock( rs.direction, vMin, vMax, stairWidth );
325 vMax[2] += stairHeight;
326 if ( rs.style == STYLE_BOB ) {
327 vMin[2] += stairHeight; // wedge bottom must be raised
336 UndoableCommand undo( "bobToolz.buildDoors" );
337 // ensure we have something selected
338 if ( GlobalSelectionSystem().countSelected() != 1 ) {
339 //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
340 globalErrorStream() << "bobToolz BuildDoors: Invalid number of brushes selected, choose 1 only.\n";
345 strcpy( rs.mainTexture, GetCurrentTexture() );
347 if ( DoDoorsBox( &rs ) == eIDOK ) {
351 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
352 VectorSubtract( instance.worldAABB().origin, instance.worldAABB().extents, vMin );
353 VectorAdd( instance.worldAABB().origin, instance.worldAABB().extents, vMax );
354 Path_deleteTop( instance.path() );
357 BuildDoorsX2( vMin, vMax,
358 rs.bScaleMainH, rs.bScaleMainV,
359 rs.bScaleTrimH, rs.bScaleTrimV,
360 rs.mainTexture, rs.trimTexture,
361 rs.nOrientation ); // shapes.cpp
365 void DoPathPlotter(){
366 UndoableCommand undo( "bobToolz.pathPlotter" );
368 EMessageBoxReturn ret = DoPathPlotterBox( &rs );
369 if ( ret == eIDCANCEL ) {
372 if ( ret == eIDNO ) {
379 // ensure we have something selected
381 if( GlobalSelectionSystem().countSelected() != 1 )
383 //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
384 globalOutputStream() << "bobToolz PathPlotter: Invalid number of entities selected, choose 1 trigger_push entity only.\n";
388 Entity* entity = Node_getEntity( GlobalSelectionSystem().ultimateSelected().path().top() );
390 DBobView_setEntity( *entity, rs.fMultiplier, rs.nPoints, rs.fGravity, rs.bNoUpdate, rs.bShowExtra );
392 else{ globalErrorStream() << "bobToolz PathPlotter: No trigger_push entitity selected, select 1 only (Use list to select it).\n"; }
397 UndoableCommand undo( "bobToolz.pitBuilder" );
398 // ensure we have something selected
399 if ( GlobalSelectionSystem().countSelected() != 1 ) {
400 //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
401 globalErrorStream() << "bobToolz PitBuilder: Invalid number of brushes selected, choose 1 only.\n";
407 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
408 //seems it does this also with a patch with valid dimensions.. but probably better to enforce a brush.
409 if ( !Node_isBrush( instance.path().top() ) ) {
410 //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
411 globalErrorStream() << "bobToolz PitBuilder: No brush selected, select ONLY 1 brush.\n";
415 VectorSubtract( instance.worldAABB().origin, instance.worldAABB().extents, vMin );
416 VectorAdd( instance.worldAABB().origin, instance.worldAABB().extents, vMax );
420 if ( pit.BuildPit( vMin, vMax ) ) {
422 Path_deleteTop( instance.path() );
426 //DoMessageBox("Failed To Make Pit\nTry Making The Brush Bigger", "Error", eMB_OK);
427 globalErrorStream() << "bobToolz PitBuilder: Failed to make Pit, try making the brush bigger.\n";
431 void DoMergePatches(){
432 UndoableCommand undo( "bobToolz.mergePatches" );
433 patch_merge_t merge_info;
434 DPatch mrgPatches[2];
437 // ensure we have something selected
438 if ( GlobalSelectionSystem().countSelected() != 2 ) {
439 globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose 2 only.\n";
440 //DoMessageBox("Invalid number of patches selected, choose 2 only", "Error", eMB_OK);
444 scene::Instance* patches[2];
445 patches[0] = &GlobalSelectionSystem().ultimateSelected();
446 patches[1] = &GlobalSelectionSystem().penultimateSelected();
448 for ( i = 0; i < 2; i++ )
450 if ( !Node_isPatch( patches[i]->path().top() ) ) {
451 //DoMessageBox("No patches selected, select ONLY patches", "Error", eMB_OK);
452 globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose ONLY 2 patches.\n";
456 mrgPatches[i].LoadFromPatch( *patches[i] );
459 /* mrgPatches[0].Transpose();
460 mrgPatches[0].RemoveFromRadiant();
461 mrgPatches[0].BuildInRadiant();*/
463 merge_info = mrgPatches[0].IsMergable( &mrgPatches[1] );
465 if ( merge_info.mergable ) {
466 // globalOutputStream() << merge_info.pos1 << " " << merge_info.pos2;
467 //Message removed, No tools give feedback on success.
468 //globalOutputStream() << "bobToolz MergePatches: Patches Mergable.\n";
469 DPatch* newPatch = mrgPatches[0].MergePatches( merge_info, &mrgPatches[0], &mrgPatches[1] );
471 /* mrgPatches[0].RemoveFromRadiant();
472 mrgPatches[0].BuildInRadiant();
474 mrgPatches[1].RemoveFromRadiant();
475 mrgPatches[1].BuildInRadiant();
484 newPatch->BuildInRadiant( patches[0]->path().parent().get_pointer() );
486 scene::Instance& parent = *( patches[1]->parent() );
487 Path_deleteTop( patches[0]->path() );
488 Path_deleteTop( patches[1]->path() );
489 Entity* entity = Node_getEntity( parent.path().top() );
491 && Node_getTraversable( parent.path().top() )->empty() ) {
492 Path_deleteTop( parent.path() );
500 globalErrorStream() << "bobToolz.mergePatch: The selected patches are not mergable.\n";
505 void DoSplitPatch() {
506 UndoableCommand undo( "bobToolz.splitPatch" );
510 // ensure we have something selected
511 if ( GlobalSelectionSystem().countSelected() != 1 ) {
512 //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
513 globalErrorStream() << "bobToolz SplitPatch: Invalid number of patches selected, choose only 1 patch.\n";
517 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
519 if ( !Node_isPatch( instance.path().top() ) ) {
520 //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
521 globalErrorStream() << "bobToolz SplitPatch: No patch selected, select ONLY 1 patch.\n";
525 patch.LoadFromPatch( instance );
527 std::list<DPatch> patchList = patch.Split();
528 for ( std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++ ) {
529 ( *patches ).BuildInRadiant( instance.path().parent().get_pointer() );
532 Path_deleteTop( instance.path() );
535 void DoSplitPatchCols() {
536 UndoableCommand undo( "bobToolz.splitPatchCols" );
540 // ensure we have something selected
541 if ( GlobalSelectionSystem().countSelected() != 1 ) {
542 //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
543 globalErrorStream() << "bobToolz SplitPatchCols: Invalid number of patches selected, choose 1 only.\n";
547 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
549 if ( !Node_isPatch( instance.path().top() ) ) {
550 //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
551 globalErrorStream() << "bobToolz SplitPatchCols: No patch selected, select ONLY 1 patch.\n";
555 patch.LoadFromPatch( instance );
557 std::list<DPatch> patchList = patch.SplitCols();
558 for ( std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++ ) {
559 ( *patches ).BuildInRadiant( instance.path().parent().get_pointer() );
562 Path_deleteTop( instance.path() );
565 void DoSplitPatchRows() {
566 UndoableCommand undo( "bobToolz.splitPatchRows" );
570 // ensure we have something selected
571 if ( GlobalSelectionSystem().countSelected() != 1 ) {
572 //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
573 globalErrorStream() << "bobToolz SplitPatchRows: Invalid number of patches selected, choose 1 only.\n";
577 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
579 if ( !Node_isPatch( instance.path().top() ) ) {
580 //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
581 globalErrorStream() << "bobToolz SplitPatchRows: No patch selected, select ONLY 1 patch.\n";
585 patch.LoadFromPatch( instance );
587 std::list<DPatch> patchList = patch.SplitRows();
588 for ( std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++ ) {
589 ( *patches ).BuildInRadiant( instance.path().parent().get_pointer() );
592 Path_deleteTop( instance.path() );
598 if ( GlobalSelectionSystem().countSelected() == 0 ) {
599 globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n";
606 // ensure we have something selected
607 if ( GlobalSelectionSystem().countSelected() != 1 ) {
608 //DoMessageBox("Invalid number of objects selected, choose 1 only", "Error", eMB_OK);
609 globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n";
613 scene::Instance& brush = GlobalSelectionSystem().ultimateSelected();
614 //ensure we have a brush selected
615 if ( !Node_isBrush( brush.path().top() ) ) {
616 //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
617 globalErrorStream() << "bobToolz VisAnalyse: No brush selected, select ONLY 1 brush.\n";
621 orgBrush.LoadFromBrush( brush, false );
623 orgBrush.BuildBounds();
625 origin[0] = ( orgBrush.bbox_max[0] + orgBrush.bbox_min[0] ) / 2.f;
626 origin[1] = ( orgBrush.bbox_max[1] + orgBrush.bbox_min[1] ) / 2.f;
627 origin[2] = ( orgBrush.bbox_max[2] + orgBrush.bbox_min[2] ) / 2.f;
630 const char* rad_filename = GlobalRadiant().getMapName();
631 if ( !rad_filename ) {
632 //DoMessageBox("An ERROR occurred while trying\n to get the map filename", "Error", eMB_OK);
633 globalErrorStream() << "bobToolz VisAnalyse: An ERROR occurred while trying to get the map filename.\n";
637 strcpy( filename, rad_filename );
639 char* ext = strrchr( filename, '.' ) + 1;
640 strcpy( ext, "bsp" ); // rename the extension
642 std::list<DWinding*> *pointList = BuildTrace( filename, origin );
645 g_VisView = new DVisDrawer;
648 g_VisView->SetList( pointList );
651 void DoTrainPathPlot() {
657 g_TrainView = new DTrainDrawer();
660 void DoCaulkSelection() {
661 UndoableCommand undo( "bobToolz.caulkSelection" );
664 float fScale[2] = { 0.5f, 0.5f };
665 float fShift[2] = { 0.0f, 0.0f };
667 int bResetScale[2] = { false, false };
668 int bResetShift[2] = { false, false };
670 world.LoadSelectedBrushes();
671 world.LoadSelectedPatches();
672 world.ResetTextures( NULL, fScale, fShift, 0, "textures/common/caulk", true, bResetScale, bResetShift, false, true );
675 void DoTreePlanter() {
676 UndoableCommand undo( "bobToolz.treePlanter" );
677 if ( g_TreePlanter ) {
678 delete g_TreePlanter;
679 g_TreePlanter = NULL;
683 g_TreePlanter = new DTreePlanter();
687 UndoableCommand undo( "bobToolz.dropEntities" );
688 if ( g_TreePlanter ) {
689 g_TreePlanter->DropEntsToGround();
695 if ( DoMakeChainBox( &rs ) == eIDOK ) {
696 if ( rs.linkNum > 1001 ) {
697 globalErrorStream() << "bobToolz MakeChain: " << rs.linkNum << " to many Elemets, limited to 1000.\n";
700 UndoableCommand undo( "bobToolz.makeChain" );
702 pl.MakeChain( rs.linkNum,rs.linkName );
706 typedef DPoint* pntTripple[3];
708 bool bFacesNoTop[6] = {true, true, true, true, true, false};
710 void DoFlipTerrain() {
711 UndoableCommand undo( "bobToolz.flipTerrain" );
712 vec3_t vUp = { 0.f, 0.f, 1.f };
715 // ensure we have something selected
716 if ( GlobalSelectionSystem().countSelected() != 2 ) {
717 //DoMessageBox("Invalid number of objects selected, choose 2 only", "Error", eMB_OK);
718 globalErrorStream() << "bobToolz FlipTerrain: Invalid number of objects selected, choose 2 only.\n";
722 scene::Instance* brushes[2];
723 brushes[0] = &GlobalSelectionSystem().ultimateSelected();
724 brushes[1] = &GlobalSelectionSystem().penultimateSelected();
725 //ensure we have only Brushes selected.
726 for ( i = 0; i < 2; i++ )
728 if ( !Node_isBrush( brushes[i]->path().top() ) ) {
729 //DoMessageBox("No brushes selected, select ONLY brushes", "Error", eMB_OK);
730 globalErrorStream() << "bobToolz FlipTerrain: No brushes selected, select ONLY 2 brushes.\n";
736 pntTripple Points[2];
737 for ( i = 0; i < 2; i++ ) {
738 Brushes[i].LoadFromBrush( *brushes[i], false );
739 if ( !( Planes[i] = Brushes[i].FindPlaneWithClosestNormal( vUp ) ) || Brushes[i].FindPointsForPlane( Planes[i], Points[i], 3 ) != 3 ) {
740 //DoMessageBox("Error", "Error", eMB_OK);
741 globalErrorStream() << "bobToolz FlipTerrain: ERROR (FindPlaneWithClosestNormal/FindPointsForPlane).\n";
746 vec3_t mins1, mins2, maxs1, maxs2;
747 Brushes[0].GetBounds( mins1, maxs1 );
748 Brushes[1].GetBounds( mins2, maxs2 );
752 int dontmatch[2] = { -1, -1 };
754 for ( i = 0; i < 3; i++ ) {
755 for ( int j = 0; j < 3 && !found; j++ ) {
756 if ( VectorCompare( ( Points[0] )[i]->_pnt, ( Points[1] )[j]->_pnt ) ) {
767 if ( dontmatch[0] == -1 ) {
768 //DoMessageBox("Error", "Error", eMB_OK);
769 globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[0]).\n";
773 for ( i = 0; i < 3; i++ ) {
774 for ( int j = 0; j < 3 && !found; j++ ) {
775 if ( VectorCompare( ( Points[1] )[i]->_pnt, ( Points[0] )[j]->_pnt ) ) {
786 if ( dontmatch[1] == -1 ) {
787 //DoMessageBox("Error", "Error", eMB_OK);
788 globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[1]).\n";
794 vec3_t plnpntsshr[3];
796 VectorCopy( ( Points[0] )[dontmatch[0]]->_pnt, plnpnts1[0] );
797 for ( i = 0; i < 3; i++ ) {
798 if ( dontmatch[0] != i ) {
799 VectorCopy( ( Points[0] )[i]->_pnt, plnpnts1[1] );
803 VectorCopy( ( Points[1] )[dontmatch[1]]->_pnt, plnpnts1[2] );
805 VectorCopy( ( Points[1] )[dontmatch[1]]->_pnt, plnpnts2[0] );
806 for ( i = 0; i < 3; i++ ) {
807 if ( dontmatch[1] != i && !VectorCompare( ( Points[1] )[i]->_pnt, plnpnts1[1] ) ) {
808 VectorCopy( ( Points[1] )[i]->_pnt, plnpnts2[1] );
812 VectorCopy( ( Points[0] )[dontmatch[0]]->_pnt, plnpnts2[2] );
814 VectorCopy( ( Points[0] )[dontmatch[0]]->_pnt, plnpntsshr[0] );
815 VectorCopy( ( Points[1] )[dontmatch[1]]->_pnt, plnpntsshr[1] );
816 if ( ( Points[1] )[dontmatch[1]]->_pnt[2] < ( Points[0] )[dontmatch[0]]->_pnt[2] ) {
817 VectorCopy( ( Points[1] )[dontmatch[1]]->_pnt, plnpntsshr[2] );
820 VectorCopy( ( Points[0] )[dontmatch[0]]->_pnt, plnpntsshr[2] );
822 plnpntsshr[2][2] -= 16;
824 for ( i = 0; i < 3; i++ ) {
825 if ( mins2[i] < mins1[i] ) {
828 if ( maxs2[i] > maxs1[i] ) {
833 DBrush* newBrushes[2];
834 newBrushes[0] = DShape::GetBoundingCube_Ext( mins1, maxs1, "textures/common/caulk", bFacesAll, true );
835 newBrushes[1] = DShape::GetBoundingCube_Ext( mins1, maxs1, "textures/common/caulk", bFacesAll, true );
838 MakeNormal( plnpnts1[0], plnpnts1[1], plnpnts1[2], normal );
839 if ( normal[2] >= 0 ) {
840 newBrushes[0]->AddFace( plnpnts1[0], plnpnts1[1], plnpnts1[2], "textures/common/terrain", true );
843 newBrushes[0]->AddFace( plnpnts1[2], plnpnts1[1], plnpnts1[0], "textures/common/terrain", true );
846 MakeNormal( plnpnts2[0], plnpnts2[1], plnpnts2[2], normal );
847 if ( normal[2] >= 0 ) {
848 newBrushes[1]->AddFace( plnpnts2[0], plnpnts2[1], plnpnts2[2], "textures/common/terrain", true );
851 newBrushes[1]->AddFace( plnpnts2[2], plnpnts2[1], plnpnts2[0], "textures/common/terrain", true );
855 MakeNormal( plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], normal );
857 VectorSubtract( plnpnts1[2], plnpnts1[1], vec );
858 if ( DotProduct( vec, normal ) >= 0 ) {
859 newBrushes[0]->AddFace( plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], "textures/common/caulk", true );
862 newBrushes[0]->AddFace( plnpntsshr[2], plnpntsshr[1], plnpntsshr[0], "textures/common/caulk", true );
865 VectorSubtract( plnpnts2[2], plnpnts2[1], vec );
866 if ( DotProduct( vec, normal ) >= 0 ) {
867 newBrushes[1]->AddFace( plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], "textures/common/caulk", true );
870 newBrushes[1]->AddFace( plnpntsshr[2], plnpntsshr[1], plnpntsshr[0], "textures/common/caulk", true );
873 for ( i = 0; i < 2; i++ ) {
874 newBrushes[i]->RemoveRedundantPlanes();
875 newBrushes[i]->BuildInRadiant( false, NULL, brushes[i]->path().parent().get_pointer() );
876 Path_deleteTop( brushes[i]->path() );
877 delete newBrushes[i];