import bpy import numpy as np from time import perf_counter, time from mathutils import Vector, Matrix from gp_interpolate.utils import (matrix_transform, plane_on_bone, ray_cast_point, intersect_with_tesselated_plane, triangle_normal, search_square, get_gp_draw_plane, create_plane, following_keys, attr_set) class GP_OT_parent_layer(bpy.types.Operator): bl_idname = "gp.parent_layer" bl_label = "Parent Layer" bl_description = 'Parent Layer' bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): if context.active_object\ and context.object.type == 'GPENCIL'\ and context.object.layers.active: return True cls.poll_message_set("Need a Grease pencil object with an active layer") return False # @classmethod # def description(cls, context, properties): # if properties.next: # return f"Interpolate Stroke Forward" # else: # return f"Interpolate Stroke Backward" def execute(self, context): settings = context.scene.gp_interpo_settings scn = bpy.context.scene gp = context.object lay = gp.layers.active # matrix = np.array(gp.matrix_world, dtype='float64')#.inverted() # origin = np.array(scn.camera.matrix_world.to_translation(), 'float64') col = settings.target_collection if not col: col = scn.collection parent_name = f'ref_{gp.name}_{lay.info}' parent_collec_name = 'gp_parents' # print('----') included_cols = [c.name for c in gp.users_collection] start = time() if settings.method == 'BONE': if not settings.target_rig or not settings.target_bone: self.report({'ERROR'}, 'No Bone Selected') return {'CANCELLED'} included_cols.append(parent_collec_name) ## Ensure collection and plane exists # Get/create collection col = bpy.data.collections.get(parent_collec_name) if not col: col = bpy.data.collections.new(parent_collec_name) if col.name not in bpy.context.scene.collection.children: bpy.context.scene.collection.children.link(col) col.hide_viewport = True # Get/create meshplane plane = bpy.data.objects.get(parent_name) if not plane: plane = create_plane(name=parent_name) plane.select_set(False) if plane.name not in col.objects: col.objects.link(plane) ## TODO: Ensure the plane is not animated! else: # Geometry mode if col != context.scene.collection: included_cols.append(col.name) ## Maybe include a plane just behing geo ? probably bad idea ## Prepare context manager store_list = [ # (context.view_layer.objects, 'active', gp), (context.tool_settings, 'use_keyframe_insert_auto', True), # (bpy.context.scene.render, 'simplify_subdivision', 0), ] for vlc in context.view_layer.layer_collection.children: store_list.append( (vlc, 'exclude', vlc.name not in included_cols), # (vlc, 'hide_viewport', vlc.name not in included_cols), # viewport viz ) # print(f'Preparation {time()-start:.4f}s') with attr_set(store_list): if settings.method == 'BONE': ## replace plane _bone_plane = plane_on_bone(settings.target_rig.pose.bones.get(settings.target_bone), arm=settings.target_rig, set_rotation=settings.use_bone_rotation, mesh=True) ## Set collection visibility intercol = bpy.data.collections.get(parent_collec_name) vl_col = bpy.context.view_layer.layer_collection.children.get(intercol.name) intercol.hide_viewport = vl_col.exclude = vl_col.hide_viewport = False # Override collection col = intercol ## TODO: Hide all other collections print('Done') return {'FINISHED'} classes = ( GP_OT_parent_layer, ) def register(): for c in classes: bpy.utils.register_class(c) def unregister(): for c in reversed(classes): bpy.utils.unregister_class(c)