View Full Version : Custom Node output not working correctly when playing animation

03 March 2011, 10:56 AM

I'm writing a node that calculates the amplitude of a WAV file per frame and outputs that value. As far as I can tell the node is working (when I click on a frame on the timeline, the output value changes).

I have hooked up the amplitude via expressions to the scale of a polycube. The polycube scales as expected when clicking in the timeline, however when playing the animation the cube will not change at all or sometimes disappear completely (presumably by scaling to 0).

Could anyone suggest why this might be happening?

On a side note, there are a couple more things about nodes I need some advice for:

Is it possible to have Compute() call automatically for every frame in an animation?

How can I create Window-esque UI features in the attribute area of a node? For example, I'd like to have a file browser, separate attributes using those drop-down divider things, etc.

03 March 2011, 07:22 PM
Ok, In the time it took for my post to be verified I managed to solve the problem. Basically the function I wrote to calculate seconds-per-frame was repeatedly modifying Maya's framerate and that was causing the animation to break.

I'd still like to get some advice on the other points I mentioned though. UI stuff and automatic Compute().

03 March 2011, 07:57 AM
in general, compute gets called ONLY when:
* an output value is requested
* an input plug, related to that output plug, is modified

that's how DG works and should be the only way to trigger the compute without hacks.

in your case, it really should have two things; first, it should take "time" node's value as input (there's undeletable time node in every maya scene in case you didn't know), and second, it should have some output attribute that is requested as animation plays through, e.g., if you're displaying fps as custom draw function, that will be called each time viewport updates - often enough for you:]

a more hacky way would be implementing a dummy output attribute and keep requesting that from a script job - but you didn't hear that from me!

regarding UI stuff, no, nodes can't know anything about UI. it's designed that way, so that scene can be opened in command-line mode of maya as well.

edit: whoops, sorry, i don't know how i didn't read the start of the post! all you need is actually there,except the time input (your "amplitude" output is related to time of the scene); when you'll scrub the animation, cube will be redrawing ,therefore, requesting it's scale, comming to your node, requesting compute (if time has changed), you then just sample your sound at the given time (again, use attribute!), and it's done.

03 March 2011, 08:25 AM
Thanks Uiron

When I talk about UI objects, I'm thinking of this:

Is it possible to replicate this kind of layout for attributes in my node? Can I implement an identical file browser? Can I have drop-down selections, tick-boxes and horizontal divisions?

03 March 2011, 09:01 AM
Thanks Uiron

When I talk about UI objects, I'm thinking of this:

in this case, you have to take a look at attribute editor templates. Chad covers some basics here:

03 March 2011, 05:03 PM
Thanks so much for the pointers, you've really got me going in the right direction now.

At the moment I'm trying to create an expression at the initialization of my node:
def postConstructor(self):
ex_string = + ".input = time"
cmds.expression( s = ex_string )

postConstructor() was my most recent attempt to get this working (it didnt work). I've also tried using __init__(), nodeCreator() and nodeInitializer(). I've been unsuccessful every time. I'm on the verge of making my own init function that is called the first time compute() is run, but it just doesn't seem particularly elegant to me. What is the correct place to build an expression when an instance of the node is created?

03 March 2011, 06:53 PM
Since you are already writing a plugin, why not just make a connection in the code when the node is created, instead of creating an expression?

03 March 2011, 07:48 PM
How would I create the connection?

03 March 2011, 07:56 PM

How would I create the connection?

03 March 2011, 08:03 PM
oh man. forget cmds module when writing node code, it's just bad bad bad.

there should be NO dag-modifying code in the node. at all. correctly written node should not care WHERE it gets it's inputs, and where it provides the outputs.

if you want to provide automatic setup of your node, then you should be creating a command for it's creation. even simplier, provide a setup script in MEL or Python, it will be just a few lines.

when connecting inputs and outputs, you don't need expressions, that's just overdoing that by a big GUI, use connection editor or hypergraph, in script code, use connectAttr command.

03 March 2011, 08:05 PM
As you already noticed creating an expression in a node's postConstructor is not very elegant and leads to the creation of additional unnecessary nodes. Furthermore you should not use a command but the MFnExpression class.

But, it's much easier than this. What you need is an input attribute of type MFnUnitAttribute.

Since I'm using the C++ API (and am particularly lazy ;)) here's the C++ code of this attribute I'm using:

aCurrentTime = uAttr.create("currentTime", "cti", MFnUnitAttribute::kTime);
CHECK_MSTATUS(attributeAffects(aCurrentTime, aOutGeometry));

You also need to make sure that this is requested every time in the compute method, otherwise Maya will NOT call the compute function in every frame. Put this in your compute and everything should work fine:

MTime time(data.inputValue(aCurrentTime).asTime());

The final thing to do is connect the outTime attribute of the time1 node (it's always there) to the currentTime attribute.

Good luck.

03 March 2011, 08:33 PM
Thanks guys, I'm extremely new to Maya's API so it's taking me a while for things to sink in.

I will try and implement this stuff and then report back.

CGTalk Moderation
03 March 2011, 08:33 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.