thanks all for your replies.
so It seems like I can use collect to do this:
fn getNonBodyMeshList = (
local list =#()
local meshes=$*mesh_*
for each in meshes do
(
if (each.name != "mesh_body") then
(
append list each.name
)
)
return list
)
with this:
fn getNonBodyMeshList=(
for obj in $mesh_* where obj.name != "mesh_body" collect obj.name
)
is this a faster method as well?
my code is full of the former style of object gathering
does collect have an anlaogue in C#?
Dennis, i think you misread the intent of my code :
return an array of names (strings) for all objects named “mesh_*” excluding “mesh_body”
Maybe this aproch. I don’t know is it fast but at least you can try
arrNames = #()
mapped fn collectObjNames arr &names =
(
append names arr.name
)
collectObjNames selection arrNames
arrNames
my bad… well. let me improve myself:
for node in $mesh_* where stricmp node.name "mesh_body" != 0 collect node.name
the stricmp compares strings not case sensitive.
Is using node instead of a variable like obj also an optimization?
I guess nodes restricts the possibilities searched to scene nodes and excludes any maxscript objects / variables …
that’s nice Denis, i’d always used matchpattern with ignorecase set as true for that sort of thing.
Thanks for the replies on dontcollect. I can see where you would use it now. I’ve even used it this morning! This was to collect any materials from the selection with a material ID applied. The extra check in this is vray materials have an ID override property that you need to look for too.
mats = for i in (selection as array) where i.material != undefined collect
(
-- check for vray mat ID override
if hasproperty i.material #override_effect_id and i.material.override_effect_id then i.material
else if i.material.effectsChannel > 0 then i.material
else dontcollect
)
if you dont use dontcollect, you’d get a lot of undefined values in the array. Thanks for the clarification.
Similar way using mapped fn
vrMtls = #()
mapped fn collectVRayMatsByID arr &mtls =
(
if isKindOf arr.material VRayMtl and arr.material.override_effect_id and \
arr.material.effect_id != 0 do append mtls arr.material
)
collectVRayMatsByID selection vrMtls
vrMtls
Also, I did some tests to wrap my head around dontcollect
Some psuedo code to illustrate my understanding:
list1=for [exp1] collect --values passing [exp1] are collected
list2=for [exp1] collect [ if [exp2] then (value)] --values failing [exp2] collected as undefined
list3= for [exp] collect [ if [exp2] then (value) else don't collect] --values failing [exp2] are skipped
does that seem correct?
so, now I’m trying to think if any of this collect/dontcollect can help me solve this task:
gather all meshes whose diffuse texture is either unique or is the first instance of a shared texture.
that is, for each unique diffuse texture in scene, return a single mesh that uses it.
I speak of the external file Path of the bitmap value of the mesh’s diffuse map (in our case each mesh has a single diffuse map bitmap file)
what material do you use? why am i asking? because i might be much easier way to find objects in some specific case
well… do you want to find the first object that uses a specified bitmap texture (file)?
here is a possible solution:
fn findObjectsByTextureUse textureFilename list: firstOnly:on =
(
if list == unsupplied do list = objects
local found = off
local nodes = for node in list while not found or not firstOnly where node.mat != undefined and finditem (usedMaps node.mat) textureFilename != 0 collect
(
found = on
node
)
if firstOnly then nodes[1] else nodes
)
there are some another…