Files
gtav-src/tools_ng/wildwest/script/3dsMax/General_tools/Collision/collset.ms
T
2025-09-29 00:52:08 +02:00

1590 lines
51 KiB
Plaintext
Executable File

--
-- Description:: Rockstar Collision Set
-- Utility for setting collision attributes by the collision type
-- Rockstar North
-- 13/10/2006
-- by Greg Smith
-----------------------------------------------------------------------------
-- Uses
-----------------------------------------------------------------------------
filein "rockstar/export/settings.ms"
fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/General_tools/Collision/ProcPainter_Funcs.ms")
fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/General_tools/Collision/Collision_FromTexture.ms")
fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/General_tools/Collision/NavPaths_LoadFuncs.ms")
RSTA_LoadCommonFunction #("fn_RSTA_vertexColours.ms")
-----------------------------------------------------------------------------
-- Rollout
-----------------------------------------------------------------------------
try (destroyDialog RsCollisionSetRoll) catch ()
try (destroyDialog collSet_showBmpRoll) catch ()
-- Predefine rollout-name:
global collSet_showBmpRoll
-- Set default vert/face-count limits, if they're not available from labelled tool-scripts yet:
if (RsMaxCollVerts == undefined) do
(
global RsMaxCollVerts = 32768
global RsMaxCollFaces = 100000
)
rollout RsCollisionSetRoll "Collision Setter" width:430 height:570
(
dotNetControl RsBannerPanel "Panel" pos:[0,0] height:32 width:RsCollisionSetRoll.width
local bannerStruct = makeRsBanner dn_Panel:RsBannerPanel wiki:"Collision_Set" versionNum:1.43 versionName:"Wary Ham"
local progressContinue = true
-- We will question user's intentions to regenerate collision on a late-stage project:
local MatureProjWarn = (matchPattern (RsConfigGetProjectName()) pattern:"gta5*")
local collCatItems = #()
local selectedSurface
-- Texmap-descriptors for current name-list:
local TexInfos = #()
local ShownTexInfos = #()
label lblTexture "" across:3 align:#left
label lblSurface "Select Surface Type:" offset:[88,0]
listbox LstTextures pos:[10, lblTexture.pos.Y + 18] width:235 height:16 align:#center
dropDownList lstCategories "" pos:(LstTextures.pos + [240,0]) width:170
listbox lstSurfaces pos:(lstCategories.pos + [0, 26]) width:lstCategories.width height:14 align:#center
label lblSetUnset "List Textures:" across:4 align:#Left
checkbox chkSetTexs "Set" align:#Left offset:[-30,-1] checked:True
checkbox chkUnsetTexs "Unset" align:#Left offset:[-90,-1] checked:True
label lblStatus "" width:218 align:#Right
checkButton btnEditLock "[ ALLOW EDITS ]" width:220 align:#right -- Editing is turned off by default
button BtnReassignCollMats "Reassign Collision-Mats For Selected" width:220 align:#right offset:[0,-4] \
Tooltip:"Reassign materials for selected object's collision-meshes, based on object's texturemaps"
button BtnCreateCollObjs "Create Collision For Selected" width:220 align:#right offset:[0,-2] \
Tooltip:"Generate collision-mesh for selected objects, with collision-materials based on object's texturemaps"
checkButton BtnCreateForFaces "Just for Sel. Faces" width:110 align:#left offset:[BtnCreateCollObjs.Pos.X - 13,-5] across:2 \
Tooltip:"On Create Collision, just generate new collision for selected faces"
checkButton BtnAddDeepness "Push DEEP Faces" width:110 align:#right offset:[0,-5] Checked:False \
Tooltip:"On Create Collision, push down verts for collision-faces that have \"*DEEP*\" surfacetypes"
checkButton btnToggleGlobal "Toggle Global" width:220 enabled:true align:#right offset:[0,-2] \
Tooltip:"Toggles whether or not selected surface-assignment is stored to global.xml"
button btnDeleteDef "Remove this definition" width:220 enabled:true align:#right offset:[0,-4] \
Tooltip:"Remove selected surface-assignment from shown xml-file"
button btnGetFolder "Get Tex List From Folder" width:220 align:#right offset:[0,-4] \
Tooltip:"Show list of textures from a given folder.\nThis allows you to assign surfacetypes to textures that aren't on selected objects."
button btnSnapPivot "Snap Pivots of Selected to Parent" width:220 align:#right offset:[0,-4]
imgTag bmpUi "" width:178 height:178 tooltip:"Double-click to show full-size texture" pos:[13, btnEditLock.pos.y]
groupBox grpFlags "RexBounds Values:" width:400 height:144
checkbox chkStairs "Stairs" pos:(grpFlags.pos + [10, 20]) tooltip:"Stairs"
checkbox chkClimable "Non Climable" pos:(grpFlags.pos + [140, 20]) tooltip:"Non Climable"
checkbox chkSeeThrough "See Through" pos:(grpFlags.pos + [230, 20]) tooltip:"See Through"
checkbox chkShootThrough "Shoot Through" pos:(grpFlags.pos + [10, 40]) tooltip:"Shoot Through"
checkbox chkShootThroughFX "Shoot Through FX" pos:(grpFlags.pos + [10, 40]) tooltip:"Shoot Through FX"
checkbox chkPath "Path" pos:(grpFlags.pos + [140, 40]) tooltip:"Path"
checkbox chkSetPedPop "Set Ped Density" pos:(grpFlags.pos + [230, 40]) tooltip:"Ped population"
spinner spnPedDensity range:[0,7,0] pos:(chkSetPedPop.pos + [105, 0]) width:50 type:#integer
checkbox chkCamera "Non Camera Collidable" pos:(grpFlags.pos + [10, 60]) tooltip:"Non Camera Collide"
checkbox chkCover "Doesn't Provide Cover" pos:(grpFlags.pos + [230, 60]) tooltip:"Doesn't Provide Cover"
checkbox chkProcCullImmune "Proc Cull Immune" pos:(grpFlags.pos + [10, 80]) tooltip:"Faces are ignored by procedural-cull"
checkbox chkRoadRoad "Road - Road" pos:(grpFlags.pos + [10, 100]) tooltip:"Road - Road"
checkbox chkRoadPath "Road - Path" pos:(grpFlags.pos + [140, 100]) tooltip:"Road - Path"
checkbox chkRoadTrail "Road - Trail" pos:(grpFlags.pos + [230, 100]) tooltip:"Road - Trail"
checkbox chkNotHorseWalkable "Not Horse Walkable" pos:(grpFlags.pos + [10, 120]) tooltip:"Not Horse Walkable"
groupBox grpPreserve "Preserve UV-channels on 'Reassign Collision':" pos:(grpFlags.pos + [0, grpFlags.height + 2]) width:grpFlags.width height:42
checkbox chkPreserve11 "11: Proc Tint" checked:false pos:(grpPreserve.pos + [10, 17]) enabled:grpPreserve.enabled \
tooltip:"Clear collision's Procedural Tint channel on reassign?\n\n(All other channels are cleared)"
checkbox chkPreserve12 "12: Proc Scaling/Density" checked:false pos:(chkPreserve11.pos + [84, 0]) enabled:grpPreserve.enabled \
tooltip:"Clear collision's Procedural Scaling/Density channel on reassign?\n\n(All other channels are cleared)"
local preserveCtrls = #(grpPreserve, chkPreserve11, chkPreserve12)
progressBar totalProgBar "" offset:[0,12] width:grpFlags.width
progressBar subProgBar "" offset:[0,-4] width:grpFlags.width
label lblProgStatus "" width:RsCollisionSetRoll.width align:#left offset:[0,-4]
-- These listed controls are only enabled if 'ALLOW EDITS' is active.
-- 'RexControls' also needs a non-blank 'Surface Type' to be selected (i.e. textures need a surfacetype before they're allowed flags)
local EditControls = #(lstCategories, lstSurfaces, btnToggleGlobal, btnDeleteDef)
local RexControls = #(chkStairs, chkClimable, chkSeeThrough, chkShootThrough, chkShootThroughFX, chkPath, chkCover, chkCamera, chkSetPedPop, spnPedDensity, chkProcCullImmune, chkRoadRoad, chkRoadPath, chkRoadTrail, chkNotHorseWalkable)
--////////////////////////////////////////////////////////////
-- methods
--////////////////////////////////////////////////////////////
-- Enables 'RexBounds Values' controls if 'ALLOW EDITS' is active, and a valid/non-blank Surface Type is selected:
fn SetRexCtrlsEnabled =
(
RexControls.Enabled = (BtnEditLock.Checked and (LstSurfaces.Selection != 0) and (LstSurfaces.Selected != RsBlankCollName))
)
-- Returns texmap-descriptor associated with selected texture-list item:
fn GetSelTexInfo =
(
local SelNum = LstTextures.Selection
if (SelNum == 0) then (return undefined) else (return ShownTexInfos[SelNum])
)
-- Build flags-integer from 'RexBounds Values' checkboxes:
fn GetFlagsUI =
(
local flagNames = #()
if chkStairs.checked do (append flagNames "Stairs")
if chkClimable.checked do (append flagNames "Non Climbable")
if chkSeeThrough.checked do (append flagNames "See Through")
if chkShootThrough.checked do (append flagNames "Shoot Through")
if chkShootThroughFX.checked do (append flagNames "Shoot Through FX")
if chkPath.checked do (append flagNames "Path")
if chkCover.checked do (append flagNames "Does Not Provide Cover")
if chkCamera.checked do (append flagNames "Non Camera Collidable")
if chkSetPedPop.checked do (append flagNames "Reserved for Tools")
if chkRoadRoad.checked do (append flagNames "Road - Road")
if chkRoadPath.checked do (append flagNames "Road - Path")
if chkRoadTrail.checked do (append flagNames "Road - Trail")
if chkNotHorseWalkable.checked do (append flagNames "Not Horse Walkable")
return (RsCollMatMakeFlagsInt flagNames)
)
-- Convert flags-integer to checkbox-settings:
fn SetFlagsUI flags =
(
chkStairs.checked = RsCollMatFlagged "Stairs" flags:flags
chkClimable.checked = RsCollMatFlagged "Non Climbable" flags:flags
chkSeeThrough.checked = RsCollMatFlagged "See Through" flags:flags
chkShootThrough.checked = RsCollMatFlagged "Shoot Through" flags:flags
chkShootThroughFX.checked = RsCollMatFlagged "Shoot Through FX" flags:flags
chkPath.checked = RsCollMatFlagged "Path" flags:flags
chkCover.checked = RsCollMatFlagged "Does Not Provide Cover" flags:flags
chkCamera.checked = RsCollMatFlagged "Non Camera Collidable" flags:flags
chkSetPedPop.checked = RsCollMatFlagged "Reserved for Tools" flags:flags
chkRoadRoad.checked = RsCollMatFlagged "Road - Road" flags:flags
chkRoadPath.checked = RsCollMatFlagged "Road - Path" flags:flags
chkRoadTrail.checked = RsCollMatFlagged "Road - Trail" flags:flags
chkNotHorseWalkable.checked = RsCollMatFlagged "Not Horse Walkable" flags:flags
)
--------------------------------------------------------------
-- Set up the surfaces and surface-category lists
--------------------------------------------------------------
fn SetupList =
(
local collCatNames = #("ALL CATEGORIES")
collCatItems = #(#())
local SurfaceTypes = (RsCollMatDef.LoadCollisionEntries Filtered:True)
for item in SurfaceTypes do
(
local catNum = findItem collCatNames item.category
if (catNum == 0) do
(
append collCatNames item.category
append collCatItems #()
catNum = collCatNames.count
)
append collCatItems[1] item.name
append collCatItems[catNum] item.name
)
for collNames in collCatItems do
(
sort collNames
)
-- Add _BLANK to top of all-surfaces list:
insertitem RsBlankCollName collCatItems[1] 1
lstCategories.items = collCatNames
lstCategories.selection = 1
lstSurfaces.items = collCatItems[1]
)
--------------------------------------------------------------
-- Set Surfaces list to show list for this category-num:
--------------------------------------------------------------
fn setListToCategory catNum =
(
print selectedSurface
lstCategories.selection = catNum
lstSurfaces.items = collCatItems[catNum]
lstSurfaces.selection = findItem lstSurfaces.items selectedSurface
SetRexCtrlsEnabled()
)
--------------------------------------------------------------
-- Updates the texture-preview thumbnail
--------------------------------------------------------------
fn UpdateTexture =
(
-- Create default bitmap:
local showBmp = bitmap bmpUi.width bmpUi.height color:(white * ((colorMan.getColor #3dLight) * [255,255,255]))
local SelTexInfo = GetSelTexInfo()
if (SelTexInfo != undefined) do
(
local selItem = SelTexInfo.TexMap
if (selItem != undefined) do
(
local bmpSet
if (isKindOf selItem bitmaptexture) then
(
bmpSet = selItem
)
else
(
bmpset = bitmaptexture()
bmpset.filename = selItem
bmpset.reload()
)
rendermap bmpset into:showBmp filter:true
)
)
bmpUi.bitmap = showBmp
)
fn setMatStatus =
(
local textureName = undefined
local SelTexInfo = GetSelTexInfo()
if (SelTexInfo != undefined) do
(
textureName = SelTexInfo.TexName
)
if (textureName == undefined) then
(
-- Get number of select-objects' containers:
local ContsCount = (MakeUniqueArray (for Obj in (GetCurrentSelection()) collect (RsGetObjContainer Obj))).Count
case of
(
(ContsCount == 0):(lblStatus.text = "(No objects selected)")
(ContsCount > 1):(lblStatus.text = "Warning: Multiple-container objs selected")
default:(lblStatus.text = "(No texture selected)")
)
)
else
(
local FindNum = (gRsTexToColl.GetFindTexNum TextureName)
if (FindNum == 0) do
(
lblStatus.text = "(No saved surface-type found)"
)
)
)
--------------------------------------------------------------
-- Set material-flag controls
--------------------------------------------------------------
fn UpdateMaterial matClicked:false =
(
local SurfaceDef
local idxFind = 0
local SelTexInfo = GetSelTexInfo()
if (SelTexInfo != undefined) do
(
-- Find surface-definition for this texname:
SurfaceDef = gRsTexToColl.GetTexDataFromXML SelTexInfo.TexName MatClicked:MatClicked CollSetRoll:RsCollisionSetRoll
)
-- Set controls to match loaded settings (or set to defaults if no definition was found)
if (SurfaceDef != undefined) then
(
idxFind = finditem lstSurfaces.items SurfaceDef.Material
-- Change category to ALL and try searching again:
if (idxFind == 0) and (lstCategories.selection != 1) do
(
setListToCategory 1
idxFind = finditem lstSurfaces.items SurfaceDef.Material
)
spnPedDensity.value = SurfaceDef.PedPop
chkProcCullImmune.checked = SurfaceDef.ProcCullImmune
SetFlagsUI SurfaceDef.flags
)
else
(
SetFlagsUI 0
spnPedDensity.value = 0
chkProcCullImmune.checked = false
)
setMatStatus()
lstSurfaces.selection = idxFind
selectedSurface = lstSurfaces.selected
SetRexCtrlsEnabled()
)
--------------------------------------------------------------
-- Update texmap-names list-control
--------------------------------------------------------------
fn UpdateTexMapList ShowSetTexs:(chkSetTexs.Checked) ShowUnsetTexs:(chkUnsetTexs.Checked) =
(
SetWaitCursor()
local LblWas = LblStatus.Text
LblStatus.Text = "Processing texmap-names..."
-- Show all TexInfos by default
ShownTexInfos = TexInfos
-- Find out if texmaps have surfaces assigned for them yet:
if (not ShowSetTexs) or (not ShowUnsetTexs) do
(
-- Get surface-definition data for these textures:
local TexMapNames = for Item in TexInfos collect Item.TexName
local TexElems = gRsTexToColl.GetTexListDataFromXML TexMapNames CollSetRoll:RsCollisionSetRoll
-- Filter out texmaps with non-matching definition-state:
if ShowUnsetTexs then
(
ShownTexInfos = for n = 1 to TexElems.count where (TexElems[n] == undefined) collect TexInfos[n]
)
else
(
ShownTexInfos = for n = 1 to TexElems.count where (TexElems[n] != undefined) collect TexInfos[n]
)
)
local GlobalNames = undefined
local NewListItems = for TexInfo in ShownTexInfos collect
(
local DisplayName = (Copy TexInfo.TexName)
if (GlobalNames == undefined) do
(
GlobalNames = gRsTexToColl.GetGlobalTextureNames()
)
-- Add suffix to display-name if it's on the globals-list:
if (FindItem GlobalNames (ToLower DisplayName)) != 0 do
(
DisplayName += " (Global)"
)
-- Collect name to be shown in list:
DisplayName
)
-- Update list-items:
LstTextures.Items = NewListItems
LblStatus.Text = LblWas
SetArrowCursor()
)
--------------------------------------------------------------
-- Updates the Select Texture list:
--------------------------------------------------------------
fn UpdateSelectionSet Objs =
(
Free TexInfos
Free ShownTexInfos
try (destroyDialog collSet_showBmpRoll) catch ()
LstTextures.selection = 0
lstSurfaces.selection = 0
selectedSurface = undefined
-- Filter out invalid objects:
Objs = for Obj in Objs where (isEditPolyMesh Obj) collect Obj
-- Get number of selected-objects' containers:
local ContsCount = (MakeUniqueArray (for Obj in Objs collect (RsGetObjContainer Obj))).Count
-- Only get texturenames if selected objects are only in one container:
if (ContsCount == 1) do
(
-- Collect the texture-data from selected objects:
TexInfos = (gRsTexToColl.GetDiffTexInfosForObjs Objs)
-- Sort texture-descriptors alphabetically:
fn SortTexNames v1 v2 = (StriCmp v1.TexName v2.TexName)
qsort TexInfos SortTexNames
)
-- Update controls:
if RsCollisionSetRoll.open do
(
lblTexture.text = if (ContsCount == 1) then "Textures on selected objects:" else ""
UpdateTexMapList()
UpdateTexture()
UpdateMaterial()
)
)
--------------------------------------------------------------
--
--------------------------------------------------------------
fn UpdateSelectionSetFromFolder =
(
lblTexture.text = "Textures from selected folder:"
-- User chooses texture-folder to process:
local Rootpath = getsavepath initialDir:(RsConfigGetArtDir() + "/textures/")
-- Get all texmap-paths from folder:
if (Rootpath != undefined) do
(
SetWaitCursor()
PushPrompt "Collecting texmap paths..."
local WildCards = for Ext in gSupportedTextureTypes collect ("*" + Ext)
local TexPaths = (RsFindFilesRecursive Rootpath Wildcards)
local TexNames = #()
TexInfos = for TexPath in TexPaths collect
(
local TexName = (ToLower (GetFilenameFile TexPath))
-- Just collect one path per unique TexName:
if (AppendIfUnique TexNames TexName) then (RsTexMapItem TexName:TexName Filename:TexPath) else DontCollect
)
-- Sort texture-descriptors alphabetically:
fn SortTexNames v1 v2 = (StriCmp v1.TexName v2.TexName)
qsort TexInfos SortTexNames
PopPrompt()
SetArrowCursor()
)
UpdateTexMapList()
UpdateTexture()
UpdateMaterial()
)
-------------------------------------------------------------------------------------
-- Gets xml-elements for all selected objects, before assigning materials:
-- Warn
-------------------------------------------------------------------------------------
fn GetTexListDataFromXMLForObjs Objs =
(
local RetVal = True
-- Update TexInfos list:
UpdateSelectionSet objs
lblProgStatus.text = "Loading material data [Esc to cancel]"
-- Load surfacenames from xml for all objects' diffusemaps:
local TexMapNames = for Item in TexInfos collect Item.TexName
local SurfaceNames = gRsTexToColl.GetTexListDataFromXML TexMapNames CollSetRoll:RsCollisionSetRoll
lblProgStatus.text = ""
lblStatus.text = ""
-- Are any texmaps undefined?
local Unassigneds = 0
for Item in SurfaceNames where (Item == undefined) do
(
Unassigneds += 1
)
if (Unassigneds != 0) do
(
local Plural = if (Unassigneds == 1) then "Texmap" else ((Unassigneds as String) + " texmaps")
RetVal = (QueryBox (Plural + " found with no SurfaceName assigned to it!\n\nTool will use DEFAULT instead.\n\nContinue?") Title:"WARNING: Texmaps with undefined SurfaceNames")
-- If user says show unset texmaps:
if (not RetVal) and (not ((not chkSetTexs.Checked) and chkUnsetTexs.Checked)) do
(
chkSetTexs.Checked = False
chkUnsetTexs.Checked = True
RsCollisionSetRoll.DoListUpdate()
)
)
return RetVal
)
--------------------------------------------------------------
-- Save changes to surface-settings:
--------------------------------------------------------------
fn SetMaterial =
(
local SelTexInfo = GetSelTexInfo()
if (SelTexInfo == undefined) do return False
local TexName = SelTexInfo.TexName
local flags = GetFlagsUI()
local texElem = (RsCollSurfaceDef name:TexName material:selectedSurface flags:flags procCullImmune:chkProcCullImmune.checked)
if chkSetPedPop.checked do
(
texElem.pedPop = spnPedDensity.value
)
gRsTexToColl.SetDataSettingXml TexElem CollSetRoll:RsCollisionSetRoll
)
--------------------------------------------------------------------
-- Get faces that are painted black/white on a given channel
--------------------------------------------------------------------
fn GetOverrideFaces obj chan blackFaces:#{} whiteFaces:#{} =
(
if not MeshOp.GetMapSupport obj chan do
return #{}
local faceCount = MeshOp.GetNumFaces obj
whiteFaces.count = faceCount
blackFaces.count = faceCount
local MeshGetMapFace = MeshOp.GetMapFace
local MeshGetMapVert = MeshOp.GetMapVert
for faceNum = 1 to faceCount do
(
local faceMapVerts = (MeshGetMapFace obj chan faceNum)
local overrideVal = 0.0
for vertIdx = 1 to 3 do
(
-- Get vertex-colour for tri-corner:
local vertNum = faceMapVerts[vertIdx]
local vertClr = MeshGetMapVert obj chan vertNum
-- Collect override-value
-- Defaults to 0.5 if non-greyscale or out-of-bounds
local vertVal = vertClr[1]
if (vertVal < 0.0) or (vertVal > 1.0) or (Distance vertClr [vertVal, vertVal, vertVal] > 0.0001) do
vertVal = 0.5
overrideVal += vertVal
)
case of
(
(overrideVal <= 0.5):(blackFaces[faceNum] = True)
(overrideVal >= 2.5):(whiteFaces[faceNum] = True)
)
)
return whiteFaces
)
----------------------------------------------------------------------------
-- Creates a new collision-mesh for obj, with correct materials set:
----------------------------------------------------------------------------
fn CreateObjectMat obj delExisting:true DoDeepness:True JustSelFaces:False =
(
lblProgStatus.text = "Creating collision: " + obj.name + " [Esc to cancel]"
local timestart = timestamp()
-- Delete object's existing collision-objects:
if delExisting do
(
local DelObjs = (for childObj in obj.children where (getattrclass childobj == "Gta Collision") collect childObj)
delete DelObjs
)
lblProgStatus.text = "Collecting face data: " + obj.name + " [Esc to cancel]"
local surfaceData = gRsTexToColl.GetObjFaceData Obj AsMesh:True JustSelFaces:JustSelFaces CollSetRoll:RsCollisionSetRoll
-- Abort if 'GetObjFaceData' was cancelled:
if (SurfaceData == False) do
return False
local Msg = ("Creating collision: " + obj.name)
lblProgStatus.text = (Msg + " [Esc to cancel]")
format "%\n" Msg
-- Convert the face-info lists to BitArrays
local matFaceLists = #()
for n = 1 to surfaceData.colSurfaceFaces.count do
(
local faceItems = surfaceData.colSurfaceFaces[n]
local faceNums = for item in faceItems collect item.num
Append matFaceLists (faceNums as Bitarray)
faceItems.count = 0
faceNums.count = 0
)
-- Create object that'll be turned in collisionmesh:
newobj = copy obj
convertToMesh newObj
meshops.unhideall newObj
setfaceselection newObj #{1..newObj.numFaces}
resetXForm newObj
collapseStack newObj
-- Get flag-bits
local collFlagNames = RexGetCollisionFlagNames()
local nonClimbableFlagIdx = FindItem collFlagNames "Non Climbable"
local tooSteepFlagIdx = FindItem collFlagNames "Too Steep"
-- Faces painted as black or white on channel 23 will be given Too Steep or Non Climbable flags
local steepChan = RsGetChanByName #SteepOverride
local steepFaces = #{}
local noClimbFaces = #{}
GetOverrideFaces newObj steepChan blackFaces:steepFaces whiteFaces:noClimbFaces
local hasSteepFaces = (steepFaces.numberSet + noClimbFaces.numberSet != 0)
-- Turn off all new object's mapping-channels:
MeshOp.SetNumMaps newObj 0
local removeFaces = #{1..newObj.numFaces}
local isRiverObj = False
local collisionEditor
-- Collect list of bound-materials and their faces
local newMatFaceItemsList = #()
struct sMatListItem (mat, faces, priority)
for surfaceNum = 1 to surfaceData.colSurfaceNames.count do
(
local surfaceName = surfaceData.colSurfaceNames[surfaceNum]
local collFlags = surfaceData.colSurfaceFlags[surfaceNum]
local cullImmune = surfaceData.colSurfaceProcCullImmune[surfaceNum]
local pedPop = surfaceData.colSurfacePops[surfaceNum]
local matFaces = matFaceLists[surfaceNum]
-- These faces will NOT be deleted from the final mesh
removeFaces -= matFaces
local newsubmat = RexBoundMtl name:surfaceName
RexSetCollisionFlags newsubmat collFlags
RexSetCollisionName newsubmat surfaceName
RexSetProcCullImmune newSubMat cullImmune
if (pedPop != -1) and (pedPop != undefined) do
RexSetPopDensity newsubmat pedPop
-- We're going to mark objects with water-surfaces with "river" flag:
if (not isRiverObj) and (surfaceName == "WATER") do
isRiverObj = True
-- Do we need to make a steep version of this material too?
if hasSteepFaces do
(
for overrideName in #(#Steep, #NoClimb) do
(
-- Get overlap of face-lists
local overrideFaces = if (overrideName == #Steep) then (matFaces * steepFaces) else (matFaces * noClimbFaces)
-- Make a new material for any matching faces
if (overrideFaces.numberSet != 0) do
(
-- Remove faces from original material's faces
matFaces -= overrideFaces
-- Add the steepness-flags to material's flags
-- (Both types have the non-climbable flag)
local newFlags = Bit.Set collFlags nonClimbableFlagIdx True
if (overrideName == #Steep) do
newFlags = Bit.Set newFlags tooSteepFlagIdx True
local overrideMat = Copy newSubMat
overrideMat.name = (surfaceName + "_" + (ToUpper overrideName))
RexSetCollisionFlags overrideMat newFlags
-- Collect material with extra flags
local sortPriority = if (overrideName == #Steep) then 2 else 3
Append newMatFaceItemsList (sMatListItem mat:overrideMat faces:overrideFaces priority:sortPriority)
)
)
)
-- Collect this material (unless all its faces were Steep)
if (matFaces.numberSet != 0) do
Append newMatFaceItemsList (sMatListItem mat:newSubMat faces:matfaces priority:1)
)
-- Sort materials by name, and sort steep etc types together
fn SortMatItems v1 v2 =
(
local sortVal = (v1.priority - v2.priority)
if (sortVal == 0) do
sortVal = StriCmp v1.mat.name v2.mat.name
return sortVal
)
Qsort newMatFaceItemsList SortMatItems
-- Set material ids for faces
for matId = 1 to newMatFaceItemsList.count do
(
local matFaces = newMatFaceItemsList[matId].faces
for faceNum in matFaces do
SetfaceMatID newobj faceNum matId
)
if (removeFaces.numberSet == newobj.numfaces) do
(
format "Not creating collision for: % (no suitable faces)\n" obj.name
-- Don't create empty collision-meshes:
delete newobj
return True
)
NewObj.Name = UniqueName (Obj.Name + "_ColMesh")
NewObj.Parent = Obj
-- Remove non-collision faces:
if (removeFaces.numberSet != 0) do
Meshop.DeleteFaces newobj removeFaces
-- Delete isolated verts - these can play havok with the object-middle detection:
Meshop.DeleteIsoVerts NewObj
local matName = "CollSet:" + newobj.name + " - Multimaterial"
local newmat = Multimaterial name:matName
local subMatList = for item in newMatFaceItemsList collect item.mat
newmat.numsubs = submatlist.count
newmat.materialList = submatlist
newobj.material = newmat
-- Make sure that edges between materials are visible,
-- to avoid messing up matids if collision is converted to Poly in future:
-- (required by Deepener methods)
if (RsMakeMeshMatBordersVisible != undefined) do
(
RsMakeMeshMatBordersVisible NewObj
)
-- Apply appropriate road-flags to faces found near NavPaths:
gRsNavPathLoad.ApplyRoadFlagsToCollision NewObj
-- Object-list; initially just includes the first generated object:
local NewObjs = #(NewObj)
local WeaponObjs = #{}
local MoverObjs = #{}
-- Are we generating any weapon/mover-specific collision?
local HasWeaponObjs = False
local HasMoverObjs = False
-- Push down verts for faces with "*DEEP*" surfacetypes:
if DoDeepness do
(
-- Get Deep-collision faces on object:
local DeepFaces = (RsGetCollFacesByName NewObj "*DEEP*")
if (DeepFaces.NumberSet != 0) do
(
HasWeaponObjs = True
HasMoverObjs = True
-- Detach copy of deep-faces, to use as Weapon collision:
local WepObj = (Copy NewObj)
ConvertToMesh WepObj
WepObj.Mesh = Meshop.DetachFaces NewObj DeepFaces Delete:False AsMesh:True
append NewObjs WepObj
WeaponObjs[NewObjs.Count] = True
-- Deepen faces on main mesh (i.e. mover-collision)
-- (Modify-tab needs to be active to make required changes)
ResumeEditing()
RsCollDeepenFaces NewObj DeepFaces:DeepFaces
SuspendEditing()
ConvertToMesh NewObj
DeepFaces = (RsGetCollFacesByName NewObj "*DEEP*")
if (DeepFaces.NumberSet == NewObj.NumFaces) then
(
-- If the whole mesh was Deep, there no need to separate its faces off:
MoverObjs[1] = True
)
else
(
-- Detach deepened faces from mesh, to be set as just Mover collision:
local MovObj = (Copy NewObj)
ConvertToMesh MovObj
MovObj.Mesh = Meshop.DetachFaces NewObj DeepFaces Delete:True AsMesh:True
append NewObjs MovObj
MoverObjs[NewObjs.Count] = True
)
)
Free DeepFaces
)
-- Split up mesh(es) until each has fewer than the max number of verts/faces:
local RedoLast = false
local doSplit = false
local NewObjNum = 0
while (NewObjNum < NewObjs.count) do
(
if not RedoLast then
(
NewObjNum += 1
)
-- Is this mesh going to be Weapon/Mover collision?
local isWeaponColl = WeaponObjs[NewObjNum]
local isMoverColl = MoverObjs[NewObjNum]
local ThisNewObj = NewObjs[NewObjNum]
local NumVerts = (GetNumVerts ThisNewObj.Mesh)
local NumFaces = (GetNumFaces ThisNewObj.Mesh)
local OverVerts = (NumVerts > RsMaxCollVerts)
local OverFaces = (NumFaces > RsMaxCollFaces)
doSplit = (OverVerts or OverFaces)
if (doSplit) then
(
-- Split mesh along its longest axis:
RsMesh_SplitLongestAxis ThisNewObj &NewObjs
-- Set the newly-generated mesh as weapon/mover-collision, if the original object was:
WeaponObjs[NewObjs.Count] = isWeaponColl
MoverObjs[NewObjs.Count] = isMoverColl
RedoLast = true
)
else
(
RedoLast = false
)
)
-- Apply collision-type flags to object(s) UDP:
if (HasWeaponObjs or HasMoverObjs or isRiverObj) do
(
-- Initialise collision-flagging struct:
CollisionEditor = RsCollTypes()
CollisionEditor.Init()
-- Set 'weapon' type-flag for objects that require it:
if HasWeaponObjs do
(
WeaponObjs = for n in WeaponObjs collect NewObjs[n]
CollisionEditor.SetObjCollTypeFlags WeaponObjs "Weapons"
for Obj in WeaponObjs do (Obj.Name += "_WEAPON")
)
-- Set 'mover' type-flag for objects that require it:
if HasMoverObjs do
(
MoverObjs = for n in MoverObjs collect NewObjs[n]
CollisionEditor.SetObjCollTypeFlags MoverObjs "Mover|Horse|Vehicle|Cover"
for Obj in MoverObjs do (Obj.Name += "_MOVER")
)
-- Set 'river' type-flag on object(s) if collision included water-surfaces:
if isRiverObj do
(
collisionEditor.setObjCollTypeFlags NewObjs "river"
for Obj in NewObjs do (Obj.Name += "_RIVER")
)
)
--format "Objs: %\n" (NewObjs as string)
--format "WeaponObjs: %\n" WeaponObjs
--format "MoverObjs: %\n" MoverObjs
-- Convert all meshes to collision, and print their names:
for NewObj in NewObjs do
(
-- Convert generated mesh to collision:
mesh2col NewObj
format " Created: %\n" NewObj.Name
)
format "[Create Collision took: % seconds] %\n" (0.001 * (Timestamp() - TimeStart)) obj.name
return True
)
---------------------------------------------------------------------------------------
-- Reassigns collision-mesh materials to match current parent-mesh textures:
---------------------------------------------------------------------------------------
fn AssignObjectMat obj =
(
local timestart = timestamp()
if not isEditPolyMesh obj do
(
return false
)
local collisionChildren = for childObj in obj.children where (isKindOf childObj Col_Mesh) collect childObj
if (collisionChildren.count == 0) do
(
return false
)
-- Read surface-data for parent object:
lblProgStatus.text = "Collecting face data: " + obj.name + " [Esc to cancel]"
local surfaceData = gRsTexToColl.GetObjFaceData Obj AsMesh:True GetPos:true CollSetRoll:RsCollisionSetRoll
if (SurfaceData != False) do
(
for childObj in collisionChildren while (progressContinue = not keyboard.escPressed) do
(
lblProgStatus.text = "Reassigning surfaces: " + childObj.name + " [Esc to cancel]"
subProgBar.value = 0
local savetrans = childobj.transform
col2mesh childobj
local numFaces = getnumfaces childobj
local matchingFaces = for n = 1 to surfaceData.colSurfaceNames.count collect #()
local removeFaces = #{}
-- This sort is used for bsearch, which tends to be faster than findItem and can make inexact matches:
fn sortPointItem v1Item v2Item =
(
v1 = v1Item[1]
v2 = v2Item[1]
case of
(
-- Matches just-off values:
((distance v1 v2) < 0.001):0
(v1[1] < v2[1]):-1
(v1[1] > v2[1]):1
(v1[2] < v2[2]):-1
(v1[2] > v2[2]):1
(v1[3] < v2[3]):-1
(v1[3] > v2[3]):1
default:0
)
)
local searchPointItems = #()
for listNum = 1 to surfaceData.colSurfaceFaces.count do
(
local faceList = surfaceData.colSurfaceFaces[listNum]
join searchPointItems (for faceItem in faceList collect #(faceItem.pos, faceItem))
)
qsort searchPointItems sortPointItem
local searchPoints = for item in searchPointItems collect item[1]
local matchingFace, nearFaceDist, newDist
for faceNum = 1 to numFaces while (progressContinue = not keyboard.escPressed) do
(
subProgBar.value = 100.0 * faceNum / numFaces
-- Find centre of face:
local faceCentre = meshOp.getFaceCenter childobj faceNum node:childobj
-- Search for exact(ish) point-match, if possible:
local matchingFace = bsearch #(faceCentre) searchPointItems sortPointItem
if (matchingFace != undefined) then
(
matchingFace = matchingFace[2]
)
else
(
-- If match wasn't found, look for the closest point instead:
local pointDists = for item in searchPoints collect (distance item faceCentre)
local findItemNum = findItem pointDists (amin pointDists)
matchingFace = searchPointItems[findItemNum][2]
)
if (matchingFace.colSurfaceNum == 0) then
(
removeFaces[faceNum] = true
)
else
(
matchingFace.matchedFace = faceNum
append matchingFaces[matchingFace.colSurfaceNum] matchingFace
)
)
-- Clear/retain uv-channel data:
(
-- Make array of channels to be preserved, if they've already been assigned:
local keepChannels = #{}
keepChannels[11] = chkPreserve11.checked
keepChannels[12] = chkPreserve12.checked
-- Deactivate all mapping-channels that haven't been marked for preservation:
for n = 1 to ((meshop.getNumMaps childobj) - 1) where not keepChannels[n] do
(
meshop.setMapSupport childobj n false
)
local topChannelNum = (meshop.getNumMaps childobj) - 1
keepChannels = keepChannels as array
-- Remove any vertex-channels above the maximum keep-channel:
if (keepChannels.count != 0) and (topChannelNum > keepChannels[keepChannels.count]) do
(
meshop.setNumMaps childobj (topChannelNum + 1)
)
-- Remove all vertex-channels if no keep-channel is in use:
if (keepChannels.count == 0) or (topChannelNum < keepChannels[1]) do
(
meshop.setNumMaps childobj 0
)
)
local submatlist = #()
for surfaceNum = 1 to surfaceData.colSurfaceNames.count where (matchingFaces[surfaceNum].count != 0) do
(
local collName = surfaceData.colSurfaceNames[surfaceNum]
local collFlags = surfaceData.colSurfaceFlags[surfaceNum]
local cullImmune = surfaceData.colSurfaceProcCullImmune[surfaceNum]
local pedPop = surfaceData.colSurfacePops[surfaceNum]
local matFaces = matchingFaces[surfaceNum]
local newsubmat = RexBoundMtl name:collName
RexSetCollisionName newsubmat collName
RexSetCollisionFlags newsubmat collFlags
RexSetProcCullImmune newSubMat cullImmune
if (pedPop != -1) and (pedPop != undefined) do
RexSetPopDensity newsubmat pedPop
-- Set the matids for all faces
for faceInfo in matFaces do
(
local faceNum = faceInfo.matchedFace
SetfaceMatID childobj faceNum surfaceNum
)
-- Mark the collisionmesh as RIVER if it uses any WATER collision-materials
if (collName == "WATER") do
(
local collisionEditor = RsCollTypes()
collisionEditor.setObjCollTypeFlags #(obj) "river"
collisionEditor.findBadFlagObjs #(obj) fix:true
)
Append submatlist newsubmat
)
if (removeFaces.numberSet == childobj.numfaces) then
(
-- Remove empty collision-meshes:
delete childobj
)
else
(
-- Delete unwanted faces:
if (removeFaces.numberSet != 0) do
(
meshop.deleteFaces childobj removeFaces
)
local matName = "CollSet:" + childobj.name + " - Multimaterial"
local newmat = Multimaterial name:matName
newmat.numsubs = submatlist.count
newmat.materialList = submatlist
childobj.material = newmat
-- Make sure that edges between materials are visible,
-- to avoid messing up matids if collision is converted to Poly in future:
if (RsMakeMeshMatBordersVisible != undefined) do
(
RsMakeMeshMatBordersVisible ChildObj
)
mesh2col childobj
childobj.transform = savetrans
)
)
)
format "[Reassign took: % seconds] %\n" (0.001 * (Timestamp() - TimeStart)) obj.name
)
--////////////////////////////////////////////////////////////
-- events
--////////////////////////////////////////////////////////////
--------------------------------------------------------------
-- Reassign Collision-Surfaces for Collision Object(s):
--------------------------------------------------------------
on BtnReassignCollMats pressed do
(
SuspendEditing()
SetWaitCursor()
progressContinue = true
local selObjs = (GetCurrentSelection())
-- Don't generate collision for LOD-objects:
local doObjs = for obj in selObjs where (getattrclass obj == "Gta Object") and ((getLODChildren obj).count == 0) collect obj
-- Load surface-assignments, offering to cancel if any are unassigned:
progressContinue = GetTexListDataFromXMLForObjs doObjs
if progressContinue do
(
undo "Reassign Collision Materials" on
(
totalProgBar.value = 0.0
for i = 1 to doObjs.count while (progressContinue = not keyboard.escPressed) do
(
local obj = doObjs[i]
subProgBar.value = 0.0
AssignObjectMat obj
totalProgBar.value = (100.0 * i / doObjs.count)
)
)
)
if progressContinue then
(
totalProgBar.value = 100.0
subProgBar.value = 100.0
lblProgStatus.text = "Reassign Completed"
)
else
(
totalProgBar.value = 0.0
subProgBar.value = 0.0
lblProgStatus.text = "Reassign Cancelled"
)
SetArrowCursor()
ResumeEditing()
)
--------------------------------------------------------------
-- Create Collision-Object(s):
--------------------------------------------------------------
on BtnCreateCollObjs pressed do
(
local idxHandEdited = getattrindex "Gta Object" "Hand edited collision"
local selObjs = (GetCurrentSelection())
-- Don't generate collision for LOD-objects:
local doObjs = for obj in selObjs where (getattrclass obj == "Gta Object") and ((getLODChildren obj).count == 0) collect obj
-- Store current subobject-level:
local SubObjWas = SubObjectLevel
-- Will we limit collision-create to selected faces?
local JustSelFaces = False
if (BtnCreateForFaces.Checked) and (doObjs.Count == 1) do
(
-- Only bother turning on this mode if we're currently in Face subobject mode:
JustSelFaces = ((GetSelectionLevel doObjs[1]) == #Face)
)
-- Load surface-assignments, offering to cancel if any are unassigned:
local success = (GetTexListDataFromXMLForObjs doObjs)
if (not success) do return False
-- Warn user if attempting to regenerate collision in a late-stage project:
if MatureProjWarn and (doObjs.Count != 0) do
(
local Msg = "This operation will create brand new collision meshes for the selected objects.\n\nWe are at a critical stage in the project where most collision has been hand edited/authored.\n\nDo you still want to continue with this operation?"
if (querybox Msg Title:"Warning: Should you be doing this?") then
(
-- Don't bother warning again:
MatureProjWarn = False
)
else
(
return False
)
)
-- Collect objects that have collision:
local hasColObjs = #()
for obj in doObjs do
(
local findCol = true
for childObj in obj.children where (getattrclass childobj == "Gta Collision") while findCol do
(
append hasColObjs obj
findCol = false
)
)
local delExistingCols = True
if (hasColObjs.count != 0) do
(
local msg = stringStream ""
local plural = if (hasColObjs.count != 1) then "s" else ""
format "Delete existing collision from object% before creating new?\n\n" plural to:msg
for objNum = 1 to hasColObjs.count do
(
format "%" hasColObjs[objNum].name to:msg
if (objNum != hasColObjs.count) do (format "\n" to:msg)
)
RsMapExportCancelled = false
delExistingCols = RsQueryBoxTimeOut (msg as string) title:"Delete existing collision?" timeout:-1 cancel:true
if RsMapExportCancelled do return false
)
undo "Create Collision Meshes" on
(
progressContinue = true
totalProgBar.value = 0.0
SuspendEditing()
SetWaitCursor()
for i = 1 to doObjs.count while (progressContinue = not keyboard.escPressed) do
(
local obj = doObjs[i]
subProgBar.value = 0.0
local createCol = true
if delExistingCols and (getattr obj idxHandEdited) then
(
createCol = querybox (obj.name + " has hand edited collision which will be destroyed. Continue?")
)
if createCol do
(
ProgressContinue = CreateObjectMat obj delExisting:delExistingCols DoDeepness:BtnAddDeepness.Checked JustSelFaces:JustSelFaces
)
totalProgBar.value = (100.0 * i / doObjs.count)
)
if progressContinue then
(
totalProgBar.value = 100.0
subProgBar.value = 100.0
lblProgStatus.text = "Create Completed"
)
else
(
totalProgBar.value = 0.0
subProgBar.value = 0.0
lblProgStatus.text = "Create Cancelled"
)
-- Filter out deleted nodes, as we can't select those...
SelObjs = for Obj in SelObjs where (isValidNode Obj) collect Obj
Select SelObjs
SetArrowCursor()
ResumeEditing()
)
-- Restore subobject-level:
if (SubObjWas != undefined) do
(
SubObjectLevel = SubObjWas
)
return OK
)
--------------------------------------------------------------
-- Move selected texname into/out fo global.xml:
--------------------------------------------------------------
on btnToggleGlobal changed state do
(
local SelTexInfo = GetSelTexInfo()
if (SelTexInfo != undefined) then
(
local TexName = SelTexInfo.TexName
gRsTexToColl.ToggleGlobalDataSettingXml TexName CollSetRoll:RsCollisionSetRoll
UpdateTexMapList()
)
else
(
btnToggleGlobal.checked = false
)
)
--------------------------------------------------------------
-- Delete Definition:
--------------------------------------------------------------
on btnDeleteDef pressed do
(
local SelTexInfo = GetSelTexInfo()
if (SelTexInfo != undefined) do
(
local TexName = SelTexInfo.TexName
gRsTexToColl.DeleteTexnameData TexName
UpdateMaterial MatClicked:True
)
)
--------------------------------------------------------------
-- Get Tex List From Folder:
--------------------------------------------------------------
on btnGetFolder pressed do
(
UpdateSelectionSetFromFolder()
)
--------------------------------------------------------------
-- Snap Pivots of Selected To Parent:
--------------------------------------------------------------
on btnSnapPivot pressed do
(
-- Iterate through the selected objects, looking for collision
for obj in (selection as array) do
(
if getattrclass obj == "Gta Collision" do
(
objParent = obj.parent
obj.pivot = objParent.pivot
)
)
)
----------------------------------------------------------------------------------
-- Update texture-list when Set/Unset checkboxes are toggled:
----------------------------------------------------------------------------------
fn DoListUpdate =
(
UpdateTexMapList()
UpdateTexture()
UpdateMaterial()
)
on chkSetTexs changed newval do
(
if (not NewVal) do (chkUnsetTexs.Checked = True)
DoListUpdate()
)
on chkUnsetTexs changed newval do
(
if (not NewVal) do (chkSetTexs.Checked = True)
DoListUpdate()
)
--------------------------------------------------------------
-- Materials-list:
--------------------------------------------------------------
fn showPreviewWindow =
(
if (LstTextures.selection == 0) then
(
if (collSet_showBmpRoll != undefined) and collSet_showBmpRoll.open do
(
destroyDialog collSet_showBmpRoll
)
)
else
(
if (collSet_showBmpRoll != undefined) and collSet_showBmpRoll.open then
(
collSet_showBmpRoll.updateBmp()
)
else
(
rollout collSet_showBmpRoll "Bitmap"
(
bitmap bigBmpShowCtrl pos:[0,0]
fn updateBmp =
(
local SelTexInfo = GetSelTexInfo()
if (SelTexInfo == undefined) then
(
destroyDialog collSet_showBmpRoll
)
else
(
local bmpSet
if (isKindOf SelTexInfo.TexMap bitmaptexture) then
(
bmpSet = SelTexInfo.TexMap
)
else
(
bmpSet = bitmaptexture()
bmpSet.filename = SelTexInfo.Filename
bmpSet.reload()
)
local bmpWidth = bmpset.bitmap.width
local bmpHeight = bmpset.bitmap.height
bigBmpShowCtrl.width = collSet_showBmpRoll.width = bmpWidth
bigBmpShowCtrl.height = collSet_showBmpRoll.height = bmpHeight
local img = bitmap bmpWidth bmpHeight
local rm = rendermap bmpSet into:img size:[bmpWidth, bmpHeight]
bigBmpShowCtrl.bitmap = img
close rm
)
)
on collSet_showBmpRoll open do
(
updateBmp()
)
)
destroyDialog collSet_showBmpRoll
createDialog collSet_showBmpRoll
)
)
)
on LstTextures selected idx do
(
btnToggleGlobal.checked = false
-- Show list-item's bitmap in preview-box;
UpdateTexture()
-- Set tool to show current settings for selected texmap:
UpdateMaterial matClicked:true
-- Update big pop-out preview-window, if it's shown:
if (collSet_showBmpRoll != undefined) and collSet_showBmpRoll.open then
(
collSet_showBmpRoll.updateBmp()
)
)
-- Show texture-preview window when image or texture-name is double-clicked:
on LstTextures doubleClicked idx do (showPreviewWindow())
on bmpUi dblclick do (showPreviewWindow())
--------------------------------------------------------------
-- Surface-categories list:
--------------------------------------------------------------
on lstCategories selected idx do
(
setListToCategory idx
)
--------------------------------------------------------------
-- Surface-types list:
--------------------------------------------------------------
on lstSurfaces selected idx do
(
selectedSurface = lstSurfaces.selected
if (LstTextures.selection == 0) then
(
-- Deselect if no texturename is selected:
lstSurfaces.selection = 0
)
else
(
SetMaterial()
)
SetRexCtrlsEnabled()
)
--------------------------------------------------------------
-- Event-handlers for "RexBounds Flags" controls:
--------------------------------------------------------------
on chkStairs changed val do (SetMaterial())
on chkClimable changed val do (SetMaterial())
on chkSeeThrough changed val do (SetMaterial())
on chkShootThrough changed val do (SetMaterial())
on chkShootThroughFX changed val do (SetMaterial())
on chkPath changed val do (SetMaterial())
on chkSetPedPop changed val do (SetMaterial())
on spnPedDensity changed val do
(
chkSetPedPop.checked = true
SetMaterial()
)
on chkCover changed val do (SetMaterial())
on chkCamera changed val do (SetMaterial())
on chkProcCullImmune changed val do (SetMaterial())
on chkRoadRoad changed val do (SetMaterial())
on chkRoadPath changed val do (SetMaterial())
on chkRoadTrail changed val do (SetMaterial())
on chkNotHorseWalkable changed val do (SetMaterial())
on btnEditLock changed state do
(
-- Disable requested editing if network-sync failed earlier:
if (gRsTexToColl.NetworkErrorShown) do
(
BtnEditLock.Checked = False
BtnEditLock.Enabled = False
)
EditControls.Enabled = BtnEditLock.Checked
SetRexCtrlsEnabled()
)
on RsCollisionSetRoll open do
(
-- Initialise tech-art banner:
bannerStruct.setup()
Format "\nCollision Setter XMLs saved to folder:\n %\n" (RsMakeBackSlashes gRsTexToColl.collSetXmlPath)
Format "Locally cached to:\n %\n\n" (RsMakeBackSlashes gRsTexToColl.collSetCachePath)
-- Set rollout to fit the flag-changes box:
RsCollisionSetRoll.height = lblProgStatus.pos.y + 18
editControls.enabled = btnEditLock.checked
RexControls.Enabled = False
-- Set default paths:
gRsTexToColl.SetupPaths()
-- Do initial data-sync on startup:
gRsTexToColl.LocalCacheSync()
-- Disable edit-control if network-sync failed:
BtnEditLock.Enabled = (not gRsTexToColl.NetworkErrorShown)
SetupList()
callbacks.addscript #selectionSetChanged "RsCollisionSetRoll.updateSelectionSet (selection as array)" id:#collisionSet
UpdateSelectionSet (selection as array)
)
on RsCollisionSetRoll close do
(
try (destroyDialog collSet_showBmpRoll) catch ()
callbacks.removescripts id:#collisionSet
gc light:true
(dotnetclass "system.gc").collect()
)
)
createDialog RsCollisionSetRoll