2 BobToolz plugin for GtkRadiant
\r
3 Copyright (C) 2001 Gordon Biggans
\r
5 This library is free software; you can redistribute it and/or
\r
6 modify it under the terms of the GNU Lesser General Public
\r
7 License as published by the Free Software Foundation; either
\r
8 version 2.1 of the License, or (at your option) any later version.
\r
10 This library is distributed in the hope that it will be useful,
\r
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
13 Lesser General Public License for more details.
\r
15 You should have received a copy of the GNU Lesser General Public
\r
16 License along with this library; if not, write to the Free Software
\r
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
22 #include "funchandlers.h"
\r
24 #include "IntersectDialog.h"
\r
25 #include "PolygonDialog.h"
\r
26 #include "StairDialog.h"
\r
27 #include "DoorDialog.h"
\r
28 #include "IntersectInfoDialog.h"
\r
29 #include "BrushCheckDialog.h"
\r
30 #include "AutoCaulkDialog.h"
\r
31 #include "AutoCaulkStartDialog.h"
\r
32 #include "TextureResetDialog.h"
\r
33 #include "pathplotterdialog.h"
\r
35 #include "DEntity.h"
\r
42 list<Str> exclusionList; // whole brush exclusion
\r
43 list<Str> exclusionList_Face; // single face exclusion
\r
48 DBobView* g_PathView = NULL;
\r
51 /************************
\r
53 ************************/
\r
55 CPolygonDialog polygonDlg;
\r
56 CIntersectDialog intrDlg;
\r
57 CStairDialog stairDlg;
\r
58 CDoorDialog doorDlg;
\r
59 CAutoCaulkStartDialog autocaulkDlg;
\r
60 CTextureResetDialog texRstDlg;
\r
61 CPathPlotterDialog ppDlg;
\r
63 /************************
\r
65 ************************/
\r
72 el1Loaded = LoadExclusionList(GetFilename(buffer, "bt\\bt-el1.txt"), &exclusionList);
\r
74 el2Loaded = LoadExclusionList(GetFilename(buffer, "bt\\bt-el2.txt"), &exclusionList);
\r
77 void PolygonBuilder(vec3_t vMin, vec3_t vMax)
\r
79 // ensure we have something selected
\r
80 if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )
\r
82 MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);
\r
86 // tell Radiant we want to access the selected brushes
\r
87 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
\r
89 // get handle to size definition brush
\r
90 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);
\r
91 // cant release until we delete the brush, if we do...
\r
93 // ask user for type, size, etc....
\r
94 if(polygonDlg.DoModal() == IDOK)
\r
98 g_FuncTable.m_pfnDeleteBrushHandle(brush);
\r
100 if(polygonDlg.m_bInverse)
\r
101 poly.BuildInversePrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop);
\r
104 if(polygonDlg.m_bBorder)
\r
105 poly.BuildBorderedPrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_nBorderSize, polygonDlg.m_bAlignTop);
\r
107 poly.BuildRegularPrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop);
\r
114 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
\r
118 void IntersectionFinder()
\r
120 if(intrDlg.DoModal() == IDCANCEL)
\r
123 if(intrDlg.m_nBrushOptions == BRUSH_OPT_SELECTED)
\r
125 // ensure we have enough brushes selected
\r
126 if( g_FuncTable.m_pfnSelectedBrushCount() < 2 )
\r
128 MessageBox(NULL, "Invalid number of brushes selected, choose at least 2", "Error", MB_OK);
\r
133 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
\r
134 intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);
\r
138 switch(intrDlg.m_nBrushOptions)
\r
140 case BRUSH_OPT_SELECTED:
\r
142 world.LoadSelectedBrushes(&intrInfoDlg->m_prog1);
\r
145 case BRUSH_OPT_WHOLE_MAP:
\r
147 world.LoadFromEntity(0, &intrInfoDlg->m_prog1);
\r
152 world.RemoveNonCheckBrushes(&exclusionList, intrDlg.m_bUseDetail);
\r
153 BOOL* pbSelectList;
\r
154 if(intrDlg.m_bDuplicateOnly)
\r
155 pbSelectList = world.BuildDuplicateList();
\r
157 pbSelectList = world.BuildIntersectList();
\r
159 world.SelectBrushes(pbSelectList);
\r
161 intrInfoDlg->DestroyWindow();
\r
162 delete[] pbSelectList;
\r
165 void StairBuilder(vec3_t vMin, vec3_t vMax)
\r
167 // ensure we have something selected
\r
168 if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )
\r
170 MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);
\r
174 // tell Radiant we want to access the selected brushes
\r
175 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
\r
177 // get handle to size definition brush
\r
178 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);
\r
179 // cant release until we delete the brush, if we do...
\r
182 // ask user for type, size, etc....
\r
183 if(stairDlg.DoModal() == IDOK)
\r
188 _VectorSubtract(vMax, vMin, size);
\r
191 if(((int)size[2] % stairDlg.m_nStairHeight) != 0)
\r
193 // stairs must fit evenly into brush
\r
194 MessageBox(NULL, "Invalid stair height\nHeight of block must be divisable by stair height", "Error", MB_OK);
\r
199 // Remove Size Brush
\r
200 g_FuncTable.m_pfnDeleteBrushHandle(brush);
\r
203 // Get Step Count, Direction of Stairs, Stair Style
\r
204 int numSteps = (int)size[2] / stairDlg.m_nStairHeight;
\r
205 int direction = stairDlg.m_StairDir;
\r
206 int style = stairDlg.m_StairStyle;
\r
208 if(stairDlg.m_StairStyle == STYLE_CORNER)
\r
210 BuildCornerStairs(vMin, vMax, numSteps, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture);
\r
214 // Get Step Dimensions
\r
215 float stairHeight = (float)stairDlg.m_nStairHeight;
\r
217 if((direction == MOVE_EAST) || (direction == MOVE_WEST))
\r
218 stairWidth = (size[0])/numSteps;
\r
220 stairWidth = (size[1])/numSteps;
\r
223 // Build Base For Stair (bob's style)
\r
224 if(style == STYLE_BOB)
\r
225 Build_Wedge(direction, vMin, vMax, TRUE);
\r
228 // Set First Step Starting Position
\r
229 vMax[2] = vMin[2] + stairHeight;
\r
230 SetInitialStairPos(direction, vMin, vMax, stairWidth);
\r
234 for(int i = 0; i < numSteps; i++)
\r
236 if(style == STYLE_BOB)
\r
237 Build_StairStep_Wedge(direction, vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, stairDlg.m_bDetail);
\r
238 else if(style == STYLE_ORIGINAL)
\r
239 Build_StairStep(vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, direction);
\r
241 // get step into next position
\r
242 MoveBlock(direction, vMin, vMax, stairWidth);
\r
243 vMax[2] += stairHeight;
\r
244 if(style == STYLE_BOB)
\r
245 vMin[2] += stairHeight; // wedge bottom must be raised
\r
251 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
\r
254 void DoorBuilder(vec3_t vMin, vec3_t vMax)
\r
256 // ensure we have something selected
\r
257 if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )
\r
259 MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);
\r
263 // tell Radiant we want to access the selected brushes
\r
264 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
\r
266 // get handle to size definition brush
\r
267 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);
\r
268 // cant release until we delete the brush, if we do...
\r
272 strcpy(doorDlg.m_fbTextureName.GetBuffer(256), g_FuncTable.m_pfnGetCurrentTexture());
\r
274 if(doorDlg.DoModal() == IDOK)
\r
276 g_FuncTable.m_pfnDeleteBrushHandle(brush);
\r
278 BuildDoorsX2(vMin, vMax,
\r
279 doorDlg.m_bSclMainHor, doorDlg.m_bSclMainVert,
\r
280 doorDlg.m_bSclTrimHor, doorDlg.m_bSclTrimVert,
\r
281 (LPCTSTR)doorDlg.m_fbTextureName,
\r
282 (LPCTSTR)doorDlg.m_trimTextureName,
\r
283 doorDlg.m_doorDirection);
\r
286 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
\r
293 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
\r
294 intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);
\r
296 world.LoadFromEntity(0, &intrInfoDlg->m_prog1);
\r
298 intrInfoDlg->DestroyWindow();
\r
300 CBrushCheckDialog* chkDlg = new CBrushCheckDialog();
\r
301 chkDlg->Create(IDD_BRUSHCHECKER_DIALOG);
\r
303 int count = world.FixBrushes(TRUE, &chkDlg->m_prog1);
\r
305 chkDlg->DestroyWindow();
\r
307 Sys_Printf("%i invalid/duplicate planes removed\n", count);
\r
313 autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED";
\r
315 if(autocaulkDlg.DoModal() == IDCANCEL)
\r
318 if(autocaulkDlg.m_nMode == MODE_AC_BUILD_MINI_PRT)
\r
320 BuildMiniPrt(&exclusionList);
\r
324 CAutoCaulkDialog* acDlg = new CAutoCaulkDialog;
\r
325 acDlg->Create(IDD_AUTOCAULK_DIALOG);
\r
327 char filename[1204];
\r
329 if(autocaulkDlg.m_nMode == MODE_AC_NORMAL)
\r
331 char* rad_filename = g_BSPTable.m_pfnGetMapName();
\r
334 MessageBox(NULL, "An Error Occurred While Trying To Get The Map Filename", "Error", MB_OK);
\r
335 acDlg->DestroyWindow();
\r
339 strcpy(filename, rad_filename);
\r
341 char* ext = strrchr(filename, '.')+1;
\r
342 strcpy(ext, "prt");// rename the extension
\r
346 IEpair* pEp = g_EpairTable.m_pfnIEpairForProjectKeys();
\r
347 char *pn = pEp->ValueForKey("mapspath");
\r
350 strcpy( filename, pn );
\r
351 strcat( filename, "/ac_prt.prt" );
\r
355 if(!portals.LoadFromPrt(filename, &acDlg->m_prog1))
\r
357 MessageBox(NULL, "Failed To Load Portal File", "Error", MB_OK);
\r
358 acDlg->DestroyWindow();
\r
361 // load portal file
\r
363 CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
\r
364 intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);
\r
368 world.LoadFromEntity(0, &intrInfoDlg->m_prog1);
\r
369 intrInfoDlg->DestroyWindow();
\r
371 if(autocaulkDlg.m_nMode == MODE_AC_NORMAL)
\r
372 world.RemoveNonCheckBrushes(&exclusionList, FALSE);
\r
374 world.RemoveNonCheckBrushes(&exclusionList, TRUE);
\r
376 world.ResetChecks(&exclusionList_Face);
\r
378 int caulkedCount = 0;
\r
379 int killCnt = world.AutoCaulk(&portals, autocaulkDlg.m_bAllowDestruction, &caulkedCount, &acDlg->m_prog2);
\r
381 if(autocaulkDlg.m_bAllowDestruction)
\r
382 Sys_Printf("%i unrequired brush(es) killed\n", killCnt);
\r
383 Sys_Printf("%i face(s) caulked\n", caulkedCount);
\r
385 acDlg->DestroyWindow();
\r
388 void ResetTextures()
\r
390 texRstDlg.m_TextureName = GetCurrentTexture();
\r
391 texRstDlg.m_NewTextureName = GetCurrentTexture();
\r
393 if(texRstDlg.DoModal() == IDCANCEL)
\r
398 fScale[1] = texRstDlg.m_fScaleVertical;
\r
399 fScale[0] = texRstDlg.m_fScaleHorizontal;
\r
401 fShift[1] = (float)texRstDlg.m_nShiftVertical;
\r
402 fShift[0] = (float)texRstDlg.m_nShiftHorizontal;
\r
405 world.LoadFromEntity(0, NULL);
\r
407 if(texRstDlg.m_bAllTextures)
\r
408 world.ResetTextures(NULL, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture);
\r
410 world.ResetTextures(texRstDlg.m_TextureName, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture);
\r
415 int ret = ppDlg.DoModal();
\r
416 if(ret == IDCANCEL)
\r
426 if( g_FuncTable.m_pfnSelectedBrushCount() != 1)
\r
428 MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);
\r
432 // tell Radiant we want to access the selected brushes
\r
433 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
\r
435 // get handle to size definition brush
\r
436 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);
\r
437 // cant release until we delete the brush, if we do...
\r
440 world.LoadEPairList(*g_FuncTable.m_pfnGetEntityKeyValList(brush->owner));
\r
442 DEPair* trigger_ep = world.FindEPairByKey("targetname");
\r
446 if(!strcmp(world.m_Classname, "trigger_push"))
\r
448 DEPair* target_ep = world.FindEPairByKey("target");
\r
451 entity_s* entTarget = FindEntityFromTargetname(target_ep->value);
\r
456 g_PathView = new DBobView;
\r
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);
\r
461 MessageBox(NULL, "trigger_push target could not be found.", "Error", MB_OK);
\r
464 MessageBox(NULL, "trigger_push has no target.", "Error", MB_OK);
\r
467 MessageBox(NULL, "You must select a 'trigger_push' entity.", "Error", MB_OK);
\r
470 MessageBox(NULL, "Entity must have a targetname", "Error", MB_OK);
\r
472 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
\r
475 void PitBuilder(vec3_t vMin, vec3_t vMax)
\r
477 // ensure we have something selected
\r
478 if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )
\r
480 MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);
\r
484 // tell Radiant we want to access the selected brushes
\r
485 g_FuncTable.m_pfnAllocateSelectedBrushHandles();
\r
487 // get handle to size definition brush
\r
488 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);
\r
489 // cant release until we delete the brush, if we do...
\r
493 if(pit.BuildPit(vMin, vMax))
\r
497 g_FuncTable.m_pfnDeleteBrushHandle(brush);
\r
500 MessageBox(NULL, "Failed To Make Pit\nTry Making The Brush Bigger", "Error", MB_OK);
\r
502 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
\r