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

788 lines
26 KiB
Plaintext
Executable File

/*###########
Creature Metadata Setup
Description:
--Used for creating creature metadata files for driving things like wrinkle maps and hair scaling
History:
--Kevin Ala-Pantti - January, 2014
--Created
Wiki:
--https://devstar.rockstargames.com/wiki/index.php/Ped_Creature_Metadata
###########*/
try(destroyDialog RSCreatureMetadata)catch()
-- This line loads the custom header
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms")
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/FN_RSTA_xml.ms")
--Load the xml assemply
dotNet.loadAssembly "system.xml"
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
global RSCreatureMetadata
/*-------------------------------------------------------------------------------------------------------------------------
RsTa_hashDriverName
Hashes the name string of an object and removes the trailing L
-------------------------------------------------------------------------------------------------------------------------*/
fn RsTa_hashDriverName driver=
(
local driverNameHash = substring driver 5 driver.count
driverNameHash = ((athash16u driverNameHash) as string)
driverNameHash = substring driverNameHash 1 (driverNameHash.count-1)
)
/*-------------------------------------------------------------------------------------------------------------------------
RsTa_clearSection
Deletes a section of an xml
-------------------------------------------------------------------------------------------------------------------------*/
fn RsTa_clearSection savePath sectionToClear=
(
-- Load the XML to edit
local xmlDoc = dotNetObject "system.xml.xmlDocument"
xmlDoc.load savePath
-- Get the root element
local docEle = xmlDoc.documentElement
local childToRemove = undefined
-- If the root element exists and is named properly try find the desired section
if docEle!=undefined and docEle.name=="CCreatureMetaData" then
(
for i = 0 to docEle.childNodes.count-1 do
(
if docEle.ChildNodes.itemOf[i].name == sectionToClear then
(
childToRemove = docEle.ChildNodes.itemOf[i]
)
)
-- If the child was found then delete that section
if childToRemove != undefined then docEle.RemoveChild childToRemove
)
xmlDoc.save (savePath)
)
/*-------------------------------------------------------------------------------------------------------------------------
RsTa_findXMLSection
Finds if a section of an xml exists; returns that section if it is found
-------------------------------------------------------------------------------------------------------------------------*/
fn RsTa_findXMLSection savePath sectionToFind=
(
-- Load the XML to edit
local xmlDoc = dotNetObject "system.xml.xmlDocument"
xmlDoc.load savePath
-- Get the root element
local docEle = xmlDoc.documentElement
local found = undefined
-- If the root element exists and is named properly try find the desired section
if docEle!=undefined and docEle.name=="CCreatureMetaData" then
(
for i = 0 to docEle.childNodes.count-1 do
(
if docEle.ChildNodes.itemOf[i].name == sectionToFind then found = docEle.ChildNodes.itemOf[i]
)
)
-- Return the found section, or undefined if it doesn't exist
found
)
/*-------------------------------------------------------------------------------------------------------------------------
RsTa_createXMLSectionNode
Fills in the "Item"s of an XML section
-------------------------------------------------------------------------------------------------------------------------*/
fn RsTa_createXMLSectionNode root nodeTypes nodeAttrTypes nodeAttrValues nodeInnerText=
(
-- Create a new Item under the current section
local item = rsta_xml.makeNode "Item" root
-- Create the contents of the item
for i = 1 to nodeTypes.count do
(
rsta_xml.makeNode nodeTypes[i] item attr:nodeAttrTypes[i] value:nodeAttrValues[i] innerText:nodeInnerText[i]
)
)
/*-------------------------------------------------------------------------------------------------------------------------
RsTa_writeXMLSection
Write a new section of the XML under the topmost root; converts passed values to proper attribute and innertext values
-------------------------------------------------------------------------------------------------------------------------*/
fn RsTa_writeXMLSection savePath root metaType compType varHash driverList numVariations=
(
local typeRoot = undefined
for i = 0 to root.childNodes.count-1 do
(
if root.ChildNodes.itemOf[i].name == metaType then typeRoot = root.ChildNodes.itemOf[i]
)
if metaType == "shaderVariableComponents" then
(
-- If the root for this type of metadata doesn't exist then make it
if typeRoot == undefined then typeRoot = rsta_xml.makeNode metaType root
-- The contents of the items to put under the root
local nodeTypes = #("pedcompID", "maskID", "shaderVariableHashString", "tracks", "ids", "components")
local nodeAttrTypes = #("value","value",undefined,"content","content","content")
for i = 1 to driverList.count do
(
local nodeAttrValues = #(((compType-1) as string), driverList[i][1], "", "char_array", "short_array", "char_array")
local driverNameHash = RsTa_hashDriverName driverList[i]
local nodeInnerText = #(undefined, undefined, varHash, "23", driverNameHash, driverList[i][3])
RsTa_createXMLSectionNode typeRoot nodeTypes nodeAttrTypes nodeAttrValues nodeInnerText
)
)
if metaType == "pedPropExpressions" then
(
if typeRoot == undefined then typeRoot = rsta_xml.makeNode metaType root
local nodeTypes = #("pedPropID", "pedPropVarIndex", "pedPropExpressionIndex", "tracks", "ids", "types", "components")
local nodeAttrTypes = #("value","value","value","content","content","content","content")
for i = 1 to driverList.count do
(
for vars = -1 to numVariations do
(
local exprSlot = 0
if vars == -1 then exprSlot = "-1"
else exprSlot = driverList[i][3]
local nodeAttrValues = #(((compType-1) as string), (vars as string), exprSlot, "char_array", "short_array", "char_array", "char_array")
local driverNameHash = RsTa_hashDriverName driverList[i]
local axis = ""
case driverList[i][1] of
(
"X": axis = "0"
"Y": axis = "1"
"Z": axis = "2"
)
local nodeInnerText = #(undefined, undefined, undefined, "33", driverNameHash, "2", axis)
RsTa_createXMLSectionNode typeRoot nodeTypes nodeAttrTypes nodeAttrValues nodeInnerText
)
)
)
if metaType == "pedCompExpressions" then
(
if typeRoot == undefined then typeRoot = rsta_xml.makeNode metaType root
local nodeTypes = #("pedcompID", "pedCompVarIndex", "pedCompExpressionIndex", "tracks", "ids", "types", "components")
local nodeAttrTypes = #("value","value","value","content","content","content","content")
for i = 1 to driverList.count do
(
for vars = 0 to numVariations do
(
local exprSlot = 0
if vars == -1 then exprSlot = "-1"
else exprSlot = driverList[i][3]
local nodeAttrValues = #(((compType-1) as string), (vars as string), exprSlot, "char_array", "short_array", "char_array", "char_array")
local driverNameHash = RsTa_hashDriverName driverList[i]
local axis = ""
case driverList[i][1] of
(
"X": axis = "0"
"Y": axis = "1"
"Z": axis = "2"
)
local nodeInnerText = #(undefined, undefined, undefined, "33", driverNameHash, "2", axis)
RsTa_createXMLSectionNode typeRoot nodeTypes nodeAttrTypes nodeAttrValues nodeInnerText
)
)
)
)
/*-------------------------------------------------------------------------------------------------------------------------
RsTa_appendXMLSection
Add on a new section after the last child of the XML root
-------------------------------------------------------------------------------------------------------------------------*/
fn RsTa_appendXMLSection savePath metaType compType varHash driverList numVariations=
(
local xmlDoc = dotNetObject "system.xml.xmlDocument"
xmlDoc.load savePath
local root = xmlDoc.documentElement
RsTa_writeXMLSection savePath root metaType compType varHash driverList numVariations
xmlDoc.save (savePath)
)
/*-------------------------------------------------------------------------------------------------------------------------
RsTa_newXML
Create a whole new XML
-------------------------------------------------------------------------------------------------------------------------*/
fn RsTa_newXML savePath metaType compType varHash driverList numVariations=
(
-- make a new XML
local xmlDoc = dotNetObject "system.xml.xmlDocument"
xmlDoc.AppendChild (xmlDoc.CreateXmlDeclaration "1.0" "utf-8" "")
-- the top most root
local root = xmlDoc.createElement "CCreatureMetaData"
xmlDoc.appendChild root
RsTa_writeXMLSection savePath root metaType compType varHash driverList numVariations
xmlDoc.save (savePath)
)
/*-------------------------------------------------------------------------------------------------------------------------
RsTa_writeXML
Ensures file exists; checks Add / Overwrite state and begins the proper type of XML writing
-------------------------------------------------------------------------------------------------------------------------*/
fn RsTa_writeXML savePath metaType compType varHash driverList numVariations updateState =
(
if doesFileExist savePath == false then
(
-- file doesn't exist so make a new XML
RsTa_newXML savePath metaType compType varHash driverList numVariations
)
else if updateState == 3 then
(
-- overwrite full file
RsTa_newXML savePath metaType compType varHash driverList numVariations
)
else if doesFileExist savePath == true then
(
if updateState == 1 then
(
-- add section
RsTa_appendXMLSection savePath metaType compType varHash driverList numVariations
)
if updateState == 2 then
(
-- overwrite section
local typeRoot = RsTa_findXMLSection savePath metaType
if typeRoot == undefined then RsTa_appendXMLSection savePath metaType compType varHash driverList numVariations
else
(
RsTa_clearSection savePath metaType
RsTa_appendXMLSection savePath metaType compType varHash driverList numVariations
)
)
)
)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*-------------------------------------------------------------------------------------------------------------------------
SHADERVARIABLECOMPONENTS ROLLOUT
-------------------------------------------------------------------------------------------------------------------------*/
rollout RSCreatureMetadata_Shaders "Shader Variable Components"
(
local compTypes = #("Head", "Berd", "Hair", "Uppr", "Lowr", "Hand", "Feet", "Teef", "Accs", "Task", "Decl", "Jbib")
local hashStrings = #("WrinkleWeights")
local overwrites = #("Add To Section","Overwrite Section", "Overwrite All")
local savePath = undefined
dropdownlist ddl_compType "Component Type:" items:compTypes
dropdownlist ddl_hashString "Variable Hash String:" items:hashStrings
button btn_populateDrivers "Populate List With Selected Drivers" width:(RSCreatureMetadata_Shaders.width-26) height:30
listbox lbx_Drivers "Drivers" align:#left width:(RSCreatureMetadata_Shaders.width-130)
spinner spn_maskID "Mask ID" range:[0,5,0] type:#integer fieldWidth:20 offset:[0, -110] enabled:false
spinner spn_rgbaChannel "RGBA Channel" range:[0,3,0] type:#integer fieldWidth:20 offset:[0,25] enabled:false
button btn_chooseDirectory "Save As..." width:(RSCreatureMetadata_Shaders.width-26) enabled:false offset:[0,80] height:40
button btn_writeXML "Write XML" width:(RSCreatureMetadata_Shaders.width-26) enabled:false height:40
group "Options"
(
radiobuttons rbtn_updateOverwrite "Add / Overwrite" labels:overwrites align:#center
)
on btn_populateDrivers pressed do
(
local sel = getCurrentSelection()
if (sel.count > 0) then
(
spn_maskID.enabled = true
spn_rgbaChannel.enabled = true
btn_chooseDirectory.enabled = true
local selNames = for x in sel collect x.name
for i = 1 to selNames.count do selNames[i] = ("0 0 " + selNames[i])
lbx_Drivers.items = selNames
)
)
on spn_maskID changed ID do
(
local tempStr = lbx_Drivers.selected
tempStr[1] = (ID as string)
lbx_Drivers.selected = tempStr
)
on spn_rgbaChannel changed chan do
(
local tempStr = lbx_Drivers.selected
tempStr[3] = (chan as string)
lbx_Drivers.selected = tempStr
)
on lbx_Drivers selected item do
(
local itemStr = lbx_Drivers.items[item]
local maskID = (itemStr[1] as integer)
local rgbaChan = (itemStr[3] as integer)
spn_maskID.value = maskID
spn_rgbaChannel.value = rgbaChan
)
on btn_chooseDirectory pressed do
(
savePath = getSaveFileName caption:"Save CreatureMetadata XML" filename:"" types:"Metadata(*.meta)|*.meta|"
if (savePath != undefined) then
(
RSCreatureMetadata.savePath = savePath
btn_writeXML.enabled = true
)
)
on btn_writeXML pressed do
(
local metaType = "shaderVariableComponents"
local compType = ddl_compType.selection
local varHash = ddl_hashString.selected
local driverList = lbx_Drivers.items
local numVariations = 0
local updateState = rbtn_updateOverwrite.state
RsTa_writeXML savePath metaType compType varHash driverList numVariations updateState
)
on rbtn_updateOverwrite changed state do
(
RSCreatureMetadata.addOverwriteState = state
)
on RSCreatureMetadata_Shaders open do
(
if RSCreatureMetadata == undefined then rbtn_updateOverwrite.state = 1
else rbtn_updateOverwrite.state = RSCreatureMetadata.addOverwriteState
if RSCreatureMetadata != undefined then
(
if RSCreatureMetadata.savePath != undefined then
(
savePath = RSCreatureMetadata.savePath
btn_writeXML.enabled = true
)
)
)
)
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
/*-------------------------------------------------------------------------------------------------------------------------
PEDPROPEXPRESSIONS ROLLOUT
-------------------------------------------------------------------------------------------------------------------------*/
rollout RSCreatureMetadata_Props "Ped Prop Expressions"
(
local compTypes = #("P_Head", "P_Eyes")
local axes = #("X","Y","Z")
local overwrites = #("Add To Section","Overwrite Section", "Overwrite All")
local savePath = undefined
dropdownlist ddl_compType "Component Type:" items:compTypes
button btn_populateDrivers "Populate List With Selected Drivers" width:(RSCreatureMetadata_Shaders.width-26) height:30
listbox lbx_Drivers "Drivers" align:#left width:(RSCreatureMetadata_Shaders.width-130)
radiobuttons rbtn_drivenAxis "Driven By Axis" labels:axes align:#right offset:[0,-140] enabled:false
spinner spn_expressionChannel "Expr. Index" range:[0,4,0] type:#integer fieldWidth:20 enabled:false offset:[0,25]
spinner spn_numVariations "# Variations" range:[0,30,0] type:#integer fieldWidth:20 enabled:false offset:[0,25]
button btn_chooseDirectory "Save As..." width:(RSCreatureMetadata_Shaders.width-26) enabled:false offset:[0,45] height:40
button btn_writeXML "Write XML" width:(RSCreatureMetadata_Shaders.width-26) enabled:false height:40
group "Options"
(
radiobuttons rbtn_updateOverwrite "Add / Overwrite" labels:overwrites align:#center
)
on btn_populateDrivers pressed do
(
local sel = getCurrentSelection()
if (sel.count > 0) then
(
rbtn_drivenAxis.enabled = true
spn_expressionChannel.enabled = true
spn_numVariations.enabled = true
btn_chooseDirectory.enabled = true
local selNames = for x in sel collect x.name
for i = 1 to selNames.count do selNames[i] = ("X 0 " + selNames[i])
lbx_Drivers.items = selNames
)
)
on rbtn_drivenAxis changed axis do
(
local tempStr = lbx_Drivers.selected
tempStr[1] = (axes[axis] as string)
lbx_Drivers.selected = tempStr
)
on spn_expressionChannel changed chan do
(
local tempStr = lbx_Drivers.selected
tempStr[3] = (chan as string)
lbx_Drivers.selected = tempStr
)
on lbx_Drivers selected item do
(
local itemStr = lbx_Drivers.items[item]
local axis = itemStr[1]
local exprChan = (itemStr[3] as integer)
local axisNum = findItem axes axis
rbtn_drivenAxis.state = axisNum
spn_expressionChannel.value = exprChan
)
on btn_chooseDirectory pressed do
(
savePath = getSaveFileName caption:"Save CreatureMetadata XML" filename:"" types:"Metadata(*.meta)|*.meta|"
if (savePath != undefined) then
(
RSCreatureMetadata.savePath = savePath
btn_writeXML.enabled = true
)
)
on btn_writeXML pressed do
(
local metaType = "pedPropExpressions"
local compType = ddl_compType.selection
local varHash = ""
local driverList = lbx_Drivers.items
local numVariations = spn_numVariations.value
local updateState = rbtn_updateOverwrite.state
RsTa_writeXML savePath metaType compType varHash driverList numVariations updateState
)
on rbtn_updateOverwrite changed state do
(
RSCreatureMetadata.addOverwriteState = state
)
on RSCreatureMetadata_Props open do
(
if RSCreatureMetadata == undefined then rbtn_updateOverwrite.state = 1
else rbtn_updateOverwrite.state = RSCreatureMetadata.addOverwriteState
if RSCreatureMetadata != undefined then
(
if RSCreatureMetadata.savePath != undefined then
(
savePath = RSCreatureMetadata.savePath
btn_writeXML.enabled = true
)
)
)
)
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
/*-------------------------------------------------------------------------------------------------------------------------
PEDCOMPEXPRESSIONS ROLLOUT
-------------------------------------------------------------------------------------------------------------------------*/
rollout RSCreatureMetadata_Components "Ped Component Expressions"
(
local compTypes = #("Head", "Berd", "Hair", "Uppr", "Lowr", "Hand", "Feet", "Teef", "Accs", "Task", "Decl", "Jbib")
local axes = #("X","Y","Z")
local overwrites = #("Add To Section","Overwrite Section", "Overwrite All")
local savePath = undefined
dropdownlist ddl_compType "Component Type:" items:compTypes
button btn_populateDrivers "Populate List With Selected Drivers" width:(RSCreatureMetadata_Shaders.width-26) height:30
listbox lbx_Drivers "Drivers" align:#left width:(RSCreatureMetadata_Shaders.width-130)
radiobuttons rbtn_drivenAxis "Driven By Axis" labels:axes align:#right offset:[0,-140] enabled:false
spinner spn_expressionChannel "Expr. Index" range:[0,4,0] type:#integer fieldWidth:20 enabled:false offset:[0,25]
spinner spn_numVariations "# Variations" range:[0,30,0] type:#integer fieldWidth:20 enabled:false offset:[0,25]
button btn_chooseDirectory "Save As..." width:(RSCreatureMetadata_Shaders.width-26) enabled:false offset:[0,45] height:40
button btn_writeXML "Write XML" width:(RSCreatureMetadata_Shaders.width-26) enabled:false height:40
group "Options"
(
radiobuttons rbtn_updateOverwrite "Add / Overwrite" labels:overwrites align:#center
)
on btn_populateDrivers pressed do
(
local sel = getCurrentSelection()
if (sel.count > 0) then
(
rbtn_drivenAxis.enabled = true
spn_expressionChannel.enabled = true
spn_numVariations.enabled = true
btn_chooseDirectory.enabled = true
local selNames = for x in sel collect x.name
for i = 1 to selNames.count do selNames[i] = ("X 0 " + selNames[i])
lbx_Drivers.items = selNames
)
)
on rbtn_drivenAxis changed axis do
(
local tempStr = lbx_Drivers.selected
tempStr[1] = (axes[axis] as string)
lbx_Drivers.selected = tempStr
)
on spn_expressionChannel changed chan do
(
local tempStr = lbx_Drivers.selected
tempStr[3] = (chan as string)
lbx_Drivers.selected = tempStr
)
on lbx_Drivers selected item do
(
local itemStr = lbx_Drivers.items[item]
local axis = itemStr[1]
local exprChan = (itemStr[3] as integer)
local axisNum = findItem axes axis
rbtn_drivenAxis.state = axisNum
spn_expressionChannel.value = exprChan
)
on btn_chooseDirectory pressed do
(
savePath = getSaveFileName caption:"Save CreatureMetadata XML" filename:"" types:"Metadata(*.meta)|*.meta|"
if (savePath != undefined) then
(
RSCreatureMetadata.savePath = savePath
btn_writeXML.enabled = true
)
)
on btn_writeXML pressed do
(
local metaType = "pedCompExpressions"
local compType = ddl_compType.selection
local varHash = ""
local driverList = lbx_Drivers.items
local numVariations = spn_numVariations.value
local updateState = rbtn_updateOverwrite.state
RsTa_writeXML savePath metaType compType varHash driverList numVariations updateState
)
on rbtn_updateOverwrite changed state do
(
RSCreatureMetadata.addOverwriteState = state
)
on RSCreatureMetadata_Components open do
(
if RSCreatureMetadata == undefined then rbtn_updateOverwrite.state = 1
else rbtn_updateOverwrite.state = RSCreatureMetadata.addOverwriteState
if RSCreatureMetadata != undefined then
(
if RSCreatureMetadata.savePath != undefined then
(
savePath = RSCreatureMetadata.savePath
btn_writeXML.enabled = true
)
)
)
)
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
/*-------------------------------------------------------------------------------------------------------------------------
MAIN ROLLOUT
-------------------------------------------------------------------------------------------------------------------------*/
rollout RSCreatureMetadata "R* Creature Metadata Editor" width:400
(
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:(RSCreatureMetadata.width)
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"Ped_Creature_Metadata" filename:(getThisScriptFilename())
dotNetControl dn_tabs "System.Windows.Forms.TabControl" height:20 width:(RSCreatureMetadata.width) align:#center pos:[-1, (RsBannerPanel.height + 2)]
subRollout theSubRollout height:750 align:#center width:(RSCreatureMetadata.width) pos:[0, dn_tabs.pos.y + dn_tabs.height]
local lastClickNum
local maxAutoHeight = 900
local keepWidth
local savePath = undefined
local addOverwriteState = 1
local tabRollouts =
#(
dataPair name:"Shaders" rollouts:#(RSCreatureMetadata_Shaders),
dataPair name:"Props" rollouts:#(RSCreatureMetadata_Props),
dataPair name:"Components" rollouts:#(RSCreatureMetadata_Components)
)
fn setSubrollSize =
(
theSubRollout.height = (RSCreatureMetadata.height - theSubRollout.pos.y)
)
fn showTab clickNum =
(
if (lastClickNum != clickNum) do --do not update if the same tab clicked twice
(
lastClickNum = clickNum
for subRoll in theSubRollout.rollouts do
(
removeSubRollout theSubRollout subroll
)
local setHeight = theSubRollout.pos.y + 6
for subRoll in tabRollouts[clickNum].rollouts do
(
addSubRollout theSubRollout subRoll
setHeight += (subRoll.height + 24)
)
if (setHeight > maxAutoHeight) do
(
setHeight = maxAutoHeight
)
RSCreatureMetadata.height = setHeight
setSubrollSize()
)
)
on dn_tabs Selected itm do
(
local clickNum = (itm.TabPageIndex + 1)
showTab clickNum
RsSettingWrite "RsCharSeamSnapper" "lastTab" tabRollouts[clickNum].name
)
on RSCreatureMetadata resized newSize do
(
if (newSize.x != keepWidth) and (keepWidth != undefined) do
(
RSCreatureMetadata.width = keepWidth
)
setSubrollSize()
)
on RSCreatureMetadata open do
(
banner.setup()
keepWidth = RSCreatureMetadata.width
local savedTabName = RsSettingsReadString "RSCreatureMetadata" "lastTab" undefined
local savedTabNum = 1
for tabNum = 1 to tabRollouts.count do
(
local tabName = tabRollouts[tabNum].name
dn_tabs.TabPages.add tabName
if (tabName == savedTabName) do
(
savedTabNum = tabNum
)
)
dn_tabs.SelectedIndex = (savedTabNum - 1)
showTab savedTabNum
)
)
-------------------------------------------------------------------------------------------------------------------------
createDialog RSCreatureMetadata 400 400 style:#(#style_resizing,#style_titlebar, #style_toolwindow, #style_sysmenu)