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
22 #include "funchandlers.h"
24 #include "IntersectDialog.h"
25 #include "PolygonDialog.h"
26 #include "StairDialog.h"
27 #include "DoorDialog.h"
28 #include "IntersectInfoDialog.h"
29 #include "BrushCheckDialog.h"
30 #include "AutoCaulkDialog.h"
31 #include "AutoCaulkStartDialog.h"
32 #include "TextureResetDialog.h"
33 #include "pathplotterdialog.h"
42 std::list<Str> exclusionList; // whole brush exclusion
43 std::list<Str> exclusionList_Face; // single face exclusion
48 DBobView* g_PathView = NULL;
51 /************************
53 ************************/
55 CPolygonDialog polygonDlg;
56 CIntersectDialog intrDlg;
57 CStairDialog stairDlg;
59 CAutoCaulkStartDialog autocaulkDlg;
60 CTextureResetDialog texRstDlg;
61 CPathPlotterDialog ppDlg;
63 /************************
65 ************************/
71 el1Loaded = LoadExclusionList( GetFilename( buffer, "bt\\bt-el1.txt" ), &exclusionList );
74 el2Loaded = LoadExclusionList( GetFilename( buffer, "bt\\bt-el2.txt" ), &exclusionList );
78 void PolygonBuilder( vec3_t vMin, vec3_t vMax ){
79 // ensure we have something selected
80 if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
81 MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
85 // tell Radiant we want to access the selected brushes
86 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
88 // get handle to size definition brush
89 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
90 // cant release until we delete the brush, if we do...
92 // ask user for type, size, etc....
93 if ( polygonDlg.DoModal() == IDOK ) {
96 g_FuncTable.m_pfnDeleteBrushHandle( brush );
98 if ( polygonDlg.m_bInverse ) {
99 poly.BuildInversePrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop );
103 if ( polygonDlg.m_bBorder ) {
104 poly.BuildBorderedPrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_nBorderSize, polygonDlg.m_bAlignTop );
107 poly.BuildRegularPrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop );
115 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
119 void IntersectionFinder(){
120 if ( intrDlg.DoModal() == IDCANCEL ) {
124 if ( intrDlg.m_nBrushOptions == BRUSH_OPT_SELECTED ) {
125 // ensure we have enough brushes selected
126 if ( g_FuncTable.m_pfnSelectedBrushCount() < 2 ) {
127 MessageBox( NULL, "Invalid number of brushes selected, choose at least 2", "Error", MB_OK );
132 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
133 intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG );
137 switch ( intrDlg.m_nBrushOptions )
139 case BRUSH_OPT_SELECTED:
141 world.LoadSelectedBrushes( &intrInfoDlg->m_prog1 );
144 case BRUSH_OPT_WHOLE_MAP:
146 world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 );
151 world.RemoveNonCheckBrushes( &exclusionList, intrDlg.m_bUseDetail );
153 if ( intrDlg.m_bDuplicateOnly ) {
154 pbSelectList = world.BuildDuplicateList();
157 pbSelectList = world.BuildIntersectList();
160 world.SelectBrushes( pbSelectList );
162 intrInfoDlg->DestroyWindow();
163 delete[] pbSelectList;
166 void StairBuilder( vec3_t vMin, vec3_t vMax ){
167 // ensure we have something selected
168 if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
169 MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
173 // tell Radiant we want to access the selected brushes
174 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
176 // get handle to size definition brush
177 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
178 // cant release until we delete the brush, if we do...
181 // ask user for type, size, etc....
182 if ( stairDlg.DoModal() == IDOK ) {
186 _VectorSubtract( vMax, vMin, size );
189 if ( ( (int)size[2] % stairDlg.m_nStairHeight ) != 0 ) {
190 // stairs must fit evenly into brush
191 MessageBox( NULL, "Invalid stair height\nHeight of block must be divisable by stair height", "Error", MB_OK );
197 g_FuncTable.m_pfnDeleteBrushHandle( brush );
200 // Get Step Count, Direction of Stairs, Stair Style
201 int numSteps = (int)size[2] / stairDlg.m_nStairHeight;
202 int direction = stairDlg.m_StairDir;
203 int style = stairDlg.m_StairStyle;
205 if ( stairDlg.m_StairStyle == STYLE_CORNER ) {
206 BuildCornerStairs( vMin, vMax, numSteps, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture );
210 // Get Step Dimensions
211 float stairHeight = (float)stairDlg.m_nStairHeight;
213 if ( ( direction == MOVE_EAST ) || ( direction == MOVE_WEST ) ) {
214 stairWidth = ( size[0] ) / numSteps;
217 stairWidth = ( size[1] ) / numSteps;
221 // Build Base For Stair (bob's style)
222 if ( style == STYLE_BOB ) {
223 Build_Wedge( direction, vMin, vMax, TRUE );
227 // Set First Step Starting Position
228 vMax[2] = vMin[2] + stairHeight;
229 SetInitialStairPos( direction, vMin, vMax, stairWidth );
233 for ( int i = 0; i < numSteps; i++ )
235 if ( style == STYLE_BOB ) {
236 Build_StairStep_Wedge( direction, vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, stairDlg.m_bDetail );
238 else if ( style == STYLE_ORIGINAL ) {
239 Build_StairStep( vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, direction );
242 // get step into next position
243 MoveBlock( direction, vMin, vMax, stairWidth );
244 vMax[2] += stairHeight;
245 if ( style == STYLE_BOB ) {
246 vMin[2] += stairHeight; // wedge bottom must be raised
253 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
256 void DoorBuilder( vec3_t vMin, vec3_t vMax ){
257 // ensure we have something selected
258 if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
259 MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
263 // tell Radiant we want to access the selected brushes
264 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
266 // get handle to size definition brush
267 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
268 // cant release until we delete the brush, if we do...
272 strcpy( doorDlg.m_fbTextureName.GetBuffer( 256 ), g_FuncTable.m_pfnGetCurrentTexture() );
274 if ( doorDlg.DoModal() == IDOK ) {
275 g_FuncTable.m_pfnDeleteBrushHandle( brush );
277 BuildDoorsX2( vMin, vMax,
278 doorDlg.m_bSclMainHor, doorDlg.m_bSclMainVert,
279 doorDlg.m_bSclTrimHor, doorDlg.m_bSclTrimVert,
280 (LPCTSTR)doorDlg.m_fbTextureName,
281 (LPCTSTR)doorDlg.m_trimTextureName,
282 doorDlg.m_doorDirection );
285 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
291 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
292 intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG );
294 world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 );
296 intrInfoDlg->DestroyWindow();
298 CBrushCheckDialog* chkDlg = new CBrushCheckDialog();
299 chkDlg->Create( IDD_BRUSHCHECKER_DIALOG );
301 int count = world.FixBrushes( TRUE, &chkDlg->m_prog1 );
303 chkDlg->DestroyWindow();
305 Sys_Printf( "%i invalid/duplicate planes removed\n", count );
309 UndoableCommand undo( "bobToolz.autoCaulk" );
312 autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED";
315 if ( autocaulkDlg.DoModal() == IDCANCEL ) {
319 if ( autocaulkDlg.m_nMode == MODE_AC_BUILD_MINI_PRT ) {
320 BuildMiniPrt( &exclusionList );
324 CAutoCaulkDialog* acDlg = new CAutoCaulkDialog;
325 acDlg->Create( IDD_AUTOCAULK_DIALOG );
329 if ( autocaulkDlg.m_nMode == MODE_AC_NORMAL ) {
330 char* rad_filename = g_BSPTable.m_pfnGetMapName();
331 if ( !rad_filename ) {
332 MessageBox( NULL, "An Error Occurred While Trying To Get The Map Filename", "Error", MB_OK );
333 acDlg->DestroyWindow();
337 strcpy( filename, rad_filename );
339 char* ext = strrchr( filename, '.' ) + 1;
340 strcpy( ext, "prt" ); // rename the extension
344 IEpair* pEp = g_EpairTable.m_pfnIEpairForProjectKeys();
345 char *pn = pEp->ValueForKey( "mapspath" );
348 strcpy( filename, pn );
349 strcat( filename, "/ac_prt.prt" );
353 if ( !portals.LoadFromPrt( filename, &acDlg->m_prog1 ) ) {
354 MessageBox( NULL, "Failed To Load Portal File", "Error", MB_OK );
355 acDlg->DestroyWindow();
360 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
361 intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG );
365 world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 );
366 intrInfoDlg->DestroyWindow();
368 if ( autocaulkDlg.m_nMode == MODE_AC_NORMAL ) {
369 world.RemoveNonCheckBrushes( &exclusionList, FALSE );
372 world.RemoveNonCheckBrushes( &exclusionList, TRUE );
375 world.ResetChecks( &exclusionList_Face );
377 int caulkedCount = 0;
378 int killCnt = world.AutoCaulk( &portals, autocaulkDlg.m_bAllowDestruction, &caulkedCount, &acDlg->m_prog2 );
380 if ( autocaulkDlg.m_bAllowDestruction ) {
381 Sys_Printf( "%i unrequired brush(es) killed\n", killCnt );
383 Sys_Printf( "%i face(s) caulked\n", caulkedCount );
385 acDlg->DestroyWindow();
388 void ResetTextures(){
389 texRstDlg.m_TextureName = GetCurrentTexture();
390 texRstDlg.m_NewTextureName = GetCurrentTexture();
392 if ( texRstDlg.DoModal() == IDCANCEL ) {
398 fScale[1] = texRstDlg.m_fScaleVertical;
399 fScale[0] = texRstDlg.m_fScaleHorizontal;
401 fShift[1] = (float)texRstDlg.m_nShiftVertical;
402 fShift[0] = (float)texRstDlg.m_nShiftHorizontal;
405 world.LoadFromEntity( 0, NULL );
407 if ( texRstDlg.m_bAllTextures ) {
408 world.ResetTextures( NULL, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture );
411 world.ResetTextures( texRstDlg.m_TextureName, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture );
416 int ret = ppDlg.DoModal();
417 if ( ret == IDCANCEL ) {
428 if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
429 MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
433 // tell Radiant we want to access the selected brushes
434 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
436 // get handle to size definition brush
437 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
438 // cant release until we delete the brush, if we do...
441 world.LoadEPairList( *g_FuncTable.m_pfnGetEntityKeyValList( brush->owner ) );
443 DEPair* trigger_ep = world.FindEPairByKey( "targetname" );
446 if ( !strcmp( world.m_Classname, "trigger_push" ) ) {
447 DEPair* target_ep = world.FindEPairByKey( "target" );
449 entity_s* entTarget = FindEntityFromTargetname( target_ep->value );
454 g_PathView = new DBobView;
456 g_PathView->Begin( trigger_ep->value, target_ep->value, ppDlg.m_fMultiplier, ppDlg.m_nPoints, ppDlg.m_fGravity, ppDlg.m_bNoUpdate, ppDlg.m_bShowExtra );
459 MessageBox( NULL, "trigger_push target could not be found.", "Error", MB_OK );
463 MessageBox( NULL, "trigger_push has no target.", "Error", MB_OK );
467 MessageBox( NULL, "You must select a 'trigger_push' entity.", "Error", MB_OK );
471 MessageBox( NULL, "Entity must have a targetname", "Error", MB_OK );
474 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
477 void PitBuilder( vec3_t vMin, vec3_t vMax ){
478 // ensure we have something selected
479 if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
480 MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
484 // tell Radiant we want to access the selected brushes
485 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
487 // get handle to size definition brush
488 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
489 // cant release until we delete the brush, if we do...
493 if ( pit.BuildPit( vMin, vMax ) ) {
496 g_FuncTable.m_pfnDeleteBrushHandle( brush );
499 MessageBox( NULL, "Failed To Make Pit\nTry Making The Brush Bigger", "Error", MB_OK );
502 g_FuncTable.m_pfnReleaseSelectedBrushHandles();