first of all you have to get this error message:
– Compile error: No outer local variable references permitted here: getSubmats
– In line: getSubmats p
if I defined it at the top:
local getSubmats, capitalizeFirst, formatName
then I don’t get this error.
check my example above… my idea is to organize ‘recursion’ in a thread scope. defining getSubmats outside you move it out of thread scope to the main scope
there are errors in your code… it’s not a problem of a using of multi-threading. just errors. fix them first.
you can make tree using getSubMtl as well
searching in ArrayParameter for materials is slow and not correct
you expect that a sub-material can be stored in ‘flat’ material property or in an array property. this is not true generally. i can write a material where you will not see any ‘material’ property. but my material will have sub-materials, and they will be shown and editable in the material editor for example.
getSubMtl and setSubMtl are only safe methods to get access to sub-materials. anything else is a ‘lucky’ coincidence.
Do you mean this:
(
struct matDef (mat, path)
subInMats=#()
fn capitalizeFirst str =
(
str[1] = toUpper str[1]
str
)
fn formatName mat index: =
if isKindOf mat TextureMap OR index == unsupplied then
capitalizeFirst ((classOf mat) as string) + "\\"
else (substituteString (substituteString (getSubTexmapSlotName mat index) " map" "")" Map" "") + "\\"
fn getAllMaterilas mat mats:#() path:"" format:"" =
(
local matInst = matDef mat:mat path:(path + format)
append subInMats matInst
if iskindof mat Material do
(
append mats mat
for k=1 to (getNumSubMtls mat) do getAllMaterilas (getSubMtl mat k) mats:mats path:(path + format) format:("\\" + formatName mat)
)
subInMats
)
local current_mtl = mEdit.getCurMtl()
local subMatInsts = getAllMaterilas current_mtl
for matInst in subMatInsts do
print matInst.path
)
what is ‘material’ path for you? every material can have many different paths. as many as number of its references.
It is important for my interior scenes, I can see where is this texture from, is it collected or not, as so on. It saves a lot of time, really.
In an addition with a bit more code, I get these results:
Texture: \\12_CORE-PC\Project 2012\zagotovki\materials and textures\wallpapers_seamless\Eijffinger_B_W_397655.jpg
MAP TREE: Blend\Diffuse\
Texture: \\12_CORE-PC\Project 2012\zagotovki\materials and textures\wallpapers_seamless\Eijffinger_B_W_397655_bg.jpg
MAP TREE: Blend\Bump\
Now, Denis, what’s next? how to solve “No outer local variable references permitted here:”?
(
local ww=#(#(),#())
struct matDef (mat, path)
fn workMaterialD s e =
(
s.Dispose()
format "% thread Done. Results: %
" e.Result.value[1] e.Result.value[2]
)
fn workMaterial s e =
(
fn capitalizeFirst str =
(
str[1] = toUpper str[1]
str
)
fn formatName mat index: =
(
if isKindOf mat TextureMap OR index == unsupplied then
capitalizeFirst ((classOf mat) as string) + "\\"
else (substituteString (substituteString (getSubTexmapSlotName mat index) " map" "")" Map" "") + "\\"
)
fn getAllMaterilas mat subInMats:#() mats:#() path:"" format:"" =
(
local matInst = matDef mat:mat path:(path + format)
append subInMats matInst
if iskindof mat Material do
(
append mats mat
for k=1 to (getNumSubMtls mat) do getAllMaterilas (getSubMtl mat k) subInMats:subInMats mats:mats path:(path + format) format:(formatName mat)
)
subInMats
)
fn recurseMat mat path:"" =
(
for i = 1 to (getNumSubTexmaps mat) where (local map = getSubTexmap mat i) != undefined do
(
if getNumSubTexmaps map > 0 then
recurseMat map path:(path + formatName mat index:i)
else if isKindOf map BitmapTexture do
(
format "Texture: %
" map.filename
format (path + formatName mat index:i + "
")
)
)
)
fn workwiththismat thismat r:#() =
(
local subMatInsts = getSubmats thismat
append r subMatInsts
)
workwiththismat val.material r:val.result
e.Result = dotnetmxsvalue #(val.thread, val.result)
)
mythreads = #()
mythreads[1] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
mythreads[2] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
dotnet.addEventHandler myThreads[1] "DoWork" workMaterial
dotnet.addEventHandler myThreads[2] "DoWork" workMaterial
dotNet.addEventHandler mythreads[1] "RunWorkerCompleted" workMaterialD
dotNet.addEventHandler mythreads[2] "RunWorkerCompleted" workMaterialD
struct MaterialData(thread, material, result = #())
ww[1] = MaterialData thread:1 material:(multimaterial numsubs:(random 60 100))
myThreads[1].runworkerasync (dotnetmxsvalue ww[1])
ww[2] = MaterialData thread:2 material:(multimaterial numsubs:(random 60 100))
myThreads[2].runworkerasync (dotnetmxsvalue ww[2])
OK
)