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 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 .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 from ..draw import Handler
class_list = ( class_list = (
# GizmoProperty, UpDownLimitsGizmo,
# UpDownLimitsGizmo, UpDownLimitsGizmoGroup,
AngleGizmo, AngleGizmo,
AngleGizmoGroup, AngleGizmoGroup,
CustomGizmo, CustomGizmo,
SimpleDeformGizmoGroupDisplayBendAxiSwitchGizmo, BendAxiSwitchGizmoGroup,
SetDeformGizmoGroup,
) )
register_class, unregister_class = bpy.utils.register_classes_factory(class_list) 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 # SPDX-License-Identifier: GPL-2.0-or-later
import math import math
from bpy.types import Gizmo
from bpy.types import ( from bpy.types import (
GizmoGroup, GizmoGroup,
) )
from bpy.types import Gizmo from mathutils import Vector
from mathutils import Vector, Euler, Matrix
from ..utils import GizmoUtils
from ..draw import Handler from ..draw import Handler
from ..utils import GizmoUtils
class AngleGizmo(Gizmo, GizmoUtils): class AngleUpdate(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)
def update_prop_value(self, event, tweak): def update_prop_value(self, event, tweak):
# radians 弧度 # radians 弧度
@ -74,6 +33,47 @@ class AngleGizmo(Gizmo, GizmoUtils):
context.area.header_text_set(text) 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): class AngleGizmoGroup(GizmoGroup, GizmoUtils, Handler):
"""ShowGizmo """ShowGizmo
""" """
@ -81,7 +81,17 @@ class AngleGizmoGroup(GizmoGroup, GizmoUtils, Handler):
bl_label = 'AngleGizmoGroup' bl_label = 'AngleGizmoGroup'
bl_space_type = 'VIEW_3D' bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW' 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 @classmethod
def poll(cls, context): def poll(cls, context):
@ -107,57 +117,8 @@ class AngleGizmoGroup(GizmoGroup, GizmoUtils, Handler):
self.generate_gizmo_mode(add_data) 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): def refresh(self, context):
self.angle.target_set_prop('angle', self.angle.target_set_prop('angle',
context.object.modifiers.active, context.object.modifiers.active,
'angle') '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'} 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 from typing import Callable, Any
import bpy import bpy
from bpy.types import Gizmo, GizmoGroup
from bpy_extras import view3d_utils from bpy_extras import view3d_utils
from bpy.types import Gizmo from mathutils import Vector
from mathutils import Euler, Vector
from ..draw import Handler from ..draw import Handler
from ..utils import GizmoUtils from ..utils import GizmoUtils
class GizmoProperty(GizmoUtils, Handler): class GizmoProperty(GizmoUtils, Handler):
@property
def is_angle_mode(self):
return self.ctrl_mode == 'angle'
@property @property
def is_up_limits_mode(self): def is_up_limits_mode(self):
return self.ctrl_mode == 'up_limits' return self.ctrl_mode == 'up_limits'
@ -24,85 +20,17 @@ class GizmoProperty(GizmoUtils, Handler):
return self.ctrl_mode == 'down_limits' return self.ctrl_mode == 'down_limits'
class UpDownLimitsGizmo(GizmoProperty, Gizmo): class GizmoUpdate(GizmoProperty):
"""显示轴向切换拖动点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_
def update_gizmo_matrix(self, context): def update_gizmo_matrix(self, context):
ob = context.object self._update_matrix_basis_to_obj()
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()
co = self.generate_co_data() co = self.generate_co_data()
# calculation limits position # calculation limits position
top, bottom, left, right, front, back = self.each_face_pos(mat) top, bottom, left, right, front, back = self.each_face_pos(mat)
(up, down), (up_, down_) = self.get_limits_pos( (up, down), (up_, down_) = self.get_limits_pos(
mod, (top, bottom, left, right, front, back)) 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.up = up
self.down = down self.down = down
@ -113,42 +41,18 @@ class UpDownLimitsGizmo(GizmoProperty, Gizmo):
data = top, bottom, left, right, front, back data = top, bottom, left, right, front, back
self.update_draw_limits_bound_box(data, mod, axis, mat, up_, down_) self.update_draw_limits_bound_box(data, mod, axis, mat, up_, down_)
def setup(self): def _update_matrix_basis_to_obj(self):
self.generate_co_data() origin = self.modifier.origin
self.draw_type = 'None_GizmoGroup_' if origin:
self.ctrl_mode = 'up_limits' # up_limits , down_limits self.matrix_basis = origin.matrix_world.normalized()
self.mouse_dpi = 10 else:
self.rotate_follow_modifier = True self.matrix_basis = self.obj_matrix_world.normalized()
self.add_handler()
def invoke(self, context, event): def _update_matrix_basis_translation(self, co, mat, up_, down_):
self.init_invoke(context, event) if self.is_up_limits_mode:
mod = context.object.modifiers.active self.matrix_basis.translation = up_
limits = mod.limits elif self.is_down_limits_mode:
up_limits = limits[1] self.matrix_basis.translation = down_
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 delta_update(self, context, event, delta): def delta_update(self, context, event, delta):
if ('draw_line' in self.G_SimpleDeformGizmoHandlerDit) and (self.ctrl_mode in ('up_limits', 'down_limits')): 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) + ' ' 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_() text += t_()
elif self.is_up_limits_mode: elif self.is_up_limits_mode:
text += t_('Upper limit', up_limits) text += t_('Upper limit', up_limits)
@ -261,35 +165,148 @@ class UpDownLimitsGizmo(GizmoProperty, Gizmo):
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
def modal(self, context, event, tweak):
self.update_bound_box(context.object)
ob = context.object class UpDownLimitsGizmo(Gizmo, GizmoUpdate):
mod = ob.modifiers.active """显示轴向切换拖动点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 limits = mod.limits
up_limits = limits[1] up_limits = limits[1]
down_limits = limits[0] 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) if 'up_limits' == self.ctrl_mode:
delta = self.delta_update(context, event, delta) 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): def exit(self, context, cancel):
self.empty_object, _ = self.new_empty(ob, mod) context.area.header_text_set(None)
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) if cancel:
self.add_handler() 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' active modifier deform_method =='BEND'
""" """
simple = cls.simple_deform_public_poll(context) 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 return simple and is_bend
@classmethod @classmethod
@ -266,74 +266,7 @@ class PublicUtils(PublicPoll):
return cls.translate_text(mode) + ':{}'.format(value) return cls.translate_text(mode) + ':{}'.format(value)
class GizmoProperty: class GizmoClassMethod(PublicUtils):
@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)
@classmethod @classmethod
def get_origin_property_group(cls, mod, ob): def get_origin_property_group(cls, mod, ob):
if mod.origin: if mod.origin:
@ -481,6 +414,44 @@ class GizmoClassMethod(GizmoProperty, PublicUtils):
axis == 'Z') else vector axis == 'Z') else vector
return vector_axis 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 @classmethod
def update_bound_box(cls, obj: 'bpy.types.Object'): def update_bound_box(cls, obj: 'bpy.types.Object'):
context = bpy.context context = bpy.context
@ -574,15 +545,6 @@ class GizmoClassMethod(GizmoProperty, PublicUtils):
cls.G_SimpleDeformGizmoHandlerDit['draw'] = (ver, indices, matrix, modifiers, limits) 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 @classmethod
def update_co_data(cls, ob, mod): def update_co_data(cls, ob, mod):
handler_dit = cls.G_SimpleDeformGizmoHandlerDit 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 \ cls.G_SimpleDeformGizmoHandlerDit['co'] = co_items[index - 1][1] if (index or (index != 1)) else \
modifiers_co['co'] 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 custom_shape: dict
init_mouse_y: float init_mouse_y: float
init_mouse_x: float init_mouse_x: float
@ -654,20 +740,19 @@ class GizmoUtils(GizmoClassMethod):
return delta return delta
def get_snap(self, delta, tweak): def get_snap(self, delta, tweak):
# ctrl SNAP # TODO ctrl SNAP
# shift PRECISE # TODO shift PRECISE
is_snap = 'SNAP' in tweak is_snap = 'SNAP' in tweak
is_precise = 'PRECISE' in tweak is_precise = 'PRECISE' in tweak
if is_snap and is_precise: if is_snap and is_precise:
delta = round(delta) delta = round(delta)
# delta /= self.mouse_dpi
elif is_snap: elif is_snap:
delta //= 5 delta //= 5
delta *= 5 delta *= 5
elif is_precise: elif is_precise:
delta /= self.mouse_dpi
delta //= 0.01 delta //= 0.01
delta *= 0.01 delta *= 0.01
print('tweak', delta, tweak)
return delta return delta
def update_gizmo_matrix(self): def update_gizmo_matrix(self):