Notifications
Clear all

[Closed] Controlling Morphs with Spinners

Hi everyone, i’m Aaron and I’ve been using 3ds Max for 3years now but am only recently trying to get to grips with MaxScript to help and enhance many features already found in max, so please forgive my inability at even minor tasks.

I have an facial animation rig that needs to be completed for next month, and while looking at the ‘how to’ section of the maxscript help I noticed the ‘Enhance the Morpher Modifier With Floating Controls’, it’s looks very useful in that it makes a floating UI control for the morph targets from the selected object, and so I was wanting to use this and add some more bits to add some more features.

However I was wanting to change the progressbar to a spinner as it would give more accurate feedback into how much of the morph is being applied. So I changed that part of the code, but now the spinner does not control the morph value…however when i change the morph value in the toolbar it changes the value of the spinner in the UI. Can anyone tell me where I’ve gone wrong? Or offer any suggestions? It would be muchly appreciated

heres the code so far

macroscript Morpher_ category:"Custom"

(

global mf_float, mf_morpher_mod

on isEnabled return 

 selection.count == 1 and (try($.morpher)catch(undefined)) != undefined   --Script is active when a object with a morpher is attached 

on execute do

(

 mf_morpher_mod = $.modifiers[#morpher] 	

 used_channels = #()   --Array to store the morpher index numbers

 txt ="rollout mf_main \"Morpher Floater\" (
" -- builds a whole new rollout dynamically, first putting all necessary definitions in a long string variable and the executing as if it were a regular script file

 for i = 1 to 100 do  --A Morpher modifier can have up to 100 channels

 (

  if WM3_MC_HasData mf_morpher_mod i then -- checks whether a channel has morpher data, if not it's skipped

  (

   append used_channels i

   txt +="spinner mf_slider_"+ i as string --adds a spinner control *I think this is where I'm going wrong*

   txt +=" value:"+ (WM3_MC_GetValue mf_morpher_mod i) as string -- appends the channel number as string to get unique names for all UI elements. Sets the current value of the progressbar to the current value of the Morpher modifier’s channel

   txt +=" width:150 height:18 across:2 align:#left
" --two UI elements on the same line

   txt +="edittext mf_label_"+i as string --

   txt +=" align:#right text:\""+i as string+": "

   txt +=(WM3_MC_GetName mf_morpher_mod i) +"\"
"

   txt +="on mf_slider_"+i as string+" clicked val do (
"

   txt +="WM3_MC_SetValue mf_morpher_mod "

   txt += i as string+" (val as float) 
"

   txt +="SliderTime +=0)
"

  )

 )--end i loop

txt +=")
"

 

createDialog (execute txt) 340 (used_channels.count*24)

txt ="fn mf_update_slider = (
"

for i in used_channels do

(

 txt +="mf_main.mf_slider_"+i as string

 txt +=".value = WM3_MC_GetValue mf_morpher_mod "+i as string+" 
"

)--end i loop

txt +=")
"

 

global mf_update_slider = execute txt

registertimecallback mf_update_slider

deleteAllChangeHandlers id:#morpher_floater

 

when parameters mf_morpher_mod changes \

 HandleAt:#RedrawViews \

 id:#morpher_floater do mf_update_slider()

)--end if
7 Replies
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

I hope this snippet will help:


 -- create sample Meshes
setCommandPanelTaskMode mode:#create
delete objects
source = converttomesh (box name:"s" wirecolor:blue)
t1 = converttomesh (box name:"t1" wirecolor:yellow)
t2 = converttomesh (box name:"t2" wirecolor:orange)
seed 1000
for v=1 to 8 do setvert t1 v ((getvert t1 v) + (random [-10,-10,-10] [10,10,10]))
update t1
for v=1 to 8 do setvert t2 v ((getvert t2 v) + (random [-10,-10,-10] [10,10,10]))
update t2

-- add Morph Modifier
modi = Morpher Autoload_of_targets:1
addmodifier source modi
setCommandPanelTaskMode mode:#modify
modpanel.setcurrentobject modi

-- add Morph Targets
WM3_MC_BuildFromNode modi 1 t1
WM3_MC_SetValue modi 1 25.0
WM3_MC_BuildFromNode modi 2 t2
WM3_MC_SetValue modi 2 5.0
WM3_RefreshChannelListUI modi

-- create Rollout and bind Morph channels to spinners  
try(destroydialog morphRol) catch()
rollout morphRol "Morph Control" 
(
	group "Weights: "
	(
		spinner sp1 "Target 1: " range:[0,100,0] type:#float scale:0.01 fieldwidth:50
		spinner sp2 "Target 2: " range:[0,100,0] type:#float scale:0.01 fieldwidth:50
	)
	on morphRol open do if IsValidMorpherMod (modi = modpanel.getcurrentobject()) do
	(
		sp1.controller = modi[1].controller
		sp2.controller = modi[2].controller
	)
)
createdialog morphRol height:70 width:200
 
 lo1

change the line

txt +="on mf_slider_"+i as string+" clicked val do (
"

to

txt +="on mf_slider_"+i as string+" changed val do (
"

‘clicked’ is a slider event while ‘changed’ is a spinner event.

Thanks, I actually managed to change it yesterday but because this was my first post it took 24hours to get OK’d by the mods lol thanks for the help none the less

Thanks to both of you for the help, the code snippet is quite a cool approach. The way I was going (with much help from someone else at Uni) was to have the spinner to set the value of the morpher whenever it changes, and then was going to try and get the timesilder to update when the frame number changes so these changes display when you scrub along the timebar, but the way you’ve done it denis skips that being necessary…very nice! Apologies I couldn’t reply sooner, but they keep checking my first posts to make sure im not spam

Cheers

you can use both Slider and Spinner synchronized together:


-- create sample Meshes
setCommandPanelTaskMode mode:#create
delete objects
source = converttomesh (box name:"s" wirecolor:blue)
t1 = converttomesh (box name:"t1" wirecolor:yellow)
t2 = converttomesh (box name:"t2" wirecolor:orange)
seed 1000
for v=1 to 8 do setvert t1 v ((getvert t1 v) + (random [-10,-10,-10] [10,10,10]))
update t1
for v=1 to 8 do setvert t2 v ((getvert t2 v) + (random [-10,-10,-10] [10,10,10]))
update t2

-- add Morph Modifier
modi = Morpher Autoload_of_targets:1
addmodifier source modi

-- add Morph Targets
WM3_MC_BuildFromNode modi 1 t1
WM3_MC_SetValue modi 1 25.0
WM3_MC_BuildFromNode modi 2 t2
WM3_MC_SetValue modi 2 5.0
WM3_RefreshChannelListUI modi

setCommandPanelTaskMode mode:#modify
modpanel.setcurrentobject modi

-- create Rollout and bind Morph channels to spinners  
try(destroydialog morphRol) catch()
rollout morphRol "Morph Control" 
(
	group "Weights: "
	(
		label lb1 "Target 1:" across:3 align:#right offset:[-40,1]
		slider sd1 range:[0,100,0] type:#float scale:0.01 width:170 ticks:0 align:#left offset:[-35,-3]
		spinner sp1 "" range:[0,100,0] type:#float scale:0.01 fieldwidth:44 offset:[0,0]
		label lb2 "Target 2:" across:3 align:#right offset:[-40,1]
		slider sd2 range:[0,100,0] type:#float scale:0.01 width:170 ticks:0 align:#left offset:[-35,-3]
		spinner sp2 "" range:[0,100,0] type:#float scale:0.01 fieldwidth:44 offset:[0,0]
	)
	on morphRol open do if IsValidMorpherMod (modi = modpanel.getcurrentobject()) do
	(
		sd1.controller = sp1.controller = modi[1].controller
		sd2.controller = sp2.controller = modi[2].controller
	)
)
createdialog morphRol height:82 width:300

 lo1

Very nice method Denis! So really the only need to use the heavier code with the timeslider updates is because the control is a progressbar which does not have an animation controller?

I remember writing something like this a long time back … maybe it could be of use to you :
http://www.aaachooo.com/Maxscript_Details/maxscripts_FacialMorphControls.html