Import_3ds: Improved distance cue chunk import
[blender-addons.git] / rigify / utils / components.py
blobebda9cfe454fc9240b5418fefbee7a443fe9fc3d
1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 from typing import Optional
6 from mathutils import Vector, Matrix
8 from .naming import make_derived_name
9 from .bones import put_bone, copy_bone_position, align_bone_orientation
10 from .widgets_basic import create_pivot_widget
11 from .misc import force_lazy, OptionalLazy
13 from ..base_rig import BaseRig, RigComponent
16 class CustomPivotControl(RigComponent):
17 """
18 A utility that generates a pivot control with a custom position.
20 Generates a control bone, and an MCH output bone.
21 """
23 ctrl: str
24 mch: str
26 def __init__(
27 self, rig: BaseRig, id_name: str, org_bone: str, *,
28 name: Optional[str] = None, parent: OptionalLazy[str] = None,
29 position: Optional[Vector] = None, matrix: Optional[Matrix] = None,
30 scale: float = 1.0, scale_mch: Optional[float] = None,
31 move_to: OptionalLazy[str] = None, align_to: OptionalLazy[str] = None,
32 snap_to: OptionalLazy[str] = None,
33 widget_axis: float = 1.5, widget_cap: float = 1.0, widget_square: bool = True,
35 super().__init__(rig)
37 assert rig.generator.stage == 'generate_bones'
39 self.bones = rig.bones
40 self.id_name = id_name
42 self.parent = parent
43 self.scale = scale or 1
44 self.scale_mch = scale_mch or (self.scale * 0.7)
45 self.move_to = move_to
46 self.align_to = align_to
47 self.snap_to = snap_to
48 self.widget_axis = widget_axis
49 self.widget_cap = widget_cap
50 self.widget_square = widget_square
52 name = name or make_derived_name(org_bone, 'ctrl', '_pivot')
54 self.do_make_bones(org_bone, name, position, matrix)
56 @property
57 def control(self):
58 return self.ctrl
60 @property
61 def output(self):
62 return self.mch
64 def do_make_bones(self, org: str, name: str,
65 position: Optional[Vector], matrix: Optional[Matrix]):
66 self.bones.ctrl[self.id_name] = self.ctrl =\
67 self.copy_bone(org, name, parent=not self.parent, scale=self.scale)
68 self.bones.mch[self.id_name] = self.mch =\
69 self.copy_bone(org, make_derived_name(name, 'mch'), scale=self.scale_mch)
71 if position or matrix:
72 put_bone(self.obj, self.ctrl, position, matrix=matrix)
73 put_bone(self.obj, self.mch, position, matrix=matrix)
75 def parent_bones(self):
76 if self.snap_to:
77 bone = force_lazy(self.snap_to)
78 copy_bone_position(self.obj, bone, self.ctrl, scale=self.scale)
79 copy_bone_position(self.obj, bone, self.mch, scale=self.scale_mch)
81 if self.move_to:
82 pos = self.get_bone(force_lazy(self.move_to)).head
83 put_bone(self.obj, self.ctrl, pos)
84 put_bone(self.obj, self.mch, pos)
86 if self.align_to:
87 self.align_to = force_lazy(self.align_to)
88 align_bone_orientation(self.obj, self.ctrl, self.align_to)
89 align_bone_orientation(self.obj, self.mch, self.align_to)
91 if self.parent:
92 self.set_bone_parent(self.ctrl, force_lazy(self.parent))
94 self.set_bone_parent(self.mch, self.ctrl)
96 def rig_bones(self):
97 self.make_constraint(
98 self.mch, 'COPY_LOCATION', self.ctrl, space='LOCAL', invert_xyz=(True,)*3)
100 def generate_widgets(self):
101 create_pivot_widget(self.obj, self.ctrl, axis_size=self.widget_axis,
102 cap_size=self.widget_cap, square=self.widget_square)