From 6197aa622b4abedeee5e3fce05e5067c93330e57 Mon Sep 17 00:00:00 2001 From: pullusb Date: Mon, 11 Dec 2023 11:37:24 +0100 Subject: [PATCH] initial code for layer parenting --- parent_layer/__init__.py | 24 +++++++ parent_layer/operator.py | 140 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 parent_layer/__init__.py create mode 100644 parent_layer/operator.py diff --git a/parent_layer/__init__.py b/parent_layer/__init__.py new file mode 100644 index 0000000..416eb32 --- /dev/null +++ b/parent_layer/__init__.py @@ -0,0 +1,24 @@ +from gp_interpolate.parent_layer import (operators, + # properties, + ) + +modules = ( + # properties, + operators, +) + +if "bpy" in locals(): + import importlib + + for mod in modules: + importlib.reload(mod) + +import bpy + +def register(): + for mod in modules: + mod.register() + +def unregister(): + for mod in reversed(modules): + mod.unregister() diff --git a/parent_layer/operator.py b/parent_layer/operator.py new file mode 100644 index 0000000..92a5c24 --- /dev/null +++ b/parent_layer/operator.py @@ -0,0 +1,140 @@ +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)