888 lines
27 KiB
Plaintext
Executable File
888 lines
27 KiB
Plaintext
Executable File
rsta_loadCommonFunction #("FN_RSTA_xml")
|
|
|
|
escapeenable = true
|
|
|
|
struct IpInstance
|
|
(
|
|
ArchetypeName = "",
|
|
ContainerRef = "",
|
|
IplGroup = "",
|
|
Pos = [0,0,0],
|
|
Rot = [0,0,0],
|
|
Scale = [1,1,1]
|
|
)
|
|
|
|
struct sIpIPLGroup
|
|
(
|
|
name,
|
|
centroid,
|
|
colour,
|
|
count = 0
|
|
)
|
|
|
|
struct IpInstanceProcessor
|
|
(
|
|
_ipInstances = #(),
|
|
_metaPath = @"x:\americas\art\dev\environment\Terrain\houdini\gtav_dlc\islandx\metas\h4_islandx_placement.meta",
|
|
_islandPositionOffset = [0, 0, 0],
|
|
_medianPlacementPoint = [4896.09,-5391.85,0],
|
|
_sw_placementCont,
|
|
_nw_placementCont,
|
|
_ne_placementCont,
|
|
_se_placementCont,
|
|
_sw_instanceCounter = 0,
|
|
_nw_instanceCounter = 0,
|
|
_ne_instanceCounter = 0,
|
|
_se_instanceCounter = 0,
|
|
_IPL_Attr = getattrindex "Gta Object" "IPL Group",
|
|
_NEWDLC_ATTR = getattrindex "Gta Object" "New DLC",
|
|
_IPL_COUNT_LIMIT = 10,
|
|
_IPL_MAXITEMS = 900,
|
|
-- _IPLGROUPS = #((DataPar)),
|
|
|
|
--These inital centroids are created by hand, based on the main point set and judgind where likely point density centres will be
|
|
_swIplInitialCentroids = #((sIpIPLGroup name:"h4_sw_ipl_00" centroid:[4803.75,-5927.7,0] colour:(color 218 105 104)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_01" centroid:[4863.74,-5453.32,0] colour:(color 232 115 57)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_02" centroid:[4709.87,-5647.74,0] colour:(color 240 120 3)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_03" centroid:[4869.29,-5661.07,0] colour:(color 186 201 53)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_04" centroid:[4810.97,-5826.6,0] colour:(color 84 213 83)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_05" centroid:[4835.41,-5527.2,0] colour:(color 62 200 243)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_06" centroid:[4819.85,-5606.63,0] colour:(color 21 22 99)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_07" centroid:[4758.2,-5781.61,0] colour:(color 145 29 144)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_08" centroid:[4755.42,-5523.31,0] colour:(color 208 82 201)),
|
|
(sIpIPLGroup name:"h4_sw_ipl_09" centroid:[4794.86,-5713.29,0] colour:(color 242 158 159))),
|
|
|
|
_seIplInitialCentroids = #((sIpIPLGroup name:"h4_se_ipl_00" centroid:[5456.97,-5828.2,0] colour:(color 255 0 255)),
|
|
(sIpIPLGroup name:"h4_se_ipl_01" centroid:[4990.22,-5434.08,0] colour:(color 166 84 82)),
|
|
(sIpIPLGroup name:"h4_se_ipl_02" centroid:[4920.74,-5638.09,0] colour:(color 124 73 39)),
|
|
(sIpIPLGroup name:"h4_se_ipl_03" centroid:[4930.21,-5837.68,0] colour:(color 112 111 106)),
|
|
(sIpIPLGroup name:"h4_se_ipl_04" centroid:[5503.71,-5478.3,0] colour:(color 133 230 51)),
|
|
(sIpIPLGroup name:"h4_se_ipl_05" centroid:[5220.75,-5471.35,0] colour:(color 206 214 206)),
|
|
(sIpIPLGroup name:"h4_se_ipl_06" centroid:[5285.81,-5567.98,0] colour:(color 95 173 230)),
|
|
(sIpIPLGroup name:"h4_se_ipl_07" centroid:[5332.54,-5725.25,0] colour:(color 66 68 239)),
|
|
(sIpIPLGroup name:"h4_se_ipl_08" centroid:[5088.11,-5558.51,0] colour:(color 232 41 230)),
|
|
(sIpIPLGroup name:"h4_se_ipl_09" centroid:[5156.96,-5685.46,0] colour:(color 208 82 201))),
|
|
|
|
_neIplInitialCentroids = #((sIpIPLGroup name:"h4_ne_ipl_00" centroid:[5054.64,-5328.6,0] colour:(color 0 255 255)),
|
|
(sIpIPLGroup name:"h4_ne_ipl_01" centroid:[5479.71,-5286.29,0] colour:(color 69 7 2 )),
|
|
(sIpIPLGroup name:"h4_ne_ipl_02" centroid:[4989.58,-4574.47,0] colour:(color 114 58 19)),
|
|
(sIpIPLGroup name:"h4_ne_ipl_03" centroid:[5085.59,-4854.27,0] colour:(color 255 251 59)),
|
|
(sIpIPLGroup name:"h4_ne_ipl_04" centroid:[5232.12,-5051.96,0] colour:(color 26 65 22)),
|
|
(sIpIPLGroup name:"h4_ne_ipl_05" centroid:[5243.49,-5281.23,0] colour:(color 26 80 31)),
|
|
(sIpIPLGroup name:"h4_ne_ipl_06" centroid:[5016.74,-4966.7,0] colour:(color 131 132 133)),
|
|
(sIpIPLGroup name:"h4_ne_ipl_07" centroid:[5026.85,-4729.85,0] colour:(color 53 53 184)),
|
|
(sIpIPLGroup name:"h4_ne_ipl_08" centroid:[5362.86,-4878.91,0] colour:(color 141 17 139)),
|
|
(sIpIPLGroup name:"h4_ne_ipl_09" centroid:[4995.9,-5083.54,0] colour:(color 80 22 25))),
|
|
|
|
_nwIplInitialCentroids = #((sIpIPLGroup name:"h4_nw_ipl_00" centroid:[4863.86,-5276.45,0] colour:(color 255 255 0)),
|
|
(sIpIPLGroup name:"h4_nw_ipl_01" centroid:[4658.81,-4465.67,0] colour:(color 149 76 53 )),
|
|
(sIpIPLGroup name:"h4_nw_ipl_02" centroid:[4608.4,-4851.28,0] colour:(color 205 99 12)),
|
|
(sIpIPLGroup name:"h4_nw_ipl_03" centroid:[4825.45,-4628.87,0] colour:(color 168 172 29)),
|
|
(sIpIPLGroup name:"h4_nw_ipl_04" centroid:[4792.4,-4368.05,0] colour:(color 20 138 18)),
|
|
(sIpIPLGroup name:"h4_nw_ipl_05" centroid:[4585.36,-4578.5,0] colour:(color 140 187 154)),
|
|
(sIpIPLGroup name:"h4_nw_ipl_06" centroid:[4263.36,-4344.47,0] colour:(color 87 92 248)),
|
|
(sIpIPLGroup name:"h4_nw_ipl_07" centroid:[4321.83,-4442.55,0] colour:(color 14 5 201)),
|
|
(sIpIPLGroup name:"h4_nw_ipl_08" centroid:[3877.75,-4721.77,0] colour:(color 80 1 77)),
|
|
(sIpIPLGroup name:"h4_nw_ipl_09" centroid:[4774.84,-4500.03,0] colour:(color 199 64 66))),
|
|
|
|
_pointClusterList = #(),
|
|
_pointClusterPaths = #(),
|
|
|
|
_iplGroupDefs = Dictionary(),
|
|
|
|
|
|
fn GetIPLName item =
|
|
(
|
|
return (getattr item _IPL_Attr)
|
|
),
|
|
|
|
fn SetIPLWireColours objList =
|
|
(
|
|
for item in objList do
|
|
(
|
|
local iplName = GetIPLName item
|
|
item.wirecolor = (_iplGroupDefs.GetValue iplName).colour
|
|
)
|
|
),
|
|
|
|
fn IPLItemCount iplName =
|
|
(
|
|
local matchingItems = for item in objects where (classof item == RsRefobject) and ((getattr item _IPL_Attr) == iplName) collect item
|
|
return matchingItems.count
|
|
),
|
|
|
|
fn SelectIPLContent iplname =
|
|
(
|
|
clearSelection()
|
|
select (local matchingItems = for item in objects where (classof item == RsRefobject) and ((getattr item _IPL_Attr) == iplName) collect item)
|
|
),
|
|
|
|
--Create an initial division of points in
|
|
fn ClusterPointAroundIPLGroups centroids points =
|
|
(
|
|
_pointClusterList = #()
|
|
-- for c in centroids do
|
|
-- (
|
|
-- clusters.addKey c.name #()
|
|
-- )
|
|
|
|
for p=1 to points.count do
|
|
(
|
|
local thisPoint = points[p]
|
|
local closestCentroid = undefined
|
|
local closestDist = 99999
|
|
for c=1 to centroids.count do
|
|
(
|
|
local dist = (distance thisPoint centroids[c].centroid)
|
|
if dist < closestDist then
|
|
(
|
|
closestDist = dist
|
|
closestCentroid = c
|
|
)
|
|
)
|
|
|
|
_pointClusterList[p] = closestCentroid
|
|
)
|
|
|
|
return _pointClusterList
|
|
),
|
|
|
|
fn UpdateMean centroids items =
|
|
(
|
|
for c = 1 to centroids.count do
|
|
(
|
|
local centroid = centroids[c]
|
|
centroid = (centroid*(items.count-1)+items[i])/(n as float)
|
|
)
|
|
|
|
return mean
|
|
),
|
|
|
|
--points reference centroids
|
|
--find closest centroid
|
|
--find all points that reference one centroid
|
|
--update the centroid position to match the avg point pos
|
|
--loop until maxiterations or nothing to move
|
|
|
|
fn DistCompare v1 v2 =
|
|
(
|
|
case of
|
|
(
|
|
(v1.dist>v2.dist):1
|
|
(v1.dist<v2.dist):-1
|
|
default:0
|
|
)
|
|
),
|
|
|
|
fn KMeansConverge centroids points maxIterations:10 =
|
|
(
|
|
_pointClusterList = #()
|
|
_pointClusterList.count = points.count
|
|
|
|
--debug path points
|
|
for i=1 to centroids.count do
|
|
(
|
|
_pointClusterPaths[i] = #(centroids[i].centroid)
|
|
)
|
|
|
|
progressStart ("Ipl Grouping " + points[1].ContainerRef + "...")
|
|
for i=1 to maxIterations do
|
|
(
|
|
format "iteration: % \n" i as string
|
|
|
|
--process all points looking for the closest centroid
|
|
for p=1 to points.count do
|
|
(
|
|
local thisPoint = points[p].Pos
|
|
local closestCentroid = undefined
|
|
--local closestDist = 99999
|
|
local closestDistRank = #()
|
|
for c=1 to centroids.count do
|
|
(
|
|
local dist = (distance thisPoint centroids[c].centroid)
|
|
append closestDistRank (datapair cIndex:c dist:dist)
|
|
)
|
|
|
|
--sort distances
|
|
qsort closestDistRank DistCompare
|
|
|
|
--check closest
|
|
local validClosestFound = false
|
|
local closestIndex = 1
|
|
while not validClosestFound do
|
|
(
|
|
--has the closest got capacity?
|
|
local centroidCapacity = 0
|
|
for q=1 to _pointClusterList.count where (_pointClusterList[q] == closestDistRank[closestIndex].cIndex) do centroidCapacity += 1
|
|
if (centroidCapacity < _IPL_MAXITEMS) then
|
|
(
|
|
validClosestFound = true
|
|
closestCentroid = closestDistRank[closestIndex].cIndex
|
|
)
|
|
else
|
|
(
|
|
closestIndex += 1
|
|
)
|
|
)
|
|
|
|
|
|
if(closestCentroid != undefined) do
|
|
(
|
|
_pointClusterList[p] = closestCentroid
|
|
|
|
--update centroid(mean) location
|
|
--get its points
|
|
local avgPos = [0,0,0]
|
|
local positions = 0
|
|
for q=1 to _pointClusterList.count where (_pointClusterList[q] == closestCentroid) do
|
|
(
|
|
avgPos += points[q].Pos
|
|
positions += 1
|
|
)
|
|
avgPos /= positions
|
|
|
|
centroids[closestCentroid].centroid = avgPos
|
|
)
|
|
)
|
|
|
|
ProgressUpdate (100.0 * (i as float / maxIterations))
|
|
)
|
|
ProgressEnd()
|
|
|
|
--now assign the relevant ipl group id to each placement point instance
|
|
for p=1 to points.count do
|
|
(
|
|
points[p].IplGroup = _pointClusterList[p] - 1
|
|
)
|
|
|
|
return true
|
|
),
|
|
|
|
|
|
fn ExtractMeta =
|
|
(
|
|
gRsPerforce.Sync _metaPath
|
|
|
|
local xmlIO = rsta_xml_io()
|
|
xmlIO.xmlFile = metaPath
|
|
xmlIO.load()
|
|
|
|
local itemNodes = xmlIO.root.GetElementsByTagName "Item"
|
|
local itemsEnumerator = itemNodes.GetEnumerator()
|
|
|
|
while itemsEnumerator.MoveNext() do
|
|
(
|
|
local thisItem = itemsEnumerator.Current
|
|
|
|
local ipItem = IpInstance()
|
|
|
|
local modelNameElems = thisitem.GetElementsByTagName "ModelName"
|
|
|
|
if (modelNameElems.Count > 0) then
|
|
(
|
|
ipItem.ArchetypeName = (modelNameElems.Item 0).InnerText
|
|
)
|
|
|
|
local positionElem = thisItem.Item "Position"
|
|
if (positionElem != undefined) then
|
|
(
|
|
ipItem.Pos = [_islandPositionOffset.x + ((positionElem.GetAttribute "x") as Float),
|
|
_islandPositionOffset.y + ((positionElem.GetAttribute "y") as Float),
|
|
_islandPositionOffset.z + ((positionElem.GetAttribute "z") as Float)]
|
|
)
|
|
|
|
local rotationElem = thisItem.Item "Rotation"
|
|
if (rotationElem != undefined) then
|
|
(
|
|
ipItem.Rot = [((rotationElem.GetAttribute "x") as Float), ((rotationElem.GetAttribute "y") as Float), ((rotationElem.GetAttribute "z") as Float)]
|
|
)
|
|
|
|
local scaleElem = thisItem.Item "Scale"
|
|
if (scaleElem != undefined) then
|
|
(
|
|
ipItem.Scale = [((scaleElem.GetAttribute "x") as Float), ((scaleElem.GetAttribute "y") as Float), ((scaleElem.GetAttribute "z") as Float)]
|
|
)
|
|
|
|
append _ipInstances ipItem
|
|
)
|
|
),
|
|
|
|
fn GetContainerRefForInstances =
|
|
(
|
|
--set container ref
|
|
for ipItem in _ipInstances do
|
|
(
|
|
case of
|
|
(
|
|
((ipItem.Pos.x <= _medianPlacementPoint.x) and (ipItem.Pos.y <= _medianPlacementPoint.y)):
|
|
(
|
|
ipItem.ContainerRef = "sw_placement"
|
|
)
|
|
|
|
((ipItem.Pos.x <= _medianPlacementPoint.x) and (ipItem.Pos.y >= _medianPlacementPoint.y)):
|
|
(
|
|
ipItem.ContainerRef = "nw_placement"
|
|
)
|
|
|
|
((ipItem.Pos.x >= _medianPlacementPoint.x) and (ipItem.Pos.y >= _medianPlacementPoint.y)):
|
|
(
|
|
ipItem.ContainerRef = "ne_placement"
|
|
)
|
|
|
|
((ipItem.Pos.x >= _medianPlacementPoint.x) and (ipItem.Pos.y <= _medianPlacementPoint.y)):
|
|
(
|
|
ipItem.ContainerRef = "se_placement"
|
|
)
|
|
)
|
|
)
|
|
),
|
|
|
|
fn CreateRefsFromIpMeta =
|
|
(
|
|
gRsPerforce.Sync _metaPath
|
|
|
|
local xmlIO = rsta_xml_io()
|
|
xmlIO.xmlFile = _metaPath
|
|
xmlIO.load()
|
|
|
|
local itemNodes = xmlIO.root.GetElementsByTagName "Item"
|
|
local itemsEnumerator = itemNodes.GetEnumerator()
|
|
|
|
while itemsEnumerator.MoveNext() do
|
|
(
|
|
local thisItem = itemsEnumerator.Current
|
|
|
|
local ipItem = IpInstance()
|
|
|
|
local modelNameElems = thisitem.GetElementsByTagName "ModelName"
|
|
|
|
if (modelNameElems.Count > 0) then
|
|
(
|
|
ipItem.ArchetypeName = (modelNameElems.Item 0).InnerText
|
|
)
|
|
|
|
local positionElem = thisItem.Item "Position"
|
|
if (positionElem != undefined) then
|
|
(
|
|
ipItem.Pos = [_islandPositionOffset.x + ((positionElem.GetAttribute "x") as Float),
|
|
_islandPositionOffset.y + ((positionElem.GetAttribute "y") as Float),
|
|
_islandPositionOffset.z + ((positionElem.GetAttribute "z") as Float)]
|
|
)
|
|
|
|
--set container ref
|
|
case of
|
|
(
|
|
((ipItem.Pos.x <= _medianPlacementPoint.x) and (ipItem.Pos.y <= _medianPlacementPoint.y)):
|
|
(
|
|
ipItem.ContainerRef = "sw_placement"
|
|
)
|
|
|
|
((ipItem.Pos.x <= _medianPlacementPoint.x) and (ipItem.Pos.y >= _medianPlacementPoint.y)):
|
|
(
|
|
ipItem.ContainerRef = "nw_placement"
|
|
)
|
|
|
|
((ipItem.Pos.x >= _medianPlacementPoint.x) and (ipItem.Pos.y >= _medianPlacementPoint.y)):
|
|
(
|
|
ipItem.ContainerRef = "ne_placement"
|
|
)
|
|
|
|
((ipItem.Pos.x >= _medianPlacementPoint.x) and (ipItem.Pos.y <= _medianPlacementPoint.y)):
|
|
(
|
|
ipItem.ContainerRef = "se_placement"
|
|
)
|
|
)
|
|
|
|
local rotationElem = thisItem.Item "Rotation"
|
|
if (rotationElem != undefined) then
|
|
(
|
|
ipItem.Rot = [((rotationElem.GetAttribute "x") as Float), ((rotationElem.GetAttribute "y") as Float), ((rotationElem.GetAttribute "z") as Float)]
|
|
)
|
|
|
|
local scaleElem = thisItem.Item "Scale"
|
|
if (scaleElem != undefined) then
|
|
(
|
|
ipItem.Scale = [((scaleElem.GetAttribute "x") as Float), ((scaleElem.GetAttribute "y") as Float), ((scaleElem.GetAttribute "z") as Float)]
|
|
)
|
|
|
|
append _ipInstances ipItem
|
|
)
|
|
|
|
--now find which container instances belong to and set that property for each
|
|
GetContainerRefForInstances()
|
|
|
|
--Now get all the instances for each container and sort them into proximate ipl groups
|
|
|
|
--sw_placement
|
|
local sw_placementPoints = for item in _ipInstances where (item.ContainerRef == "sw_placement") collect item
|
|
KMeansConverge _swIplInitialCentroids sw_placementPoints
|
|
|
|
--nw_placement
|
|
local nw_placementPoints = for item in _ipInstances where (item.ContainerRef == "nw_placement") collect item
|
|
KMeansConverge _nwIplInitialCentroids nw_placementPoints
|
|
|
|
--ne_placement
|
|
local ne_placementPoints = for item in _ipInstances where (item.ContainerRef == "ne_placement") collect item
|
|
KMeansConverge _neIplInitialCentroids ne_placementPoints
|
|
|
|
--se_placement
|
|
local se_placementPoints = for item in _ipInstances where (item.ContainerRef == "se_placement") collect item
|
|
KMeansConverge _seIplInitialCentroids se_placementPoints
|
|
|
|
),
|
|
|
|
fn DebugPositionMesh objname positions:unsupplied =
|
|
(
|
|
local em = Plane name:objName widthSegs:1 lengthSegs:1
|
|
converttomesh em
|
|
|
|
if (positions == unsupplied) then
|
|
(
|
|
positions = for item in _ipInstances collect item.Pos
|
|
)
|
|
|
|
setmesh em vertices:positions faces:#()
|
|
|
|
update em
|
|
),
|
|
|
|
|
|
fn _SetNodeWorldRotation theNode theRot =
|
|
(
|
|
in coordsys (transmatrix theNode.transform.pos)
|
|
theNode.rotation = theRot
|
|
),
|
|
|
|
|
|
fn _RemoveContainerNodes contHelper nodes =
|
|
(
|
|
with undo off
|
|
(
|
|
for item in nodes do
|
|
(
|
|
contHelper.RemoveNodeFromContent item true
|
|
if (isValidNode item) do delete item
|
|
)
|
|
)
|
|
),
|
|
|
|
|
|
fn _ImportContainers =
|
|
(
|
|
--check if they are already loaded
|
|
|
|
if (_sw_placementCont == undefined) do
|
|
(
|
|
_sw_placementCont = (Containers.CreateInheritedContainer @"X:\gta5_dlc\mpPacks\mpHeist4\Art\ng\Models\mph4_Island\mph4_island_sw_placement.maxc")
|
|
_sw_placementCont.SetEditInPlace True
|
|
local nodes = #()
|
|
_sw_placementCont.GetContentNodes false &nodes
|
|
|
|
_RemoveContainerNodes _sw_placementCont nodes
|
|
)
|
|
|
|
if (_nw_placementCont == undefined) do
|
|
(
|
|
_nw_placementCont = (Containers.CreateInheritedContainer @"X:\gta5_dlc\mpPacks\mpHeist4\Art\ng\Models\mph4_Island\mph4_island_nw_placement.maxc")
|
|
_nw_placementCont.SetEditInPlace True
|
|
local nodes = #()
|
|
_nw_placementCont.GetContentNodes false &nodes
|
|
|
|
_RemoveContainerNodes _nw_placementCont nodes
|
|
)
|
|
|
|
if (_ne_placementCont == undefined) do
|
|
(
|
|
_ne_placementCont = (Containers.CreateInheritedContainer @"X:\gta5_dlc\mpPacks\mpHeist4\Art\ng\Models\mph4_Island\mph4_island_ne_placement.maxc")
|
|
_ne_placementCont.SetEditInPlace True
|
|
local nodes = #()
|
|
_ne_placementCont.GetContentNodes false &nodes
|
|
|
|
_RemoveContainerNodes _ne_placementCont nodes
|
|
)
|
|
|
|
if (_se_placementCont == undefined) do
|
|
(
|
|
_se_placementCont = (Containers.CreateInheritedContainer @"X:\gta5_dlc\mpPacks\mpHeist4\Art\ng\Models\mph4_Island\mph4_island_se_placement.maxc")
|
|
_se_placementCont.SetEditInPlace True
|
|
local nodes = #()
|
|
_se_placementCont.GetContentNodes false &nodes
|
|
|
|
_RemoveContainerNodes _se_placementCont nodes )
|
|
),
|
|
|
|
|
|
fn _GetContainerRef ipItem =
|
|
(
|
|
case ipItem.ContainerRef of
|
|
(
|
|
"sw_placement": return _sw_placementCont
|
|
"nw_placement": return _nw_placementCont
|
|
"ne_placement": return _ne_placementCont
|
|
"se_placement": return _se_placementCont
|
|
)
|
|
|
|
return undefined
|
|
),
|
|
|
|
|
|
fn CreateRsRefinstancesFromIpInstances =
|
|
(
|
|
RSrefAllowUpdate = false
|
|
|
|
_ImportContainers()
|
|
|
|
local swIplCount = 0
|
|
local swIplName = "h4_sw_ipl_" + (formattedPrint swIplCount format:"02i")
|
|
local nwIplCount = 0
|
|
local nwIplName = "h4_nw_ipl_" + (formattedPrint nwIplCount format:"02i")
|
|
local neIplCount = 0
|
|
local neIplName = "h4_ne_ipl_" + (formattedPrint neIplCount format:"02i")
|
|
local seIplCount = 0
|
|
local seIplName = "h4_se_ipl_" + (formattedPrint seIplCount format:"02i")
|
|
|
|
local sw_instanceCounter = 0
|
|
local nw_instanceCounter = 0
|
|
local ne_instanceCounter = 0
|
|
local se_instanceCounter = 0
|
|
|
|
with undo off
|
|
(
|
|
ProgressStart "Creating IP RsRefs..."
|
|
local progressCounter = 0.0
|
|
for ipItem in _ipInstances while (ProgressUpdate (100.0 * (progressCounter / _ipInstances.count))) do
|
|
(
|
|
local newRef = RsrefObject objectname:ipItem.ArchetypeName
|
|
|
|
newRef.pos = ipItem.Pos
|
|
_SetNodeWorldRotation newRef (eulerangles ipItem.Rot.x ipItem.Rot.y ipItem.Rot.z)
|
|
Scale newRef ipItem.Scale
|
|
|
|
--add to the relevant container based on its position
|
|
local containerRef = _GetContainerRef ipItem
|
|
containerRef.AddNodeToContent newRef
|
|
|
|
case containerRef.name of
|
|
(
|
|
"sw_placement":
|
|
(
|
|
swIplName = "h4_sw_ipl_" + (formattedPrint ipItem.IplGroup format:"02i")
|
|
|
|
setattr newRef _IPL_Attr swIplName
|
|
setattr newRef _NEWDLC_ATTR true
|
|
)
|
|
|
|
"nw_placement":
|
|
(
|
|
nwIplName = "h4_nw_ipl_" + (formattedPrint ipItem.IplGroup format:"02i")
|
|
|
|
setattr newRef _IPL_Attr nwIplName
|
|
setattr newRef _NEWDLC_ATTR true
|
|
)
|
|
|
|
"ne_placement":
|
|
(
|
|
neIplName = "h4_ne_ipl_" + (formattedPrint ipItem.IplGroup format:"02i")
|
|
|
|
setattr newRef _IPL_Attr neIplName
|
|
setattr newRef _NEWDLC_ATTR true
|
|
)
|
|
|
|
"se_placement":
|
|
(
|
|
seIplName = "h4_se_ipl_" + (formattedPrint ipItem.IplGroup format:"02i")
|
|
|
|
setattr newRef _IPL_Attr seIplName
|
|
setattr newRef _NEWDLC_ATTR true
|
|
)
|
|
)
|
|
|
|
progressCounter += 1.0
|
|
)
|
|
|
|
ProgressEnd()
|
|
)
|
|
),
|
|
|
|
fn Run =
|
|
(
|
|
this.CreateRefsFromIpMeta() -- this._metaPath
|
|
this.CreateRsRefinstancesFromIpInstances()
|
|
),
|
|
|
|
on create do
|
|
(
|
|
for item in _swIplInitialCentroids do
|
|
(
|
|
_iplGroupDefs.AddKey item.name item
|
|
)
|
|
for item in _nwIplInitialCentroids do
|
|
(
|
|
_iplGroupDefs.AddKey item.name item
|
|
)
|
|
for item in _seIplInitialCentroids do
|
|
(
|
|
_iplGroupDefs.AddKey item.name item
|
|
)
|
|
for item in _neIplInitialCentroids do
|
|
(
|
|
_iplGroupDefs.AddKey item.name item
|
|
)
|
|
)
|
|
)
|
|
|
|
-- global gIpProc = IpInstanceProcessor()
|
|
-- gIpProc.Run()
|
|
|
|
try(destroydialog RSTA_IPIPLToolUI)catch()
|
|
rollout RSTA_IPIPLToolUI "IP IPL Tool" width:300
|
|
(
|
|
local ipProc = IpInstanceProcessor()
|
|
local IPLSELECTIONMAX = 925
|
|
|
|
|
|
struct IplMeta
|
|
(
|
|
name, dist, pos, count
|
|
)
|
|
|
|
button btnCreateRefs "Create Refs from Meta" tooltip:"Create rsrefs from placement meta" width:280
|
|
button btnSelectionToIPL "Selection to closest IPL" tooltip:"Assign the items in the selection to the closest ipl group" width:280
|
|
|
|
dropdownlist ddlIPLNames "IPL Names" items:(ipProc._iplGroupDefs.keys())
|
|
button btnIplCounter "Item Count" tooltip:"Count the number of items in each ipl group" width:280
|
|
edittext edtIPLCount "Count:" readonly:true bold:true text:"-"
|
|
progressbar prgIPLCount "IPL Capacity"
|
|
button btnGetIPLFromSelection "Get IPL From Selected" tooltip:"Set the ipl group name from the first selected" width:280
|
|
button btnSelectIPLContents "Select IPL Items" tooltip:"Select Items for chosen IPL" width:280
|
|
button btnAssignSelToIPL "Assign selection to chosen IPL" width:280
|
|
|
|
fn UpdateIPLCounter iplname =
|
|
(
|
|
local iplCount = ipProc.IPLItemCount iplname
|
|
|
|
local idx = finditem ddlIPLNames.items iplname
|
|
ddlIPLNames.selection = idx
|
|
|
|
if (iplCount > 950) then
|
|
(
|
|
prgIPLCount.color = red
|
|
)
|
|
else
|
|
(
|
|
prgIPLCount.color = green
|
|
)
|
|
|
|
prgIPLCount.value = (100 * (iplCount / IPLSELECTIONMAX as float))
|
|
edtIPLCount.text = iplCount as string
|
|
)
|
|
|
|
on btnAssignSelToIPL pressed do
|
|
(
|
|
local items = GetCurrentSelection()
|
|
items = for item in items where (classof item == Rsrefobject) and ((ipProc.GetIPLName item) != ddlIPLNames.selected) collect item
|
|
if (items.count == 0) do
|
|
(
|
|
messagebox "Nothing valid selected" title:"Bad Selection"
|
|
return false
|
|
)
|
|
|
|
--Check we have capacity to assign this many items to this ipl group
|
|
local iplCount = ipProc.IPLItemCount ddlIPLNames.selected
|
|
if (items.count > (IPLSELECTIONMAX - iplCount)) then
|
|
(
|
|
messagebox "Adding this many items will bust the limit on the chosen IPL group" title:"OVERLOAD"
|
|
return false
|
|
)
|
|
|
|
undo label:("Assign Items to " + ddlIPLNames.selected) on
|
|
(
|
|
print "Assiging items to ipl"
|
|
for item in items do
|
|
(
|
|
SetAttr item ipProc._IPL_Attr ddlIPLNames.selected
|
|
)
|
|
)
|
|
|
|
UpdateIPLCounter ddlIPLNames.selected
|
|
)
|
|
|
|
on btnGetIPLFromSelection pressed do
|
|
(
|
|
if (classof selection[1] == RsrefObject) then
|
|
(
|
|
local iplname = ipProc.GetIPLName selection[1]
|
|
local idx = finditem ddlIPLNames.items iplname
|
|
if (idx == 0) then
|
|
(
|
|
messagebox ("Ipl name: " + iplname + " not found!") title:"Not Found"
|
|
return false
|
|
)
|
|
else
|
|
(
|
|
ddlIPLNames.selection = idx
|
|
)
|
|
)
|
|
else
|
|
(
|
|
messagebox "Pick an RsRef object please." title:"Bad Selection"
|
|
return false
|
|
)
|
|
)
|
|
|
|
on btnSelectIPLContents pressed do
|
|
(
|
|
ipProc.SelectIPLContent ddlIPLNames.selected
|
|
)
|
|
|
|
on btnIplCounter pressed do
|
|
(
|
|
UpdateIPLCounter ddlIPLNames.selected
|
|
)
|
|
|
|
on btnCreateRefs pressed do
|
|
(
|
|
ipProc.Run()
|
|
)
|
|
|
|
on btnSelectionToIPL pressed do
|
|
(
|
|
--get ipl counts
|
|
local iplGroups = Dictionary()
|
|
for item in objects where (classof item == RSrefObject) do
|
|
(
|
|
local iplGroup = getAttr item ipProc._IPL_Attr
|
|
|
|
if (iplGroup != undefined) or (iplGroup != "undefined") then
|
|
(
|
|
if (not iplGroups.hasKey iplGroup) then
|
|
(
|
|
iplGroups.addKey iplGroup #(item)
|
|
)
|
|
else
|
|
(
|
|
local currentItems = iplGroups.getValue iplGroup
|
|
append currentItems item
|
|
iplGroups.setValue iplGroup currentItems
|
|
)
|
|
)
|
|
)
|
|
|
|
--get ipl groups centres
|
|
local iplCenters = Dictionary()
|
|
for key in iplGroups.keys() do
|
|
(
|
|
--get the values and find the avg center from the contents positions
|
|
local items = iplGroups.getValue key
|
|
local commonCenter = [0,0,0]
|
|
for obj in items do
|
|
(
|
|
commonCenter += obj.pos
|
|
)
|
|
commonCenter /= items.count
|
|
|
|
iplCenters.addKey key (iplMeta name:key pos:commonCenter count:items.count)
|
|
)
|
|
|
|
for key in iplCenters.keys() do print (iplCenters.getValue key)
|
|
|
|
--find the closest ipl group that has capacity to take another
|
|
for item in (GetCurrentSelection()) where (classof item == RsrefObject) do
|
|
(
|
|
local closestIplRank = #()
|
|
|
|
for key in iplCenters.keys() do
|
|
(
|
|
local iplData = iplCenters.getValue key
|
|
local dist = distance item.pos iplData.pos
|
|
|
|
--find the array index that is closer than this closest distance
|
|
append closestIplRank (DataPair dist:dist data:iplData)
|
|
)
|
|
|
|
--sort them by distance
|
|
qsort closestIplRank ipProc.DistCompare
|
|
|
|
local iplWithRoom = false
|
|
local iplGroupName = undefined
|
|
for ipl in closestIplRank while not iplWithRoom do
|
|
(
|
|
if (ipl.data.count < IPLSELECTIONMAX) and (ipl.data.name != "undefined") then
|
|
(
|
|
iplGroupName = ipl.data.name
|
|
ipl.data.count += 1
|
|
iplWithRoom = true
|
|
)
|
|
)
|
|
|
|
if (iplGroupName != undefined) then
|
|
(
|
|
format "iplGroupName: %\n" iplGroupName
|
|
setAttr item ipProc._IPL_Attr iplGroupName
|
|
)
|
|
else
|
|
(
|
|
print "no iplGroupName to assign"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
createDialog RSTA_IPIPLToolUI
|
|
|
|
/*
|
|
if FALSE do
|
|
(
|
|
nwPos = for item in gIpProc._ipInstances where item.ContainerRef == "nw_placement" collect item.pos
|
|
nw_clusters = gIpProc.ClusterPointAroundIPLGroups gIpProc._nwIplInitialCentroids nwPos
|
|
--for key in nw_Clusters.keys() do gIpProc.DebugPositionMesh key positions:(nw_Clusters.getValue key)
|
|
|
|
success = gIpProc.KMeansConverge gIpProc._nwIplInitialCentroids nwPos
|
|
for i=1 to 10 do
|
|
(
|
|
local iplPos = for idx=1 to gIpProc._pointClusterList.count where gIpProc._pointClusterList[idx]==i collect nwPos[idx]
|
|
gIpProc.DebugPositionMesh ("ipl_" + i as string) positions:iplPos
|
|
)
|
|
|
|
for item in $selection do centerpivot item
|
|
|
|
|
|
|
|
nwmesh = Plane name:"nw" widthSegs:1 lengthSegs:1
|
|
converttomesh nwmesh
|
|
setmesh nwmesh vertices:nwPos faces:#()
|
|
update nwmesh
|
|
select nwmesh
|
|
|
|
|
|
|
|
ipls = #()
|
|
for i=1 to 10 do
|
|
(
|
|
ipls[i] = for x=1 to gIpProc._pointClusterList.count where gIpProc._pointClusterList[x] == i collect nwPos[x]
|
|
)
|
|
|
|
for i=1 to ipls.count do print ipls[i].count
|
|
|
|
|
|
for item in gIpProc._nwIplInitialCentroids do Point name:item.name pos:item.centroid color:red
|
|
|
|
|
|
--spline paths for cluster centres
|
|
for i=1 to gIpProc._pointClusterPaths.count do
|
|
(
|
|
local new_spline = splineShape name:("PointCluster_" + i as string)
|
|
|
|
select new_spline
|
|
addNewSpline new_spline
|
|
|
|
for p =1 to gIpProc._pointClusterPaths[i].count do
|
|
(
|
|
addKnot new_spline 1 #corner #line gIpProc._pointClusterPaths[i][p]
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
)*/ |