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 list<Str> exclusionList; // whole brush exclusion
43 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 );
310 autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED";
313 if ( autocaulkDlg.DoModal() == IDCANCEL ) {
317 if ( autocaulkDlg.m_nMode == MODE_AC_BUILD_MINI_PRT ) {
318 BuildMiniPrt( &exclusionList );
322 CAutoCaulkDialog* acDlg = new CAutoCaulkDialog;
323 acDlg->Create( IDD_AUTOCAULK_DIALOG );
327 if ( autocaulkDlg.m_nMode == MODE_AC_NORMAL ) {
328 char* rad_filename = g_BSPTable.m_pfnGetMapName();
329 if ( !rad_filename ) {
330 MessageBox( NULL, "An Error Occurred While Trying To Get The Map Filename", "Error", MB_OK );
331 acDlg->DestroyWindow();
335 strcpy( filename, rad_filename );
337 char* ext = strrchr( filename, '.' ) + 1;
338 strcpy( ext, "prt" ); // rename the extension
342 IEpair* pEp = g_EpairTable.m_pfnIEpairForProjectKeys();
343 char *pn = pEp->ValueForKey( "mapspath" );
346 strcpy( filename, pn );
347 strcat( filename, "/ac_prt.prt" );
351 if ( !portals.LoadFromPrt( filename, &acDlg->m_prog1 ) ) {
352 MessageBox( NULL, "Failed To Load Portal File", "Error", MB_OK );
353 acDlg->DestroyWindow();
358 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
359 intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG );
363 world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 );
364 intrInfoDlg->DestroyWindow();
366 if ( autocaulkDlg.m_nMode == MODE_AC_NORMAL ) {
367 world.RemoveNonCheckBrushes( &exclusionList, FALSE );
370 world.RemoveNonCheckBrushes( &exclusionList, TRUE );
373 world.ResetChecks( &exclusionList_Face );
375 int caulkedCount = 0;
376 int killCnt = world.AutoCaulk( &portals, autocaulkDlg.m_bAllowDestruction, &caulkedCount, &acDlg->m_prog2 );
378 if ( autocaulkDlg.m_bAllowDestruction ) {
379 Sys_Printf( "%i unrequired brush(es) killed\n", killCnt );
381 Sys_Printf( "%i face(s) caulked\n", caulkedCount );
383 acDlg->DestroyWindow();
386 void ResetTextures(){
387 texRstDlg.m_TextureName = GetCurrentTexture();
388 texRstDlg.m_NewTextureName = GetCurrentTexture();
390 if ( texRstDlg.DoModal() == IDCANCEL ) {
396 fScale[1] = texRstDlg.m_fScaleVertical;
397 fScale[0] = texRstDlg.m_fScaleHorizontal;
399 fShift[1] = (float)texRstDlg.m_nShiftVertical;
400 fShift[0] = (float)texRstDlg.m_nShiftHorizontal;
403 world.LoadFromEntity( 0, NULL );
405 if ( texRstDlg.m_bAllTextures ) {
406 world.ResetTextures( NULL, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture );
409 world.ResetTextures( texRstDlg.m_TextureName, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture );
414 int ret = ppDlg.DoModal();
415 if ( ret == IDCANCEL ) {
426 if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
427 MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
431 // tell Radiant we want to access the selected brushes
432 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
434 // get handle to size definition brush
435 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
436 // cant release until we delete the brush, if we do...
439 world.LoadEPairList( *g_FuncTable.m_pfnGetEntityKeyValList( brush->owner ) );
441 DEPair* trigger_ep = world.FindEPairByKey( "targetname" );
444 if ( !strcmp( world.m_Classname, "trigger_push" ) ) {
445 DEPair* target_ep = world.FindEPairByKey( "target" );
447 entity_s* entTarget = FindEntityFromTargetname( target_ep->value );
452 g_PathView = new DBobView;
454 g_PathView->Begin( trigger_ep->value, target_ep->value, ppDlg.m_fMultiplier, ppDlg.m_nPoints, ppDlg.m_fGravity, ppDlg.m_bNoUpdate, ppDlg.m_bShowExtra );
457 MessageBox( NULL, "trigger_push target could not be found.", "Error", MB_OK );
461 MessageBox( NULL, "trigger_push has no target.", "Error", MB_OK );
465 MessageBox( NULL, "You must select a 'trigger_push' entity.", "Error", MB_OK );
469 MessageBox( NULL, "Entity must have a targetname", "Error", MB_OK );
472 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
475 void PitBuilder( vec3_t vMin, vec3_t vMax ){
476 // ensure we have something selected
477 if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
478 MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
482 // tell Radiant we want to access the selected brushes
483 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
485 // get handle to size definition brush
486 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
487 // cant release until we delete the brush, if we do...
491 if ( pit.BuildPit( vMin, vMax ) ) {
494 g_FuncTable.m_pfnDeleteBrushHandle( brush );
497 MessageBox( NULL, "Failed To Make Pit\nTry Making The Brush Bigger", "Error", MB_OK );
500 g_FuncTable.m_pfnReleaseSelectedBrushHandles();