Welcome to mirror list, hosted at ThFree Co, Russian Federation.

rear_paw.py « limbs « rigs « rigify - git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9d3f0d2eb4f6c004630cff63b652e2b769c2ba41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# SPDX-License-Identifier: GPL-2.0-or-later

import bpy

from ...utils.bones import align_bone_roll
from ...utils.naming import make_derived_name
from ...utils.misc import map_list

from itertools import count

from ...base_rig import stage

from .limb_rigs import BaseLimbRig
from .paw import Rig as pawRig, create_sample as create_paw_sample


class Rig(pawRig):
    """Rear paw rig with special IK automation."""

    ####################################################
    # EXTRA BONES
    #
    # mch:
    #   ik2_target
    #     Three bone IK stretch limit
    #   ik2_chain[2]
    #     Second IK system (pre-driving thigh and ik3)
    #   ik3_chain[2]
    #     Third IK system (pre-driving heel)
    #
    ####################################################

    ####################################################
    # IK controls

    def get_middle_ik_controls(self):
        return [self.bones.ctrl.heel]

    def get_ik_fk_position_chains(self):
        ik_chain, tail_chain, fk_chain = super().get_ik_fk_position_chains()
        assert not tail_chain
        if not self.use_heel2:
            return [*ik_chain, ik_chain[-1]], [], [*fk_chain, fk_chain[-1]]
        return ik_chain, tail_chain, fk_chain

    def get_extra_ik_controls(self):
        extra = [self.bones.ctrl.heel2] if self.use_heel2 else []
        return BaseLimbRig.get_extra_ik_controls(self) + extra

    def get_ik_pole_parents(self):
        return [(self.bones.mch.ik2_target, self.bones.ctrl.ik)]


    ####################################################
    # Heel control

    @stage.parent_bones
    def parent_heel_control_bone(self):
        self.set_bone_parent(self.bones.ctrl.heel, self.bones.mch.ik3_chain[-1])


    ####################################################
    # Second IK system (pre-driving thigh)

    use_mch_ik_base = True

    def get_ik2_input_bone(self):
        return self.bones.ctrl.heel2 if self.use_heel2 else self.bones.mch.toe_socket

    @stage.generate_bones
    def make_ik2_mch_stretch(self):
        orgs = self.bones.org.main

        self.bones.mch.ik2_target = self.make_ik2_mch_target_bone(orgs)

    def make_ik2_mch_target_bone(self, orgs):
        return self.copy_bone(orgs[3], make_derived_name(orgs[0], 'mch', '_ik2_target'), scale=1/2)

    @stage.generate_bones
    def make_ik2_mch_chain(self):
        orgs = self.bones.org.main
        chain = map_list(self.make_ik2_mch_bone, count(0), orgs[0:2])
        self.bones.mch.ik2_chain = chain

        org_bones = map_list(self.get_bone, orgs)
        chain_bones = map_list(self.get_bone, chain)

        # Extend the base IK control (used in the ik2 chain) with the projected length of org2
        chain_bones[0].length += org_bones[2].vector.dot(chain_bones[0].vector.normalized())
        chain_bones[1].head = chain_bones[0].tail
        chain_bones[1].tail = org_bones[2].tail
        align_bone_roll(self.obj, chain[1], orgs[1])

    def make_ik2_mch_bone(self, i, org):
        return self.copy_bone(org, make_derived_name(org, 'mch', '_ik2'))

    @stage.parent_bones
    def parent_ik2_mch_chain(self):
        mch = self.bones.mch
        self.set_bone_parent(mch.ik2_target, self.get_ik2_input_bone())
        self.set_bone_parent(mch.ik2_chain[0], self.bones.ctrl.ik_base, inherit_scale='AVERAGE')
        self.parent_bone_chain(mch.ik2_chain, use_connect=True)

    @stage.configure_bones
    def configure_ik2_mch_chain(self):
        for i, mch in enumerate(self.bones.mch.ik2_chain):
            self.configure_ik2_mch_bone(i, mch)

    def configure_ik2_mch_bone(self, i, mch):
        bone = self.get_bone(mch)
        bone.ik_stretch = 0.1
        if i == 1:
            bone.lock_ik_x = bone.lock_ik_y = bone.lock_ik_z = True
            setattr(bone, 'lock_ik_' + self.main_axis, False)

    @stage.rig_bones
    def rig_ik2_mch_chain(self):
        mch = self.bones.mch
        input_bone = self.get_ik2_input_bone()
        head_tail = 1 if self.use_heel2 else 0

        self.rig_ik_mch_stretch_limit(mch.ik2_target, mch.follow, input_bone, head_tail, 3)
        self.rig_ik_mch_end_bone(mch.ik2_chain[-1], mch.ik2_target, self.bones.ctrl.ik_pole)


    ####################################################
    # Third IK system (pre-driving heel control)

    @stage.generate_bones
    def make_ik3_mch_chain(self):
        self.bones.mch.ik3_chain = map_list(self.make_ik3_mch_bone, count(0), self.bones.org.main[1:3])

    def make_ik3_mch_bone(self, i, org):
        return self.copy_bone(org, make_derived_name(org, 'mch', '_ik3'))

    @stage.parent_bones
    def parent_ik3_mch_chain(self):
        mch = self.bones.mch

        self.set_bone_parent(mch.ik3_chain[0], mch.ik2_chain[0])
        self.parent_bone_chain(mch.ik3_chain, use_connect=True)

    @stage.configure_bones
    def configure_ik3_mch_chain(self):
        for i, mch in enumerate(self.bones.mch.ik3_chain):
            self.configure_ik3_mch_bone(i, mch)

    def configure_ik3_mch_bone(self, i, mch):
        bone = self.get_bone(mch)
        bone.ik_stretch = 0.1
        if i == 0:
            bone.lock_ik_x = bone.lock_ik_y = bone.lock_ik_z = True
            setattr(bone, 'lock_ik_' + self.main_axis, False)

    @stage.rig_bones
    def rig_ik3_mch_chain(self):
        mch = self.bones.mch
        # Mostly cancel ik2 scaling.
        self.make_constraint(
            mch.ik3_chain[0], 'COPY_SCALE', self.bones.ctrl.ik_base,
            use_make_uniform=True, influence=0.75,
        )
        self.make_constraint(mch.ik3_chain[-1], 'IK', mch.ik2_target, chain_count=2)


def create_sample(obj):
    bones = create_paw_sample(obj)
    pbone = obj.pose.bones[bones['thigh.L']]
    pbone.rigify_type = 'limbs.rear_paw'
    return bones