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

996 lines
27 KiB
Plaintext
Executable File

filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms")
struct proceduralMapperStruct
(
tileSize,
worldMapSize = [9150, 12450],
worldBottomCorner = [-4000, -4950],
worldOffset = [4000, 4950],
tileSize = 50.0,
tileCount = [(worldMapSize.x / tileSize), (worldMapSize.y / tileSize)],
maxTileIdx = (worldMapSize.x / tileSize) as Integer,
maxTileIdy = (worldMapSize.y / tileSize) as Integer,
containerPositions = #(),
containerBounds,
windowsTEMPDir = systemTools.getEnvVariable "TEMP",
mapTileArchivePath = (RsConfigGetAssetsDir() + "reports/heightmap/images_4_5/materialmasks.zip"),
extractPath = windowsTEMPDir + "/ProcMasks",
maskPaths = extractPath + "/materialmasks/",
tempMaskPath = windowsTEMPDir + "/TempMaterialMasks/",
tempProcPaintPath = windowsTEMPDir + "/ProcPaint/",
procPaintPath = (RsConfigGetAssetsDir() + "maps/procPaint/"),
borderDist = 4, --border tiles around a bounds selection
cellBounds,
containerTiles,
--tileRect,
UIEditLayers = #(),
UIMaskLayers = #(),
editLayers = #((tempProcPaintPath + "Procedural Sets")),
maskLayers = #(),
editTypes = #("Procedural_Sets"),
procMaskImages = #(),
collProcMaskImages = #(),
maskTypes = #(),
editProcessList = #("ProceduralSetMap"),
maskProcessList = #(),
procedural_meta = (RsConfigGetCommonDir() + "data/materials/procedural.meta"),
procedural_metaTypes = #(),
containerProcTypes = #(),
rolloutUI = undefined,
--/////////////////////////////////////////
-- Send a message to the status UI
--/////////////////////////////////////////
fn updateUIStatus msg =
(
if rolloutUI != undefined then
(
rolloutUI.edtStatus.text = msg
)
),
--/////////////////////////////////////////
-- Set progress bar status UI
--/////////////////////////////////////////
fn setProgress val =
(
if rolloutUI != undefined then
(
rolloutUI.prgBar.value = val
)
),
--/////////////////////////////////////////
-- Set the options for saving png images in the application
--/////////////////////////////////////////
fn setPNGOpts type =
(
case type of
(
#editLayer:portable_network_graphics.setType #true24
#maskLayer:portable_network_graphics.setType #true24
)
portable_network_graphics.setAlpha false
portable_network_graphics.setInterlaced false
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getTileByPos pos =
(
local offsetX = worldOffset.x + pos.x
if offsetX > worldMapSize.x then format "Out of map bounds X: %\n" offsetX
local offsetY = worldOffset.y + pos.y
if offsetY > worldMapSize.y then format "Out of map bounds Y: %\n" offsetY
local x = (offsetX - (mod offsetX tileSize)) / tileSize
local y = (offsetY - (mod offsetY tileSize)) / tileSize
format "tile from pos:% \n" [x, y]
return [x, y]
),
--/////////////////////////////////////////
--tile is a Point2
--dir is a Point2
--/////////////////////////////////////////
fn getTileByAdjacency tile dir =
(
[(tile.x + dir.x), (tile.y + dir.y)]
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getBorderTiles tile border =
(
tileBorder = #()
for x = -border to border do
(
for y = -border to border do
(
local newX = tile.x + x
local newY = tile.y + y
if (x != 0 or y != 0) and (newX > -1 and newX < maxTileIdx and newY > -1 and newY < maxTileIdy) then
(
append tileBorder [newX, newY]
)
)
)
--return
tileBorder
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn tileBounds tileArray =
(
bounds = undefined
local xRange = for item in tileArray collect item.x
local yRange = for item in tileArray collect item.y
local minX = amin xRange as Integer
local maxX = amax xRange as Integer
local minY = amin yRange as Integer
local maxY = amax yRange as Integer
--return
bounds = #([minX, minY], [maxX, maxY])
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getTilesByBounds =
(
if containerBounds == undefined then return false
--using the bounds find all the tiles it covers and return a tileRect
local minBoundsTile = getTileByPos containerBounds[1]
local maxBoundsTile = getTileByPos containerBounds[2]
containerTiles = tileBounds #(minBoundsTile, maxBoundsTile)
--expand the selection to all the tiles within the bounds
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn expandBounds minBB maxBB currentBounds =
(
local minBounds = currentBounds[1]
local maxBounds = currentBounds[2]
if ( minBB.x < minBounds.x ) then
(
minBounds.x = minBB.x
)
if ( minBB.y < minBounds.y ) then
(
minBounds.y = minBB.y
)
if ( maxBB.x > maxBounds.x ) then
(
maxBounds.x = maxBB.x
)
if ( maxBB.y > maxBounds.y ) then
(
maxBounds.y = maxBB.y
)
#(minBounds, maxBounds)
),
--/////////////////////////////////////////
-- For all the containers in the scene determine the bounds that cover all
--/////////////////////////////////////////
fn getAggregateContainerBounds =
(
local conts = RsMapGetMapContainers()
if conts.count == 0 then
(
messagebox "No containers loaded to work with." title:"ERROR"
return false
)
containerBounds = nodeGetBoundingBox conts[1].cont (matrix3 1)
for c in conts do
(
local thisContainer = c.cont
local bounds = nodeGetBoundingBox thisContainer (matrix3 1)
containerBounds = expandBounds bounds[1] bounds[2] containerBounds
)
),
--/////////////////////////////////////////
-- Check the bounds do not go out of range and trim them if they do
--/////////////////////////////////////////
fn checkTileBounds =
(
local minBounds = containerTiles[1]
local maxBounds = containerTiles[2]
--check and trim bounds
--min
if minBounds.x < 0 then containerTiles[1].x = 0
if minBounds.x > tileCount.x then containerTiles[1].x = tileCount.x
if minBounds.y < 0 then containerTiles[1].y = 0
if minBounds.y > tileCount.y then containerTiles[1].y = tileCount.y
--max
if maxBounds.x < 0 then containerTiles[2].x = 0
if maxBounds.x > tileCount.x then containerTiles[2].x = tileCount.x
if maxBounds.y < 0 then containerTiles[2].y = 0
if maxBounds.y > tileCount.y then containerTiles[2].y = tileCount.y
--check min < max
if containerTiles[2].x < containerTiles[1].x then containerTiles[2].x = containerTiles[1].x + 1
if containerTiles[2].y < containerTiles[1].y then containerTiles[2].y = containerTiles[1].y + 1
--check for degenerate bounds
if containerTiles[1].x == containerTiles[2].x then containerTiles[2].x += 1
if containerTiles[1].y == containerTiles[2].y then containerTiles[2].y += 1
ok
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getContainerPositions =
(
local conts = RsMapGetMapContainers()
containerPositions = for item in conts collect item.cont.pos
if containerPositions.count == 0 then containerPositions = #([0,0,0])
),
--/////////////////////////////////////////
-- get the tile maps surrounfing a given tile and merge the images into
-- one combined map for editing
--/////////////////////////////////////////
fn combineTileMaps tile =
(
local cellTiles = getBorderTiles tile borderDist
),
--/////////////////////////////////////////
-- Extract the materialmask archive
--/////////////////////////////////////////
fn extractMaskMaps =
(
--Clean the old ones out first
for filename in (getFiles (extractPath + "*.png")) do deleteFile filename
--check for newest version
local fstat = ( gRsPerforce.getFileStats mapTileArchivePath )[ 1 ]
local haveRev = fstat.Item[ "haveRev" ]
local headRev = fstat.Item[ "headRev" ]
local doUpDateMasks = false
if (haveRev == undefined) or ((haveRev as Integer) < (headRev as Integer)) then
(
print "Syncing to head revision"
gRsPerforce.sync mapTileArchivePath
doUpDateMasks = true
)
--check we have the archive
if (doesFileExist mapTileArchivePath ) or doUpDateMasks then
(
--extract to the temp dir
if (getDirectories extractPath).count == 0 then makeDir (RsMakeSafeSlashes(extractPath))
zipFile = (dotNetClass "Ionic.Zip.ZipFile").Read mapTileArchivePath
zipFile.TempFileFolder = extractPath
zipFile.ExtractSelectedEntries "name = *.png" "materialmasks" extractPath (dotNetClass "Ionic.Zip.ExtractExistingFileAction").OverwriteSilently
--zipFile.ExtractAll extractPath (dotNetClass "Ionic.Zip.ExtractExistingFileAction").OverwriteSilently
--clean
zipFile.dispose()
)
OK
),
--/////////////////////////////////////////
-- using a tile index with bottom left being 0,0
-- return the top left corner in bitmap coords
-- bmSize is the size of the bitmap - [x, y]
-- tileSize is the size of a tile in pixels
-- tile is the tile index of interest
-- return a Point2 coord [x, y]
--/////////////////////////////////////////
fn getTileBitmapOrigin bmSize tileSize tileRect =
(
local pixelTileSize = bmSize / tileCount
--tileRect is #([x,y], [x,y])
local imageX = tileRect[1].x * pixelTileSize.x
local imageY = tileRect[1].y * pixelTileSize.y
--return
format "image xy:% \n" [imageX, imageY]
return [imageX, imageY]
),
--/////////////////////////////////////////
-- get the size in pixels of the tile Rectangle
-- unsing the supplied bitmap dimensions
--/////////////////////////////////////////
fn getTileBitmapDimensions bmSize tileRect =
(
local pixelTileSize = bmSize / tileCount
(pixelTileSize * [(tileRect[2].x - tileRect[1].x), (tileRect[2].y - tileRect[1].y)])
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getTileFilePath tile =
(
local tilePath = extractPath + "materialmasks/"
),
--/////////////////////////////////////////
-- extract a section from an image
-- and paste it into a new bitmap object to be returned
--/////////////////////////////////////////
fn copyBitmapRegion imagePath tileRect =
(
if (not (doesFileExist imagePath)) then return undefined
local sourceBMP = openBitmap imagePath
local tilePixelsOrigin = getTileBitmapOrigin [sourceBMP.Width, sourceBMP.Height] tileSize tileRect
local tilePixelsDim = getTileBitmapDimensions [sourceBMP.Width, sourceBMP.Height] tileRect
local compBm = bitmap tilePixelsDim.x tilePixelsDim.y color:black
pasteBitmap sourceBMP compBm (box2 tilePixelsOrigin.x tilePixelsOrigin.y tilePixelsDim.x tilePixelsDim.y) [0, 0]
close sourceBMP
free sourceBMP
--debug
--display compBm
--return
compBm
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn prepareMap type bmpName =
(
case type of
(
#editLayer:
(
local topLeftTileName = "_" + (containerTiles[1].x as Integer) as String + "_" + (containerTiles[1].y as Integer) as String
local bmpPath = procPaintPath + bmpName + ".png"
if (not (doesFileExist bmpPath)) then --try to sync it
(
gRsPerforce.sync #(bmpPath)
)
if (not (doesFileExist bmpPath)) then --missing
(
messageBox ("Cant find file:" + bmpPath) title:"Missing File"
return false
)
local regionBmp = copyBitmapRegion bmpPath containerTiles
local outPath = tempProcPaintPath + bmpName + topLeftTileName + ".png"
regionBmp.filename = outPath
setPNGOpts #editLayer
save regionBmp
free regionBmp
append editLayers outPath
)
#maskLayer:
(
local bmpPath = maskPaths + bmpName + ".png"
local regionBmp = copyBitmapRegion bmpPath containerTiles
local outPath = tempProcPaintPath + bmpName + ".png"
regionBmp.filename = outPath
setPNGOpts #maskLayer
save regionBmp
free regionBmp
append maskLayers outPath
)
)
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn constructMaps =
(
updateUIStatus "Constructing working images"
--check dirs exist, create if need be
for dir in #(extractPath, maskPaths, tempMaskPath, tempProcPaintPath) where (not (doesFileExist dir)) do
(
makeDir dir
)
--check if file exists already, prompt for update
for filename in (getFiles (tempProcPaintPath + "*.png")) do deleteFile filename
--process maps
updateUIStatus "Processing masks..."
setProgress 0
local prgMax = maskProcessList.count
for i=1 to maskProcessList.count do
(
local thisItem = maskProcessList[i]
local bmpName = getFilenameFile thisItem
prepareMap #maskLayer bmpName
setProgress (100.0 * ( i as float / prgMax))
)
setProgress 0
updateUIStatus "Processing edit maps..."
prgMax = editProcessList.count
for i=1 to editProcessList.count do
(
local thisItem = editProcessList[i]
local bmpName = getFilenameFile thisItem
prepareMap #editLayer bmpName
setProgress (100.0 * ( i as float / prgMax))
)
setProgress 0
updateUIStatus "."
),
--/////////////////////////////////////////
-- Find all the extracted mask images
--/////////////////////////////////////////
fn discoverProceduralMaskImages =
(
local files = getFiles (maskPaths + "*.png")
if files.count == 0 then return false
-- 'ALL_' type procedural images
procMaskImages = getFiles (maskPaths + "ALL_*.png")
-- collision/procedural combinations
collProcMaskImages = for name in files where (MatchPattern (getFilenameFile name) pattern:"ALL_*") == false collect name
OK
),
--/////////////////////////////////////////
--Break up the collProcMaskImages list into lists by category
--/////////////////////////////////////////
fn categoriseMasks =
(
----------------------------------
-- procMaskImages
----------------------------------
if procMaskImages.count != 0 then
(
--determine types
local scratchMaskTypes = #()
for item in procMaskImages do
(
local nameBits = filterString (getFileNameFile item) "_"
if nameBits.count > 0 then appendIfUnique scratchMaskTypes nameBits[1]
)
--now create lists of mask images under these types
for type in scratchMaskTypes do
(
local maskList = for item in procMaskImages where MatchPattern (getFilenameFile item) pattern:(type + "*") collect item
append maskTypes (DataPair type:type masks:maskList)
)
)
----------------------------------
-- collProcMaskImages
----------------------------------
if collProcMaskImages.count != 0 then
(
--determine types
local scratchMaskTypes = #()
for item in collProcMaskImages do
(
local nameBits = filterString (getFileNameFile item) "_"
if nameBits.count > 0 then appendIfUnique scratchMaskTypes nameBits[1]
)
--now create lists of mask images under these types
for type in scratchMaskTypes do
(
local maskList = for item in collProcMaskImages where MatchPattern (getFilenameFile item) pattern:(type + "*") collect item
append maskTypes (DataPair type:type masks:maskList)
)
)
OK
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn processScene =
(
--get the containers positions
--getContainerPositions()
--get the containers bounds
getAggregateContainerBounds()
--find the tiles
--containerTiles = for cPos in containerPositions collect (getTileByPos cPos)
getTilesByBounds()
--grow the border
local minBorder = [(containerTiles[1].x - borderDist), (containerTiles[1].y - borderDist)]
local maxBorder = [(containerTiles[2].x + borderDist), (containerTiles[2].y + borderDist)]
containerTiles = expandBounds minBorder maxBorder containerTiles
--trim the bounds if they go out of range
checkTileBounds()
--get the bounds of the tiles to make a rectangular area
--tileRect = tileBounds containerTiles
format "containerBounds: % \n" containerBounds
--extract the map archive to build the composite image from
print "extractMaskMaps"
discoverProceduralMaskImages()
--extractMaskMaps()
--build a composite image for each mask and the edit layer
print "ConstructMaps"
constructMaps()
--send to photoshop for editing
),
--//////////////////////////////////////////////////////////////////////
-- Get all the types defined in procedural.meta
--//////////////////////////////////////////////////////////////////////
fn parseProcedural_meta =
(
local xmlDoc = XmlDocument()
xmlDoc.load procedural_meta
local procTags = xmlDoc.document.selectNodes "./CProceduralInfo/procObjInfos/Item/Tag"
procedural_metaTypes = #()
for i=0 to (procTags.count - 1) do
(
appendIfUnique procedural_metaTypes procTags.itemOf[i].InnerText
)
sort procedural_metaTypes
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn discoverProcedural_metaTypes =
(
for item in collProcMaskImages do
(
stringBits = filterString (getFilenameFile item) "[*]"
if (stringBits[2] != undefined) then
(
appendIfUnique procedural_metaTypes stringBits[2]
)
)
sort procedural_metaTypes
),
--/////////////////////////////////////////
-- Analyse all the collision meshes
-- in the scene and collect all the proctypes from the assigned materials
-- Then tag the tree mask items that match against those.
--/////////////////////////////////////////
fn collectSceneProcTypes =
(
for obj in objects where (isKindOf obj col_mesh) do
(
--get the applied material IDs
--copyMesh = copy obj
local objMesh = getColMesh obj
local materialIDs = for face in objMesh.faces collect (getFaceMatID objMesh face.index)
materialIDs = sort(makeUniqueArray materialIDs)
for id in materialIDs do
(
local procType = RexGetProceduralName obj.material.materialList[id]
if procType != "" then
(
append containerProcTypes procType
)
)
--clean up
--delete copyMesh
--delete objMesh
)
containerProcTypes = makeUniqueArray containerProcTypes
),
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on create do
(
--discover if we have the latest materialmasks zip
extractMaskMaps()
discoverProceduralMaskImages()
categoriseMasks()
discoverProcedural_metaTypes()
collectSceneProcTypes()
--parseProcedural_meta()
)
)
--/////////////////////////////////////////
-- UI
--/////////////////////////////////////////
rollout InitMessageUI "Initialising.." width:200 height:60
(
label lblInitMsg "Initialising Procedural Mapper" align:#left
label lblWait "Please Wait..." align:#left
)
createDialog InitMessageUI
try(destroyDialog ProceduralMapperUI)catch()
rollout ProceduralMapperUI "Procedural Mapper" width:400 height:725
(
--/////////////////////////////////////////
-- VARIABLES
--/////////////////////////////////////////
local procMapper = proceduralMapperStruct()
local nodeActionList = #()
--/////////////////////////////////////////
-- CONTROLS
--/////////////////////////////////////////
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:400
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"ProceduralMapper" filename:(getThisScriptFilename())
dropdownlist ddlProcTypes items:procMapper.procedural_metaTypes width:(ProceduralMapperUI.width - 110) across:2
button btnSelectMasks "Select Masks" align:#right
dotNetControl dnTreeView "System.Windows.Forms.TreeView" width:(ProceduralMapperUI.width - 25) height:(ProceduralMapperUI.height - 145)
button btnEditMaps "Edit Maps" width:(ProceduralMapperUI.width - 25)
progressBar prgBar
editText edtStatus text:"Status" enabled:false
--/////////////////////////////////////////
-- FUNCTIONS
--/////////////////////////////////////////
--/////////////////////////////////////////
-- Populates the tree control with content
--/////////////////////////////////////////
fn buildTree =
(
--editLayers
editLayersNode = dnTreeView.nodes.Add "Edit Layers"
editLayersNode.checked = true
--add the child nodes
for item in procMapper.editTypes do
(
local newNode = editLayersNode.nodes.add item
newNode.tag = item
newNode.checked = true
)
--maskLayers
maskLayersNode = dnTreeView.nodes.Add "Mask Layers"
maskLayersNode.expand()
--add the child nodes
--first by category
local maskTypeNodes = #()
for item in procMapper.maskTypes do
(
append maskTypeNodes (maskLayersNode.nodes.add item.type)
)
--then the children for each category
for i = 1 to maskTypeNodes.count do
(
for childMask in procMapper.maskTypes[i].masks do
(
local aNode = maskTypeNodes[i].nodes.add (getFileNameFile childMask)
aNode.tag = childMask
--tick it on if it matches to a proctype in the scene
local childMaskProcType = FilterString childMask "[]"
if childMaskProcType.count > 1 then
(
if (findItem procMapper.containerProcTypes childMaskProcType[2]) != 0 then
(
aNode.checked = true
local root = false
local parentNode = aNode.parent
while (parentNode != undefined) do
(
parentNode.Expand()
parentNode = parentNode.parent
)
)
)
)
)
)
--/////////////////////////////////////////
-- setup the dotnet UI
--/////////////////////////////////////////
fn init =
(
procMapper.rolloutUI = ProceduralMapperUI
dnTreeView.CheckBoxes = true
buildTree()
)
--/////////////////////////////////////////
-- Traverse up the tree to the root
--/////////////////////////////////////////
fn findRoot node =
(
if node.parent != undefined then
(
findRoot node.parent
)
else
(
return node
)
)
--/////////////////////////////////////////
-- update the nodeActionList
-- when a node is check or not
--/////////////////////////////////////////
fn updateMaskProcessList item state =
(
--add checked nodes to the list for processing
local treeRoot = findRoot item
if treeRoot.text == "Mask Layers" then
(
if state == true then
(
appendIfUnique procMapper.maskProcessList item.tag
)
else --remove them
(
--print "remove"
local id = findItem procMapper.maskProcessList item.tag
if id != 0 then deleteItem procMapper.maskProcessList id
)
)
)
--/////////////////////////////////////////
-- Get the root mask treeview nodes list
--/////////////////////////////////////////
fn getMaskLayerRootNodes =
(
local maskLayersNodeChildren = #()
local maskLayersNode = for t=0 to (dnTreeView.nodes.count - 1) \
where (MatchPattern dnTreeView.nodes.item[t].text pattern:"Mask Layers" ) \
collect dnTreeView.nodes.item[t]
if maskLayersNode.count != 0 then
(
maskLayersNodeChildren = for t=0 to (maskLayersNode[1].nodes.count - 1) collect maskLayersNode[1].nodes.item[t]
)
--retval
maskLayersNodeChildren
)
--//////////////////////////////////////////////////////////////////////////////////////
--switch all treeNode child nodes to checkbox state
--//////////////////////////////////////////////////////////////////////////////////////
fn checkTreeNodeChildren treeNodes state =
(
for thisNode in treeNodes do
(
--thisNode = treeNodes.item[n]
thisNode.checked = state
--add checked nodes to the list for processing
updateMaskProcessList thisNode state
--recurse?
if thisNode.nodes.count > 0 then
(
newNodes = for t=0 to (thisNode.nodes.count - 1) collect thisNode.nodes.item[t]
checkTreeNodeChildren newNodes state
)
)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn findMatchingNode maskName treeNodes &nodes =
(
local found = False
for thisNode in treeNodes while not found do
(
--format "node: % mask: % \n" (tolower thisNode.text) (tolower maskName)
if (tolower thisNode.text) == (tolower maskName) then
(
found = True
append nodes thisNode
)
--recurse?
if thisNode.nodes.count > 0 then
(
newNodes = for t=0 to (thisNode.nodes.count - 1) collect thisNode.nodes.item[t]
findMatchingNode maskName newNodes &nodes
)
)
)
--/////////////////////////////////////////
-- Search for nodes matching names and Switch
--/////////////////////////////////////////
fn checkMatchingNodes namesList =
(
for maskName in namesList do
(
local nodes = #()
findMatchingNode (getFilenameFile maskName) (getMaskLayerRootNodes()) &nodes
--print nodes
--set node to checked
if nodes != undefined then
(
for node in nodes do node.checked = True
)
)
)
--/////////////////////////////////////////
-- EVENTS
--/////////////////////////////////////////
--/////////////////////////////////////////
-- Select any mask items in the list
-- matching the currently selected Procedural from the dropdown
--/////////////////////////////////////////
on btnSelectMasks pressed do
(
local procFromList = tolower ddlProcTypes.selected
--local masksArray = for item in procMapper.maskTypes collect item.masks
local matchingMasks = #()
for item in procMapper.collProcMaskImages do
(
if MatchPattern (getFilenameFile item) pattern:("*["+procFromList+"]*") ignoreCase:true then append matchingMasks item
)
if matchingMasks.count != 0 then
(
--clear any checked selection first
checkTreeNodeChildren (for t=0 to (dnTreeView.nodes.count - 1) collect dnTreeView.nodes.item[t]) False
--take the matches and set the tree nodes
checkMatchingNodes matchingMasks
)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on dnTreeView AfterCheck sender ev do
(
--print "check"
--print ev
--print sender
if ev.node.nodes.count > 0 then
(
childNodes = for n=0 to (ev.node.nodes.count - 1) collect ev.node.nodes.item[n]
checkTreeNodeChildren childNodes ev.node.checked
)
if ev.node.nodes.count == 0 then
(
updateMaskProcessList ev.node ev.node.checked
)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on btnEditMaps pressed do
(
--From the checked tree nodes build a list of mask maps to process for working with
--Now process them
procMapper.processScene()
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on ProceduralMapperUI open do
(
banner.setup()
init()
try(DestroyDialog InitMessageUI)catch()
)
)
createDialog ProceduralMapperUI