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 ************************/
72 el1Loaded = LoadExclusionList(GetFilename(buffer, "bt\\bt-el1.txt"), &exclusionList);
74 el2Loaded = LoadExclusionList(GetFilename(buffer, "bt\\bt-el2.txt"), &exclusionList);
77 void PolygonBuilder(vec3_t vMin, vec3_t vMax)
79 // ensure we have something selected
80 if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )
82 MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);
86 // tell Radiant we want to access the selected brushes
87 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
89 // get handle to size definition brush
90 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);
91 // cant release until we delete the brush, if we do...
93 // ask user for type, size, etc....
94 if(polygonDlg.DoModal() == IDOK)
98 g_FuncTable.m_pfnDeleteBrushHandle(brush);
100 if(polygonDlg.m_bInverse)
101 poly.BuildInversePrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop);
104 if(polygonDlg.m_bBorder)
105 poly.BuildBorderedPrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_nBorderSize, polygonDlg.m_bAlignTop);
107 poly.BuildRegularPrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop);
114 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
118 void IntersectionFinder()
120 if(intrDlg.DoModal() == IDCANCEL)
123 if(intrDlg.m_nBrushOptions == BRUSH_OPT_SELECTED)
125 // ensure we have enough brushes selected
126 if( g_FuncTable.m_pfnSelectedBrushCount() < 2 )
128 MessageBox(NULL, "Invalid number of brushes selected, choose at least 2", "Error", MB_OK);
133 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
134 intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);
138 switch(intrDlg.m_nBrushOptions)
140 case BRUSH_OPT_SELECTED:
142 world.LoadSelectedBrushes(&intrInfoDlg->m_prog1);
145 case BRUSH_OPT_WHOLE_MAP:
147 world.LoadFromEntity(0, &intrInfoDlg->m_prog1);
152 world.RemoveNonCheckBrushes(&exclusionList, intrDlg.m_bUseDetail);
154 if(intrDlg.m_bDuplicateOnly)
155 pbSelectList = world.BuildDuplicateList();
157 pbSelectList = world.BuildIntersectList();
159 world.SelectBrushes(pbSelectList);
161 intrInfoDlg->DestroyWindow();
162 delete[] pbSelectList;
165 void StairBuilder(vec3_t vMin, vec3_t vMax)
167 // ensure we have something selected
168 if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )
170 MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);
174 // tell Radiant we want to access the selected brushes
175 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
177 // get handle to size definition brush
178 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);
179 // cant release until we delete the brush, if we do...
182 // ask user for type, size, etc....
183 if(stairDlg.DoModal() == IDOK)
188 _VectorSubtract(vMax, vMin, size);
191 if(((int)size[2] % stairDlg.m_nStairHeight) != 0)
193 // stairs must fit evenly into brush
194 MessageBox(NULL, "Invalid stair height\nHeight of block must be divisable by stair height", "Error", MB_OK);
200 g_FuncTable.m_pfnDeleteBrushHandle(brush);
203 // Get Step Count, Direction of Stairs, Stair Style
204 int numSteps = (int)size[2] / stairDlg.m_nStairHeight;
205 int direction = stairDlg.m_StairDir;
206 int style = stairDlg.m_StairStyle;
208 if(stairDlg.m_StairStyle == STYLE_CORNER)
210 BuildCornerStairs(vMin, vMax, numSteps, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture);
214 // Get Step Dimensions
215 float stairHeight = (float)stairDlg.m_nStairHeight;
217 if((direction == MOVE_EAST) || (direction == MOVE_WEST))
218 stairWidth = (size[0])/numSteps;
220 stairWidth = (size[1])/numSteps;
223 // Build Base For Stair (bob's style)
224 if(style == STYLE_BOB)
225 Build_Wedge(direction, vMin, vMax, TRUE);
228 // Set First Step Starting Position
229 vMax[2] = vMin[2] + stairHeight;
230 SetInitialStairPos(direction, vMin, vMax, stairWidth);
234 for(int i = 0; i < numSteps; i++)
236 if(style == STYLE_BOB)
237 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);
241 // get step into next position
242 MoveBlock(direction, vMin, vMax, stairWidth);
243 vMax[2] += stairHeight;
244 if(style == STYLE_BOB)
245 vMin[2] += stairHeight; // wedge bottom must be raised
251 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
254 void DoorBuilder(vec3_t vMin, vec3_t vMax)
256 // ensure we have something selected
257 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)
276 g_FuncTable.m_pfnDeleteBrushHandle(brush);
278 BuildDoorsX2(vMin, vMax,
279 doorDlg.m_bSclMainHor, doorDlg.m_bSclMainVert,
280 doorDlg.m_bSclTrimHor, doorDlg.m_bSclTrimVert,
281 (LPCTSTR)doorDlg.m_fbTextureName,
282 (LPCTSTR)doorDlg.m_trimTextureName,
283 doorDlg.m_doorDirection);
286 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
293 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
294 intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);
296 world.LoadFromEntity(0, &intrInfoDlg->m_prog1);
298 intrInfoDlg->DestroyWindow();
300 CBrushCheckDialog* chkDlg = new CBrushCheckDialog();
301 chkDlg->Create(IDD_BRUSHCHECKER_DIALOG);
303 int count = world.FixBrushes(TRUE, &chkDlg->m_prog1);
305 chkDlg->DestroyWindow();
307 Sys_Printf("%i invalid/duplicate planes removed\n", count);
313 autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED";
315 if(autocaulkDlg.DoModal() == IDCANCEL)
318 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)
331 char* rad_filename = g_BSPTable.m_pfnGetMapName();
334 MessageBox(NULL, "An Error Occurred While Trying To Get The Map Filename", "Error", MB_OK);
335 acDlg->DestroyWindow();
339 strcpy(filename, rad_filename);
341 char* ext = strrchr(filename, '.')+1;
342 strcpy(ext, "prt");// rename the extension
346 IEpair* pEp = g_EpairTable.m_pfnIEpairForProjectKeys();
347 char *pn = pEp->ValueForKey("mapspath");
350 strcpy( filename, pn );
351 strcat( filename, "/ac_prt.prt" );
355 if(!portals.LoadFromPrt(filename, &acDlg->m_prog1))
357 MessageBox(NULL, "Failed To Load Portal File", "Error", MB_OK);
358 acDlg->DestroyWindow();
363 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
364 intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);
368 world.LoadFromEntity(0, &intrInfoDlg->m_prog1);
369 intrInfoDlg->DestroyWindow();
371 if(autocaulkDlg.m_nMode == MODE_AC_NORMAL)
372 world.RemoveNonCheckBrushes(&exclusionList, FALSE);
374 world.RemoveNonCheckBrushes(&exclusionList, TRUE);
376 world.ResetChecks(&exclusionList_Face);
378 int caulkedCount = 0;
379 int killCnt = world.AutoCaulk(&portals, autocaulkDlg.m_bAllowDestruction, &caulkedCount, &acDlg->m_prog2);
381 if(autocaulkDlg.m_bAllowDestruction)
382 Sys_Printf("%i unrequired brush(es) killed\n", killCnt);
383 Sys_Printf("%i face(s) caulked\n", caulkedCount);
385 acDlg->DestroyWindow();
390 texRstDlg.m_TextureName = GetCurrentTexture();
391 texRstDlg.m_NewTextureName = GetCurrentTexture();
393 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);
410 world.ResetTextures(texRstDlg.m_TextureName, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture);
415 int ret = ppDlg.DoModal();
426 if( g_FuncTable.m_pfnSelectedBrushCount() != 1)
428 MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);
432 // tell Radiant we want to access the selected brushes
433 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
435 // get handle to size definition brush
436 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);
437 // cant release until we delete the brush, if we do...
440 world.LoadEPairList(*g_FuncTable.m_pfnGetEntityKeyValList(brush->owner));
442 DEPair* trigger_ep = world.FindEPairByKey("targetname");
446 if(!strcmp(world.m_Classname, "trigger_push"))
448 DEPair* target_ep = world.FindEPairByKey("target");
451 entity_s* entTarget = FindEntityFromTargetname(target_ep->value);
456 g_PathView = new DBobView;
458 g_PathView->Begin(trigger_ep->value, target_ep->value, ppDlg.m_fMultiplier, ppDlg.m_nPoints, ppDlg.m_fGravity, ppDlg.m_bNoUpdate, ppDlg.m_bShowExtra);
461 MessageBox(NULL, "trigger_push target could not be found.", "Error", MB_OK);
464 MessageBox(NULL, "trigger_push has no target.", "Error", MB_OK);
467 MessageBox(NULL, "You must select a 'trigger_push' entity.", "Error", MB_OK);
470 MessageBox(NULL, "Entity must have a targetname", "Error", MB_OK);
472 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
475 void PitBuilder(vec3_t vMin, vec3_t vMax)
477 // ensure we have something selected
478 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))
497 g_FuncTable.m_pfnDeleteBrushHandle(brush);
500 MessageBox(NULL, "Failed To Make Pit\nTry Making The Brush Bigger", "Error", MB_OK);
502 g_FuncTable.m_pfnReleaseSelectedBrushHandles();