1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
10 "location": "View3D > Tools > PKHG (tab)",
11 "description": "Faces selected will become added faces of different style",
19 from bpy
.types
import Operator
20 from mathutils
import Vector
21 from bpy
.props
import (
30 class MESH_OT_add_faces_to_object(Operator
):
31 bl_idname
= "mesh.add_faces_to_object"
32 bl_label
= "Face Shape"
33 bl_description
= "Set parameters and build object with added faces"
34 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
36 reverse_faces
: BoolProperty(
39 description
="Revert the normals of selected faces"
41 name_source_object
: StringProperty(
43 description
="Choose a Source Mesh",
46 remove_start_faces
: BoolProperty(
47 name
="Remove Start Faces",
49 description
="Make a choice about removal of Original Faces"
51 base_height
: FloatProperty(
56 description
="Set general Base Height"
58 use_relative_base_height
: BoolProperty(
59 name
="Relative Base Height",
61 description
="Relative or absolute Base Height"
63 second_height
: FloatProperty(
64 name
="2nd height", min=-5,
67 description
="Second height for various shapes"
73 description
="Set general width"
75 repeat_extrude
: IntProperty(
79 description
="For longer base"
81 move_inside
: FloatProperty(
86 description
="How much move to inside"
88 thickness
: FloatProperty(
91 soft_max
=5.0, max=20.0,
97 soft_max
=5.0, max=20.0,
100 collapse_edges
: BoolProperty(
103 description
="Collapse the vertices of edges"
105 spike_base_width
: FloatProperty(
106 name
="Spike Base Width",
110 description
="Base width of a spike"
112 base_height_inset
: FloatProperty(
113 name
="Base Height Inset",
116 description
="To elevate or drop the Base height Inset"
118 top_spike
: FloatProperty(
122 description
="The Base Height of a spike"
124 top_extra_height
: FloatProperty(
125 name
="Top Extra Height",
128 description
="Add extra height"
130 step_with_real_spike
: BoolProperty(
131 name
="Step with Real Spike",
133 description
="In stepped, use a real spike"
135 use_relative
: BoolProperty(
138 description
="Change size using area, min or max"
140 face_types
: EnumProperty(
142 description
="Different types of Faces",
145 ('no', "Pick an Option", "Choose one of the available options"),
146 ('open_inset', "Open Inset", "Inset without closing faces (holes)"),
147 ('with_base', "With Base", "Base and ..."),
148 ('clsd_vertical', "Closed Vertical", "Closed Vertical"),
149 ('open_vertical', "Open Vertical", "Open Vertical"),
150 ('spiked', "Spiked", "Spike"),
151 ('stepped', "Stepped", "Stepped"),
152 ('boxed', "Boxed", "Boxed"),
153 ('bar', "Bar", "Bar"),
156 strange_boxed_effect
: BoolProperty(
157 name
="Strange Effect",
159 description
="Do not show one extrusion"
161 use_boundary
: BoolProperty(
165 use_even_offset
: BoolProperty(
169 use_relative_offset
: BoolProperty(
170 name
="Relative Offset",
173 use_edge_rail
: BoolProperty(
177 use_outset
: BoolProperty(
181 use_select_inset
: BoolProperty(
185 use_interpolate
: BoolProperty(
191 def poll(cls
, context
):
193 active_object
= context
.active_object
195 mesh_objects_name
= [el
.name
for el
in bpy
.data
.objects
if el
.type == "MESH"]
196 if active_object
.name
in mesh_objects_name
:
201 def draw(self
, context
):
203 col
= layout
.column()
206 col
.label(text
="Using Active Object", icon
="INFO")
208 col
.label(text
="Face Types:")
209 col
.prop(self
, "face_types", text
="")
211 col
.prop(self
, "use_relative")
213 if self
.face_types
== "open_inset":
214 col
.prop(self
, "move_inside")
215 col
.prop(self
, "base_height")
217 elif self
.face_types
== "with_base":
218 col
.prop(self
, "move_inside")
219 col
.prop(self
, "base_height")
220 col
.prop(self
, "second_height")
221 col
.prop(self
, "width")
223 elif self
.face_types
== "clsd_vertical":
224 col
.prop(self
, "base_height")
226 elif self
.face_types
== "open_vertical":
227 col
.prop(self
, "base_height")
229 elif self
.face_types
== "boxed":
230 col
.prop(self
, "move_inside")
231 col
.prop(self
, "base_height")
232 col
.prop(self
, "top_spike")
233 col
.prop(self
, "strange_boxed_effect")
235 elif self
.face_types
== "spiked":
236 col
.prop(self
, "spike_base_width")
237 col
.prop(self
, "base_height_inset")
238 col
.prop(self
, "top_spike")
240 elif self
.face_types
== "bar":
241 col
.prop(self
, "spike_base_width")
242 col
.prop(self
, "top_spike")
243 col
.prop(self
, "top_extra_height")
245 elif self
.face_types
== "stepped":
246 col
.prop(self
, "spike_base_width")
247 col
.prop(self
, "base_height_inset")
248 col
.prop(self
, "top_extra_height")
249 col
.prop(self
, "second_height")
250 col
.prop(self
, "step_with_real_spike")
252 def execute(self
, context
):
253 obj_name
= self
.name_source_object
254 face_type
= self
.face_types
256 is_selected
= check_is_selected()
259 self
.report({'WARNING'},
260 "Operation Cancelled. No selected Faces found on the Active Object")
263 if face_type
== "spiked":
264 Spiked(spike_base_width
=self
.spike_base_width
,
265 base_height_inset
=self
.base_height_inset
,
266 top_spike
=self
.top_spike
, top_relative
=self
.use_relative
)
268 elif face_type
== "boxed":
269 startinfo
= prepare(self
, context
, self
.remove_start_faces
)
272 obj
= startinfo
['obj']
273 obj_matrix_local
= obj
.matrix_local
278 areas
= startinfo
['areas']
279 base_height
= self
.base_height
281 if self
.use_relative
:
282 distance
= [min(t
* area
, 1.0) for i
, area
in enumerate(areas
)]
283 base_heights
= [base_height
* area
for i
, area
in enumerate(areas
)]
285 distance
= [t
] * len(areas
)
286 base_heights
= [base_height
] * len(areas
)
288 rings
= startinfo
['rings']
289 centers
= startinfo
['centers']
290 normals
= startinfo
['normals']
291 for i
in range(len(rings
)):
292 make_one_inset(self
, context
, bm
=bm
, ringvectors
=rings
[i
],
293 center
=centers
[i
], normal
=normals
[i
],
294 t
=distance
[i
], base_height
=base_heights
[i
])
295 bpy
.ops
.mesh
.select_mode(type="EDGE")
296 bpy
.ops
.mesh
.select_more()
297 bpy
.ops
.mesh
.select_more()
298 bpy
.ops
.object.mode_set(mode
='OBJECT')
299 # PKHG>INFO base extrusion done and set to the mesh
301 # PKHG>INFO if the extrusion is NOT done ... it'll look strange soon!
302 if not self
.strange_boxed_effect
:
303 bpy
.ops
.object.mode_set(mode
='EDIT')
304 obj
= context
.active_object
305 bm
= bmesh
.from_edit_mesh(obj
.data
)
306 bmfaces
= [face
for face
in bm
.faces
if face
.select
]
307 res
= extrude_faces(self
, context
, bm
=bm
, face_l
=bmfaces
)
308 ring_edges
= [face
.edges
[:] for face
in res
]
310 bpy
.ops
.object.mode_set(mode
='OBJECT')
312 # PKHG>INFO now the extruded facec have to move in normal direction
313 bpy
.ops
.object.mode_set(mode
='EDIT')
314 obj
= bpy
.context
.view_layer
.objects
.active
315 bm
= bmesh
.from_edit_mesh(obj
.data
)
316 todo_faces
= [face
for face
in bm
.faces
if face
.select
]
317 for face
in todo_faces
:
318 bmesh
.ops
.translate(bm
, vec
=face
.normal
* top
, space
=obj_matrix_local
,
320 bpy
.ops
.object.mode_set(mode
='OBJECT')
322 elif face_type
== "stepped":
323 Stepped(spike_base_width
=self
.spike_base_width
,
324 base_height_inset
=self
.base_height_inset
,
325 top_spike
=self
.second_height
,
326 top_extra_height
=self
.top_extra_height
,
327 use_relative_offset
=self
.use_relative
, with_spike
=self
.step_with_real_spike
)
329 elif face_type
== "open_inset":
330 startinfo
= prepare(self
, context
, self
.remove_start_faces
)
333 # PKHG>INFO adjust for relative, via areas
335 areas
= startinfo
['areas']
336 base_height
= self
.base_height
339 if self
.use_relative
:
340 distance
= [min(t
* area
, 1.0) for i
, area
in enumerate(areas
)]
341 base_heights
= [base_height
* area
for i
, area
in enumerate(areas
)]
343 distance
= [t
] * len(areas
)
344 base_heights
= [base_height
] * len(areas
)
346 rings
= startinfo
['rings']
347 centers
= startinfo
['centers']
348 normals
= startinfo
['normals']
349 for i
in range(len(rings
)):
350 make_one_inset(self
, context
, bm
=bm
, ringvectors
=rings
[i
],
351 center
=centers
[i
], normal
=normals
[i
],
352 t
=distance
[i
], base_height
=base_heights
[i
])
353 bpy
.ops
.object.mode_set(mode
='OBJECT')
355 elif face_type
== "with_base":
356 startinfo
= prepare(self
, context
, self
.remove_start_faces
)
358 obj
= startinfo
['obj']
359 object_matrix
= obj
.matrix_local
361 # PKHG>INFO for relative (using areas)
363 areas
= startinfo
['areas']
364 base_height
= self
.base_height
368 if self
.use_relative
:
369 distance
= [min(t
* area
, 1.0) for i
, area
in enumerate(areas
)]
370 base_heights
= [base_height
* area
for i
, area
in enumerate(areas
)]
372 distance
= [t
] * len(areas
)
373 base_heights
= [base_height
] * len(areas
)
376 rings
= startinfo
['rings']
377 centers
= startinfo
['centers']
378 normals
= startinfo
['normals']
379 for i
in range(len(rings
)):
380 next_rings
.append(make_one_inset(self
, context
, bm
=bm
, ringvectors
=rings
[i
],
381 center
=centers
[i
], normal
=normals
[i
],
382 t
=distance
[i
], base_height
=base_heights
[i
]))
384 prepare_ring
= extrude_edges(self
, context
, bm
=bm
, edge_l_l
=next_rings
)
386 second_height
= self
.second_height
388 vectors
= [[ele
.verts
[:] for ele
in edge
] for edge
in prepare_ring
]
391 for rings
in vectors
:
395 # PKHF>INFO no double verts allowed, coming from two adjacents edges!
396 bm
.verts
.ensure_lookup_table()
397 vv
= list(set([ele
.index
for ele
in v
]))
399 vvv
= [bm
.verts
[i
].co
for i
in vv
]
400 n_ring_vecs
.append(vvv
)
402 for i
, ring
in enumerate(n_ring_vecs
):
403 make_one_inset(self
, context
, bm
=bm
, ringvectors
=ring
,
404 center
=centers
[i
], normal
=normals
[i
],
405 t
=width
, base_height
=base_heights
[i
] + second_height
)
406 bpy
.ops
.object.mode_set(mode
='OBJECT')
409 if face_type
== "clsd_vertical":
410 obj_name
= context
.active_object
.name
411 ClosedVertical(name
=obj_name
, base_height
=self
.base_height
,
412 use_relative_base_height
=self
.use_relative
)
414 elif face_type
== "open_vertical":
415 obj_name
= context
.active_object
.name
416 OpenVertical(name
=obj_name
, base_height
=self
.base_height
,
417 use_relative_base_height
=self
.use_relative
)
419 elif face_type
== "bar":
420 startinfo
= prepare(self
, context
, self
.remove_start_faces
)
424 rings
= startinfo
['rings']
425 centers
= startinfo
['centers']
426 normals
= startinfo
['normals']
427 spike_base_width
= self
.spike_base_width
428 for i
, ring
in enumerate(rings
):
429 result
.append(make_one_inset(self
, context
, bm
=bm
,
430 ringvectors
=ring
, center
=centers
[i
],
431 normal
=normals
[i
], t
=spike_base_width
))
433 next_ring_edges_list
= extrude_edges(self
, context
, bm
=bm
,
435 top_spike
= self
.top_spike
437 object_matrix
= startinfo
['obj'].matrix_local
438 for i
in range(len(next_ring_edges_list
)):
440 self
, context
, bm
=bm
,
441 object_matrix
=object_matrix
,
442 ring_edges
=next_ring_edges_list
[i
],
443 normal
=normals
[i
], distance
=fac
445 next_ring_edges_list_2
= extrude_edges(self
, context
, bm
=bm
,
446 edge_l_l
=next_ring_edges_list
)
448 top_extra_height
= self
.top_extra_height
449 for i
in range(len(next_ring_edges_list_2
)):
450 move_corner_vecs_outside(
451 self
, context
, bm
=bm
,
452 edge_list
=next_ring_edges_list_2
[i
],
453 center
=centers
[i
], normal
=normals
[i
],
454 base_height_erlier
=fac
+ top_extra_height
,
457 bpy
.ops
.mesh
.select_mode(type="VERT")
458 bpy
.ops
.mesh
.select_more()
460 bpy
.ops
.object.mode_set(mode
='OBJECT')
465 def find_one_ring(sel_vertices
):
466 ring0
= sel_vertices
.pop(0)
469 for i
, edge
in enumerate(sel_vertices
):
471 if len(ring0
- edge
) < len_nu
:
473 ring0
= ring0
.union(edge
)
480 return (ring0
, sel_vertices
)
484 def __init__(self
, spike_base_width
=0.5, base_height_inset
=0.0, top_spike
=0.2,
485 top_relative
=False, top_extra_height
=0, use_relative_offset
=False,
488 bpy
.ops
.object.mode_set(mode
='EDIT')
490 use_boundary
=True, use_even_offset
=True, use_relative_offset
=False,
491 use_edge_rail
=False, thickness
=spike_base_width
, depth
=0, use_outset
=True,
492 use_select_inset
=False, use_individual
=True, use_interpolate
=True
495 use_boundary
=True, use_even_offset
=True, use_relative_offset
=use_relative_offset
,
496 use_edge_rail
=False, thickness
=top_extra_height
, depth
=base_height_inset
,
497 use_outset
=True, use_select_inset
=False, use_individual
=True, use_interpolate
=True
500 use_boundary
=True, use_even_offset
=True, use_relative_offset
=use_relative_offset
,
501 use_edge_rail
=False, thickness
=spike_base_width
, depth
=0, use_outset
=True,
502 use_select_inset
=False, use_individual
=True, use_interpolate
=True
505 use_boundary
=True, use_even_offset
=True, use_relative_offset
=False,
506 use_edge_rail
=False, thickness
=0, depth
=top_spike
, use_outset
=True,
507 use_select_inset
=False, use_individual
=True, use_interpolate
=True
510 bpy
.ops
.mesh
.merge(type='COLLAPSE')
512 bpy
.ops
.object.mode_set(mode
='OBJECT')
516 def __init__(self
, spike_base_width
=0.5, base_height_inset
=0.0, top_spike
=0.2, top_relative
=False):
518 obj
= bpy
.context
.active_object
519 bpy
.ops
.object.mode_set(mode
='EDIT')
521 use_boundary
=True, use_even_offset
=True, use_relative_offset
=False,
522 use_edge_rail
=False, thickness
=spike_base_width
, depth
=base_height_inset
,
523 use_outset
=True, use_select_inset
=False, use_individual
=True, use_interpolate
=True
526 use_boundary
=True, use_even_offset
=True, use_relative_offset
=top_relative
,
527 use_edge_rail
=False, thickness
=0, depth
=top_spike
, use_outset
=True,
528 use_select_inset
=False, use_individual
=True, use_interpolate
=True
531 bm
= bmesh
.from_edit_mesh(obj
.data
)
532 bpy
.ops
.mesh
.merge(type='COLLAPSE')
533 bpy
.ops
.object.mode_set(mode
='OBJECT')
536 class ClosedVertical
:
537 def __init__(self
, name
="Plane", base_height
=1, use_relative_base_height
=False):
538 obj
= bpy
.data
.objects
[name
]
539 bpy
.ops
.object.mode_set(mode
='OBJECT')
541 bm
.from_mesh(obj
.data
)
542 # PKHG>INFO deselect chosen faces
543 sel
= [f
for f
in bm
.faces
if f
.select
]
546 res
= bmesh
.ops
.extrude_discrete_faces(bm
, faces
=sel
)
547 # PKHG>INFO select extruded faces
548 for f
in res
['faces']:
552 for face
in res
['faces']:
553 if use_relative_base_height
:
554 area
= face
.calc_area()
555 factor
= area
* base_height
558 for el
in face
.verts
:
559 tmp
= el
.co
+ face
.normal
* factor
562 me
= bpy
.data
.meshes
[name
]
568 def __init__(self
, name
="Plane", base_height
=1, use_relative_base_height
=False):
570 obj
= bpy
.data
.objects
[name
]
571 bpy
.ops
.object.mode_set(mode
='OBJECT')
573 bm
.from_mesh(obj
.data
)
574 # PKHG>INFO deselect chosen faces
575 sel
= [f
for f
in bm
.faces
if f
.select
]
578 res
= bmesh
.ops
.extrude_discrete_faces(bm
, faces
=sel
)
579 # PKHG>INFO select extruded faces
580 for f
in res
['faces']:
583 # PKHG>INFO adjust extrusion by a vector
585 for face
in res
['faces']:
586 if use_relative_base_height
:
587 area
= face
.calc_area()
588 factor
= area
* base_height
591 for el
in face
.verts
:
592 tmp
= el
.co
+ face
.normal
* factor
595 me
= bpy
.data
.meshes
[name
]
599 bpy
.ops
.object.editmode_toggle()
600 bpy
.ops
.mesh
.delete(type='FACE')
601 bpy
.ops
.object.editmode_toggle()
605 def __init__(self
, use_boundary
=True, use_even_offset
=True, use_relative_offset
=False,
606 use_edge_rail
=True, thickness
=0.0, depth
=0.0, use_outset
=False,
607 use_select_inset
=False, use_individual
=True, use_interpolate
=True):
609 bpy
.ops
.object.mode_set(mode
='EDIT')
611 use_boundary
=use_boundary
, use_even_offset
=True, use_relative_offset
=False,
612 use_edge_rail
=True, thickness
=thickness
, depth
=depth
, use_outset
=use_outset
,
613 use_select_inset
=use_select_inset
, use_individual
=use_individual
,
614 use_interpolate
=use_interpolate
617 bpy
.ops
.object.mode_set(mode
='OBJECT')
619 # PKHG>IMFO only 3 parameters inc execution context supported!!
622 use_boundary
, use_even_offset
, use_relative_offset
, use_edge_rail
,
623 thickness
, depth
, use_outset
, use_select_inset
, use_individual
,
628 use_boundary
=True, use_even_offset
=True, use_relative_offset
=False,
629 use_edge_rail
=True, thickness
=thickness
, depth
=depth
, use_outset
=False,
630 use_select_inset
=False, use_individual
=True, use_interpolate
=True
634 use_boundary
=True, use_even_offset
=True, use_relative_offset
=False,
635 use_edge_rail
=True, thickness
=thickness
, depth
=depth
, use_outset
=False,
636 use_select_inset
=False, use_individual
=True, use_interpolate
=False
638 bpy
.ops
.mesh
.delete(type='FACE')
642 use_boundary
=True, use_even_offset
=False, use_relative_offset
=True,
643 use_edge_rail
=True, thickness
=thickness
, depth
=depth
, use_outset
=False,
644 use_select_inset
=False, use_individual
=True, use_interpolate
=False
647 bpy
.ops
.mesh
.delete(type='FACE')
651 use_boundary
=True, use_even_offset
=False, use_relative_offset
=True,
652 use_edge_rail
=True, thickness
=depth
, depth
=thickness
, use_outset
=False,
653 use_select_inset
=False, use_individual
=True, use_interpolate
=True
655 bpy
.ops
.mesh
.delete(type='FACE')
658 use_boundary
=True, use_even_offset
=False, use_relative_offset
=True,
659 use_edge_rail
=True, thickness
=thickness
, depth
=depth
, use_outset
=True,
660 use_select_inset
=False, use_individual
=True, use_interpolate
=True
663 use_boundary
=True, use_even_offset
=False, use_relative_offset
=True,
664 use_edge_rail
=True, thickness
=thickness
, depth
=depth
, use_outset
=True,
665 use_select_inset
=False, use_individual
=True, use_interpolate
=True
667 bpy
.ops
.mesh
.delete(type='FACE')
669 bpy
.ops
.object.mode_set(mode
='OBJECT')
672 def check_is_selected():
674 for face
in bpy
.context
.active_object
.data
.polygons
:
681 def prepare(self
, context
, remove_start_faces
=True):
683 Start for a face selected change of faces
684 select an object of type mesh, with activated several (all) faces
686 obj
= bpy
.context
.view_layer
.objects
.active
687 bpy
.ops
.object.mode_set(mode
='OBJECT')
688 selectedpolygons
= [el
for el
in obj
.data
.polygons
if el
.select
]
690 # PKHG>INFO copies of the vectors are needed, otherwise Blender crashes!
691 centers
= [face
.center
for face
in selectedpolygons
]
692 centers_copy
= [Vector((el
[0], el
[1], el
[2])) for el
in centers
]
693 normals
= [face
.normal
for face
in selectedpolygons
]
694 normals_copy
= [Vector((el
[0], el
[1], el
[2])) for el
in normals
]
696 vertindicesofpolgons
= [
697 [vert
for vert
in face
.vertices
] for face
in selectedpolygons
699 vertVectorsOfSelectedFaces
= [
700 [obj
.data
.vertices
[ind
].co
for ind
in vertIndiceofface
] for
701 vertIndiceofface
in vertindicesofpolgons
703 vertVectorsOfSelectedFaces_copy
= [
704 [Vector((el
[0], el
[1], el
[2])) for el
in listofvecs
] for
705 listofvecs
in vertVectorsOfSelectedFaces
708 bpy
.ops
.object.mode_set(mode
='EDIT')
709 bm
= bmesh
.from_edit_mesh(obj
.data
)
710 selected_bm_faces
= [ele
for ele
in bm
.faces
if ele
.select
]
712 selected_edges_per_face_ind
= [
713 [ele
.index
for ele
in face
.edges
] for face
in selected_bm_faces
715 indices
= [el
.index
for el
in selectedpolygons
]
716 selected_faces_areas
= [bm
.faces
[:][i
] for i
in indices
]
717 tmp_area
= [el
.calc_area() for el
in selected_faces_areas
]
719 # PKHG>INFO, selected faces are removed, only their edges are used!
720 if remove_start_faces
:
721 bpy
.ops
.mesh
.delete(type='ONLY_FACE')
722 bpy
.ops
.object.mode_set(mode
='OBJECT')
724 bpy
.ops
.object.mode_set(mode
='EDIT')
725 bm
= bmesh
.from_edit_mesh(obj
.data
)
726 bm
.verts
.ensure_lookup_table()
727 bm
.faces
.ensure_lookup_table()
730 [bm
.verts
[ind
].index
for ind
in vertIndiceofface
] for
731 vertIndiceofface
in vertindicesofpolgons
735 for el
in start_ring_raw
:
736 start_ring
.append(set(el
))
737 bm
.edges
.ensure_lookup_table()
739 bm_selected_edges_l_l
= [
740 [bm
.edges
[i
] for i
in bm_ind_list
] for
741 bm_ind_list
in selected_edges_per_face_ind
744 'obj': obj
, 'centers': centers_copy
, 'normals': normals_copy
,
745 'rings': vertVectorsOfSelectedFaces_copy
, 'bm': bm
,
746 'areas': tmp_area
, 'startBMRingVerts': start_ring
,
747 'base_edges': bm_selected_edges_l_l
753 def make_one_inset(self
, context
, bm
=None, ringvectors
=None, center
=None,
754 normal
=None, t
=None, base_height
=0):
755 # a face will get 'inserted' faces to create (normally) a hole if t is > 0 and < 1)
758 for el
in ringvectors
:
759 tmp
.append((el
* (1 - t
) + center
* t
) + normal
* base_height
)
761 tmp
= [bm
.verts
.new(v
) for v
in tmp
] # the new corner bmvectors
762 # PKHG>INFO so to say sentinells, to use ONE for ...
764 vectorsFace_i
= [bm
.verts
.new(v
) for v
in ringvectors
]
765 vectorsFace_i
.append(vectorsFace_i
[0])
767 for ii
in range(len(vectorsFace_i
) - 1):
768 # PKHG>INFO next line: sequence is important! for added edge
769 bmvecs
= [vectorsFace_i
[ii
], vectorsFace_i
[ii
+ 1], tmp
[ii
+ 1], tmp
[ii
]]
770 res
= bm
.faces
.new(bmvecs
)
771 myres
.append(res
.edges
[2])
772 myres
[-1].select
= True # PKHG>INFO to be used later selected!
776 def extrude_faces(self
, context
, bm
=None, face_l
=None):
777 # to make a ring extrusion
778 res
= bmesh
.ops
.extrude_discrete_faces(bm
, faces
=face_l
)['faces']
785 def extrude_edges(self
, context
, bm
=None, edge_l_l
=None):
786 # to make a ring extrusion
788 for edge_l
in edge_l_l
:
791 res
= bmesh
.ops
.extrude_edge_only(bm
, edges
=edge_l
)
792 tmp
= [ele
for ele
in res
['geom'] if isinstance(ele
, bmesh
.types
.BMEdge
)]
795 all_results
.append(tmp
)
799 def translate_ONE_ring(self
, context
, bm
=None, object_matrix
=None, ring_edges
=None,
800 normal
=(0, 0, 1), distance
=0.5):
801 # translate a ring in given (normal?!) direction with given (global) amount
803 for edge
in ring_edges
:
804 tmp
.extend(edge
.verts
[:])
805 # PKHG>INFO no double vertices allowed by bmesh!
808 bmesh
.ops
.translate(bm
, vec
=normal
* distance
, space
=object_matrix
, verts
=tmp
)
809 # PKHG>INFO relevant edges will stay selected
813 def move_corner_vecs_outside(self
, context
, bm
=None, edge_list
=None, center
=None,
814 normal
=None, base_height_erlier
=0.5, distance
=0.5):
815 # move corners (outside meant mostly) dependent on the parameters
817 for edge
in edge_list
:
818 tmp
.extend([ele
for ele
in edge
.verts
if isinstance(ele
, bmesh
.types
.BMVert
)])
819 # PKHG>INFO to remove vertices, they are all used twice in the ring!
823 for i
in range(len(tmp
)):
825 direction
= vec
+ (vec
- (normal
* base_height_erlier
+ center
)) * distance
826 tmp
[i
].co
= direction
828 # define classes for registration
830 MESH_OT_add_faces_to_object
,
835 bpy
.utils
.register_class(cls
)
840 bpy
.utils
.unregister_class(cls
)
843 if __name__
== "__main__":