4

this works in viewport but not in render.

import bpy
from math import *

def frame_handler(scene):
    z = scene.objects['Lift'].location[2]
    scene.objects['Text'].data.body = str(floor(z / 4.0) - 2)

bpy.app.handlers.frame_change_pre.clear()
bpy.app.handlers.frame_change_pre.append(frame_handler)

How to get it working in render? I've read this answer and changed from "bpy.data.objects" to "scene.objects" as already seen in the script. What am I missing? Blender v. 2.81.16

Edit. Tried that depsgraph thing mentioned in comments and changed to frame_change_post:

import bpy
from bpy.app.handlers import persistent
from math import *

@persistent  # maybe not relevant but doesn't harm anything?
def frame_handler(scene, depsgraph):
    z = scene.objects['Lift'].evaluated_get(depsgraph).location[2]
    scene.objects['Text'].data.body = str(floor(z / 4.0) - 2)

bpy.app.handlers.frame_change_pre.clear()
bpy.app.handlers.frame_change_post.clear()
bpy.app.handlers.frame_change_post.append(frame_handler)

Now the Text doesn't show up at all in rendered (but works in viewport).

user3202179
  • 311
  • 1
  • 8
  • 2
  • @lemon Unfortunately I don't get a solution there. – user3202179 Feb 26 '20 at 17:55
  • Should use frame_change_post instead (if possible) and with the depsgraph indicated above. – lemon Feb 26 '20 at 18:07
  • Possibly related: https://blender.stackexchange.com/questions/161758/typing-animation-in-2-81#comment273967_161758 , haven't tried with evaluated object as suggested by @lemon – batFINGER Feb 26 '20 at 18:10
  • pre has no depsgraph parameter, and renderer has its own context (dr.Sybren information) so in pre objects are not evaluated during rendering if I understand well (@batFINGER). – lemon Feb 26 '20 at 18:19
  • @lemon That depsgraph thing seems just inconceivable to me... Can't figure out what to do with it. Maybe some other day.@batFINGER I read that Animation Nodes crash this version of Blender, and I haven't tried them earlier. – user3202179 Feb 26 '20 at 18:20
  • depsgraph is a second parameter in the handlers. It is used to evaluate objects at the step they are during frame change (and especially in rendering). Depsgraph is the dependency graph of the object (things that the object depends on during animation for instance). Have a look at the link of my first comment and the doc link indicated in it. – lemon Feb 26 '20 at 18:23
  • 1
    Point of link being: If you render the animation as single image and change frame in script, it renders the changed body of font object. – batFINGER Feb 26 '20 at 18:24
  • For information, even if named 'post', " This can be used, for example, to alter scene prior it gets rendered. " following this documentation: https://wiki.blender.org/wiki/Reference/Release_Notes/2.81/Python_API#Handlers Will write a quick answer if that helps. – lemon Feb 26 '20 at 18:40
  • @batFINGER, ok good to know... in between wrote a little answer in hope than can clarify the subject for this question. But as 'post' is before rendering, 'pre' also... so if 'pre' has depsgraph in 2.83, maybe 'pre' will allow to retreive the state before frame change? That's it? – lemon Feb 26 '20 at 18:57
  • If that does not work. That could be Blender version. Can you try 2.82? rthese changes are new from 2.81) – lemon Feb 26 '20 at 19:06
  • @batFINGER, you mean 'render changed body' without depsgraph (in 2.83)? If yes I've misunderstood what dr.Sybren told me. About bug nothing to report, I think, as things are evolving. Or that means rendering context will be considered as active in 2.83 (not the case in 2.82). – lemon Feb 26 '20 at 19:17

2 Answers2

6

The answer is similar to this question. Though all this is new from 2.81.

So here are some little more information (as far as I understand all this, which seems to be new thing along the current versions).

To make your script work, you can change it to:

import bpy

def frame_handler(scene, depsgraph): #print(depsgraph) obj = scene.objects['Cube'] obj = obj.evaluated_get(depsgraph) scene.objects['Text'].data.body = '{0:.2f}'.format(obj.location.z)

bpy.app.handlers.frame_change_post.clear() bpy.app.handlers.frame_change_post.append(frame_handler)

Here frame_change_post is used. But following this documentation:

This can be used, for example, to alter scene prior it gets rendered.

So the result will be what you want to do.

In the script above I've changed the rounding for Z. That allows to confirm that 'post' is before rendering. If object Z position is 10 at frame 10, the text object will display 10 at the same frame.

Additionally, depsgraph is for dependencies graph. That means a data provided in the API to take into account the fact that during animation (or others) the object state varies due to what it depends on.

frame_change_pre has no depsgraph parameter in 2.82.

brockmann
  • 12,613
  • 4
  • 50
  • 93
lemon
  • 60,295
  • 3
  • 66
  • 136
  • Now it works but behaves strangely! The Text object drifts vertically as the lift moves, or that's what appears in the render result. Maybe the situation is too complex. Both the camera and the Text are parented to the Lift object. – user3202179 Feb 26 '20 at 20:47
  • Well for this other aspect you should share more details and maybe a part of your blend file to reproduce the situation. I suggest you ask another question about that. – lemon Feb 27 '20 at 07:08
1

In sequence-view:

  • click View menu item
  • click Sequence Render animation

This will correctly export an animation with frame_handler

Duarte Farrajota Ramos
  • 59,425
  • 39
  • 130
  • 187