Hi All,
In a recent script I noticed that events in my console display were not appearing in the order that I thought they should. This lead me to create a small test script to verify event handlers do indeed operate in the correct order.(they seems to)
What I noticed is that frame_change_pre and frame_change_post seem to be the same thing. For instance, what is frame_change_post to? I assumed frame_change_post was post to scene update but I am not sure? And what happens if I issue a mesh.update() inside a frame_change_pre? Also scene_update seems to run constantly if you uncomment those two lines. Is that normal?
So here is my example script that detects the render process, swaps the default cube for a triangle before rendering begins. The triangle is rendered instead of the cube. After render is complete another handler swaps the default cube back into the data slot of the object.
import bpy, time
from mathutils import Vector
global isRendering, mesh_name
def fetchIfMesh(passedName=""):
try:
result = bpy.data.meshes[passedName]
except:
result = None
return result
def returnSingleTriangleMesh(passedName):
me = fetchIfMesh (passedName)
if me == None:
vp_points = []
vp_faces = []
vp_objects = []
vp_D1 = Vector([0.06, 0.08, 0.0])
vp_D2 = Vector([0.06, -0.08, 0.0])
vp_D3 = Vector([-0.1, 0.0, 0.0])
vp_scale = 6.0
c = 0
# Single triangle object at world origin.
dd = Vector([0.0,0.0,0.0])
vp_points.append(dd+vp_D1*vp_scale)
vp_points.append(dd+vp_D2*vp_scale)
vp_points.append(dd+vp_D3*vp_scale)
vp_faces.append([c,c+1,c+2])
me = bpy.data.meshes.new(passedName)
me.from_pydata(vp_points,[],vp_faces)
else:
# Just use the existing mesh.
pass
# Make sure all verts are deselected.
for v in me.vertices:
v.select = False
me.update()
return me
def render_pre(passedScene):
global isRendering
isRendering = True
print ("
EVENT: render_pre")
def render_post(passedScene):
global isRendering,mesh_name
# Restore the cube.
ob = bpy.data.objects["Cube"]
me_old = ob.data
print ("recovering mesh [" + mesh_name +"].")
me_new = bpy.data.meshes[mesh_name]
print ("assigning mesh [" + me_new.name +"] to the viewport.")
ob.data = me_new
print ("removing mesh [" + me_old.name +"].")
bpy.data.meshes.remove(me_old)
isRendering = False
print ("EVENT: render_post
")
def render_stats(passedScene):
print ("EVENT: render_stats")
def frame_change_pre(passedScene):
global isRendering,mesh_name
if isRendering == True:
#Remove the cube.
ob = bpy.data.objects["Cube"]
me_old = ob.data
mesh_name = me_old.name
print("saving name [" + mesh_name + "].")
#Render a triangle
me_new = returnSingleTriangleMesh("me_triangle")
print ("assigning mesh [" + me_new.name +"] to be rendered.")
ob.data = me_new
else:
# GUI frame change.
pass
print ("EVENT: frame_change_pre")
def frame_change_post(passedScene):
print ("EVENT: frame_change_post")
def scene_update_pre(passedScene):
print ("EVENT: scene_update_pre")
def scene_update_post(passedScene):
print ("EVENT: scene_update_post")
def load_pre(passedScene):
print ("EVENT: load_pre")
def load_post(passedScene):
print ("EVENT: load_post")
def save_pre(passedScene):
print ("EVENT: save_pre")
def save_post(passedScene):
print ("EVENT: save_post")
# Setup our event handlers.
bpy.app.handlers.render_pre.append(render_pre)
bpy.app.handlers.render_post.append(render_post)
bpy.app.handlers.render_stats.append(render_stats)
bpy.app.handlers.frame_change_pre.append(frame_change_pre)
bpy.app.handlers.frame_change_post.append(frame_change_post)
bpy.app.handlers.load_pre.append(load_pre)
bpy.app.handlers.load_post.append(load_post)
bpy.app.handlers.save_pre.append(save_pre)
bpy.app.handlers.save_post.append(save_post)
#bpy.app.handlers.scene_update_post.append(scene_update_post)
#bpy.app.handlers.scene_update_pre.append(scene_update_pre)
The net result is that this script renders one mesh as if it were another mesh.
Attachments
26_handler_event_order.blend (390 KB)