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

1906 lines
83 KiB
Plaintext
Executable File

---------------------------------------------------------------------------------------------------------------------------------------
-- RSL_CollisionOps2Edit
-- 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 edit mode
---------------------------------------------------------------------------------------------------------------------------------------
-- Struct used to store per material rexbound data gathered from the currentMesh
struct RSL_RexBoundData
(
---------------------------------------------------------------------------------------------------------------------------------------
-- Struct variables
---------------------------------------------------------------------------------------------------------------------------------------
surfaceType,
flags = 0,
proceduralType = -1,
miloRoom = -1,
faceArray = #(),
ID = 1,
---------------------------------------------------------------------------------------------------------------------------------------
--
-- FUNCTIONS
--
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
-- compare() Compares the parsed data which is a RSL_RexBoundData with the struct variables. Returns true if they are the same.
-- faceArray and ID struct variables are ignored.
---------------------------------------------------------------------------------------------------------------------------------------
fn compare data =
(
local result = true
if data.surfaceType != surfaceType then result = false
if data.flags != flags then result = false
if data.proceduralType != proceduralType then result = false
if data.miloRoom != miloRoom then result = false
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- compareType() Compares the surfaceType for the parsed data which is a RSL_RexBoundData with the surfaceType struct variable.
-- Returns true if they are the same. faceArray and ID struct variables are ignored.
---------------------------------------------------------------------------------------------------------------------------------------
fn compareType data =
(
data.surfaceType == surfaceType
),
---------------------------------------------------------------------------------------------------------------------------------------
-- compareAttr() Compares the attributes for the parsed data which is a RSL_RexBoundData with the attributes of the struct.
-- Returns true if they are the same. faceArray and ID struct variables are ignored.
---------------------------------------------------------------------------------------------------------------------------------------
fn compareAttr data =
(
local result = true
if data.flags != flags then result = false
if data.proceduralType != proceduralType then result = false
if data.miloRoom != miloRoom then result = false
result
)
)
-- main struct
struct RSL_CollisionOps2Edit
(
---------------------------------------------------------------------------------------------------------------------------------------
-- Struct variables
---------------------------------------------------------------------------------------------------------------------------------------
INIfile = (RsConfigGetWildWestDir() + "script\\max\\Rockstar_London\\config\\collisionOps2.ini"),
-- 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",
-- surface type used if we cannot get the correct surface type from the object
defaultType = "DEFAULT",
displayBitmapArray = #(),
-- SimpleFaceData IDs
surfaceTypeID = #(0x3b6adfa6, 0xec24cd5),
flagsID = #(0x38aacec5, 0x12f38bdc),
proceduralTypeID = #(0x5c8d87e0, 0x63ac911b),
miloRoomID = #(0x10ec28e7, 0x106a0362),
-- SimpleFaceData channel variables
surfaceChannel,
flagsChannel,
proceduralChannel,
miloRoomChannel,
pickType,
mouseTrackType,
selectType,
assignType,
---------------------------------------------------------------------------------------------------------------------------------------
-- UI variables
---------------------------------------------------------------------------------------------------------------------------------------
pallette,searchTextBox,attributesGroup,pickGroup,selectGroup,assignGroup,editTableLayout,
attributesTableLayout,
stairsCheckBox,noCoverCheckBox,noClimbCheckBox,noWalkCheckBox,seeCheckBox,noCameraCheckBox,shootCheckBox,
stairsSelectButton,noCoverSelectButton,noClimbSelectButton,noWalkSelectButton,seeSelectButton,noCamSelectButton,shootSelectButton,
pieceTypeButton,dayNumeric,nightNumeric,audioTextBox,roomIDNumeric,BVHCheckBox,procTintCheckBox,clothCollCheckBox,
proceduralTypeButton,pedMultiplierNumeric,miloRoomButton,
toolTip = dotNetObject "ToolTip",
---------------------------------------------------------------------------------------------------------------------------------------
--
-- FUNCTIONS
--
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
-- disableAccelerators() Called when the user enters any control that needs keyboard input e.g. a textBox
---------------------------------------------------------------------------------------------------------------------------------------
fn disableAccelerators s e =
(
enableAccelerators = false
),
---------------------------------------------------------------------------------------------------------------------------------------
-- isUsedInObject() Checks the parsed object to see if the parsed ID is used in the object.
-- Returns true if the ID and therefore the material is used.
---------------------------------------------------------------------------------------------------------------------------------------
fn isUsedInObject object ID =
(
-- create a temp mesh object so that we dont have to worry about object class when getting the material ID from the face
local tempMesh = snapshotasmesh object
local result = false
for face in tempMesh.faces do
(
if (getFaceMatID tempMesh face.index) == ID then
(
result = true
exit
)
)
delete tempMesh
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- getType() Checks the class of the object and returns the type. #rexbound if it's a collision mesh or #primitive for any other
-- class of collision object
---------------------------------------------------------------------------------------------------------------------------------------
fn getType object =
(
if (classOf object) == Col_Mesh then
(
#rexbound
)
else
(
#primitive
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- findID() Searches the parsed array for any item with the same ID as the parsed ID. Returns the index if found or 0
---------------------------------------------------------------------------------------------------------------------------------------
fn findID array ID =
(
local result = 0
for i = 1 to array.count where array[i] != undefined do
(
if array[i].ID == ID then
(
result = i
)
)
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- getIDFaceArray() Gathers a dataPair for each unique material ID found on the object and an array of faces assigned that ID.
-- Returns an array of all the unique dataPairs
---------------------------------------------------------------------------------------------------------------------------------------
fn getIDFaceArray object =
(
local result = #()
for face in object.faces do
(
-- get the ID from the face
local ID = (getFaceMatID object face.index)
-- check that we don't alreadi have a dataPair for that ID
local index = findID result ID
-- if we do then append the face.index to the faceArray of the found dataPair. Other wise we
-- create a new dataPair and append it to the result array
if index > 0 then
(
append result[index].faceArray face.index
)
else
(
append result (dataPair ID:ID faceArray:#(face.index))
)
)
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- fixMatIDs() Fixes any out of range IDs e.g. ID:10 when there are only 5 sub materials assigned.
---------------------------------------------------------------------------------------------------------------------------------------
fn fixMatIDs array object =
(
local result = #()
local materialCount = object.material.numSubs
for entry in array do
(
if entry.ID > materialCount then
(
-- fix the ID if it's out of range. If it's not, it will return the same value
local newID = int (mod entry.ID materialCount)
if newID == 0 then
(
newID = materialCount
)
-- check to see if we already have a dataPair with that ID in the parsed array
local index = findID array newID
if index > 0 then
(
-- check to see if we already have a dataPair with that ID in the result array
local fIndex = findID result newID
-- if we do have one in the result array, we add the face indices from the entry dataPair to the
-- found dataPair faceArray in the result array. Otherwise we create a new dataPair with the combined
-- faceArrays from the entry dataPair and the array[index] dataPair.
if fIndex > 0 then
(
result[fIndex].faceArray = makeUniqueArray (result[fIndex].faceArray + entry.faceArray)
)
else
(
append result (dataPair ID:newID faceArray:(makeUniqueArray (array[index].faceArray + entry.faceArray)))
)
)
else
(
append result (dataPair ID:newID faceArray:entry.faceArray)
)
)
else
(
append result entry
)
)
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- compareID() Qsort function used to compare ID variables
---------------------------------------------------------------------------------------------------------------------------------------
fn compareID v1 v2 =
(
case of
(
(v1.ID > v2.ID):1
(v1.ID < v2.ID):-1
default:0
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setID() Mapped function to set the face ID on editable meshes
---------------------------------------------------------------------------------------------------------------------------------------
mapped fn setID face object ID =
(
setFaceMatID object face ID
),
---------------------------------------------------------------------------------------------------------------------------------------
-- reNumberMatIDs() Re-numbers the IDs in the parsed array and sets the face IDs on the parsed object
---------------------------------------------------------------------------------------------------------------------------------------
fn reNumberMatIDs array object =
(
for i = 1 to array.count do
(
setID array[i].faceArray object i
array[i].ID = i
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- findRexBoundData() Searches the parsed array for the parse data. Returns the index in the array or 0
---------------------------------------------------------------------------------------------------------------------------------------
fn findRexBoundData array data =
(
local result = 0
for i = 1 to array.count do
(
if (data.compare array[i]) then
(
result = i
exit
)
)
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- getFlagsFromAttributes() Generates a rexBound flag integer from the standard attributes of the parsed object
---------------------------------------------------------------------------------------------------------------------------------------
fn getFlagsFromAttributes object =
(
local result = 0
if (try(getAttr object idxStairs) catch (false)) == true then
(
result = bit.or result (bit.shift 1 0)
)
if (try(getAttr object idxNoClimb) catch (false)) == true then
(
result = bit.or result (bit.shift 1 1)
)
if (try(getAttr object idxSee) catch (false)) == true then
(
result = bit.or result (bit.shift 1 2)
)
if (try(getAttr object idxShoot) catch (false)) == true then
(
result = bit.or result (bit.shift 1 3)
)
if (try(getAttr object idxWet) catch (false)) == true then
(
result = bit.or result (bit.shift 1 4)
)
if (try(getAttr object idxPath) catch (false)) == true then
(
result = bit.or result (bit.shift 1 5)
)
/*
if (try(getAttr object idxLeeds) catch (false)) == true then
(
result = bit.or result (bit.shift 1 6)
)
*/
if (try(getAttr object idxNoCamera) catch (false)) == true then
(
result = bit.or result (bit.shift 1 7)
)
if (try(getAttr object idxBVH) catch (false)) == true then
(
result = bit.or result (bit.shift 1 8)
)
if (try(getAttr object idxProcTint) catch (false)) == true then
(
result = bit.or result (bit.shift 1 9)
)
if (try(getAttr object idxClothColl) catch (false)) == true then
(
result = bit.or result (bit.shift 1 10)
)
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- getFaceDataFromMaterial() Generates an array of RSL_RexBoundData structs from the parsed material if it is a rexBound
-- material or a multimaterial with rexBound materials. Uses the parsed attributeData if the material is not a rexBound material
-- or a multimaterial.
---------------------------------------------------------------------------------------------------------------------------------------
fn getFaceDataFromMaterial material object attributeData =
(
local result = #()
local default = (findItem ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray defaultType)
case (classOf material) of
(
default:
(
-- the material is not a rexBoung material or a multimaterial so we must use the standard attributes of the parsed object
attributeData.faceArray = (for f in object.faces collect f.index)
append result attributeData
)
RexBoundMtl:
(
-- it's a rexBound material so we can gather the data from the material
local newData = RSL_RexBoundData surfaceType:default faceArray:(for f in object.faces collect f.index)
local type = findItem ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray (toUpper (RexGetCollisionName material))
local flags = RexGetCollisionFlags material
local proc = findItem ::RSL_CollisionOps.attribute.proceduralArray (RexGetProceduralName material)
if proc == 0 then proc = -1
local miloHandle = -1
local miloRoom = (RexGetRoomNode material)
if (isValidNode miloRoom) then
(
miloHandle = miloRoom.inode.handle
)
if type > 0 then
(
newData.surfaceType = type
)
newData.flags = flags
newData.proceduralType = proc
newData.miloRoom = miloHandle
append result newData
)
Multimaterial:
(
-- gather the face ID data and sort the array. Fix the ID is needed at the same time
local IDArray = fixMatIDs (getIDFaceArray object) object
qSort IDArray compareID
-- for each data in the array we create a RSL_RexBoundData struct. We setup the struct as a default struct
-- in case the sub material the ID points to is not a rexBound material
for IDData in IDArray do
(
local newData = RSL_RexBoundData surfaceType:default faceArray:IDData.faceArray ID:IDData.ID
-- check to see if the ID exists in the materialIDList
idxID = findItem material.materialIDList IDData.ID
-- if it does, we can attempt to get the data. Otherwise we leave the RSL_RexBoundData struct as default
if idxID > 0 then
(
local subMaterial = object.material.materialList[idxID]
-- if the subMaterial is a rexBound material, get the data from the material
if (classOf subMaterial) == RexBoundMtl then
(
local type = findItem ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray (toUpper (RexGetCollisionName subMaterial))
local flags = RexGetCollisionFlags subMaterial
local proc = findItem ::RSL_CollisionOps.attribute.proceduralArray (RexGetProceduralName subMaterial)
if proc == 0 then proc = -1 -- -1 because dotNet indices start at 0
local miloHandle = -1 -- -1 just in case
local miloRoom = (RexGetRoomNode subMaterial)
-- if the miloRoom is a valid node e.g. it's not been deleted, we get the handle
if (isValidNode miloRoom) then
(
miloHandle = miloRoom.inode.handle
)
if type > 0 then
(
newData.surfaceType = type
)
newData.flags = flags
newData.proceduralType = proc
newData.miloRoom = miloHandle
)
)
else
(
)
-- check to see if we already have a RSL_RexBoundData struct in the array that matches our newly created struct
-- We do this to avoid duplicates
local index = findRexBoundData result newData
-- if we don't, we append the new RSL_RexBoundData struct to the result array
if index == 0 then
(
append result newData
)
else
(
-- we already have a RSL_RexBoundData struct that matches so we set the face ID to the found struct's ID
-- and add teh faceArray to the found struct
setID IDData.faceArray object result[index].ID
join result[index].faceArray IDData.faceArray
)
)
)
)
reNumberMatIDs result object
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setData() sets the value for each parsed face to the parse value in the parsed faceChannel
---------------------------------------------------------------------------------------------------------------------------------------
mapped fn setData face faceChannel value =
(
faceChannel.setValue face value
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setFaceData() Sets the face data for all the face channels on the parsed objects using the parsed data
---------------------------------------------------------------------------------------------------------------------------------------
fn setFaceData object data =
(
-- add the face data channels to the parsed object
surfaceChannel = simpleFaceManager.addChannel object id:surfaceTypeID
flagsChannel = simpleFaceManager.addChannel object id:flagsID
proceduralChannel = simpleFaceManager.addChannel object id:proceduralTypeID
miloRoomChannel = simpleFaceManager.addChannel object id:miloRoomID
for entry in data do
(
setData entry.faceArray surfaceChannel entry.surfaceType
setData entry.faceArray flagsChannel entry.flags
setData entry.faceArray proceduralChannel entry.proceduralType
setData entry.faceArray miloRoomChannel entry.miloRoom
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- getFaceData() Generates an array of RSL_RexBoundData structs from the faces of the parsed object. InputArray is
-- used when we want to get the data from a particular array of faces in the parsed object
---------------------------------------------------------------------------------------------------------------------------------------
fn getFaceData object inputArray:undefined =
(
local result = #()
local faceArray
-- setup faceArray depending on weather inputArray is undefined of not.
if inputArray != undefined then
(
faceArray = inputArray
)
else
(
faceArray = object.faces
)
-- get the data for each face in faceArray
for face in faceArray do
(
local newData = RSL_RexBoundData surfaceType:(surfaceChannel.getValue face.index) faceArray:#(face.index)
newData.flags = flagsChannel.getValue face.index
newData.proceduralType = proceduralChannel.getValue face.index
newData.miloRoom = miloRoomChannel.getValue face.index
-- check to see if we already have a RSL_RexBoundData struct that matches our newly created struct
local index = findRexBoundData result newData
-- if we do, we append the face index to the faceArray of the found struct
if index > 0 then
(
append result[index].faceArray face.index
)
else
(
append result newData
)
)
-- we only use inputArray when we want to get the data for a particular set of faces and only when we want to update
-- the UI. When we want to get all the data, we might have changed the data so we make sure the faces have the correct
-- IDs
if inputArray == undefined then
(
for i = 1 to result.count do
(
setID result[i].faceArray object i
result.ID = i
)
)
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setDisplayMaterial() Generates a display material for the parsed object based on the parsed faceData
---------------------------------------------------------------------------------------------------------------------------------------
fn setDisplayMaterial object faceData =
(
local displayMaterial
displayBitmapArray = #()
-- if there's more than one set of face data, we create a Multimaterial
if faceData.count > 1 then
(
displayMaterial = Multimaterial numSubs:faceData.count name:"RSL_CollisionOps_Display"
for i = 1 to faceData.count do
(
local data = faceData[i]
local surfaceType = ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray[data.surfaceType]
local collisionBitmap = ::RSL_CollisionOps.attribute.textureDirectory + surfaceType + ".bmp"
local subMaterial = standardMaterial name:(surfaceType + " - " + i as string) diffuseMap:(bitmapTexture filename:collisionBitmap) --showInViewport:true
-- set the opacity so that in shaded mode, we can see the render geometry behide the collision mesh.
-- set the self illumination so that the collision geometry is always visible.
subMaterial.opacity = 75
subMaterial.selfIllumAmount = 50
showTextureMap subMaterial subMaterial.diffuseMap true
displayMaterial.materialList[i] = subMaterial
displayMaterial.names[i] = surfaceType
append displayBitmapArray subMaterial.diffuseMap
)
)
else
(
local surfaceType = ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray[faceData[1].surfaceType]
local collisionBitmap = ::RSL_CollisionOps.attribute.textureDirectory + surfaceType + ".bmp"
displayMaterial = standardMaterial name:"RSL_CollisionOps_Display" diffuseMap:(bitmapTexture filename:collisionBitmap) --showInViewport:true
-- set the opacity so that in shaded mode, we can see the render geometry behide the collision mesh.
-- set the self illumination so that the collision geometry is always visible.
displayMaterial.opacity = 75
displayMaterial.selfIllumAmount = 50
showTextureMap displayMaterial displayMaterial.diffuseMap true
append displayBitmapArray displayMaterial.diffuseMap
)
-- store the sub level if needed and then set it to 0 so that when we assign the material,
-- we do not accidentally assign it to a face selection
local level
if subObjectLevel > 0 then
(
level = subObjectLevel
subObjectLevel = 0
)
object.material = displayMaterial
-- if we've stored the sub level before we assigned the material, set it back again
if level != undefined then
(
subObjectLevel = level
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setRexBoundAttributes() Set the parsed data attributes on the parsed material which is a rexdBound material
---------------------------------------------------------------------------------------------------------------------------------------
fn setRexBoundAttributes material data =
(
RexSetCollisionName material ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray[data.surfaceType]
if data.proceduralType > 0 then
(
RexSetProceduralName material ::RSL_CollisionOps.attribute.proceduralArray[data.proceduralType]
)
if data.miloRoom > 0 then
(
local miloRoom = maxOps.getNodeByHandle data.miloRoom
if (isValidNode miloRoom) and (classOf miloRoom) == GtaMloRoom then
(
RexSetRoomNode material miloRoom
)
)
RexsetCollisionFlags material data.flags
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setRexBoundMaterial() Creates a rexBound material or series of rexBound materials for the parsed object based on the
-- parsed faceData
---------------------------------------------------------------------------------------------------------------------------------------
fn setRexBoundMaterial object faceData =
(
local rexBoundMaterial
-- if we have more than one set of faceData, we create a multimaterial
if faceData.count > 1 then
(
rexBoundMaterial = Multimaterial numSubs:faceData.count name:(Object.name)
for i = 1 to faceData.count do
(
local data = faceData[i]
local surfaceType = ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray[data.surfaceType]
setID data.faceArray object i
local subMaterial = RexBoundMtl name:(Object.name + " - " + surfaceType + " " + i as string)
setRexBoundAttributes subMaterial data
rexBoundMaterial.materialList[i] = subMaterial
rexBoundMaterial.names[i] = surfaceType
)
)
else
(
rexBoundMaterial = RexBoundMtl name:(Object.name)
setRexBoundAttributes rexBoundMaterial faceData[1]
setID faceData[1].faceArray object 1
)
object.material = rexBoundMaterial
),
---------------------------------------------------------------------------------------------------------------------------------------
-- getAttributeData() Creates and returns an RSL_RexBoundData struct based on the standard attributes of the parsed object.
---------------------------------------------------------------------------------------------------------------------------------------
fn getAttributeData object =
(
local result = RSL_RexBoundData surfaceType:(findItem ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray (toUpper (getAttr object idxColType)))
result.flags = getFlagsFromAttributes object
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setEdgeVisByMaterial() Experimental function to make sure that edges of teh parsed object on a boundary between materials are visible.
-- Only used when the script worked on editable poly objects. Sadly the function is way too slow and currently this is not used.
---------------------------------------------------------------------------------------------------------------------------------------
fn setEdgeVisByMaterial object =
(
if (classOf object.material) == Multimaterial then
(
local processed = #()
print "setEdgeVisByMaterial"
-- loop through the edges of the parsed object
for this in object.edges where (findItem processed this.index) == 0 do
(
-- get the reverse edge, there are 2 edges between 2 faces in an editable mesh object
local other = ((meshop.getEdgesReverseEdge object this.index) as array)[1]
-- if there is a reverse edge...
if other != undefined then
(
-- get the 2 faces
local thisFace = ((meshop.getFacesUsingEdge object this.index) as array)[1]
local otherFace = ((meshop.getFacesUsingEdge object other) as array)[1]
-- if the faces have different material IDs, make the edges visible
if (getFaceMatID object thisFace) != (getFaceMatID object otherFace) then
(
local thisIndex = findItem ((meshop.getEdgesUsingFace object thisFace) as array) this.index
local otherIndex = findItem ((meshop.getEdgesUsingFace object otherFace) as array) other
setEdgeVis object thisFace thisIndex true
setEdgeVis object otherFace otherIndex true
append processed this.index
append processed other
)
)
)
print "setEdgeVisByMaterial End"
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- switchToMesh() Takes the parsed object and converts it to a mesh object with a display material.
---------------------------------------------------------------------------------------------------------------------------------------
fn switchToMesh object =
(
-- get the standard attribute data in case the object does not have rexBound materials
local attrData = getAttributeData object
-- switch to create mode in the max command panel before we convert because collision meshes do not properly
-- update when they are converted
setCommandPanelTaskMode #create
col2mesh object
setCommandPanelTaskMode #modify
-- create face data from the object's material, set it on the faces via SimpleFaceData, give the object some basic
-- uv co-ordinates to esure the display textures show up properly and then create and assign a display material
local faceDataArray = getFaceDataFromMaterial object.material object attrData
setFaceData object faceDataArray
meshOp.applyUVWMap object #box uTile:2.0 vTile:2.0
setDisplayMaterial object faceDataArray
),
---------------------------------------------------------------------------------------------------------------------------------------
-- switchToCollision() Takes the parsed object and converts it to a collision mesh with a rexBound material based on the
-- object's face data
---------------------------------------------------------------------------------------------------------------------------------------
fn switchToCollision object =
(
-- create mode in the max command panel before setting the sub object level and making sure the faces are un-selected.
-- I some times had it loose data when I did not do this, not sure why though.
setCommandPanelTaskMode #create
subObjectLevel = 0
object.selectedFaces = #()
-- get the face data from the object and create a rexBound material
local faceDataArray = getFaceData object
setRexBoundMaterial object faceDataArray
-- remove the SimpleFaceData channels because if we don't, we can no longer create and access them.
simpleFaceManager.removeChannel object surfaceTypeID
simpleFaceManager.removeChannel object flagsID
simpleFaceManager.removeChannel object proceduralTypeID
simpleFaceManager.removeChannel object miloRoomID
-- convert to collision mesh
mesh2Col object
setCommandPanelTaskMode #modify
-- if we've modified the collision types, set the attributes from the currentColType struct
/*
if ::RSL_CollisionOps.currentColType.modified then
(
try (setAttr object idxCamera ::RSL_CollisionOps.currentColType.camera) catch()
try (setAttr object idxPhysics ::RSL_CollisionOps.currentColType.physics) catch()
try (setAttr object idxHiDetail ::RSL_CollisionOps.currentColType.hiDetail) catch()
try (setAttr object idxLoco ::RSL_CollisionOps.currentColType.loco) catch()
)
*/
completeRedraw()
),
---------------------------------------------------------------------------------------------------------------------------------------
-- setAttributeControlsRex() Sets the rexBound attribute controls based on the parsed faceNum. This is used in the pick functions
---------------------------------------------------------------------------------------------------------------------------------------
fn setAttributeControlsRex faceNum =
(
-- get the face data for the chosen faceNum
local faceData = (getFaceData ::RSL_CollisionOps.currentMesh inputArray:#(::RSL_CollisionOps.currentMesh.faces[faceNum]))[1]
-- set the surface type if we've used a pick function that supports it
if pickType == "pickSurfaceButton" or pickType == "pickAllButton" then
(
local surfaceType = ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray[faceData.surfaceType]
for i = 0 to pallette.items.count - 1 do
(
local item = pallette.items.item[i]
if (toUpper item.text) == (toUpper surfaceType) then
(
item.selected = true
-- this makes sure the list view item is visible in the list view. It will scroll to it if needed
item.EnsureVisible()
)
)
)
-- set the attribute check buttons if we've used a pick function that supports it
if pickType == "pickFlagsButton" or pickType == "pickAllButton" then
(
stairsCheckBox.checked = (bit.and faceData.flags (bit.shift 1 0) > 0)
--noCoverCheckBox.checked = (bit.and faceData.flags (bit.shift 1 4) > 0)
noClimbCheckBox.checked = (bit.and faceData.flags (bit.shift 1 1) > 0)
--noWalkCheckBox.checked = (bit.and faceData.flags (bit.shift 1 5) > 0)
seeCheckBox.checked = (bit.and faceData.flags (bit.shift 1 2) > 0)
noCameraCheckBox.checked = (bit.and faceData.flags (bit.shift 1 7) > 0)
shootCheckBox.checked = (bit.and faceData.flags (bit.shift 1 3) > 0)
if faceData.proceduralType > 0 then
(
proceduralTypeButton.text = ::RSL_CollisionOps.attribute.proceduralArray[faceData.proceduralType + 1]
)
else
(
proceduralTypeButton.text = "None"
)
if faceData.miloRoom > 0 then
(
local miloRoom = maxOps.getNodeByHandle faceData.miloRoom
if (isValidNode miloRoom) and (classOf miloRoom) == GtaMloRoom then
(
miloRoomButton.text = miloRoom.name
miloRoomButton.tag = dotNetMXSValue miloRoom
)
)
else
(
miloRoomButton.text = "None"
miloRoomButton.tag = undefined
)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- findFaceIndex() Searches the parsed array for the parsed index in the faceArray. Returns the index or 0
---------------------------------------------------------------------------------------------------------------------------------------
fn findFaceIndex array index =
(
local result = 0
for i = 1 to array.count do
(
if (findItem array[i].faceArray index) > 0 then
(
result = i
exit
)
)
result
),
---------------------------------------------------------------------------------------------------------------------------------------
-- selectFacesByAttributes() Selects faces on the currentMesh struct variable if they match the criteria of the chosen
-- select function.
---------------------------------------------------------------------------------------------------------------------------------------
fn selectFacesByAttributes faceNum ctrl =
(
local faceDataArray = getFaceData ::RSL_CollisionOps.currentMesh
local index = findFaceIndex faceDataArray faceNum
local faceData = faceDataArray[index]
local faceArray = #()
-- if the control button is down, add the currently selected faces to faceArray so that we grow the face
-- selection rather than replace it
if ctrl then
(
faceArray = for f in ::RSL_CollisionOps.currentMesh.selectedFaces collect f.index
)
case selectType of
(
"selectSurfaceButton":
(
for entry in faceDataArray do
(
if (entry.compareType faceData) then
(
faceArray += entry.faceArray
)
)
)
"selectFlagsButton":
(
for entry in faceDataArray do
(
if (entry.compareAttr faceData) then
(
faceArray += entry.faceArray
)
)
)
"selectAllButton":
(
for entry in faceDataArray do
(
if (entry.compare faceData) then
(
faceArray += entry.faceArray
)
)
)
)
-- make sure we're in face sub object mode and then select the faces
subObjectLevel = 4
::RSL_CollisionOps.currentMesh.selectedFaces = #()
::RSL_CollisionOps.currentMesh.selectedFaces = faceArray
),
---------------------------------------------------------------------------------------------------------------------------------------
-- cb_mouseTrack() Mouse track function used by pick and select functions. The function ends when we click on a face.
---------------------------------------------------------------------------------------------------------------------------------------
fn cb_mouseTrack msg ir obj faceNum shift ctrl alt =
(
case msg of
(
#freeMove:
(
#continue
)
#mousePoint:
(
if ir != undefined then
(
-- if we're using one of the pick functions, we set eh attribute controls based on the face we clicked
-- otherwise we're using select functions so we select similar attrbute faces to the face we clicked
if mouseTrackType == #pick then
(
setAttributeControlsRex faceNum
)
else
(
selectFacesByAttributes faceNum ctrl
)
::RSL_CollisionOps.CollisionForm.enabled = true
#exit
)
else
(
#continue
)
)
#mouseMove:
(
if ir != undefined then
(
-- if we're using one of the pick functions, we set eh attribute controls based on the face we clicked
-- otherwise we're using select functions so we select similar attrbute faces to the face we clicked
if mouseTrackType == #pick then
(
setAttributeControlsRex faceNum
)
else
(
selectFacesByAttributes faceNum ctrl
)
::RSL_CollisionOps.CollisionForm.enabled = true
#exit
)
else
(
#continue
)
)
#mouseAbort:
(
::RSL_CollisionOps.CollisionForm.enabled = true
#exit
)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- pickFilter() Filter function used to ensure we only pick from object we have selected
---------------------------------------------------------------------------------------------------------------------------------------
fn pickFilter object =
(
findItem ::RSL_CollisionOps.theObjects object > 0
),
---------------------------------------------------------------------------------------------------------------------------------------
-- pickPrimitiveAttributes() Sets the standard attribute controls based on the object we pick. This is used in the pick functions
---------------------------------------------------------------------------------------------------------------------------------------
fn pickPrimitiveAttributes =
(
-- pick an object from the selected objects
local pickedObject = pickObject filter:pickFilter
if pickedObject != undefined then
(
-- get eh attribute daat for the picked object
local AttributeData = getAttributeData pickedObject
-- set the surface type if we've used a pick function that supports it
if pickType == "pickSurfaceButton" or pickType == "pickAllButton" then
(
local surfaceType = ::RSL_CollisionOps.attribute.fullAttSurfaceTypeArray[AttributeData.surfaceType]
for i = 0 to pallette.items.count - 1 do
(
local item = pallette.items.item[i]
if (toUpper item.text) == (toUpper surfaceType) then
(
item.selected = true
item.EnsureVisible()
)
)
)
-- set the attribute check buttons if we've used a pick function that supports it
if pickType == "pickFlagsButton" or pickType == "pickAllButton" then
(
stairsCheckBox.checked = (bit.and faceData.flags (bit.shift 1 0) > 0)
noCoverCheckBox.checked = (bit.and faceData.flags (bit.shift 1 4) > 0)
noClimbCheckBox.checked = (bit.and faceData.flags (bit.shift 1 1) > 0)
--noWalkCheckBox.checked = (bit.and faceData.flags (bit.shift 1 5) > 0)
seeCheckBox.checked = (bit.and faceData.flags (bit.shift 1 2) > 0)
noCameraCheckBox.checked = (bit.and faceData.flags (bit.shift 1 7) > 0)
shootCheckBox.checked = (bit.and faceData.flags (bit.shift 1 3) > 0)
pieceTypeButton.text = ::RSL_CollisionOps.attribute.pieceTypeArray[(getAttr pickedObject idxPiece) + 1]
dayNumeric.value = (getAttr pickedObject idxDay)
nightNumeric.value = (getAttr pickedObject idxNight)
audioTextBox.text = (getAttr pickedObject idxAudio)
roomIDNumeric.value = (getAttr pickedObject idxRoomID)
--leedsCheckBox.checked = (getAttr pickedObject idxLeeds)
BVHCheckBox.checked = (getAttr pickedObject idxBVH)
procTintCheckBox.checked = (getAttr pickedObject idxProcTint)
clothCollCheckBox.checked = (getAttr pickedObject idxClothColl)
)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- pickRexBoundAttributes() Starts the mouse track function for picking attributes and selecting faces
---------------------------------------------------------------------------------------------------------------------------------------
fn pickSelectRexBoundAttributes =
(
::RSL_CollisionOps.CollisionForm.enabled = false
mouseTrack on:::RSL_CollisionOps.currentMesh trackCallback:::RSL_CollisionOps.editUI.cb_mouseTrack
),
---------------------------------------------------------------------------------------------------------------------------------------
-- assignPrimitiveAttributes() Assigns standard attrbiutes for each parsed object based on the attribute controls
---------------------------------------------------------------------------------------------------------------------------------------
mapped fn assignPrimitiveAttributes object =
(
-- set the surface type if we've used an assign function that supports it
if assignType == "assignSurfaceButton" or assignType == "assignAllButton" then
(
try (setAttr object idxColType pallette.selectedItems.item[0].text) catch()
)
-- set the attributes if we've used an assign function that supports it
if assignType == "assignFlagsButton" or assignType == "assignAllButton" then
(
try (setAttr object idxStairs stairsCheckBox.checked) catch()
try (setAttr object idxNoCover noCoverCheckBox.checked) catch()
try (setAttr object idxNoClimb noClimbCheckBox.checked) catch()
try (setAttr object idxNoWalk noWalkCheckBox.checked) catch()
try (setAttr object idxSee seeCheckBox.checked) catch()
try (setAttr object idxNoCamera noCameraCheckBox.checked) catch()
try (setAttr object idxShoot shootCheckBox.checked) catch()
try (setAttr object idxPiece ((findItem ::RSL_CollisionOps.attribute.pieceTypeArray pieceTypeButton.text) - 1)) catch()
try (setAttr object idxDay dayNumeric.value) catch()
try (setAttr object idxNight nightNumeric.value) catch()
try (setAttr object idxAudio audioTextBox.text) catch()
try (setAttr object idxRoomID roomIDNumeric.value) catch()
--try (setAttr object idxLeeds leedsCheckBox.checked) catch()
try (setAttr object idxBVH BVHCheckBox.checked) catch()
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- assignRexboundAttibutes() Assigns rexBound attrbiutes for each parsed object based on the attribute controls
---------------------------------------------------------------------------------------------------------------------------------------
fn assignRexboundAttibutes =
(
local okToContinue = pallette.selectedItems.count == 1
local faceArray
-- setup the faceArray and make sure we want to assign to the entire object if we don't have a face selection
if ::RSL_CollisionOps.currentMesh.selectedFaces.count > 0 and subObjectLevel != 0 then
(
faceArray = for f in ::RSL_CollisionOps.currentMesh.selectedFaces collect f.index
)
else
(
okToContinue = queryBox "Ok to assign to the entire object?" title:"Warning..."
faceArray = for f in ::RSL_CollisionOps.currentMesh.faces collect f.index
)
if okToContinue then
(
-- set the surface type if we've used an assign function that supports it
if assignType == "assignSurfaceButton" or assignType == "assignAllButton" then
(
local surfaceValue = findItem ::RSL_CollisionOps.attribute.fullMaterialsDatSurfaceTypeArray (pallette.selectedItems.item[0].text)
setData faceArray surfaceChannel surfaceValue
local faceDataArray = getFaceData ::RSL_CollisionOps.currentMesh
setDisplayMaterial ::RSL_CollisionOps.currentMesh faceDataArray
)
-- set the attributes if we've used an assign function that supports it
if assignType == "assignFlagsButton" or assignType == "assignAllButton" then
(
local flags = 0
if stairsCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 0)
)
if noClimbCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 1)
)
if seeCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 2)
)
if shootCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 3)
)
if noCoverCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 4)
)
--if noWalkCheckBox.checked then
--(
-- flags = bit.or flags (bit.shift 1 5)
--)
if noCameraCheckBox.checked then
(
flags = bit.or flags (bit.shift 1 6)
)
local procValue = (findItem ::RSL_CollisionOps.attribute.proceduralArray proceduralTypeButton.text) - 1
if procValue == 0 then procValue = -1
local miloHandle = -1
if miloRoomButton.tag != undefined then
(
miloHandle = miloRoomButton.tag.value.inode.handle
)
setData faceArray flagsChannel flags
setData faceArray proceduralChannel procValue
setData faceArray miloRoomChannel miloHandle
)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
--
-- UI FUNCTIONS
--
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchFlagSelectClick() Dispatches flagSelectClick() Called when the user clicks any one of the attribute selection buttons
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchFlagSelectClick s e =
(
::RSL_CollisionOps.editUI.flagSelectClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- flagSelectClick() Selects any faces on the currentMesh that have the clicked attributes state e.g. click stairs selection button
-- when the stairs attribute is unchecked will select all faces not marked as stairs
---------------------------------------------------------------------------------------------------------------------------------------
fn flagSelectClick s e =
(
if ::RSL_CollisionOps.currentType == #rexbound then
(
local bitInteger = s.tag.value[1]
local bool = s.tag.value[2]
local faceDataArray = getFaceData ::RSL_CollisionOps.currentMesh
local faceArray = #()
-- check to see if the control button is down and append the selected faces to faceArray so that we grow the face
-- selection rather than replace it
local control = dotNetClass "system.windows.forms.control"
if control.modifierKeys == control.modifierKeys.Control then
(
faceArray = for f in ::RSL_CollisionOps.currentMesh.selectedFaces collect f.index
)
for entry in faceDataArray do
(
if bool then
(
if (bit.and entry.flags (bit.shift 1 bitInteger) > 0) then
(
faceArray += entry.faceArray
)
)
else
(
if (bit.and entry.flags (bit.shift 1 bitInteger) == 0) then
(
faceArray += entry.faceArray
)
)
)
-- set the sub object level the face and select the faces
subObjectLevel = 4
::RSL_CollisionOps.currentMesh.selectedFaces = #()
::RSL_CollisionOps.currentMesh.selectedFaces = faceArray
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchFlagCheck() Dispatches flagCheck() Called when the user checks any one of the attribute buttons
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchFlagCheck s e =
(
::RSL_CollisionOps.editUI.flagCheck s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- flagCheck() Sets the tag of the relevant attribute selection button to the state of the check button so that the selection
-- button knows what to look for when it's pressed
---------------------------------------------------------------------------------------------------------------------------------------
fn flagCheck s e =
(
case s.name of
(
"stairsCheckBox":(stairsSelectButton.tag.value[2] = s.checked)
--"noCoverCheckBox":(noCoverSelectButton.tag.value[2] = s.checked)
"noClimbCheckBox":(noClimbSelectButton.tag.value[2] = s.checked)
--"noWalkCheckBox":(noWalkSelectButton.tag.value[2] = s.checked)
"seeCheckBox":(seeSelectButton.tag.value[2] = s.checked)
"noCameraCheckBox":(noCamSelectButton.tag.value[2] = s.checked)
"shootCheckBox":(shootSelectButton.tag.value[2] = s.checked)
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- 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.editUI.pieceTypeButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- pieceTypeButtonClick() Displays the piece type dialog
---------------------------------------------------------------------------------------------------------------------------------------
fn pieceTypeButtonClick s e =
(
::RSL_CollisionOps.attribute.pieceTypeDialog()
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchRexAttrSelectClick() Dispatches rexAttrSelectClick(), called when the user presses one of the rexBound specific
-- attributes selection buttons e.g. proceduralSelectButton
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchRexAttrSelectClick s e =
(
::RSL_CollisionOps.editUI.rexAttrSelectClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- rexAttrSelectClick() Selects any faces on the currentMesh that have the clicked rexBound attributes state
-- e.g. click proceduralSelectButton to select any faces that match to current state of the procedural attribute
---------------------------------------------------------------------------------------------------------------------------------------
fn rexAttrSelectClick s e =
(
local faceDataArray = getFaceData ::RSL_CollisionOps.currentMesh
local faceArray = #()
-- check to see if the control button is down and append the selected faces to faceArray so that we grow the face
-- selection rather than replace it
local control = dotNetClass "system.windows.forms.control"
if control.modifierKeys == control.modifierKeys.Control then
(
faceArray = for f in ::RSL_CollisionOps.currentMesh.selectedFaces collect f.index
)
local procIndex = (findItem ::RSL_CollisionOps.attribute.proceduralArray proceduralTypeButton.text) - 1
if procIndex == 0 then
(
procIndex = -1
)
local miloHandle = -1
if miloRoomButton.tag != undefined then
(
miloHandle = miloRoomButton.tag.value.inode.handle
)
for entry in faceDataArray do
(
case s.name of
(
"proceduralSelectButton":
(
if entry.proceduralType == procIndex then
(
faceArray += entry.faceArray
)
)
"miloRoomSelectButton":
(
if entry.miloRoom == miloHandle then
(
faceArray += entry.faceArray
)
)
)
)
-- set the sub object level the face and select the faces
subObjectLevel = 4
::RSL_CollisionOps.currentMesh.selectedFaces = #()
::RSL_CollisionOps.currentMesh.selectedFaces = faceArray
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchProceduralTypeButtonClick() Dispatches proceduralTypeButtonClick(), called when the user presses the proceduralTypeButton
-- which is only available for collision meshes
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchProceduralTypeButtonClick s e =
(
::RSL_CollisionOps.editUI.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.editUI.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
---------------------------------------------------------------------------------------------------------------------------------------
fn createAttributeControls type =
(
attributesGroup.controls.clear()
collisionTypeLabel = RS_dotNetUI.Label "collisionTypeLabel" text:" Per Object Collision Type:" textAlign:RS_dotNetPreset.CA_MiddleLeft \
borderStyle:RS_dotNetPreset.BS_None dockStyle:RS_dotNetPreset.DS_Fill
stairsSelectButton = RS_dotNetUI.Button "stairsSelectButton" text:"Stairs" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
stairsSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
stairsSelectButton.tag = dotNetMXSValue #(0,false)
dotnet.addEventHandler stairsSelectButton "click" dispatchFlagSelectClick
stairsCheckBox = RS_dotNetUI.checkBox "stairsCheckBox" text:"" dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler stairsCheckBox "CheckedChanged" dispatchFlagCheck
stairsTableLayout = RS_dotNetUI.tableLayout "stairsTableLayout" \
collumns:#((dataPair type:"Absolute" value:20),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) dockStyle:RS_dotNetPreset.DS_Fill
stairsTableLayout.controls.add stairsCheckBox 0 0
stairsTableLayout.controls.add stairsSelectButton 1 0
/*
noCoverSelectButton = RS_dotNetUI.Button "noCoverSelectButton" text:"Doesn't Provide Cover" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
noCoverSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
noCoverSelectButton.tag = dotNetMXSValue #(4,false)
dotnet.addEventHandler noCoverSelectButton "click" dispatchFlagSelectClick
noCoverCheckBox = RS_dotNetUI.checkBox "noCoverCheckBox" text:"" dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler noCoverCheckBox "CheckedChanged" dispatchFlagCheck
noCoverTableLayout = RS_dotNetUI.tableLayout "noCoverTableLayout" \
collumns:#((dataPair type:"Absolute" value:20),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:20)) dockStyle:RS_dotNetPreset.DS_Fill
noCoverTableLayout.controls.add noCoverCheckBox 0 0
noCoverTableLayout.controls.add noCoverSelectButton 1 0
*/
noClimbSelectButton = RS_dotNetUI.Button "noClimbSelectButton" text:"Non Climable" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
noClimbSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
noClimbSelectButton.tag = dotNetMXSValue #(1,false)
dotnet.addEventHandler noClimbSelectButton "click" dispatchFlagSelectClick
noClimbCheckBox = RS_dotNetUI.checkBox "noClimbCheckBox" text:"" dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler noClimbCheckBox "CheckedChanged" dispatchFlagCheck
noClimbTableLayout = RS_dotNetUI.tableLayout "noClimbTableLayout" \
collumns:#((dataPair type:"Absolute" value:20),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) dockStyle:RS_dotNetPreset.DS_Fill
noClimbTableLayout.controls.add noClimbCheckBox 0 0
noClimbTableLayout.controls.add noClimbSelectButton 1 0
/*
noWalkSelectButton = RS_dotNetUI.Button "noWalkSelectButton" text:"Non Walkable" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
noWalkSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
noWalkSelectButton.tag = dotNetMXSValue #(5,false)
dotnet.addEventHandler noWalkSelectButton "click" dispatchFlagSelectClick
noWalkCheckBox = RS_dotNetUI.checkBox "noWalkCheckBox" text:"" dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler noWalkCheckBox "CheckedChanged" dispatchFlagCheck
noWalkTableLayout = RS_dotNetUI.tableLayout "noWalkTableLayout" \
collumns:#((dataPair type:"Absolute" value:20),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:20)) dockStyle:RS_dotNetPreset.DS_Fill
noWalkTableLayout.controls.add noWalkCheckBox 0 0
noWalkTableLayout.controls.add noWalkSelectButton 1 0
*/
seeSelectButton = RS_dotNetUI.Button "seeSelectButton" text:"See Through" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
seeSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
seeSelectButton.tag = dotNetMXSValue #(2,false)
dotnet.addEventHandler seeSelectButton "click" dispatchFlagSelectClick
seeCheckBox = RS_dotNetUI.checkBox "seeCheckBox" text:"" dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler seeCheckBox "CheckedChanged" dispatchFlagCheck
seeTableLayout = RS_dotNetUI.tableLayout "seeTableLayout" \
collumns:#((dataPair type:"Absolute" value:20),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) dockStyle:RS_dotNetPreset.DS_Fill
seeTableLayout.controls.add seeCheckBox 0 0
seeTableLayout.controls.add seeSelectButton 1 0
noCamSelectButton = RS_dotNetUI.Button "noCamSelectButton" text:"Non Camera Collide" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
noCamSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
noCamSelectButton.tag = dotNetMXSValue #(6,false)
dotnet.addEventHandler noCamSelectButton "click" dispatchFlagSelectClick
noCameraCheckBox = RS_dotNetUI.checkBox "noCameraCheckBox" text:"" dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler noCameraCheckBox "CheckedChanged" dispatchFlagCheck
noCamTableLayout = RS_dotNetUI.tableLayout "noCamTableLayout" \
collumns:#((dataPair type:"Absolute" value:20),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) dockStyle:RS_dotNetPreset.DS_Fill
noCamTableLayout.controls.add noCameraCheckBox 0 0
noCamTableLayout.controls.add noCamSelectButton 1 0
shootSelectButton = RS_dotNetUI.Button "shootSelectButton" text:"Shoot Through" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
shootSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
shootSelectButton.tag = dotNetMXSValue #(3,false)
dotnet.addEventHandler shootSelectButton "click" dispatchFlagSelectClick
shootCheckBox = RS_dotNetUI.checkBox "shootCheckBox" text:"" dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler shootCheckBox "CheckedChanged" dispatchFlagCheck
shootTableLayout = RS_dotNetUI.tableLayout "shootTableLayout" \
collumns:#((dataPair type:"Absolute" value:20),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24)) dockStyle:RS_dotNetPreset.DS_Fill
shootTableLayout.controls.add shootCheckBox 0 0
shootTableLayout.controls.add shootSelectButton 1 0
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:24),(dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:24), (dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
attributesTableLayout.controls.add collisionTypeLabel 0 0
attributesTableLayout.controls.add stairsTableLayout 0 1 --stairsCheckBox
--attributesTableLayout.controls.add noCoverTableLayout 1 4 --noCoverCheckBox
attributesTableLayout.controls.add noClimbTableLayout 0 2 --noClimbCheckBox
--attributesTableLayout.controls.add noWalkTableLayout 1 5 --noWalkCheckBox
attributesTableLayout.controls.add seeTableLayout 0 3 --seeCheckBox
attributesTableLayout.controls.add noCamTableLayout 1 3 --noCameraCheckBox
attributesTableLayout.controls.add shootTableLayout 0 4 --shootCheckBox
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 "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 "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 "Enter" disableAccelerators
--leedsCheckBox = RS_dotNetUI.checkBox "leedsCheckBox" text:("Edited by Leeds") dockStyle:RS_dotNetPreset.DS_Fill
BVHCheckBox = RS_dotNetUI.checkBox "BVHCheckBox" text:("BVH Bound") dockStyle:RS_dotNetPreset.DS_Fill
procTintCheckBox = RS_dotNetUI.checkBox "procTintCheckBox" text:("Use Procedural Tint") dockStyle:RS_dotNetPreset.DS_Fill
clothCollCheckBox = RS_dotNetUI.checkBox "clothCollCheckBox" text:("Is Cloth Collision") dockStyle:RS_dotNetPreset.DS_Fill
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 10
attributesTableLayout.controls.add BVHCheckBox 1 10
attributesTableLayout.controls.add procTintCheckBox 0 11
attributesTableLayout.controls.add clothCollCheckBox 1 11
editTableLayout.RowStyles.Item[2].Height = (296 + 16)
)
#rexbound:
(
proceduralSelectButton = RS_dotNetUI.Button "proceduralSelectButton" text:"Procedural Type:" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
proceduralSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
dotnet.addEventHandler proceduralSelectButton "click" dispatchRexAttrSelectClick
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 = false
pedMultiplierNumeric = RS_dotNetUI.Numeric "ZPadding" value:0 range:#(7, 0, 1, 0) dockStyle:RS_dotNetPreset.DS_Fill
pedMultiplierNumeric.enabled = false
dotnet.addEventHandler pedMultiplierNumeric "Enter" disableAccelerators
miloRoomSelectButton = RS_dotNetUI.Button "miloRoomSelectButton" text:"Milo Room:" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
miloRoomSelectButton.FlatStyle = RS_dotNetPreset.FS_Flat
dotnet.addEventHandler miloRoomSelectButton "click" dispatchRexAttrSelectClick
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" 24)
--attributesTableLayout.RowStyles.add (RS_dotNetObject.RowStyleObject "absolute" 20)
attributesTableLayout.controls.add proceduralSelectButton 0 5 --proceduralTypeLabel
attributesTableLayout.controls.add proceduralTypeButton 1 5
attributesTableLayout.controls.add pedMultiplierLabel 0 6
attributesTableLayout.controls.add pedMultiplierNumeric 1 6
attributesTableLayout.controls.add miloRoomSelectButton 0 7 --miloRoomLabel
attributesTableLayout.controls.add miloRoomButton 1 7
editTableLayout.RowStyles.Item[2].Height = (206 + 16)
)
)
attributesTableLayout
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchSearchTextChanged() Dispatches searchTextChanged(), called when the user changes the text in the searchTextBox
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchSearchTextChanged s e =
(
::RSL_CollisionOps.editUI.searchTextChanged s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- searchTextChanged() Re-populates the surface pallette based on the search text
---------------------------------------------------------------------------------------------------------------------------------------
fn searchTextChanged s e =
(
pallette.Items.clear()
::RSL_CollisionOps.attribute.addSurfaceTypeItem ::RSL_CollisionOps.attribute.matDatSurfaceTypeArray pallette searchTextBox.text
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchPickButtonClick() Dispatches pickButtonClick(), called when the user presses one of the pick check buttons
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchPickButtonClick s e =
(
::RSL_CollisionOps.editUI.pickButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- pickButtonClick() Runs the correct pick function based on the currentType struct variable
---------------------------------------------------------------------------------------------------------------------------------------
fn pickButtonClick s e =
(
-- set the mouseTrackType to #pick so that the mouse track function know which functions to run when we pick a face
mouseTrackType = #pick
searchTextBox.text = ""
pickType = s.name
if ::RSL_CollisionOps.currentType == #primitive then
(
pickPrimitiveAttributes()
)
else
(
pickSelectRexBoundAttributes()
)
s.checked = false
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchSelectButtonClick() Dispatches selectButtonClick(), called when the user presses one of the select check buttons
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchSelectButtonClick s e =
(
::RSL_CollisionOps.editUI.selectButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- selectButtonClick() Runs the function for selecting rexBound attribute faces
---------------------------------------------------------------------------------------------------------------------------------------
fn selectButtonClick s e =
(
-- set the mouseTrackType to #select so that the mouse track function know which functions to run when we pick a face
mouseTrackType = #select
selectType = s.name
pickSelectRexBoundAttributes()
),
---------------------------------------------------------------------------------------------------------------------------------------
-- dispatchAssignButtonClick() Dispatches assignButtonClick(), called when the user presses one of the assign buttons
---------------------------------------------------------------------------------------------------------------------------------------
fn dispatchAssignButtonClick s e =
(
::RSL_CollisionOps.editUI.assignButtonClick s e
),
---------------------------------------------------------------------------------------------------------------------------------------
-- assignButtonClick() Runs the correct assign function based on the currentType struct variable
---------------------------------------------------------------------------------------------------------------------------------------
fn assignButtonClick s e =
(
assignType = s.name
if ::RSL_CollisionOps.currentType == #primitive then
(
assignPrimitiveAttributes ::RSL_CollisionOps.theObjects
)
else
(
assignRexboundAttibutes()
)
),
---------------------------------------------------------------------------------------------------------------------------------------
-- getUI() Creates the edit mode UI. Returns the editTableLayout
---------------------------------------------------------------------------------------------------------------------------------------
fn getUI =
(
editTableLayout = RS_dotNetUI.tableLayout "editTableLayout" text:"editTableLayout" \
collumns:#((dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Percent" value:50),(dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:260)
,(dataPair type:"Absolute" value:(48 + 24)),(dataPair type:"Absolute" value:(48 + 24))) \
dockStyle:RS_dotNetPreset.DS_Fill
pallette = ::RSL_CollisionOps.attribute.surfaceTypePallette ::RSL_CollisionOps.currentType ""
searchLabel = RS_dotNetUI.Label "searchLabel" text:(" Search:") \
textAlign:RS_dotNetPreset.CA_MiddleLeft borderStyle:RS_dotNetPreset.BS_None \
dockStyle:RS_dotNetPreset.DS_Fill
searchTextBox = RS_dotNetUI.textBox "searchTextBox" borderStyle:RS_dotNetPreset.BS_Fixed3D dockStyle:RS_dotNetPreset.DS_Fill
dotNet.addEventHandler searchTextBox "TextChanged" dispatchSearchTextChanged
dotnet.addEventHandler searchTextBox "Enter" disableAccelerators
attributesGroup = RS_dotNetUI.GroupBox "attributesGroup" Text:"Attributes" dockStyle:RS_dotNetPreset.DS_Fill
attributesGroup.controls.add (createAttributeControls ::RSL_CollisionOps.currentType)
pickSurfaceButton = RS_dotNetUI.checkBox "pickSurfaceButton" text:("Surface") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler pickSurfaceButton "click" dispatchPickButtonClick
pickFlagsButton = RS_dotNetUI.checkBox "pickFlagsButton" text:("Attributes") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler pickFlagsButton "click" dispatchPickButtonClick
pickAllButton = RS_dotNetUI.checkBox "pickAllButton" text:("All") appearance:RS_dotNetPreset.AC_Button dockStyle:RS_dotNetPreset.DS_Fill
dotnet.addEventHandler pickAllButton "click" dispatchPickButtonClick
pickTableLayout = RS_dotNetUI.tableLayout "pickTableLayout" text:"pickTableLayout" \
collumns:#((dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
pickTableLayout.controls.add pickSurfaceButton 0 0
pickTableLayout.controls.add pickFlagsButton 1 0
pickTableLayout.controls.add pickAllButton 0 1
pickTableLayout.SetColumnSpan pickAllButton 2
pickGroup = RS_dotNetUI.GroupBox "pickGroup" Text:"Pick" dockStyle:RS_dotNetPreset.DS_Fill
pickGroup.controls.add pickTableLayout
selectSurfaceButton = RS_dotNetUI.Button "selectSurfaceButton" text:"Surface" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler selectSurfaceButton "click" dispatchSelectButtonClick
selectFlagsButton = RS_dotNetUI.Button "selectFlagsButton" text:"Attributes" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler selectFlagsButton "click" dispatchSelectButtonClick
selectAllButton = RS_dotNetUI.Button "selectAllButton" text:"All" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler selectAllButton "click" dispatchSelectButtonClick
selectTableLayout = RS_dotNetUI.tableLayout "selectTableLayout" text:"editTableLayout" \
collumns:#((dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
selectTableLayout.controls.add selectSurfaceButton 0 0
selectTableLayout.controls.add selectFlagsButton 1 0
selectTableLayout.controls.add selectAllButton 0 1
selectTableLayout.SetColumnSpan selectAllButton 2
selectGroup = RS_dotNetUI.GroupBox "selectGroup" Text:"Select" dockStyle:RS_dotNetPreset.DS_Fill
selectGroup.controls.add selectTableLayout
assignSurfaceButton = RS_dotNetUI.Button "assignSurfaceButton" text:"Surface" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler assignSurfaceButton "click" dispatchAssignButtonClick
assignFlagsButton = RS_dotNetUI.Button "assignFlagsButton" text:"Attributes" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler assignFlagsButton "click" dispatchAssignButtonClick
assignAllButton = RS_dotNetUI.Button "assignAllButton" text:"All" dockStyle:RS_dotNetPreset.DS_Fill margin:(RS_dotNetObject.paddingObject 2)
dotnet.addEventHandler assignAllButton "click" dispatchAssignButtonClick
assignTableLayout = RS_dotNetUI.tableLayout "assignTableLayout" text:"editTableLayout" \
collumns:#((dataPair type:"Percent" value:50),(dataPair type:"Percent" value:50)) \
rows:#((dataPair type:"Absolute" value:24),(dataPair type:"Absolute" value:24)) \
dockStyle:RS_dotNetPreset.DS_Fill
assignTableLayout.controls.add assignSurfaceButton 0 0
assignTableLayout.controls.add assignFlagsButton 1 0
assignTableLayout.controls.add assignAllButton 0 1
assignTableLayout.SetColumnSpan assignAllButton 2
assignGroup = RS_dotNetUI.GroupBox "assignGroup" Text:"Assign" dockStyle:RS_dotNetPreset.DS_Fill
assignGroup.controls.add assignTableLayout
editTableLayout.controls.add pallette 0 0
editTableLayout.controls.add searchLabel 0 1
editTableLayout.controls.add searchTextBox 1 1
editTableLayout.controls.add attributesGroup 0 2
editTableLayout.controls.add pickGroup 0 3
editTableLayout.controls.add selectGroup 1 3
editTableLayout.controls.add assignGroup 0 4
editTableLayout.SetColumnSpan pallette 2
editTableLayout.SetColumnSpan attributesGroup 2
editTableLayout.SetColumnSpan assignGroup 2
editTableLayout
)
)