new addon simple_deform_helper #104464
@ -17,10 +17,10 @@ class Handler:
|
||||
|
||||
@classmethod
|
||||
def del_handler_text(cls):
|
||||
if 'handler_text' in cls.G_GizmoData:
|
||||
if 'scale_text' in cls.G_GizmoData:
|
||||
bpy.types.SpaceView3D.draw_handler_remove(
|
||||
cls.G_GizmoData['handler_text'], 'WINDOW')
|
||||
cls.G_GizmoData.pop('handler_text')
|
||||
cls.G_GizmoData['scale_text'], 'WINDOW')
|
||||
cls.G_GizmoData.pop('scale_text')
|
||||
|
||||
@classmethod
|
||||
def del_handler(cls):
|
||||
@ -75,8 +75,6 @@ class DrawText:
|
||||
f'The scaling value of the object {obj.name_full} is not 1,'
|
||||
f' which will cause the deformation of the simple deformation modifier.'
|
||||
f' Please apply the scaling before deformation')
|
||||
if obj.scale == Vector((1, 1, 1)):
|
||||
cls.del_handler_text()
|
||||
|
||||
@classmethod
|
||||
def draw_text(cls, x, y, text='Hello Word', font_id=0, size=10, *, color=(0.5, 0.5, 0.5, 1), dpi=72, column=0):
|
||||
@ -105,7 +103,7 @@ class Draw3D(GizmoUtils, DrawPublic, DrawText, Handler):
|
||||
self.draw_scale_text(obj)
|
||||
if not self.modifier_origin_angle_is_available:
|
||||
self.draw_bound_box()
|
||||
if self.simple_deform_show_gizmo_poll(context):
|
||||
elif self.simple_deform_show_gizmo_poll(context):
|
||||
# draw bound box
|
||||
self.draw_bound_box()
|
||||
self.draw_deform_mesh()
|
||||
@ -113,11 +111,10 @@ class Draw3D(GizmoUtils, DrawPublic, DrawText, Handler):
|
||||
self.draw_limits_bound_box()
|
||||
elif self.simple_deform_show_bend_axis_witch_poll(context):
|
||||
self.draw_bound_box()
|
||||
# self.new_empty(obj, modifier)
|
||||
|
||||
def draw_bound_box(self):
|
||||
coords = self.matrix_calculation(self.obj_matrix_world,
|
||||
self.tow_co_to_coordinate(self.get_bound_co_data()))
|
||||
self.tow_co_to_coordinate(self.modifier_bound_co))
|
||||
self.draw_3d_shader(coords, self.G_INDICES, self.pref.bound_box_color)
|
||||
|
||||
def draw_limits_bound_box(self):
|
||||
@ -143,8 +140,8 @@ class Draw3D(GizmoUtils, DrawPublic, DrawText, Handler):
|
||||
handler_dit = self.G_GizmoData
|
||||
active = self.modifier
|
||||
# draw deform mesh
|
||||
if 'draw' in handler_dit:
|
||||
pos, indices, mat, mod_data, limits = handler_dit['draw']
|
||||
if 'simple_deform_box_data' in handler_dit and self.pref.update_deform_wireframe:
|
||||
pos, indices, mat, mod_data, limits = handler_dit['simple_deform_box_data']
|
||||
if ([getattr(active, i) for i in self.G_MODIFIERS_PROPERTY] == mod_data) and (
|
||||
ob.matrix_world == mat) and limits == active.limits[:]:
|
||||
self.draw_3d_shader(
|
||||
@ -152,8 +149,8 @@ class Draw3D(GizmoUtils, DrawPublic, DrawText, Handler):
|
||||
|
||||
def draw_scale_text(self, ob):
|
||||
scale_error = (ob.scale != Vector((1, 1, 1)))
|
||||
if scale_error and ('handler_text' not in self.G_GizmoData):
|
||||
self.G_GizmoData['handler_text'] = bpy.types.SpaceView3D.draw_handler_add(
|
||||
if scale_error and ('scale_text' not in self.G_GizmoData):
|
||||
self.G_GizmoData['scale_text'] = bpy.types.SpaceView3D.draw_handler_add(
|
||||
self.draw_str, (), 'WINDOW', 'POST_PIXEL')
|
||||
|
||||
def draw_origin_error(self):
|
||||
|
@ -19,12 +19,11 @@ class AngleUpdate(GizmoUtils):
|
||||
new_value = (self.get_snap(value, tweak))
|
||||
old_value = math.degrees(self.target_get_value('angle'))
|
||||
|
||||
print(new_value, old_value)
|
||||
self.target_set_value('angle', math.radians(new_value))
|
||||
|
||||
def update_gizmo_matrix(self, context):
|
||||
matrix = context.object.matrix_world
|
||||
point = self.get_bound_co_data()[1]
|
||||
point = self.modifier_bound_co[1]
|
||||
self.matrix_basis = self.obj_matrix_world
|
||||
self.matrix_basis.translation = matrix @ point
|
||||
|
||||
@ -72,7 +71,7 @@ class AngleGizmo(Gizmo, AngleUpdate):
|
||||
|
||||
self.update_prop_value(event, tweak)
|
||||
self.update_header_text(context)
|
||||
self.update_deform_wireframe()
|
||||
self.update_multiple_modifiers_data()
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def exit(self, context, cancel):
|
||||
|
@ -53,7 +53,7 @@ class BendAxiSwitchGizmoGroup(GizmoGroup, GizmoGroupUtils):
|
||||
_color_b = 0, 1, 0
|
||||
|
||||
for na, axis, rot, positive in (
|
||||
('top_a', 'X', (math.radians(90), 0, math.radians(9 - 0)), True),
|
||||
('top_a', 'X', (math.radians(90), 0, math.radians(90)), True),
|
||||
('top_b', 'X', (math.radians(90), 0, 0), True),
|
||||
|
||||
('bottom_a', 'X', (math.radians(90), 0, math.radians(90)), False),
|
||||
@ -93,7 +93,7 @@ class BendAxiSwitchGizmoGroup(GizmoGroup, GizmoGroupUtils):
|
||||
def draw_prepare(self, context):
|
||||
ob = context.object
|
||||
mat = ob.matrix_world
|
||||
top, bottom, left, right, front, back = self.each_face_pos
|
||||
top, bottom, left, right, front, back = self.modifier_bound_box_pos
|
||||
|
||||
rad = math.radians
|
||||
for_list = (
|
||||
|
@ -10,7 +10,7 @@ class SetDeformGizmoGroup(GizmoGroup, GizmoGroupUtils):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return cls.simple_deform_show_gizmo_poll(context)
|
||||
return cls.simple_deform_show_gizmo_poll(context) and cls.pref_().show_set_axis_button
|
||||
|
||||
def setup(self, context):
|
||||
data_path = 'object.modifiers.active.deform_axis'
|
||||
@ -36,10 +36,13 @@ class SetDeformGizmoGroup(GizmoGroup, GizmoGroupUtils):
|
||||
def draw_prepare(self, context):
|
||||
|
||||
if 'co' in self.G_GizmoData:
|
||||
obj = self.get_depsgraph(self.obj)
|
||||
dimensions = obj.dimensions
|
||||
|
||||
def _mat(f):
|
||||
co = self.G_GizmoData['co'][0]
|
||||
co = (co[0] + (max(self.obj.dimensions) * f), co[1],
|
||||
co[2] - (min(self.obj.dimensions) * 0.3))
|
||||
co = (co[0] + (max(dimensions) * f), co[1],
|
||||
co[2] - (min(dimensions) * 0.3))
|
||||
return self.obj_matrix_world @ Vector(co)
|
||||
|
||||
self.deform_axis_x.matrix_basis.translation = _mat(0)
|
||||
|
@ -147,30 +147,6 @@ class GizmoUpdate(GizmoProperty):
|
||||
text += t('Down limit', value)
|
||||
context.area.header_text_set(text)
|
||||
|
||||
# def update_modifiers_origin_matrix(self):
|
||||
# ob = bpy.context.object
|
||||
# for mod in ob.modifiers:
|
||||
# if mod.type == 'SIMPLE_DEFORM':
|
||||
# self.update_matrix(mod, ob)
|
||||
#
|
||||
# def update_matrix(self, mod, ob):
|
||||
# # if mod.deform_method == 'BEND':
|
||||
# # cls.new_empty(ob, mod)
|
||||
# origin_object = mod.origin
|
||||
# if mod.origin:
|
||||
# modifiers_co = self.G_GizmoData['modifiers_co']
|
||||
# for index, mod_name in enumerate(modifiers_co):
|
||||
# co_items = list(modifiers_co.items())
|
||||
# if mod.name == mod_name:
|
||||
# data = co_items[index - 1][1] if (
|
||||
# index or (index != 1)) else modifiers_co['co']
|
||||
# (up, down), (up_, down_) = self.get_limits_pos(
|
||||
# mod, self.co_to_direction(ob.matrix_world.copy(), data))
|
||||
# origin_mode = self.obj_origin_property_group(
|
||||
# mod, ob).origin_mode
|
||||
# self.set_empty_obj_matrix(
|
||||
# origin_mode, origin_object, up_, down_, up, down)
|
||||
|
||||
|
||||
class UpDownLimitsGizmo(Gizmo, GizmoUpdate):
|
||||
bl_idname = 'UpDownLimitsGizmo'
|
||||
@ -234,7 +210,7 @@ class UpDownLimitsGizmo(Gizmo, GizmoUpdate):
|
||||
|
||||
self.set_prop_value(event)
|
||||
self.update_object_origin_matrix()
|
||||
self.update_deform_wireframe()
|
||||
self.update_multiple_modifiers_data()
|
||||
|
||||
self.update_header_text(context)
|
||||
return self.event_handle(event)
|
||||
|
@ -26,12 +26,11 @@ class DeformAxisOperator(Operator, GizmoUtils):
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def modal(self, context, event):
|
||||
from .gizmo.angle_and_factor import GizmoUtils
|
||||
|
||||
self.clear_cache()
|
||||
mod = context.object.modifiers.active
|
||||
mod.deform_axis = self.Deform_Axis
|
||||
empty, con_limit_name = GizmoUtils.new_origin_empty_object(context.object, mod)
|
||||
is_positive = GizmoUtils.is_positive(mod.angle)
|
||||
empty = self.new_origin_empty_object()
|
||||
is_positive = self.is_positive(mod.angle)
|
||||
|
||||
for limit, value in (('max_x', self.X_Value),
|
||||
('min_x', self.X_Value),
|
||||
@ -40,13 +39,14 @@ class DeformAxisOperator(Operator, GizmoUtils):
|
||||
('max_z', self.Z_Value),
|
||||
('min_z', self.Z_Value),
|
||||
):
|
||||
setattr(empty.constraints[con_limit_name], limit, value)
|
||||
setattr(empty.constraints[self.G_CON_LIMIT_NAME], limit, value)
|
||||
|
||||
if ((not is_positive) and self.Is_Positive) or (is_positive and (not self.Is_Positive)):
|
||||
mod.angle = mod.angle * -1
|
||||
|
||||
if not event.ctrl:
|
||||
self.pref.display_bend_axis_switch_gizmo = False
|
||||
# self.new_origin_empty_object()
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
@ -33,20 +33,21 @@ class SimpleDeformHelperToolPanel(Panel, GizmoUtils):
|
||||
layout.prop(ctrl_obj,
|
||||
'origin_mode',
|
||||
text='')
|
||||
|
||||
layout.prop(pref,
|
||||
'update_deform_wireframe',
|
||||
icon='MOD_WIREFRAME',
|
||||
text='Deform Wireframe')
|
||||
|
||||
layout.prop(pref,
|
||||
'modifiers_limits_tolerance',
|
||||
text='')
|
||||
|
||||
layout.prop(pref,
|
||||
'show_set_axis_button',
|
||||
icon='EMPTY_AXIS',
|
||||
text='')
|
||||
if mod.deform_method == 'BEND':
|
||||
layout.prop(pref,
|
||||
'display_bend_axis_switch_gizmo',
|
||||
toggle=1)
|
||||
layout.prop(pref,
|
||||
'modifiers_limits_tolerance',
|
||||
text='')
|
||||
|
||||
|
||||
class_list = (
|
||||
|
@ -53,8 +53,12 @@ class SimpleDeformGizmoAddonPreferences(AddonPreferences, GizmoUtils):
|
||||
options={'SKIP_SAVE'})
|
||||
|
||||
update_deform_wireframe: BoolProperty(
|
||||
name='Update Deform Wireframe',
|
||||
default=True)
|
||||
name='Show Deform Wireframe',
|
||||
default=False)
|
||||
|
||||
show_set_axis_button: BoolProperty(
|
||||
name='Show Set Axis Button',
|
||||
default=False)
|
||||
|
||||
def draw(self, context):
|
||||
col = self.layout.column()
|
||||
@ -64,6 +68,7 @@ class SimpleDeformGizmoAddonPreferences(AddonPreferences, GizmoUtils):
|
||||
col.prop(self, 'modifiers_limits_tolerance')
|
||||
col.prop(self, 'display_bend_axis_switch_gizmo')
|
||||
col.prop(self, 'update_deform_wireframe', icon='MOD_WIREFRAME', )
|
||||
col.prop(self, 'show_set_axis_button', icon='EMPTY_AXIS', )
|
||||
|
||||
def draw_header_tool_settings(self, context):
|
||||
if GizmoUtils.simple_deform_public_poll(context):
|
||||
|
@ -10,10 +10,10 @@ from .utils import GizmoUpdate
|
||||
def remove_not_use_empty(scene, dep):
|
||||
"""循环场景内的所有物体,找出没用的空物体并删掉
|
||||
"""
|
||||
GizmoUpdate.clear_cache()
|
||||
remove_name: str = "ViewSimpleDeformGizmo_"
|
||||
context = bpy.context
|
||||
if GizmoUpdate.simple_deform_modifier_is_simple(context):
|
||||
GizmoUpdate.clear_cache()
|
||||
for obj in context.scene.objects:
|
||||
is_empty = obj.type == "EMPTY"
|
||||
not_parent = not obj.parent
|
||||
|
@ -115,7 +115,8 @@ class PublicPoll(PublicClass):
|
||||
is_available_obj = available_modifiers_type and available_obj_type
|
||||
is_obj_mode = context.mode == 'OBJECT'
|
||||
show_mod = mod.show_viewport
|
||||
return is_available_obj and is_obj_mode and show_mod
|
||||
not_is_self_mesh = obj.name != cls.G_NAME
|
||||
return is_available_obj and is_obj_mode and show_mod and not_is_self_mesh
|
||||
|
||||
@classmethod
|
||||
def simple_deform_public_poll(cls, context: 'bpy.types.context') -> bool:
|
||||
@ -228,7 +229,7 @@ class PublicUtils(PublicPoll):
|
||||
list_vertices = np.zeros(ver_len * 3, dtype=np.float32)
|
||||
obj.data.points.foreach_get('co', list_vertices)
|
||||
list_vertices = list_vertices.reshape(ver_len, 3)
|
||||
return Vector(list_vertices.min(axis=0)), Vector(list_vertices.max(axis=0))
|
||||
return Vector(list_vertices.min(axis=0)).freeze(), Vector(list_vertices.max(axis=0)).freeze()
|
||||
|
||||
@classmethod
|
||||
def matrix_calculation(cls, mat: 'Matrix', calculation_list: 'list') -> list:
|
||||
@ -326,7 +327,7 @@ class PublicProperty(GizmoClassMethod):
|
||||
|
||||
@cache
|
||||
def _get_limits_point_and_bound_box_co(self):
|
||||
top, bottom, left, right, front, back = self.each_face_pos
|
||||
top, bottom, left, right, front, back = self.modifier_bound_box_pos
|
||||
mod = self.modifier
|
||||
g_l = self.__from_up_down_point_get_limits_point
|
||||
if self.modifier.origin:
|
||||
@ -381,14 +382,13 @@ class PublicProperty(GizmoClassMethod):
|
||||
# ----------------------
|
||||
|
||||
@cache
|
||||
def _each_face_pos(self, mat):
|
||||
return self.co_to_direction(mat, self.get_bound_co_data())
|
||||
def _each_face_pos(self, mat, co):
|
||||
return self.co_to_direction(mat, co)
|
||||
|
||||
@classmethod
|
||||
def clear_cache(cls):
|
||||
cls._each_face_pos.cache_clear()
|
||||
cls._get_limits_point_and_bound_box_co.cache_clear()
|
||||
cls.clear_data()
|
||||
|
||||
@classmethod
|
||||
def clear_data(cls):
|
||||
@ -399,7 +399,15 @@ class PublicProperty(GizmoClassMethod):
|
||||
|
||||
@property
|
||||
def each_face_pos(self):
|
||||
return self._each_face_pos(self.obj_matrix_world)
|
||||
return self._each_face_pos(self.obj_matrix_world, self.get_bound_co_data())
|
||||
|
||||
@property
|
||||
def modifier_bound_co(self):
|
||||
return self.G_GizmoData['modifiers_co'].get(self.modifier.name, self.get_bound_co_data())
|
||||
|
||||
@property
|
||||
def modifier_bound_box_pos(self):
|
||||
return self._each_face_pos(self.obj_matrix_world, self.modifier_bound_co)
|
||||
|
||||
@property
|
||||
def modifier_limits_point(self):
|
||||
@ -417,6 +425,7 @@ class PublicProperty(GizmoClassMethod):
|
||||
self._get_limits_point_and_bound_box_co()
|
||||
return True
|
||||
except UnboundLocalError:
|
||||
self.clear_cache()
|
||||
return False
|
||||
|
||||
# --------------- Compute Data ----------------------
|
||||
@ -532,13 +541,14 @@ class GizmoUpdate(PublicProperty):
|
||||
else:
|
||||
origin_object = mod.origin
|
||||
origin_object.hide_viewport = False
|
||||
|
||||
if origin_object == obj:
|
||||
return
|
||||
if origin_object.parent != obj:
|
||||
origin_object.parent = obj
|
||||
|
||||
# add constraints
|
||||
name = self.G_CON_LIMIT_NAME
|
||||
if origin_object.constraints.keys().__len__() > 1:
|
||||
if origin_object.constraints.keys().__len__() > 2:
|
||||
origin_object.constraints.clear()
|
||||
if name in origin_object.constraints.keys():
|
||||
limit_constraints = origin.constraints.get(name)
|
||||
@ -566,6 +576,8 @@ class GizmoUpdate(PublicProperty):
|
||||
origin_object.rotation_euler.zero()
|
||||
origin_object.scale = 1, 1, 1
|
||||
|
||||
return origin_object
|
||||
|
||||
def update_object_origin_matrix(self):
|
||||
self.clear_cache()
|
||||
origin_mode = self.origin_mode
|
||||
@ -582,29 +594,26 @@ class GizmoUpdate(PublicProperty):
|
||||
translation = (self.point_up + self.point_down) / 2
|
||||
empty_object.matrix_world.translation = translation
|
||||
|
||||
def update_deform_wireframe(self):
|
||||
if not self.pref.update_deform_wireframe:
|
||||
return
|
||||
context = bpy.context
|
||||
data = bpy.data
|
||||
def update_multiple_modifiers_data(self):
|
||||
self.clear_data()
|
||||
obj = self.obj
|
||||
data = bpy.data
|
||||
context = bpy.context
|
||||
|
||||
matrix = obj.matrix_world.copy() # 物体矩阵
|
||||
# add simple_deform mesh
|
||||
name = self.G_NAME
|
||||
|
||||
vertices = self.matrix_calculation(self.obj_matrix_world.inverted(), self.modifier_limits_bound_box)
|
||||
if data.objects.get(name):
|
||||
data.objects.remove(data.objects.get(name))
|
||||
|
||||
if data.meshes.get(name):
|
||||
data.meshes.remove(data.meshes.get(name))
|
||||
|
||||
vertices = self.tow_co_to_coordinate(self.get_bound_co_data())
|
||||
new_mesh = data.meshes.new(name)
|
||||
new_mesh.from_pydata(vertices, self.G_INDICES, [])
|
||||
new_mesh.update()
|
||||
|
||||
deform_obj = data.objects.get(name, None)
|
||||
if deform_obj and deform_obj.type == 'MESH':
|
||||
deform_obj.data = new_mesh
|
||||
else:
|
||||
if deform_obj:
|
||||
data.objects.remove(deform_obj)
|
||||
deform_obj = data.objects.new(name, new_mesh)
|
||||
deform_obj = data.objects.new(name, new_mesh)
|
||||
|
||||
self.link_obj_to_active_collection(deform_obj)
|
||||
if deform_obj == obj:
|
||||
@ -616,8 +625,12 @@ class GizmoUpdate(PublicProperty):
|
||||
subdivision = deform_obj.modifiers.new('1', 'SUBSURF')
|
||||
subdivision.levels = 7
|
||||
self.G_GizmoData['modifiers_co']['co'] = self.get_bound_co_data()
|
||||
|
||||
for mo in context.object.modifiers:
|
||||
if mo.type == 'SIMPLE_DEFORM':
|
||||
obj = self.get_depsgraph(deform_obj)
|
||||
self.G_GizmoData['modifiers_co'][mo.name] = self.get_mesh_max_min_co(
|
||||
obj)
|
||||
simple_deform = deform_obj.modifiers.new(
|
||||
mo.name, 'SIMPLE_DEFORM')
|
||||
simple_deform.deform_method = mo.deform_method
|
||||
@ -626,19 +639,23 @@ class GizmoUpdate(PublicProperty):
|
||||
simple_deform.lock_y = mo.lock_y
|
||||
simple_deform.lock_z = mo.lock_z
|
||||
simple_deform.origin = mo.origin
|
||||
# simple_deform.limits[1] = mo.limits[1]
|
||||
# simple_deform.limits[0] = mo.limits[0]
|
||||
simple_deform.limits[1] = mo.limits[1]
|
||||
simple_deform.limits[0] = mo.limits[0]
|
||||
simple_deform.angle = mo.angle
|
||||
simple_deform.show_viewport = mo.show_viewport
|
||||
obj = PublicUtils.get_depsgraph(deform_obj)
|
||||
self.G_GizmoData['modifiers_co'][mo.name] = self.get_mesh_max_min_co(
|
||||
obj)
|
||||
# deform_obj.hide_set(True)
|
||||
# deform_obj.hide_viewport = False
|
||||
# deform_obj.hide_select = True
|
||||
# deform_obj.hide_render = True
|
||||
# deform_obj.hide_viewport = True
|
||||
# deform_obj.hide_set(True)
|
||||
deform_obj.hide_select = True
|
||||
deform_obj.hide_set(True)
|
||||
deform_obj.hide_viewport = False
|
||||
self.update_deform_wireframe(self.get_depsgraph(deform_obj))
|
||||
deform_obj.hide_render = True
|
||||
deform_obj.hide_viewport = True
|
||||
deform_obj.hide_set(True)
|
||||
|
||||
def update_deform_wireframe(self, obj):
|
||||
if not self.pref.update_deform_wireframe:
|
||||
return
|
||||
context = bpy.context
|
||||
matrix = self.obj_matrix_world.copy()
|
||||
ver_len = obj.data.vertices.__len__()
|
||||
edge_len = obj.data.edges.__len__()
|
||||
|
||||
@ -667,7 +684,7 @@ class GizmoUpdate(PublicProperty):
|
||||
limits = context.object.modifiers.active.limits[:]
|
||||
modifiers = [getattr(context.object.modifiers.active, i)
|
||||
for i in self.G_MODIFIERS_PROPERTY]
|
||||
self.G_GizmoData['draw'] = (ver, indices, matrix, modifiers, limits)
|
||||
self.G_GizmoData['simple_deform_box_data'] = (ver, indices, matrix, modifiers, limits[:])
|
||||
|
||||
|
||||
class GizmoUtils(GizmoUpdate):
|
||||
|
Loading…
Reference in New Issue
Block a user