PDA

View Full Version : Scripted Rollout UI on CA-- Questions: Wiring UI buttons to controllers, etc.


Archangel35757
12-15-2010, 05:50 AM
Ok... my progress in creating this two-handed sword rig & UI is painfully slow as my MAXscript learning curve is steep. However, I've got the floating rollout being launched from a button on a custom attribute and it appears to work ok, and I've got the checkbuttons in trackview by creating parameters and associating them to the ui buttons in the parameters block.

Now, I'm trying to get some other UI buttons properly connected up to controller parameters in the Motion Tab so that manipulating the UI buttons, sliders, etc. drive those parameters in Max-- and if the user should modify a controller weight, etc. directly in the Motion Tab, I'd like that to be reflected in the floating rollout.

So how do I go about this exactly? Bi-directional wiring? e.g.: I've got 3 radiobuttons that I want to control a bone's position and orientation constraint weightings to three other reference bones. What I tried below didn't work...

MAXscript excerpt from custom attribute script:
ca = attributes swordUI
(
local bskin_pos_wt = $bone_skin.pos.controller.Position_Constraint.weight
local bskin_orient_wt = $bone_skin.rotation.controller.orientation_constraint.weight

parameters params rollout:sword
(
...
)

rollout sword "Animation Interface"
(
group "Pivot Points"
(
radiobuttons rdo_pivot labels:#("Left Hand", "Right Hand", "Blade Tip")
)

--Event Handlers
on rdo_pivot changed state do
(
case rdo_pivot.state of
(
--Left Hand
1:(bskin_pos_wt = #(100.0, 0.0, 0.0); bskin_orient_wt = #(100.0, 0.0, 0.0))
--Right Hand
2:(bskin_pos_wt = #(0.0, 100.0, 0.0); bskin_orient_wt = #(0.0, 100.0, 0.0))
--Blade Tip
3:(bskin_pos_wt = #(0.0, 0.0, 100.0); bskin_orient_wt = #(0.0, 0.0, 100.0))
)
)
)
)
.
.
.

Archangel35757
12-16-2010, 05:47 AM
Ok... so after doing some more digging into the MXS reference and trial-and-error... I finally got it to work.

Does anyone see any pitfalls with this approach (especially in terms of animation)?

ca = attributes sword
(
parameters params rollout:swordUI
(
blade_pos_wt type:#floatTab tabSizeVariable:true animatable:true
blade_orient_wt type:#floatTab tabSizeVariable:true animatable:true
.
.
.
)

rollout swordUI "Sword Animation Interface"
(
group "Pivot Point"
(
radiobuttons rdo_pivot labels:#("Left Hand", "Right Hand", "Blade Tip") default:2 columns:3
)

on rdo_pivot changed state do
(
case rdo_pivot.state of
(
1:(--Left Hand
blade_pos_wt = #(0.0, 100.0, 0.0)
blade_orient_wt = #(0.0, 100.0, 0.0)
)
2:(--Right Hand
blade_pos_wt = #(100.0, 0.0, 0.0)
blade_orient_wt = #(100.0, 0.0, 0.0)
)
3:(--Blade Tip
blade_pos_wt = #(0.0, 0.0, 100.0)
blade_orient_wt = #(0.0, 0.0, 100.0)
)
)
$bone_skin.pos.controller.Position_Constraint.weight= blade_pos_wt
$bone_skin.rotation.controller.orientation_constraint.weight= blade_orient_wt
)
.
.
.
)
)
.
.
.

This has the effect of making the blade's bone ($bone_skin) position/orient itself to the selected pivot point's bone depending on which radio button is selected (Left Hand, Right Hand, Blade Tip) and animating the pivot selections causes the $bone_skin to blend between the other reference bones. Does anyone foresee animation pitfalls with this setup?

Edit: Hmm, this is keying the position and orientation constraint weighting... but the radio buttons are not reflecting their previous selection states. How should I add the radio buttons into the parameter block to get them to reflect past selections?

PEN
12-16-2010, 12:52 PM
I see several issues with it. One it is name dependent and it doesn't need to be, use nodeTransformMonitor and #maxObject type parameters to get around this.

Next I'm not sure why you are using floatTabs, is there something that I'm missing here?

Archangel35757
12-16-2010, 04:01 PM
I see several issues with it. One it is name dependent and it doesn't need to be, use nodeTransformMonitor and #maxObject type parameters to get around this.

Next I'm not sure why you are using floatTabs, is there something that I'm missing here?

Well, in a nutshell I'm trying to teach myself MAXscript and don't fully understand what I'm doing.

At first I had both blade_pos_wt and blade_orient_wt defined up top as local variables set equal to the $bone_skin constraint ".weight" property and MXS complained they were already defined when I was trying to put them in the parameter block (which makes sense... so I commented out the local declaration...) but I thought I needed them in the parameter block-- (although now I'm not sure I do...); these two variables aren't really associated directly with a UI button... but are indirectly related to the "Pivot Point" radio buttons-- which change the constraint weights as shown (...I'm having a difficult time finding clear guidance on radio button usage-- I find the MXS reference rather difficult to follow at times-- especially for what I'm trying to do with this floating rollout on a CA).

In trying to add them in the parameter block their value is an array of the weights, right? (...and so I thought I needed to use an array value).

Paul, thanks for your reply and I'll attempt to follow/implement your guidance. If I may ask, how do I add variables in the parameter block to properly reflect past "pivot point" selectons of the radio button states (1, 2, or 3)? I don't think they need to be manipulated in the trackview but would be nice if they could show up there... (I have so much to learn).

denisT
12-16-2010, 04:35 PM
how do I add variables in the parameter block to properly reflect past "pivot point" selectons of the radio button states (1, 2, or 3)? I don't think they need to be manipulated in the trackview but would be nice if they could show up there... (I have so much to learn).

I suggest you not using radiobuttons for this kind of animation handling. There is a theoretical chance to correctly bind your weight controllers to radiobuttons UI control. (using when parameters change and when controller change constructs for example). But practically it's not possible.
Use three buttons to set current animation (pose). Why do you need a radiobuttons? To show that the sword in the left hand? An animator can see it in viewport. If you can't absolutely correct bind Animation State with UI state-control (radiobuttons, checkbox, checkbutton, dropdown control, etc.), it's better to not use those controls at all. Its incorrect state will only confuse an animator.

Archangel35757
12-16-2010, 05:11 PM
I suggest you not using radiobuttons for this kind of animation handling. There is a theoretical chance to correctly bind your weight controllers to radiobuttons UI control. (using when parameters change and when controller change constructs for example). But practically it's not possible.
Thanks for the reply Denis, what I have implemented (although badly...) does bind the position and orientation constraint weighting (as defined in my event handler) to the three radio buttons like you said... but the radio buttons only reflect the last state when scrubbing the time slider because they have no associated parameters in the parameter block (I guess...)

Use three buttons to set current animation (pose). Why do you need a radiobuttons? To show that the sword in the left hand? An animator can see it in viewport. If you can't absolutely correct bind Animation State with UI state-control (radiobuttons, checkbox, checkbutton, dropdown control, etc.), it's better to not use those controls at all. Its incorrect state will only confuse an animator.
I just wanted the UI to reflect what the active "pivot" was via the radiobuttons... the sword will more often be wielded in a two-handed fashion-- and so it might not be clear which pivot bone is active. The Left Hand CTRL, Right Hand CTRL, and BladeTip CTRL are all siblings under a parent "Mid-Hands" CTRL object (allowing for rotations between both hands). I was just thinking, in weilding the sword in a two-handed fashion, that sometimes the Left Hand (or Right Hand) should lead (or drive) the rotations depending on the move.

Are you saying it's not possible to construct a variable (edit: something like a boolean type to reflect when a specific pivot was selected?) in the parameter block that is associated with a specific state of UI radiobuttons (having more than one selection option)?

Archangel35757
12-18-2010, 09:06 PM
I see several issues with it. One it is name dependent and it doesn't need to be, use nodeTransformMonitor and #maxObject type parameters to get around this.

Next I'm not sure why you are using floatTabs, is there something that I'm missing here?

Paul, I tried reading your tutorial on weak referencing... but I'm just not getting it. I attempted the following in the script:

parameters params rollout:swordUI
(
blade type:#maxObject NodeTransformMonitor node:$bone_skin forwardTransformChangeMsgs:false
)
.
.
.
blade.pos.controller.Position_Constraint.weight = blade_pos_wt
blade.rotation.controller.orientation_constraint.weight = blade_orient_wt
.
.
.

But I get this error in the listener when trying to re-run the script on the attribute holder:

-- Unable to convert: unsupplied to type: String

What am I doing wrong? Thanks...

Archangel35757
12-19-2010, 03:44 PM
Ok... after a little more diligent searching on the forums I saw my mistake... I made the following changes to the floating rollout script and it appears to work:

.
.
.
parameters params rollout:swordUI
(
.
.
blade type:#maxObject
)
.
.
.
on rdo_pivot changed state do
(
case rdo_pivot.state of
(
1:(--Left Hand
blade_pos_wt = #(0.0, 100.0, 0.0)
blade_orient_wt = #(0.0, 100.0, 0.0)
)
2:(--Right Hand
blade_pos_wt = #(100.0, 0.0, 0.0)
blade_orient_wt = #(100.0, 0.0, 0.0)
)
3:(--Blade Tip
blade_pos_wt = #(0.0, 0.0, 100.0)
blade_orient_wt = #(0.0, 0.0, 100.0)
)
)
blade = NodeTransformMonitor node:$bone_skin forwardTransformChangeMsgs:false
blade.node.pos.controller.Position_Constraint.weight = blade_pos_wt
blade.node.rotation.controller.orientation_constraint.weight = blade_orient_wt
)
.
.
.

However, during a quick animation of the sword only (changing pivots...) things seemed to be a bit laggy moving things around in the viewports-- have I implemented the NodeTransformMonitor properly?

denisT
12-19-2010, 05:41 PM
here is a sample how to bind a radiobuttons controls to a node property value:

global heightStateCA = attributes HeightStateControl attribID:#(0x1cabed9b, 0x3333de47)
(
fn showPopupDialog node: =
(
rollout popupDialog "heightStateCA PopupDialog"
(
local popup_pos = if popup_pos == undefined then [400,200] else popup_pos
local node

group "Height State: " ( radiobuttons state_rb labels:#("Zero", "Half", "Full") default:0 )

local states = #(0,25,50)
fn match pre:0.0001 =
(
local state = 0
for k=1 to states.count while state == 0 where abs(node.pos.z - states[k]) < pre do state = k
state
)
fn updateState = state_rb.state = if not isvalidnode node then 0 else match()

fn updateNodeHeight state:0 = undo "Set Height State" on try(node.pos.z = states[state]) catch()
on state_rb changed state do updateNodeHeight state:state

local event_handler
fn bindControl =
(
unregisterTimeCallback updateState
if event_handler != undefined do deleteChangeHandler event_handler
if isvalidnode node do
(
registerTimeCallback updateState
event_handler = when transform node change handleAt:#redrawViews do updateState()
)
updateState()
)
on popupDialog open do bindControl()
on popupDialog close do
(
unregisterTimeCallback updateState
if event_handler != undefined do deleteChangeHandler event_handler
popup_pos = getDialogPos popupDialog
)
)
createdialog popupDialog width:200 pos:popupDialog.popup_pos
popupDialog.node = node
popupDialog.title = "Height Control: " + (try(node.name) catch()) as string
popupDialog.bindControl()
)
parameters params rollout:params
(
)
rollout params "Paramerets"
(
button popup "Display Dialog" width:100
on popup pressed do
(
nodes = refs.dependentNodes (custAttributes.getOwner this)
showPopupDialog node:nodes[1]
)
)
)

(
delete objects

b1 = box length:50 width:50 height:50 pos:[0,0,0] wirecolor:yellow
addmodifier b1 (m1 = EmptyModifier())
CustAttributes.add m1 heightStateCA

b2 = box length:50 width:50 height:50 pos:[50,0,100] wirecolor:orange isselected:on
addmodifier b2 (m2 = EmptyModifier())
CustAttributes.add m2 heightStateCA
)

Archangel35757
12-19-2010, 07:23 PM
Thanks Denis, it's going to take me some time to mentally digest what you've written.

denisT
12-19-2010, 07:39 PM
... it's going to take me some time to mentally digest what you've written.
that's exactly why I'm not leaving comments. but any questions will be welcome.

CGTalk Moderation
12-19-2010, 07:39 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.