-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadd_star.py
More file actions
138 lines (109 loc) · 4.06 KB
/
Copy pathadd_star.py
File metadata and controls
138 lines (109 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# SPDX-FileCopyrightText: © 2016 Michel Anders (varkenvarken) & contributors
#
# SPDX-License-Identifier: GPL-2.0-or-later
bl_info = {
"name": "Star",
"author": "Your Name",
"version": (0, 0, 2),
"blender": (5, 0, 0),
"location": "Object > Add",
"description": "Add a star shaped mesh to the scene",
"category": "Object",
}
from math import pi, sin, cos
import bpy
from bpy.types import Operator
from bpy.props import IntProperty, FloatProperty
from bpy_extras.object_utils import object_data_add
# help function to check that that the outer radius is
# always larger than the inner radius.
# Note that the comparisons are strict, i.e. do NOT
# check for equality to prevent infinite recursion!
def update_outer_radius(self, context):
"""make sure outer radius > inner radius"""
if self.inner_radius > self.outer_radius:
self.outer_radius = self.inner_radius
def update_inner_radius(self, context):
"""make sure inner radius <= outer radius"""
if self.outer_radius < self.inner_radius:
self.inner_radius = self.outer_radius
class OBJECT_OT_add_star(Operator):
bl_idname = "object.add_star"
bl_label = "Add star"
bl_description = "Add a star shaped mesh to the scene"
bl_options = {"REGISTER", "UNDO"}
points: IntProperty(
name="Points",
description="Number of points on the star",
default=5,
min=3,
soft_max=20,
)
inner_radius: FloatProperty(
name="Inner radius",
description="Distance from center to indented vertices",
default=1.0,
min=0.0,
update=update_outer_radius,
)
outer_radius: FloatProperty(
name="Outer radius",
description="Distance from center to point tips",
default=1.5,
min=0.0,
update=update_inner_radius,
)
def star_geometry(self):
"""Calculate and return vertices, edges, and faces for the star mesh."""
vertices = []
angle = 2 * pi / self.points # angle between two tips, in radians
for p in range(self.points):
vertices.append( # tip vertex
(
self.outer_radius * -sin(p * angle),
self.outer_radius * cos(p * angle),
0.0,
)
)
vertices.append( # intermediate vertex
(
self.inner_radius * -sin(p * angle + angle / 2),
self.inner_radius * cos(p * angle + angle / 2),
0.0,
)
)
number_of_vertices = len(vertices)
# edges connecting each vertex to the next one; the modulo assures we wrap around at the end
edges = [(p, (p + 1) % number_of_vertices) for p in range(number_of_vertices)]
# a verts form a single face (an NGON)
faces = [list(range(number_of_vertices))]
return vertices, edges, faces
def execute(self, context):
"""Create a star mesh from calculated geometry."""
vertices, edges, faces = self.star_geometry()
mesh = bpy.data.meshes.new(name="Star")
mesh.from_pydata(vertices, edges, faces)
object_data_add(context, mesh, operator=None, name=None)
return {"FINISHED"}
@classmethod
def poll(cls, context):
"""Enable operator only in Object mode."""
return context.mode == "OBJECT"
# Note: best practice is to put all imports at the beginning
# but we want make a clear distinction between operator
# implementation and registration.
from bpy.utils import register_class, unregister_class
from bpy.types import VIEW3D_MT_add
def menu_func(self, context):
"""Add the star operator to the Object menu."""
self.layout.operator(OBJECT_OT_add_star.bl_idname)
def register():
"""Register the add-on classes and menu."""
register_class(OBJECT_OT_add_star)
VIEW3D_MT_add.append(menu_func)
def unregister():
"""Unregister the add-on classes and menu."""
VIEW3D_MT_add.remove(menu_func)
unregister_class(OBJECT_OT_add_star)
if __name__ == "__main__":
register()