fn workMaterial s e =
(
fn collectMats mat mats:#() fun: =
(
if iskindof mat Material and (appendifunique mats mat) do for k=1 to getNumSubMtls mat where (m = getSubMtl mat k) != undefined do
(
if (appendifunique mats m) do fun mat mats:mats fun:fun
)
ok
)
val = e.Argument.value
collectmats val.material mats:val.result fun:collectmats
s.Dispose()
)
mythreads = #()
mythreads[1] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
mythreads[2] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
dotnet.addEventHandler myThreads[1] "DoWork" workMaterial
dotnet.addEventHandler myThreads[2] "DoWork" workMaterial
struct MaterialData(material, result = #())
ww[1] = MaterialData material:(multimaterial numsubs:(random 60 100))
myThreads[1].runworkerasync (dotnetmxsvalue ww[1])
ww[2] = MaterialData material:(multimaterial numsubs:(random 60 100))
myThreads[2].runworkerasync (dotnetmxsvalue ww[2])
while (myThreads[1].IsBusy or myThreads[2].IsBusy) and (not keyboard.escPressed) do ()
format "1 done:(%) - %
" ww[1].result.count ww[1]
format "2 done:(%) - %
" ww[2].result.count ww[2]
it’s an example how to run worker with arguments
Denis, I was very excited last night when I saw your vision in this matter, but I’m disappointed now when I see that it still crashes my max. Look what I came up to:
(
local ww=#(#(),#()), subInMats=#()
local getSubmats, getSubmatsRecurse, capitalizeFirst, formatName
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 =
(
val = e.Argument.value
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 (substituteString (substituteString (getSubTexmapSlotName mat index) " map" "")" Map" "") + "\\"
fn getSubmatsRecurse mat matInst path:"" =
(
for propName in (getPropNames mat) do
(
local prop = try(getProperty mat propname) catch ()
if isKindOf prop Material then
getSubmats prop path:path format:(capitalizeFirst (propname as string) + "\\" + formatName prop) thread:thread
else if classOf prop == ArrayParameter do
for sub = 1 to prop.count where isKindOf prop[sub] Material do
getSubmats prop[sub] path:path format:(formatName prop[sub]) thread:thread
)
)
fn getSubmats mat path:"" format:"" =
(
local matInst = matDef mat:mat path:(path + format)
append subInMats matInst
getSubmatsRecurse mat matInst path:(path + format)
matInst
)
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
)
This is only the first part of my code, but smth went wrong already…
because
while (myThreads[1].IsBusy or myThreads[2].IsBusy) and (not keyboard.escPressed) do ()
format "1 done:(%) - %
" ww[1].result.count ww[1]
format "2 done:(%) - %
" ww[2].result.count ww[2]
is creating an infinite loop and 3d max becomes not responding. I will send as result other information, here is just for me to see the result step by step.
If I replace this code:
if isKindOf prop Material then
getSubmats prop path:path format:(capitalizeFirst (propname as string) + "\\" + formatName prop) thread:thread
else if classOf prop == ArrayParameter do
for sub = 1 to prop.count where isKindOf prop[sub] Material do
getSubmats prop[sub] path:path format:(formatName prop[sub]) thread:thread
with
if isKindOf prop Material then
print prop
then the sript doesn’t crash max
if you want to do everything faster:
fn capitalizeFirst str =
(
str[1] = toUpper str[1]
str
)
why do you collect sub-materials searching in ArrayParameter props? does getSubMtl() not work for you for any reason?
i see in your code that in getSubmatsRecurse you call getSubmats, and in getSubmats you call getSubmatsRecurse… it should’t be like that
Do you mean like this:
(
local ww=#(#(),#()), subInMats=#()
local getSubmats, capitalizeFirst, formatName
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 =
(
val = e.Argument.value
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 getSubmats mat path:"" format:"" =
(
local matInst = matDef mat:mat path:(path + format)
append subInMats matInst
for propName in (getPropNames mat) do
(
local prop = try(getProperty mat propname) catch ()
if isKindOf prop Material then
getSubmats prop path:(path + format) format:(capitalizeFirst (propname as string) + "\\" + formatName prop) thread:thread
else if classOf prop == ArrayParameter do
for sub = 1 to prop.count where isKindOf prop[sub] Material do
getSubmats prop[sub] path:(path + format) format:(formatName prop[sub]) thread:thread
)
matInst
)
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
)
anyway, it’s crashing max.
because I need to get all the material map tree, like here:
and without multithreading this code is working very very well, the only problem is that it takes long to calculate in big scenes.