From 288fa42419d70dd7709d15f00e8a6bee10c24e89 Mon Sep 17 00:00:00 2001
From: "Spivak Vladimir (cwolf3d)" <cwolf3d@gmail.com>
Date: Sun, 3 Feb 2019 03:51:50 +0200
Subject: [PATCH] Added (in add_curve_simple) a type of curve creation.
 Implemented the ability to add curves (add_curve_aceous_galore) in edit mode.

---
 add_curve_extra_objects/__init__.py           |   7 +-
 .../add_curve_aceous_galore.py                | 114 ++--
 add_curve_extra_objects/add_curve_simple.py   | 612 ++++++++++--------
 3 files changed, 400 insertions(+), 333 deletions(-)

diff --git a/add_curve_extra_objects/__init__.py b/add_curve_extra_objects/__init__.py
index 383058132..d7fbe2a49 100644
--- a/add_curve_extra_objects/__init__.py
+++ b/add_curve_extra_objects/__init__.py
@@ -244,13 +244,12 @@ class INFO_MT_curve_knots_add(Menu):
 
 # Define "Extras" menus
 def menu_func(self, context):
-    if context.mode != 'OBJECT':
-        # fix in D2142 will allow to work in EDIT_CURVE
-        return None
-
     layout = self.layout
 
     layout.operator_menu_enum("curve.curveaceous_galore", "ProfileType", icon='CURVE_DATA')
+    if context.mode != 'OBJECT':
+        # fix in D2142 will allow to work in EDIT_CURVE
+        return None
     layout.operator_menu_enum("curve.spirals", "spiral_type", icon='CURVE_DATA')
     layout.separator()
 
diff --git a/add_curve_extra_objects/add_curve_aceous_galore.py b/add_curve_extra_objects/add_curve_aceous_galore.py
index 3a0bdaf38..2f8fc3de5 100644
--- a/add_curve_extra_objects/add_curve_aceous_galore.py
+++ b/add_curve_extra_objects/add_curve_aceous_galore.py
@@ -20,7 +20,7 @@
 bl_info = {
     "name": "Curveaceous Galore!",
     "author": "Jimmy Hazevoet, testscreenings",
-    "version": (0, 2, 2),
+    "version": (0, 2, 3),
     "blender": (2, 80),
     "location": "View3D > Add > Curve",
     "description": "Adds many different types of Curves",
@@ -32,11 +32,13 @@ bl_info = {
 """
 
 import bpy
+from bpy_extras import object_utils
 from bpy.props import (
         BoolProperty,
         EnumProperty,
         FloatProperty,
         IntProperty,
+        FloatVectorProperty
         )
 from mathutils import Matrix, Vector
 from bpy.types import Operator
@@ -717,35 +719,17 @@ def NoiseCurve(type=0, number=100, length=2.0, size=0.5,
 # ------------------------------------------------------------
 # calculates the matrix for the new object
 # depending on user pref
-def align_matrix(context):
-
-    loc = Matrix.Translation(context.scene.cursor_location)
+def align_matrix(context, location):
+    loc = Matrix.Translation(location)
     obj_align = context.preferences.edit.object_align
-
     if (context.space_data.type == 'VIEW_3D' and
-                obj_align == 'VIEW'):
+            obj_align == 'VIEW'):
         rot = context.space_data.region_3d.view_matrix.to_3x3().inverted().to_4x4()
     else:
         rot = Matrix()
-
     align_matrix = loc @ rot
-    return align_matrix
-
-
-# ------------------------------------------------------------
-# Curve creation functions, sets bezierhandles to auto
-def setBezierHandles(obj, mode='AUTO'):
-    scene = bpy.context.scene
-
-    if obj.type != 'CURVE':
-        return
 
-    #scene.objects.active = obj
-    #bpy.ops.object.mode_set(mode='EDIT', toggle=True)
-    #bpy.ops.curve.select_all(action='SELECT')
-    #obj.select_set(action='SELECT')
-    #bpy.ops.curve.handle_type_set(type=mode)
-    #bpy.ops.object.mode_set(mode='OBJECT', toggle=True)
+    return align_matrix
 
 # get array of vertcoordinates according to splinetype
 def vertsToPoints(Verts, splineType):
@@ -773,17 +757,31 @@ def vertsToPoints(Verts, splineType):
 
 # create new CurveObject from vertarray and splineType
 def createCurve(context, vertArray, self, align_matrix):
-    scene = bpy.context.scene
-
     # output splineType 'POLY' 'NURBS' 'BEZIER'
     splineType = self.outputType
-
+    
     # GalloreType as name
     name = self.ProfileType
-
-    # create curve
-    newCurve = bpy.data.curves.new(name, type='CURVE')
-    newSpline = newCurve.splines.new(type=splineType)
+    
+    # create object
+    if bpy.context.mode == 'EDIT_CURVE':
+        Curve = context.active_object
+        newSpline = Curve.data.splines.new(type=splineType)          # spline
+        Curve.matrix_world = align_matrix  # apply matrix
+        Curve.rotation_euler = self.rotation_euler
+    else:
+        # create curve
+        newCurve = bpy.data.curves.new(name, type='CURVE')  # curve data block
+        newSpline = newCurve.splines.new(type=splineType)          # spline
+
+        # set curveOptions
+        newCurve.dimensions = self.shape
+        
+        # create object with newCurve
+        SimpleCurve = object_utils.object_data_add(context, newCurve, operator=self)  # place in active scene
+        SimpleCurve.select_set(True)
+        SimpleCurve.matrix_world = align_matrix  # apply matrix
+        SimpleCurve.rotation_euler = self.rotation_euler
 
     # create spline from vertarray
     if splineType == 'BEZIER':
@@ -798,32 +796,15 @@ def createCurve(context, vertArray, self, align_matrix):
         newSpline.use_endpoint_u = True
 
     # set curveOptions
-    newCurve.dimensions = self.shape
     newSpline.use_cyclic_u = self.use_cyclic_u
     newSpline.use_endpoint_u = self.endp_u
     newSpline.order_u = self.order_u
-
-    # create object with newCurve
-    new_obj = bpy.data.objects.new(name, newCurve)
-    scene.collection.objects.link(new_obj)
-    new_obj.select_set(True)
-    #scene.objects.active = new_obj
-    new_obj.matrix_world = align_matrix
-
-    # set bezierhandles
-    #if splineType == 'BEZIER':
-        #bpy.ops.curve.handle_type_set(type='AUTO')
-        #setBezierHandles(new_obj, self.handleType)
-
     return
 
 
 # ------------------------------------------------------------
 # Main Function
 def main(context, self, align_matrix):
-    # deselect all objects
-    #bpy.ops.object.select_all(action='DESELECT')
-
     # options
     proType = self.ProfileType
     splineType = self.outputType
@@ -934,14 +915,14 @@ def main(context, self, align_matrix):
     return
 
 
-class Curveaceous_galore(Operator):
+class Curveaceous_galore(Operator, object_utils.AddObjectHelper):
     bl_idname = "curve.curveaceous_galore"
     bl_label = "Curve Profiles"
     bl_description = "Construct many types of curves"
     bl_options = {'REGISTER', 'UNDO', 'PRESET'}
 
     # align_matrix for the invoke
-    align_matrix = None
+    align_matrix : Matrix()
 
     # general properties
     ProfileType : EnumProperty(
@@ -1294,6 +1275,19 @@ class Curveaceous_galore(Operator):
             min=0,
             description="Random Seed"
             )
+    # Line properties
+    startlocation : FloatVectorProperty(
+            name="",
+            description="Start location",
+            default=(0.0, 0.0, 0.0),
+            subtype='TRANSLATION'
+            )
+    rotation_euler : FloatVectorProperty(
+            name="",
+            description="Rotation",
+            default=(0.0, 0.0, 0.0),
+            subtype='EULER'
+            )
 
     def draw(self, context):
         layout = self.layout
@@ -1413,16 +1407,26 @@ class Curveaceous_galore(Operator):
             col.prop(self, "noiseBasis")
             col.prop(self, "noiseSeed")
 
+        # output options
         col = layout.column()
         col.label(text="Output Curve Type:")
         col.row().prop(self, "outputType", expand=True)
-
-        # output options
+        
         if self.outputType == 'NURBS':
             col.prop(self, 'order_u')
         elif self.outputType == 'BEZIER':
             col.row().prop(self, 'handleType', expand=True)
 
+        #col = layout.column()
+        #col.row().prop(self, "use_cyclic_u", expand=True)
+
+        box = layout.box()
+        box.label(text="Location:")
+        box.prop(self, "startlocation")
+        box = layout.box()
+        box.label(text="Rotation:")
+        box.prop(self, "rotation_euler")
+
     @classmethod
     def poll(cls, context):
         return context.scene is not None
@@ -1452,6 +1456,7 @@ class Curveaceous_galore(Operator):
                 self.use_cyclic_u = True
 
         # main function
+        self.align_matrix = align_matrix(context, self.startlocation)
         main(context, self, self.align_matrix or Matrix())
 
         # restore pre operator undo state
@@ -1459,13 +1464,6 @@ class Curveaceous_galore(Operator):
 
         return {'FINISHED'}
 
-    def invoke(self, context, event):
-        # store creation_matrix
-        self.align_matrix = align_matrix(context)
-        self.execute(context)
-
-        return {'FINISHED'}
-
 # Register
 classes = [
     Curveaceous_galore
diff --git a/add_curve_extra_objects/add_curve_simple.py b/add_curve_extra_objects/add_curve_simple.py
index 6cc0ab3a2..39a5f1592 100644
--- a/add_curve_extra_objects/add_curve_simple.py
+++ b/add_curve_extra_objects/add_curve_simple.py
@@ -19,7 +19,7 @@
 bl_info = {
     "name": "Simple Curve",
     "author": "Spivak Vladimir (http://cwolf3d.korostyshev.net)",
-    "version": (1, 5, 4),
+    "version": (1, 5, 5),
     "blender": (2, 80, 0),
     "location": "View3D > Add > Curve",
     "description": "Adds Simple Curve",
@@ -32,6 +32,7 @@ bl_info = {
 # ------------------------------------------------------------
 
 import bpy
+from bpy_extras import object_utils
 from bpy.types import (
         Operator,
         Menu,
@@ -392,56 +393,74 @@ def align_matrix(context, location):
 
     return align_matrix
 
+# ------------------------------------------------------------
+# get array of vertcoordinates according to splinetype
+def vertsToPoints(Verts, splineType):
+
+    # main vars
+    vertArray = []
+
+    # array for BEZIER spline output (V3)
+    if splineType == 'BEZIER':
+        for v in Verts:
+            vertArray += v
+
+    # array for nonBEZIER output (V4)
+    else:
+        for v in Verts:
+            vertArray += v
+            if splineType == 'NURBS':
+                # for nurbs w=1
+                vertArray.append(1)
+            else:
+                # for poly w=0
+                vertArray.append(0)
+    return vertArray
+
 
 # ------------------------------------------------------------
 # Main Function
 
 def main(context, self, align_matrix):
-    # create object
-    scene = bpy.context.scene
+    # output splineType 'POLY' 'NURBS' 'BEZIER'
+    splineType = self.outputType
     
+    # create object
     if bpy.context.mode == 'EDIT_CURVE':
-        newCurve = context.active_object.data
-        newSpline = newCurve.splines.new('BEZIER')          # spline
+        Curve = context.active_object
+        newSpline = Curve.data.splines.new(type=splineType)          # spline
+        Curve.matrix_world = align_matrix  # apply matrix
+        Curve.rotation_euler = self.Simple_rotation_euler
     else:
         name = self.Simple_Type  # Type as name
         # create curve
     
         newCurve = bpy.data.curves.new(name, type='CURVE')  # curvedatablock
-        newSpline = newCurve.splines.new('BEZIER')          # spline
+        newSpline = newCurve.splines.new(type=splineType)          # spline
 
         # set curveOptions
         newCurve.dimensions = self.shape
         
         # create object with newCurve
-        SimpleCurve = bpy.data.objects.new(name, newCurve)  # object
-        scene.collection.objects.link(SimpleCurve)  # place in active scene
+        SimpleCurve = object_utils.object_data_add(context, newCurve, operator=self)  # place in active scene
         SimpleCurve.select_set(True)
         SimpleCurve.matrix_world = align_matrix  # apply matrix
         SimpleCurve.rotation_euler = self.Simple_rotation_euler
 
-    
-    newSpline.use_endpoint_u = True
-
     sides = abs(int((self.Simple_endangle - self.Simple_startangle) / 90))
 
     # get verts
     if self.Simple_Type == 'Point':
         verts = SimplePoint()
-        newSpline.use_cyclic_u = False
 
     if self.Simple_Type == 'Line':
         verts = SimpleLine(self.Simple_startlocation, self.Simple_endlocation)
-        newSpline.use_cyclic_u = False
-        newCurve.dimensions = '3D'
 
     if self.Simple_Type == 'Distance':
         verts = SimpleDistance(self.Simple_length, self.Simple_center)
-        newSpline.use_cyclic_u = False
 
     if self.Simple_Type == 'Angle':
         verts = SimpleAngle(self.Simple_length, self.Simple_angle)
-        newSpline.use_cyclic_u = False
 
     if self.Simple_Type == 'Circle':
         if self.Simple_sides < 4:
@@ -449,11 +468,9 @@ def main(context, self, align_matrix):
         if self.Simple_radius == 0:
             return {'FINISHED'}
         verts = SimpleCircle(self.Simple_sides, self.Simple_radius)
-        newSpline.use_cyclic_u = True
 
     if self.Simple_Type == 'Ellipse':
         verts = SimpleEllipse(self.Simple_a, self.Simple_b)
-        newSpline.use_cyclic_u = True
 
     if self.Simple_Type == 'Arc':
         if self.Simple_sides < sides:
@@ -464,7 +481,6 @@ def main(context, self, align_matrix):
                     self.Simple_sides, self.Simple_radius,
                     self.Simple_startangle, self.Simple_endangle
                     )
-        newSpline.use_cyclic_u = False
 
     if self.Simple_Type == 'Sector':
         if self.Simple_sides < sides:
@@ -475,7 +491,6 @@ def main(context, self, align_matrix):
                     self.Simple_sides, self.Simple_radius,
                     self.Simple_startangle, self.Simple_endangle
                     )
-        newSpline.use_cyclic_u = True
 
     if self.Simple_Type == 'Segment':
         if self.Simple_sides < sides:
@@ -492,20 +507,17 @@ def main(context, self, align_matrix):
                     self.Simple_sides, self.Simple_b, self.Simple_a,
                     self.Simple_startangle, self.Simple_endangle
                     )
-        newSpline.use_cyclic_u = True
 
     if self.Simple_Type == 'Rectangle':
         verts = SimpleRectangle(
                     self.Simple_width, self.Simple_length,
                     self.Simple_rounded, self.Simple_center
                     )
-        newSpline.use_cyclic_u = True
 
     if self.Simple_Type == 'Rhomb':
         verts = SimpleRhomb(
                     self.Simple_width, self.Simple_length, self.Simple_center
                     )
-        newSpline.use_cyclic_u = True
 
     if self.Simple_Type == 'Polygon':
         if self.Simple_sides < 3:
@@ -513,7 +525,6 @@ def main(context, self, align_matrix):
         verts = SimplePolygon(
                     self.Simple_sides, self.Simple_radius
                     )
-        newSpline.use_cyclic_u = True
 
     if self.Simple_Type == 'Polygon_ab':
         if self.Simple_sides < 3:
@@ -521,248 +532,258 @@ def main(context, self, align_matrix):
         verts = SimplePolygon_ab(
                     self.Simple_sides, self.Simple_a, self.Simple_b
                     )
-        newSpline.use_cyclic_u = True
 
     if self.Simple_Type == 'Trapezoid':
         verts = SimpleTrapezoid(
                     self.Simple_a, self.Simple_b, self.Simple_h, self.Simple_center
                     )
-        newSpline.use_cyclic_u = True
 
-    vertArray = []
-    for v in verts:
-        vertArray += v
-
-    newSpline.bezier_points.add(int(len(vertArray) * 0.333333333))
-    newSpline.bezier_points.foreach_set('co', vertArray)
+    # set curveOptions
+    newSpline.use_cyclic_u = self.use_cyclic_u
+    newSpline.use_endpoint_u = self.endp_u
+    newSpline.order_u = self.order_u
+    
+    # turn verts into array
+    vertArray = vertsToPoints(verts, splineType)
+        
+    # create spline from vertarray
+    if splineType == 'BEZIER':
+        newSpline.bezier_points.add(int(len(vertArray) * 0.33))
+        newSpline.bezier_points.foreach_set('co', vertArray)
+        all_points = [p for p in newSpline.bezier_points]
+        for point in newSpline.bezier_points:
+            point.handle_right_type = self.handleType
+            point.handle_left_type = self.handleType
+    else:
+        newSpline.points.add(int(len(vertArray) * 0.25 - 1))
+        newSpline.points.foreach_set('co', vertArray)
+        newSpline.use_endpoint_u = True
+        all_points = [p for p in newSpline.points]
+    
+    n = len(all_points)
 
-    all_points = [p for p in newSpline.bezier_points]
     d = 2 * 0.27606262
-    n = 0
-    for p in all_points:
-        p.handle_right_type = 'VECTOR'
-        p.handle_left_type = 'VECTOR'
-        n += 1
-
-    if self.Simple_Type == 'Circle' or self.Simple_Type == 'Arc' or \
-            self.Simple_Type == 'Sector' or self.Simple_Type == 'Segment' or \
-            self.Simple_Type == 'Ellipse':
 
-        for p in all_points:
-            p.handle_right_type = 'FREE'
-            p.handle_left_type = 'FREE'
+    if splineType == 'BEZIER':
+        if self.Simple_Type == 'Circle' or self.Simple_Type == 'Arc' or \
+           self.Simple_Type == 'Sector' or self.Simple_Type == 'Segment' or \
+           self.Simple_Type == 'Ellipse':
 
-    if self.Simple_Type == 'Circle':
-        i = 0
-        for p1 in all_points:
-            if i != n - 1:
-                p2 = all_points[i + 1]
-                u1 = asin(p1.co.y / self.Simple_radius)
-                u2 = asin(p2.co.y / self.Simple_radius)
-                if p1.co.x > 0 and p2.co.x < 0:
-                    u1 = acos(p1.co.x / self.Simple_radius)
-                    u2 = acos(p2.co.x / self.Simple_radius)
-                elif p1.co.x < 0 and p2.co.x > 0:
-                    u1 = acos(p1.co.x / self.Simple_radius)
-                    u2 = acos(p2.co.x / self.Simple_radius)
-                u = u2 - u1
-                if u < 0:
-                    u = -u
-                l = 4 / 3 * tan(1 / 4 * u) * self.Simple_radius
-                v1 = Vector((-p1.co.y, p1.co.x, 0))
-                v1.normalize()
-                v2 = Vector((-p2.co.y, p2.co.x, 0))
-                v2.normalize()
-                vh1 = v1 * l
-                vh2 = v2 * l
-                v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
-                v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
-                p1.handle_right = v1
-                p2.handle_left = v2
-            if i == n - 1:
-                p2 = all_points[0]
-                u1 = asin(p1.co.y / self.Simple_radius)
-                u2 = asin(p2.co.y / self.Simple_radius)
-                if p1.co.x > 0 and p2.co.x < 0:
-                    u1 = acos(p1.co.x / self.Simple_radius)
-                    u2 = acos(p2.co.x / self.Simple_radius)
-                elif p1.co.x < 0 and p2.co.x > 0:
-                    u1 = acos(p1.co.x / self.Simple_radius)
-                    u2 = acos(p2.co.x / self.Simple_radius)
-                u = u2 - u1
-                if u < 0:
-                    u = -u
-                l = 4 / 3 * tan(1 / 4 * u) * self.Simple_radius
-                v1 = Vector((-p1.co.y, p1.co.x, 0))
-                v1.normalize()
-                v2 = Vector((-p2.co.y, p2.co.x, 0))
-                v2.normalize()
-                vh1 = v1 * l
-                vh2 = v2 * l
-                v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
-                v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
-                p1.handle_right = v1
-                p2.handle_left = v2
-            i += 1
-
-    if self.Simple_Type == 'Ellipse':
-        all_points[0].handle_right = Vector((self.Simple_a, self.Simple_b * d, 0))
-        all_points[0].handle_left = Vector((self.Simple_a, -self.Simple_b * d, 0))
-        all_points[1].handle_right = Vector((-self.Simple_a * d, self.Simple_b, 0))
-        all_points[1].handle_left = Vector((self.Simple_a * d, self.Simple_b, 0))
-        all_points[2].handle_right = Vector((-self.Simple_a, -self.Simple_b * d, 0))
-        all_points[2].handle_left = Vector((-self.Simple_a, self.Simple_b * d, 0))
-        all_points[3].handle_right = Vector((self.Simple_a * d, -self.Simple_b, 0))
-        all_points[3].handle_left = Vector((-self.Simple_a * d, -self.Simple_b, 0))
-
-    if self.Simple_Type == 'Arc':
-        i = 0
-        for p1 in all_points:
-            if i != n - 1:
-                p2 = all_points[i + 1]
-                u1 = asin(p1.co.y / self.Simple_radius)
-                u2 = asin(p2.co.y / self.Simple_radius)
-                if p1.co.x > 0 and p2.co.x < 0:
-                    u1 = acos(p1.co.x / self.Simple_radius)
-                    u2 = acos(p2.co.x / self.Simple_radius)
-                elif p1.co.x < 0 and p2.co.x > 0:
-                    u1 = acos(p1.co.x / self.Simple_radius)
-                    u2 = acos(p2.co.x / self.Simple_radius)
-                u = u2 - u1
-                if u < 0:
-                    u = -u
-                l = 4 / 3 * tan(1 / 4 * u) * self.Simple_radius
-                v1 = Vector((-p1.co.y, p1.co.x, 0))
-                v1.normalize()
-                v2 = Vector((-p2.co.y, p2.co.x, 0))
-                v2.normalize()
-                vh1 = v1 * l
-                vh2 = v2 * l
-                if self.Simple_startangle < self.Simple_endangle:
-                    v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
-                    v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
-                    p1.handle_right = v1
-                    p2.handle_left = v2
-                else:
-                    v1 = Vector((p1.co.x, p1.co.y, 0)) - vh1
-                    v2 = Vector((p2.co.x, p2.co.y, 0)) + vh2
-                    p1.handle_right = v1
-                    p2.handle_left = v2
-            i += 1
-
-    if self.Simple_Type == 'Sector':
-        i = 0
-        for p1 in all_points:
-            if i == 0:
-                p1.handle_right_type = 'VECTOR'
-                p1.handle_left_type = 'VECTOR'
-            elif i != n - 1:
-                p2 = all_points[i + 1]
-                u1 = asin(p1.co.y / self.Simple_radius)
-                u2 = asin(p2.co.y / self.Simple_radius)
-                if p1.co.x > 0 and p2.co.x < 0:
-                    u1 = acos(p1.co.x / self.Simple_radius)
-                    u2 = acos(p2.co.x / self.Simple_radius)
-                elif p1.co.x < 0 and p2.co.x > 0:
-                    u1 = acos(p1.co.x / self.Simple_radius)
-                    u2 = acos(p2.co.x / self.Simple_radius)
-                u = u2 - u1
-                if u < 0:
-                    u = -u
-                l = 4 / 3 * tan(1 / 4 * u) * self.Simple_radius
-                v1 = Vector((-p1.co.y, p1.co.x, 0))
-                v1.normalize()
-                v2 = Vector((-p2.co.y, p2.co.x, 0))
-                v2.normalize()
-                vh1 = v1 * l
-                vh2 = v2 * l
-                if self.Simple_startangle < self.Simple_endangle:
-                    v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
-                    v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
-                    p1.handle_right = v1
-                    p2.handle_left = v2
-                else:
-                    v1 = Vector((p1.co.x, p1.co.y, 0)) - vh1
-                    v2 = Vector((p2.co.x, p2.co.y, 0)) + vh2
-                    p1.handle_right = v1
-                    p2.handle_left = v2
-            i += 1
+            for p in all_points:
+                p.handle_right_type = 'FREE'
+                p.handle_left_type = 'FREE'
 
-    if self.Simple_Type == 'Segment':
-        i = 0
-        if self.Simple_a > self.Simple_b:
-            Segment_a = self.Simple_a
-            Segment_b = self.Simple_b
-        if self.Simple_a < self.Simple_b:
-            Segment_b = self.Simple_a
-            Segment_a = self.Simple_b
-        for p1 in all_points:
-            if i < n / 2 - 1:
-                p2 = all_points[i + 1]
-                u1 = asin(p1.co.y / Segment_a)
-                u2 = asin(p2.co.y / Segment_a)
-                if p1.co.x > 0 and p2.co.x < 0:
-                    u1 = acos(p1.co.x / Segment_a)
-                    u2 = acos(p2.co.x / Segment_a)
-                elif p1.co.x < 0 and p2.co.x > 0:
-                    u1 = acos(p1.co.x / Segment_a)
-                    u2 = acos(p2.co.x / Segment_a)
-                u = u2 - u1
-                if u < 0:
-                    u = -u
-                l = 4 / 3 * tan(1 / 4 * u) * Segment_a
-                v1 = Vector((-p1.co.y, p1.co.x, 0))
-                v1.normalize()
-                v2 = Vector((-p2.co.y, p2.co.x, 0))
-                v2.normalize()
-                vh1 = v1 * l
-                vh2 = v2 * l
-                if self.Simple_startangle < self.Simple_endangle:
+        if self.Simple_Type == 'Circle':
+            i = 0
+            for p1 in all_points:
+                if i != (n - 1):
+                    p2 = all_points[i + 1]
+                    u1 = asin(p1.co.y / self.Simple_radius)
+                    u2 = asin(p2.co.y / self.Simple_radius)
+                    if p1.co.x > 0 and p2.co.x < 0:
+                        u1 = acos(p1.co.x / self.Simple_radius)
+                        u2 = acos(p2.co.x / self.Simple_radius)
+                    elif p1.co.x < 0 and p2.co.x > 0:
+                        u1 = acos(p1.co.x / self.Simple_radius)
+                        u2 = acos(p2.co.x / self.Simple_radius)
+                    u = u2 - u1
+                    if u < 0:
+                        u = -u
+                    l = 4 / 3 * tan(1 / 4 * u) * self.Simple_radius
+                    v1 = Vector((-p1.co.y, p1.co.x, 0))
+                    v1.normalize()
+                    v2 = Vector((-p2.co.y, p2.co.x, 0))
+                    v2.normalize()
+                    vh1 = v1 * l
+                    vh2 = v2 * l
                     v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
                     v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
                     p1.handle_right = v1
                     p2.handle_left = v2
-                else:
-                    v1 = Vector((p1.co.x, p1.co.y, 0)) - vh1
-                    v2 = Vector((p2.co.x, p2.co.y, 0)) + vh2
-                    p1.handle_right = v1
-                    p2.handle_left = v2
-            elif i != n / 2 - 1 and i != n - 1:
-                p2 = all_points[i + 1]
-                u1 = asin(p1.co.y / Segment_b)
-                u2 = asin(p2.co.y / Segment_b)
-                if p1.co.x > 0 and p2.co.x < 0:
-                    u1 = acos(p1.co.x / Segment_b)
-                    u2 = acos(p2.co.x / Segment_b)
-                elif p1.co.x < 0 and p2.co.x > 0:
-                    u1 = acos(p1.co.x / Segment_b)
-                    u2 = acos(p2.co.x / Segment_b)
-                u = u2 - u1
-                if u < 0:
-                    u = -u
-                l = 4 / 3 * tan(1 / 4 * u) * Segment_b
-                v1 = Vector((-p1.co.y, p1.co.x, 0))
-                v1.normalize()
-                v2 = Vector((-p2.co.y, p2.co.x, 0))
-                v2.normalize()
-                vh1 = v1 * l
-                vh2 = v2 * l
-                if self.Simple_startangle < self.Simple_endangle:
-                    v1 = Vector((p1.co.x, p1.co.y, 0)) - vh1
-                    v2 = Vector((p2.co.x, p2.co.y, 0)) + vh2
-                    p1.handle_right = v1
-                    p2.handle_left = v2
-                else:
+                if i == (n - 1):
+                    p2 = all_points[0]
+                    u1 = asin(p1.co.y / self.Simple_radius)
+                    u2 = asin(p2.co.y / self.Simple_radius)
+                    if p1.co.x > 0 and p2.co.x < 0:
+                        u1 = acos(p1.co.x / self.Simple_radius)
+                        u2 = acos(p2.co.x / self.Simple_radius)
+                    elif p1.co.x < 0 and p2.co.x > 0:
+                        u1 = acos(p1.co.x / self.Simple_radius)
+                        u2 = acos(p2.co.x / self.Simple_radius)
+                    u = u2 - u1
+                    if u < 0:
+                        u = -u
+                    l = 4 / 3 * tan(1 / 4 * u) * self.Simple_radius
+                    v1 = Vector((-p1.co.y, p1.co.x, 0))
+                    v1.normalize()
+                    v2 = Vector((-p2.co.y, p2.co.x, 0))
+                    v2.normalize()
+                    vh1 = v1 * l
+                    vh2 = v2 * l
                     v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
                     v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
                     p1.handle_right = v1
                     p2.handle_left = v2
-
-            i += 1
-        all_points[0].handle_left_type = 'VECTOR'
-        all_points[n - 1].handle_right_type = 'VECTOR'
-        all_points[int(n / 2) - 1].handle_right_type = 'VECTOR'
-        all_points[int(n / 2)].handle_left_type = 'VECTOR'
+                i += 1
+    
+        if self.Simple_Type == 'Ellipse':
+            all_points[0].handle_right = Vector((self.Simple_a, self.Simple_b * d, 0))
+            all_points[0].handle_left = Vector((self.Simple_a, -self.Simple_b * d, 0))
+            all_points[1].handle_right = Vector((-self.Simple_a * d, self.Simple_b, 0))
+            all_points[1].handle_left = Vector((self.Simple_a * d, self.Simple_b, 0))
+            all_points[2].handle_right = Vector((-self.Simple_a, -self.Simple_b * d, 0))
+            all_points[2].handle_left = Vector((-self.Simple_a, self.Simple_b * d, 0))
+            all_points[3].handle_right = Vector((self.Simple_a * d, -self.Simple_b, 0))
+            all_points[3].handle_left = Vector((-self.Simple_a * d, -self.Simple_b, 0))
+    
+        if self.Simple_Type == 'Arc':
+            i = 0
+            for p1 in all_points:
+                if i != (n - 1):
+                    p2 = all_points[i + 1]
+                    u1 = asin(p1.co.y / self.Simple_radius)
+                    u2 = asin(p2.co.y / self.Simple_radius)
+                    if p1.co.x > 0 and p2.co.x < 0:
+                        u1 = acos(p1.co.x / self.Simple_radius)
+                        u2 = acos(p2.co.x / self.Simple_radius)
+                    elif p1.co.x < 0 and p2.co.x > 0:
+                        u1 = acos(p1.co.x / self.Simple_radius)
+                        u2 = acos(p2.co.x / self.Simple_radius)
+                    u = u2 - u1
+                    if u < 0:
+                        u = -u
+                    l = 4 / 3 * tan(1 / 4 * u) * self.Simple_radius
+                    v1 = Vector((-p1.co.y, p1.co.x, 0))
+                    v1.normalize()
+                    v2 = Vector((-p2.co.y, p2.co.x, 0))
+                    v2.normalize()
+                    vh1 = v1 * l
+                    vh2 = v2 * l
+                    if self.Simple_startangle < self.Simple_endangle:
+                        v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
+                        v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
+                        p1.handle_right = v1
+                        p2.handle_left = v2
+                    else:
+                        v1 = Vector((p1.co.x, p1.co.y, 0)) - vh1
+                        v2 = Vector((p2.co.x, p2.co.y, 0)) + vh2
+                        p1.handle_right = v1
+                        p2.handle_left = v2
+                i += 1
+    
+        if self.Simple_Type == 'Sector':
+            i = 0
+            for p1 in all_points:
+                if i == 0:
+                    p1.handle_right_type = 'VECTOR'
+                    p1.handle_left_type = 'VECTOR'
+                elif i != (n - 1):
+                    p2 = all_points[i + 1]
+                    u1 = asin(p1.co.y / self.Simple_radius)
+                    u2 = asin(p2.co.y / self.Simple_radius)
+                    if p1.co.x > 0 and p2.co.x < 0:
+                        u1 = acos(p1.co.x / self.Simple_radius)
+                        u2 = acos(p2.co.x / self.Simple_radius)
+                    elif p1.co.x < 0 and p2.co.x > 0:
+                        u1 = acos(p1.co.x / self.Simple_radius)
+                        u2 = acos(p2.co.x / self.Simple_radius)
+                    u = u2 - u1
+                    if u < 0:
+                        u = -u
+                    l = 4 / 3 * tan(1 / 4 * u) * self.Simple_radius
+                    v1 = Vector((-p1.co.y, p1.co.x, 0))
+                    v1.normalize()
+                    v2 = Vector((-p2.co.y, p2.co.x, 0))
+                    v2.normalize()
+                    vh1 = v1 * l
+                    vh2 = v2 * l
+                    if self.Simple_startangle < self.Simple_endangle:
+                        v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
+                        v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
+                        p1.handle_right = v1
+                        p2.handle_left = v2
+                    else:
+                        v1 = Vector((p1.co.x, p1.co.y, 0)) - vh1
+                        v2 = Vector((p2.co.x, p2.co.y, 0)) + vh2
+                        p1.handle_right = v1
+                        p2.handle_left = v2
+                i += 1
+    
+        if self.Simple_Type == 'Segment':
+            i = 0
+            if self.Simple_a > self.Simple_b:
+                Segment_a = self.Simple_a
+                Segment_b = self.Simple_b
+            if self.Simple_a < self.Simple_b:
+                Segment_b = self.Simple_a
+                Segment_a = self.Simple_b
+            for p1 in all_points:
+                if i < (n / 2 - 1):
+                    p2 = all_points[i + 1]
+                    u1 = asin(p1.co.y / Segment_a)
+                    u2 = asin(p2.co.y / Segment_a)
+                    if p1.co.x > 0 and p2.co.x < 0:
+                        u1 = acos(p1.co.x / Segment_a)
+                        u2 = acos(p2.co.x / Segment_a)
+                    elif p1.co.x < 0 and p2.co.x > 0:
+                        u1 = acos(p1.co.x / Segment_a)
+                        u2 = acos(p2.co.x / Segment_a)
+                    u = u2 - u1
+                    if u < 0:
+                        u = -u
+                    l = 4 / 3 * tan(1 / 4 * u) * Segment_a
+                    v1 = Vector((-p1.co.y, p1.co.x, 0))
+                    v1.normalize()
+                    v2 = Vector((-p2.co.y, p2.co.x, 0))
+                    v2.normalize()
+                    vh1 = v1 * l
+                    vh2 = v2 * l
+                    if self.Simple_startangle < self.Simple_endangle:
+                        v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
+                        v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
+                        p1.handle_right = v1
+                        p2.handle_left = v2
+                    else:
+                        v1 = Vector((p1.co.x, p1.co.y, 0)) - vh1
+                        v2 = Vector((p2.co.x, p2.co.y, 0)) + vh2
+                        p1.handle_right = v1
+                        p2.handle_left = v2
+                elif i != (n / 2 - 1) and i != (n - 1):
+                    p2 = all_points[i + 1]
+                    u1 = asin(p1.co.y / Segment_b)
+                    u2 = asin(p2.co.y / Segment_b)
+                    if p1.co.x > 0 and p2.co.x < 0:
+                        u1 = acos(p1.co.x / Segment_b)
+                        u2 = acos(p2.co.x / Segment_b)
+                    elif p1.co.x < 0 and p2.co.x > 0:
+                        u1 = acos(p1.co.x / Segment_b)
+                        u2 = acos(p2.co.x / Segment_b)
+                    u = u2 - u1
+                    if u < 0:
+                        u = -u
+                    l = 4 / 3 * tan(1 / 4 * u) * Segment_b
+                    v1 = Vector((-p1.co.y, p1.co.x, 0))
+                    v1.normalize()
+                    v2 = Vector((-p2.co.y, p2.co.x, 0))
+                    v2.normalize()
+                    vh1 = v1 * l
+                    vh2 = v2 * l
+                    if self.Simple_startangle < self.Simple_endangle:
+                        v1 = Vector((p1.co.x, p1.co.y, 0)) - vh1
+                        v2 = Vector((p2.co.x, p2.co.y, 0)) + vh2
+                        p1.handle_right = v1
+                        p2.handle_left = v2
+                    else:
+                        v1 = Vector((p1.co.x, p1.co.y, 0)) + vh1
+                        v2 = Vector((p2.co.x, p2.co.y, 0)) - vh2
+                        p1.handle_right = v1
+                        p2.handle_left = v2
+    
+                i += 1
+            all_points[0].handle_left_type = 'VECTOR'
+            all_points[n - 1].handle_right_type = 'VECTOR'
+            all_points[int(n / 2) - 1].handle_right_type = 'VECTOR'
+            all_points[int(n / 2)].handle_left_type = 'VECTOR'
 
     return
 
@@ -776,69 +797,70 @@ def Simple_curve_edit_menu(self, context):
 
 def menu(self, context):
     oper1 = self.layout.operator(Simple.bl_idname, text="Angle", icon="MOD_CURVE")
-    oper1.Simple_Change = False
     oper1.Simple_Type = "Angle"
+    oper1.use_cyclic_u = False
 
     oper2 = self.layout.operator(Simple.bl_idname, text="Arc", icon="MOD_CURVE")
-    oper2.Simple_Change = False
     oper2.Simple_Type = "Arc"
+    oper2.use_cyclic_u = False
 
     oper3 = self.layout.operator(Simple.bl_idname, text="Circle", icon="MOD_CURVE")
-    oper3.Simple_Change = False
     oper3.Simple_Type = "Circle"
+    oper3.use_cyclic_u = True
 
     oper4 = self.layout.operator(Simple.bl_idname, text="Distance", icon="MOD_CURVE")
-    oper4.Simple_Change = False
     oper4.Simple_Type = "Distance"
+    oper4.use_cyclic_u = False
 
     oper5 = self.layout.operator(Simple.bl_idname, text="Ellipse", icon="MOD_CURVE")
-    oper5.Simple_Change = False
     oper5.Simple_Type = "Ellipse"
+    oper5.use_cyclic_u = True
 
     oper6 = self.layout.operator(Simple.bl_idname, text="Line", icon="MOD_CURVE")
-    oper6.Simple_Change = False
     oper6.Simple_Type = "Line"
+    oper6.use_cyclic_u = False
+    oper6.shape = '3D'
 
     oper7 = self.layout.operator(Simple.bl_idname, text="Point", icon="MOD_CURVE")
-    oper7.Simple_Change = False
     oper7.Simple_Type = "Point"
+    oper7.use_cyclic_u = False
 
     oper8 = self.layout.operator(Simple.bl_idname, text="Polygon", icon="MOD_CURVE")
-    oper8.Simple_Change = False
     oper8.Simple_Type = "Polygon"
+    oper8.use_cyclic_u = True
 
     oper9 = self.layout.operator(Simple.bl_idname, text="Polygon ab", icon="MOD_CURVE")
-    oper9.Simple_Change = False
     oper9.Simple_Type = "Polygon_ab"
+    oper9.use_cyclic_u = True
 
     oper10 = self.layout.operator(Simple.bl_idname, text="Rectangle", icon="MOD_CURVE")
-    oper10.Simple_Change = False
     oper10.Simple_Type = "Rectangle"
+    oper10.use_cyclic_u = True
 
     oper11 = self.layout.operator(Simple.bl_idname, text="Rhomb", icon="MOD_CURVE")
-    oper11.Simple_Change = False
     oper11.Simple_Type = "Rhomb"
+    oper11.use_cyclic_u = True
 
     oper12 = self.layout.operator(Simple.bl_idname, text="Sector", icon="MOD_CURVE")
-    oper12.Simple_Change = False
     oper12.Simple_Type = "Sector"
+    oper12.use_cyclic_u = True
 
     oper13 = self.layout.operator(Simple.bl_idname, text="Segment", icon="MOD_CURVE")
-    oper13.Simple_Change = False
     oper13.Simple_Type = "Segment"
+    oper13.use_cyclic_u = True
 
     oper14 = self.layout.operator(Simple.bl_idname, text="Trapezoid", icon="MOD_CURVE")
-    oper14.Simple_Change = False
     oper14.Simple_Type = "Trapezoid"
+    oper14.use_cyclic_u = True
     
 # ------------------------------------------------------------
 # Simple operator
 
-class Simple(Operator):
+class Simple(Operator, object_utils.AddObjectHelper):
     bl_idname = "curve.simple"
     bl_label = "Simple Curve"
     bl_description = "Construct a Simple Curve"
-    bl_options = {'REGISTER', 'UNDO'}
+    bl_options = {'REGISTER', 'UNDO', 'PRESET'}
 
     # align_matrix for the invoke
     align_matrix : Matrix()
@@ -995,6 +1017,40 @@ class Simple(Operator):
             items=shapeItems,
             description="2D or 3D Curve"
             )
+    outputType : EnumProperty(
+            name="Output splines",
+            description="Type of splines to output",
+            items=[
+            ('POLY', "Poly", "Poly Spline type"),
+            ('NURBS', "Nurbs", "Nurbs Spline type"),
+            ('BEZIER', "Bezier", "Bezier Spline type")],
+            default='BEZIER'
+            )
+    use_cyclic_u : BoolProperty(
+            name="Cyclic",
+            default=True,
+            description="make curve closed"
+            )
+    endp_u : BoolProperty(
+            name="Use endpoint u",
+            default=True,
+            description="stretch to endpoints"
+            )
+    order_u : IntProperty(
+            name="Order u",
+            default=4,
+            min=2, soft_min=2,
+            max=6, soft_max=6,
+            description="Order of nurbs spline"
+            )
+    handleType : EnumProperty(
+            name="Handle type",
+            default='VECTOR',
+            description="Bezier handles type",
+            items=[
+            ('VECTOR', "Vector", "Vector type Bezier handles"),
+            ('AUTO', "Auto", "Automatic type Bezier handles")]
+            )
 
     def draw(self, context):
         layout = self.layout
@@ -1029,8 +1085,8 @@ class Simple(Operator):
             col.prop(self, "Simple_length")
             col.prop(self, "Simple_angle")
 
-            row = layout.row()
-            row.prop(self, "Simple_degrees_or_radians", expand=True)
+            #row = layout.row()
+            #row.prop(self, "Simple_degrees_or_radians", expand=True)
 
         if self.Simple_Type == 'Circle':
             box = layout.box()
@@ -1065,8 +1121,8 @@ class Simple(Operator):
             col = box.column(align=True)
             col.prop(self, "Simple_startangle")
             col.prop(self, "Simple_endangle")
-            row = layout.row()
-            row.prop(self, "Simple_degrees_or_radians", expand=True)
+            #row = layout.row()
+            #row.prop(self, "Simple_degrees_or_radians", expand=True)
 
             l = abs(pi * self.Simple_radius * (self.Simple_endangle - self.Simple_startangle) / 180)
 
@@ -1080,8 +1136,8 @@ class Simple(Operator):
             col = box.column(align=True)
             col.prop(self, "Simple_startangle")
             col.prop(self, "Simple_endangle")
-            row = layout.row()
-            row.prop(self, "Simple_degrees_or_radians", expand=True)
+            #row = layout.row()
+            #row.prop(self, "Simple_degrees_or_radians", expand=True)
 
             l = abs(pi * self.Simple_radius *
                    (self.Simple_endangle - self.Simple_startangle) / 180) + self.Simple_radius * 2
@@ -1101,8 +1157,8 @@ class Simple(Operator):
             col.prop(self, "Simple_startangle")
             col.prop(self, "Simple_endangle")
 
-            row = layout.row()
-            row.prop(self, "Simple_degrees_or_radians", expand=True)
+            #row = layout.row()
+            #row.prop(self, "Simple_degrees_or_radians", expand=True)
 
             la = abs(pi * self.Simple_a * (self.Simple_endangle - self.Simple_startangle) / 180)
             lb = abs(pi * self.Simple_b * (self.Simple_endangle - self.Simple_startangle) / 180)
@@ -1170,6 +1226,20 @@ class Simple(Operator):
 
         row = layout.row()
         row.prop(self, "shape", expand=True)
+        
+        # output options
+        col = layout.column()
+        col.label(text="Output Curve Type:")
+        col.row().prop(self, "outputType", expand=True)
+        
+        if self.outputType == 'NURBS':
+            col.prop(self, "order_u")
+        elif self.outputType == 'BEZIER':
+            col.row().prop(self, 'handleType', expand=True)
+
+        col = layout.column()
+        col.row().prop(self, "use_cyclic_u", expand=True)
+        
         box = layout.box()
         box.label(text="Location:")
         box.prop(self, "Simple_startlocation")
-- 
GitLab