1 # SPDX-License-Identifier: GPL-2.0-or-later
7 from ...utils
.rig
import connected_children_names
8 from ...utils
.layers
import ControlLayersOption
9 from ...utils
.bones
import BoneUtilityMixin
, flip_bone_chain
11 from ...base_generate
import SubstitutionRig
13 from . import basic_spine
, basic_tail
, super_head
16 class Rig(SubstitutionRig
, BoneUtilityMixin
):
17 """Compatibility proxy for the monolithic super_spine rig that splits it into parts."""
20 params_copy
= self
.params_copy
21 orgs
= [self
.base_bone
] + connected_children_names(self
.obj
, self
.base_bone
)
23 # Split the bone list according to the settings
28 pivot_pos
= self
.params
.pivot_pos
30 if self
.params
.use_head
:
31 neck_pos
= self
.params
.neck_pos
32 if neck_pos
<= pivot_pos
:
33 self
.raise_error("Neck cannot be below or the same as pivot.")
34 if neck_pos
>= len(orgs
):
35 self
.raise_error("Neck is too short.")
37 spine_orgs
= orgs
[0 : neck_pos
-1]
38 head_orgs
= orgs
[neck_pos
-1 : ]
40 if self
.params
.use_tail
:
41 tail_pos
= self
.params
.tail_pos
43 self
.raise_error("Tail is too short.")
44 if tail_pos
>= pivot_pos
:
45 self
.raise_error("Tail cannot be above or the same as pivot.")
47 tail_orgs
= list(reversed(spine_orgs
[0 : tail_pos
]))
48 spine_orgs
= spine_orgs
[tail_pos
: ]
51 # Split the bone chain and flip the tail
52 if head_orgs
or tail_orgs
:
53 bpy
.ops
.object.mode_set(mode
='EDIT')
55 if spine_orgs
[0] != orgs
[0]:
56 self
.set_bone_parent(spine_orgs
[0], self
.get_bone_parent(orgs
[0]))
59 self
.get_bone(head_orgs
[0]).use_connect
= False
62 flip_bone_chain(self
.obj
, reversed(tail_orgs
))
63 self
.set_bone_parent(tail_orgs
[0], spine_orgs
[0])
65 bpy
.ops
.object.mode_set(mode
='OBJECT')
68 self
.assign_params(spine_orgs
[0], params_copy
, pivot_pos
=pivot_pos
, make_fk_controls
=False)
70 result
= [ self
.instantiate_rig(basic_spine
.Rig
, spine_orgs
[0]) ]
73 self
.assign_params(tail_orgs
[0], params_copy
, connect_chain
=True)
75 result
+= [ self
.instantiate_rig(basic_tail
.Rig
, tail_orgs
[0]) ]
78 self
.assign_params(head_orgs
[0], params_copy
, connect_chain
=True)
80 result
+= [ self
.instantiate_rig(super_head
.Rig
, head_orgs
[0]) ]
85 def add_parameters(params
):
86 basic_spine
.Rig
.add_parameters(params
)
87 basic_tail
.Rig
.add_parameters(params
)
88 super_head
.Rig
.add_parameters(params
)
90 params
.neck_pos
= bpy
.props
.IntProperty(
91 name
= 'neck_position',
94 description
= 'Neck start position'
97 params
.tail_pos
= bpy
.props
.IntProperty(
101 description
='Where the tail starts'
104 params
.use_tail
= bpy
.props
.BoolProperty(
107 description
='Create tail bones'
110 params
.use_head
= bpy
.props
.BoolProperty(
113 description
='Create head and neck bones'
117 def parameters_ui(layout
, params
):
118 """ Create the ui for the rig parameters."""
120 layout
.label(text
="Note: this combined rig is deprecated.", icon
='INFO')
122 r
= layout
.row(align
=True)
123 r
.prop(params
, "use_head", toggle
=True, text
="Head")
124 r
.prop(params
, "use_tail", toggle
=True, text
="Tail")
127 r
.prop(params
, "neck_pos")
128 r
.enabled
= params
.use_head
131 r
.prop(params
, "pivot_pos")
134 r
.prop(params
, "tail_pos")
135 r
.enabled
= params
.use_tail
138 col
= r
.column(align
=True)
139 row
= col
.row(align
=True)
140 for i
, axis
in enumerate(['x', 'y', 'z']):
141 row
.prop(params
, "copy_rotation_axes", index
=i
, toggle
=True, text
=axis
)
142 r
.enabled
= params
.use_tail
144 ControlLayersOption
.TWEAK
.parameters_ui(layout
, params
)
147 def create_sample(obj
):
148 bones
= basic_spine
.create_sample(obj
)
149 basic_tail
.create_sample(obj
, parent
=bones
['spine'])
150 super_head
.create_sample(obj
, parent
=bones
['spine.003'])