0
$\begingroup$

I need to write a script, that automatically changes the current frame according to the active layer. For example if layer 1 is active, current frame is 1. If layer 2 is active current frame is 11. There are 2 problems:

If I run this code:

 bpy.ops.anim.change_frame(frame=25)

it gives error:

Expected an timeline/animation area to be active

I can read the active layer via bpy.context.scene.active_layer however, I have no idea how to make this script always check the active layer.

$\endgroup$
2
  • $\begingroup$ Answer provided. Don't forget to upvote and mark as answered if it solved your problem to help future users $\endgroup$
    – Tak
    Commented Jun 13, 2018 at 13:44
  • 1
    $\begingroup$ Use context.scene.frame_set(frame) to set the current frame to frame. $\endgroup$
    – batFINGER
    Commented Jun 13, 2018 at 14:18

2 Answers 2

0
$\begingroup$

The draw callback hack.

There are a number of ways to make a script run constantly, via scene update handlers, modal operators, and draw callbacks to name a few.

The scene update handlers run a squi-billion-times a second which IMO is overkill. A modal timer, akin to one in text editor > templates > python > Modal Timer Operator would do the trick, but has some downside as it potentially blocks auto-save, and other functionality while running.

The draw callback, primarily designed for bgl and blf displays can be used.

Example, left in the blf which writes on 3d view. The frame is set using the active layer.

import bpy
import blf
#from gi.repository import Gdk
class DrawingClass:
    def __init__(self, context, prop):
        self.prop = prop
        self.handle = bpy.types.SpaceView3D.draw_handler_add(
                   self.draw_text_callback,(context,),
                   'WINDOW', 'POST_PIXEL')

    def draw_text_callback(self, context):
        font_id = 0  # XXX, need to find out how best to get this.
        # draw some text
        blf.position(font_id, 15, 50, 20)
        blf.size(font_id, 20, 72)
        blf.draw(font_id, "%s %s" % (context.scene.name, self.prop))
        scene = context.scene
        layer = scene.active_layer
        frame = (layer + 1) * 10 + 1
        if scene.frame_current - frame:
            scene.frame_set(frame)

    def remove_handle(self):
         bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')

if __name__ == "__main__":
    # test call            
    dc = DrawingClass(bpy.context, "Auto Layer Running......")

Hint: If you give the script a .py extension in text editor you can import it into other scripts / console etc.

enter image description here

$\endgroup$
0
$\begingroup$

You can do this using the below script:

import bpy

if bpy.context.scene.active_layer == 1:
    bpy.context.scene.frame_current=1
elif bpy.context.scene.active_layer == 2:
    bpy.context.scene.frame_current=11
$\endgroup$
1
  • $\begingroup$ Thanks but this still doesn't check active layer continuously. If I run this script on layer 2 then it changes current frame, however if I go back to previous layer it doesn't change current frame, unless I run this script again. $\endgroup$ Commented Jun 13, 2018 at 17:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .