2

The script I'm writing contains a bpy.app.timer which is supposed to detect if the user has manually exited Grease Pencil paint mode, then convert the grease pencil object to a curve. No matter what I try I just can't get past the 'context is incorrect' error. Everything up to the convert operator works; for a selected pose bone a GP-Emtpy is added and you enter Paint Mode, if you draw something and then switch to Object Mode the timer finds it and goes on to execute the script below it - until it hits the convert operator. I tried invoking the area but then I get 'missing window in context' as an error. How can I set a context?

bl_info = {
"name": "Swoosh Animation",
"author": "Anton Lux",
"version": (1, 0),
"blender": (2, 83, 3),
"location": "View3D > Pose",
"description": "Animates Bones using GP Strokes",
"warning": "",
"doc_url": "",
"category": "Object",
}

import time import bpy import os from pathlib import Path from bpy.types import Operator, PropertyGroup from bpy.props import IntProperty, BoolProperty, FloatVectorProperty from bpy.types import ( AddonPreferences, Operator, Panel, PropertyGroup, )

class Object_OT_applyAnim(bpy.types.Operator): bl_idname = "pose.apply_anim" bl_label = "Apply GP Animation" bl_description = "Apply the Animation to selected Bone" bl_space_type = "View_3D" bl_region_type = "UI" bl_options = {'REGISTER', 'UNDO'}

def execute(self, context):

    #defining timer to call later
    def every_2_seconds():
        if bpy.context.mode == 'OBJECT':
            bpy.app.timers.unregister(every_2_seconds)
            #testing if timer found the new mode
            print("Cookies")



            #Converting GP to Curve
            bpy.ops.gpencil.convert('INVOKE_AREA', type='PATH', use_link_strokes=True, frame_range=500, use_realtime=True, use_timing_data=True)
            #Below here doesn't work either cause the context is noneType
            #Storing constraint target
            curve = bpy.context.selected_objects[1]

            #Setting up follow path constraint
            bpy.context.view_layer.objects.active = Armature
            bpy.ops.object.posemode_toggle()
            Bone.bone.select = True
            bpy.ops.transform.translate(value=(relative_zero), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL')

            Bone.constraints["Follow Path"].target = curve


            #Baking constraint into keyframes
            bpy.ops.nla.bake(frame_start=1, frame_end=70, visual_keying=True, clear_constraints=True, bake_types={'POSE'})
            #Decimating keyframes
            bpy.ops.action.clean(threshold=0.001, channels=False)
        return 2.0       

     #Step 1 creating grease pencil stroke

    Bone = bpy.context.active_pose_bone
    boneName = bpy.context.active_pose_bone.name
    Armature = bpy.context.active_object
    Bone_tail = bpy.context.active_pose_bone.tail
    relative_zero =  (Armature.location + Bone_tail) * (-1)
    window = bpy.context.window_manager.windows[0]

    #Leaving Pose Mode
    bpy.ops.object.posemode_toggle()
    #Adding GP Empty
    bpy.ops.object.gpencil_add(align='WORLD', location= Bone.location, type='EMPTY')
    bpy.context.object.name = boneName        

    #Entering Paint Mode
    bpy.ops.gpencil.paintmode_toggle()

    #Step 2 activating the timer defined above
    bpy.app.timers.register(every_2_seconds)








    return {'FINISHED'}

def menu_func2 (self,context): self.layout.operator(Object_OT_applyAnim.bl_idname)

def register(): bpy.utils.register_class(Object_OT_applyAnim) bpy.types.VIEW3D_MT_pose.append(menu_func2)

def unregister(): bpy.utils.unregister_class(Object_OT_applyAnim) bpy.types.VIEW3D_MT_pose.remove(menu_func2)

if name == "main": register()

batFINGER
  • 84,216
  • 10
  • 108
  • 233
Shmoomin
  • 21
  • 1
  • 1
    Consider a modal timer operator. https://blender.stackexchange.com/questions/135970/context-is-incorrect-when-calling-from-a-timer https://blender.stackexchange.com/questions/146163/python-timer-is-not-working-for-me-in-blender When context is passed as an argument ie def foo(self, context) use it rather than bpy.context in method code – batFINGER Aug 08 '20 at 12:13
  • Thx a lot. That did the trick. You're a legend. – Shmoomin Aug 20 '20 at 17:12

0 Answers0