Cleanup: quiet float argument to in type warning
[blender-addons.git] / add_mesh_extra_objects / add_mesh_torusknot.py
blob28c790279ccf5884c30748532826d3440fe02fa6
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # Author: Anthony D'Agostino
5 import bpy
6 from mathutils import Vector
7 from math import sin, cos, pi
8 from bpy.props import (
9 BoolProperty,
10 IntProperty,
11 StringProperty,
13 from bpy_extras import object_utils
16 def create_mesh_object(context, verts, edges, faces, name):
17 # Create new mesh
18 mesh = bpy.data.meshes.new(name)
19 # Make a mesh from a list of verts/edges/faces.
20 mesh.from_pydata(verts, edges, faces)
21 # Update mesh geometry after adding stuff.
22 mesh.update()
23 from bpy_extras import object_utils
24 return object_utils.object_data_add(context, mesh, operator=None)
27 # ========================
28 # === Torus Knot Block ===
29 # ========================
31 def k1(t):
32 x = cos(t) - 2 * cos(2 * t)
33 y = sin(t) + 2 * sin(2 * t)
34 z = sin(3 * t)
35 return Vector([x, y, z])
38 def k2(t):
39 x = 10 * (cos(t) + cos(3 * t)) + cos(2 * t) + cos(4 * t)
40 y = 6 * sin(t) + 10 * sin(3 * t)
41 z = 4 * sin(3 * t) * sin(5 * t / 2) + 4 * sin(4 * t) - 2 * sin(6 * t)
42 return Vector([x, y, z]) * 0.2
45 def k3(t):
46 x = 2.5 * cos(t + pi) / 3 + 2 * cos(3 * t)
47 y = 2.5 * sin(t) / 3 + 2 * sin(3 * t)
48 z = 1.5 * sin(4 * t) + sin(2 * t) / 3
49 return Vector([x, y, z])
52 def make_verts(ures, vres, r2, knotfunc):
53 verts = []
54 for i in range(ures):
55 t1 = (i + 0) * 2 * pi / ures
56 t2 = (i + 1) * 2 * pi / ures
57 a = knotfunc(t1) # curr point
58 b = knotfunc(t2) # next point
59 a, b = map(Vector, (a, b))
60 e = a - b
61 f = a + b
62 g = e.cross(f)
63 h = e.cross(g)
64 g.normalize()
65 h.normalize()
66 for j in range(vres):
67 k = j * 2 * pi / vres
68 l = (cos(k), 0.0, sin(k))
69 l = Vector(l)
70 m = l * r2
71 x, y, z = m
72 n = h * x
73 o = g * z
74 p = n + o
75 q = a + p
76 verts.append(q)
77 return verts
80 def make_faces(ures, vres):
81 faces = []
82 for u in range(0, ures):
83 for v in range(0, vres):
84 p1 = v + u * vres
85 p2 = v + ((u + 1) % ures) * vres
86 p4 = (v + 1) % vres + u * vres
87 p3 = (v + 1) % vres + ((u + 1) % ures) * vres
88 faces.append([p4, p3, p2, p1])
89 return faces
92 def make_knot(knotidx, ures):
93 knots = [k1, k2, k3]
94 knotfunc = knots[knotidx - 1]
95 vres = ures // 10
96 r2 = 0.5
97 verts = make_verts(ures, vres, r2, knotfunc)
98 faces = make_faces(ures, vres)
99 return (verts, faces)
102 class AddTorusKnot(bpy.types.Operator, object_utils.AddObjectHelper):
103 bl_idname = "mesh.primitive_torusknot_add"
104 bl_label = "Add Torus Knot"
105 bl_description = "Construct a torus knot mesh"
106 bl_options = {"REGISTER", "UNDO"}
108 TorusKnot : BoolProperty(name = "TorusKnot",
109 default = True,
110 description = "TorusKnot")
111 change : BoolProperty(name = "Change",
112 default = False,
113 description = "change TorusKnot")
115 resolution: IntProperty(
116 name="Resolution",
117 description="Resolution of the Torus Knot",
118 default=80,
119 min=30, max=256
121 objecttype: IntProperty(
122 name="Knot Type",
123 description="Type of Knot",
124 default=1,
125 min=1, max=3
128 def draw(self, context):
129 layout = self.layout
131 layout.prop(self, 'resolution', expand=True)
132 layout.prop(self, 'objecttype', expand=True)
134 if self.change == False:
135 col = layout.column(align=True)
136 col.prop(self, 'align', expand=True)
137 col = layout.column(align=True)
138 col.prop(self, 'location', expand=True)
139 col = layout.column(align=True)
140 col.prop(self, 'rotation', expand=True)
142 def execute(self, context):
143 # turn off 'Enter Edit Mode'
144 use_enter_edit_mode = bpy.context.preferences.edit.use_enter_edit_mode
145 bpy.context.preferences.edit.use_enter_edit_mode = False
147 if bpy.context.mode == "OBJECT":
148 if context.selected_objects != [] and context.active_object and \
149 (context.active_object.data is not None) and ('TorusKnot' in context.active_object.data.keys()) and \
150 (self.change == True):
151 obj = context.active_object
152 oldmesh = obj.data
153 oldmeshname = obj.data.name
154 verts, faces = make_knot(self.objecttype, self.resolution)
155 mesh = bpy.data.meshes.new('TorusKnot')
156 mesh.from_pydata(verts, [], faces)
157 obj.data = mesh
158 for material in oldmesh.materials:
159 obj.data.materials.append(material)
160 bpy.data.meshes.remove(oldmesh)
161 obj.data.name = oldmeshname
162 else:
163 verts, faces = make_knot(self.objecttype, self.resolution)
164 mesh = bpy.data.meshes.new('TorusKnot')
165 mesh.from_pydata(verts, [], faces)
166 obj = object_utils.object_data_add(context, mesh, operator=self)
168 obj.data["TorusKnot"] = True
169 obj.data["change"] = False
170 for prm in TorusKnotParameters():
171 obj.data[prm] = getattr(self, prm)
173 if bpy.context.mode == "EDIT_MESH":
174 active_object = context.active_object
175 name_active_object = active_object.name
176 bpy.ops.object.mode_set(mode='OBJECT')
177 verts, faces = make_knot(self.objecttype, self.resolution)
178 mesh = bpy.data.meshes.new('TorusKnot')
179 mesh.from_pydata(verts, [], faces)
180 obj = object_utils.object_data_add(context, mesh, operator=self)
181 obj.select_set(True)
182 active_object.select_set(True)
183 bpy.context.view_layer.objects.active = active_object
184 bpy.ops.object.join()
185 context.active_object.name = name_active_object
186 bpy.ops.object.mode_set(mode='EDIT')
188 if use_enter_edit_mode:
189 bpy.ops.object.mode_set(mode = 'EDIT')
191 # restore pre operator state
192 bpy.context.preferences.edit.use_enter_edit_mode = use_enter_edit_mode
194 return {'FINISHED'}
196 def TorusKnotParameters():
197 TorusKnotParameters = [
198 "resolution",
199 "objecttype",
201 return TorusKnotParameters