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
):
18 A utility that generates a pivot control with a custom position.
20 Generates a control bone, and an MCH output bone.
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,
37 assert rig
.generator
.stage
== 'generate_bones'
39 self
.bones
= rig
.bones
40 self
.id_name
= id_name
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
)
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
):
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
)
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
)
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
)
92 self
.set_bone_parent(self
.ctrl
, force_lazy(self
.parent
))
94 self
.set_bone_parent(self
.mch
, self
.ctrl
)
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
)