new addon simple_deform_helper #104464

Closed
EMM wants to merge 29 commits from Guai_Wo_Ge_EMM/blender-addons:simple_deform_helper into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
6 changed files with 440 additions and 322 deletions
Showing only changes of commit 9351c3c895 - Show all commits

View File

@ -1,20 +1,22 @@
import bpy
from bpy_types import Gizmo
from .bend_axis import SimpleDeformGizmoGroupDisplayBendAxiSwitchGizmo, CustomGizmo
from .up_down_limits_point import GizmoProperty, UpDownLimitsGizmo
from .angle_and_factor import AngleGizmoGroup, AngleGizmo
from .bend_axis import BendAxiSwitchGizmoGroup, CustomGizmo
from .set_deform_axis import SetDeformGizmoGroup
from .up_down_limits_point import UpDownLimitsGizmo, UpDownLimitsGizmoGroup
from ..draw import Handler
class_list = (
# GizmoProperty,
# UpDownLimitsGizmo,
UpDownLimitsGizmo,
UpDownLimitsGizmoGroup,
AngleGizmo,
AngleGizmoGroup,
CustomGizmo,
SimpleDeformGizmoGroupDisplayBendAxiSwitchGizmo,
BendAxiSwitchGizmoGroup,
SetDeformGizmoGroup,
)
register_class, unregister_class = bpy.utils.register_classes_factory(class_list)

View File

@ -1,58 +1,17 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import math
from bpy.types import Gizmo
from bpy.types import (
GizmoGroup,
)
from bpy.types import Gizmo
from mathutils import Vector, Euler, Matrix
from mathutils import Vector
from ..utils import GizmoUtils
from ..draw import Handler
from ..utils import GizmoUtils
class AngleGizmo(Gizmo, GizmoUtils):
bl_idname = 'ViewSimpleAngleGizmo'
bl_target_properties = (
{'id': 'up_limits', 'type': 'FLOAT', 'array_length': 1},
{'id': 'down_limits', 'type': 'FLOAT', 'array_length': 1},
{'id': 'angle', 'type': 'FLOAT', 'array_length': 1},
)
__slots__ = (
'draw_type',
'mouse_dpi',
'empty_object',
'init_mouse_y',
'init_mouse_x',
'custom_shape',
'int_value_angle',
'rotate_follow_modifier',
)
int_value_angle: float
rotate_follow_modifier: bool
def setup(self):
self.mouse_dpi = 2
self.rotate_follow_modifier = True
self.init_setup()
def invoke(self, context, event):
self.init_invoke(context, event)
self.int_value_angle = self.target_get_value('angle')
return {'RUNNING_MODAL'}
def modal(self, context, event, tweak):
self.update_header_text(context)
self.update_prop_value(event, tweak)
return {'RUNNING_MODAL'}
def exit(self, context, cancel):
context.area.header_text_set(None)
if cancel:
self.target_set_value('angle', self.int_value_angle)
class AngleUpdate(GizmoUtils):
def update_prop_value(self, event, tweak):
# radians 弧度
@ -74,6 +33,47 @@ class AngleGizmo(Gizmo, GizmoUtils):
context.area.header_text_set(text)
class AngleGizmo(Gizmo, AngleUpdate):
bl_idname = 'ViewSimpleAngleGizmo'
bl_target_properties = (
{'id': 'up_limits', 'type': 'FLOAT', 'array_length': 1},
{'id': 'down_limits', 'type': 'FLOAT', 'array_length': 1},
{'id': 'angle', 'type': 'FLOAT', 'array_length': 1},
)
__slots__ = (
'draw_type',
'mouse_dpi',
'empty_object',
'init_mouse_y',
'init_mouse_x',
'custom_shape',
'int_value_angle',
)
int_value_angle: float
def setup(self):
self.mouse_dpi = 10
self.init_setup()
def invoke(self, context, event):
self.init_invoke(context, event)
self.int_value_angle = self.target_get_value('angle')
return {'RUNNING_MODAL'}
def modal(self, context, event, tweak):
self.update_header_text(context)
self.update_prop_value(event, tweak)
return {'RUNNING_MODAL'}
def exit(self, context, cancel):
context.area.header_text_set(None)
if cancel:
self.target_set_value('angle', self.int_value_angle)
class AngleGizmoGroup(GizmoGroup, GizmoUtils, Handler):
"""ShowGizmo
"""
@ -81,7 +81,17 @@ class AngleGizmoGroup(GizmoGroup, GizmoUtils, Handler):
bl_label = 'AngleGizmoGroup'
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
bl_options = {'3D', 'PERSISTENT', }
bl_options = {'3D',
# 'SCALE',
# 'DEPTH_3D',
# 'SELECT',
'PERSISTENT',
'SHOW_MODAL_ALL',
# 'EXCLUDE_MODAL',
# 'TOOL_INIT', # not show
# 'TOOL_FALLBACK_KEYMAP',
# 'VR_REDRAWS'
}
@classmethod
def poll(cls, context):
@ -107,57 +117,8 @@ class AngleGizmoGroup(GizmoGroup, GizmoUtils, Handler):
self.generate_gizmo_mode(add_data)
data_path = 'object.modifiers.active.deform_axis'
set_enum = 'wm.context_set_enum'
for axis in ('X', 'Y', 'Z'):
# show toggle axis button
gizmo = self.gizmos.new('GIZMO_GT_button_2d')
gizmo.icon = f'EVENT_{axis.upper()}'
gizmo.draw_options = {'BACKDROP', 'HELPLINE'}
ops = gizmo.target_set_operator(set_enum)
ops.data_path = data_path
ops.value = axis
gizmo.color = (0, 0, 0)
gizmo.alpha = 0.3
gizmo.color_highlight = 1.0, 1.0, 1.0
gizmo.alpha_highlight = 0.3
gizmo.use_draw_modal = True
gizmo.use_draw_value = True
gizmo.scale_basis = 0.1
setattr(self, f'deform_axis_{axis.lower()}', gizmo)
def refresh(self, context):
self.angle.target_set_prop('angle',
context.object.modifiers.active,
'angle')
# pro = context.object.SimpleDeformGizmo_PropertyGroup
# 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')
def draw_prepare(self, context):
ob = context.object
mat = ob.matrix_world
if 'co' in self.G_SimpleDeformGizmoHandlerDit:
def _mat(f):
co = self.G_SimpleDeformGizmoHandlerDit['co'][0]
co = (co[0] + (max(ob.dimensions) * f), co[1],
co[2] - (min(ob.dimensions) * 0.3))
return mat @ Vector(co)
self.deform_axis_x.matrix_basis.translation = _mat(0)
self.deform_axis_y.matrix_basis.translation = _mat(0.3)
self.deform_axis_z.matrix_basis.translation = _mat(0.6)

View File

@ -40,7 +40,7 @@ class CustomGizmo(Gizmo, GizmoUtils, Handler):
return {'RUNNING_MODAL'}
class SimpleDeformGizmoGroupDisplayBendAxiSwitchGizmo(GizmoGroup, GizmoUtils):
class BendAxiSwitchGizmoGroup(GizmoGroup, GizmoUtils):
"""绘制切换变型轴的
变换方向
"""

View File

@ -0,0 +1,53 @@
from bpy.types import GizmoGroup
from mathutils import Vector
from utils import GizmoUtils
class SetDeformGizmoGroup(GizmoGroup, GizmoUtils):
bl_idname = 'OBJECT_GGT_SetDeformGizmoGroup'
bl_label = 'SetDeformGizmoGroup'
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
bl_options = {'3D',
'PERSISTENT',
'SHOW_MODAL_ALL',
}
@classmethod
def poll(cls, context):
return cls.simple_deform_show_gizmo_poll(context)
def setup(self, context):
data_path = 'object.modifiers.active.deform_axis'
set_enum = 'wm.context_set_enum'
for axis in ('X', 'Y', 'Z'):
# show toggle axis button
gizmo = self.gizmos.new('GIZMO_GT_button_2d')
gizmo.icon = f'EVENT_{axis.upper()}'
gizmo.draw_options = {'BACKDROP', 'HELPLINE'}
ops = gizmo.target_set_operator(set_enum)
ops.data_path = data_path
ops.value = axis
gizmo.color = (0, 0, 0)
gizmo.alpha = 0.3
gizmo.color_highlight = 1.0, 1.0, 1.0
gizmo.alpha_highlight = 0.3
gizmo.use_draw_modal = True
gizmo.use_draw_value = True
gizmo.scale_basis = 0.1
setattr(self, f'deform_axis_{axis.lower()}', gizmo)
def draw_prepare(self, context):
if 'co' in self.G_SimpleDeformGizmoHandlerDit:
def _mat(f):
co = self.G_SimpleDeformGizmoHandlerDit['co'][0]
co = (co[0] + (max(self.obj.dimensions) * f), co[1],
co[2] - (min(self.obj.dimensions) * 0.3))
return self.obj_matrix_world @ Vector(co)
self.deform_axis_x.matrix_basis.translation = _mat(0)
self.deform_axis_y.matrix_basis.translation = _mat(0.3)
self.deform_axis_z.matrix_basis.translation = _mat(0.6)

View File

@ -2,19 +2,15 @@ import math
from typing import Callable, Any
import bpy
from bpy.types import Gizmo, GizmoGroup
from bpy_extras import view3d_utils
from bpy.types import Gizmo
from mathutils import Euler, Vector
from mathutils import Vector
from ..draw import Handler
from ..utils import GizmoUtils
class GizmoProperty(GizmoUtils, Handler):
@property
def is_angle_mode(self):
return self.ctrl_mode == 'angle'
@property
def is_up_limits_mode(self):
return self.ctrl_mode == 'up_limits'
@ -24,85 +20,17 @@ class GizmoProperty(GizmoUtils, Handler):
return self.ctrl_mode == 'down_limits'
class UpDownLimitsGizmo(GizmoProperty, Gizmo):
"""显示轴向切换拖动点Gizmo(两个点)
"""
bl_idname = 'UpDownLimitsGizmo'
bl_target_properties = (
{'id': 'up_limits', 'type': 'FLOAT', 'array_length': 1},
{'id': 'down_limits', 'type': 'FLOAT', 'array_length': 1},
)
__slots__ = (
'mod',
'up',
'down',
'up_',
'down_',
'draw_type',
'mouse_dpi',
'ctrl_mode',
'empty_object',
'init_mouse_y',
'init_mouse_x',
'custom_shape',
'int_value_angle',
'value_deform_axis',
'int_value_up_limits',
'int_value_down_limits',
'rotate_follow_modifier',
)
def update_draw_limits_bound_box(self, data, mod, axis, mat, up_, down_):
top, bottom, left, right, front, back = data
if mod.origin:
vector_axis = self.get_vector_axis(mod)
origin_mat = mod.origin.matrix_world.to_3x3()
axis_ = origin_mat @ vector_axis
point_lit = [[top, bottom], [left, right], [front, back]]
for f in range(point_lit.__len__()):
i = point_lit[f][0]
j = point_lit[f][1]
angle = self.point_to_angle(i, j, f, axis_)
if abs(angle - 180) < 0.00001:
point_lit[f][1], point_lit[f][0] = up_, down_
elif abs(angle) < 0.00001:
point_lit[f][0], point_lit[f][1] = up_, down_
[[top, bottom], [left, right], [front, back]] = point_lit
else:
top, bottom, left, right, front, back = self.get_up_down_return_list(
mod, axis, up_, down_, data)
data = top, bottom, left, right, front, back
(top, bottom, left, right, front,
back) = self.matrix_calculation(mat.inverted(), data)
self.G_SimpleDeformGizmoHandlerDit['draw_limits_bound_box'] = (
mat, ((right[0], back[1], top[2]), (left[0], front[1], bottom[2],)))
def update_matrix_basis_translation(self, co, mat, up_, down_):
if self.is_angle_mode:
self.matrix_basis.translation = mat @ Vector((co[1]))
elif self.is_up_limits_mode:
self.matrix_basis.translation = up_
elif self.is_down_limits_mode:
self.matrix_basis.translation = down_
class GizmoUpdate(GizmoProperty):
def update_gizmo_matrix(self, context):
ob = context.object
mat = ob.matrix_world
mod = context.object.modifiers.active
axis = mod.deform_axis
if mod.origin:
self.matrix_basis = mod.origin.matrix_world.normalized()
else:
self.matrix_basis = ob.matrix_world.normalized()
self._update_matrix_basis_to_obj()
co = self.generate_co_data()
# calculation limits position
top, bottom, left, right, front, back = self.each_face_pos(mat)
(up, down), (up_, down_) = self.get_limits_pos(
mod, (top, bottom, left, right, front, back))
self.update_matrix_basis_translation(co, mat, up_, down_)
self._update_matrix_basis_translation(co, mat, up_, down_)
self.up = up
self.down = down
@ -113,42 +41,18 @@ class UpDownLimitsGizmo(GizmoProperty, Gizmo):
data = top, bottom, left, right, front, back
self.update_draw_limits_bound_box(data, mod, axis, mat, up_, down_)
def setup(self):
self.generate_co_data()
self.draw_type = 'None_GizmoGroup_'
self.ctrl_mode = 'up_limits' # up_limits , down_limits
self.mouse_dpi = 10
self.rotate_follow_modifier = True
self.add_handler()
def _update_matrix_basis_to_obj(self):
origin = self.modifier.origin
if origin:
self.matrix_basis = origin.matrix_world.normalized()
else:
self.matrix_basis = self.obj_matrix_world.normalized()
def invoke(self, context, event):
self.init_invoke(context, event)
mod = context.object.modifiers.active
limits = mod.limits
up_limits = limits[1]
down_limits = limits[0]
if 'up_limits' == self.ctrl_mode:
self.int_value_up_limits = up_limits
self.target_set_value('up_limits', self.int_value_up_limits)
elif 'down_limits' == self.ctrl_mode:
self.int_value_down_limits = down_limits
self.target_set_value('down_limits', self.int_value_down_limits)
return {'RUNNING_MODAL'}
def exit(self, context, cancel):
context.area.header_text_set(None)
if cancel:
if 'angle' == self.ctrl_mode:
self.target_set_value('angle', self.int_value_angle)
elif 'deform_axis' == self.ctrl_mode:
self.target_set_value('deform_axis', self.value_deform_axis)
elif 'up_limits' == self.ctrl_mode:
self.target_set_value('up_limits', self.int_value_up_limits)
elif 'down_limits' == self.ctrl_mode:
self.target_set_value(
'down_limits', self.int_value_down_limits)
def _update_matrix_basis_translation(self, co, mat, up_, down_):
if self.is_up_limits_mode:
self.matrix_basis.translation = up_
elif self.is_down_limits_mode:
self.matrix_basis.translation = down_
def delta_update(self, context, event, delta):
if ('draw_line' in self.G_SimpleDeformGizmoHandlerDit) and (self.ctrl_mode in ('up_limits', 'down_limits')):
@ -231,7 +135,7 @@ class UpDownLimitsGizmo(GizmoProperty, Gizmo):
text = translate(mode) + ' '
if self.is_use_angle_value and self.is_angle_mode:
if self.modifier_is_use_angle_value and self.is_angle_mode:
text += t_()
elif self.is_up_limits_mode:
text += t_('Upper limit', up_limits)
@ -261,35 +165,148 @@ class UpDownLimitsGizmo(GizmoProperty, Gizmo):
return {'RUNNING_MODAL'}
def modal(self, context, event, tweak):
self.update_bound_box(context.object)
ob = context.object
mod = ob.modifiers.active
class UpDownLimitsGizmo(Gizmo, GizmoUpdate):
"""显示轴向切换拖动点Gizmo(两个点)
"""
bl_idname = 'UpDownLimitsGizmo'
bl_target_properties = (
{'id': 'up_limits', 'type': 'FLOAT', 'array_length': 1},
{'id': 'down_limits', 'type': 'FLOAT', 'array_length': 1},
)
__slots__ = (
'mod',
'up_limits',
'down_limits',
'draw_type',
'mouse_dpi',
'ctrl_mode',
'empty_object',
'init_mouse_y',
'init_mouse_x',
'custom_shape',
'value_deform_axis',
'int_value_up_limits',
'int_value_down_limits',
)
def setup(self):
self.generate_co_data()
self.draw_type = 'None_GizmoGroup_'
self.ctrl_mode = 'up_limits' # up_limits , down_limits
self.mouse_dpi = 10
def invoke(self, context, event):
self.init_invoke(context, event)
mod = context.object.modifiers.active
limits = mod.limits
up_limits = limits[1]
down_limits = limits[0]
origin = self.get_origin_property_group(mod, ob)
origin_mode = origin.origin_mode
middle = origin_mode in ('LIMITS_MIDDLE', 'MIDDLE')
limit_scope = self.pref.modifiers_limits_tolerance
max_value = up_limits - limit_scope
min_value = down_limits + limit_scope
difference_value = up_limits - down_limits
delta = self.get_delta(event, tweak)
delta = self.delta_update(context, event, delta)
if 'up_limits' == self.ctrl_mode:
self.int_value_up_limits = up_limits
self.target_set_value('up_limits', self.int_value_up_limits)
elif 'down_limits' == self.ctrl_mode:
self.int_value_down_limits = down_limits
self.target_set_value('down_limits', self.int_value_down_limits)
return {'RUNNING_MODAL'}
if origin_mode != 'NOT' and ('draw_line' in self.G_SimpleDeformGizmoHandlerDit):
self.empty_object, _ = self.new_empty(ob, mod)
self.G_SimpleDeformGizmoHandlerDit['empty_object'] = self.empty_object
data = up_limits, down_limits, delta, middle, min_value, max_value, limit_scope, difference_value, event, origin_mode
self.set_prop_value(data)
self.update_gizmo_matrix(context)
self.update_empty_matrix()
self.update_bound_box(context.object)
def exit(self, context, cancel):
context.area.header_text_set(None)
self.update_header_text(context, mod, origin, up_limits, down_limits)
self.add_handler()
if cancel:
if 'deform_axis' == self.ctrl_mode:
self.target_set_value('deform_axis', self.value_deform_axis)
elif 'up_limits' == self.ctrl_mode:
self.target_set_value('up_limits', self.int_value_up_limits)
elif 'down_limits' == self.ctrl_mode:
self.target_set_value(
'down_limits', self.int_value_down_limits)
return self.event_ops(event, ob, origin)
def modal(self, context, event, tweak):
# self.update_bound_box(context.object)
#
# ob = context.object
# mod = ob.modifiers.active
# limits = mod.limits
# up_limits = limits[1]
# down_limits = limits[0]
# origin = self.get_origin_property_group(mod, ob)
# origin_mode = origin.origin_mode
# middle = origin_mode in ('LIMITS_MIDDLE', 'MIDDLE')
# limit_scope = self.pref.modifiers_limits_tolerance
# max_value = up_limits - limit_scope
# min_value = down_limits + limit_scope
# difference_value = up_limits - down_limits
#
# delta = self.get_delta(event, tweak)
# delta = self.delta_update(context, event, delta)
#
# if origin_mode != 'NOT' and ('draw_line' in self.G_SimpleDeformGizmoHandlerDit):
# self.empty_object, _ = self.new_empty(ob, mod)
# self.G_SimpleDeformGizmoHandlerDit['empty_object'] = self.empty_object
# data = up_limits, down_limits, delta, middle, min_value, max_value, limit_scope, difference_value, event, origin_mode
# self.set_prop_value(data)
# self.update_gizmo_matrix(context)
# self.update_empty_matrix()
# self.update_bound_box(context.object)
# self.update_header_text(context, mod, origin, up_limits, down_limits)
# self.add_handler()
# return self.event_ops(event, ob, origin)
return {'RUNNING_MODAL'}
class UpDownLimitsGizmoGroup(GizmoGroup, GizmoUtils, Handler):
bl_idname = 'OBJECT_GGT_SimpleDeformGizmoGroup'
@classmethod
def poll(cls, context):
return cls.simple_deform_show_gizmo_poll(context)
def setup(self, context):
sd_name = UpDownLimitsGizmo.bl_idname
add_data = (
('up_limits',
sd_name,
{'ctrl_mode': 'up_limits',
'draw_type': 'Sphere_GizmoGroup_',
'mouse_dpi': 1000,
'color': (1.0, 0, 0),
'alpha': 0.5,
'color_highlight': (1.0, 1.0, 1.0),
'alpha_highlight': 0.3,
'use_draw_modal': True,
'scale_basis': 0.1,
'use_draw_value': True, }),
('down_limits',
sd_name,
{'ctrl_mode': 'down_limits',
'draw_type': 'Sphere_GizmoGroup_',
'mouse_dpi': 1000,
'color': (0, 1.0, 0),
'alpha': 0.5,
'color_highlight': (1.0, 1.0, 1.0),
'alpha_highlight': 0.3,
'use_draw_modal': True,
'scale_basis': 0.1,
'use_draw_value': True, }),
)
def refresh(self, context):
pro = context.object.SimpleDeformGizmo_PropertyGroup
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')

View File

@ -128,7 +128,7 @@ class PublicPoll(PublicClass):
active modifier deform_method =='BEND'
"""
simple = cls.simple_deform_public_poll(context)
is_bend = (context.object.modifiers.active.deform_method == 'BEND')
is_bend = simple and (context.object.modifiers.active.deform_method == 'BEND')
return simple and is_bend
@classmethod
@ -266,74 +266,7 @@ class PublicUtils(PublicPoll):
return cls.translate_text(mode) + ':{}'.format(value)
class GizmoProperty:
@property
def obj(self):
return bpy.context.object
@property
def modifier(self):
obj = self.obj
if not obj:
return
return obj.modifiers.active
@property
def modifier_deform_axis(self):
mod = self.modifier
if mod:
return mod.deform_axis
@property
def modifier_angle(self):
mod = self.modifier
if mod:
return mod.angle
@property
def active_modifier_is_simple_deform(self):
return self.modifier and self.modifier.type == 'SIMPLE_DEFORM'
@property
def is_use_angle_value(self):
if self.active_modifier_is_simple_deform:
return self.modifier.deform_method in ('TWIST', 'BEND')
class GizmoClassMethod(GizmoProperty, PublicUtils):
@classmethod
def each_face_pos(cls, mat: 'Matrix' = None):
if mat is None:
mat = Matrix()
return cls.co_to_direction(mat, cls.G_SimpleDeformGizmoHandlerDit['co'])
@classmethod
def update_matrix(cls, mod, ob):
if mod.deform_method == 'BEND':
cls.new_empty(ob, mod)
if mod.origin:
empty_object = mod.origin
modifiers_co = cls.G_SimpleDeformGizmoHandlerDit['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_) = cls.get_limits_pos(
mod, cls.co_to_direction(ob.matrix_world.copy(), data))
origin_mode = cls.get_origin_property_group(
mod, ob).origin_mode
cls.set_empty_obj_matrix(
origin_mode, empty_object, up_, down_, up, down)
@classmethod
def update_empty_matrix(cls):
ob = bpy.context.object
for mod in ob.modifiers:
if mod.type == 'SIMPLE_DEFORM':
cls.update_matrix(mod, ob)
class GizmoClassMethod(PublicUtils):
@classmethod
def get_origin_property_group(cls, mod, ob):
if mod.origin:
@ -481,6 +414,44 @@ class GizmoClassMethod(GizmoProperty, PublicUtils):
axis == 'Z') else vector
return vector_axis
@classmethod
def generate_co_data(cls):
handler_dit = cls.G_SimpleDeformGizmoHandlerDit
if 'co' not in handler_dit:
handler_dit['co'] = cls.get_mesh_max_min_co(
bpy.context.object)
return handler_dit['co']
class GizmoUpdate(GizmoClassMethod):
@classmethod
def update_matrix(cls, mod, ob):
if mod.deform_method == 'BEND':
cls.new_empty(ob, mod)
if mod.origin:
empty_object = mod.origin
modifiers_co = cls.G_SimpleDeformGizmoHandlerDit['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_) = cls.get_limits_pos(
mod, cls.co_to_direction(ob.matrix_world.copy(), data))
origin_mode = cls.get_origin_property_group(
mod, ob).origin_mode
cls.set_empty_obj_matrix(
origin_mode, empty_object, up_, down_, up, down)
@classmethod
def update_empty_matrix(cls):
ob = bpy.context.object
for mod in ob.modifiers:
if mod.type == 'SIMPLE_DEFORM':
cls.update_matrix(mod, ob)
@classmethod
def update_bound_box(cls, obj: 'bpy.types.Object'):
context = bpy.context
@ -574,15 +545,6 @@ class GizmoClassMethod(GizmoProperty, PublicUtils):
cls.G_SimpleDeformGizmoHandlerDit['draw'] = (ver, indices, matrix, modifiers, limits)
@classmethod
def generate_co_data(cls):
handler_dit = cls.G_SimpleDeformGizmoHandlerDit
if 'co' not in handler_dit:
handler_dit['co'] = cls.get_mesh_max_min_co(
bpy.context.object)
return handler_dit['co']
@classmethod
def update_co_data(cls, ob, mod):
handler_dit = cls.G_SimpleDeformGizmoHandlerDit
@ -595,8 +557,132 @@ class GizmoClassMethod(GizmoProperty, PublicUtils):
cls.G_SimpleDeformGizmoHandlerDit['co'] = co_items[index - 1][1] if (index or (index != 1)) else \
modifiers_co['co']
def update_draw_limits_bound_box(self, data, mod, axis, mat, up_, down_):
top, bottom, left, right, front, back = data
if mod.origin:
vector_axis = self.get_vector_axis(mod)
origin_mat = mod.origin.matrix_world.to_3x3()
axis_ = origin_mat @ vector_axis
point_lit = [[top, bottom], [left, right], [front, back]]
for f in range(point_lit.__len__()):
i = point_lit[f][0]
j = point_lit[f][1]
angle = self.point_to_angle(i, j, f, axis_)
if abs(angle - 180) < 0.00001:
point_lit[f][1], point_lit[f][0] = up_, down_
elif abs(angle) < 0.00001:
point_lit[f][0], point_lit[f][1] = up_, down_
[[top, bottom], [left, right], [front, back]] = point_lit
else:
top, bottom, left, right, front, back = self.get_up_down_return_list(
mod, axis, up_, down_, data)
data = top, bottom, left, right, front, back
(top, bottom, left, right, front,
back) = self.matrix_calculation(mat.inverted(), data)
self.G_SimpleDeformGizmoHandlerDit['draw_limits_bound_box'] = (
mat, ((right[0], back[1], top[2]), (left[0], front[1], bottom[2],)))
class GizmoUtils(GizmoClassMethod):
def update_bound_box_wireframe(self):
...
def update_up_down_limits_wireframe(self):
...
def update_deform_wireframe(self):
...
class PublicProperty(GizmoUpdate):
@classmethod
def each_face_pos(cls, mat: 'Matrix' = None):
if mat is None:
mat = Matrix()
return cls.co_to_direction(mat, cls.G_SimpleDeformGizmoHandlerDit['co'])
@property
def obj(self):
return bpy.context.object
@property
def obj_matrix_world(self):
if self.obj:
return self.obj.matrix_world
@property
def modifier(self):
obj = self.obj
if not obj:
return
return obj.modifiers.active
@property
def modifier_deform_axis(self):
mod = self.modifier
if mod:
return mod.deform_axis
@property
def modifier_angle(self):
mod = self.modifier
if mod:
return mod.angle
@property
def active_modifier_is_simple_deform(self):
return self.modifier and self.modifier.type == 'SIMPLE_DEFORM'
@property
def modifier_is_use_angle_value(self):
if self.active_modifier_is_simple_deform:
return self.modifier.deform_method in ('TWIST', 'BEND')
@property
def point_up(self):
...
@property
def point_down(self):
...
@property
def point_limits_up(self):
...
@property
def point_limits_down(self):
...
@property
def point_top(self):
...
@property
def point_bottom(self):
...
@property
def point_left(self):
...
@property
def point_right(self):
...
@property
def point_front(self):
...
@property
def point_back(self):
...
@classmethod
def clear_cache(cls):
...
class GizmoUtils(PublicProperty):
custom_shape: dict
init_mouse_y: float
init_mouse_x: float
@ -654,20 +740,19 @@ class GizmoUtils(GizmoClassMethod):
return delta
def get_snap(self, delta, tweak):
# ctrl SNAP
# shift PRECISE
# TODO ctrl SNAP
# TODO shift PRECISE
is_snap = 'SNAP' in tweak
is_precise = 'PRECISE' in tweak
if is_snap and is_precise:
delta = round(delta)
# delta /= self.mouse_dpi
elif is_snap:
delta //= 5
delta *= 5
elif is_precise:
delta /= self.mouse_dpi
delta //= 0.01
delta *= 0.01
print('tweak', delta, tweak)
return delta
def update_gizmo_matrix(self):