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

1255 lines
36 KiB
Plaintext
Executable File

struct DataNode
(
parent,
key = "",
value = ""
)
struct ContentNode
(
parent,
type, --#source #export #scenexml #processed #target
id = "",
data = #(),
fn addData item =
(
append this.data (DataNode parent:this key:item.key value:item.value)
)
)
struct ContentEdge
(
parent,
source,
target,
type, --#export #preprocess #rage
data = #(),
fn addData item =
(
append this.data (DataNode parent:this key:item.key value:item.value)
)
)
struct ContentGraphNode
(
id = "",
edgedefault = "directed",
children = #()
)
struct ContentCreator
(
--dlcPathRoot = "X:/gta5_dlc/dlc_maps_test",
--assetType = "interior",
contentRoot = "",
assetName = "",
contentConfigPath = "",
parentContentPath = "",
contentGraph,
contentType,
writer,
archetypes,
entities,
slod2link,
prefix = "",
sourceAssetPath = "",
sourcePathRoot = "$(art)/models/",
exportPathRoot = ("$(export)/levels/" + (RsConfigGetProjectName()) + "/" ),
processedPathRoot = ("$(processed)/levels/" + (RsConfigGetProjectName()) + "/" ),
targetPathRoot = ("$(target)/levels/" + (RsConfigGetProjectName()) + "/" ),
area,
block,
/***
***/
fn graphNameSolver =
(
local id = "level:"
id += RsConfigGetProjectName()
id += ":"
id += contentType
return id
),
/***
return a name for a node based on the content
***/
fn nodeIdNameSolver inputNode =
(
local id = "level:"
--projectname
id += RsConfigGetProjectName()
--content type
id += ":"
local pathbits = filterString sourceAssetPath "\\"
local modelsIdx = findItem pathbits "models"
if modelsIdx != 0 then
(
id += pathbits[modelsIdx + 1]
)
--id += inputNode.
--filename
id += ":"
id += assetName
--node type
id += ":"
id += inputNode.type
--replace any :: with :
id = substituteString id "::" ":"
--return
id
),
/***
***/
fn createNode parentGraph type: =
(
local newNode = ContentNode parent:parentGraph
newNode.type = type
append newNode.parent.children newNode
newNode.id = nodeIdNameSolver newNode
return newNode
),
/***
create and edge between two nodes
***/
fn createEdge node1 node2 parentGraph type: =
(
local newEdge = ContentEdge parent:parentGraph
newEdge.source = node1
newEdge.target = node2
--newEdge.parent = parentGraph
newEdge.type = type
append newEdge.parent.children newEdge
return newEdge
),
/***
Create a data processor
***/
fn createProcessorDataNode type parentNode =
(
),
/***
Create a interior content graph
***/
fn constructInteriorGraph =
(
this.contentGraph = ContentGraphNode()
this.contentGraph.id = graphNameSolver()
--paths
local pathValue = "$(art)/models/interiors/" + assetName + ".max"
local exportPathValue = "$(export)/levels/" + gRsCoreConfig.project.name + "/interiors/" + assetName + ".zip"
local processedPathValue = processedPathRoot + "interiors/" + assetName + ".zip"
local targetPathValue = "$(target)/levels/" + gRsCoreConfig.project.name + "/interiors/" + assetName + ".rpf"
--create Source nodes
local sourceNode = createNode this.contentGraph type:#source
sourceNode.addData (DataPair key:"content_type" value:"file")
sourceNode.addData (DataPair key:"path" value:pathValue)
sourceNode.addData (DataPair key:"max_type" value:"interior")
sourceNode.addData (DataPair key:"archetypes" value:archetypes)
sourceNode.addData (DataPair key:"entities" value:entities)
sourceNode.addData (DataPair key:"prefix" value:prefix)
--create Export nodes
local zipExportNode = createNode this.contentGraph type:#export
zipExportNode.addData (DataPair key:"content_type" value:"file")
zipExportNode.addData (DataPair key:"path" value:exportPathValue)
local sceneExportNode = createNode this.contentGraph type:#scenexml
sceneExportNode.addData (DataPair key:"content_type" value:"file")
exportPathValue = "$(export)/levels/" + gRsCoreConfig.project.name + "/interiors/" + assetName + ".xml"
sceneExportNode.addData (DataPair key:"path" value:exportPathValue)
--create Processed Nodes
local processedNode = createNode this.contentGraph type:#processed
processedNode.addData (DataPair key:"content_type" value:"file")
processedNode.addData (DataPair key:"path" value:processedPathValue)
--create Target nodes
local targetNode = createNode this.contentGraph type:#target
targetNode.addData (DataPair key:"content_type" value:"file")
targetNode.addData (DataPair key:"path" value:targetPathValue)
--create ExportEdges
local exportEdge1 = createEdge sourceNode zipExportNode this.contentGraph type:#export
exportEdge1.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Common.Dcc3dsmaxExportProcessor")
exportEdge1.addData (DataPair key:"dcc_export_process" value:"true")
local exportEdge2 = createEdge sourceNode sceneExportNode this.contentGraph type:#export
exportEdge2.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Common.Dcc3dsmaxExportProcessor")
exportEdge2.addData (DataPair key:"dcc_export_process" value:"true")
--create Processed Edges
local processEdge1 = createEdge zipExportNode processedNode this.contentGraph type:#preprocess
processEdge1.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Map.PreProcess")
local processEdge2 = createEdge sceneExportNode processedNode this.contentGraph type:#preprocess
processEdge2.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Map.PreProcess")
--create Target Edge
local targetEdge = createEdge processedNode targetNode this.contentGraph type:#rage
targetEdge.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Platform.Rage")
),
/***
Create a map_container content graph
***/
fn constructMapContainerGraph =
(
this.contentGraph = ContentGraphNode()
this.contentGraph.id = graphNameSolver()
--PATHS
local localityPath
local sourcePathValue
local exportPathValue
local exportSceneXml
local processedPathValue
local targetPathValue
if prefix == "" then
(
prefix = assetName
)
case gRsCoreConfig.project.name of
(
"gta5":
(
localityPath = block + "/" + area
sourcePathValue = sourcePathRoot + localityPath + assetName + ".maxc"
exportPathValue = exportPathRoot + localityPath + assetName + ".zip"
exportSceneXml = exportPathRoot + localityPath + assetName + ".xml"
processedPathValue = "$(processed)/levels/" + gRsCoreConfig.project.name + "/" + localityPath + assetName + ".zip"
targetPathValue = targetPathRoot + localityPath + assetName + ".rpf"
)
"gta5_liberty":
(
localityPath = block + "/" + area
sourcePathValue = sourcePathRoot + area + assetName + ".maxc"
exportPathValue = exportPathRoot + area + assetName + ".zip"
exportSceneXml = exportPathRoot + area + assetName + ".xml"
processedPathValue = "$(processed)/levels/" + gRsCoreConfig.project.name + "/" + area + assetName + ".zip"
targetPathValue = targetPathRoot + area + assetName + ".rpf"
)
)
--create Source nodes
local sourceNode = createNode this.contentGraph type:#source
sourceNode.addData (DataPair key:"content_type" value:"file")
sourceNode.addData (DataPair key:"path" value:sourcePathValue)
sourceNode.addData (DataPair key:"max_type" value:"map_container")
sourceNode.addData (DataPair key:"archetypes" value:archetypes)
sourceNode.addData (DataPair key:"entities" value:entities)
sourceNode.addData (DataPair key:"prefix" value:prefix)
--create Export nodes
local zipExportNode = createNode this.contentGraph type:#export
zipExportNode.addData (DataPair key:"content_type" value:"file")
zipExportNode.addData (DataPair key:"path" value:exportPathValue)
local sceneExportNode = createNode this.contentGraph type:#scenexml
sceneExportNode.addData (DataPair key:"content_type" value:"file")
sceneExportNode.addData (DataPair key:"path" value:exportSceneXml)
--create Processed Nodes
local processedNode = createNode this.contentGraph type:#processed
processedNode.addData (DataPair key:"content_type" value:"file")
processedNode.addData (DataPair key:"path" value:processedPathValue)
processedNode.addData (DataPair key:"slod2link" value:slod2link)
--create Target nodes
local targetNode = createNode this.contentGraph type:#target
targetNode.addData (DataPair key:"content_type" value:"file")
targetNode.addData (DataPair key:"path" value:targetPathValue)
--create ExportEdges
local exportEdge1 = createEdge sourceNode zipExportNode this.contentGraph type:#export
exportEdge1.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Common.Dcc3dsmaxExportProcessor")
exportEdge1.addData (DataPair key:"dcc_export_process" value:"true")
local exportEdge2 = createEdge sourceNode sceneExportNode this.contentGraph type:#export
exportEdge2.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Common.Dcc3dsmaxExportProcessor")
exportEdge2.addData (DataPair key:"dcc_export_process" value:"true")
--create Processed Edges
local processEdge1 = createEdge zipExportNode processedNode this.contentGraph type:#preprocess
processEdge1.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Map.PreProcess")
local processEdge2 = createEdge sceneExportNode processedNode this.contentGraph type:#preprocess
processEdge2.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Map.PreProcess")
--create Target Edge
local targetEdge = createEdge processedNode targetNode this.contentGraph type:#rage
targetEdge.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Platform.Rage")
),
/***
Create a lod_container graph
***/
fn constructLodContainerGraph =
(
),
/***
Create a occl_container graph
***/
fn constructOcclContainerGraph =
(
),
/***
Create a prop graph
***/
fn constructPropGraph =
(
--like interior except dont export entities
this.contentGraph = ContentGraphNode()
this.contentGraph.id = graphNameSolver()
--paths
local propFolder
local pathValue
local exportPathValue
local sceneXmlPathValue
local processedPathValue
local targetPathValue
case gRsCoreConfig.project.name of
(
"gta5":
(
propFolder = substituteString (pathConfig.stripPathToLeaf maxfilepath) "\\" "/"
pathValue = "$(art)/models/" + propFolder + assetName + ".max"
exportPathValue = "$(export)/levels/" + gRsCoreConfig.project.name + "/props/" + assetName + ".zip"
sceneXmlPathValue = "$(export)/levels/" + gRsCoreConfig.project.name + "/props/" + propFolder + assetName + ".xml"
processedPathValue = processedPathRoot + "props/" + assetName + ".zip"
targetPathValue = "$(target)/levels/" + gRsCoreConfig.project.name + "/props/" + assetName + ".rpf"
)
"gta5_liberty":
(
propFolder = substituteString (pathConfig.stripPathToLeaf maxfilepath) "\\" "/"
pathValue = "$(art)/models/gta5/props/" + propFolder + assetName + ".max"
exportPathValue = "$(export)/levels/" + "gta5" + "/props/" + propFolder + assetName + ".zip"
sceneXmlPathValue = "$(export)/levels/" + "gta5" + "/props/" + propFolder + assetName + ".xml"
processedPathValue = processedPathRoot + "props/" + propFolder + assetName + ".zip"
targetPathValue = "$(target)/levels/" + gRsCoreConfig.project.name + "/props/" + propFolder + assetName + ".rpf"
)
)
--create Source nodes
local sourceNode = createNode this.contentGraph type:#source
sourceNode.addData (DataPair key:"content_type" value:"file")
sourceNode.addData (DataPair key:"path" value:pathValue)
sourceNode.addData (DataPair key:"max_type" value:"props")
sourceNode.addData (DataPair key:"archetypes" value:archetypes)
sourceNode.addData (DataPair key:"entities" value:entities)
sourceNode.addData (DataPair key:"prefix" value:prefix)
--create Export nodes
local zipExportNode = createNode this.contentGraph type:#export
zipExportNode.addData (DataPair key:"content_type" value:"file")
zipExportNode.addData (DataPair key:"path" value:exportPathValue)
local sceneExportNode = createNode this.contentGraph type:#scenexml
sceneExportNode.addData (DataPair key:"content_type" value:"file")
sceneExportNode.addData (DataPair key:"path" value:sceneXmlPathValue)
--create Processed Nodes
local processedNode = createNode this.contentGraph type:#processed
processedNode.addData (DataPair key:"content_type" value:"file")
processedNode.addData (DataPair key:"path" value:processedPathValue)
--create Target nodes
local targetNode = createNode this.contentGraph type:#target
targetNode.addData (DataPair key:"content_type" value:"file")
targetNode.addData (DataPair key:"path" value:targetPathValue)
--create ExportEdges
local exportEdge1 = createEdge sourceNode zipExportNode this.contentGraph type:#export
exportEdge1.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Common.Dcc3dsmaxExportProcessor")
exportEdge1.addData (DataPair key:"dcc_export_process" value:"true")
local exportEdge2 = createEdge sourceNode sceneExportNode this.contentGraph type:#export
exportEdge2.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Common.Dcc3dsmaxExportProcessor")
exportEdge2.addData (DataPair key:"dcc_export_process" value:"true")
--create Processed Edges
local processEdge1 = createEdge zipExportNode processedNode this.contentGraph type:#preprocess
processEdge1.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Map.PreProcess")
local processEdge2 = createEdge sceneExportNode processedNode this.contentGraph type:#preprocess
processEdge2.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Map.PreProcess")
--create Target Edge
local targetEdge = createEdge processedNode targetNode this.contentGraph type:#rage
targetEdge.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Platform.Rage")
),
/***
Create a vehicle graph
***/
fn constructVehicleGraph =
(
this.contentGraph = ContentGraphNode()
this.contentGraph.id = graphNameSolver()
--PATHS
--local sourcePathValue = "$(art)/models/props/weapons/" + assetName + "/" + assetName + ".max"
local exportPathValue = "$(export)/levels/gta5/vehicles_packed"
local targetPathValue = "$(target)/models/cdimages/" + assetName + ".rpf"
),
/***
Create a weapon graph
***/
fn constructWeaponGraph =
(
this.contentGraph = ContentGraphNode()
this.contentGraph.id = graphNameSolver()
--PATHS
local sourcePathValue = "$(art)/models/props/weapons/" + assetName + "/" + assetName + ".max"
local exportPathValue = "$(export)/models/cdimages/weapons.zip"
local targetPathValue = "$(target)/models/cdimages/weapons.rpf"
--create Source nodes
local sourceNode = createNode this.contentGraph type:#source
sourceNode.addData (DataPair key:"content_type" value:"file")
sourceNode.addData (DataPair key:"path" value:sourcePathValue)
sourceNode.addData (DataPair key:"archetypes" value:archetypes)
sourceNode.addData (DataPair key:"entities" value:entities)
--create Export nodes
local zipExportNode = createNode this.contentGraph type:#export
zipExportNode.addData (DataPair key:"content_type" value:"file")
zipExportNode.addData (DataPair key:"path" value:exportPathValue)
--create Target nodes
local targetNode = createNode this.contentGraph type:#target
targetNode.addData (DataPair key:"content_type" value:"file")
targetNode.addData (DataPair key:"path" value:targetPathValue)
--create ExportEdges
local exportEdge1 = createEdge sourceNode zipExportNode this.contentGraph type:#export
exportEdge1.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Common.Dcc3dsmaxExportProcessor")
--create Target Edge
local targetEdge = createEdge zipExportNode targetNode this.contentGraph type:#rage
targetEdge.addData (DataPair key:"processor" value:"RSG.Pipeline.Processor.Platform.Rage")
),
/***
Create a graph
***/
fn createGraph =
(
print contentType
case contentType of
(
"map_container": constructMapContainerGraph()
"lod_container": constructLodContainerGraph()
"occl_container": constructOcclContainerGraph()
"interior": constructInteriorGraph()
"prop": constructPropGraph()
"weapon": constructWeaponGraph()
"vehicle": constructVehicleGraph()
default: print "da fuq!?"
)
),
/**********************************************************************************************************************
IO Functions
**********************************************************************************************************************/
/***
Read an existing content tree document and create an internal node tree representation
***/
fn readContent =
(
),
/***
***/
fn harvestContentNodePaths xmlRoot =
(
--collect all the paths in the content tree using the input xml
local pathNodes = xmlRoot.SelectNodes ".//data[@key=\"path\"]"
local pathValues = for i=0 to (pathNodes.count - 1) collect pathNodes.item[i].innerText
return pathValues
),
/***
***/
fn harvestContentGraphPaths =
(
local contentNodes = for item in this.contentGraph.children where (classOf item == ContentNode) collect item
local paths = #()
for item in contentNodes do
(
local pathVal = for elem in item.data where elem.key == "path" collect elem.value
appendifunique paths pathVal[1]
)
return paths
),
/***
Validate conent that is being created or appended against existing content tree to check that these paths are not already being
defined for data conversion, which could lead to errors in the build pipeline
***/
fn validateContent xml contentNodePaths =
(
--gRsProject.name
local foundConflict = false
--get the XInclude nodes
local nt = dotnetobject "System.Xml.NameTable"
local xmlns = dotnetobject "System.Xml.XmlNamespaceManager" nt
xmlns.AddNameSpace "xi" "http://www.w3.org/2003/XInclude"
local includedXml = xml.SelectNodes ".//xi:include/@href" xmlns
--print includedXml.count
for i=0 to (includedXml.count - 1) do
(
local thisXml = includedXml.item[i].value
local xmlDoc = dotNetObject "System.Xml.XmlDocument"
try
(
xmlDoc.load thisXml
)
catch
(
print "Could not load this xml"
print thisXml
continue
)
local xmlRoot = xmlDoc.DocumentElement
local pathValues = harvestContentNodePaths xmlRoot
--see if any match against the supplied paths for the new content
for path in pathValues do
(
if (findItem contentNodePaths path) != 0 then
(
--break()
foundConflict = true
return foundConflict
)
)
)
return foundConflict
),
/***
***/
fn writeEdges type =
(
for item in this.contentGraph.children where (classOf item == ContentEdge) and (item.type == type) do
(
writer.WriteStartElement("edge")
writer.WriteAttributeString "source" item.source.id
writer.WriteAttributeString "target" item.target.id
for data in item.data do
(
writer.WriteStartElement("data")
writer.WriteAttributeString "key" data.key
writer.WriteValue data.value
writer.WriteEndElement()
)
writer.WriteEndElement()
)
),
/***
***/
fn writeNodes type =
(
for item in this.contentGraph.children where (classOf item == ContentNode) and (item.type == type) do
(
writer.WriteStartElement("node")
writer.WriteAttributeString "id" item.id
for data in item.data do
(
writer.WriteStartElement("data")
writer.WriteAttributeString "key" data.key
writer.WriteValue data.value
writer.WriteEndElement()
)
writer.WriteEndElement()
)
),
/***
***/
fn removeContent xmlDoc graphNode id =
(
--find all the nodes and get their names
local matchingNodes = graphNode.SelectNodes (".//node[contains(@id, \"" + id + "\")]")
--now match the node names for edges that use them
local nodeIt = matchingNodes.GetEnumerator()
while nodeIt.MoveNext() do
(
local idAttr = nodeIt.Current.GetAttribute "id"
--find edges referencing this node
local dependentEdges = graphNode.SelectNodes (".//edge[contains(@source, \"" + idAttr + "\") or contains(@target, \"" + idAttr + "\")]")
local edgeIt = dependentEdges.GetEnumerator()
while edgeIt.MoveNext() do
(
graphNode.RemoveChild edgeIt.Current
)
graphNode.RemoveChild nodeIt.Current
)
),
/***
***/
fn appendEdges xmlDoc graph type =
(
for item in this.contentGraph.children where (classOf item == ContentEdge) and (item.type == type) do
(
local newEdge = xmlDoc.CreateElement "edge"
local sourceAttr = xmlDoc.CreateAttribute "source"
sourceAttr.value = item.source.id
newEdge.SetAttributeNode sourceAttr
local targetAttr = xmlDoc.CreateAttribute "target"
targetAttr.value = item.target.id
newEdge.SetAttributeNode targetAttr
for data in item.data do
(
local dataNode = xmlDoc.CreateElement "data"
local keyAttr = xmlDoc.CreateAttribute "key"
keyAttr.value = data.key
dataNode.InnerText = data.value
dataNode.SetAttributeNode keyAttr
newEdge.AppendChild dataNode
)
graph.AppendChild newEdge
)
),
/***
***/
fn appendNodes xmlDoc graph type =
(
for item in this.contentGraph.children where (classOf item == ContentNode) and (item.type == type) do
(
local newNode = xmlDoc.CreateElement "node"
local idAttr = xmlDoc.CreateAttribute "id"
idAttr.value = item.id
newNode.SetAttributeNode idAttr
for data in item.data do
(
local dataNode = xmlDoc.CreateElement "data"
local keyAttr = xmlDoc.CreateAttribute "key"
keyAttr.value = data.key
dataNode.InnerText = data.value
dataNode.SetAttributeNode keyAttr
newNode.AppendChild dataNode
)
graph.AppendChild newNode
)
),
/***
Append to a content tree document
***/
fn appendContent =
(
local xmlDoc = dotNetObject "System.Xml.XmlDocument"
--load the xml doc
xmlDoc.load this.contentConfigPath
local xmlRoot = xmlDoc.DocumentElement
local nt = dotnetobject "System.Xml.NameTable"
local xmlns = dotnetobject "System.Xml.XmlNamespaceManager" nt
xmlns.AddNameSpace "ns" "http://graphml.graphdrawing.org/xmlns"
local graphNode = xmlRoot.SelectSingleNode "//graph" xmlns
if (graphNode == undefined) then
(
graphNode = xmlRoot.SelectSingleNode "//ns:graph" xmlns
)
local foundConflicts = validateContent xmlRoot (harvestContentGraphPaths())
if not foundConflicts then
(
--create a changelist to store the file changes
local changeListNum = gRsPerforce.createChangelist "Append content"
--maybe check if there is content to overwrite
--using this.assetName
local matchingNodes = graphNode.SelectNodes (".//node[contains(@id, \"" + assetName + "\")]")
if (matchingNodes.count != 0) then --we have some nodes already in place that need removing
(
removeContent xmlDoc graphNode assetName
)
--append the nodes and edges
appendNodes xmlDoc graphNode #source
appendNodes xmlDoc graphNode #export
appendNodes xmlDoc graphNode #scenexml
appendNodes xmlDoc graphNode #processed
appendNodes xmlDoc graphNode #target
appendEdges xmlDoc graphNode #export
appendEdges xmlDoc graphNode #preprocess
appendEdges xmlDoc graphNode #rage
--is it writable? check out of perforce?
if ( (getFileAttribute this.contentConfigPath #readonly) == true) then
(
local p4Exists = gRsPerforce.exists #(this.contentConfigPath)
if p4Exists[1] then
(
gRsPerforce.add_or_edit #(this.contentConfigPath)
gRsPerforce.addToChangelist changeListNum this.contentConfigPath
)
else
(
setFileAttribute this.contentConfigPath #readonly false
)
)
--save it
try
(
xmlDoc.save this.contentConfigPath
)
catch
(
messagebox "failed to save the conent document" title:"Failed Save"
)
)
else
(
messagebox "This content already exists in the content tree" title:"Content Tree Conflict"
)
),
/***
Create a new content tree document
***/
fn createContent =
(
--check for valid output path
if (this.contentConfigPath == undefined ) or (pathConfig.isLegalPath this.contentConfigPath == false) then
(
messagebox "No valid path set" title:"Bad Path"
return false
)
--create a changelist to store the file changes
local changeListNum = gRsPerforce.createChangelist "Create contenttree"
--init the document
--create the xml doc
--initiate writer
local xmlFormatter = dotnetobject "System.Xml.XMLWriterSettings"
xmlFormatter.Indent = true
writer = dotnetclass "System.Xml.XMLWriter"
writer = writer.Create this.contentConfigPath xmlFormatter
--make the header
writer.WriteStartDocument()
writer.WriteStartElement("graphml")
-- writer.WriteAttributeString "xmlns" "http://graphml.graphdrawing.org/xmlns"
-- writer.WriteAttributeString "xmlns:xsi" "http://www.w3.org/2001/XMLSchema-instance"
-- writer.WriteAttributeString "xmlns:xi" "http://www.w3.org/2003/XInclude"
-- writer.WriteAttributeString "xsi:schemaLocation" "http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"
writer.WriteStartElement("graph")
writer.WriteAttributeString "id" (this.contentGraph.id)
writer.WriteAttributeString "edgedefault" "directed"
writer.WriteComment("Nodes")
--make the nodes
writeNodes #source
writeNodes #export
writeNodes #scenexml
writeNodes #processed
writeNodes #target
writer.WriteComment("Edges")
--make the edges
writeEdges #export
writeEdges #preprocess
writeEdges #rage
--make the footer
writer.WriteEndElement()
writer.WriteEndElement()
--finish up
writer.WriteEndDocument()
--save the document
try
(
writer.Flush()
writer.Close()
gRsPerforce.add_or_edit #(this.contentConfigPath)
gRsPerforce.addToChangelist changeListNum this.contentConfigPath
)
catch
(
messagebox "Problem saving the content tree file" title:"File Save Error"
return false
)
--Now check if parentContnetPath is set and add this new file into that
if (parentContentPath != "") then
(
--check writable
if ( (getFileAttribute this.parentContentPath #readonly) == true) then
(
local p4Exists = gRsPerforce.exists #(this.parentContentPath)
if p4Exists[1] then
(
gRsPerforce.add_or_edit #(this.parentContentPath)
gRsPerforce.addToChangelist changeListNum this.parentContentPath
)
else
(
setFileAttribute this.parentContentPath #readonly false
)
)
local xmlDoc = dotNetObject "System.Xml.XmlDocument"
--load the xml doc
xmlDoc.load this.parentContentPath
local xmlRoot = xmlDoc.DocumentElement
--check for content clashes
local paths = harvestContentGraphPaths()
local foundConflicts = validateContent xmlRoot paths
format "foundConflicts: % \n" foundConflicts as String
if not foundConflicts then
(
local includeNode = xmlDoc.CreateElement "xi" "include" "http://www.w3.org/2003/XInclude"
local keyAttr = xmlDoc.CreateAttribute "href"
keyAttr.value = (getfilenamefile this.contentConfigPath) + ".xml"
includeNode.SetAttributeNode keyAttr
xmlRoot.AppendChild includeNode
try
(
xmlDoc.save this.parentContentPath
)
catch
(
messagebox "Problem saving the parent content tree file" title:"File Save Error"
return false
)
)
else
(
messagebox "This content already exists in the content tree" title:"Content Tree Conflict"
try
(
deletefile this.contentConfigPath
)
catch
(
print "Tried to delete the new content file, but failed"
)
gRsPerforce.deleteChangelistIfItHasNoChanges changeListNum
)
)
),
/***
***/
on create do
(
--Init ContentCreator struct
)
)
--/////////////////////////////////////////
-- UI
--/////////////////////////////////////////
try(destroyDialog ContentCreatorUI)catch()
rollout ContentCreatorUI "Content Tree Creator" width:400 height:350
(
--/////////////////////////////////////////
-- VARIABLES
--/////////////////////////////////////////
local contentTree = ContentCreator()
--local max_TypeList = #("map_container", "lod_container", "occl_container", "interior", "prop", "weapon", "vehicle")
local max_TypeList = #("interior", "weapon", "prop")
local contentPath
--/////////////////////////////////////////
-- CONTROLS
--/////////////////////////////////////////
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:(ContentCreatorUI.width)
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"DLC_ContentTree_Creator" versionNum:0.57 versionName:"Amethyst Fist" filename:(getThisScriptFilename())
--label lblAssetPath "Asset Path"
--checkbox chkDlc "DLC"
group "Asset settings"
(
dropdownlist ddlMax_Type items:max_TypeList
checkbox chkArchetypes "Archetypes" across:3
checkbox chkEntities "Entities"
checkbox chkSLOD2Link "Slod2 Link"
edittext edtPrefix "Prefix:"
)
group "Create Content"
(
edittext edtContentFolderPath "DLC Folder: " text:"" edittable:false width:(ContentCreatorUI.width - 75) across:2
button btnContentPathBrowse "..." align:#right
edittext edtParentContentFilePath "Parent Content: " text:"dlc_content.xml" width:(ContentCreatorUI.width - 75) across:2
button btnParentContentPathBrowse "..." align:#right
edittext edtContentName "Name:" width:(ContentCreatorUI.width - 75)
button btnCreateConfig "Create" width:(ContentCreatorUI.width - 25)
)
group "Append Content"
(
edittext edtContentAppendFilePath "Asset Path: " text:"" edittable:false width:(ContentCreatorUI.width - 75) across:2
button btnContentAppendPathBrowse "..." align:#right
button btnAppendConfig "Append" width:(ContentCreatorUI.width - 25)
)
--/////////////////////////////////////////
-- FUNCTIONS
--/////////////////////////////////////////
fn setOpts =
(
if (contentPath == "") then
(
messageBox "No asset path set" title:":'("
return false
)
--set config from UI
local sceneFileName = getFileNameFile maxFileName
local containerSelected = if (classof selection[1] == Container) then true else false
if (sceneFileName == "") and (not containerSelected) then
(
messageBox "Select a container or load a valid scene to proceed" title:"no content"
return false
)
if containerSelected then
(
local containerPath = undefined
containerPath = selection[1].sourceDefinitionFilename
if (containerPath == undefined) or (containerPath == "") then
(
containerPath = selection[1].localDefinitionFilename
)
if (containerPath == undefined) or (containerPath == "") then
(
print "cant get a container path"
messageBox "Cant get a container path" title:"Error: Container Path"
return false
)
contentTree.sourceAssetPath = containerPath
contentTree.assetName = tolower (getFileNameFile containerPath)
contentTree.area = substituteString (pathConfig.stripPathToLeaf (getFileNamePath containerPath)) "\\" "/"
local trimmed = pathConfig.removePathLeaf (getFileNamePath containerPath)
contentTree.block = substituteString (pathConfig.stripPathToLeaf trimmed) "\\" "/"
)
else
(
contentTree.sourceAssetPath = maxFilePath
contentTree.assetName = tolower(getFileNameFile maxFileName)
contentTree.area = ""
contentTree.block = ""
)
contentTree.archetypes = chkArchetypes.state as String
contentTree.entities = chkEntities.state as String
contentTree.prefix = edtPrefix.text
contentTree.slod2link = chkSLOD2Link.state as String
contentTree.contentConfigPath = contentPath
return true
)
--/////////////////////////////////////////
-- EVENTS
--/////////////////////////////////////////
/***
Browse for a content file path
***/
on btnContentPathBrowse pressed do
(
local savePath = getSavePath caption:"Content Save Folder" initialDir:(RsConfigGetProjRootDir())
if (savePath == undefined) then
(
return false
)
else
(
edtContentFolderPath.text = savePath
)
if (edtContentName.text == "") then--set a default name
(
edtContentName.text = (RsConfigGetProjectName()) + "_content_level_" + gRsCoreConfig.project.name + "_" + ContentCreatorUI.ddlMax_Type.selected + ".xml"
savePath += ("/" + edtContentName.text)
print savePath
)
else
(
savePath += ("/" + edtContentName.text)
)
contentTree.contentConfigPath = savePath
contentPath = savePath
--set the Parent content control using this path if it hasnt been changed from the default
if edtParentContentFilePath.text == "dlc_content.xml" then
(
edtParentContentFilePath.text = edtContentFolderPath.text + "/" + edtParentContentFilePath.text
contentTree.parentContentPath = RsMakeSafeSlashes edtParentContentFilePath.text
)
)
/***
Update the output path when new text is entered in the create content name field
***/
on edtContentName entered val do
(
print val
local newVal = ""
--add extension if need be
if ( matchpattern val pattern:"*.xml" == false ) then --add the extension
(
newVal = val + ".xml"
)
else
(
newVal = val
)
edtContentName.text = newVal
local savePath = edtContentFolderPath.text + "\\" + newVal
contentTree.contentConfigPath = savePath
contentPath = savePath
print savePath
)
/***
Browse for a parent content path to add the created content to
***/
on btnParentContentPathBrowse pressed do
(
local savePath = getOpenFileName caption:"Content Path" types:"Content (*.xml)|*.xml"
if (savePath == undefined) then
(
return false
)
edtParentContentFilePath.text = savePath
contentTree.parentContentPath = savePath
)
/***
Browse for an existing content file path to append to
***/
on btnContentAppendPathBrowse pressed do
(
local savePath = getOpenFileName caption:"Content Path" types:"Content (*.xml)|*.xml"
if (savePath == undefined) then
(
return false
)
edtContentAppendFilePath.text = savePath
--contentTree.contentConfigPath = savePath
contentPath = savePath
)
/***
Set the ContentCreator based on the type of content chosen in this dropdown
***/
fn ddlMax_TypeSelected arg =
(
contentTree.contentType = max_TypeList[arg]
case contentTree.contentType of
(
"map_container":
(
chkArchetypes.state = true
chkEntities.state = true
)
"interior":
(
chkArchetypes.state = true
chkEntities.state = false
)
"weapon":
(
chkArchetypes.state = true
chkEntities.state = false
)
"prop":
(
chkArchetypes.state = true
chkEntities.state = false
)
)
)
on ddlMax_Type selected arg do ddlMax_TypeSelected arg
/***
***/
on btnCreateConfig pressed do
(
local success = setOpts()
if (not success) then
(
return false
)
contentTree.createGraph()
contentTree.createContent()
)
/***
***/
on btnAppendConfig pressed do
(
case contentTree.contentType of
(
"map_container":
(
for item in (selection as array) do
(
clearSelection()
select item
local success = setOpts()
if (not success) then
(
return false
)
contentTree.createGraph()
contentTree.appendContent()
)
)
default:
(
local success = setOpts()
if (not success) then
(
return false
)
contentTree.createGraph()
contentTree.appendContent()
)
)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on ContentCreatorUI open do
(
banner.setup()
contentTree.contentType = max_TypeList[1]
contentTree.contentRoot = RsConfigGetProjRootDir()
--set default asset type
ddlMax_TypeSelected 1
)
)
createDialog ContentCreatorUI