new addon simple_deform_helper #104464
@ -105,7 +105,6 @@ class Draw3D(GizmoUtils, DrawPublic, DrawText, Handler):
|
|||||||
self.draw_scale_text(obj)
|
self.draw_scale_text(obj)
|
||||||
if not self.modifier_origin_angle_is_available:
|
if not self.modifier_origin_angle_is_available:
|
||||||
self.draw_bound_box()
|
self.draw_bound_box()
|
||||||
...
|
|
||||||
if self.simple_deform_show_gizmo_poll(context):
|
if self.simple_deform_show_gizmo_poll(context):
|
||||||
# draw bound box
|
# draw bound box
|
||||||
self.draw_bound_box()
|
self.draw_bound_box()
|
||||||
@ -136,6 +135,8 @@ class Draw3D(GizmoUtils, DrawPublic, DrawText, Handler):
|
|||||||
# draw pos
|
# draw pos
|
||||||
self.draw_3d_shader([line_pos[1]], (), (0, 1, 0, 0.5),
|
self.draw_3d_shader([line_pos[1]], (), (0, 1, 0, 0.5),
|
||||||
shader_name='3D_UNIFORM_COLOR', draw_type='POINTS')
|
shader_name='3D_UNIFORM_COLOR', draw_type='POINTS')
|
||||||
|
self.draw_3d_shader([line_pos[0]], (), (1, 0, 0, 0.5),
|
||||||
|
shader_name='3D_UNIFORM_COLOR', draw_type='POINTS')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def draw_deform_mesh(cls, ob, context):
|
def draw_deform_mesh(cls, ob, context):
|
||||||
@ -151,8 +152,10 @@ class Draw3D(GizmoUtils, DrawPublic, DrawText, Handler):
|
|||||||
pos, indices, pref.deform_wireframe_color)
|
pos, indices, pref.deform_wireframe_color)
|
||||||
|
|
||||||
def draw_scale_text(self, ob):
|
def draw_scale_text(self, ob):
|
||||||
ob = self.obj
|
scale_error = (ob.scale != Vector((1, 1, 1)))
|
||||||
dit = self.G_GizmoData
|
if scale_error and ('handler_text' not in self.G_GizmoData):
|
||||||
if (ob.scale != Vector((1, 1, 1))) and ('handler_text' not in dit):
|
self.G_GizmoData['handler_text'] = bpy.types.SpaceView3D.draw_handler_add(
|
||||||
dit['handler_text'] = bpy.types.SpaceView3D.draw_handler_add(
|
|
||||||
self.draw_str, (), 'WINDOW', 'POST_PIXEL')
|
self.draw_str, (), 'WINDOW', 'POST_PIXEL')
|
||||||
|
|
||||||
|
def draw_origin_error(self):
|
||||||
|
...
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import math
|
import math
|
||||||
from typing import Callable, Any
|
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Gizmo, GizmoGroup
|
from bpy.types import Gizmo, GizmoGroup
|
||||||
@ -22,29 +21,13 @@ class GizmoProperty(GizmoUtils):
|
|||||||
def is_down_limits_mode(self):
|
def is_down_limits_mode(self):
|
||||||
return self.ctrl_mode == 'down_limits'
|
return self.ctrl_mode == 'down_limits'
|
||||||
|
|
||||||
@property
|
|
||||||
def origin_mode(self):
|
|
||||||
return self.SimpleDeformGizmo_origin_property_group.origin_mode
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_middle_mode(self):
|
|
||||||
return self.origin_mode in ('LIMITS_MIDDLE', 'MIDDLE')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def limit_scope(self):
|
def limit_scope(self):
|
||||||
return self.pref.modifiers_limits_tolerance
|
return self.pref.modifiers_limits_tolerance
|
||||||
|
|
||||||
@property
|
|
||||||
def difference_value(self):
|
|
||||||
return self.modifier_up_limits - self.modifier_down_limits
|
|
||||||
|
|
||||||
@property
|
|
||||||
def middle_value(self):
|
|
||||||
return (self.modifier_up_limits + self.modifier_down_limits) / 2
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def limits_min_value(self):
|
def limits_min_value(self):
|
||||||
return self.modifier_up_limits + self.limit_scope
|
return self.modifier_down_limits + self.limit_scope
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def limits_max_value(self):
|
def limits_max_value(self):
|
||||||
@ -54,39 +37,22 @@ class GizmoProperty(GizmoUtils):
|
|||||||
|
|
||||||
def get_up_limits_value(self, event):
|
def get_up_limits_value(self, event):
|
||||||
delta = self.get_delta(event)
|
delta = self.get_delta(event)
|
||||||
mid = self.middle_value + self.limit_scope
|
mid = self.middle_limits_value + self.limit_scope
|
||||||
min_value = mid if self.is_middle_mode else self.limits_min_value
|
min_value = mid if self.is_middle_mode else self.limits_min_value
|
||||||
return self.value_limit(delta, min_value=min_value)
|
return self.value_limit(delta, min_value=min_value)
|
||||||
|
|
||||||
def get_down_limits_value(self, event):
|
def get_down_limits_value(self, event):
|
||||||
delta = self.get_delta(event)
|
delta = self.get_delta(event)
|
||||||
mid = self.middle_value - self.limit_scope
|
mid = self.middle_limits_value - self.limit_scope
|
||||||
max_value = mid if self.is_middle_mode else self.limits_max_value
|
max_value = mid if self.is_middle_mode else self.limits_max_value
|
||||||
return self.value_limit(delta, max_value=max_value)
|
return self.value_limit(delta, max_value=max_value)
|
||||||
|
|
||||||
|
def get_delta(self, event):
|
||||||
class GizmoUpdate(GizmoProperty):
|
context = bpy.context
|
||||||
|
|
||||||
def update_gizmo_matrix(self, context):
|
|
||||||
self.align_orientation_to_user_perspective(context)
|
|
||||||
self.align_point_to_limits_point()
|
|
||||||
|
|
||||||
def align_orientation_to_user_perspective(self, context):
|
|
||||||
rotation = context.space_data.region_3d.view_matrix.inverted().to_quaternion()
|
|
||||||
matrix = rotation.to_matrix().to_4x4()
|
|
||||||
self.matrix_basis = matrix
|
|
||||||
|
|
||||||
def align_point_to_limits_point(self):
|
|
||||||
if self.is_up_limits_mode:
|
|
||||||
self.matrix_basis.translation = self.point_limits_up
|
|
||||||
elif self.is_down_limits_mode:
|
|
||||||
self.matrix_basis.translation = self.point_limits_down
|
|
||||||
|
|
||||||
def delta_update(self, context, event, delta):
|
|
||||||
x, y = view3d_utils.location_3d_to_region_2d(
|
x, y = view3d_utils.location_3d_to_region_2d(
|
||||||
context.region, context.space_data.region_3d, self.up)
|
context.region, context.space_data.region_3d, self.point_up)
|
||||||
x2, y2 = view3d_utils.location_3d_to_region_2d(
|
x2, y2 = view3d_utils.location_3d_to_region_2d(
|
||||||
context.region, context.space_data.region_3d, self.down)
|
context.region, context.space_data.region_3d, self.point_down)
|
||||||
|
|
||||||
mouse_line_distance = math.sqrt(((event.mouse_region_x - x2) ** 2) +
|
mouse_line_distance = math.sqrt(((event.mouse_region_x - x2) ** 2) +
|
||||||
((event.mouse_region_y - y2) ** 2))
|
((event.mouse_region_y - y2) ** 2))
|
||||||
@ -104,20 +70,43 @@ class GizmoUpdate(GizmoProperty):
|
|||||||
angle_ = mouse_angle.angle(limits_angle)
|
angle_ = mouse_angle.angle(limits_angle)
|
||||||
if angle_ > (math.pi / 2):
|
if angle_ > (math.pi / 2):
|
||||||
delta = 0
|
delta = 0
|
||||||
|
|
||||||
return delta
|
return delta
|
||||||
|
|
||||||
|
|
||||||
|
class GizmoUpdate(GizmoProperty):
|
||||||
|
# ---update gizmo matrix
|
||||||
|
def update_gizmo_matrix(self, context):
|
||||||
|
self.align_orientation_to_user_perspective(context)
|
||||||
|
self.align_point_to_limits_point()
|
||||||
|
|
||||||
|
def align_orientation_to_user_perspective(self, context):
|
||||||
|
rotation = context.space_data.region_3d.view_matrix.inverted().to_quaternion()
|
||||||
|
matrix = rotation.to_matrix().to_4x4()
|
||||||
|
self.matrix_basis = matrix
|
||||||
|
|
||||||
|
def align_point_to_limits_point(self):
|
||||||
|
if self.is_up_limits_mode:
|
||||||
|
self.matrix_basis.translation = self.point_limits_up
|
||||||
|
elif self.is_down_limits_mode:
|
||||||
|
self.matrix_basis.translation = self.point_limits_down
|
||||||
|
|
||||||
|
# ---- set prop
|
||||||
|
def set_prop_value(self, event):
|
||||||
|
if self.is_up_limits_mode:
|
||||||
|
self.set_up_value(event)
|
||||||
|
elif self.is_down_limits_mode:
|
||||||
|
self.set_down_value(event)
|
||||||
|
|
||||||
def set_down_value(self, event):
|
def set_down_value(self, event):
|
||||||
value = self.get_down_limits_value(event)
|
value = self.get_down_limits_value(event)
|
||||||
self.target_set_value('down_limits', value)
|
self.target_set_value('down_limits', value)
|
||||||
if event.ctrl:
|
if event.ctrl:
|
||||||
self.target_set_value(
|
self.target_set_value('up_limits', value + self.difference_value)
|
||||||
'up_limits', value + self.difference_value)
|
|
||||||
|
|
||||||
elif self.is_middle_mode:
|
elif self.is_middle_mode:
|
||||||
if self.origin_mode == 'LIMITS_MIDDLE':
|
if self.origin_mode == 'LIMITS_MIDDLE':
|
||||||
mu = self.middle_value
|
mu = self.middle_limits_value
|
||||||
self.target_set_value('up_limits', mu - (value - mu))
|
v = mu - (value - mu)
|
||||||
|
self.target_set_value('up_limits', v)
|
||||||
elif self.origin_mode == 'MIDDLE':
|
elif self.origin_mode == 'MIDDLE':
|
||||||
self.target_set_value('up_limits', 1 - value)
|
self.target_set_value('up_limits', 1 - value)
|
||||||
else:
|
else:
|
||||||
@ -129,12 +118,12 @@ class GizmoUpdate(GizmoProperty):
|
|||||||
value = self.get_up_limits_value(event)
|
value = self.get_up_limits_value(event)
|
||||||
self.target_set_value('up_limits', value)
|
self.target_set_value('up_limits', value)
|
||||||
if event.ctrl:
|
if event.ctrl:
|
||||||
self.target_set_value(
|
self.target_set_value('down_limits', value - self.difference_value)
|
||||||
'down_limits', value - self.difference_value)
|
|
||||||
elif self.is_middle_mode:
|
elif self.is_middle_mode:
|
||||||
if self.origin_mode == 'LIMITS_MIDDLE':
|
if self.origin_mode == 'LIMITS_MIDDLE':
|
||||||
mu = self.middle_value
|
mu = self.middle_limits_value
|
||||||
self.target_set_value('down_limits', mu - (value - mu))
|
value = mu - (value - mu)
|
||||||
|
self.target_set_value('down_limits', value)
|
||||||
elif self.origin_mode == 'MIDDLE':
|
elif self.origin_mode == 'MIDDLE':
|
||||||
self.target_set_value('down_limits', 1 - value)
|
self.target_set_value('down_limits', 1 - value)
|
||||||
else:
|
else:
|
||||||
@ -142,14 +131,9 @@ class GizmoUpdate(GizmoProperty):
|
|||||||
else:
|
else:
|
||||||
self.target_set_value('down_limits', self.modifier_down_limits)
|
self.target_set_value('down_limits', self.modifier_down_limits)
|
||||||
|
|
||||||
def set_prop_value(self, event):
|
# -------
|
||||||
if self.is_up_limits_mode:
|
|
||||||
self.set_up_value(event)
|
|
||||||
elif self.is_down_limits_mode:
|
|
||||||
self.set_down_value(event)
|
|
||||||
|
|
||||||
def update_header_text(self, context):
|
def update_header_text(self, context):
|
||||||
origin = self.SimpleDeformGizmo_origin_property_group
|
origin = self.obj_origin_property_group
|
||||||
mode = origin.bl_rna.properties['origin_mode'].enum_items[origin.origin_mode].name
|
mode = origin.bl_rna.properties['origin_mode'].enum_items[origin.origin_mode].name
|
||||||
|
|
||||||
t = self.translate_header_text
|
t = self.translate_header_text
|
||||||
@ -157,30 +141,35 @@ class GizmoUpdate(GizmoProperty):
|
|||||||
|
|
||||||
if self.is_up_limits_mode:
|
if self.is_up_limits_mode:
|
||||||
value = round(self.modifier_up_limits, 3)
|
value = round(self.modifier_up_limits, 3)
|
||||||
text += t('Upper limit', value)
|
text += t('Up limit', value)
|
||||||
elif self.is_down_limits_mode:
|
elif self.is_down_limits_mode:
|
||||||
value = round(self.modifier_down_limits, 3)
|
value = round(self.modifier_down_limits, 3)
|
||||||
text += t('Down limit', value)
|
text += t('Down limit', value)
|
||||||
context.area.header_text_set(text)
|
context.area.header_text_set(text)
|
||||||
|
|
||||||
def event_ops(self, event, ob, origin):
|
# def update_modifiers_origin_matrix(self):
|
||||||
"""通过输入键位来更改属性"""
|
# ob = bpy.context.object
|
||||||
# event ctrl
|
# for mod in ob.modifiers:
|
||||||
data_path = ('object.SimpleDeformGizmo_PropertyGroup.origin_mode',
|
# if mod.type == 'SIMPLE_DEFORM':
|
||||||
'object.modifiers.active.origin.SimpleDeformGizmo_PropertyGroup.origin_mode')
|
# self.update_matrix(mod, ob)
|
||||||
|
#
|
||||||
if event.type in ('WHEELUPMOUSE', 'WHEELDOWNMOUSE'):
|
# def update_matrix(self, mod, ob):
|
||||||
reverse = (event.type == 'WHEELUPMOUSE')
|
# # if mod.deform_method == 'BEND':
|
||||||
for path in data_path:
|
# # cls.new_empty(ob, mod)
|
||||||
bpy.ops.wm.context_cycle_enum(
|
# origin_object = mod.origin
|
||||||
data_path=path, reverse=reverse, wrap=True)
|
# if mod.origin:
|
||||||
elif event.type in ('X', 'Y', 'Z'):
|
# modifiers_co = self.G_GizmoData['modifiers_co']
|
||||||
ob.modifiers.active.deform_axis = event.type
|
# for index, mod_name in enumerate(modifiers_co):
|
||||||
elif event.type == 'A':
|
# co_items = list(modifiers_co.items())
|
||||||
self.pref.display_bend_axis_switch_gizmo = True
|
# if mod.name == mod_name:
|
||||||
return {'FINISHED'}
|
# data = co_items[index - 1][1] if (
|
||||||
|
# index or (index != 1)) else modifiers_co['co']
|
||||||
return {'RUNNING_MODAL'}
|
# (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):
|
class UpDownLimitsGizmo(Gizmo, GizmoUpdate):
|
||||||
@ -190,6 +179,7 @@ class UpDownLimitsGizmo(Gizmo, GizmoUpdate):
|
|||||||
{'id': 'up_limits', 'type': 'FLOAT', 'array_length': 1},
|
{'id': 'up_limits', 'type': 'FLOAT', 'array_length': 1},
|
||||||
{'id': 'down_limits', 'type': 'FLOAT', 'array_length': 1},
|
{'id': 'down_limits', 'type': 'FLOAT', 'array_length': 1},
|
||||||
)
|
)
|
||||||
|
bl_options = {'UNDO', 'GRAB_CURSOR'}
|
||||||
|
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
'mod',
|
'mod',
|
||||||
@ -198,12 +188,16 @@ class UpDownLimitsGizmo(Gizmo, GizmoUpdate):
|
|||||||
'draw_type',
|
'draw_type',
|
||||||
'mouse_dpi',
|
'mouse_dpi',
|
||||||
'ctrl_mode',
|
'ctrl_mode',
|
||||||
|
'difference_value',
|
||||||
|
'middle_limits_value',
|
||||||
'init_mouse_region_y',
|
'init_mouse_region_y',
|
||||||
'init_mouse_region_x',
|
'init_mouse_region_x',
|
||||||
'custom_shape',
|
'custom_shape',
|
||||||
'int_value_up_limits',
|
'int_value_up_limits',
|
||||||
'int_value_down_limits',
|
'int_value_down_limits',
|
||||||
)
|
)
|
||||||
|
difference_value: float
|
||||||
|
middle_limits_value: float
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.mouse_dpi = 10
|
self.mouse_dpi = 10
|
||||||
@ -232,15 +226,17 @@ class UpDownLimitsGizmo(Gizmo, GizmoUpdate):
|
|||||||
def modal(self, context, event, tweak):
|
def modal(self, context, event, tweak):
|
||||||
self.clear_cache()
|
self.clear_cache()
|
||||||
|
|
||||||
|
if self.modifier_is_use_origin_axis:
|
||||||
|
self.new_origin_empty_object()
|
||||||
|
|
||||||
|
self.difference_value = self.modifier_up_limits - self.modifier_down_limits
|
||||||
|
self.middle_limits_value = (self.modifier_up_limits + self.modifier_down_limits) / 2
|
||||||
|
|
||||||
self.set_prop_value(event)
|
self.set_prop_value(event)
|
||||||
if self.SimpleDeformGizmo_is_use_empty_as_axis:
|
self.update_object_origin_matrix()
|
||||||
self.new_empty(self.obj, self.modifier)
|
|
||||||
# self.update_empty_matrix()
|
|
||||||
|
|
||||||
# self.update_header_text(context, mod, origin, up_limits, down_limits)
|
self.update_header_text(context)
|
||||||
|
return self.event_handle(event)
|
||||||
# return self.event_ops(event, ob, origin)
|
|
||||||
return {'RUNNING_MODAL'}
|
|
||||||
|
|
||||||
|
|
||||||
class UpDownLimitsGizmoGroup(GizmoGroup, GizmoGroupUtils):
|
class UpDownLimitsGizmoGroup(GizmoGroup, GizmoGroupUtils):
|
||||||
@ -286,15 +282,3 @@ class UpDownLimitsGizmoGroup(GizmoGroup, GizmoGroupUtils):
|
|||||||
for i in (self.down_limits, self.up_limits):
|
for i in (self.down_limits, self.up_limits):
|
||||||
for j in ('down_limits', 'up_limits'):
|
for j in ('down_limits', 'up_limits'):
|
||||||
i.target_set_prop(j, pro, j)
|
i.target_set_prop(j, pro, j)
|
||||||
self.down_limits.target_set_prop('down_limits',
|
|
||||||
pro,
|
|
||||||
'down_limits')
|
|
||||||
self.down_limits.target_set_prop('up_limits',
|
|
||||||
pro,
|
|
||||||
'up_limits')
|
|
||||||
self.up_limits.target_set_prop('down_limits',
|
|
||||||
pro,
|
|
||||||
'down_limits')
|
|
||||||
self.up_limits.target_set_prop('up_limits',
|
|
||||||
pro,
|
|
||||||
'up_limits')
|
|
||||||
|
@ -30,7 +30,7 @@ class DeformAxisOperator(Operator, GizmoUtils):
|
|||||||
|
|
||||||
mod = context.object.modifiers.active
|
mod = context.object.modifiers.active
|
||||||
mod.deform_axis = self.Deform_Axis
|
mod.deform_axis = self.Deform_Axis
|
||||||
empty, con_limit_name = GizmoUtils.new_empty(context.object, mod)
|
empty, con_limit_name = GizmoUtils.new_origin_empty_object(context.object, mod)
|
||||||
is_positive = GizmoUtils.is_positive(mod.angle)
|
is_positive = GizmoUtils.is_positive(mod.angle)
|
||||||
|
|
||||||
for limit, value in (('max_x', self.X_Value),
|
for limit, value in (('max_x', self.X_Value),
|
||||||
|
@ -278,65 +278,6 @@ class PublicUtils(PublicPoll):
|
|||||||
|
|
||||||
|
|
||||||
class GizmoClassMethod(PublicUtils):
|
class GizmoClassMethod(PublicUtils):
|
||||||
@classmethod
|
|
||||||
def new_empty(cls, obj, mod):
|
|
||||||
origin = mod.origin
|
|
||||||
if origin is None:
|
|
||||||
new_name = cls.G_NAME + '_Empty_' + str(uuid.uuid4())
|
|
||||||
origin_object = bpy.data.objects.new(new_name, None)
|
|
||||||
cls.link_obj_to_active_collection(origin_object)
|
|
||||||
origin_object.hide_set(True)
|
|
||||||
origin_object.empty_display_size = min(obj.dimensions)
|
|
||||||
mod.origin = origin_object
|
|
||||||
else:
|
|
||||||
origin_object = mod.origin
|
|
||||||
origin_object.hide_viewport = False
|
|
||||||
|
|
||||||
if origin_object.parent != obj:
|
|
||||||
origin_object.parent = obj
|
|
||||||
|
|
||||||
# add constraints
|
|
||||||
con_name = cls.G_CON_LIMIT_NAME
|
|
||||||
if con_name in origin_object.constraints.keys():
|
|
||||||
limit_constraints = origin.constraints.get(con_name)
|
|
||||||
else:
|
|
||||||
limit_constraints = origin_object.constraints.new(
|
|
||||||
'LIMIT_ROTATION')
|
|
||||||
limit_constraints.name = con_name
|
|
||||||
limit_constraints.owner_space = 'WORLD'
|
|
||||||
limit_constraints.space_object = obj
|
|
||||||
limit_constraints.use_transform_limit = True
|
|
||||||
limit_constraints.use_limit_x = True
|
|
||||||
limit_constraints.use_limit_y = True
|
|
||||||
limit_constraints.use_limit_z = True
|
|
||||||
con_copy_name = cls.G_NAME + 'constraints_copy_rotation'
|
|
||||||
if con_copy_name in origin_object.constraints.keys():
|
|
||||||
copy_constraints = origin.constraints.get(con_copy_name)
|
|
||||||
else:
|
|
||||||
copy_constraints = origin_object.constraints.new(
|
|
||||||
'COPY_ROTATION')
|
|
||||||
copy_constraints.name = con_copy_name
|
|
||||||
copy_constraints.target = obj
|
|
||||||
copy_constraints.mix_mode = 'BEFORE'
|
|
||||||
copy_constraints.target_space = 'WORLD'
|
|
||||||
copy_constraints.owner_space = 'WORLD'
|
|
||||||
origin_object.rotation_euler.zero()
|
|
||||||
origin_object.scale = 1, 1, 1
|
|
||||||
return origin_object, con_name
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_empty_obj_matrix(cls, origin_mode, empty_object, up_, down_, up, down):
|
|
||||||
tow = Vector((2, 2, 2))
|
|
||||||
if origin_mode == 'UP_LIMITS':
|
|
||||||
empty_object.matrix_world.translation = Vector(up_)
|
|
||||||
elif origin_mode == 'DOWN_LIMITS':
|
|
||||||
empty_object.matrix_world.translation = Vector(
|
|
||||||
down_)
|
|
||||||
elif origin_mode == 'LIMITS_MIDDLE':
|
|
||||||
empty_object.matrix_world.translation = (up_ + down_) / tow
|
|
||||||
elif origin_mode == 'MIDDLE':
|
|
||||||
empty_object.matrix_world.translation = (up + down) / tow
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_vector_axis(cls, mod):
|
def get_vector_axis(cls, mod):
|
||||||
axis = mod.deform_axis
|
axis = mod.deform_axis
|
||||||
@ -550,7 +491,7 @@ class PublicProperty(GizmoClassMethod):
|
|||||||
# ------
|
# ------
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def SimpleDeformGizmo_origin_property_group(self):
|
def obj_origin_property_group(self):
|
||||||
mod = self.modifier
|
mod = self.modifier
|
||||||
if mod.origin:
|
if mod.origin:
|
||||||
return mod.origin.SimpleDeformGizmo_PropertyGroup
|
return mod.origin.SimpleDeformGizmo_PropertyGroup
|
||||||
@ -558,132 +499,179 @@ class PublicProperty(GizmoClassMethod):
|
|||||||
return self.obj.SimpleDeformGizmo_PropertyGroup
|
return self.obj.SimpleDeformGizmo_PropertyGroup
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def SimpleDeformGizmo_is_use_empty_as_axis(self):
|
def origin_mode(self):
|
||||||
return self.SimpleDeformGizmo_origin_property_group.origin_mode != 'NOT'
|
return self.obj_origin_property_group.origin_mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_limits_middle_mode(self):
|
||||||
|
return self.origin_mode == 'LIMITS_MIDDLE'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_middle_mode(self):
|
||||||
|
return self.origin_mode in ('LIMITS_MIDDLE', 'MIDDLE')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def modifier_is_use_origin_axis(self):
|
||||||
|
return self.obj_origin_property_group.origin_mode != 'NOT'
|
||||||
|
|
||||||
|
|
||||||
class GizmoUpdate(PublicProperty):
|
class GizmoUpdate(PublicProperty):
|
||||||
|
|
||||||
@classmethod
|
def new_origin_empty_object(self):
|
||||||
def update_matrix(cls, mod, ob):
|
mod = self.modifier
|
||||||
if mod.deform_method == 'BEND':
|
obj = self.obj
|
||||||
cls.new_empty(ob, mod)
|
origin = mod.origin
|
||||||
if mod.origin:
|
if not origin:
|
||||||
empty_object = mod.origin
|
new_name = self.G_NAME + '_Empty_' + str(uuid.uuid4())
|
||||||
modifiers_co = cls.G_GizmoData['modifiers_co']
|
origin_object = bpy.data.objects.new(new_name, None)
|
||||||
for index, mod_name in enumerate(modifiers_co):
|
self.link_obj_to_active_collection(origin_object)
|
||||||
co_items = list(modifiers_co.items())
|
origin_object.hide_set(True)
|
||||||
if mod.name == mod_name:
|
origin_object.empty_display_size = min(obj.dimensions)
|
||||||
data = co_items[index - 1][1] if (
|
mod.origin = origin_object
|
||||||
index or (index != 1)) else modifiers_co['co']
|
else:
|
||||||
(up, down), (up_, down_) = cls.get_limits_pos(
|
origin_object = mod.origin
|
||||||
mod, cls.co_to_direction(ob.matrix_world.copy(), data))
|
origin_object.hide_viewport = False
|
||||||
origin_mode = cls.SimpleDeformGizmo_origin_property_group(
|
|
||||||
mod, ob).origin_mode
|
|
||||||
cls.set_empty_obj_matrix(
|
|
||||||
origin_mode, empty_object, up_, down_, up, down)
|
|
||||||
|
|
||||||
# @classmethod
|
if origin_object.parent != obj:
|
||||||
# def update_empty_matrix(cls):
|
origin_object.parent = obj
|
||||||
# ob = bpy.context.object
|
|
||||||
# for mod in ob.modifiers:
|
# add constraints
|
||||||
# if mod.type == 'SIMPLE_DEFORM':
|
name = self.G_CON_LIMIT_NAME
|
||||||
# cls.update_matrix(mod, ob)
|
if origin_object.constraints.keys().__len__() > 1:
|
||||||
#
|
origin_object.constraints.clear()
|
||||||
# @classmethod
|
if name in origin_object.constraints.keys():
|
||||||
# context = bpy.context
|
limit_constraints = origin.constraints.get(name)
|
||||||
# data = bpy.data
|
else:
|
||||||
# matrix = obj.matrix_world.copy() # 物体矩阵
|
limit_constraints = origin_object.constraints.new(
|
||||||
# # add simple_deform mesh
|
'LIMIT_ROTATION')
|
||||||
# (min_x, min_y, min_z), (max_x, max_y,
|
limit_constraints.name = name
|
||||||
# max_z) = cls.get_mesh_max_min_co(obj)
|
limit_constraints.owner_space = 'WORLD'
|
||||||
# vertexes = ((max_x, min_y, min_z),
|
limit_constraints.space_object = obj
|
||||||
# (min_x, min_y, min_z),
|
limit_constraints.use_transform_limit = True
|
||||||
# (max_x, max_y, min_z),
|
limit_constraints.use_limit_x = True
|
||||||
# (min_x, max_y, min_z),
|
limit_constraints.use_limit_y = True
|
||||||
# (max_x, min_y, max_z),
|
limit_constraints.use_limit_z = True
|
||||||
# (min_x, min_y, max_z),
|
con_copy_name = self.G_NAME + 'constraints_copy_rotation'
|
||||||
# (max_x, max_y, max_z),
|
if con_copy_name in origin_object.constraints.keys():
|
||||||
# (min_x, max_y, max_z))
|
copy_constraints = origin.constraints.get(con_copy_name)
|
||||||
# name = cls.G_NAME
|
else:
|
||||||
# if data.objects.get(name):
|
copy_constraints = origin_object.constraints.new(
|
||||||
# data.objects.remove(data.objects.get(name))
|
'COPY_ROTATION')
|
||||||
#
|
copy_constraints.name = con_copy_name
|
||||||
# if data.meshes.get(name):
|
copy_constraints.target = obj
|
||||||
# data.meshes.remove(data.meshes.get(name))
|
copy_constraints.mix_mode = 'BEFORE'
|
||||||
# mesh = data.meshes.new(name)
|
copy_constraints.target_space = 'WORLD'
|
||||||
# mesh.from_pydata(vertexes, cls.G_INDICES, [])
|
copy_constraints.owner_space = 'WORLD'
|
||||||
# mesh.update()
|
origin_object.rotation_euler.zero()
|
||||||
#
|
origin_object.scale = 1, 1, 1
|
||||||
# new_object = data.objects.new(name, mesh)
|
|
||||||
#
|
def update_object_origin_matrix(self):
|
||||||
# cls.link_obj_to_active_collection(new_object)
|
self.clear_data()
|
||||||
#
|
origin_mode = self.origin_mode
|
||||||
# if new_object.parent != obj:
|
empty_object = self.modifier.origin
|
||||||
# new_object.parent = obj
|
if empty_object and self.modifier_is_use_origin_axis :
|
||||||
#
|
if origin_mode == 'UP_LIMITS':
|
||||||
# new_object.modifiers.clear()
|
empty_object.matrix_world.translation = Vector(self.point_limits_up)
|
||||||
# subdivision = new_object.modifiers.new('1', 'SUBSURF')
|
elif origin_mode == 'DOWN_LIMITS':
|
||||||
# subdivision.levels = 7
|
empty_object.matrix_world.translation = Vector(self.point_limits_down)
|
||||||
# cls.G_GizmoData['modifiers_co'] = {}
|
elif origin_mode == 'LIMITS_MIDDLE':
|
||||||
# cls.G_GizmoData['modifiers_co']['co'] = (
|
translation = (self.point_limits_up + self.point_limits_down) / 2
|
||||||
# min_x, min_y, min_z), (max_x, max_y, max_z)
|
empty_object.matrix_world.translation = translation
|
||||||
# for mo in context.object.modifiers:
|
elif origin_mode == 'MIDDLE':
|
||||||
# if mo.type == 'SIMPLE_DEFORM':
|
translation = (self.point_up + self.point_down) / 2
|
||||||
# simple_deform = new_object.modifiers.new(
|
empty_object.matrix_world.translation = translation
|
||||||
# mo.name, 'SIMPLE_DEFORM')
|
|
||||||
# simple_deform.deform_method = mo.deform_method
|
|
||||||
# simple_deform.deform_axis = mo.deform_axis
|
|
||||||
# simple_deform.lock_x = mo.lock_x
|
|
||||||
# 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.angle = mo.angle
|
|
||||||
# simple_deform.show_viewport = mo.show_viewport
|
|
||||||
# obj = PublicUtils.get_depsgraph(new_object)
|
|
||||||
# cls.G_GizmoData['modifiers_co'][mo.name] = cls.get_mesh_max_min_co(
|
|
||||||
# obj)
|
|
||||||
# new_object.hide_set(True)
|
|
||||||
# new_object.hide_viewport = False
|
|
||||||
# new_object.hide_select = True
|
|
||||||
# new_object.hide_render = True
|
|
||||||
# new_object.hide_viewport = True
|
|
||||||
# new_object.hide_set(True)
|
|
||||||
# ver_len = obj.data.vertices.__len__()
|
|
||||||
# edge_len = obj.data.edges.__len__()
|
|
||||||
#
|
|
||||||
# if 'numpy_data' not in cls.G_GizmoData:
|
|
||||||
# cls.G_GizmoData['numpy_data'] = {}
|
|
||||||
#
|
|
||||||
# numpy_data = cls.G_GizmoData['numpy_data']
|
|
||||||
# key = (ver_len, edge_len)
|
|
||||||
# if key in numpy_data:
|
|
||||||
# list_edges, list_vertices = numpy_data[key]
|
|
||||||
# else:
|
|
||||||
# list_edges = np.zeros(edge_len * 2, dtype=np.int32)
|
|
||||||
# list_vertices = np.zeros(ver_len * 3, dtype=np.float32)
|
|
||||||
# numpy_data[key] = (list_edges, list_vertices)
|
|
||||||
# obj.data.vertices.foreach_get('co', list_vertices)
|
|
||||||
# ver = list_vertices.reshape((ver_len, 3))
|
|
||||||
# ver = np.insert(ver, 3, 1, axis=1).T
|
|
||||||
# ver[:] = np.dot(matrix, ver)
|
|
||||||
#
|
|
||||||
# ver /= ver[3, :]
|
|
||||||
# ver = ver.T
|
|
||||||
# ver = ver[:, :3]
|
|
||||||
# obj.data.edges.foreach_get('vertices', list_edges)
|
|
||||||
# indices = list_edges.reshape((edge_len, 2))
|
|
||||||
#
|
|
||||||
# limits = context.object.modifiers.active.limits[:]
|
|
||||||
# modifiers = [getattr(context.object.modifiers.active, i)
|
|
||||||
# for i in cls.G_MODIFIERS_PROPERTY]
|
|
||||||
#
|
|
||||||
# cls.G_GizmoData['draw'] = (ver, indices, matrix, modifiers, limits)
|
|
||||||
|
|
||||||
def update_deform_wireframe(self):
|
def update_deform_wireframe(self):
|
||||||
...
|
context = bpy.context
|
||||||
|
data = bpy.data
|
||||||
|
matrix = obj.matrix_world.copy() # 物体矩阵
|
||||||
|
# add simple_deform mesh
|
||||||
|
(min_x, min_y, min_z), (max_x, max_y,
|
||||||
|
max_z) = cls.get_mesh_max_min_co(obj)
|
||||||
|
vertexes = ((max_x, min_y, min_z),
|
||||||
|
(min_x, min_y, min_z),
|
||||||
|
(max_x, max_y, min_z),
|
||||||
|
(min_x, max_y, min_z),
|
||||||
|
(max_x, min_y, max_z),
|
||||||
|
(min_x, min_y, max_z),
|
||||||
|
(max_x, max_y, max_z),
|
||||||
|
(min_x, max_y, max_z))
|
||||||
|
name = cls.G_NAME
|
||||||
|
if data.objects.get(name):
|
||||||
|
data.objects.remove(data.objects.get(name))
|
||||||
|
|
||||||
|
if data.meshes.get(name):
|
||||||
|
data.meshes.remove(data.meshes.get(name))
|
||||||
|
mesh = data.meshes.new(name)
|
||||||
|
mesh.from_pydata(vertexes, cls.G_INDICES, [])
|
||||||
|
mesh.update()
|
||||||
|
|
||||||
|
new_object = data.objects.new(name, mesh)
|
||||||
|
|
||||||
|
cls.link_obj_to_active_collection(new_object)
|
||||||
|
|
||||||
|
if new_object.parent != obj:
|
||||||
|
new_object.parent = obj
|
||||||
|
|
||||||
|
new_object.modifiers.clear()
|
||||||
|
subdivision = new_object.modifiers.new('1', 'SUBSURF')
|
||||||
|
subdivision.levels = 7
|
||||||
|
cls.G_GizmoData['modifiers_co'] = {}
|
||||||
|
cls.G_GizmoData['modifiers_co']['co'] = (
|
||||||
|
min_x, min_y, min_z), (max_x, max_y, max_z)
|
||||||
|
for mo in context.object.modifiers:
|
||||||
|
if mo.type == 'SIMPLE_DEFORM':
|
||||||
|
simple_deform = new_object.modifiers.new(
|
||||||
|
mo.name, 'SIMPLE_DEFORM')
|
||||||
|
simple_deform.deform_method = mo.deform_method
|
||||||
|
simple_deform.deform_axis = mo.deform_axis
|
||||||
|
simple_deform.lock_x = mo.lock_x
|
||||||
|
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.angle = mo.angle
|
||||||
|
simple_deform.show_viewport = mo.show_viewport
|
||||||
|
obj = PublicUtils.get_depsgraph(new_object)
|
||||||
|
cls.G_GizmoData['modifiers_co'][mo.name] = cls.get_mesh_max_min_co(
|
||||||
|
obj)
|
||||||
|
new_object.hide_set(True)
|
||||||
|
new_object.hide_viewport = False
|
||||||
|
new_object.hide_select = True
|
||||||
|
new_object.hide_render = True
|
||||||
|
new_object.hide_viewport = True
|
||||||
|
new_object.hide_set(True)
|
||||||
|
ver_len = obj.data.vertices.__len__()
|
||||||
|
edge_len = obj.data.edges.__len__()
|
||||||
|
|
||||||
|
if 'numpy_data' not in cls.G_GizmoData:
|
||||||
|
cls.G_GizmoData['numpy_data'] = {}
|
||||||
|
|
||||||
|
numpy_data = cls.G_GizmoData['numpy_data']
|
||||||
|
key = (ver_len, edge_len)
|
||||||
|
if key in numpy_data:
|
||||||
|
list_edges, list_vertices = numpy_data[key]
|
||||||
|
else:
|
||||||
|
list_edges = np.zeros(edge_len * 2, dtype=np.int32)
|
||||||
|
list_vertices = np.zeros(ver_len * 3, dtype=np.float32)
|
||||||
|
numpy_data[key] = (list_edges, list_vertices)
|
||||||
|
obj.data.vertices.foreach_get('co', list_vertices)
|
||||||
|
ver = list_vertices.reshape((ver_len, 3))
|
||||||
|
ver = np.insert(ver, 3, 1, axis=1).T
|
||||||
|
ver[:] = np.dot(matrix, ver)
|
||||||
|
|
||||||
|
ver /= ver[3, :]
|
||||||
|
ver = ver.T
|
||||||
|
ver = ver[:, :3]
|
||||||
|
obj.data.edges.foreach_get('vertices', list_edges)
|
||||||
|
indices = list_edges.reshape((edge_len, 2))
|
||||||
|
|
||||||
|
limits = context.object.modifiers.active.limits[:]
|
||||||
|
modifiers = [getattr(context.object.modifiers.active, i)
|
||||||
|
for i in cls.G_MODIFIERS_PROPERTY]
|
||||||
|
|
||||||
|
cls.G_GizmoData['draw'] = (ver, indices, matrix, modifiers, limits)
|
||||||
|
|
||||||
|
|
||||||
class GizmoUtils(GizmoUpdate):
|
class GizmoUtils(GizmoUpdate):
|
||||||
@ -725,7 +713,7 @@ class GizmoUtils(GizmoUpdate):
|
|||||||
self.init_mouse_region_y = event.mouse_region_y
|
self.init_mouse_region_y = event.mouse_region_y
|
||||||
self.init_mouse_region_x = event.mouse_region_x
|
self.init_mouse_region_x = event.mouse_region_x
|
||||||
|
|
||||||
def _update_matrix(self, context):
|
def __update_matrix_func(self, context):
|
||||||
func = getattr(self, 'update_gizmo_matrix', None)
|
func = getattr(self, 'update_gizmo_matrix', None)
|
||||||
if func and self.modifier_origin_angle_is_available:
|
if func and self.modifier_origin_angle_is_available:
|
||||||
func(context)
|
func(context)
|
||||||
@ -733,13 +721,13 @@ class GizmoUtils(GizmoUpdate):
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if self.modifier_origin_angle_is_available:
|
if self.modifier_origin_angle_is_available:
|
||||||
self.draw_custom_shape(self.custom_shape[self.draw_type])
|
self.draw_custom_shape(self.custom_shape[self.draw_type])
|
||||||
self._update_matrix(context)
|
self.__update_matrix_func(context)
|
||||||
|
|
||||||
def draw_select(self, context, select_id):
|
def draw_select(self, context, select_id):
|
||||||
if self.modifier_origin_angle_is_available:
|
if self.modifier_origin_angle_is_available:
|
||||||
self.draw_custom_shape(
|
self.draw_custom_shape(
|
||||||
self.custom_shape[self.draw_type], select_id=select_id)
|
self.custom_shape[self.draw_type], select_id=select_id)
|
||||||
self._update_matrix(context)
|
self.__update_matrix_func(context)
|
||||||
|
|
||||||
def get_delta(self, event):
|
def get_delta(self, event):
|
||||||
delta = (self.init_mouse_region_x - event.mouse_region_x) / self.mouse_dpi
|
delta = (self.init_mouse_region_x - event.mouse_region_x) / self.mouse_dpi
|
||||||
@ -764,6 +752,24 @@ class GizmoUtils(GizmoUpdate):
|
|||||||
def update_gizmo_matrix(self):
|
def update_gizmo_matrix(self):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
def event_handle(self, event):
|
||||||
|
"""通过输入键位来更改属性"""
|
||||||
|
# event ctrl
|
||||||
|
data_path = ('object.SimpleDeformGizmo_PropertyGroup.origin_mode',
|
||||||
|
'object.modifiers.active.origin.SimpleDeformGizmo_PropertyGroup.origin_mode')
|
||||||
|
|
||||||
|
if event.type in ('WHEELUPMOUSE', 'WHEELDOWNMOUSE'):
|
||||||
|
reverse = (event.type == 'WHEELUPMOUSE')
|
||||||
|
for path in data_path:
|
||||||
|
bpy.ops.wm.context_cycle_enum(
|
||||||
|
data_path=path, reverse=reverse, wrap=True)
|
||||||
|
elif event.type in ('X', 'Y', 'Z'):
|
||||||
|
self.obj.modifiers.active.deform_axis = event.type
|
||||||
|
elif event.type == 'A':
|
||||||
|
self.pref.display_bend_axis_switch_gizmo = True
|
||||||
|
return {'FINISHED'}
|
||||||
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
|
|
||||||
class GizmoGroupUtils(GizmoUtils):
|
class GizmoGroupUtils(GizmoUtils):
|
||||||
bl_space_type = 'VIEW_3D'
|
bl_space_type = 'VIEW_3D'
|
||||||
|
Loading…
Reference in New Issue
Block a user