msh release
This commit is contained in:
parent
209197e4aa
commit
3987cc9ed5
82
__init__.py
82
__init__.py
@ -127,7 +127,7 @@ def add_capped_frustum(bm: bmesh.types.BMesh,
|
|||||||
# Bone → per-end matrices
|
# Bone → per-end matrices
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def _end_matrices(world_mat: Matrix, bone_matrix: Matrix, bone_length: float):
|
def _end_matrices(bone_matrix: Matrix, bone_length: float):
|
||||||
"""
|
"""
|
||||||
Return (head_mat, tail_mat) — world-space matrices for each bone end.
|
Return (head_mat, tail_mat) — world-space matrices for each bone end.
|
||||||
|
|
||||||
@ -160,15 +160,44 @@ def _end_matrices(world_mat: Matrix, bone_matrix: Matrix, bone_length: float):
|
|||||||
def _make(pos_local):
|
def _make(pos_local):
|
||||||
local_mat = orient.to_4x4()
|
local_mat = orient.to_4x4()
|
||||||
local_mat.col[3][:3] = pos_local
|
local_mat.col[3][:3] = pos_local
|
||||||
return world_mat @ local_mat
|
return local_mat
|
||||||
|
|
||||||
return _make(head_local), _make(tail_local)
|
return _make(head_local), _make(tail_local)
|
||||||
|
|
||||||
|
SUFFIX = "_envelope_mesh"
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Operator
|
# Operators
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ARMATURE_OT_release_mesh(bpy.types.Operator):
|
||||||
|
bl_idname = "armature.release_mesh"
|
||||||
|
bl_label = "Release Mesh"
|
||||||
|
bl_description = (
|
||||||
|
"Clear the target mesh reference from the panel. "
|
||||||
|
"Does not delete any objects or data, but allows the next build to create a new mesh."
|
||||||
|
)
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
obj = context.active_object
|
||||||
|
if obj is not None and obj.type == 'ARMATURE':
|
||||||
|
lookup_name = obj.name + SUFFIX
|
||||||
|
for child in obj.children:
|
||||||
|
if child.type == 'MESH' and child.name == lookup_name:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
obj = context.active_object
|
||||||
|
for child in obj.children:
|
||||||
|
if child.type == 'MESH' and child.name == obj.name + SUFFIX:
|
||||||
|
m = child.matrix_world.copy()
|
||||||
|
child.parent = None
|
||||||
|
child.matrix_world = m
|
||||||
|
child.name = child.name.replace(SUFFIX, "_snapshot")
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
class ARMATURE_OT_build_envelope_mesh(bpy.types.Operator):
|
class ARMATURE_OT_build_envelope_mesh(bpy.types.Operator):
|
||||||
bl_idname = "armature.build_envelope_mesh"
|
bl_idname = "armature.build_envelope_mesh"
|
||||||
bl_label = "Build Envelope Mesh"
|
bl_label = "Build Envelope Mesh"
|
||||||
@ -192,12 +221,11 @@ class ARMATURE_OT_build_envelope_mesh(bpy.types.Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
arm_obj = context.active_object
|
arm_obj = context.active_object
|
||||||
world_mat = arm_obj.matrix_world
|
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
tables = _Tables(self.segments)
|
tables = _Tables(self.segments)
|
||||||
|
|
||||||
def meshify(bone_matrix, bone_length, head_radius, tail_radius, draw_head=True):
|
def meshify(bone_matrix, bone_length, head_radius, tail_radius, draw_head=True):
|
||||||
head_mat, tail_mat = _end_matrices(world_mat, bone_matrix, bone_length)
|
head_mat, tail_mat = _end_matrices(bone_matrix, bone_length)
|
||||||
if draw_head:
|
if draw_head:
|
||||||
add_sphere(bm, head_mat, max(head_radius, 0.001), tables)
|
add_sphere(bm, head_mat, max(head_radius, 0.001), tables)
|
||||||
add_sphere(bm, tail_mat, max(tail_radius, 0.001), tables)
|
add_sphere(bm, tail_mat, max(tail_radius, 0.001), tables)
|
||||||
@ -217,8 +245,14 @@ class ARMATURE_OT_build_envelope_mesh(bpy.types.Operator):
|
|||||||
bone.bone.head_radius, bone.bone.tail_radius,
|
bone.bone.head_radius, bone.bone.tail_radius,
|
||||||
bone.parent is None)
|
bone.parent is None)
|
||||||
|
|
||||||
panel_props = context.scene.envelope_mesher
|
lookup_name = arm_obj.name + SUFFIX
|
||||||
target = panel_props.target
|
target = None
|
||||||
|
for child in arm_obj.children:
|
||||||
|
if child.type == 'MESH' and child.name == lookup_name:
|
||||||
|
target = child
|
||||||
|
break
|
||||||
|
|
||||||
|
print(target)
|
||||||
|
|
||||||
if target is not None:
|
if target is not None:
|
||||||
# Destructively replace the target's mesh data.
|
# Destructively replace the target's mesh data.
|
||||||
@ -231,30 +265,17 @@ class ARMATURE_OT_build_envelope_mesh(bpy.types.Operator):
|
|||||||
bpy.data.meshes.remove(old_mesh)
|
bpy.data.meshes.remove(old_mesh)
|
||||||
else:
|
else:
|
||||||
# Create a new object and hand it back to the panel picker.
|
# Create a new object and hand it back to the panel picker.
|
||||||
new_mesh = bpy.data.meshes.new(arm_obj.name + "_envelope_mesh")
|
new_mesh = bpy.data.meshes.new(lookup_name)
|
||||||
bm.to_mesh(new_mesh)
|
bm.to_mesh(new_mesh)
|
||||||
bm.free()
|
bm.free()
|
||||||
new_mesh.update()
|
new_mesh.update()
|
||||||
result_obj = bpy.data.objects.new(arm_obj.name + "_envelope", new_mesh)
|
result_obj = bpy.data.objects.new(lookup_name, new_mesh)
|
||||||
|
result_obj.parent = arm_obj
|
||||||
context.collection.objects.link(result_obj)
|
context.collection.objects.link(result_obj)
|
||||||
panel_props.target = result_obj
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Panel properties
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class EnvelopeMesherProperties(bpy.types.PropertyGroup):
|
|
||||||
target: bpy.props.PointerProperty(
|
|
||||||
name="Target",
|
|
||||||
description="Object whose mesh will be replaced on each run. "
|
|
||||||
"Leave empty to create a new object on first run.",
|
|
||||||
type=bpy.types.Object,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Panel
|
# Panel
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@ -268,9 +289,6 @@ class VIEW3D_PT_armature_mesher(bpy.types.Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
props = context.scene.envelope_mesher
|
|
||||||
|
|
||||||
layout.prop(props, "target")
|
|
||||||
|
|
||||||
op = layout.operator(
|
op = layout.operator(
|
||||||
ARMATURE_OT_build_envelope_mesh.bl_idname,
|
ARMATURE_OT_build_envelope_mesh.bl_idname,
|
||||||
@ -279,13 +297,19 @@ class VIEW3D_PT_armature_mesher(bpy.types.Panel):
|
|||||||
)
|
)
|
||||||
op.segments = 16
|
op.segments = 16
|
||||||
|
|
||||||
|
op = layout.operator(
|
||||||
|
ARMATURE_OT_release_mesh.bl_idname,
|
||||||
|
text="Release Mesh",
|
||||||
|
icon='OUTLINER_OB_MESH',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Registration
|
# Registration
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
EnvelopeMesherProperties,
|
ARMATURE_OT_release_mesh,
|
||||||
ARMATURE_OT_build_envelope_mesh,
|
ARMATURE_OT_build_envelope_mesh,
|
||||||
VIEW3D_PT_armature_mesher,
|
VIEW3D_PT_armature_mesher,
|
||||||
)
|
)
|
||||||
@ -293,12 +317,8 @@ classes = (
|
|||||||
def register():
|
def register():
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
bpy.types.Scene.envelope_mesher = bpy.props.PointerProperty(
|
|
||||||
type=EnvelopeMesherProperties,
|
|
||||||
)
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
del bpy.types.Scene.envelope_mesher
|
|
||||||
for cls in reversed(classes):
|
for cls in reversed(classes):
|
||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user