Pose library: fix asset creation operator poll when no object active
[blender-addons.git] / curve_tools / splines_sequence.py
blob89b9624c9f705b02c2319f60ce28042e92cfb2a5
1 # SPDX-License-Identifier: GPL-2.0-or-later
4 import bpy
6 import blf
7 import gpu
8 from gpu_extras.batch import batch_for_shader
10 import math
11 import mathutils
12 from mathutils import Vector
14 from bpy.props import (
15 EnumProperty,
18 # ------------------------------------------------------------
19 # ShowSplinesSequence
21 def draw_number(n, co, font_height):
23 point_list = []
25 numeral = [
26 [Vector((0, 0, 0)), Vector((0, 2, 0)), Vector((0, 2, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((1, 0, 0)), Vector((1, 0, 0)), Vector((0, 0, 0))],
27 [Vector((0, 1, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((1, 0, 0))],
28 [Vector((0, 2, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((1, 1, 0)), Vector((1, 1, 0)), Vector((0, 0, 0)), Vector((0, 0, 0)), Vector((1, 0, 0))],
29 [Vector((0, 2, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((0, 1, 0)), Vector((0, 1, 0)), Vector((1, 1, 0)), Vector((1, 1, 0)), Vector((0, 0, 0))],
30 [Vector((0, 2, 0)), Vector((0, 1, 0)), Vector((0, 1, 0)), Vector((1, 1, 0)), Vector((1, 1, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((1, 0, 0))],
31 [Vector((1, 2, 0)), Vector((0, 2, 0)), Vector((0, 2, 0)), Vector((0, 1, 0)), Vector((0, 1, 0)), Vector((1, 1, 0)), Vector((1, 1, 0)), Vector((1, 0, 0)), Vector((1, 0, 0)), Vector((0, 0, 0))],
32 [Vector((1, 2, 0)), Vector((0, 1, 0)), Vector((0, 1, 0)), Vector((0, 0, 0)), Vector((0, 0, 0)), Vector((1, 0, 0)), Vector((1, 0, 0)), Vector((1, 1, 0)), Vector((1, 1, 0)), Vector((0, 1, 0))],
33 [Vector((0, 2, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((0, 1, 0)), Vector((0, 1, 0)), Vector((0, 0, 0))],
34 [Vector((0, 1, 0)), Vector((0, 2, 0)), Vector((0, 2, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((1, 0, 0)), Vector((1, 0, 0)), Vector((0, 0, 0)), Vector((0, 0, 0)), Vector((0, 1, 0)), Vector((0, 1, 0)), Vector((1, 1, 0))],
35 [Vector((0, 0, 0)), Vector((1, 1, 0)), Vector((1, 1, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((0, 2, 0)), Vector((0, 2, 0)), Vector((0, 1, 0)), Vector((0, 1, 0)), Vector((1, 1, 0))],
38 for num in numeral[n]:
39 point_list.extend([num * font_height + co])
41 return point_list
44 def draw(self, context, splines, sequence_color, font_thickness, font_size, matrix_world):
46 splines_len = len(splines)
47 for n in range(0, splines_len):
49 res = [int(x) for x in str(n)]
51 i = 0
52 for r in res:
53 # draw some text
54 if splines[n].type == 'BEZIER':
55 first_point_co = matrix_world @ splines[n].bezier_points[0].co
56 else:
57 first_point = matrix_world @ splines[n].points[0].co
58 first_point_co = Vector((first_point.x, first_point.y, first_point.z))
60 first_point_co = Vector((i, 0, 0)) + first_point_co
61 points = draw_number(r, first_point_co, font_size)
63 shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
65 batch = batch_for_shader(shader, 'LINES', {"pos": points})
67 shader.bind()
68 gpu.state.line_width_set(font_thickness)
69 shader.uniform_float("color", sequence_color)
70 batch.draw(shader)
71 i += font_size + font_size * 0.5
73 class ShowSplinesSequence(bpy.types.Operator):
74 bl_idname = "curvetools.show_splines_sequence"
75 bl_label = "Show Splines Sequence"
76 bl_description = "Show Splines Sequence / [ESC] - remove"
78 handlers = []
80 def modal(self, context, event):
81 context.area.tag_redraw()
83 if event.type in {'ESC'}:
84 for handler in self.handlers:
85 try:
86 bpy.types.SpaceView3D.draw_handler_remove(handler, 'WINDOW')
87 except:
88 pass
89 for handler in self.handlers:
90 self.handlers.remove(handler)
91 return {'CANCELLED'}
93 return {'PASS_THROUGH'}
96 def invoke(self, context, event):
98 if context.area.type == 'VIEW_3D':
100 # color change in the panel
101 sequence_color = bpy.context.scene.curvetools.sequence_color
102 font_thickness = bpy.context.scene.curvetools.font_thickness
103 font_size = bpy.context.scene.curvetools.font_size
105 splines = context.active_object.data.splines
106 matrix_world = context.active_object.matrix_world
108 # the arguments we pass the the callback
109 args = (self, context, splines, sequence_color, font_thickness, font_size, matrix_world)
111 # Add the region OpenGL drawing callback
112 # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
113 self.handlers.append(bpy.types.SpaceView3D.draw_handler_add(draw, args, 'WINDOW', 'POST_VIEW'))
115 context.window_manager.modal_handler_add(self)
116 return {'RUNNING_MODAL'}
117 else:
118 self.report({'WARNING'},
119 "View3D not found, cannot run operator")
120 return {'CANCELLED'}
122 @classmethod
123 def poll(cls, context):
124 return (context.object is not None and
125 context.object.type == 'CURVE')
127 # ------------------------------------------------------------
128 # RearrangeSpline
130 def rearrangesplines(dataCurve, select_spline1, select_spline2):
132 spline1 = dataCurve.splines[select_spline1]
133 spline2 = dataCurve.splines[select_spline2]
135 bpy.ops.curve.select_all(action='SELECT')
136 bpy.ops.curve.spline_type_set(type='BEZIER')
137 bpy.ops.curve.select_all(action='DESELECT')
139 type1 = spline1.type
140 type2 = spline2.type
142 len_spline1 = len(spline1.bezier_points)
143 len_spline2 = len(spline2.bezier_points)
145 newSpline = dataCurve.splines.new(type=type1)
146 newSpline.bezier_points.add(len_spline1 - 1)
147 newSpline.use_cyclic_u = spline1.use_cyclic_u
148 for n in range(0, len_spline1):
149 newSpline.bezier_points[n].co = spline1.bezier_points[n].co
150 newSpline.bezier_points[n].handle_left_type = spline1.bezier_points[n].handle_left_type
151 newSpline.bezier_points[n].handle_left = spline1.bezier_points[n].handle_left
152 newSpline.bezier_points[n].handle_right_type = spline1.bezier_points[n].handle_right_type
153 newSpline.bezier_points[n].handle_right = spline1.bezier_points[n].handle_right
154 spline1.bezier_points[n].select_control_point = True
156 spline1.bezier_points[0].select_control_point = False
157 spline1.bezier_points[0].select_left_handle = False
158 spline1.bezier_points[0].select_right_handle = False
159 bpy.ops.curve.delete(type='VERT')
161 spline1.bezier_points[0].select_control_point = True
162 bpy.ops.curve.spline_type_set(type=type2)
164 bpy.ops.curve.select_all(action='DESELECT')
166 spline1.bezier_points.add(len_spline2 - 1)
167 spline1.use_cyclic_u = spline2.use_cyclic_u
168 for n in range(0, len_spline2):
169 spline1.bezier_points[n].co = spline2.bezier_points[n].co
170 spline1.bezier_points[n].handle_left_type = spline2.bezier_points[n].handle_left_type
171 spline1.bezier_points[n].handle_left = spline2.bezier_points[n].handle_left
172 spline1.bezier_points[n].handle_right_type = spline2.bezier_points[n].handle_right_type
173 spline1.bezier_points[n].handle_right = spline2.bezier_points[n].handle_right
174 spline1.bezier_points[n].select_control_point = False
175 spline1.bezier_points[n].select_left_handle = False
176 spline1.bezier_points[n].select_right_handle = False
177 spline2.bezier_points[n].select_control_point = True
179 spline2.bezier_points[0].select_control_point = False
180 spline2.bezier_points[0].select_left_handle = False
181 spline2.bezier_points[0].select_right_handle = False
182 bpy.ops.curve.delete(type='VERT')
184 spline2.bezier_points[0].select_control_point = True
185 bpy.ops.curve.spline_type_set(type=type1)
187 spline2.bezier_points.add(len_spline1 - 1)
188 spline2.use_cyclic_u = newSpline.use_cyclic_u
189 for m in range(0, len_spline1):
190 spline2.bezier_points[m].co = newSpline.bezier_points[m].co
191 spline2.bezier_points[m].handle_left_type = newSpline.bezier_points[m].handle_left_type
192 spline2.bezier_points[m].handle_left = newSpline.bezier_points[m].handle_left
193 spline2.bezier_points[m].handle_right_type = newSpline.bezier_points[m].handle_right_type
194 spline2.bezier_points[m].handle_right = newSpline.bezier_points[m].handle_right
196 bpy.ops.curve.select_all(action='DESELECT')
197 for point in newSpline.bezier_points:
198 point.select_control_point = True
199 bpy.ops.curve.delete(type='VERT')
201 spline2.bezier_points[0].select_control_point = True
203 def rearrange(dataCurve, select_spline, command):
204 len_splines = len(dataCurve.splines)
205 if command == 'NEXT':
206 if select_spline < len_splines - 1:
207 rearrangesplines(dataCurve, select_spline + 1, select_spline)
209 if command == 'PREV':
210 if select_spline > 0:
211 rearrangesplines(dataCurve, select_spline, select_spline - 1)
213 class RearrangeSpline(bpy.types.Operator):
214 bl_idname = "curvetools.rearrange_spline"
215 bl_label = "Rearrange Spline"
216 bl_description = "Rearrange Spline"
217 bl_options = {'UNDO'}
219 Types = [('NEXT', "Next", "next"),
220 ('PREV', "Prev", "prev")]
221 command : EnumProperty(
222 name="command",
223 description="Command (prev or next)",
224 items=Types
227 def execute(self, context):
228 bpy.ops.object.mode_set(mode = 'EDIT')
229 bpy.context.view_layer.update()
231 dataCurve = context.active_object.data
233 splines = context.active_object.data.splines
235 select_spline = 0
237 sn = 0
238 for spline in splines:
239 for bezier_points in spline.bezier_points:
240 if bezier_points.select_control_point:
241 select_spline = sn
242 sn += 1
244 sn = 0
245 for spline in splines:
246 for point in spline.points:
247 if point.select:
248 select_spline = sn
249 sn += 1
251 rearrange(dataCurve, select_spline, self.command)
253 return {'FINISHED'}
255 @classmethod
256 def poll(cls, context):
257 return (context.object is not None and
258 context.object.type == 'CURVE')
260 def register():
261 for cls in classes:
262 bpy.utils.register_class(operators)
264 def unregister():
265 for cls in classes:
266 bpy.utils.unregister_class(operators)
268 if __name__ == "__main__":
269 register()
271 operators = [ShowSplinesSequence, RearrangeSpline]