ScriptSpot is a diverse online community of artists and developers who come together to find and share scripts that empower their creativity with 3ds Max. Our users come from all parts of the world and work in everything from visual effects to gaming, architecture, students or hobbyists.
This is some really horrible code but it might work:
(
struct matDef (mat, path)
local getSubmats, subMats = #()
fn capitalizeFirst str =
toUpper str[1] + subString str 2 -1
fn formatName mat index: =
if isKindOf mat TextureMap OR index == unsupplied then
capitalizeFirst ((classOf mat) as string) + "\\"else(getSubTexmapSlotName mat index) + "\\"
fn getSubmatsRecurse mat matInst path:"" =
for propName in (getPropNames mat)do(
local prop = getProperty mat propname
ifsuperClassOf prop == Material then
getSubmats prop path:path
elseifclassOf prop == ArrayParameter dofor sub in prop where superClassOf sub == Material do
getSubmats sub path:path
)
fn getSubmats mat path:"" =
(
local matInst = matDef mat:mat path:path
append subMats matInst
getSubmatsRecurse mat matInst path:(path + formatName mat)
subMats
)
fn recurseMat mat path:"" =
for i = 1 to (getNumSubTexmaps mat)
where (local map = getSubTexmap mat i)!= undefined doif getNumSubTexmaps map > 0 then
recurseMat map path:(path + formatName mat index:i)elseif isKindOf map BitmapTexture do(format"Texture: %\n" map.filename
format(path + getSubTexmapSlotName mat i + "\\\n\n"))
local current_mtl = mEdit.getCurMtl()
local subMatInsts = getSubmats current_mtl
format"\nBase material: %\n\n"(classOf current_mtl)for matInst in subMatInsts do
recurseMat matInst.mat path:("MAP TREE: " + matInst.path))
No idea why refs.dependsOn doesn't work in some cases, in the end I had to switch to the previous implementation you've posted before.
Find all submaterials in one mat, but unfortunately it is also limited, not going deep enough!!! And after finding the last submaterial, it is possible to use your code that works for any materials without submaterials
fn All_Submats onematerial =
(
Propertieses = (getPropNames onematerial)for SubProp in Propertieses do(if isProperty onematerial SubProp == truedo(
Insert = getproperty onematerial SubProp
ifsuperclassof Insert == material do(
append All_SubMaterials Insert
All_Submats Insert
)ifclassof Insert == ArrayParameter do(for i in Insert doifsuperclassof i == material do(
append All_SubMaterials i
All_Submats i
)))))
subMats = #()
fn getSubmats mat =
for sub in (refs.dependsOn mat)
where isKindOf sub Material AND NOT isKindOf sub TextureMap do(
append subMats sub
getSubmats sub
)
Anyway, I don't think it's a good idea to work from top to bottom and then back again... Have a look at my previous reply, it's certainly not universal and handles Blend material and Multisub material separately (obviously you'd have to add any other material type that can contain other materials - but there are not really that many cases).
I see that it's a recursive function but... it store the result in All_SubMaterials (that s'd be array), but this variable is not a part of this function (not defined inside, nor yet passed as argument). So that mean, that this function will work properly only if you define array variable with exact the same name before calling the function. In other words:
You answer is very GOOD and your code works perfectly! I could not even imagine how to do this! And thank you that you found time to think about this problem.
The only thing is that it does not work now for multisubobject materials, or composite, or blend material(those materials which contain submaterials) - I tried your first code for detecting MAP TREE in ActiveSlot in MTLEDITOR:
fn getmapsfrommateditor =
(
current_mtl=medit.getcurmtl()print(classOf current_mtl)
current_mtl_slot=medit.GetActiveMtlSlot()
bitmaps_for_selection=getClassInstances Bitmaptexture target:current_mtl
for bmp in bitmaps_for_selection do(
local mats = for item in refs.dependents bmp where isKindOf item Material collect item
format"\nTexture: %\n" bmp.filename
for mat in mats dofor i = 1 to (getNumSubTexmaps mat)
where getSubTexmap mat i == bmp doformat"\tSlot name: %\n"(getSubTexmapSlotName mat i)))
and it's working well! I have in my slot Multisubobject Material with 3 sub vraymtl's. I get this answer in listener:
And this is typically what I need + submaterials tree + submaps tree:
Base material: Multimaterial
Texture: \\S003\all\3d\maps\maps\6_3_9_D.jpg
MAP TREE: VRayMtl\Diffuse\Color_Correction\
or
Base Material:BlendMTl
Texture: \\S003\all\3d\maps\maps\6_3_9_D.jpg
MAP TREE: Material1:VrayMtl\Diffuse\Color_Correction\
Texture: \\S003\all\3d\maps\maps\6_3_8_D.jpg
MAP TREE: Material2:VrayMtl\Diffuse\
Your second code is very POWERFUL. It's working great for Materials which does not contain submaterials. For a material with no submaterials I get very fine result:
Is this the way you intend to use it? If that is so, it could have saved a lot of hassle had you said this in the original post... Getting the material tree going from the lowest level up is way harder than going the other way round:
(
fn capitalizeFirst str =
toUpper str[1] + subString str 2 -1
fn formatName mat index =
if isKindOf mat TextureMap then
capitalizeFirst ((classOf mat) as string) + "\\"else(getSubTexmapSlotName mat index) + "\\"
fn recurseMat mat previous:"" =
for i = 1 to (getNumSubTexmaps mat)
where (local map = getSubTexmap mat i)!= undefined doif getNumSubTexmaps map > 0 then
recurseMat map previous:(previous + formatName mat i)elseif isKindOf map BitmapTexture do(format"Texture: %\n" map.filename
format(previous + getSubTexmapSlotName mat i + "\\\n\n"))
fn parseMat mat format:"MAP TREE: " =
if isKindOf mat Blend then
(
recurseMat mat previous:formatif mat.map1 != undefined do parseMat mat.map1 \
format:(format + "Material1:" + (classOf mat.map1) as string + "\\")if mat.map2 != undefined do parseMat mat.map2 \
format:(format + "Material2:" + (classOf mat.map2) as string + "\\"))elseif isKindOf mat MultiMaterial then
for subMat in mat do
recurseMat subMat previous:(format + (classOf subMat) as string + "\\")else recurseMat mat previous:format
local current_mtl = medit.getcurmtl()format"\nBase material: %\n\n"(classOf current_mtl)
parseMat current_mtl
)
This Script is much better!
But how to make it work for all materials, for example, if we have inside multimaterial blend mtl - then it skips it at all!
or if we have composite material, it does not work! This should be Universal! Where we have
elseif isKindOf mat MultiMaterial then
for subMat in mat do
recurseMat subMat previous:(format + (classOf subMat) as string + "\\")
it should recall somehow
if isKindOf mat Blend
and all other mtl types
We need smth recursive - material in material in material...
while
( material contains submaterial) do
And it's very interesting that if I have a vrayLightmtl inside multimaterial then it's showing all it's textures, but if we have blend or composite, override etc it doesn't! I'm really stupid at this! I need to test 3 months to make it work by myself!
Comments
Glad to be of assistance :)
Glad to be of assistance :)
Some of my scripts and MCGs :: 3ds Max SDK Intro for Scripters
This is some really horrible
This is some really horrible code but it might work:
No idea why refs.dependsOn doesn't work in some cases, in the end I had to switch to the previous implementation you've posted before.
Some of my scripts and MCGs :: 3ds Max SDK Intro for Scripters
we need to integrate somehow this function
Find all submaterials in one mat, but unfortunately it is also limited, not going deep enough!!! And after finding the last submaterial, it is possible to use your code that works for any materials without submaterials
This is shorter and does the
This is shorter and does the same:
Anyway, I don't think it's a good idea to work from top to bottom and then back again... Have a look at my previous reply, it's certainly not universal and handles Blend material and Multisub material separately (obviously you'd have to add any other material type that can contain other materials - but there are not really that many cases).
Some of my scripts and MCGs :: 3ds Max SDK Intro for Scripters
Thanks
I've wrote the code to find submaterials inside composite material
hmm...
Who wrote this function?
And how you using it?
I see that it's a recursive function but... it store the result in
All_SubMaterials
(that s'd be array), but this variable is not a part of this function (not defined inside, nor yet passed as argument). So that mean, that this function will work properly only if you define array variable with exact the same name before calling the function. In other words:my recent MAXScripts RSS (archive here)
I found it in materialselector_2
sorry for this if smth !!!!
Thanks, Swordslayer, YOU ARE A GREAT MAN!!!!
You answer is very GOOD and your code works perfectly! I could not even imagine how to do this! And thank you that you found time to think about this problem.
The only thing is that it does not work now for multisubobject materials, or composite, or blend material(those materials which contain submaterials) - I tried your first code for detecting MAP TREE in ActiveSlot in MTLEDITOR:
and it's working well! I have in my slot Multisubobject Material with 3 sub vraymtl's. I get this answer in listener:
When I get inside 1st VrayMTL, I get this answer:
And this is typically what I need + submaterials tree + submaps tree:
Your second code is very POWERFUL. It's working great for Materials which does not contain submaterials. For a material with no submaterials I get very fine result:
or
but for other materials I get no answer :(
We need to combine them somehow!
Is this the way you intend to
Is this the way you intend to use it? If that is so, it could have saved a lot of hassle had you said this in the original post... Getting the material tree going from the lowest level up is way harder than going the other way round:
Some of my scripts and MCGs :: 3ds Max SDK Intro for Scripters
THANKS Swordslayer! You're really perfect scripter
This Script is much better!
But how to make it work for all materials, for example, if we have inside multimaterial blend mtl - then it skips it at all!
or if we have composite material, it does not work! This should be Universal! Where we have
it should recall somehow
if isKindOf mat Blend
and all other mtl types
We need smth recursive - material in material in material...
while
( material contains submaterial) do
And it's very interesting that if I have a vrayLightmtl inside multimaterial then it's showing all it's textures, but if we have blend or composite, override etc it doesn't! I'm really stupid at this! I need to test 3 months to make it work by myself!