From 0592bfecec826725e1bffecf4dd18dddbec31982 Mon Sep 17 00:00:00 2001
From: "Spivak Vladimir (cwolf3d)" <cwolf3d@gmail.com>
Date: Fri, 10 May 2019 01:55:56 +0300
Subject: [PATCH] Bsurfaces: Added "annotations" as guide strokes

---
 mesh_bsurfaces.py | 198 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 151 insertions(+), 47 deletions(-)

diff --git a/mesh_bsurfaces.py b/mesh_bsurfaces.py
index 4bc6534ab..ab052695c 100644
--- a/mesh_bsurfaces.py
+++ b/mesh_bsurfaces.py
@@ -75,12 +75,20 @@ class VIEW3D_PT_tools_SURFSK_mesh(Panel):
         row.separator()
         col.operator("gpencil.surfsk_init", text="Initialize")
         col.prop(scn, "SURFSK_object_with_retopology")
-        col.prop(scn, "SURFSK_object_with_strokes")
+        col.prop(scn, "SURFSK_use_annotation")
+        if not scn.SURFSK_use_annotation:
+            col.prop(scn, "SURFSK_object_with_strokes")
         col.separator()
         col.operator("gpencil.surfsk_add_surface", text="Add Surface")
         col.operator("gpencil.surfsk_edit_surface", text="Edit Surface")
-        col.operator("gpencil.surfsk_add_strokes", text="Add Strokes")
-        col.operator("gpencil.surfsk_edit_strokes", text="Edit Strokes")
+        if not scn.SURFSK_use_annotation:
+           col.operator("gpencil.surfsk_add_strokes", text="Add Strokes")
+           col.operator("gpencil.surfsk_edit_strokes", text="Edit Strokes")
+        else:
+           col.operator("gpencil.surfsk_add_annotation", text="Add Annotation")
+        col.separator()
+        col.prop(scn, "SURFSK_edges_U")
+        col.prop(scn, "SURFSK_edges_V")
         col.prop(scn, "SURFSK_cyclic_cross")
         col.prop(scn, "SURFSK_cyclic_follow")
         col.prop(scn, "SURFSK_loops_on_strokes")
@@ -110,11 +118,22 @@ class VIEW3D_PT_tools_SURFSK_curve(Panel):
 
 
 # Returns the type of strokes used
-def get_strokes_type():
+def get_strokes_type(context):
     strokes_type = ""
     strokes_num = 0
 
     # Check if they are grease pencil
+    if context.scene.bsurfaces.SURFSK_use_annotation:
+        try:
+            frame = bpy.data.grease_pencils["Annotations"].layers["Note"].active_frame
+        
+            strokes_num = len(frame.strokes)
+
+            if strokes_num > 0:
+               strokes_type = "GP_ANNOTATION"
+        except:
+            pass
+    
     try:
        gpencil = bpy.context.scene.bsurfaces.SURFSK_object_with_strokes
        layer = gpencil.data.layers[0]
@@ -452,14 +471,15 @@ class GPENCIL_OT_SURFSK_add_surface(Operator):
             except:
                 pass
 
-            bpy.ops.object.delete({"selected_objects": [self.main_object]})
+            #bpy.ops.object.delete({"selected_objects": [self.main_object]})
         else:
             bpy.ops.object.select_all('INVOKE_REGION_WIN', action='DESELECT')
             self.original_curve.select_set(True)
             self.main_object.select_set(True)
             bpy.context.view_layer.objects.active = self.main_object
 
-        bpy.ops.object.editmode_toggle('INVOKE_REGION_WIN')
+        #bpy.ops.object.editmode_toggle('INVOKE_REGION_WIN')
+        bpy.ops.object.mode_set(mode='OBJECT')
 
     # Returns a list with the coords of the points distributed over the splines
     # passed to this method according to the proportions parameter
@@ -3058,7 +3078,6 @@ class GPENCIL_OT_SURFSK_add_surface(Operator):
 
         bsurfaces_props = bpy.context.scene.bsurfaces
         
-        bsurfaces_props.SURFSK_object_with_strokes.select_set(True)
         self.main_object = bsurfaces_props.SURFSK_object_with_retopology
         self.main_object.select_set(True)
         bpy.context.view_layer.objects.active = self.main_object
@@ -3122,13 +3141,26 @@ class GPENCIL_OT_SURFSK_add_surface(Operator):
                 self.crosshatch_surface_execute()
 
             # Delete main splines
-            bpy.ops.object.editmode_toggle('INVOKE_REGION_WIN')
+            #bpy.ops.object.editmode_toggle('INVOKE_REGION_WIN')
+            bpy.ops.object.mode_set(mode='OBJECT')
             bpy.ops.object.delete({"selected_objects": [self.main_splines]})
             
             # Delete grease pencil strokes
             if self.strokes_type == "GP_STROKES" and not self.stopping_errors and not self.keep_strokes:
                 bpy.context.scene.bsurfaces.SURFSK_object_with_strokes.data.layers[0].clear()
-
+                
+            # Delete annotations
+            if self.strokes_type == "GP_ANNOTATION" and not self.stopping_errors and not self.keep_strokes:
+                bpy.data.grease_pencils["Annotations"].layers["Note"].clear()
+
+            bsurfaces_props.SURFSK_edges_U = self.edges_U
+            bsurfaces_props.SURFSK_edges_V = self.edges_V
+            bsurfaces_props.SURFSK_cyclic_cross = self.cyclic_cross
+            bsurfaces_props.SURFSK_cyclic_follow = self.cyclic_follow
+            bsurfaces_props.SURFSK_automatic_join = self.automatic_join
+            bsurfaces_props.SURFSK_loops_on_strokes = self.loops_on_strokes
+            bsurfaces_props.SURFSK_keep_strokes = self.keep_strokes
+            
             bpy.ops.object.select_all('INVOKE_REGION_WIN', action='DESELECT')
             self.main_object.select_set(True)
             bpy.context.view_layer.objects.active = self.main_object
@@ -3148,15 +3180,13 @@ class GPENCIL_OT_SURFSK_add_surface(Operator):
         self.automatic_join = bsurfaces_props.SURFSK_automatic_join
         self.loops_on_strokes = bsurfaces_props.SURFSK_loops_on_strokes
         self.keep_strokes = bsurfaces_props.SURFSK_keep_strokes
-        
+            
+        self.main_object = bsurfaces_props.SURFSK_object_with_retopology
         try:
-            bsurfaces_props.SURFSK_object_with_strokes.select_set(True)
+            self.main_object.select_set(True)
         except:
             self.report({'WARNING'}, "Specify the name of the object with retopology")
             return{"CANCELLED"}
-            
-        self.main_object = bsurfaces_props.SURFSK_object_with_retopology
-        self.main_object.select_set(True)
         bpy.context.view_layer.objects.active = self.main_object
 
         self.main_object_selected_verts_count = int(self.main_object.data.total_vert_sel)
@@ -3165,28 +3195,43 @@ class GPENCIL_OT_SURFSK_add_surface(Operator):
         bpy.ops.wm.context_set_value(data_path='tool_settings.mesh_select_mode',
                                      value='True, False, False')
 
-        self.edges_U = 5
+        self.edges_U = bsurfaces_props.SURFSK_edges_U
 
         if self.loops_on_strokes:
             self.edges_V = 1
         else:
-            self.edges_V = 5
+            self.edges_V = bsurfaces_props.SURFSK_edges_V
 
         self.is_fill_faces = False
         self.stopping_errors = False
         self.last_strokes_splines_coords = []
 
         # Determine the type of the strokes
-        self.strokes_type = get_strokes_type()
+        self.strokes_type = get_strokes_type(context)
 
         # Check if it will be used grease pencil strokes or curves
         # If there are strokes to be used
-        if self.strokes_type == "GP_STROKES" or self.strokes_type == "EXTERNAL_CURVE":
+        if self.strokes_type == "GP_STROKES" or self.strokes_type == "EXTERNAL_CURVE" or self.strokes_type == "GP_ANNOTATION":
             if self.strokes_type == "GP_STROKES":
                 # Convert grease pencil strokes to curve
                 gp = bsurfaces_props.SURFSK_object_with_strokes
                 #bpy.ops.gpencil.convert(type='CURVE', use_link_strokes=False)
-                self.original_curve = conver_gpencil_to_curve(context, gp)
+                self.original_curve = conver_gpencil_to_curve(context, gp, 'GPensil')
+                # XXX gpencil.convert now keep org object as active/selected, *not* newly created curve!
+                # XXX This is far from perfect, but should work in most cases...
+                # self.original_curve = bpy.context.object
+                gplayer_prefix_translated = bpy.app.translations.pgettext_data('GP_Layer')
+                for ob in bpy.context.selected_objects:
+                    if ob != bpy.context.view_layer.objects.active and \
+                       ob.name.startswith((gplayer_prefix_translated, 'GP_Layer')):
+                        self.original_curve = ob
+                self.using_external_curves = False
+                
+            elif self.strokes_type == "GP_ANNOTATION":
+                # Convert grease pencil strokes to curve
+                gp = bpy.data.grease_pencils["Annotations"]
+                #bpy.ops.gpencil.convert(type='CURVE', use_link_strokes=False)
+                self.original_curve = conver_gpencil_to_curve(context, gp, 'Annotation')
                 # XXX gpencil.convert now keep org object as active/selected, *not* newly created curve!
                 # XXX This is far from perfect, but should work in most cases...
                 # self.original_curve = bpy.context.object
@@ -3360,6 +3405,10 @@ class GPENCIL_OT_SURFSK_add_surface(Operator):
             # Delete grease pencil strokes
             if self.strokes_type == "GP_STROKES" and not self.stopping_errors and not self.keep_strokes:
                 bpy.context.scene.bsurfaces.SURFSK_object_with_strokes.data.layers[0].clear()
+                
+            # Delete grease pencil strokes
+            if self.strokes_type == "GP_ANNOTATION" and not self.stopping_errors and not self.keep_strokes:
+                bpy.data.grease_pencils["Annotations"].layers["Note"].clear()
             
             bpy.ops.object.select_all('INVOKE_REGION_WIN', action='DESELECT')
             self.main_object.select_set(True)
@@ -3425,30 +3474,45 @@ class GPENCIL_OT_SURFSK_init(Operator):
     active_object: PointerProperty(type=bpy.types.Object)
 
     def execute(self, context):
+    
+        bs = bpy.context.scene.bsurfaces
+    
         if bpy.ops.object.mode_set.poll():
              bpy.ops.object.mode_set(mode='OBJECT')
-        bpy.ops.object.select_all('INVOKE_REGION_WIN', action='DESELECT')
-        mesh = bpy.data.meshes.new('BSurfaceMesh')
-        mesh_object = object_utils.object_data_add(context, mesh, operator=None)
-        mesh_object.select_set(True)
-        bpy.context.view_layer.objects.active = mesh_object
-        bpy.ops.object.modifier_add(type='SHRINKWRAP')
-        modifier = mesh_object.modifiers["Shrinkwrap"]
-        if self.active_object is not None:
-            modifier.target = self.active_object
-            modifier.wrap_method = 'TARGET_PROJECT'
-            modifier.wrap_mode = 'OUTSIDE_SURFACE'
-            #modifier.offset = 0.05
         
-        bpy.ops.object.gpencil_add(radius=1.0, view_align=False, location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0), type='EMPTY')
-        bpy.context.scene.tool_settings.gpencil_stroke_placement_view3d = 'SURFACE'
-        gpencil_object = bpy.context.scene.objects[bpy.context.scene.objects[-1].name]
-        gpencil_object.select_set(True)
-        bpy.context.view_layer.objects.active = gpencil_object
-        bpy.ops.object.mode_set(mode='PAINT_GPENCIL')
+        if bs.SURFSK_object_with_retopology == None:
+            bpy.ops.object.select_all('INVOKE_REGION_WIN', action='DESELECT')
+            mesh = bpy.data.meshes.new('BSurfaceMesh')
+            mesh_object = object_utils.object_data_add(context, mesh, operator=None)
+            mesh_object.select_set(True)
+            mesh_object.show_all_edges = True
+            mesh_object.show_in_front = True
+            mesh_object.display_type = 'SOLID'
+            mesh_object.show_wire = True
+            bpy.context.view_layer.objects.active = mesh_object
+            bpy.ops.object.modifier_add(type='SHRINKWRAP')
+            modifier = mesh_object.modifiers["Shrinkwrap"]
+            if self.active_object is not None:
+                modifier.target = self.active_object
+                modifier.wrap_method = 'TARGET_PROJECT'
+                modifier.wrap_mode = 'OUTSIDE_SURFACE'
+                #modifier.offset = 0.05
+            
+            bpy.context.scene.bsurfaces.SURFSK_object_with_retopology = mesh_object
+        
+        if not context.scene.bsurfaces.SURFSK_use_annotation and bs.SURFSK_object_with_strokes == None:
+            bpy.ops.object.select_all('INVOKE_REGION_WIN', action='DESELECT')
+            bpy.ops.object.gpencil_add(radius=1.0, view_align=False, location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0), type='EMPTY')
+            bpy.context.scene.tool_settings.gpencil_stroke_placement_view3d = 'SURFACE'
+            gpencil_object = bpy.context.scene.objects[bpy.context.scene.objects[-1].name]
+            gpencil_object.select_set(True)
+            bpy.context.view_layer.objects.active = gpencil_object
+            bpy.ops.object.mode_set(mode='PAINT_GPENCIL')
+            bpy.context.scene.bsurfaces.SURFSK_object_with_strokes = gpencil_object
         
-        bpy.context.scene.bsurfaces.SURFSK_object_with_retopology = mesh_object
-        bpy.context.scene.bsurfaces.SURFSK_object_with_strokes = gpencil_object
+        if context.scene.bsurfaces.SURFSK_use_annotation:
+            bpy.ops.wm.tool_set_by_id(name="builtin.annotate")
+            bpy.context.scene.tool_settings.annotation_stroke_placement_view3d = 'SURFACE'
 
         return {"FINISHED"}
 
@@ -3484,7 +3548,7 @@ class GPENCIL_OT_SURFSK_edit_surface(Operator):
 
         return {"FINISHED"}
 
-# Edit strokes operator
+# Add strokes operator
 class GPENCIL_OT_SURFSK_add_strokes(Operator):
     bl_idname = "gpencil.surfsk_add_strokes"
     bl_label = "Bsurfaces add strokes"
@@ -3492,7 +3556,7 @@ class GPENCIL_OT_SURFSK_add_strokes(Operator):
 
     def execute(self, context):
         # Determine the type of the strokes
-        self.strokes_type = get_strokes_type()
+        self.strokes_type = get_strokes_type(context)
         # Check if strokes are grease pencil strokes or a curves object
         selected_objs = bpy.context.selected_objects
         if self.strokes_type == "EXTERNAL_CURVE" or self.strokes_type == "SINGLE_CURVE_STROKE_NO_SELECTION":
@@ -3525,7 +3589,6 @@ class GPENCIL_OT_SURFSK_add_strokes(Operator):
 
         return {"FINISHED"}
 
-
 # Edit strokes operator
 class GPENCIL_OT_SURFSK_edit_strokes(Operator):
     bl_idname = "gpencil.surfsk_edit_strokes"
@@ -3534,7 +3597,7 @@ class GPENCIL_OT_SURFSK_edit_strokes(Operator):
 
     def execute(self, context):
         # Determine the type of the strokes
-        self.strokes_type = get_strokes_type()
+        self.strokes_type = get_strokes_type(context)
         # Check if strokes are grease pencil strokes or a curves object
         selected_objs = bpy.context.selected_objects
         if self.strokes_type == "EXTERNAL_CURVE" or self.strokes_type == "SINGLE_CURVE_STROKE_NO_SELECTION":
@@ -3554,7 +3617,7 @@ class GPENCIL_OT_SURFSK_edit_strokes(Operator):
             bpy.ops.object.editmode_toggle('INVOKE_REGION_WIN')
             #bpy.ops.gpencil.convert('INVOKE_REGION_WIN', type='CURVE', use_link_strokes=False)
             gp = bpy.context.scene.bsurfaces.SURFSK_object_with_strokes
-            conver_gpencil_to_curve(context, gp)
+            conver_gpencil_to_curve(context, gp, 'GPensil')
             for ob in bpy.context.selected_objects:
                     if ob != bpy.context.view_layer.objects.active and ob.name.startswith("GP_Layer"):
                         ob_gp_strokes = ob
@@ -3602,6 +3665,23 @@ class GPENCIL_OT_SURFSK_edit_strokes(Operator):
 
         return {"FINISHED"}
 
+# Add annotation
+class GPENCIL_OT_SURFSK_add_annotation(Operator):
+    bl_idname = "gpencil.surfsk_add_annotation"
+    bl_label = "Bsurfaces add annotation"
+    bl_description = "Add annotation"
+
+    def execute(self, context):
+        bpy.ops.wm.tool_set_by_id(name="builtin.annotate")
+        bpy.context.scene.tool_settings.annotation_stroke_placement_view3d = 'SURFACE'
+
+        return{"FINISHED"}
+
+    def invoke(self, context, event):
+        
+        self.execute(context)
+
+        return {"FINISHED"}
 
 class CURVE_OT_SURFSK_reorder_splines(Operator):
     bl_idname = "curve.surfsk_reorder_splines"
@@ -3987,13 +4067,18 @@ def update_panel(self, context):
         print("\n[{}]\n{}\n\nError:\n{}".format(__name__, message, e))
         pass
         
-def conver_gpencil_to_curve(context, pencil):
+def conver_gpencil_to_curve(context, pencil, type):
     newCurve = bpy.data.curves.new('gpencil_curve', type='CURVE')  # curvedatablock
     newCurve.dimensions = '3D'
     CurveObject = object_utils.object_data_add(context, newCurve)  # place in active scene
     
-    for i, stroke in enumerate(pencil.data.layers[0].active_frame.strokes):
-        stroke_points = pencil.data.layers[0].active_frame.strokes[i].points
+    if type == 'GPensil':
+        strokes = pencil.data.layers[0].active_frame.strokes
+    elif type == 'Annotation':
+        strokes = bpy.data.grease_pencils["Annotations"].layers["Note"].active_frame.strokes
+    
+    for i, stroke in enumerate(strokes):
+        stroke_points = strokes[i].points
         data_list = [ (point.co.x, point.co.y, point.co.z) 
                         for point in stroke_points ]
         points_to_add = len(data_list)-1
@@ -4035,6 +4120,24 @@ class BsurfPreferences(AddonPreferences):
 
 # Properties
 class BsurfacesProps(PropertyGroup):
+    SURFSK_use_annotation: BoolProperty(
+                name="Use Annotation",
+                default=True
+                )
+    SURFSK_edges_U: IntProperty(
+                    name="Cross",
+                    description="Number of face-loops crossing the strokes",
+                    default=5,
+                    min=1,
+                    max=200
+                    )
+    SURFSK_edges_V: IntProperty(
+                    name="Follow",
+                    description="Number of face-loops following the strokes",
+                    default=1,
+                    min=1,
+                    max=200
+                    )
     SURFSK_cyclic_cross: BoolProperty(
                 name="Cyclic Cross",
                 description="Make cyclic the face-loops crossing the strokes",
@@ -4083,6 +4186,7 @@ classes = (
     GPENCIL_OT_SURFSK_edit_surface,    
     GPENCIL_OT_SURFSK_add_strokes,
     GPENCIL_OT_SURFSK_edit_strokes,
+    GPENCIL_OT_SURFSK_add_annotation,
     CURVE_OT_SURFSK_reorder_splines,
     CURVE_OT_SURFSK_first_points,
     BsurfPreferences,
-- 
GitLab