Files
2025-09-29 00:52:08 +02:00

1879 lines
88 KiB
Plaintext
Executable File

---------------------------------------------------------------------------------------------------------------------------------------
-- RSL_CollisionOps2Create
-- By Paul Truss
-- Senior Technical Artist
-- Rockstar Games London
-- 12/01/2011
--
-- Modified for Rockstar North by Neil Gregory
-- 07/2011
--
-- Structure containing functions and UI used by RSL_CollisionOps2 in create mode
---------------------------------------------------------------------------------------------------------------------------------------
-- Struct used to store oriented bounding box information
struct RSL_OBB
(
size = [0,0,0], -- bounding box size
matrix -- transformation matrix
)
-- main struct
struct RSL_CollisionOps2Create
(
---------------------------------------------------------------------------------------------------------------------------------------
-- Struct variables
---------------------------------------------------------------------------------------------------------------------------------------
INIfile = (RsConfigGetWildWestDir() + "/etc/config/general/collisionOps2.ini"),
boxParameterArray = #(),
percentPaddingArray = #(),
newCollisionMeshArray = #(),
-- standard attribute indices
idxColType = getAttrIndex "Gta Collision" "Coll Type",
idxStairs = getAttrIndex "Gta Collision" "Stairs",
idxNoClimb = getAttrIndex "Gta Collision" "Non Climable",
idxSee = getAttrIndex "Gta Collision" "See Through",
idxNoCamera = getAttrIndex "Gta Collision" "Non Camera Collidable",
idxShoot = getAttrIndex "Gta Collision" "Shoot Through",
idxWet = getAttrIndex "Gta Collision" "Wet",
idxPath = getAttrIndex "Gta Collision" "Path",
idxPiece = getAttrIndex "Gta Collision" "Piece Type",
idxDay = getAttrIndex "Gta Collision" "Day Brightness",
idxNight = getAttrIndex "Gta Collision" "Night Brightness",
idxAudio = getAttrIndex "Gta Collision" "Audio Material",
idxRoomID = getAttrIndex "Gta Collision" "Room ID",
--idxLeeds = getAttrIndex "Gta Collision" "Edited by Leeds",
idxBVH = getAttrIndex "Gta Collision" "BVH Bound",
idxProcTint = getAttrIndex "Gta Collision" "Use Procedural Tint",
idxClothColl = getAttrIndex "Gta Collision" "Is Cloth Collision",
currentTool, -- variable containing the interface for the current collision object mode
lastType, -- variable containg the name of the last surface type
lastBoxType, -- variable containing the name of the last box parameters
currentBoxParams, -- variable containing the UI for the current box parameters
---------------------------------------------------------------------------------------------------------------------------------------
-- UI variables
---------------------------------------------------------------------------------------------------------------------------------------
toolTip = dotNetObject "ToolTip",
createTableLayout,createButton,deleteButton,statusLabel,
boxCheckButton,sphereCheckButton,cylinderCheckButton,meshCheckButton,
parametersGroup,attributesGroup,createGroup,
boxParametersTableLayout,bestAlignButton,offsetTypeCheckButton,percentTypeCheckButton,
lockAxesButton,
radiusNumeric,
bestAlignButton,useShortestAxis,paddingNumeric,
ignoreOpenEdgeCheckButton,convertToCollisionCheckButton,angleNumeric,
expandButton,
attributesTableLayout,surfaceTypeButton,cameraCheckBox,physicsCheckBox,hiDetailCheckBox,locoCheckBox,
stairsCheckBox,noCoverCheckBox,noClimbCheckBox,pathCheckBox,seeCheckBox,noCameraCheckBox,shootCheckBox,noDecalCheckBox,
noNavMeshCheckBox,noRagDollCheckBox,noParticleCheckBox,wetCheckBox,
pieceTypeButton,dayNumeric,nightNumeric,audioTextBox,roomIDNumeric,BVHCheckBox,procTintCheckBox,clothCollTintCheckBox,
proceduralTypeButton,pedMultiplierNumeric,miloRoomButton,
---------------------------------------------------------------------------------------------------------------------------------------
--
-- FUNCTIONS
--
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
-- disableAccelerators() Called when the user enters any control that needs keyboard input e.g. a textBox
---------------------------------------------------------------------------------------------------------------------------------------
fn disableAccelerators s e =
(
enableAccelerators = false
),
---------------------------------------------------------------------------------------------------------------------------------------
-- decimalToFloat() Converts the value of the parsed control from a dotNet decimal to a max script float
---------------------------------------------------------------------------------------------------------------------------------------
fn decimalToFloat control =
(
local dValue = getProperty control #value asDotNetObject:true
local fValue = (dotNetClass "System.Decimal").ToSingle dValue
),
---------------------------------------------------------------------------------------------------------------------------------------
-- calculateMaxMin() Calculates the maximum and minimum bounds of the parsed pos (array of vertex positions). Stores the
-- results to the parsed &maximum &minimum point3 variables.
---------------------------------------------------------------------------------------------------------------------------------------
mapped fn calculateMaxMin pos &maximum &minimum =
(
-- if any one of the pos axes is outside the bounds of &maximum or &minimum, set the relevant axis
if pos.x > maximum.x then maximum.x = pos.x
if pos.y > maximum.y then maximum.y = pos.y
if pos.z > maximum.z then maximum.z = pos.z
if pos.x < minimum.x then minimum.x = pos.x
if pos.y < minimum.y then minimum.y = pos.y
if pos.z < minimum.z then minimum.z = pos.z
),
---------------------------------------------------------------------------------------------------------------------------------------
-- OBBFromAngle() Returns an RSL_OBB struct based on the parsed vertPositions and rotation.
---------------------------------------------------------------------------------------------------------------------------------------
fn OBBFromAngle vertPositions rotation =
(
local maximum = [-999999999,-999999999,-999999999]
local minimum = [999999999,999999999,999999999]
-- get the bounds for the parsed vertPositions
calculateMaxMin vertPositions maximum minimum
-- calculate the size and transform for the RSL_OBB
local size = (maximum - minimum)
local center = ((maximum + minimum) * 0.5) * rotation
local matrix = rotation as matrix3
matrix.translation = center
RSL_OBB size:size matrix:matrix
),
---------------------------------------------------------------------------------------------------------------------------------------
-- gatherVertextPositions() Returns an array of vertex positions for the parsed object based on the parsed faceSelection
---------------------------------------------------------------------------------------------------------------------------------------
fn gatherVertextPositions object faceSelection =
(
local result
-- check to see what class the object is and use the correct functions to get the vertex positions
case (classOf object.baseObject) of
(
editable_mesh:
(
result = for index in (meshOp.getVertsUsingFace object faceSelection) collect object.verts[index].pos
)
editable_poly:
(
result = for index in (polyOp.getVertsUsingFace object faceSelection) collect object.verts[index].pos
)
)
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- findOBB() Calculates and returns the smallest RSL_OBB for the parsed opbject based on the parsed faceSelection
-- which is used to gather the vertices, the parsed angleStep which is used to rotate the vertex positions by a minimum amount,
-- the parsed maximumAngle which controls the total rotation and the parsed baseMatrix which is used as a starting point
-- for the rotation.
---------------------------------------------------------------------------------------------------------------------------------------
fn findOBB object faceSelection angleStep maximumAngle baseMatrix =
(
-- get the vertex positions from the object based on the face selection.
local vertPositions = gatherVertextPositions object faceSelection
-- create a starting RSL_OBB
local firstOBB = OBBFromAngle vertPositions (eulerToQuat (eulerAngles 0 0 0))
-- set the smallestOBB to the firstOBB and setup the smallest size based on the smallestOBB
local smallestOBB = firstOBB
local smallestSize = smallestOBB.size.x + smallestOBB.size.y + smallestOBB.size.z
-- loop through each axis from the -maximumAngle to the maximumAngle by the angleStep
for x = -maximumAngle to maximumAngle by angleStep do
(
for y = -maximumAngle to maximumAngle by angleStep do
(
for z = -maximumAngle to maximumAngle by angleStep do
(
-- setup the euler variable so that it contains the rotation from the parsed baseMatrix
-- and assign it to the quatRotation variable as a quat
local baseEuler = (baseMatrix as eulerAngles)
local euler = eulerAngles x y z
euler.x += baseEuler.x
euler.y += baseEuler.y
euler.z += baseEuler.z
local quatRotation = eulerToQuat euler
-- get the current vertex positions rotated by the quatRotation
local currentVertPositions = (for pos in vertPositions collect (pos * (inverse quatRotation)))
-- generate an RSL_OBB from the currentVertPositions & quatRotation and calculate the size
local currentOBB = (OBBFromAngle currentVertPositions quatRotation)
local currentSize = currentOBB.size.x + currentOBB.size.y + currentOBB.size.z
-- if the size of the currentOBB is smaller than the smallestSize, we have a smaller RSL_OBB so we
-- set the smallestOBB to the currentOBB and the smallestSize to the currentSize
if currentSize < smallestSize then
(
smallestOBB = currentOBB
smallestSize = currentSize
)
)
)
)
smallestOBB
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setAttribute() Sets the standard attributes for the parsed object based on the attribute parameters
---------------------------------------------------------------------------------------------------------------------------------------
fn setAttribute object =
(
try (setAttr object idxColType surfaceTypeButton.text) catch(format "S Type:%" (getCurrentException()))
try (setAttr object idxStairs stairsCheckBox.checked) catch(format "Stairs:%" (getCurrentException()))
try (setAttr object idxNoClimb noClimbCheckBox.checked) catch(format "No Climb:%" (getCurrentException()))
try (setAttr object idxSee seeCheckBox.checked) catch(format "See:%" (getCurrentException()))
try (setAttr object idxNoCamera noCameraCheckBox.checked) catch(format "No Camera:%" (getCurrentException()))
try (setAttr object idxShoot shootCheckBox.checked) catch(format "Shoot:%" (getCurrentException()))
try (setAttr object idxWet wetCheckBox.checked) catch(format "Wet:%" (getCurrentException()))
try (setAttr object idxPiece ((findItem ::RSL_CollisionOps.attribute.pieceTypeArray pieceTypeButton.text) - 1)) catch(format "Piece:%" (getCurrentException()))
try (setAttr object idxPath pathCheckBox.checked) catch(format "Path:%" (getCurrentException()))
try (setAttr object idxDay dayNumeric.value) catch(format "Day:%" (getCurrentException()))
try (setAttr object idxNight nightNumeric.value) catch(format "Night:%" (getCurrentException()))
try (setAttr object idxAudio audioTextBox.text) catch(format "Audio:%" (getCurrentException()))
try (setAttr object idxRoomID roomIDNumeric.value) catch(format "Room:%" (getCurrentException()))
try (setAttr object idxBVH BVHCheckBox.checked) catch(format "BVH:%" (getCurrentException()))
try (setAttr object idxProcTint ProcTintCheckBox.checked) catch(format "ProcTint:%" (getCurrentException()))
try (setAttr object idxClothColl clothCollTintCheckBox.checked) catch(format "ClothColl:%" (getCurrentException()))
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setRexBound() Sets the rexbound attributes for the parsed object based on the attribute parameters
---------------------------------------------------------------------------------------------------------------------------------------
fn setRexBound object =
(
-- create a new rexbound material ans set the surface type based on the surfaceTypeButton control
local newRexBoundMaterial = RexBoundMtl name:object.name
RexSetCollisionName newRexBoundMaterial surfaceTypeButton.text
if proceduralTypeButton.text != "NONE" then
(
RexSetProceduralName newRexBoundMaterial proceduralTypeButton.text
)
-- if the miloRoomButton control .tag has a valid miloRoom object assigned, we can set the roomNode parameter.
-- We only check that the node is valid rather than check that it's a miloRoom beacuse we only allow miloRooms
-- to be assigned to the control in the first place. We check that it's a valid node in case it has been deleted.
if miloRoomButton.tag != undefined and (isValidNode miloRoomButton.tag.value) then
(
RexSetRoomNode newRexBoundMaterial miloRoomButton.tag.value
)
if pedMultiplierNumeric.value > 0 then
(
RexSetPopDensity newRexBoundMaterial pedMultiplierNumeric.value
)
-- setup the flags based on the check state of the attributes
local flags = 0
/*
Stairs = 1 (bit0)
Non Climable = 2 (bit1)
See Through = 4 (bit2)
Shoot Through = 8 (bit3)
Doesnt provide cover = 16 (bit4)
Path = 32 (bit5)
Non Camera Collidable = 64 (bit6)
Spare 3 = 128(bit7)
No Decal = 256(bit8)
No Navmesh = 512(bit9)
No Ragdoll = 1024(bit10)
No particle effects = 4096 (bit12)
*/
if stairsCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 0)
)
if noCoverCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 4)
)
if noClimbCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 1)
)
if pathCheckBox.checked then flags = bit.or flags (bit.shift 1 5)
if seeCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 2)
)
if noCameraCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 6)
)
if shootCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 3)
)
if noDecalCheckBox.checked then flags = bit.or flags (bit.shift 1 8)
if noNavMeshCheckBox.checked then flags = bit.or flags (bit.shift 1 9)
if noRagDollCheckBox.checked then flags = bit.or flags (bit.shift 1 10)
if noParticleCheckBox.checked then flags = bit.or flags (bit.shift 1 12)
RexsetCollisionFlags newRexBoundMaterial flags
-- assign the new rexbound material to the object
object.material = newRexBoundMaterial
),
---------------------------------------------------------------------------------------------------------------------------------------
-- makeBox() Creates a Collision Box for the parsed object based on the parsed faceSelection
---------------------------------------------------------------------------------------------------------------------------------------
fn makeBox object faceSelection =
(
local okToContinue = true
local bound
local paddingX = 0
local paddingY = 0
local paddingZ = 0
local offsetX = 0
local offsetY = 0
local offsetZ = 0
-- if we're using the offset parameters, we setup the padding and offset variables
if offsetTypeCheckButton.checked then
(
paddingX = ((decimalToFloat boxParameterArray[1]) + (decimalToFloat boxParameterArray[2]))
paddingY = ((decimalToFloat boxParameterArray[3]) + (decimalToFloat boxParameterArray[4]))
paddingZ = ((decimalToFloat boxParameterArray[5]) + (decimalToFloat boxParameterArray[6]))
offsetX = ((decimalToFloat boxParameterArray[2]) + -(decimalToFloat boxParameterArray[1])) * 0.5
offsetY = ((decimalToFloat boxParameterArray[4]) + -(decimalToFloat boxParameterArray[3])) * 0.5
offsetZ = ((decimalToFloat boxParameterArray[6]) + -(decimalToFloat boxParameterArray[5])) * 0.5
)
-- if we're aligning to the selection, we calculate the oriented bounding box and assign it to the bound variable
if bestAlignButton.checked then
(
-- we do this three times, each time the angle step and maximum angle are
-- smaller so that we get as close as we can within a reasonable amount of time.
bound = findOBB object faceSelection 10.0 90.0 (matrix3 1)
bound = findOBB object faceSelection 2.0 10.0 bound.matrix
bound = findOBB object faceSelection 0.5 2.0 bound.matrix
-- if we're using the percent parameters, we multiply the bound size by the percent parameters
-- to get our final size. Otherwise we use the padding variables to get our final size
if percentTypeCheckButton.checked then
(
bound.size.x = bound.size.x * (decimalToFloat percentPaddingArray[1]) / 100.0
bound.size.y = bound.size.y * (decimalToFloat percentPaddingArray[2]) / 100.0
bound.size.z = bound.size.z * (decimalToFloat percentPaddingArray[3]) / 100.0
)
else
(
bound.size.x += paddingX
bound.size.y += paddingY
bound.size.z += paddingZ
)
-- add the offset variables to the transformation matrix of our bound
bound.matrix.row4 += [offsetX,offsetY,offsetZ]
)
else
(
-- we're not aligning to the selection so...
local maxBounds = [-999999999999,-999999999999,-999999999999]
local minBounds = [999999999999,999999999999,999999999999]
local vertexPosArray
-- gather an array of the vertex positions based on the faceSelection
case classOf object of
(
editable_mesh:
(
vertexPosArray = for v in ((meshOp.getVertsUsingFace object faceSelection) as array) collect object.verts[v].pos
)
editable_poly:
(
vertexPosArray = for v in ((polyOp.getVertsUsingFace object faceSelection) as array) collect object.verts[v].pos
)
)
-- calculate the bounds of the vertexPosArray and assign the values to the maxBounds and minBounds
calculateMaxMin vertexPosArray maxBounds minBounds
-- if we're using the percent parameters, we create the oriented bounding box based on the maxBounds, minBounds, percent parameters and offset variables
if percentTypeCheckButton.checked then
(
bound = RSL_OBB size:[(abs (maxBounds.x - minBounds.x)) * (decimalToFloat percentPaddingArray[1]) / 100.0, \
(abs (maxBounds.y - minBounds.y)) * (decimalToFloat percentPaddingArray[2]) / 100.0, \
(abs (maxBounds.z - minBounds.z)) * (decimalToFloat percentPaddingArray[3]) / 100.0]
bound.matrix = transMatrix (((maxBounds + minBounds) * 0.5) + [offsetX,offsetY,offsetZ])
)
else
(
-- we're using the offset parameters so we create the oriented bounding box based on the maxBounds, minBounds, padding and offset variables
bound = RSL_OBB size:[(abs (maxBounds.x - minBounds.x)) + paddingX, (abs (maxBounds.y - minBounds.y)) + paddingY, (abs (maxBounds.z - minBounds.z)) + paddingZ]
bound.matrix = transMatrix (((maxBounds + minBounds) * 0.5) + [offsetX,offsetY,offsetZ])
-- check to see if the bound size for each axis is not a minus number. this means that the padding values are to big somewhere
if bound.size.x < 0 or bound.size.y < 0 or bound.size.z < 0 then
(
local errorString = stringStream ""
format "One or more of the padding values is too high and the resulting mesh cannot be created.\n\n" to:errorString
if bound.size.x < 0 then
(
format "Width (X) is:%. Change either +X or -X so that the width is greater than 0\n" boxWidth to:errorString
)
if bound.size.y < 0 then
(
format "Length (y) is:%. Change either +Y or -Y so that the length is greater than 0\n" boxLength to:errorString
)
if bound.size.z < 0 then
(
format "Height (Z) is:%. Change either +Z or -Z so that the height is greater than 0\n" boxHeight to:errorString
)
messageBox errorString title:"Error..."
okToContinue = false
)
)
)
bound = RsFindMinBox object
-- if everthing is ok, we have a valid bound RSL_OBB and we can create the collision box
if okToContinue then
(
newCollisionMesh = Col_Box name:(uniqueName (object.name + " - colBox"))
newCollisionMesh.wireColor = orange
newCollisionMesh.transform = bound.transform
newCollisionMesh.length = bound.length
newCollisionMesh.width = bound.width
newCollisionMesh.height = bound.height
newCollisionMesh.parent = object
setAttribute newCollisionMesh
append newCollisionMeshArray newCollisionMesh
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- makeMesh() Creates a Collision Mesh for the parsed object based on the parsed faceSelection
---------------------------------------------------------------------------------------------------------------------------------------
fn makeMesh object faceSelection =
(
-- depending on the class of our object, we create the newCollisionMesh using the correct functions
case (classOf object) of
(
Editable_mesh:
(
newCollisionMesh = Editable_mesh name:(uniqueName (object.name + " - colMesh"))
newCollisionMesh.transform = object.transform
-- detach the faceSelection from the object as a copy and assign it to the mesh property of our newCollisionMesh
newCollisionMesh.mesh = meshOp.detachFaces object faceSelection delete:false asMesh:true
-- set the face ID for all faces to 1 because we're going to assign a rexbound material to the newCollisionMesh
for f in newCollisionMesh.faces do
(
setFaceMatID newCollisionMesh f.index 1
)
)
Editable_poly:
(
-- generate a name for our newCollisionMesh
local name = (uniqueName (object.name + " - colMesh"))
-- detach the faceSelection from the object as a copy to a new node and then get the node by it's name
polyOp.detachFaces object faceSelection delete:false asNode:true name:name
newCollisionMesh = getNodeByName name
-- set the face ID for all faces to 1 because we're going to assign a rexbound material to the newCollisionMesh
polyOp.setFaceMatID newCollisionMesh (for f in newCollisionMesh.faces collect f.index) 1
)
)
newCollisionMesh.material = undefined
newCollisionMesh.showVertexColors = false
newCollisionMesh.wireColor = orange
newCollisionMesh.pivot = object.pivot
newCollisionMesh.parent = object
resetXForm newCollisionMesh
convertTo newCollisionMesh Editable_poly
-- get the value of the angleNumeric parameter as a float
local currentAngle = (decimalToFloat angleNumeric)
-- if the currentAngle is greater than 0 we optimise the newCollisionMesh by removing edges
if currentAngle > 0.0 then
(
local edgeArray = #()
local vertArray = #()
-- loop through the edges checking if any of them have face angles less than the currentAngle
for edge in newCollisionMesh.edges do
(
local edgeFaces = (polyOp.getFacesUsingEdge newCollisionMesh edge) as array
if edgeFaces.count == 2 then
(
-- get the face normals for the 2 faces connected to the edge
local face1Normal = polyOp.getFaceNormal newCollisionMesh edgeFaces[1]
local face2Normal = polyOp.getFaceNormal newCollisionMesh edgeFaces[2]
-- calculate the angle difference between them
local angle = acos (dot face1Normal face2Normal)
-- if the angle is less than the currentAngle, we can remove the edge
if angle < currentAngle then
(
append edgeArray edge.index
-- we also add the vertx connected to the edge to see if they can be removed also
local verts = (polyOp.getVertsUsingEdge newCollisionMesh edge.index) as array
for v in verts do
(
appendIfUnique vertArray v
)
)
)
)
-- select the edges we want to remove and remove them
polyOp.setEdgeSelection newCollisionMesh edgeArray
newCollisionMesh.Remove selLevel:#Edge
local finalVertArray = #()
-- loop through the verts connected to the edges we removed and check to see if they are now connected to
-- less than 3 edges and append them to the finalVertArray if they are
for vert in vertArray do
(
local edges = (polyOp.getEdgesUsingVert newCollisionMesh vert) as array
if edges.count < 3 then
(
append finalVertArray vert
)
)
-- select the vertices we want to remove and remove them
polyOp.setVertSelection newCollisionMesh finalVertArray
newCollisionMesh.Remove selLevel:#Vertex
)
-- if we want to check for open edges
local okToConvert = true
if not ignoreOpenEdgeCheckButton.checked then
(
-- get the open edges
local openEdges = (polyop.getOpenEdges newCollisionMesh) as array
-- if we have open edges, we query the user if they would like to still convert to a collision mesh or leave the newCollisionMesh
-- as an editable poly object
if openEdges.count > 0 then
(
local warningStream = stringStream ""
format "There are holes in the collision mesh (open edges). This could be a problem for dynamic objects.\n" to:warningStream
format "Do you want to continue? Pressing no will leave the new collision object as an editable poly and will not assign any collision type attributes." to:warningStream
okToConvert = queryBox warningStream title:"Warning..."
if not okToConvert then
(
convertToCollisionCheckButton.checked = false
select newCollisionMesh
)
)
)
setRexBound newCollisionMesh
append newCollisionMeshArray newCollisionMesh
),
---------------------------------------------------------------------------------------------------------------------------------------
-- makeSphere() Creates a Collision Sphere for the parsed object based on the parsed faceSelection
---------------------------------------------------------------------------------------------------------------------------------------
fn makeSphere object faceSelection =
(
local maxBounds = [-999999999999,-999999999999,-999999999999]
local minBounds = [999999999999,999999999999,999999999999]
local vertexPosArray
-- gather an array of the vertex positions based on the faceSelection
case classOf object of
(
editable_mesh:
(
vertexPosArray = for v in ((meshOp.getVertsUsingFace object faceSelection) as array) collect object.verts[v].pos
)
editable_poly:
(
vertexPosArray = for v in ((polyOp.getVertsUsingFace object faceSelection) as array) collect object.verts[v].pos
)
)
-- calculate the bounds of the vertexPosArray and assign the values to the maxBounds and minBounds
calculateMaxMin vertexPosArray maxBounds minBounds
-- calculate the bound and padding
local bound = (maxBounds - minBounds) * 0.5
local paddingR = (decimalToFloat radiusNumeric)
local radius = bound.x
if radius < bound.y then radius = bound.y
if radius < bound.z then radius = bound.z
radius += paddingR
-- if the radius is less than 0, the radius padding is too small
if radius < 0.0 then
(
messageBox "The radius is less than zero. Reduce the Radius Padding and try again." title:"Error..."
)
else
(
newCollisionMesh = Col_Sphere name:(uniqueName (object.name + " - ColSph"))
newCollisionMesh.wireColor = orange
newCollisionMesh.pos = (maxBounds + minBounds) * 0.5
newCollisionMesh.radius = radius
newCollisionMesh.parent = object
setAttribute newCollisionMesh
append newCollisionMeshArray newCollisionMesh
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- makeCylinder() Creates a Collision Cylinder for the parsed object based on the parsed faceSelection
---------------------------------------------------------------------------------------------------------------------------------------
fn makeCylinder object faceSelection =
(
local okToContinue = true
local bound
local paddingFloat = (decimalToFloat paddingNumeric)
-- if we're aligning to the selection, we calculate the oriented bounding box and assign it to the bound variable
if bestAlignButton.checked then
(
bound = findOBB object faceSelection 10.0 45.0 (matrix3 1)
bound = findOBB object faceSelection 4.0 10.0 bound.matrix
bound = findOBB object faceSelection 1.0 4.0 bound.matrix
bound.size += paddingFloat
)
else
(
-- we're not aligning to the selection so...
local maxBounds = [-999999999999,-999999999999,-999999999999]
local minBounds = [999999999999,999999999999,999999999999]
local vertexPosArray
-- gather an array of the vertex positions based on the faceSelection
case classOf object of
(
editable_mesh:
(
vertexPosArray = for v in ((meshOp.getVertsUsingFace object faceSelection) as array) collect object.verts[v].pos
)
editable_poly:
(
vertexPosArray = for v in ((polyOp.getVertsUsingFace object faceSelection) as array) collect object.verts[v].pos
)
)
-- calculate the bounds of the vertexPosArray and assign the values to the maxBounds and minBounds
calculateMaxMin vertexPosArray maxBounds minBounds
-- create the bound from the maxBounds, minBounds and paddingFloat
bound = RSL_OBB size:[(abs (maxBounds.x - minBounds.x)) + paddingFloat, (abs (maxBounds.y - minBounds.y)) + paddingFloat, (abs (maxBounds.z - minBounds.z)) + paddingFloat]
bound.matrix = transMatrix ((maxBounds + minBounds) * 0.5)
-- if any of the bound axes are less than 0, the padding is too high
if bound.size.x < 0 or bound.size.y < 0 or bound.size.z < 0 then
(
local errorString = stringStream ""
format "The padding value is too high and the resulting mesh cannot be created. Increase or reduce the padding value." to:errorString
messageBox errorString title:"Error..."
okToContinue = false
)
)
if okToContinue then
(
newCollisionMesh = Col_Cylinder name:(uniqueName (object.name + " - ColCylinder"))
newCollisionMesh.wireColor = orange
newCollisionMesh.transform = bound.matrix
local radius
local length
-- if we're aligning to the selection and we want the shortest axis to be the main cylindrical axis,
-- we must rotate the newCollisionMesh based on which bound axis is smaller
if bestAlignButton.Checked and useShortestAxis.checked then
(
radius = (amax #(bound.size.x, bound.size.y, bound.size.z)) * 0.5
length = amin #(bound.size.x, bound.size.y, bound.size.z)
-- if the x axis is the smallest, we rotate 90 degrees aroung z
-- if the z axis is the smallest, we rotate 90 degrees aroung x
case of
(
(bound.size.x < bound.size.y and bound.size.x < bound.size.z): (in coordsys local rotate newCollisionMesh (eulerangles 0 0 90))
(bound.size.z < bound.size.x and bound.size.z < bound.size.y): (in coordsys local rotate newCollisionMesh (eulerangles 90 0 0))
)
)
else
(
-- we're not aligning and we're not using the shortest axis so we must rotate the newCollisionMesh
-- based on which bound axis is bigger
radius = (amin #(bound.size.x, bound.size.y, bound.size.z)) * 0.5
length = amax #(bound.size.x, bound.size.y, bound.size.z)
-- if the x axis is the biggest, we rotate 90 degrees aroung z
-- if the z axis is the biggest, we rotate 90 degrees aroung x
case of
(
(bound.size.x > bound.size.y and bound.size.x > bound.size.z): (in coordsys local rotate newCollisionMesh (eulerangles 0 0 90))
(bound.size.z > bound.size.x and bound.size.z > bound.size.y): (in coordsys local rotate newCollisionMesh (eulerangles 90 0 0))
)
)
newCollisionMesh.radius = radius
newCollisionMesh.length = length
newCollisionMesh.parent = object
setAttribute newCollisionMesh
append newCollisionMeshArray newCollisionMesh
)
),
---------------------------------------------------------------------------------------------------------------------------------------
--
-- UI FUNCTIONS
--
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
-- createMeshTypeControls() Creates the parameter controls for mesh collision objects. Called when the user presses the mesh
-- mode
---------------------------------------------------------------------------------------------------------------------------------------
fn createMeshTypeControls =
(
meshParametersTableLayout = RS_dotNetUI.tableLayout "meshParametersTableLayout" \
collumns:#((dataPair type:"Percent" value:50)) \
rows:(for i = 1 to 3 collect (dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
ignoreOpenEdgeCheckButton = RS_dotNetUI.checkBox "ignoreOpenEdgeCheckButton" text:("Ignore Open Edges") \
textAlign:RS_dotNetPreset.CA_MiddleLeft checkAlign:RS_dotNetPreset.CA_MiddleRight \
dockStyle:RS_dotNetPreset.DS_Fill
convertToCollisionCheckButton = RS_dotNetUI.checkBox "convertToCollisionCheckButton" text:("Convert to Collision Mesh") \
textAlign:RS_dotNetPreset.CA_MiddleLeft checkAlign:RS_dotNetPreset.CA_MiddleRight \
dockStyle:RS_dotNetPreset.DS_Fill
convertToCollisionCheckButton.Checked = true
angleTableLayout = RS_dotNetUI.tableLayout "angleTableLayout" \
collumns:#((dataPair type:"Percent" value:50), (dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
angleLabel = RS_dotNetUI.Label "angleLabel" text:(" Optimisation Angle") textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
angleNumeric = RS_dotNetUI.Numeric "angleNumeric" value:0.0 range:#(45.0, 0.0, 0.1, 1) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler angleNumeric "Enter" disableAccelerators
angleTableLayout.Controls.Add angleLabel 0 0
angleTableLayout.Controls.Add angleNumeric 1 0
meshParametersTableLayout.Controls.Add ignoreOpenEdgeCheckButton 0 0
meshParametersTableLayout.Controls.Add convertToCollisionCheckButton 0 1
meshParametersTableLayout.Controls.Add angleTableLayout 0 2
meshParametersTableLayout
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchBestAlignCheck() Dispatches bestAlignCheck(), called when the use checks the bestAlignButton
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchBestAlignCheck s e =
(
::RSL_CollisionOps.createUI.bestAlignCheck s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- bestAlignCheck() Enables the useShortestAxis check button based on the check state of the bestAlignButton. You can
-- only use useShortestAxis is you're aligning to the selection.
---------------------------------------------------------------------------------------------------------------------------------------
fn bestAlignCheck s e =
(
useShortestAxis.enabled = bestAlignButton.Checked
),
---------------------------------------------------------------------------------------------------------------------------------------
-- createCylinderTypeControls() Creates the parameter controls for cylinder collision objects. Called when the user presses
-- the cylinder mode
---------------------------------------------------------------------------------------------------------------------------------------
fn createCylinderTypeControls =
(
cylinderParametersTableLayout = RS_dotNetUI.tableLayout "cylinderParametersTableLayout" \
collumns:#((dataPair type:"Percent" value:50)) \
rows:(for i = 1 to 3 collect (dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
bestAlignButton = RS_dotNetUI.checkBox "bestAlignButton" text:("Align To Selection") \
textAlign:RS_dotNetPreset.CA_MiddleLeft checkAlign:RS_dotNetPreset.CA_MiddleRight \
dockStyle:RS_dotNetPreset.DS_Fill
bestAlignButton.Checked = true
dotnet.addEventHandler bestAlignButton "click" dispatchBestAlignCheck
useShortestAxis = RS_dotNetUI.checkBox "useShortestAxis" text:("Align to Shortest Axis") \
textAlign:RS_dotNetPreset.CA_MiddleLeft checkAlign:RS_dotNetPreset.CA_MiddleRight \
dockStyle:RS_dotNetPreset.DS_Fill
useShortestAxis.enabled = bestAlignButton.Checked
cylinderPaddingTableLayout = RS_dotNetUI.tableLayout "cylinderPaddingTableLayout" \
collumns:#((dataPair type:"Percent" value:50), (dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
paddingLabel = RS_dotNetUI.Label "paddingLabel" text:(" Padding") textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
paddingNumeric = RS_dotNetUI.Numeric "paddingNumeric" value:0.0 range:#(100.0, -100.0, 0.001, 3) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler paddingNumeric "Enter" disableAccelerators
cylinderPaddingTableLayout.Controls.Add paddingLabel 0 0
cylinderPaddingTableLayout.Controls.Add paddingNumeric 1 0
cylinderParametersTableLayout.Controls.Add bestAlignButton 0 0
cylinderParametersTableLayout.Controls.Add useShortestAxis 0 1
cylinderParametersTableLayout.Controls.Add cylinderPaddingTableLayout 0 2
cylinderParametersTableLayout
),
---------------------------------------------------------------------------------------------------------------------------------------
-- createSphereTypeControls() Creates the parameter controls for sphere collision objects. Called when the user presses
-- the sphere mode
---------------------------------------------------------------------------------------------------------------------------------------
fn createSphereTypeControls =
(
sphereParametersTableLayout = RS_dotNetUI.tableLayout "sphereParametersTableLayout" \
collumns:#((dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
radiusPaddingTableLayout = RS_dotNetUI.tableLayout "radiusPaddingTableLayout" \
collumns:#((dataPair type:"Percent" value:50), (dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
radiusLabel = RS_dotNetUI.Label "radiusLabel" text:(" Radius Padding") textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
radiusNumeric = RS_dotNetUI.Numeric "radiusNumeric" value:0.0 range:#(100.0, -100.0, 0.001, 3) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler radiusNumeric "Enter" disableAccelerators
radiusPaddingTableLayout.Controls.Add radiusLabel 0 0
radiusPaddingTableLayout.Controls.Add radiusNumeric 1 0
sphereParametersTableLayout.Controls.Add radiusPaddingTableLayout 0 0
sphereParametersTableLayout
),
---------------------------------------------------------------------------------------------------------------------------------------
-- offsetPaddingControls() Creates the parameter controls for box collision objects in offset padding mode. Called when the
-- user presses the offsetTypeCheckButton in box mode
---------------------------------------------------------------------------------------------------------------------------------------
fn offsetPaddingControls =
(
offsetPaddingTableLayout = RS_dotNetUI.tableLayout "offsetPaddingTableLayout" \
collumns:#((dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50)) \
rows:(for i = 1 to 6 collect (dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
xPaddingLabel = RS_dotNetUI.Label "xPaddingLabel" text:(" X Padding (-X +X)") \
textAlign:RS_dotNetPreset.CA_MiddleLeft borderStyle:RS_dotNetPreset.BS_None \
dockStyle:RS_dotNetPreset.DS_Fill
minusXPadding = RS_dotNetUI.Numeric "minusXPadding" value:0.0 range:#(100.0, -100.0, 0.001, 3) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler minusXPadding "Enter" disableAccelerators
plusXPadding = RS_dotNetUI.Numeric "plusXPadding" value:0.0 range:#(100.0, -100.0, 0.001, 3) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler plusXPadding "Enter" disableAccelerators
yPaddingLabel = RS_dotNetUI.Label "yPaddingLabel" text:(" Y Padding (-Y +Y)") textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
minusYPadding = RS_dotNetUI.Numeric "minusYPadding" value:0.0 range:#(100.0, -100.0, 0.001, 3) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler minusYPadding "Enter" disableAccelerators
plusYPadding = RS_dotNetUI.Numeric "plusYPadding" value:0.0 range:#(100.0, -100.0, 0.001, 3) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler plusYPadding "Enter" disableAccelerators
zPaddingLabel = RS_dotNetUI.Label "zPaddingLabel" text:(" Z Padding (-Z +Z)") textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
minusZPadding = RS_dotNetUI.Numeric "minusZPadding" value:0.0 range:#(100.0, -100.0, 0.001, 3) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler minusZPadding "Enter" disableAccelerators
plusZPadding = RS_dotNetUI.Numeric "plusZPadding" value:0.0 range:#(100.0, -100.0, 0.001, 3) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler plusZPadding "Enter" disableAccelerators
offsetPaddingTableLayout.Controls.Add xPaddingLabel 0 0
offsetPaddingTableLayout.Controls.Add minusXPadding 0 1
offsetPaddingTableLayout.Controls.Add plusXPadding 1 1
offsetPaddingTableLayout.Controls.Add yPaddingLabel 0 2
offsetPaddingTableLayout.Controls.Add minusYPadding 0 3
offsetPaddingTableLayout.Controls.Add plusYPadding 1 3
offsetPaddingTableLayout.Controls.Add zPaddingLabel 0 4
offsetPaddingTableLayout.Controls.Add minusZPadding 0 5
offsetPaddingTableLayout.Controls.Add plusZPadding 1 5
boxParameterArray = #(plusXPadding,minusXPadding,plusYPadding,minusYPadding,plusZPadding,minusZPadding)
offsetPaddingTableLayout
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchLockAxesCheck() Dispatches lockAxesCheck(), called when the user checks the lockAxesButton in the percent padding
-- controls of the box mode.
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchLockAxesCheck s e =
(
::RSL_CollisionOps.createUI.lockAxesCheck s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- lockAxesCheck() Sets the percent controls to the same value when checked is true
---------------------------------------------------------------------------------------------------------------------------------------
fn lockAxesCheck s e =
(
if lockAxesButton.checked then
(
local floatValue = decimalToFloat percentPaddingArray[1]
for i = 2 to percentPaddingArray.count where entry != s do
(
percentPaddingArray[i].value = floatValue
)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchPercentPaddingValueChanged() Dispatches percentPaddingValueChanged(), called when the user changes a value in
-- one of the percent padding controls
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchPercentPaddingValueChanged s e =
(
::RSL_CollisionOps.createUI.percentPaddingValueChanged s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- percentPaddingValueChanged() Sets the percent controls to the same value if the lockAxesButton is checked
---------------------------------------------------------------------------------------------------------------------------------------
fn percentPaddingValueChanged s e =
(
if lockAxesButton.checked then
(
local floatValue = decimalToFloat s
for entry in percentPaddingArray where entry != s do
(
entry.value = floatValue
)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- offsetPaddingControls() Creates the parameter controls for box collision objects in percent padding padding mode. Called
-- when the user presses the percentTypeCheckButton in box mode
---------------------------------------------------------------------------------------------------------------------------------------
fn percentPaddingControls =
(
percentPaddingTableLayout = RS_dotNetUI.tableLayout "percentPaddingTableLayout" \
collumns:#((dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50)) \
rows:(for i = 1 to 4 collect (dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
lockAxesButton = RS_dotNetUI.checkBox "bestAlignButton" text:("Lock Axes") \
textAlign:RS_dotNetPreset.CA_MiddleLeft checkAlign:RS_dotNetPreset.CA_MiddleRight \
dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler lockAxesButton "click" dispatchLockAxesCheck
XLabel = RS_dotNetUI.Label "XLabel" text:(" X Percent:") textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
XPadding = RS_dotNetUI.Numeric "XPadding" value:100.0 range:#(1000.0, 0, 0.1, 1) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler XPadding "ValueChanged" dispatchPercentPaddingValueChanged
dotnet.addEventHandler XPadding "Enter" disableAccelerators
YLabel = RS_dotNetUI.Label "YLabel" text:(" Y Percent:") textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
YPadding = RS_dotNetUI.Numeric "YPadding" value:100.0 range:#(1000.0, 0, 0.1, 1) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler YPadding "ValueChanged" dispatchPercentPaddingValueChanged
dotnet.addEventHandler YPadding "Enter" disableAccelerators
ZLabel = RS_dotNetUI.Label "ZLabel" text:(" Z Percent:") textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
ZPadding = RS_dotNetUI.Numeric "ZPadding" value:100.0 range:#(1000.0, 0, 0.1, 1) dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler ZPadding "ValueChanged" dispatchPercentPaddingValueChanged
dotnet.addEventHandler ZPadding "Enter" disableAccelerators
percentPaddingTableLayout.Controls.Add lockAxesButton 0 0
percentPaddingTableLayout.Controls.Add XLabel 0 1
percentPaddingTableLayout.Controls.Add XPadding 1 1
percentPaddingTableLayout.Controls.Add YLabel 0 2
percentPaddingTableLayout.Controls.Add YPadding 1 2
percentPaddingTableLayout.Controls.Add ZLabel 0 3
percentPaddingTableLayout.Controls.Add ZPadding 1 3
percentPaddingTableLayout.SetColumnSpan lockAxesButton 2
percentPaddingArray = #(XPadding, YPadding, ZPadding)
percentPaddingTableLayout
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchBoxPaddingTypeCheck() Dispatches boxPaddingTypeCheck(), called when the user presses any of the box parameters
-- mode buttons
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchBoxPaddingTypeCheck s e =
(
::RSL_CollisionOps.createUI.boxPaddingTypeCheck s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- boxPaddingTypeCheck() Switches the box parameters mode
---------------------------------------------------------------------------------------------------------------------------------------
fn boxPaddingTypeCheck s e =
(
-- make sure the pressed mode is always checked
s.checked = true
-- if the pressed mode is not the last mode we pressed, we need to create the controls
if s != lastBoxType then
(
case s.name of
(
"offsetTypeCheckButton":
(
-- un-check the percentTypeCheckButton
percentTypeCheckButton.checked = false
-- dispose of the currentBoxParams and create the offset padding controls
if currentBoxParams != undefined then
(
currentBoxParams.dispose()
)
currentBoxParams = offsetPaddingControls()
-- assign the currentBoxParams controls to the boxParametersTableLayout
boxParametersTableLayout.Controls.Add currentBoxParams 0 2
boxParametersTableLayout.SetColumnSpan currentBoxParams 2
-- set the row to the correct height
createTableLayout.RowStyles.Item[1].Height = 220
-- depending on weather the attributes group is expanded or not, set the correct height for the main form
case attributesGroup.text of
(
default:(::RSL_CollisionOps.CollisionForm.Height = 554)
" Attributes - Basic":(::RSL_CollisionOps.CollisionForm.Height = 554)
" Attributes - Advanced":(::RSL_CollisionOps.CollisionForm.Height = 785)
)
)
"percentTypeCheckButton":
(
-- un-check the offsetTypeCheckButton
offsetTypeCheckButton.checked = false
-- dispose of the currentBoxParams and create the percent padding controls
if currentBoxParams != undefined then
(
currentBoxParams.dispose()
)
currentBoxParams = percentPaddingControls()
-- assign the currentBoxParams controls to the boxParametersTableLayout
boxParametersTableLayout.Controls.Add currentBoxParams 0 2
boxParametersTableLayout.SetColumnSpan currentBoxParams 2
-- set the row to the correct height
createTableLayout.RowStyles.Item[1].Height = 172
-- depending on weather the attributes group is expanded or not, set the correct height for the main form
case attributesGroup.text of
(
default:(::RSL_CollisionOps.CollisionForm.Height = 506)
" Attributes - Basic":(::RSL_CollisionOps.CollisionForm.Height = 506)
" Attributes - Advanced":(::RSL_CollisionOps.CollisionForm.Height = 736)
)
)
)
)
lastBoxType = s
),
---------------------------------------------------------------------------------------------------------------------------------------
-- createBoxTypeControls() Creates the parameter controls for box collision objects. Called when the user presses
-- the box mode
---------------------------------------------------------------------------------------------------------------------------------------
fn createBoxTypeControls =
(
bestAlignButton = RS_dotNetUI.checkBox "bestAlignButton" text:("Align To Selection") \
textAlign:RS_dotNetPreset.CA_MiddleLeft checkAlign:RS_dotNetPreset.CA_MiddleRight \
dockStyle:RS_dotNetPreset.DS_Fill
offsetTypeCheckButton = RS_dotNetUI.checkBox "offsetTypeCheckButton" text:(toUpper "Offset") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler offsetTypeCheckButton "click" dispatchBoxPaddingTypeCheck
offsetTypeCheckButton.checked = true
lastBoxType = undefined
percentTypeCheckButton = RS_dotNetUI.checkBox "percentTypeCheckButton" text:(toUpper "Percent") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler percentTypeCheckButton "click" dispatchBoxPaddingTypeCheck
boxParametersTableLayout = RS_dotNetUI.tableLayout "boxParametersTableLayout" \
collumns:#((dataPair type:"Percent" value:50), (dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24), (dataPair type:"Absolute" value:24), (dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
boxParametersTableLayout.SetColumnSpan bestAlignButton 2
boxParametersTableLayout.Controls.Add bestAlignButton 0 0
boxParametersTableLayout.Controls.Add offsetTypeCheckButton 1 0
boxParametersTableLayout.Controls.Add percentTypeCheckButton 1 1
boxPaddingTypeCheck offsetTypeCheckButton ""
boxParametersTableLayout
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchSurfaceTypeButtonClick() Dispatches surfaceTypeButtonClick(), called when the user presses the surfaceTypeButton
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchSurfaceTypeButtonClick s e =
(
::RSL_CollisionOps.createUI.surfaceTypeButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- surfaceTypeButtonClick() Displays the correct surface type dialog depending on the mode.
---------------------------------------------------------------------------------------------------------------------------------------
fn surfaceTypeButtonClick s e =
(
-- if the lastType is the mesh mode, we must create the surface type dialog in rexbound mode
case lastType.name of
(
default:
(
::RSL_CollisionOps.attribute.surfaceTypeDialog #primitive
)
"meshCheckButton":
(
::RSL_CollisionOps.attribute.surfaceTypeDialog #rexbound
)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchPieceTypeButtonClick() Dispatches pieceTypeButtonClick(), called when the user presses the pieceTypeButton
-- which is only available for collision primitives and not collision meshes
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchPieceTypeButtonClick s e =
(
::RSL_CollisionOps.createUI.pieceTypeButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- pieceTypeButtonClick() Displays the piece type dialog
---------------------------------------------------------------------------------------------------------------------------------------
fn pieceTypeButtonClick s e =
(
::RSL_CollisionOps.attribute.pieceTypeDialog()
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchProceduralTypeButtonClick() Dispatches proceduralTypeButtonClick(), called when the user presses the proceduralTypeButton
-- which is only available for collision meshes
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchProceduralTypeButtonClick s e =
(
::RSL_CollisionOps.createUI.proceduralTypeButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- proceduralTypeButtonClick() Displays the procedural type dialog
---------------------------------------------------------------------------------------------------------------------------------------
fn proceduralTypeButtonClick s e =
(
::RSL_CollisionOps.attribute.proceduralTypeDialog()
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchMiloRoomButtonClick() Dispatches miloRoomButtonClick(), called when the user presses the miloRoomButton
-- which is only available for collision meshes
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchMiloRoomButtonClick s e =
(
::RSL_CollisionOps.createUI.miloRoomButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- miloRoomButtonClick() Displays the milo room dialog
---------------------------------------------------------------------------------------------------------------------------------------
fn miloRoomButtonClick s e =
(
::RSL_CollisionOps.attribute.miloRoomDialog()
),
---------------------------------------------------------------------------------------------------------------------------------------
-- createAttributeControls() Creates the attribute controls based on the parsed type which is either #primitive or #rexbound
-- Returns the attributesTableLayout
---------------------------------------------------------------------------------------------------------------------------------------
fn createAttributeControls type =
(
attributesGroup.controls.clear()
surfaceTypeLabel = RS_dotNetUI.Label "surfaceTypeLabel" text:" Surface Type:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
surfaceTypeButton = RS_dotNetUI.Button "surfaceTypeButton" text:(::RSL_CollisionOps.attribute.lastType) dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler surfaceTypeButton "click" dispatchSurfaceTypeButtonClick
local colour = getINISetting INIFile "surfaceColours" ::RSL_CollisionOps.attribute.lastType
if colour != "" then
(
local colourValue = readExpr (colour as stringStream)
surfaceTypeButton.backColor = RS_dotNetClass.colourClass.fromARGB colourValue.r colourValue.g colourValue.b
)
collisionTypeLabel = RS_dotNetUI.Label "collisionTypeLabel" text:" Collision Type:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
stairsCheckBox = RS_dotNetUI.checkBox "stairsCheckBox" text:("Stairs") dockStyle:RS_dotNetPreset.DS_Left textAlign:RS_dotNetPreset.CA_MiddleLeft
--noCoverCheckBox = RS_dotNetUI.checkBox "noCoverCheckBox" text:("Does not Provide Cover") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
noClimbCheckBox = RS_dotNetUI.checkBox "noClimbCheckBox" text:("Non Climable") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
pathCheckBox = RS_dotNetUI.checkBox "pathCheckBox" text:("Path") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
--noWalkCheckBox = RS_dotNetUI.checkBox "noWalkCheckBox" text:("Non Walkable") dockStyle:RS_dotNetPreset.DS_Fill
seeCheckBox = RS_dotNetUI.checkBox "seeCheckBox" text:("See Through") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
noCameraCheckBox = RS_dotNetUI.checkBox "noCameraCheckBox" text:("Non Camera Collidable") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
shootCheckBox = RS_dotNetUI.checkBox "shootCheckBox" text:("Shoot Through") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
attributesTableLayout = RS_dotNetUI.tableLayout "attributesTableLayout" text:"attributesTableLayout" \
collumns:#((dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:20),(dataPair type:"Absolute" value:20),(dataPair type:"Absolute" value:20)
,(dataPair type:"Absolute" value:20)) \
dockStyle:RS_dotNetPreset.DS_Fill
attributesTableLayout.controls.add surfaceTypeLabel 0 0
attributesTableLayout.controls.add surfaceTypeButton 1 0
attributesTableLayout.controls.add collisionTypeLabel 0 1
attributesTableLayout.controls.add stairsCheckBox 0 2
--attributesTableLayout.controls.add noCoverCheckBox 1 2
attributesTableLayout.controls.add noClimbCheckBox 1 2
attributesTableLayout.controls.add pathCheckBox 0 3
attributesTableLayout.controls.add seeCheckBox 1 3
attributesTableLayout.controls.add noCameraCheckBox 0 4
attributesTableLayout.controls.add shootCheckBox 1 4
--attributesTableLayout.controls.add noDecalCheckBox 1 5
--attributesTableLayout.controls.add noNavmeshCheckBox 0 6
--attributesTableLayout.controls.add noRagDollCheckBox 1 6
--attributesTableLayout.controls.add noParticleCheckBox 0 7
case type of
(
#primitive:
(
pieceLabel = RS_dotNetUI.Label "pieceLabel" text:" Piece Type:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
pieceTypeButton = RS_dotNetUI.Button "pieceTypeButton" text:"DEFAULT" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler pieceTypeButton "click" dispatchPieceTypeButtonClick
dayLabel = RS_dotNetUI.Label "dayLabel" text:" Day Brightness:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
dayNumeric = RS_dotNetUI.Numeric "dayNumeric" value:11 range:#(15, 0, 1, 0) dockStyle:RS_dotNetPreset.DS_Fill
-- dotnet.addEventHandler dayNumeric "ValueChanged" dispatchDayNumericChanged
dotnet.addEventHandler dayNumeric "Enter" disableAccelerators
nightLabel = RS_dotNetUI.Label "nightLabel" text:" Night Brightness:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
nightNumeric = RS_dotNetUI.Numeric "nightNumeric" value:11 range:#(15, 0, 1, 0) dockStyle:RS_dotNetPreset.DS_Fill
-- dotnet.addEventHandler nightNumeric "ValueChanged" dispatchDayNumericChanged
dotnet.addEventHandler nightNumeric "Enter" disableAccelerators
audioLabel = RS_dotNetUI.Label "audioLabel" text:" Audio Material:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
audioTextBox = RS_dotNetUI.textBox "findTextBox" text:"" dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler audioTextBox "Enter" disableAccelerators
roomIDLabel = RS_dotNetUI.Label "roomIDLabel" text:" Room ID:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
roomIDNumeric = RS_dotNetUI.Numeric "roomIDNumeric" value:0 range:#(1000, 0, 1, 0) dockStyle:RS_dotNetPreset.DS_Fill
-- dotnet.addEventHandler roomIDNumeric "ValueChanged" dispatchRoomIDNumericChanged
dotnet.addEventHandler roomIDNumeric "Enter" disableAccelerators
--leedsCheckBox = RS_dotNetUI.checkBox "leedsCheckBox" text:("Edited by Leeds") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
BVHCheckBox = RS_dotNetUI.checkBox "BVHCheckBox" text:("BVH Bound") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
wetCheckBox = RS_dotNetUI.checkBox "wetCheckBox" text:("Wet") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
pathCheckBox = RS_dotNetUI.checkBox "pathCheckBox" text:("Path") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
procTintCheckBox = RS_dotNetUI.checkBox "procTintCheckBox" text:("Use Procedural Tint") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
clothCollTintCheckBox = RS_dotNetUI.checkBox "clothCollCheckBox" text:("Is Cloth Collision") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
--attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 20)
attributesTableLayout.controls.add pieceLabel 0 5
attributesTableLayout.controls.add pieceTypeButton 1 5
attributesTableLayout.controls.add dayLabel 0 6
attributesTableLayout.controls.add dayNumeric 1 6
attributesTableLayout.controls.add nightLabel 0 7
attributesTableLayout.controls.add nightNumeric 1 7
attributesTableLayout.controls.add audioLabel 0 8
attributesTableLayout.controls.add audioTextBox 1 8
attributesTableLayout.controls.add roomIDLabel 0 9
attributesTableLayout.controls.add roomIDNumeric 1 9
--attributesTableLayout.controls.add leedsCheckBox 0 11
attributesTableLayout.controls.add BVHCheckBox 0 10
attributesTableLayout.controls.add wetCheckBox 0 11
attributesTableLayout.controls.add pathCheckBox 1 11
attributesTableLayout.controls.add procTintCheckBox 0 12
attributesTableLayout.controls.add clothCollTintCheckBox 1 12
createTableLayout.RowStyles.Item[2].Height = 324
)
#rexbound:
(
proceduralTypeLabel = RS_dotNetUI.Label "collisionTypeLabel" text:" Procedural Type:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
proceduralTypeButton = RS_dotNetUI.Button "proceduralTypeButton" text:"NONE" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler proceduralTypeButton "click" dispatchProceduralTypeButtonClick
pedMultiplierLabel = RS_dotNetUI.Label "collisionTypeLabel" text:" Ped Multiplier:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
pedMultiplierLabel.enabled = true
pedMultiplierNumeric = RS_dotNetUI.Numeric "ZPadding" value:0 range:#(7, 0, 1, 0) dockStyle:RS_dotNetPreset.DS_Fill
pedMultiplierNumeric.enabled = true
-- dotnet.addEventHandler pedMultiplierNumeric "ValueChanged" dispatchPedMultiplierChanged
dotnet.addEventHandler pedMultiplierNumeric "Enter" disableAccelerators
noCoverCheckBox = RS_dotNetUI.checkBox "noCoverCheckBox" text:("Does not Provide Cover") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
noDecalCheckBox = RS_dotNetUI.checkBox "noDecalCheckBox" text:("No Decal") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
noNavmeshCheckBox = RS_dotNetUI.checkBox "noNavMeshCheckBox" text:("No Navmesh") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
noRagDollCheckBox = RS_dotNetUI.checkBox "noRagDollCheckBox" text:("No Ragdoll") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
noParticleCheckBox = RS_dotNetUI.checkBox "noParticleCheckBox" text:("No Particle Effects") dockStyle:RS_dotNetPreset.DS_Fill textAlign:RS_dotNetPreset.CA_MiddleLeft
miloRoomLabel = RS_dotNetUI.Label "miloRoomLabel" text:" Milo Room:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
miloRoomButton = RS_dotNetUI.Button "miloRoomButton" text:"None" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler miloRoomButton "click" dispatchMiloRoomButtonClick
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 24)
attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 20)
attributesTableLayout.controls.add noCoverCheckBox 0 5
attributesTableLayout.controls.add noDecalCheckBox 1 5
attributesTableLayout.controls.add noNavmeshCheckBox 0 6
attributesTableLayout.controls.add noRagDollCheckBox 1 6
attributesTableLayout.controls.add noParticleCheckBox 0 7
attributesTableLayout.controls.add proceduralTypeLabel 0 8
attributesTableLayout.controls.add proceduralTypeButton 1 8
attributesTableLayout.controls.add pedMultiplierLabel 0 9
attributesTableLayout.controls.add pedMultiplierNumeric 1 9
attributesTableLayout.controls.add miloRoomLabel 0 10
attributesTableLayout.controls.add miloRoomButton 1 10
createTableLayout.RowStyles.Item[2].Height = 280
)
)
/*
case attributesGroup.text of
(
" Attributes - Advanced":
(
if type == #rexbound then
(
createTableLayout.RowStyles.Item[2].Height = 280
)
else
(
createTableLayout.RowStyles.Item[2].Height = 358
)
)
" Attributes - Basic":
(
createTableLayout.RowStyles.Item[2].Height = 128
)
)
*/
attributesTableLayout
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchCreateCheck() Dispatches createCheck(), called when the user presses any of the collision object type buttons
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchCreateCheck s e =
(
::RSL_CollisionOps.createUI.createCheck s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- createCheck() Switches the collision object type mode
---------------------------------------------------------------------------------------------------------------------------------------
fn createCheck s e =
(
-- set the pressed mode the true
s.Checked = true
-- if the last mode is not the pressed button, we need to create the controls for the chosen mode
if s != lastType then
(
case s.name of
(
"boxCheckButton":
(
-- un-check the other mode buttons
sphereCheckButton.checked = false
cylinderCheckButton.checked = false
meshCheckButton.checked = false
-- dispose of the currentTool, create the new controls and add them to the parametersGroup
if currentTool != undefined then currentTool.Dispose()
currentTool = createBoxTypeControls()
parametersGroup.Controls.Add currentTool
-- if the last controls were then mesh controls, we need to re-create the attributes for primitive collision objects
/*
if lastType != undefined and lastType.name == "meshCheckButton" then
(
attributesGroup.controls.add (createAttributeControls #primitive)
attributesGroup.controls.add expandButton
)
*/
attributesGroup.controls.add (createAttributeControls #primitive)
RSL_CollisionOps.CollisionForm.Height = 744
)
"sphereCheckButton":
(
-- un-check the other mode buttons
boxCheckButton.checked = false
cylinderCheckButton.checked = false
meshCheckButton.checked = false
-- dispose of the currentTool, create the new controls and add them to the parametersGroup
if currentTool != undefined then currentTool.Dispose()
currentTool = createSphereTypeControls()
parametersGroup.Controls.Add currentTool
-- set the height for the row
createTableLayout.RowStyles.Item[1].Height = 51
-- set the height of the main form depending on the expanded state of the attributes group
/*
case attributesGroup.text of
(
" Attributes - Basic":(::RSL_CollisionOps.CollisionForm.Height = 386)
" Attributes - Advanced":(::RSL_CollisionOps.CollisionForm.Height = 616)
)
*/
RSL_CollisionOps.CollisionForm.Height = 580
-- if the last controls were then mesh controls, we need to re-create the attributes for primitive collision objects
/*
if lastType != undefined and lastType.name == "meshCheckButton" then
(
attributesGroup.controls.add (createAttributeControls #primitive)
attributesGroup.controls.add expandButton
)
*/
attributesGroup.controls.add (createAttributeControls #primitive)
)
"cylinderCheckButton":
(
-- un-check the other mode buttons
sphereCheckButton.checked = false
boxCheckButton.checked = false
meshCheckButton.checked = false
-- dispose of the currentTool, create the new controls and add them to the parametersGroup
if currentTool != undefined then currentTool.Dispose()
currentTool = createCylinderTypeControls()
parametersGroup.Controls.Add currentTool
-- set the height for the row
createTableLayout.RowStyles.Item[1].Height = 99
-- set the height of the main form depending on the expanded state of the attributes group
/*
case attributesGroup.text of
(
" Attributes - Basic":(::RSL_CollisionOps.CollisionForm.Height = 434)
" Attributes - Advanced":(::RSL_CollisionOps.CollisionForm.Height = 664)
)
*/
RSL_CollisionOps.CollisionForm.Height = 634
-- if the last controls were then mesh controls, we need to re-create the attributes for primitive collision objects
/*
if lastType != undefined and lastType.name == "meshCheckButton" then
(
attributesGroup.controls.add (createAttributeControls #primitive)
attributesGroup.controls.add expandButton
)
*/
attributesGroup.controls.add (createAttributeControls #primitive)
)
"meshCheckButton":
(
-- un-check the other mode buttons
sphereCheckButton.checked = false
cylinderCheckButton.checked = false
boxCheckButton.checked = false
-- dispose of the currentTool, create the new controls and add them to the parametersGroup
if currentTool != undefined then currentTool.Dispose()
currentTool = createMeshTypeControls()
parametersGroup.Controls.Add currentTool
-- set the height for the row
createTableLayout.RowStyles.Item[1].Height = 99
-- set the height of the main form depending on the expanded state of the attributes group
/*
case attributesGroup.text of
(
" Attributes - Basic":(::RSL_CollisionOps.CollisionForm.Height = 434)
" Attributes - Advanced":(::RSL_CollisionOps.CollisionForm.Height = 586)
)
*/
RSL_CollisionOps.CollisionForm.Height = 585
-- re-create the attributes for rexbound collision meshes
attributesGroup.controls.add (createAttributeControls #rexbound)
--attributesGroup.controls.add expandButton
)
)
)
lastType = s
),
/*
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchAttributesClick() Dispatches attributesClick(), called when the user double clicks the attributesGroup
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchAttributesClick s e =
(
::RSL_CollisionOps.createUI.attributesClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- attributesClick() Expands or contracts the attributesGroup - deprecated
---------------------------------------------------------------------------------------------------------------------------------------
fn attributesClick s e =
(
case attributesGroup.text of
(
-- expand the attributesGroup and depending on which collision object mode is pressed, set the correct height
-- for the row and the main form
" Attributes - Basic":
(
case lastType.name of
(
"boxCheckButton":
(
if lastBoxType.name == "offsetTypeCheckButton" then
(
::RSL_CollisionOps.CollisionForm.Height = 785
)
else
(
::RSL_CollisionOps.CollisionForm.Height = 736
)
createTableLayout.RowStyles.Item[2].Height = 358
)
"sphereCheckButton":
(
createTableLayout.RowStyles.Item[2].Height = 358
::RSL_CollisionOps.CollisionForm.Height = 616
)
"cylinderCheckButton":
(
createTableLayout.RowStyles.Item[2].Height = 358
::RSL_CollisionOps.CollisionForm.Height = 664
)
"meshCheckButton":
(
createTableLayout.RowStyles.Item[2].Height = 280
::RSL_CollisionOps.CollisionForm.Height = 588
)
)
s.text = "-"
attributesGroup.text = " Attributes - Advanced"
)
-- contract the attributesGroup and depending on which collision object mode is pressed, set the correct height
-- for the row and the main form
" Attributes - Advanced":
(
case lastType.name of
(
"boxCheckButton":
(
if lastBoxType.name == "offsetTypeCheckButton" then
(
::RSL_CollisionOps.CollisionForm.Height = 554
)
else
(
::RSL_CollisionOps.CollisionForm.Height = 506
)
)
"sphereCheckButton":
(
::RSL_CollisionOps.CollisionForm.Height = 384
)
"cylinderCheckButton":
(
::RSL_CollisionOps.CollisionForm.Height = 434
)
"meshCheckButton":
(
::RSL_CollisionOps.CollisionForm.Height = 434
)
)
createTableLayout.RowStyles.Item[2].Height = 128
s.text = "+"
attributesGroup.text = " Attributes - Basic"
)
)
::RSL_CollisionOps.CollisionForm.focus()
),
*/
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchCreateButtonClick() Dispatches createButtonClick(), called when the user presses the createButton
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchCreateButtonClick s e =
(
::RSL_CollisionOps.createUI.createButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- createButtonClick() Creates a new collision object based on the chosen type and parameters
---------------------------------------------------------------------------------------------------------------------------------------
fn createButtonClick s e =
(
local faceSelection
newCollisionMeshArray = #()
-- if only one object is selected, we can attempt to get the faceSelection if the object has selected faces
if ::RSL_CollisionOps.theObjects.count == 1 then
(
-- make sure we're in the max modify panel and we're at one of the valid sub object levels for faces
local modify = getCommandPanelTaskMode() == #modify
local faceMode = subObjectLevel == 4 or subObjectLevel == 5 or (subObjectLevel == 3 and (classOf ::RSL_CollisionOps.theObjects[1]) == editable_mesh)
local selectedCount = ::RSL_CollisionOps.theObjects[1].SelectedFaces.count
-- if we are in the right mode and we have selected faces, we assign the selected indices to faceSelection
-- otherwise we assign all the faces' indices in the object to faceSelection
if modify and faceMode and selectedCount > 0 then
(
faceSelection = for face in ::RSL_CollisionOps.theObjects[1].selectedFaces collect face.index
)
else
(
faceSelection = for face in ::RSL_CollisionOps.theObjects[1].faces collect face.index
)
)
-- loop through each selected object creating the chosen collision object
for object in ::RSL_CollisionOps.theObjects do
(
-- set the faceSelection to all the faces in the object if we have multiple objects selected
if ::RSL_CollisionOps.theObjects.count > 1 then
(
faceSelection = for face in object.faces collect face.index
)
if boxCheckButton.Checked then
(
makeBox object faceSelection
)
if meshCheckButton.Checked then
(
makeMesh object faceSelection
)
if sphereCheckButton.Checked then
(
makeSphere object faceSelection
)
if cylinderCheckButton.Checked then
(
makeCylinder object faceSelection
)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchDeleteButtonClick() Dispatches deleteButtonClick(), called when the user presses the deleteButton
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchDeleteButtonClick s e =
(
::RSL_CollisionOps.createUI.deleteButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- deleteButtonClick() Deletes all the object found in the newCollisionMeshArray. When a collision object is created, it is
-- added to this array.
---------------------------------------------------------------------------------------------------------------------------------------
fn deleteButtonClick s e =
(
try (delete newCollisionMeshArray) catch()
),
---------------------------------------------------------------------------------------------------------------------------------------
-- getUI() Creates the UI for create mode
---------------------------------------------------------------------------------------------------------------------------------------
fn getUI =
(
boxCheckButton = RS_dotNetUI.checkBox "boxCheckButton" text:(toUpper "Box") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler boxCheckButton "click" dispatchCreateCheck
boxCheckButton.checked = true
sphereCheckButton = RS_dotNetUI.checkBox "sphereCheckButton" text:(toUpper "Sphere") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler sphereCheckButton "click" dispatchCreateCheck
cylinderCheckButton = RS_dotNetUI.checkBox "cylinderCheckButton" text:(toUpper "Cylinder") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler cylinderCheckButton "click" dispatchCreateCheck
meshCheckButton = RS_dotNetUI.checkBox "meshCheckButton" text:(toUpper "Mesh") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler meshCheckButton "click" dispatchCreateCheck
parametersGroup = RS_dotNetUI.GroupBox "parametersGroup" Text:"Parameters" dockStyle:RS_dotNetPreset.DS_Fill
--expandButton = RS_dotNetUI.Button "expandButton" text:"-" size:[14,14] location:[8,0] margin:(RS_dotNetObject.paddingObject 2)
-- expandButton.FlatStyle = RS_dotNetPreset.FS_Flat
--expandButton.Font = dotNetObject "System.Drawing.Font" "Small Fonts" 7.0 RS_dotNetPreset.f_Regular--RS_dotNetPreset.FontSmall
-- expandButton.TextAlign = (dotNetClass "System.Drawing.ContentAlignment").MiddleCenter
--dotnet.addEventHandler expandButton "click" dispatchAttributesClick
attributesGroup = RS_dotNetUI.GroupBox "parametersGroup" Text:"Attributes" dockStyle:RS_dotNetPreset.DS_Fill
-- dotnet.addEventHandler attributesGroup "MouseDoubleClick" dispatchAttributesClick
-- toolTip.SetToolTip attributesGroup "Double Click to expand/Contract Attributes"
createButton = RS_dotNetUI.Button "createButton" text:"Create" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
createButton.enabled = false
dotnet.addEventHandler createButton "click" dispatchCreateButtonClick
deleteButton = RS_dotNetUI.Button "deleteButton" text:"Delete Last" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler deleteButton "click" dispatchDeleteButtonClick
createDeleteTableLayout = RS_dotNetUI.tableLayout "createDeleteTableLayout" text:"createDeleteTableLayout" \
collumns:#((dataPair type:"Percent" value:50)) rows:#((dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
createDeleteTableLayout.controls.add createButton 0 0
createDeleteTableLayout.controls.add deleteButton 0 1
createGroup = RS_dotNetUI.GroupBox "createGroup" Text:"Create/Delete" dockStyle:RS_dotNetPreset.DS_Fill
createGroup.controls.add createDeleteTableLayout
statusLabel = RS_dotNetUI.Label "statusLabel" text:" Selected:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
createTableLayout = RS_dotNetUI.tableLayout "createTableLayout" text:"createTableLayout" \
collumns:#((dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:120),(dataPair type:"Absolute" value:100),(dataPair type:"Absolute" value:74) \
,(dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
createTableLayout.controls.add boxCheckButton 0 0
createTableLayout.controls.add sphereCheckButton 1 0
createTableLayout.controls.add cylinderCheckButton 2 0
createTableLayout.controls.add meshCheckButton 3 0
createTableLayout.controls.add parametersGroup 0 1
createTableLayout.controls.add attributesGroup 0 2
createTableLayout.controls.add createGroup 0 3
createTableLayout.controls.add statusLabel 0 4
createTableLayout.SetColumnSpan parametersGroup 4
createTableLayout.SetColumnSpan attributesGroup 4
createTableLayout.SetColumnSpan createGroup 4
createTableLayout.SetColumnSpan statusLabel 4
createCheck boxCheckButton ""
attributesGroup.controls.add (createAttributeControls #primitive)
--attributesGroup.controls.add expandButton
createTableLayout
)
)