1906 lines
83 KiB
Plaintext
Executable File
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
|
|
)
|
|
) |