-/*\r
-BobToolz plugin for GtkRadiant\r
-Copyright (C) 2001 Gordon Biggans\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
-*/\r
-\r
-#include "StdAfx.h"\r
-\r
-#include "funchandlers.h"\r
-\r
-#include "IntersectDialog.h"\r
-#include "PolygonDialog.h"\r
-#include "StairDialog.h"\r
-#include "DoorDialog.h"\r
-#include "IntersectInfoDialog.h"\r
-#include "BrushCheckDialog.h"\r
-#include "AutoCaulkDialog.h"\r
-#include "AutoCaulkStartDialog.h"\r
-#include "TextureResetDialog.h"\r
-#include "pathplotterdialog.h"\r
-\r
-#include "DEntity.h"\r
-#include "shapes.h"\r
-#include "lists.h"\r
-#include "misc.h"\r
-#include "DShape.h"\r
-\r
-// for autocaulk\r
-list<Str> exclusionList; // whole brush exclusion\r
-list<Str> exclusionList_Face; // single face exclusion\r
-\r
-BOOL el1Loaded;\r
-BOOL el2Loaded;\r
-\r
-DBobView* g_PathView = NULL;\r
-// -------------\r
-\r
-/************************\r
- Global Variables\r
-************************/\r
-\r
-CPolygonDialog polygonDlg;\r
-CIntersectDialog intrDlg;\r
-CStairDialog stairDlg;\r
-CDoorDialog doorDlg;\r
-CAutoCaulkStartDialog autocaulkDlg;\r
-CTextureResetDialog texRstDlg;\r
-CPathPlotterDialog ppDlg;\r
-\r
-/************************\r
- --Main Functions--\r
-************************/\r
-\r
-void LoadLists()\r
-{\r
- char buffer[256];\r
-\r
- if(!el1Loaded)\r
- el1Loaded = LoadExclusionList(GetFilename(buffer, "bt\\bt-el1.txt"), &exclusionList);\r
- if(!el2Loaded)\r
- el2Loaded = LoadExclusionList(GetFilename(buffer, "bt\\bt-el2.txt"), &exclusionList);\r
-}\r
-\r
-void PolygonBuilder(vec3_t vMin, vec3_t vMax)\r
-{\r
- // ensure we have something selected\r
- if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )\r
- {\r
- MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);\r
- return; \r
- }\r
-\r
- // tell Radiant we want to access the selected brushes\r
- g_FuncTable.m_pfnAllocateSelectedBrushHandles();\r
- \r
- // get handle to size definition brush\r
- brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);\r
- // cant release until we delete the brush, if we do...\r
-\r
- // ask user for type, size, etc....\r
- if(polygonDlg.DoModal() == IDOK)\r
- {\r
- DShape poly;\r
-\r
- g_FuncTable.m_pfnDeleteBrushHandle(brush);\r
-\r
- if(polygonDlg.m_bInverse)\r
- poly.BuildInversePrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop);\r
- else\r
- {\r
- if(polygonDlg.m_bBorder)\r
- poly.BuildBorderedPrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_nBorderSize, polygonDlg.m_bAlignTop);\r
- else\r
- poly.BuildRegularPrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop);\r
- }\r
-\r
- poly.Commit();\r
- }\r
-\r
-\r
- g_FuncTable.m_pfnReleaseSelectedBrushHandles();\r
-}\r
-\r
-\r
-void IntersectionFinder()\r
-{\r
- if(intrDlg.DoModal() == IDCANCEL)\r
- return;\r
-\r
- if(intrDlg.m_nBrushOptions == BRUSH_OPT_SELECTED)\r
- {\r
- // ensure we have enough brushes selected\r
- if( g_FuncTable.m_pfnSelectedBrushCount() < 2 )\r
- {\r
- MessageBox(NULL, "Invalid number of brushes selected, choose at least 2", "Error", MB_OK);\r
- return; \r
- }\r
- }\r
-\r
- CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();\r
- intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);\r
-\r
- DEntity world;\r
-\r
- switch(intrDlg.m_nBrushOptions)\r
- {\r
- case BRUSH_OPT_SELECTED:\r
- {\r
- world.LoadSelectedBrushes(&intrInfoDlg->m_prog1);\r
- break;\r
- }\r
- case BRUSH_OPT_WHOLE_MAP:\r
- {\r
- world.LoadFromEntity(0, &intrInfoDlg->m_prog1);\r
- break;\r
- }\r
- }\r
-\r
- world.RemoveNonCheckBrushes(&exclusionList, intrDlg.m_bUseDetail);\r
- BOOL* pbSelectList;\r
- if(intrDlg.m_bDuplicateOnly)\r
- pbSelectList = world.BuildDuplicateList();\r
- else\r
- pbSelectList = world.BuildIntersectList();\r
-\r
- world.SelectBrushes(pbSelectList);\r
- \r
- intrInfoDlg->DestroyWindow();\r
- delete[] pbSelectList;\r
-}\r
-\r
-void StairBuilder(vec3_t vMin, vec3_t vMax)\r
-{\r
- // ensure we have something selected\r
- if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )\r
- {\r
- MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);\r
- return; \r
- }\r
-\r
- // tell Radiant we want to access the selected brushes\r
- g_FuncTable.m_pfnAllocateSelectedBrushHandles();\r
- \r
- // get handle to size definition brush\r
- brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);\r
- // cant release until we delete the brush, if we do...\r
-\r
-\r
- // ask user for type, size, etc....\r
- if(stairDlg.DoModal() == IDOK)\r
- {\r
- \r
- // calc brush size\r
- vec3_t size;\r
- _VectorSubtract(vMax, vMin, size);\r
-\r
-\r
- if(((int)size[2] % stairDlg.m_nStairHeight) != 0)\r
- {\r
- // stairs must fit evenly into brush\r
- MessageBox(NULL, "Invalid stair height\nHeight of block must be divisable by stair height", "Error", MB_OK);\r
- }\r
- else\r
- {\r
- \r
- // Remove Size Brush\r
- g_FuncTable.m_pfnDeleteBrushHandle(brush);\r
-\r
- \r
- // Get Step Count, Direction of Stairs, Stair Style\r
- int numSteps = (int)size[2] / stairDlg.m_nStairHeight;\r
- int direction = stairDlg.m_StairDir;\r
- int style = stairDlg.m_StairStyle;\r
-\r
- if(stairDlg.m_StairStyle == STYLE_CORNER)\r
- {\r
- BuildCornerStairs(vMin, vMax, numSteps, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture);\r
- }\r
- else\r
- {\r
- // Get Step Dimensions\r
- float stairHeight = (float)stairDlg.m_nStairHeight;\r
- float stairWidth;\r
- if((direction == MOVE_EAST) || (direction == MOVE_WEST))\r
- stairWidth = (size[0])/numSteps;\r
- else\r
- stairWidth = (size[1])/numSteps;\r
-\r
-\r
- // Build Base For Stair (bob's style)\r
- if(style == STYLE_BOB)\r
- Build_Wedge(direction, vMin, vMax, TRUE);\r
-\r
-\r
- // Set First Step Starting Position\r
- vMax[2] = vMin[2] + stairHeight;\r
- SetInitialStairPos(direction, vMin, vMax, stairWidth);\r
-\r
-\r
- // Build The Steps\r
- for(int i = 0; i < numSteps; i++)\r
- {\r
- if(style == STYLE_BOB)\r
- Build_StairStep_Wedge(direction, vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, stairDlg.m_bDetail);\r
- else if(style == STYLE_ORIGINAL)\r
- Build_StairStep(vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, direction);\r
-\r
- // get step into next position\r
- MoveBlock(direction, vMin, vMax, stairWidth);\r
- vMax[2] += stairHeight;\r
- if(style == STYLE_BOB)\r
- vMin[2] += stairHeight; // wedge bottom must be raised\r
- }\r
- }\r
- }\r
- }\r
-\r
- g_FuncTable.m_pfnReleaseSelectedBrushHandles();\r
-}\r
-\r
-void DoorBuilder(vec3_t vMin, vec3_t vMax)\r
-{\r
- // ensure we have something selected\r
- if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )\r
- {\r
- MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);\r
- return; \r
- }\r
-\r
- // tell Radiant we want to access the selected brushes\r
- g_FuncTable.m_pfnAllocateSelectedBrushHandles();\r
- \r
- // get handle to size definition brush\r
- brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);\r
- // cant release until we delete the brush, if we do...\r
-\r
-\r
-\r
- strcpy(doorDlg.m_fbTextureName.GetBuffer(256), g_FuncTable.m_pfnGetCurrentTexture());\r
- \r
- if(doorDlg.DoModal() == IDOK)\r
- {\r
- g_FuncTable.m_pfnDeleteBrushHandle(brush);\r
-\r
- BuildDoorsX2(vMin, vMax, \r
- doorDlg.m_bSclMainHor, doorDlg.m_bSclMainVert,\r
- doorDlg.m_bSclTrimHor, doorDlg.m_bSclTrimVert,\r
- (LPCTSTR)doorDlg.m_fbTextureName, \r
- (LPCTSTR)doorDlg.m_trimTextureName,\r
- doorDlg.m_doorDirection);\r
- }\r
-\r
- g_FuncTable.m_pfnReleaseSelectedBrushHandles();\r
-}\r
-\r
-void FixBrushes()\r
-{\r
- DEntity world;\r
-\r
- CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();\r
- intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);\r
-\r
- world.LoadFromEntity(0, &intrInfoDlg->m_prog1);\r
-\r
- intrInfoDlg->DestroyWindow();\r
- \r
- CBrushCheckDialog* chkDlg = new CBrushCheckDialog();\r
- chkDlg->Create(IDD_BRUSHCHECKER_DIALOG);\r
-\r
- int count = world.FixBrushes(TRUE, &chkDlg->m_prog1);\r
-\r
- chkDlg->DestroyWindow();\r
-\r
- Sys_Printf("%i invalid/duplicate planes removed\n", count);\r
-}\r
-\r
-void AutoCaulk()\r
-{\r
- if(!el1Loaded)\r
- autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED";\r
-\r
- if(autocaulkDlg.DoModal() == IDCANCEL)\r
- return;\r
-\r
- if(autocaulkDlg.m_nMode == MODE_AC_BUILD_MINI_PRT)\r
- {\r
- BuildMiniPrt(&exclusionList);\r
- return;\r
- }\r
-\r
- CAutoCaulkDialog* acDlg = new CAutoCaulkDialog;\r
- acDlg->Create(IDD_AUTOCAULK_DIALOG);\r
-\r
- char filename[1204];\r
-\r
- if(autocaulkDlg.m_nMode == MODE_AC_NORMAL)\r
- {\r
- char* rad_filename = g_BSPTable.m_pfnGetMapName();\r
- if(!rad_filename)\r
- {\r
- MessageBox(NULL, "An Error Occurred While Trying To Get The Map Filename", "Error", MB_OK);\r
- acDlg->DestroyWindow();\r
- return;\r
- }\r
-\r
- strcpy(filename, rad_filename);\r
- \r
- char* ext = strrchr(filename, '.')+1;\r
- strcpy(ext, "prt");// rename the extension\r
- }\r
- else\r
- {\r
- IEpair* pEp = g_EpairTable.m_pfnIEpairForProjectKeys();\r
- char *pn = pEp->ValueForKey("mapspath");\r
- pEp->DecRef();\r
-\r
- strcpy( filename, pn );\r
- strcat( filename, "/ac_prt.prt" );\r
- }\r
-\r
- DEntity portals;\r
- if(!portals.LoadFromPrt(filename, &acDlg->m_prog1))\r
- {\r
- MessageBox(NULL, "Failed To Load Portal File", "Error", MB_OK);\r
- acDlg->DestroyWindow();\r
- return;\r
- }\r
- // load portal file\r
-\r
- CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();\r
- intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG);\r
-\r
- DEntity world;\r
-\r
- world.LoadFromEntity(0, &intrInfoDlg->m_prog1);\r
- intrInfoDlg->DestroyWindow();\r
-\r
- if(autocaulkDlg.m_nMode == MODE_AC_NORMAL)\r
- world.RemoveNonCheckBrushes(&exclusionList, FALSE);\r
- else\r
- world.RemoveNonCheckBrushes(&exclusionList, TRUE);\r
-\r
- world.ResetChecks(&exclusionList_Face);\r
-\r
- int caulkedCount = 0;\r
- int killCnt = world.AutoCaulk(&portals, autocaulkDlg.m_bAllowDestruction, &caulkedCount, &acDlg->m_prog2);\r
-\r
- if(autocaulkDlg.m_bAllowDestruction)\r
- Sys_Printf("%i unrequired brush(es) killed\n", killCnt);\r
- Sys_Printf("%i face(s) caulked\n", caulkedCount);\r
-\r
- acDlg->DestroyWindow();\r
-}\r
-\r
-void ResetTextures()\r
-{\r
- texRstDlg.m_TextureName = GetCurrentTexture();\r
- texRstDlg.m_NewTextureName = GetCurrentTexture();\r
-\r
- if(texRstDlg.DoModal() == IDCANCEL)\r
- return;\r
-\r
- float fScale[2];\r
- float fShift[2];\r
- fScale[1] = texRstDlg.m_fScaleVertical;\r
- fScale[0] = texRstDlg.m_fScaleHorizontal;\r
-\r
- fShift[1] = (float)texRstDlg.m_nShiftVertical;\r
- fShift[0] = (float)texRstDlg.m_nShiftHorizontal;\r
-\r
- DEntity world;\r
- world.LoadFromEntity(0, NULL);\r
-\r
- if(texRstDlg.m_bAllTextures)\r
- world.ResetTextures(NULL, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture);\r
- else \r
- world.ResetTextures(texRstDlg.m_TextureName, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture);\r
-}\r
-\r
-void PathPlotter()\r
-{\r
- int ret = ppDlg.DoModal();\r
- if(ret == IDCANCEL)\r
- return;\r
- if(ret == IDNO)\r
- {\r
- if(g_PathView)\r
- delete g_PathView;\r
-\r
- return;\r
- }\r
-\r
- if( g_FuncTable.m_pfnSelectedBrushCount() != 1)\r
- {\r
- MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);\r
- return;\r
- }\r
-\r
- // tell Radiant we want to access the selected brushes\r
- g_FuncTable.m_pfnAllocateSelectedBrushHandles();\r
- \r
- // get handle to size definition brush\r
- brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);\r
- // cant release until we delete the brush, if we do...\r
-\r
- DEntity world;\r
- world.LoadEPairList(*g_FuncTable.m_pfnGetEntityKeyValList(brush->owner));\r
-\r
- DEPair* trigger_ep = world.FindEPairByKey("targetname");\r
-\r
- if(trigger_ep)\r
- {\r
- if(!strcmp(world.m_Classname, "trigger_push"))\r
- {\r
- DEPair* target_ep = world.FindEPairByKey("target");\r
- if(target_ep)\r
- {\r
- entity_s* entTarget = FindEntityFromTargetname(target_ep->value);\r
- if(entTarget)\r
- {\r
- if(g_PathView)\r
- delete g_PathView;\r
- g_PathView = new DBobView;\r
-\r
- 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
- }\r
- else\r
- MessageBox(NULL, "trigger_push target could not be found.", "Error", MB_OK);\r
- }\r
- else\r
- MessageBox(NULL, "trigger_push has no target.", "Error", MB_OK);\r
- }\r
- else\r
- MessageBox(NULL, "You must select a 'trigger_push' entity.", "Error", MB_OK);\r
- } \r
- else\r
- MessageBox(NULL, "Entity must have a targetname", "Error", MB_OK);\r
-\r
- g_FuncTable.m_pfnReleaseSelectedBrushHandles();\r
-}\r
-\r
-void PitBuilder(vec3_t vMin, vec3_t vMax)\r
-{\r
- // ensure we have something selected\r
- if( g_FuncTable.m_pfnSelectedBrushCount() != 1 )\r
- {\r
- MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK);\r
- return; \r
- }\r
-\r
- // tell Radiant we want to access the selected brushes\r
- g_FuncTable.m_pfnAllocateSelectedBrushHandles();\r
- \r
- // get handle to size definition brush\r
- brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(0);\r
- // cant release until we delete the brush, if we do...\r
-\r
- DShape pit;\r
-\r
- if(pit.BuildPit(vMin, vMax))\r
- {\r
- pit.Commit();\r
-\r
- g_FuncTable.m_pfnDeleteBrushHandle(brush);\r
- }\r
- else\r
- MessageBox(NULL, "Failed To Make Pit\nTry Making The Brush Bigger", "Error", MB_OK);\r
-\r
- g_FuncTable.m_pfnReleaseSelectedBrushHandles();\r
-}\r
+/*
+ BobToolz plugin for GtkRadiant
+ Copyright (C) 2001 Gordon Biggans
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "StdAfx.h"
+
+#include "funchandlers.h"
+
+#include "IntersectDialog.h"
+#include "PolygonDialog.h"
+#include "StairDialog.h"
+#include "DoorDialog.h"
+#include "IntersectInfoDialog.h"
+#include "BrushCheckDialog.h"
+#include "AutoCaulkDialog.h"
+#include "AutoCaulkStartDialog.h"
+#include "TextureResetDialog.h"
+#include "pathplotterdialog.h"
+
+#include "DEntity.h"
+#include "shapes.h"
+#include "lists.h"
+#include "misc.h"
+#include "DShape.h"
+
+// for autocaulk
+list<Str> exclusionList; // whole brush exclusion
+list<Str> exclusionList_Face; // single face exclusion
+
+BOOL el1Loaded;
+BOOL el2Loaded;
+
+DBobView* g_PathView = NULL;
+// -------------
+
+/************************
+ Global Variables
+************************/
+
+CPolygonDialog polygonDlg;
+CIntersectDialog intrDlg;
+CStairDialog stairDlg;
+CDoorDialog doorDlg;
+CAutoCaulkStartDialog autocaulkDlg;
+CTextureResetDialog texRstDlg;
+CPathPlotterDialog ppDlg;
+
+/************************
+ --Main Functions--
+************************/
+
+void LoadLists(){
+ char buffer[256];
+
+ if ( !el1Loaded ) {
+ el1Loaded = LoadExclusionList( GetFilename( buffer, "bt\\bt-el1.txt" ), &exclusionList );
+ }
+ if ( !el2Loaded ) {
+ el2Loaded = LoadExclusionList( GetFilename( buffer, "bt\\bt-el2.txt" ), &exclusionList );
+ }
+}
+
+void PolygonBuilder( vec3_t vMin, vec3_t vMax ){
+ // ensure we have something selected
+ if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
+ MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
+ return;
+ }
+
+ // tell Radiant we want to access the selected brushes
+ g_FuncTable.m_pfnAllocateSelectedBrushHandles();
+
+ // get handle to size definition brush
+ brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
+ // cant release until we delete the brush, if we do...
+
+ // ask user for type, size, etc....
+ if ( polygonDlg.DoModal() == IDOK ) {
+ DShape poly;
+
+ g_FuncTable.m_pfnDeleteBrushHandle( brush );
+
+ if ( polygonDlg.m_bInverse ) {
+ poly.BuildInversePrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop );
+ }
+ else
+ {
+ if ( polygonDlg.m_bBorder ) {
+ poly.BuildBorderedPrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_nBorderSize, polygonDlg.m_bAlignTop );
+ }
+ else{
+ poly.BuildRegularPrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop );
+ }
+ }
+
+ poly.Commit();
+ }
+
+
+ g_FuncTable.m_pfnReleaseSelectedBrushHandles();
+}
+
+
+void IntersectionFinder(){
+ if ( intrDlg.DoModal() == IDCANCEL ) {
+ return;
+ }
+
+ if ( intrDlg.m_nBrushOptions == BRUSH_OPT_SELECTED ) {
+ // ensure we have enough brushes selected
+ if ( g_FuncTable.m_pfnSelectedBrushCount() < 2 ) {
+ MessageBox( NULL, "Invalid number of brushes selected, choose at least 2", "Error", MB_OK );
+ return;
+ }
+ }
+
+ CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
+ intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG );
+
+ DEntity world;
+
+ switch ( intrDlg.m_nBrushOptions )
+ {
+ case BRUSH_OPT_SELECTED:
+ {
+ world.LoadSelectedBrushes( &intrInfoDlg->m_prog1 );
+ break;
+ }
+ case BRUSH_OPT_WHOLE_MAP:
+ {
+ world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 );
+ break;
+ }
+ }
+
+ world.RemoveNonCheckBrushes( &exclusionList, intrDlg.m_bUseDetail );
+ BOOL* pbSelectList;
+ if ( intrDlg.m_bDuplicateOnly ) {
+ pbSelectList = world.BuildDuplicateList();
+ }
+ else{
+ pbSelectList = world.BuildIntersectList();
+ }
+
+ world.SelectBrushes( pbSelectList );
+
+ intrInfoDlg->DestroyWindow();
+ delete[] pbSelectList;
+}
+
+void StairBuilder( vec3_t vMin, vec3_t vMax ){
+ // ensure we have something selected
+ if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
+ MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
+ return;
+ }
+
+ // tell Radiant we want to access the selected brushes
+ g_FuncTable.m_pfnAllocateSelectedBrushHandles();
+
+ // get handle to size definition brush
+ brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
+ // cant release until we delete the brush, if we do...
+
+
+ // ask user for type, size, etc....
+ if ( stairDlg.DoModal() == IDOK ) {
+
+ // calc brush size
+ vec3_t size;
+ _VectorSubtract( vMax, vMin, size );
+
+
+ if ( ( (int)size[2] % stairDlg.m_nStairHeight ) != 0 ) {
+ // stairs must fit evenly into brush
+ MessageBox( NULL, "Invalid stair height\nHeight of block must be divisable by stair height", "Error", MB_OK );
+ }
+ else
+ {
+
+ // Remove Size Brush
+ g_FuncTable.m_pfnDeleteBrushHandle( brush );
+
+
+ // Get Step Count, Direction of Stairs, Stair Style
+ int numSteps = (int)size[2] / stairDlg.m_nStairHeight;
+ int direction = stairDlg.m_StairDir;
+ int style = stairDlg.m_StairStyle;
+
+ if ( stairDlg.m_StairStyle == STYLE_CORNER ) {
+ BuildCornerStairs( vMin, vMax, numSteps, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture );
+ }
+ else
+ {
+ // Get Step Dimensions
+ float stairHeight = (float)stairDlg.m_nStairHeight;
+ float stairWidth;
+ if ( ( direction == MOVE_EAST ) || ( direction == MOVE_WEST ) ) {
+ stairWidth = ( size[0] ) / numSteps;
+ }
+ else{
+ stairWidth = ( size[1] ) / numSteps;
+ }
+
+
+ // Build Base For Stair (bob's style)
+ if ( style == STYLE_BOB ) {
+ Build_Wedge( direction, vMin, vMax, TRUE );
+ }
+
+
+ // Set First Step Starting Position
+ vMax[2] = vMin[2] + stairHeight;
+ SetInitialStairPos( direction, vMin, vMax, stairWidth );
+
+
+ // Build The Steps
+ for ( int i = 0; i < numSteps; i++ )
+ {
+ if ( style == STYLE_BOB ) {
+ Build_StairStep_Wedge( direction, vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, stairDlg.m_bDetail );
+ }
+ else if ( style == STYLE_ORIGINAL ) {
+ Build_StairStep( vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, direction );
+ }
+
+ // get step into next position
+ MoveBlock( direction, vMin, vMax, stairWidth );
+ vMax[2] += stairHeight;
+ if ( style == STYLE_BOB ) {
+ vMin[2] += stairHeight; // wedge bottom must be raised
+ }
+ }
+ }
+ }
+ }
+
+ g_FuncTable.m_pfnReleaseSelectedBrushHandles();
+}
+
+void DoorBuilder( vec3_t vMin, vec3_t vMax ){
+ // ensure we have something selected
+ if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
+ MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
+ return;
+ }
+
+ // tell Radiant we want to access the selected brushes
+ g_FuncTable.m_pfnAllocateSelectedBrushHandles();
+
+ // get handle to size definition brush
+ brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
+ // cant release until we delete the brush, if we do...
+
+
+
+ strcpy( doorDlg.m_fbTextureName.GetBuffer( 256 ), g_FuncTable.m_pfnGetCurrentTexture() );
+
+ if ( doorDlg.DoModal() == IDOK ) {
+ g_FuncTable.m_pfnDeleteBrushHandle( brush );
+
+ BuildDoorsX2( vMin, vMax,
+ doorDlg.m_bSclMainHor, doorDlg.m_bSclMainVert,
+ doorDlg.m_bSclTrimHor, doorDlg.m_bSclTrimVert,
+ (LPCTSTR)doorDlg.m_fbTextureName,
+ (LPCTSTR)doorDlg.m_trimTextureName,
+ doorDlg.m_doorDirection );
+ }
+
+ g_FuncTable.m_pfnReleaseSelectedBrushHandles();
+}
+
+void FixBrushes(){
+ DEntity world;
+
+ CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
+ intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG );
+
+ world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 );
+
+ intrInfoDlg->DestroyWindow();
+
+ CBrushCheckDialog* chkDlg = new CBrushCheckDialog();
+ chkDlg->Create( IDD_BRUSHCHECKER_DIALOG );
+
+ int count = world.FixBrushes( TRUE, &chkDlg->m_prog1 );
+
+ chkDlg->DestroyWindow();
+
+ Sys_Printf( "%i invalid/duplicate planes removed\n", count );
+}
+
+void AutoCaulk(){
+ if ( !el1Loaded ) {
+ autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED";
+ }
+
+ if ( autocaulkDlg.DoModal() == IDCANCEL ) {
+ return;
+ }
+
+ if ( autocaulkDlg.m_nMode == MODE_AC_BUILD_MINI_PRT ) {
+ BuildMiniPrt( &exclusionList );
+ return;
+ }
+
+ CAutoCaulkDialog* acDlg = new CAutoCaulkDialog;
+ acDlg->Create( IDD_AUTOCAULK_DIALOG );
+
+ char filename[1204];
+
+ if ( autocaulkDlg.m_nMode == MODE_AC_NORMAL ) {
+ char* rad_filename = g_BSPTable.m_pfnGetMapName();
+ if ( !rad_filename ) {
+ MessageBox( NULL, "An Error Occurred While Trying To Get The Map Filename", "Error", MB_OK );
+ acDlg->DestroyWindow();
+ return;
+ }
+
+ strcpy( filename, rad_filename );
+
+ char* ext = strrchr( filename, '.' ) + 1;
+ strcpy( ext, "prt" ); // rename the extension
+ }
+ else
+ {
+ IEpair* pEp = g_EpairTable.m_pfnIEpairForProjectKeys();
+ char *pn = pEp->ValueForKey( "mapspath" );
+ pEp->DecRef();
+
+ strcpy( filename, pn );
+ strcat( filename, "/ac_prt.prt" );
+ }
+
+ DEntity portals;
+ if ( !portals.LoadFromPrt( filename, &acDlg->m_prog1 ) ) {
+ MessageBox( NULL, "Failed To Load Portal File", "Error", MB_OK );
+ acDlg->DestroyWindow();
+ return;
+ }
+ // load portal file
+
+ CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog();
+ intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG );
+
+ DEntity world;
+
+ world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 );
+ intrInfoDlg->DestroyWindow();
+
+ if ( autocaulkDlg.m_nMode == MODE_AC_NORMAL ) {
+ world.RemoveNonCheckBrushes( &exclusionList, FALSE );
+ }
+ else{
+ world.RemoveNonCheckBrushes( &exclusionList, TRUE );
+ }
+
+ world.ResetChecks( &exclusionList_Face );
+
+ int caulkedCount = 0;
+ int killCnt = world.AutoCaulk( &portals, autocaulkDlg.m_bAllowDestruction, &caulkedCount, &acDlg->m_prog2 );
+
+ if ( autocaulkDlg.m_bAllowDestruction ) {
+ Sys_Printf( "%i unrequired brush(es) killed\n", killCnt );
+ }
+ Sys_Printf( "%i face(s) caulked\n", caulkedCount );
+
+ acDlg->DestroyWindow();
+}
+
+void ResetTextures(){
+ texRstDlg.m_TextureName = GetCurrentTexture();
+ texRstDlg.m_NewTextureName = GetCurrentTexture();
+
+ if ( texRstDlg.DoModal() == IDCANCEL ) {
+ return;
+ }
+
+ float fScale[2];
+ float fShift[2];
+ fScale[1] = texRstDlg.m_fScaleVertical;
+ fScale[0] = texRstDlg.m_fScaleHorizontal;
+
+ fShift[1] = (float)texRstDlg.m_nShiftVertical;
+ fShift[0] = (float)texRstDlg.m_nShiftHorizontal;
+
+ DEntity world;
+ world.LoadFromEntity( 0, NULL );
+
+ if ( texRstDlg.m_bAllTextures ) {
+ world.ResetTextures( NULL, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture );
+ }
+ else{
+ world.ResetTextures( texRstDlg.m_TextureName, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture );
+ }
+}
+
+void PathPlotter(){
+ int ret = ppDlg.DoModal();
+ if ( ret == IDCANCEL ) {
+ return;
+ }
+ if ( ret == IDNO ) {
+ if ( g_PathView ) {
+ delete g_PathView;
+ }
+
+ return;
+ }
+
+ if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
+ MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
+ return;
+ }
+
+ // tell Radiant we want to access the selected brushes
+ g_FuncTable.m_pfnAllocateSelectedBrushHandles();
+
+ // get handle to size definition brush
+ brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
+ // cant release until we delete the brush, if we do...
+
+ DEntity world;
+ world.LoadEPairList( *g_FuncTable.m_pfnGetEntityKeyValList( brush->owner ) );
+
+ DEPair* trigger_ep = world.FindEPairByKey( "targetname" );
+
+ if ( trigger_ep ) {
+ if ( !strcmp( world.m_Classname, "trigger_push" ) ) {
+ DEPair* target_ep = world.FindEPairByKey( "target" );
+ if ( target_ep ) {
+ entity_s* entTarget = FindEntityFromTargetname( target_ep->value );
+ if ( entTarget ) {
+ if ( g_PathView ) {
+ delete g_PathView;
+ }
+ g_PathView = new DBobView;
+
+ g_PathView->Begin( trigger_ep->value, target_ep->value, ppDlg.m_fMultiplier, ppDlg.m_nPoints, ppDlg.m_fGravity, ppDlg.m_bNoUpdate, ppDlg.m_bShowExtra );
+ }
+ else{
+ MessageBox( NULL, "trigger_push target could not be found.", "Error", MB_OK );
+ }
+ }
+ else{
+ MessageBox( NULL, "trigger_push has no target.", "Error", MB_OK );
+ }
+ }
+ else{
+ MessageBox( NULL, "You must select a 'trigger_push' entity.", "Error", MB_OK );
+ }
+ }
+ else{
+ MessageBox( NULL, "Entity must have a targetname", "Error", MB_OK );
+ }
+
+ g_FuncTable.m_pfnReleaseSelectedBrushHandles();
+}
+
+void PitBuilder( vec3_t vMin, vec3_t vMax ){
+ // ensure we have something selected
+ if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) {
+ MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK );
+ return;
+ }
+
+ // tell Radiant we want to access the selected brushes
+ g_FuncTable.m_pfnAllocateSelectedBrushHandles();
+
+ // get handle to size definition brush
+ brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
+ // cant release until we delete the brush, if we do...
+
+ DShape pit;
+
+ if ( pit.BuildPit( vMin, vMax ) ) {
+ pit.Commit();
+
+ g_FuncTable.m_pfnDeleteBrushHandle( brush );
+ }
+ else{
+ MessageBox( NULL, "Failed To Make Pit\nTry Making The Brush Bigger", "Error", MB_OK );
+ }
+
+ g_FuncTable.m_pfnReleaseSelectedBrushHandles();
+}