1 # SPDX-License-Identifier: GPL-2.0-or-later
9 from gpu_extras
.batch
import batch_for_shader
13 from mathutils
import Vector
15 from bpy
.props
import (
19 # ------------------------------------------------------------
22 def draw_number(n
, co
, font_height
):
27 [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))],
28 [Vector((0, 1, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((1, 0, 0))],
29 [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))],
30 [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))],
31 [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))],
32 [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))],
33 [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))],
34 [Vector((0, 2, 0)), Vector((1, 2, 0)), Vector((1, 2, 0)), Vector((0, 1, 0)), Vector((0, 1, 0)), Vector((0, 0, 0))],
35 [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))],
36 [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))],
39 for num
in numeral
[n
]:
40 point_list
.extend([num
* font_height
+ co
])
45 def draw(self
, context
, splines
, sequence_color
, font_thickness
, font_size
, matrix_world
):
47 splines_len
= len(splines
)
48 for n
in range(0, splines_len
):
50 res
= [int(x
) for x
in str(n
)]
55 if splines
[n
].type == 'BEZIER':
56 first_point_co
= matrix_world
@ splines
[n
].bezier_points
[0].co
58 first_point
= matrix_world
@ splines
[n
].points
[0].co
59 first_point_co
= Vector((first_point
.x
, first_point
.y
, first_point
.z
))
61 first_point_co
= Vector((i
, 0, 0)) + first_point_co
62 points
= draw_number(r
, first_point_co
, font_size
)
64 shader
= gpu
.shader
.from_builtin('3D_UNIFORM_COLOR')
66 batch
= batch_for_shader(shader
, 'LINES', {"pos": points
})
69 bgl
.glLineWidth(font_thickness
)
70 shader
.uniform_float("color", sequence_color
)
72 i
+= font_size
+ font_size
* 0.5
74 class ShowSplinesSequence(bpy
.types
.Operator
):
75 bl_idname
= "curvetools.show_splines_sequence"
76 bl_label
= "Show Splines Sequence"
77 bl_description
= "Show Splines Sequence / [ESC] - remove"
81 def modal(self
, context
, event
):
82 context
.area
.tag_redraw()
84 if event
.type in {'ESC'}:
85 for handler
in self
.handlers
:
87 bpy
.types
.SpaceView3D
.draw_handler_remove(handler
, 'WINDOW')
90 for handler
in self
.handlers
:
91 self
.handlers
.remove(handler
)
94 return {'PASS_THROUGH'}
97 def invoke(self
, context
, event
):
99 if context
.area
.type == 'VIEW_3D':
101 # color change in the panel
102 sequence_color
= bpy
.context
.scene
.curvetools
.sequence_color
103 font_thickness
= bpy
.context
.scene
.curvetools
.font_thickness
104 font_size
= bpy
.context
.scene
.curvetools
.font_size
106 splines
= context
.active_object
.data
.splines
107 matrix_world
= context
.active_object
.matrix_world
109 # the arguments we pass the the callback
110 args
= (self
, context
, splines
, sequence_color
, font_thickness
, font_size
, matrix_world
)
112 # Add the region OpenGL drawing callback
113 # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
114 self
.handlers
.append(bpy
.types
.SpaceView3D
.draw_handler_add(draw
, args
, 'WINDOW', 'POST_VIEW'))
116 context
.window_manager
.modal_handler_add(self
)
117 return {'RUNNING_MODAL'}
119 self
.report({'WARNING'},
120 "View3D not found, cannot run operator")
124 def poll(cls
, context
):
125 return (context
.object is not None and
126 context
.object.type == 'CURVE')
128 # ------------------------------------------------------------
131 def rearrangesplines(dataCurve
, select_spline1
, select_spline2
):
133 spline1
= dataCurve
.splines
[select_spline1
]
134 spline2
= dataCurve
.splines
[select_spline2
]
136 bpy
.ops
.curve
.select_all(action
='SELECT')
137 bpy
.ops
.curve
.spline_type_set(type='BEZIER')
138 bpy
.ops
.curve
.select_all(action
='DESELECT')
143 len_spline1
= len(spline1
.bezier_points
)
144 len_spline2
= len(spline2
.bezier_points
)
146 newSpline
= dataCurve
.splines
.new(type=type1
)
147 newSpline
.bezier_points
.add(len_spline1
- 1)
148 newSpline
.use_cyclic_u
= spline1
.use_cyclic_u
149 for n
in range(0, len_spline1
):
150 newSpline
.bezier_points
[n
].co
= spline1
.bezier_points
[n
].co
151 newSpline
.bezier_points
[n
].handle_left_type
= spline1
.bezier_points
[n
].handle_left_type
152 newSpline
.bezier_points
[n
].handle_left
= spline1
.bezier_points
[n
].handle_left
153 newSpline
.bezier_points
[n
].handle_right_type
= spline1
.bezier_points
[n
].handle_right_type
154 newSpline
.bezier_points
[n
].handle_right
= spline1
.bezier_points
[n
].handle_right
155 spline1
.bezier_points
[n
].select_control_point
= True
157 spline1
.bezier_points
[0].select_control_point
= False
158 spline1
.bezier_points
[0].select_left_handle
= False
159 spline1
.bezier_points
[0].select_right_handle
= False
160 bpy
.ops
.curve
.delete(type='VERT')
162 spline1
.bezier_points
[0].select_control_point
= True
163 bpy
.ops
.curve
.spline_type_set(type=type2
)
165 bpy
.ops
.curve
.select_all(action
='DESELECT')
167 spline1
.bezier_points
.add(len_spline2
- 1)
168 spline1
.use_cyclic_u
= spline2
.use_cyclic_u
169 for n
in range(0, len_spline2
):
170 spline1
.bezier_points
[n
].co
= spline2
.bezier_points
[n
].co
171 spline1
.bezier_points
[n
].handle_left_type
= spline2
.bezier_points
[n
].handle_left_type
172 spline1
.bezier_points
[n
].handle_left
= spline2
.bezier_points
[n
].handle_left
173 spline1
.bezier_points
[n
].handle_right_type
= spline2
.bezier_points
[n
].handle_right_type
174 spline1
.bezier_points
[n
].handle_right
= spline2
.bezier_points
[n
].handle_right
175 spline1
.bezier_points
[n
].select_control_point
= False
176 spline1
.bezier_points
[n
].select_left_handle
= False
177 spline1
.bezier_points
[n
].select_right_handle
= False
178 spline2
.bezier_points
[n
].select_control_point
= True
180 spline2
.bezier_points
[0].select_control_point
= False
181 spline2
.bezier_points
[0].select_left_handle
= False
182 spline2
.bezier_points
[0].select_right_handle
= False
183 bpy
.ops
.curve
.delete(type='VERT')
185 spline2
.bezier_points
[0].select_control_point
= True
186 bpy
.ops
.curve
.spline_type_set(type=type1
)
188 spline2
.bezier_points
.add(len_spline1
- 1)
189 spline2
.use_cyclic_u
= newSpline
.use_cyclic_u
190 for m
in range(0, len_spline1
):
191 spline2
.bezier_points
[m
].co
= newSpline
.bezier_points
[m
].co
192 spline2
.bezier_points
[m
].handle_left_type
= newSpline
.bezier_points
[m
].handle_left_type
193 spline2
.bezier_points
[m
].handle_left
= newSpline
.bezier_points
[m
].handle_left
194 spline2
.bezier_points
[m
].handle_right_type
= newSpline
.bezier_points
[m
].handle_right_type
195 spline2
.bezier_points
[m
].handle_right
= newSpline
.bezier_points
[m
].handle_right
197 bpy
.ops
.curve
.select_all(action
='DESELECT')
198 for point
in newSpline
.bezier_points
:
199 point
.select_control_point
= True
200 bpy
.ops
.curve
.delete(type='VERT')
202 spline2
.bezier_points
[0].select_control_point
= True
204 def rearrange(dataCurve
, select_spline
, command
):
205 len_splines
= len(dataCurve
.splines
)
206 if command
== 'NEXT':
207 if select_spline
< len_splines
- 1:
208 rearrangesplines(dataCurve
, select_spline
+ 1, select_spline
)
210 if command
== 'PREV':
211 if select_spline
> 0:
212 rearrangesplines(dataCurve
, select_spline
, select_spline
- 1)
214 class RearrangeSpline(bpy
.types
.Operator
):
215 bl_idname
= "curvetools.rearrange_spline"
216 bl_label
= "Rearrange Spline"
217 bl_description
= "Rearrange Spline"
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
]