A minor headache, thought this was worth a share…
https://davewortley.wordpress.com/2017/11/15/sme-slating-the-right-nodes/
(code looks better here than on my blog)
fn getSelectedFromSME =
(
--The Problem with the SME and 3dsmax in general is that maps/materials can share the same name, 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.
--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, then renaming back to original names.
--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()
