1 # SPDX-License-Identifier: GPL-2.0-or-later
8 from gpu_extras
.batch
import batch_for_shader
12 from mathutils
import Vector
14 from bpy
.props
import (
18 # ------------------------------------------------------------
21 def draw_number(n
, co
, font_height
):
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
])
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
)]
54 if splines
[n
].type == 'BEZIER':
55 first_point_co
= matrix_world
@ splines
[n
].bezier_points
[0].co
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
})
68 gpu
.state
.line_width_set(font_thickness
)
69 shader
.uniform_float("color", sequence_color
)
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"
80 def modal(self
, context
, event
):
81 context
.area
.tag_redraw()
83 if event
.type in {'ESC'}:
84 for handler
in self
.handlers
:
86 bpy
.types
.SpaceView3D
.draw_handler_remove(handler
, 'WINDOW')
89 for handler
in self
.handlers
:
90 self
.handlers
.remove(handler
)
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'}
118 self
.report({'WARNING'},
119 "View3D not found, cannot run operator")
123 def poll(cls
, context
):
124 return (context
.object is not None and
125 context
.object.type == 'CURVE')
127 # ------------------------------------------------------------
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')
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(
223 description
="Command (prev or next)",
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
238 for spline
in splines
:
239 for bezier_points
in spline
.bezier_points
:
240 if bezier_points
.select_control_point
:
245 for spline
in splines
:
246 for point
in spline
.points
:
251 rearrange(dataCurve
, select_spline
, self
.command
)
256 def poll(cls
, context
):
257 return (context
.object is not None and
258 context
.object.type == 'CURVE')
262 bpy
.utils
.register_class(operators
)
266 bpy
.utils
.unregister_class(operators
)
268 if __name__
== "__main__":
271 operators
= [ShowSplinesSequence
, RearrangeSpline
]