SME: Slating the right Nodes

Whilst working on my next tool I hit a rather large stumbling block. Getting the selected nodes in the Slate Material Editor only passes you string names.  The Problem with the SME and 3dsmax in general is that maps/materials can share the same names, and to get the selected materials from the SME we need to reference by name… this can easily cause problems with complex material sub-trees where sub-maps and sub-mats have the same name, or you have two material trees in your SME view which have the same named (but different) materials in their graphs.

Below is a function which does a dirty work-around of this by temporarily giving every map a unique name, then collecting the selection of mats/maps values from the SME, then renaming back to original names. Our collection will still be valid as we’ve now got a pointer to materials not string names.

fn getSelectedFromSME =
(
–Get all the node names in SME
smeNames = (for i = 1 to (sme.getView (sme.activeView)).GetNumNodes() collect ((sme.getView (sme.activeView)).getNode i).name)

–let’s see if we have clashing material/map names in the SME before we bother doing dirty tricks
if (makeUniqueArray smeNames).count == smeNames.count then
(
–If no clashes we can use the standard method for getting the selected nodes by looking at the trackview and finding the name
selNodes = (sme.GetView (sme.activeView)).getselectednodes()
selectedNodesNames = for o in selNodes collect o.name

selectedMaps = #()
for i = 1 to trackViewNodes[#sme][sme.activeView].numSubs do
(
if (superclassof trackViewNodes[#sme][sme.activeView][i].reference == textureMap or superclassof trackViewNodes[#sme][sme.activeView][i].reference == material) and finditem selectedNodesNames trackViewNodes[#sme][sme.activeView][i].reference.name != 0 do
append selectedMaps trackViewNodes[#sme][sme.activeView][i].reference
)

selectedMaps
)
else
(
–if not, we need to work out which are nodes which have the same name, create a list of these
allItems = makeUniqueArray smeNames
for i = 1 to allItems.count do (deleteitem smeNames (finditem smeNames allItems[i]))
clashNames = (makeUniquearray (smeNames))

–we’ll use this array to keep a record of which we changed
changeID = #()

–loop through all the nodes in the SME
for i = 1 to trackViewNodes[#sme][sme.activeView].numSubs do
(
–if we find one which has a clashing name…..
if (finditem clashNames trackViewNodes[#sme][sme.activeView][i].reference.name) != 0 do
(
–add it to our change ID with the index and original name
append changeID (datapair v1:i v2:trackViewNodes[#sme][sme.activeView][i].reference.name)

–set the name to a unique name using what will hopefully be a safe name
trackViewNodes[#sme][sme.activeView][i].reference.name += (“_________________________________” + i as string)

)
)

–Now we can get the selected names and all names will be unique
selNodes = (sme.GetView (sme.activeView)).getselectednodes()
selectedNodesNames = for o in selNodes collect o.name

selectedMaps = #()

–now we loop through the trackView SME nodes and find the references using the names (as all names are now unique)
for i = 1 to trackViewNodes[#sme][sme.activeView].numSubs do
(
if (superclassof trackViewNodes[#sme][sme.activeView][i].reference == textureMap or superclassof trackViewNodes[#sme][sme.activeView][i].reference == material) and finditem selectedNodesNames trackViewNodes[#sme][sme.activeView][i].reference.name != 0 do
append selectedMaps trackViewNodes[#sme][sme.activeView][i].reference
)
–this returns an array of maps/materials values – at this point the names have been modified but now we have a pointer to the map/mat it doesn’t matter any more
selectedMaps

–now we loop through our change ID and change them back to original (clashing) names so the user won’t freak out
for o in changeID do
trackViewNodes[#sme][sme.activeView][o.v1].reference.name = o.v2

–Our array of materials/maps values have the original names but we’ll have the correct mat/map values in our array.
selectedMaps
)
)
getSelectedFromSME()

About davewortley

Somewhere between an artist and a programmer, I like technical things, but being creative. I love problem solving and coming up with elaborate solutions. This blog is where I shall share ideas, tips, tutorials and anything that amuses me.
This entry was posted in 3dsmax, MaxScript. Bookmark the permalink.

Leave a comment