Jump to content

Accessing Keyframes through Xpresso


Robert Krawczyk

Recommended Posts

Hello @everyone,

 

On 10/20/2021 at 9:34 PM, Robert Krawczyk said:

Hi, I would like to move keyframes around the timeline with Xpresso - is this possible? Is there any way to access keyframes and markers?

 

Yes, it is, but it is a bit clunky.

 

On 10/20/2021 at 11:21 PM, MJV said:

Not sure about markers, but keys, no. It's not possible, as it would create complete chaos when scrubbing and a ruined timeline and animation.

 

While this is probably practically true, it is technically not. You can always spice up your Xpresso with Python, which also means you can do whatever you want to do. The question then is how "Xpresso-esque" the results are when 99% of the stuff happens inside a Python node. There is also the problem of Xpresso that it really dislikes linking classic API node types other than BaseObjects, i.e., objects, so that one must use the user data trick for linking other node types.

 

The attached example has a null called "Xpresso" which has a user data field "Slot". With this Slot field we pass in some node into our Xpresso graph. In this case the track of an animation. Also passed in is the x-position of another null. The final result is then that one can select a key via its index. The frame time value of that key is then driven by the position x-component of that driving null. I.e., effectively, when the null is at (40, 0, 0) units, then the second key in that track will be at 40 frames in the example file. You could animate that null and the key frame value will follow. The result would be rather non-sensical, as that track animation would change over time, but it works ^^

 

How practical all that is, is up to you. It is certainly technically possible. But it makes much more sense to do such things right away as a Python Programming Tag IMHO. But opinions can differ here, and some people find such mixed setups useful.

 

Cheers,

Ferdinand

xpresso_keyframes.c4d

Link to comment
13 minutes ago, zipit said:

but it works

 

...until it crashes? 😇

 

Seriously, with constructs inside a tag (be it a Python node in XPresso or a direct Python tag) that changes major object structures while the tree is evaluated, I get a bellyache even if the API technically allows it. Maybe it works, but no one can guarantee that it will keep working in the next C4D version. Maybe it doesn't crash immediately but later. Maybe the API doesn't allow it and responds with either a thrown error, or by doing nothing at all. Maybe it works under the current circumstances but will not be transferable to another situation. Maybe it will totally work and is fine with C4D but no one will understand later what the frag you are even doing.

I just wouldn't do it or recommend it; as I don't have access to the C4D source code I couldn't even analyze to verify. (Which I wouldn't want to do either.)

 

Anyway, in 95% of all cases, the answer to that kind of question is: You are abusing the evaluative system while trying to program a functionality that is meant to run outside the tree evaluation on top level. Use a script instead.

 

I don't know what the OP ultimately wants that functionality for, but I'm taking bets.

(Not really.)

Link to comment
19 minutes ago, Cairyn said:

 

...until it crashes? 😇

 

Seriously, with constructs inside a tag (be it a Python node in XPresso or a direct Python tag) that changes major object structures while the tree is evaluated ...

 

I do not really see what should crash here in my example. Although we are outside of the main thread in a Python node, modifying parameters is fine in such context. Which is what we are doing. Modifying a BaseTime paramater of a key in Python programming Tag scenario would also be fine, I would even say that is the exact usage scenario of a (Python) Tag. Inserting nodes or invoking events would be off-limits in both scenarios, but that is not what we are doing here.

 

What could go wrong with such Xpresso/Python setups, is that one could create feed-back loops, but for that one would have to use a parameter both as in input and output. But we are not doing this either. And this should also not crash; it is just that it would constantly evaluate each frame and by that converge to some value. I am also not sure what you mean by evaluating "the tree".  We are here in the expression pass of the scene evaluation in Xpresso. I do not really see how this would make modifying parameters off limits, as this is what the expression pass is for.

 

While I agree that this ugly and also somewhat pointless, a Python Programming Tag would be a much better solution, I would disagree that this will crash. 

Link to comment
21 minutes ago, zipit said:

While I agree that this ugly and also somewhat pointless, a Python Programming Tag would be a much better solution, I would disagree that this will crash. 

 

Maybe, maybe not. Maybe it works under these circumstances with that code for this purpose. But what if you have some time-based behavior, like dynamics or particle physics? You can move a keyframe for anything into the past, where it has not been evaluated (as that frame may already have been drawn), and create a situation where a solver relies on a past keyframe being evaluated - which never happened because at the time when that frame was drawn, the keyframe simply was somewhen else...

 

Maybe the programmers of C4D and maybe all the plugins that exist have thought of those kind of situations (as you can scrub the timeline and the algorithm must be prepared to a non-sequential time anyway), but even if it doesn't crash, it makes me deeply uncomfortable to work this way. The least of issues would be that past rendered frames will become invalid if the moved keyframe had any influence on them.

 

I'd like to challenge the OP's purpose and want to know what this "moving keyframes" is for.

Link to comment
On 10/26/2021 at 7:05 AM, zipit said:

Hello @everyone,

 

 

Yes, it is, but it is a bit clunky.

 

 

While this is probably practically true, it is technically not. You can always spice up your Xpresso with Python, which also means you can do whatever you want to do. The question then is how "Xpresso-esque" the results are when 99% of the stuff happens inside a Python node. There is also the problem of Xpresso that it really dislikes linking classic API node types other than BaseObjects, i.e., objects, so that one must use the user data trick for linking other node types.

 

The attached example has a null called "Xpresso" which has a user data field "Slot". With this Slot field we pass in some node into our Xpresso graph. In this case the track of an animation. Also passed in is the x-position of another null. The final result is then that one can select a key via its index. The frame time value of that key is then driven by the position x-component of that driving null. I.e., effectively, when the null is at (40, 0, 0) units, then the second key in that track will be at 40 frames in the example file. You could animate that null and the key frame value will follow. The result would be rather non-sensical, as that track animation would change over time, but it works ^^

 

How practical all that is, is up to you. It is certainly technically possible. But it makes much more sense to do such things right away as a Python Programming Tag IMHO. But opinions can differ here, and some people find such mixed setups useful.

 

Cheers,

Ferdinand

xpresso_keyframes.c4d 173.34 kB · 1 download

 

On 10/26/2021 at 8:50 AM, Cairyn said:

 

Maybe, maybe not. Maybe it works under these circumstances with that code for this purpose. But what if you have some time-based behavior, like dynamics or particle physics? You can move a keyframe for anything into the past, where it has not been evaluated (as that frame may already have been drawn), and create a situation where a solver relies on a past keyframe being evaluated - which never happened because at the time when that frame was drawn, the keyframe simply was somewhen else...

 

Maybe the programmers of C4D and maybe all the plugins that exist have thought of those kind of situations (as you can scrub the timeline and the algorithm must be prepared to a non-sequential time anyway), but even if it doesn't crash, it makes me deeply uncomfortable to work this way. The least of issues would be that past rendered frames will become invalid if the moved keyframe had any influence on them.

 

I'd like to challenge the OP's purpose and want to know what this "moving keyframes" is for.

 

Thanks for the replies, it's cool that there is actually a way to access keyframes. Is there a way to access a marker's frame number?

My purpose is to make it easier to move around major time marks. Like if character A grabs character B at frame 1207, there are multiple objects that have a keyframe corresponding to that event, and those keyframes always need to happen at 1207 for the event to look right. This makes it annoying to move the event to 1260, because I would have to move a bunch of keyframes to 1260 and remember which objects, etc. So I want to put a marker at 1207 and give it a list of objects' keyframes which will always lock to the marker's frame number.

I would not be animating the movement of keyframes at all.

I thought Xpresso would be good for this because it constantly updates. But if that causes problems, is there a way to have Python code that would run every time a marker moves?

Link to comment

The workflow you describe is not advisable. Instead of using keyframes to get the response you need on contact, you should use condition based xpessions that automatically force the required actions to occur when a condition of your choosing is met, instead of using keyframes.

Link to comment
12 hours ago, Robert Krawczyk said:

I thought Xpresso would be good for this because it constantly updates.

 

For the specific usecase, I wouldn't use any dynamic stuff... after all, you do not want to move around the Event dynamically (if I understand you correctly) but just want to move the event during the animation phase manually. You may even get into trouble when the Event needs to contain keyframes before or after the marker in a defined offset (like, if you have a scene where char1 gives an object to char2, then char1 needs to have the hand closed before the transfer, and open it at the transfer, while char2 needs to open the hand before the transfer and close it at the transfer, so for a complex action you end up with staggered keyframes around the Event.

 

Isn't that all possible through the motion system already? Storing a specific activity with multiple keyframes so you can move the whole motion around as a single block? (I'll leave that for the motion experts to answer...)

 

Link to comment
Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Copyright Core 4D © 2023 Powered by Invision Community