[Closed] morpher: addind progressives via maxscript problem
hey guys,
I did a very simple script ( with the help of Jonathan de Blok, thanks man!)to add targets to a morpher modifier. The way it works is simple, it reads the name of the objects you want to add and whenever 2 objects have the same name, adds them to the same channel, it reads the sufix of the object and gets the value from there to set the % of each target. For example: smile_100, smile_025, smile_050. you can run the script, select the 3 objects and those will be added to the same channel, each with its own correct value of % BUT i've hit a problem ( maybe a bug ) when doing that, the targets get the right value, but the little listbox with the targets is in the wrong order, almost if it doesn't update properly when adding the values via maxscript. Could anyone have a look and see if I'm just getting crazy or this is indeed a bug? thanks, here is the code and the usage
usage:
1) select your object that has an empty Morpher modifier applied
2) run script
3) it ask to to pick targets where name = "chn_percentage" ( ie: smile_100, smile_050, smile_025)
mainObject=selection[1]
trgs=selectByName prompt:"Pick objects" single:false
--Setup main channels for item with 100%
channels = #()
for item in trgs do
(
chop=filterString item.name "_"
if (chop.count==2) do
(
chn=chop[1]
prc=chop[2] as float
appendIfUnique channels chn --store channels in an array
chn_index= findItem channels chn
if (prc==100) do
( print "aa"
WM3_MC_BuildFromNode mainObject.Morpher chn_index item
WM3_SetProgressiveMorphWeight mainObject.Morpher chn_index item prc
)
)
)
--Setup item with <100% as Prog targets
for item in trgs do
(
chop=filterString item.name "_"
if (chop.count==2) do
(
chn=chop[1]
prc=chop[2] as float
chn_index= findItem channels chn
if (prc<100) do
(
WM3_AddProgressiveMorphNode mainObject.Morpher chn_index item
WM3_SetProgressiveMorphWeight mainObject.Morpher chn_index item prc
for i in 1 to 100 do
(
if WM3_MC_HasData $.morpher i then
(
numMorph = WM3_NumberOfProgressiveMorphs $.morpher i
--append info numMorph
for m in 1 to numMorph do
(
nameProg = WM3_GetProgressiveMorphNode $.morpher i m
print nameProg
chop=filterString nameProg.name "_"
print chop
value = chop[2] as float
print value
WM3_SetProgressiveMorphWeight $.morpher i nameProg value
)
)
)
sh**iiit, how did that happen?
edited the content again, should be ok now!, thanks
I have made some modifications to the script. It still needs improvements and clean up, but I hope it does what you need.
(
struct morphTarget (node, channel, value)
fn SortByName n1 n2 =
(
if n1.name < n2.name then 1
else if n1.name > n2.name then -1
else 0
)
fn GetMorphChannels mMod =
(
usedChannels = for j = 1 to 100 where WM3_MC_HasData mMod j collect #(j, WM3_MC_GetName mMod j)
if usedChannels.count > 0 do
(
answer = querybox "Would you like to delete existing Morph Channels?"
if answer do
(
for j in usedChannels do WM3_MC_Delete mMod j[1]
usedChannels = #()
)
)
usedChannels = for j in usedChannels collect (filterString j[2] "_")[1]
return usedChannels
)
fn AddMorphTargets node =
(
morpherMod = modPanel.getCurrentObject()
if classof morpherMod != Morpher do return undefined
channels = GetMorphChannels morpherMod
trgs = selectByName single:false
if trgs == undefined do return undefined
qsort trgs SortByName
targets = for i in trgs collect
(
chop=filterString i.name "_"
if (chop.count==2) then
(
chn = chop[1]
appendIfUnique channels chn
chnIdx = findItem channels chn
morphTarget node:i channel:chnIdx value:(chop[2] as float)
)else(
dontcollect
)
)
for i in targets do
(
if (i.value==100.0) then
(
WM3_MC_BuildFromNode morpherMod i.channel i.node
)else(
WM3_AddProgressiveMorphNode morpherMod i.channel i.node
)
)
for i in targets do WM3_SetProgressiveMorphWeight morpherMod i.channel i.node i.value
)
AddMorphTargets selection[1]
)
Hey Jorge! Thanks a lot! I’ll give that a try later on today and I’ll let you know! I’ll see if i can understand your changes as I’m quite a newbie with scripting!
Gracias por la ayuda!
You are welcome Alex.
The code is very similar to the original script, I just removed a few lines and reorganized it a little, but nothing too fancy, so I am sure you will catch up very quick.
The most important change was to sort the array of nodes in order to properly assign to the Weight percentage.
Note that in order to properly sort the nodes, their names must have the same format for the numeric part (3 digits), as in the examples you have. Names like “smile_1” will not be correctly sorted, contrary to “smile_001”.
This issue can be fixed, as Rotem showed in another thread, but I personally prefer to use a fixed number of digits.
Other than that I just added a function GetMorphChannels() (should probably be GetUsedMorphChannels()), to get the used channels if any and to delete all existing used channels if you want, which was useful for testing. It also allows you to add more channels in case you need. For example if you have “smile”, “leg”, “arm” and you just add “smile”, you can later on add the “leg” and “arm” channels.
As it is now you can’t add more targets to an existing channel with their proper Weights. But with some modification it could be done.
If you need me to clarify anything or if the script does not work please let me know.
hey Jorge,
again thanks for the help on this. Unfortunately I’m having the same problem I was having with the previous version of the script, and I think that is just a bug in morpher:
When you add a few targets in the same channel, you have a target list, and the targets show there. Whenever you modify the weight of each target manually, that list updates, and shows the targets with smaller value on top, and as you move your way down the list the target% goes higher according. When you do that via script, the targets get the right value as for the naming convention BUT this target list doesn’t update so even if they have the right values, the position of the targets in that list is wrong, and makes the morphs go crazy ( i believe that only happens if you have more than 2 targets on the same channel…)
I’m uploading a file where shows the 3 targets and according to their values it shoudl read:
a_025
a_050
a_100
BUT it reads:
a_050
a_100
a_025
I’m not sure i’m being clear on where the bug/problem is…?
edit: I cant seem to upload the img file…
I was testing it in Max 2011 and it works well. I now tested it on Max 2012 and 2015 and I have the problem as you. The list does not update correctly. So I think perhaps this is a bug in the modifier.
I've added a workaround that seems to work in Max 2012+. I hope it works for you too.
(
struct morphTarget (node, channel, value)
fn SortByName n1 n2 =
(
if n1.name < n2.name then 1
else if n1.name > n2.name then -1
else 0
)
fn GetMorphChannels mMod =
(
usedChannels = for j = 1 to 100 where WM3_MC_HasData mMod j collect #(j, WM3_MC_GetName mMod j)
if usedChannels.count > 0 do
(
answer = querybox "Would you like to delete existing Morph Channels?"
if answer do
(
for j in usedChannels do WM3_MC_Delete mMod j[1]
usedChannels = #()
)
)
usedChannels = for j in usedChannels collect (filterString j[2] "_")[1]
return usedChannels
)
fn AddMorphTargets node =
(
morpherMod = modPanel.getCurrentObject()
if classof morpherMod != Morpher do return undefined
channels = GetMorphChannels morpherMod
trgs = selectByName single:false
if trgs == undefined do return undefined
qsort trgs SortByName
targets = for i in trgs collect
(
chop=filterString i.name "_"
if (chop.count==2) then
(
chn = chop[1]
appendIfUnique channels chn
chnIdx = findItem channels chn
morphTarget node:i channel:chnIdx value:(chop[2] as float)
)else(
dontcollect
)
)
for i in targets do
(
print i
if (i.value==100.0) then
(
WM3_MC_BuildFromNode morpherMod i.channel i.node
)else(
WM3_AddProgressiveMorphNode morpherMod i.channel i.node
)
)
for i in targets do WM3_SetProgressiveMorphWeight morpherMod i.channel i.node 0.0
for i in targets do WM3_SetProgressiveMorphWeight morpherMod i.channel i.node i.value
)
AddMorphTargets selection[1]
)
you have to add targets in ‘weight ascending’ order if you want to get them finally in this loading order:
delete objects
fn getTargetWeight node =
(
prefix = trimright node.name "0123456789"
(substring node.name (prefix.count + 1) -1) as float
)
fn sortByTargetWeight n1 n2 =
(
(getTargetWeight n1) - (getTargetWeight n2)
)
numtargets = 4
b0 = converttomesh (box name:#source width:10 length:10 height:10 wirecolor:brown)
targets = for k=1 to numtargets collect
(
name = "target_" + formattedprint (random 0 100) format:"03d"
converttomesh (box name:name width:(random 5 20) length:(random 5 20) height:(random 2 40) pos:[30*k,0,0] wirecolor:orange)
)
qsort targets sortByTargetWeight
_morpher = Morpher()
addmodifier b0 _morpher
for k=1 to targets.count do
(
target = targets[k]
(if k==1 then WM3_MC_BuildFromNode else WM3_AddProgressiveMorphNode) _morpher 1 target
)
for k=1 to targets.count do
(
target = targets[k]
weight = getTargetWeight target
WM3_SetProgressiveMorphWeight _morpher 1 target weight
)
select b0
all other is not really important