Rigify 0.5 advanced generation options, fixes and improvements. removed CREDITS and README files
This commit is contained in:
parent
8d5d983116
commit
c60d7e3257
|
@ -1,32 +0,0 @@
|
|||
A big thank you to all the people listed here for supporting Rigify.
|
||||
|
||||
Original prototyping and development, and Python API support:
|
||||
- Campbell Barton
|
||||
|
||||
Development:
|
||||
- PitchiPoy Animation Productions
|
||||
- Kfir Merlaub
|
||||
- Tamir Lousky
|
||||
|
||||
General financial support:
|
||||
- Benjamin Tolputt
|
||||
- Nesterenko Viktoriya
|
||||
- Jeff Hogan
|
||||
- PitchiPoy Animation Productions
|
||||
|
||||
IK/FK snapping financial support:
|
||||
- Benjamin Tolputt
|
||||
- Nesterenko Viktoriya
|
||||
- Leslie Chih
|
||||
- Isaac Ah-Loe
|
||||
- Casey "TheLorax" Jones
|
||||
|
||||
### Rigify Version 0.5 ###
|
||||
Development:
|
||||
- Lucio Rossi
|
||||
|
||||
Design:
|
||||
- Ivan Cappiello
|
||||
|
||||
General financial support:
|
||||
- Mad Entertainment Animation
|
250
rigify/README
250
rigify/README
|
@ -1,250 +0,0 @@
|
|||
INTRODUCTION
|
||||
------------
|
||||
Rigify is an auto-rigging system based on a "building blocks" paradigm. The
|
||||
user can create a rig by putting together any combination of rig types, in any
|
||||
configuration that they want.
|
||||
|
||||
A rig type is something like "biped arm" or "spine" or "finger".
|
||||
|
||||
The input to the Rigify system is something called a "metarig". It is an
|
||||
armature that contains data about how to construct the rig. In particular, it
|
||||
contains bones in the basic configuration of the rig, with some bones tagged
|
||||
to indicate the rig type.
|
||||
|
||||
For example, a metarig might contain a chain of three bones, the root-most of
|
||||
which is tagged as being a biped arm. When given as input to Rigify, Rigify
|
||||
will then generate a fully-featured biped arm rig in the same position and
|
||||
proportions as the 3-bone chain.
|
||||
|
||||
One could also have another chain of bones, the root-most of which is tagged as
|
||||
being a spine. And the root-most bone of the arm chain could be the child of
|
||||
any of those spine bones. Then the rig that Rigify generates would be a
|
||||
spine rig with an arm rig attached to it.
|
||||
|
||||
|
||||
THE GUTS OF RIGIFY, SUMMARIZED
|
||||
------------------------------
|
||||
The concept behind rigify is fairly simple. It recieves an armature as input
|
||||
with some of the bones tagged as being certain rig types (arm, leg, etc.)
|
||||
|
||||
When Rigify recieves that armature as input, the first thing it does is
|
||||
duplicate the armature. From here on out, the original armature is totally
|
||||
ignored. Only the duplicate is used. And this duplicate armature object will
|
||||
become the generated rig.
|
||||
|
||||
Rigify next prepends "ORG-" to all of the bones. These are the "original"
|
||||
bones of the metarig, and they are used as the glue between rig types, as I
|
||||
will explain later.
|
||||
|
||||
Rigify then generates the rig in two passes. The first pass is the
|
||||
"information gathering" stage.
|
||||
|
||||
The information gathering stage doesn't modify the armature at all. It simply
|
||||
gathers information about it. Or, rather, it lets the rig types gather
|
||||
information about it.
|
||||
It traverses the bones in a root-most to leaf-most order, and whenever it
|
||||
stumbles upon a bone that has a rig type tagged on it, it creates a rig-type
|
||||
python object (rig types will be explained further down) for that rig type,
|
||||
and executes the resulting python object's information gathering code.
|
||||
|
||||
At the end of the information gathering stage, Rigify has a collection of
|
||||
python objects, each of which know all the information they need to generate
|
||||
their own bit of the rig.
|
||||
|
||||
The next stage is the rig generation stage. This part is pretty simple. All
|
||||
Rigify does is it loops over all of the rig-type python objects that it created
|
||||
in the previous stage (also in root-most to leaf-most order), and executes
|
||||
their rig-generate code. All of the actual rig generation happens in the
|
||||
rig-type python objects.
|
||||
|
||||
And that's pretty much it. As you can see, most of the important code is
|
||||
actually in the rig types themselves, not in Rigify. Rigify is pretty sparse
|
||||
when it comes right down to it.
|
||||
|
||||
There is one final stage to rig generation. Rigify checks all of the bones
|
||||
for "DEF-", "MCH-", and "ORG-" prefixes, and moves those bones to their own
|
||||
layers. It also sets all of the "DEF-" bones to deform, and sets all other
|
||||
bones to _not_ deform. And finally, it looks for any bone that does not have
|
||||
a parent, and sets the root bone (which Rigify creates) as their parent.
|
||||
|
||||
|
||||
THE GUTS OF A RIG TYPE, BASIC
|
||||
-----------------------------
|
||||
A rig type is simply a python module containing a class named "Rig", and some
|
||||
optional module functions. The Rig class has only two methods:
|
||||
__init__() and generate()
|
||||
|
||||
__init__() is the "information gathering" code for the rig type. When Rigify
|
||||
loops through the bones and finds a tagged bone, it will create a python
|
||||
object from the Rig class, executing this method.
|
||||
In addition to the default "self" parameter, __init__() needs to take the
|
||||
armature object, the name of the bone that was tagged, and a parameters object.
|
||||
|
||||
A proper rig-type __init__() will look like this:
|
||||
|
||||
def __init__(self, obj, bone_name, params):
|
||||
# code goes here
|
||||
|
||||
At the bare minimum, you are going to want to store the object and bone name
|
||||
in the rig type object for later reference in the generate() method. So:
|
||||
|
||||
def __init__(self, obj, bone_name, params):
|
||||
self.obj = obj
|
||||
self.org_bone = bone_name
|
||||
|
||||
Most rig types involve more than just that one bone, though, so you will also
|
||||
want to store the names of any other relevant bones. For example, maybe the
|
||||
parent of the tagged bone is important to the rig type:
|
||||
|
||||
def __init__(self, obj, bone_name, params):
|
||||
self.obj = obj
|
||||
self.org_bone = bone_name
|
||||
self.org_parent = obj.data.bones[bone_name].parent.name
|
||||
|
||||
It is important that you store the _names_ of the bones, and not direct
|
||||
references. Due to the inner workings of Blender's armature system, direct
|
||||
edit-bone and pose-bone references are lost when flipping in and out of
|
||||
armature edit mode. (Arg...)
|
||||
|
||||
Remember that it is critical that the information-gathering method does _not_
|
||||
modify the armature in any way. This way all of the rig type's info-gathering
|
||||
methods can execute on a clean armature. Many rig types depend on traversing
|
||||
parent-child relationships to figure out what bones are relevant to them, for
|
||||
example.
|
||||
|
||||
|
||||
Next is the generate() method. This is the method that Rigify calls to
|
||||
actually generate the rig. It takes the form:
|
||||
|
||||
def generate(self):
|
||||
# code goes here
|
||||
|
||||
It doesn't take any parameters beyond "self". So you have to store any
|
||||
information you need with the __init__() method.
|
||||
|
||||
generate() pretty much has free reign to do whatever it wants, with the exception
|
||||
of two simple rules:
|
||||
1. Other than the "ORG-" bones, do not touch anything that is not created by
|
||||
the rig type (this prevents rig types from messing each other up).
|
||||
2. Even with "ORG-" bones, the only thing you are allowed to do is add children
|
||||
and add constraints. Do not rename them, do not remove children or
|
||||
constraints, and especially do not change their parents. (Adding constraints
|
||||
and adding children are encouraged, though. ;-)) This is because the "ORG-"
|
||||
bones are the glue that holds everything together, and changing them beyond
|
||||
adding children/constraints ruins the glue, so to speak.
|
||||
|
||||
In short: with the exception of adding children/constraints to "ORG-"
|
||||
bones, only mess with things that you yourself create.
|
||||
|
||||
It is also generally a good idea (though not strictly required) that the rig
|
||||
type add constraints to the "ORG-" bones it was generated from so that the
|
||||
"ORG-" bones move with the animation controls.
|
||||
For example, if I make a simple arm rig type, the controls that the animator
|
||||
uses should also move the "ORG-" bones. That way, any other rig-types that are
|
||||
children of those "ORG-" bones will move along with them. For example, any
|
||||
fingers on the end of the arm.
|
||||
|
||||
Also, any bones that the animator should not directly animate with should have
|
||||
their names prefixed with "DEF-" or "MCH-". The former if it is a bone that
|
||||
is intended to deform the mesh, the latter if it is not.
|
||||
It should be obvious, then, that a bone cannot be both an animation control and
|
||||
a deforming bone in Rigify. This is on purpose.
|
||||
|
||||
Also note that there are convenience functions in utils.py for prepending
|
||||
"DEF-" and "MCH-" to bone names: deformer() and mch()
|
||||
There is also a convenience function for stripping "ORG-" from a bone name:
|
||||
strip_org()
|
||||
Which is useful for removing "ORG-" from bones you create by duplicating
|
||||
the "ORG-" bones.
|
||||
I recommend you use these functions instead of manually adding/stripping
|
||||
these prefixes. That way if the prefixes are changed, it can be changed in
|
||||
one place (those functions) and all the rig types will still work.
|
||||
|
||||
|
||||
THE GUTS OF A RIG TYPE, ADVANCED
|
||||
--------------------------------
|
||||
If you look at any of the rig types included with Rigify, you'll note that they
|
||||
have several functions outside of the Rig class.
|
||||
THESE ADDITIONAL FUNCTIONS ARE _NOT_ REQUIRED for a rig type to function. But
|
||||
they can add some nifty functionality to your rig.
|
||||
|
||||
Here are the additional functions relevant to Rigify, with brief decriptions of
|
||||
what they are for:
|
||||
|
||||
|
||||
RIG PARAMETERS
|
||||
--------------
|
||||
For many rig types, it is handy for the user to be able to tweak how they are
|
||||
generated. For example, the included biped arm rig allows the user to specify
|
||||
the axis of rotation for the elbow.
|
||||
|
||||
There are two functions necessary to give a rig type user-tweakable parameters:
|
||||
add_parameters()
|
||||
parameters_ui()
|
||||
|
||||
add_parameters() takes an IDPropertyGroup as input, and adds its parameters
|
||||
to that group as RNA properties. For example:
|
||||
|
||||
def add_parameters(params):
|
||||
params.toggle_param = bpy.props.BoolProperty(name="Test toggle:", default=False, description="Just a test, not really used for anything.")
|
||||
|
||||
parameters_ui() recieves a Blender UILayout object and an IDPropertyGroup
|
||||
containing the parameters added by add_parameters(). It creates a GUI in the
|
||||
UILayout for the user to tweak those parameters. For example:
|
||||
|
||||
def parameters_ui(layout, params):
|
||||
r = layout.row()
|
||||
r.prop(params, "toggle_param")
|
||||
|
||||
|
||||
SAMPLE METARIG
|
||||
--------------
|
||||
It is a good idea for all rig types to have a sample metarig that the user can
|
||||
add to their own metarig. This is what the create_sample() function is for.
|
||||
|
||||
create_sample() takes the current armature object as input, and adds the bones
|
||||
for its rig-type's metarig. For example:
|
||||
|
||||
def create_sample(obj):
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
arm = obj.data
|
||||
|
||||
bone = arm.edit_bones.new('Bone')
|
||||
bone.head[:] = 0.0000, 0.0000, 0.0000
|
||||
bone.tail[:] = 0.0000, 0.0000, 1.0000
|
||||
bone.roll = 0.0000
|
||||
bone.use_connect = False
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
pbone = obj.pose.bones[bone]
|
||||
pbone.rigify_type = 'copy'
|
||||
pbone.rigify_parameters.add()
|
||||
|
||||
Obviously, this isn't something that you generally want to hand-code,
|
||||
especially with more complex samples. When in edit-mode on an armature,
|
||||
there is a "Rigify Dev Tools" panel in the View3d tools panel containing a
|
||||
button labeled "Encode Sample to Python". This button will generate the python
|
||||
code for create_sample() from the armature you are editing. The generated code
|
||||
appears in a text block called "metarig_sample.py"
|
||||
|
||||
IMPLEMENTATION RIGS
|
||||
-------------------
|
||||
Starting from version 0.5 you can create a Rig class as an implementation of a wrapper class.
|
||||
This happens for limb rigs for example, where super_limb is kind of a wrapper class for arm, leg and paws.
|
||||
To declare a class as an implementation just declare an IMPLEMENTATION constant in the module and set it to True.
|
||||
Implementation classes are shown in the metarig samples list and generate a sample if a proper create_sample function is implemented, but cannot be directly assigned as a rigify type.
|
||||
|
||||
GENERATING A PYTHON UI
|
||||
----------------------
|
||||
The generate() method can also, optionally, return python code as a single
|
||||
string. This python code is added to the "rig properties" panel that gets
|
||||
auto-generated along with the rig. This is useful for exposing things like
|
||||
IK/FK switches in a nice way to the animator.
|
||||
|
||||
The string must be returned in a list, e.g.:
|
||||
|
||||
return ["my python code"]
|
||||
|
||||
The reason it needs to be put in a list is to leave room for expanding the API
|
||||
in the future, for returning additional information.
|
||||
|
|
@ -286,24 +286,38 @@ def register():
|
|||
IDStore.rigify_types = bpy.props.CollectionProperty(type=RigifyName)
|
||||
IDStore.rigify_active_type = bpy.props.IntProperty(name="Rigify Active Type", description="The selected rig type")
|
||||
|
||||
IDStore.rigify_advanced_generation = bpy.props.BoolProperty(name="Rigify Advanced Generation",
|
||||
description="Rigify Advanced Generation Parameters",
|
||||
IDStore.rigify_advanced_generation = bpy.props.BoolProperty(name="Advanced Options",
|
||||
description="Enables/disables advanced options for Rigify rig generation",
|
||||
default=False)
|
||||
|
||||
def update_mode(self, context):
|
||||
if self.rigify_generate_mode == 'new':
|
||||
self.rigify_force_widget_update = False
|
||||
|
||||
IDStore.rigify_generate_mode = bpy.props.EnumProperty(name="Rigify Generate Rig Mode",
|
||||
description="'Generate Rig' mode. In 'overwrite' mode the features of the target rig will be updated as defined by the metarig. In 'new' mode a new rig will be created as defined by the metarig. Current mode",
|
||||
update=update_mode,
|
||||
items=(('overwrite', 'overwrite', ''),
|
||||
('new', 'new', '')))
|
||||
|
||||
IDStore.rigify_force_widget_update = bpy.props.BoolProperty(name="Force Widget Update",
|
||||
description="Rigify Force Widget Update",
|
||||
description="Forces Rigify to delete and rebuild all the rig widgets. if unset, only missing widgets will be created",
|
||||
default=False)
|
||||
|
||||
IDStore.rigify_target_rigs = bpy.props.CollectionProperty(type=RigifyName)
|
||||
IDStore.rigify_target_rig = bpy.props.StringProperty(name="Rigify Target Rig",
|
||||
description="The Rig, Generate will run upon",
|
||||
description="Defines which rig to overwrite. If unset, a new one called 'rig' will be created.",
|
||||
default="")
|
||||
|
||||
IDStore.rigify_rig_uis = bpy.props.CollectionProperty(type=RigifyName)
|
||||
IDStore.rigify_rig_ui = bpy.props.StringProperty(name="Rigify Target Rig UI",
|
||||
description="The Rig UI to overwrite",
|
||||
description="Defines the UI to overwrite. It should always be the same as the target rig. If unset, 'rig_ui.py' will be used",
|
||||
default="")
|
||||
|
||||
IDStore.rigify_rig_basename = bpy.props.StringProperty(name="Rigify Rig Name",
|
||||
description="Defines the name of the Rig. If unset, in 'new' mode 'rig' will be used, in 'overwrite' mode the target rig name will be used",
|
||||
default="")
|
||||
|
||||
if (ui and 'legacy' in str(ui)) or bpy.context.user_preferences.addons['rigify'].preferences.legacy_mode:
|
||||
# update legacy on restart or reload
|
||||
bpy.context.user_preferences.addons['rigify'].preferences.legacy_mode = True
|
||||
|
@ -326,11 +340,13 @@ def unregister():
|
|||
del IDStore.rigify_types
|
||||
del IDStore.rigify_active_type
|
||||
del IDStore.rigify_advanced_generation
|
||||
del IDStore.rigify_generate_mode
|
||||
del IDStore.rigify_force_widget_update
|
||||
del IDStore.rigify_target_rig
|
||||
del IDStore.rigify_target_rigs
|
||||
del IDStore.rigify_rig_uis
|
||||
del IDStore.rigify_rig_ui
|
||||
del IDStore.rigify_rig_basename
|
||||
|
||||
bpy.utils.unregister_class(RigifyName)
|
||||
bpy.utils.unregister_class(RigifyParameters)
|
||||
|
|
|
@ -81,15 +81,30 @@ def generate_rig(context, metarig):
|
|||
# object to generate the rig in.
|
||||
print("Fetch rig.")
|
||||
|
||||
name = id_store.rigify_target_rig or "rig"
|
||||
rig_new_name = ""
|
||||
rig_old_name = ""
|
||||
if id_store.rigify_rig_basename:
|
||||
rig_new_name = id_store.rigify_rig_basename + "_rig"
|
||||
|
||||
try:
|
||||
obj = scene.objects[name]
|
||||
except KeyError:
|
||||
obj = bpy.data.objects.new(name, bpy.data.armatures.new(name))
|
||||
if id_store.rigify_generate_mode == 'overwrite':
|
||||
name = id_store.rigify_target_rig or "rig"
|
||||
try:
|
||||
obj = scene.objects[name]
|
||||
rig_old_name = name
|
||||
obj.name = rig_new_name or name
|
||||
except KeyError:
|
||||
rig_old_name = name
|
||||
name = rig_new_name or name
|
||||
obj = bpy.data.objects.new(name, bpy.data.armatures.new(name))
|
||||
obj.draw_type = 'WIRE'
|
||||
scene.objects.link(obj)
|
||||
else:
|
||||
name = rig_new_name or "rig"
|
||||
obj = bpy.data.objects.new(name, bpy.data.armatures.new(name)) # in case name 'rig' exists it will be rig.001
|
||||
obj.draw_type = 'WIRE'
|
||||
scene.objects.link(obj)
|
||||
|
||||
id_store.rigify_target_rig = obj.name
|
||||
obj.data.pose_position = 'POSE'
|
||||
|
||||
# Get rid of anim data in case the rig already existed
|
||||
|
@ -102,17 +117,22 @@ def generate_rig(context, metarig):
|
|||
scene.objects.active = obj
|
||||
|
||||
# Remove wgts if force update is set
|
||||
if "WGTS" in scene.objects and id_store.rigify_force_widget_update:
|
||||
wgts_group_name = "WGTS_" + (rig_old_name or obj.name)
|
||||
if wgts_group_name in scene.objects and id_store.rigify_force_widget_update:
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for i, lyr in enumerate(WGT_LAYERS):
|
||||
if lyr:
|
||||
context.scene.layers[i] = True
|
||||
for wgt in bpy.data.objects["WGTS"].children:
|
||||
for wgt in bpy.data.objects[wgts_group_name].children:
|
||||
wgt.select = True
|
||||
bpy.ops.object.delete(use_global=False)
|
||||
for i, lyr in enumerate(WGT_LAYERS):
|
||||
if lyr:
|
||||
context.scene.layers[i] = False
|
||||
if rig_old_name:
|
||||
bpy.data.objects[wgts_group_name].name = "WGTS_" + obj.name
|
||||
|
||||
wgts_group_name = "WGTS_" + obj.name
|
||||
|
||||
# Remove all bones from the generated rig armature.
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
@ -281,7 +301,7 @@ def generate_rig(context, metarig):
|
|||
t.tick("Create root bone: ")
|
||||
|
||||
# Create Group widget
|
||||
wgts_group_name = "WGTS"
|
||||
# wgts_group_name = "WGTS"
|
||||
if wgts_group_name not in scene.objects:
|
||||
if wgts_group_name in bpy.data.objects:
|
||||
bpy.data.objects[wgts_group_name].user_clear()
|
||||
|
@ -291,6 +311,18 @@ def generate_rig(context, metarig):
|
|||
scene.objects.link(wgts_obj)
|
||||
wgts_obj.layers = WGT_LAYERS
|
||||
t.tick("Create main WGTS: ")
|
||||
#
|
||||
# if id_store.rigify_generate_mode == 'new':
|
||||
# bpy.ops.object.select_all(action='DESELECT')
|
||||
# for wgt in bpy.data.objects[wgts_group_name].children:
|
||||
# wgt.select = True
|
||||
# for i, lyr in enumerate(WGT_LAYERS):
|
||||
# if lyr:
|
||||
# context.scene.layers[i] = True
|
||||
# bpy.ops.object.make_single_user(obdata=True)
|
||||
# for i, lyr in enumerate(WGT_LAYERS):
|
||||
# if lyr:
|
||||
# context.scene.layers[i] = False
|
||||
|
||||
#----------------------------------
|
||||
try:
|
||||
|
@ -410,7 +442,7 @@ def generate_rig(context, metarig):
|
|||
# Assign shapes to bones
|
||||
# Object's with name WGT-<bone_name> get used as that bone's shape.
|
||||
for bone in bones:
|
||||
wgt_name = (WGT_PREFIX + obj.data.bones[bone].name)[:63] # Object names are limited to 63 characters... arg
|
||||
wgt_name = (WGT_PREFIX + obj.name + '_' + obj.data.bones[bone].name)[:63] # Object names are limited to 63 characters... arg
|
||||
if wgt_name in context.scene.objects:
|
||||
# Weird temp thing because it won't let me index by object name
|
||||
for ob in context.scene.objects:
|
||||
|
@ -439,13 +471,24 @@ def generate_rig(context, metarig):
|
|||
layer_layout += [(l.name, l.row)]
|
||||
|
||||
# Generate the UI script
|
||||
rig_ui_name = id_store.rigify_rig_ui or 'rig_ui.py'
|
||||
if id_store.rigify_generate_mode == 'overwrite':
|
||||
rig_ui_name = id_store.rigify_rig_ui or 'rig_ui.py'
|
||||
else:
|
||||
rig_ui_name = 'rig_ui.py'
|
||||
|
||||
if rig_ui_name in bpy.data.texts.keys():
|
||||
if id_store.rigify_generate_mode == 'overwrite' and rig_ui_name in bpy.data.texts.keys():
|
||||
script = bpy.data.texts[rig_ui_name]
|
||||
script.clear()
|
||||
else:
|
||||
script = bpy.data.texts.new("rig_ui.py")
|
||||
|
||||
rig_ui_old_name = ""
|
||||
if id_store.rigify_rig_basename:
|
||||
rig_ui_old_name = script.name
|
||||
script.name = id_store.rigify_rig_basename + "_rig_ui.py"
|
||||
|
||||
id_store.rigify_rig_ui = script.name
|
||||
|
||||
script.write(UI_SLIDERS % rig_id)
|
||||
for s in ui_scripts:
|
||||
script.write("\n " + s.replace("\n", "\n ") + "\n")
|
||||
|
@ -465,14 +508,15 @@ def generate_rig(context, metarig):
|
|||
# Add rig_ui to logic
|
||||
skip = False
|
||||
ctrls = obj.game.controllers
|
||||
|
||||
for c in ctrls:
|
||||
if 'Python' in c.name and c.text.name == 'rig_ui.py':
|
||||
if 'Python' in c.name and c.text.name == script.name:
|
||||
skip = True
|
||||
break
|
||||
if not skip:
|
||||
bpy.ops.logic.controller_add(type='PYTHON', object=obj.name)
|
||||
ctrl = obj.game.controllers[-1]
|
||||
ctrl.text = bpy.data.texts['rig_ui.py']
|
||||
ctrl.text = bpy.data.texts[script.name]
|
||||
|
||||
|
||||
t.tick("The rest: ")
|
||||
|
|
29
rigify/ui.py
29
rigify/ui.py
|
@ -69,19 +69,33 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
|
|||
if show_warning:
|
||||
layout.label(text=WARNING, icon='ERROR')
|
||||
|
||||
layout.operator("pose.rigify_generate", text="Generate Rig")
|
||||
layout.prop(id_store, "rigify_advanced_generation")
|
||||
layout.operator("pose.rigify_generate", text="Generate Rig", icon='POSE_HLT')
|
||||
if id_store.rigify_advanced_generation:
|
||||
icon = 'UNLOCKED'
|
||||
else:
|
||||
icon = 'LOCKED'
|
||||
layout.prop(id_store, "rigify_advanced_generation", toggle=True, icon=icon)
|
||||
|
||||
if id_store.rigify_advanced_generation:
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(id_store, "rigify_generate_mode", expand=True)
|
||||
|
||||
main_row = layout.row(align=True).split(percentage=0.3)
|
||||
col1 = main_row.column()
|
||||
col2 = main_row.column()
|
||||
col1.label(text="Target Rig")
|
||||
col1.label(text="Target UI")
|
||||
col1.label(text="Rig Name")
|
||||
row = col1.row()
|
||||
row.label(text="Target Rig")
|
||||
row.enabled = (id_store.rigify_generate_mode == "overwrite")
|
||||
row = col1.row()
|
||||
row.label(text="Target UI")
|
||||
row.enabled = (id_store.rigify_generate_mode == "overwrite")
|
||||
|
||||
row = col2.row(align=True)
|
||||
row.prop(id_store, "rigify_rig_basename", text="", icon="SORTALPHA")
|
||||
|
||||
row = col2.row(align=True)
|
||||
for i in range(0, len(id_store.rigify_target_rigs)):
|
||||
id_store.rigify_target_rigs.remove(0)
|
||||
|
||||
|
@ -92,6 +106,7 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
|
|||
|
||||
row.prop_search(id_store, "rigify_target_rig", id_store, "rigify_target_rigs", text="",
|
||||
icon='OUTLINER_OB_ARMATURE')
|
||||
row.enabled = (id_store.rigify_generate_mode == "overwrite")
|
||||
|
||||
for i in range(0, len(id_store.rigify_rig_uis)):
|
||||
id_store.rigify_rig_uis.remove(0)
|
||||
|
@ -102,8 +117,12 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
|
|||
|
||||
row = col2.row()
|
||||
row.prop_search(id_store, "rigify_rig_ui", id_store, "rigify_rig_uis", text="", icon='TEXT')
|
||||
row.enabled = (id_store.rigify_generate_mode == "overwrite")
|
||||
|
||||
layout.prop(id_store, "rigify_force_widget_update")
|
||||
row = layout.row()
|
||||
row.prop(id_store, "rigify_force_widget_update")
|
||||
if id_store.rigify_generate_mode == 'new':
|
||||
row.enabled = False
|
||||
|
||||
if show_update_metarig:
|
||||
layout.label(text="Some bones have old legacy rigify_type. Click to upgrade", icon='ERROR')
|
||||
|
|
|
@ -412,8 +412,9 @@ def create_widget(rig, bone_name, bone_transform_name=None):
|
|||
if bone_transform_name is None:
|
||||
bone_transform_name = bone_name
|
||||
|
||||
obj_name = WGT_PREFIX + bone_name
|
||||
obj_name = WGT_PREFIX + rig.name + '_' + bone_name
|
||||
scene = bpy.context.scene
|
||||
id_store = bpy.context.window_manager
|
||||
|
||||
# Check if it already exists in the scene
|
||||
if obj_name in scene.objects:
|
||||
|
@ -437,8 +438,9 @@ def create_widget(rig, bone_name, bone_transform_name=None):
|
|||
|
||||
# Move object to bone position and set layers
|
||||
obj_to_bone(obj, rig, bone_transform_name)
|
||||
if 'WGTS' in bpy.data.objects.keys():
|
||||
obj.parent = bpy.data.objects['WGTS']
|
||||
wgts_group_name = 'WGTS_' + rig.name
|
||||
if wgts_group_name in bpy.data.objects.keys():
|
||||
obj.parent = bpy.data.objects[wgts_group_name]
|
||||
obj.layers = WGT_LAYERS
|
||||
|
||||
return obj
|
||||
|
|
Loading…
Reference in New Issue