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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/modules')
-rw-r--r--release/scripts/modules/add_object_utils.py83
-rw-r--r--release/scripts/modules/animsys_refactor.py201
-rwxr-xr-xrelease/scripts/modules/blend_render_info.py100
-rw-r--r--release/scripts/modules/bpy/__init__.py12
-rw-r--r--release/scripts/modules/bpy/path.py174
-rw-r--r--release/scripts/modules/bpy/utils.py217
-rw-r--r--release/scripts/modules/bpy_types.py298
-rw-r--r--release/scripts/modules/bpyml.py204
-rw-r--r--release/scripts/modules/bpyml_ui.py100
-rw-r--r--release/scripts/modules/console/complete_calltip.py2
-rw-r--r--release/scripts/modules/console/complete_import.py6
-rw-r--r--release/scripts/modules/graphviz_export.py35
-rw-r--r--release/scripts/modules/rigify/__init__.py60
-rw-r--r--release/scripts/modules/rigify/arm_biped.py72
-rw-r--r--release/scripts/modules/rigify/copy.py4
-rw-r--r--release/scripts/modules/rigify/delta.py8
-rw-r--r--release/scripts/modules/rigify/eye_balls.py161
-rw-r--r--release/scripts/modules/rigify/eye_lid.py119
-rw-r--r--release/scripts/modules/rigify/finger_curl.py162
-rw-r--r--release/scripts/modules/rigify/leg_biped.py80
-rw-r--r--release/scripts/modules/rigify/leg_quadruped.py62
-rw-r--r--release/scripts/modules/rigify/mouth.py94
-rw-r--r--release/scripts/modules/rigify/neck.py344
-rw-r--r--release/scripts/modules/rigify/neck_flex.py52
-rw-r--r--release/scripts/modules/rigify/palm_curl.py24
-rw-r--r--release/scripts/modules/rigify/shape_key_control.py4
-rw-r--r--release/scripts/modules/rigify/shape_key_distance.py4
-rw-r--r--release/scripts/modules/rigify/shape_key_rotdiff.py4
-rw-r--r--release/scripts/modules/rigify/spine_pivot_flex.py72
-rw-r--r--release/scripts/modules/rigify/stretch.py6
-rw-r--r--release/scripts/modules/rigify/stretch_twist.py12
-rw-r--r--release/scripts/modules/rigify/tail_control.py16
-rw-r--r--release/scripts/modules/rigify/tongue.py361
-rw-r--r--release/scripts/modules/rigify/track_dual.py6
-rw-r--r--release/scripts/modules/rigify/track_reverse.py4
-rw-r--r--release/scripts/modules/rigify_utils.py22
-rw-r--r--release/scripts/modules/rna_info.py212
-rw-r--r--release/scripts/modules/rna_prop_ui.py139
38 files changed, 2702 insertions, 834 deletions
diff --git a/release/scripts/modules/add_object_utils.py b/release/scripts/modules/add_object_utils.py
new file mode 100644
index 00000000000..eaa97512f89
--- /dev/null
+++ b/release/scripts/modules/add_object_utils.py
@@ -0,0 +1,83 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import bpy
+import mathutils
+
+
+def add_object_align_init(context, operator):
+
+ if operator and operator.properties.is_property_set("location") and operator.properties.is_property_set("rotation"):
+ location = mathutils.Matrix.Translation(mathutils.Vector(operator.properties.location))
+ rotation = mathutils.Euler(operator.properties.rotation).to_matrix().resize4x4()
+ else:
+ # TODO, local view cursor!
+ location = mathutils.Matrix.Translation(context.scene.cursor_location)
+
+ if context.user_preferences.edit.object_align == 'VIEW' and context.space_data.type == 'VIEW_3D':
+ rotation = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
+ else:
+ rotation = mathutils.Matrix()
+
+ # set the operator properties
+ if operator:
+ operator.properties.location = location.translation_part()
+ operator.properties.rotation = rotation.to_euler()
+
+ return location * rotation
+
+
+def add_object_data(context, obdata, operator=None):
+
+ scene = context.scene
+
+ # ugh, could be made nicer
+ for ob in scene.objects:
+ ob.select = False
+
+ obj_new = bpy.data.objects.new(obdata.name, obdata)
+
+ base = scene.objects.link(obj_new)
+ base.select = True
+
+ if context.space_data and context.space_data.type == 'VIEW_3D':
+ base.layers_from_view(context.space_data)
+
+
+ obj_new.matrix_world = add_object_align_init(context, operator)
+
+ obj_act = scene.objects.active
+
+ if obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type:
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ obj_act.select = True
+ scene.update() # apply location
+ #scene.objects.active = obj_new
+
+ bpy.ops.object.join() # join into the active.
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ else:
+ scene.objects.active = obj_new
+ if context.user_preferences.edit.use_enter_edit_mode:
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ return base
diff --git a/release/scripts/modules/animsys_refactor.py b/release/scripts/modules/animsys_refactor.py
new file mode 100644
index 00000000000..8cc91873b0e
--- /dev/null
+++ b/release/scripts/modules/animsys_refactor.py
@@ -0,0 +1,201 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+"""
+This module has utility functions for renaming
+rna values in fcurves and drivers.
+
+The main function to use is: update_data_paths(...)
+"""
+
+IS_TESTING = False
+
+class DataPathBuilder(object):
+ __slots__ = ("data_path", )
+ """ Dummy class used to parse fcurve and driver data paths.
+ """
+ def __init__(self, attrs):
+ self.data_path = attrs
+
+ def __getattr__(self, attr):
+ str_value = ".%s" % attr
+ return DataPathBuilder(self.data_path + (str_value, ))
+
+ def __getitem__(self, key):
+ str_value = '["%s"]' % key
+ return DataPathBuilder(self.data_path + (str_value, ))
+
+ def resolve(self, real_base, rna_update_from_map=None):
+ """ Return (attribute, value) pairs.
+ """
+ pairs = []
+ base = real_base
+ for item in self.data_path:
+ if base is not Ellipsis:
+ try:
+ # this only works when running with an old blender
+ # where the old path will resolve
+ base = eval("base" + item)
+ except:
+ base_new = Ellipsis
+ # guess the new name
+ if item.startswith("."):
+ for item_new in rna_update_from_map.get(item[1:], ()):
+ try:
+ print("base." + item_new)
+ base_new = eval("base." + item_new)
+ break # found, dont keep looking
+ except:
+ pass
+
+ if base_new is Ellipsis:
+ print("Failed to resolve data path:", self.data_path)
+ base = base_new
+
+ pairs.append((item, base))
+ return pairs
+
+import bpy
+
+
+def id_iter():
+ type_iter = type(bpy.data.objects)
+
+ for attr in dir(bpy.data):
+ data_iter = getattr(bpy.data, attr, None)
+ if type(data_iter) == type_iter:
+ for id_data in data_iter:
+ if id_data.library is None:
+ yield id_data
+
+
+def anim_data_actions(anim_data):
+ actions = []
+ actions.append(anim_data.action)
+ for track in anim_data.nla_tracks:
+ for strip in track.strips:
+ actions.append(strip.action)
+
+ # filter out None
+ return [act for act in actions if act]
+
+
+def classes_recursive(base_type, clss=None):
+ if clss is None:
+ clss = [base_type]
+ else:
+ clss.append(base_type)
+
+ for base_type_iter in base_type.__bases__:
+ if base_type_iter is not object:
+ classes_recursive(base_type_iter, clss)
+
+ return clss
+
+
+def find_path_new(id_data, data_path, rna_update_dict, rna_update_from_map):
+ # ignore ID props for now
+ if data_path.startswith("["):
+ return data_path
+
+ # recursive path fixing, likely will be one in most cases.
+ data_path_builder = eval("DataPathBuilder(tuple())." + data_path)
+ data_resolve = data_path_builder.resolve(id_data, rna_update_from_map)
+
+ path_new = [pair[0] for pair in data_resolve]
+
+ # print(data_resolve)
+ data_base = id_data
+
+ for i, (attr, data) in enumerate(data_resolve):
+ if data is Ellipsis:
+ break
+
+ if attr.startswith("."):
+ # try all classes
+ for data_base_type in classes_recursive(type(data_base)):
+ attr_new = rna_update_dict.get(data_base_type.__name__, {}).get(attr[1:])
+ if attr_new:
+ path_new[i] = "." + attr_new
+
+ # set this as the base for further properties
+ data_base = data
+
+ data_path_new = "".join(path_new)[1:] # skip the first "."
+ return data_path_new
+
+
+def update_data_paths(rna_update):
+ ''' rna_update triple [(class_name, from, to), ...]
+ '''
+
+ # make a faster lookup dict
+ rna_update_dict = {}
+ for ren_class, ren_from, ren_to in rna_update:
+ rna_update_dict.setdefault(ren_class, {})[ren_from] = ren_to
+
+ rna_update_from_map = {}
+ for ren_class, ren_from, ren_to in rna_update:
+ rna_update_from_map.setdefault(ren_from, []).append(ren_to)
+
+ for id_data in id_iter():
+ anim_data = getattr(id_data, "animation_data", None)
+ if anim_data is None:
+ continue
+
+ for fcurve in anim_data.drivers:
+ for var in fcurve.driver.variables:
+ if var.type == 'SINGLE_PROP':
+ for tar in var.targets:
+ id_data_other = tar.id
+ data_path = tar.data_path
+
+ if id_data_other and data_path:
+ data_path_new = find_path_new(id_data_other, data_path, rna_update_dict, rna_update_from_map)
+ # print(data_path_new)
+ if data_path_new != data_path:
+ if not IS_TESTING:
+ tar.data_path = data_path_new
+ print("driver (%s): %s -> %s" % (id_data_other.name, data_path, data_path_new))
+
+
+
+ for action in anim_data_actions(anim_data):
+ for fcu in action.fcurves:
+ data_path = fcu.data_path
+ data_path_new = find_path_new(id_data, data_path, rna_update_dict, rna_update_from_map)
+ # print(data_path_new)
+ if data_path_new != data_path:
+ if not IS_TESTING:
+ fcu.data_path = data_path_new
+ print("fcurve (%s): %s -> %s" % (id_data.name, data_path, data_path_new))
+
+
+if __name__ == "__main__":
+
+ # Example, should be called externally
+ # (class, from, to)
+ replace_ls = [
+ ('AnimVizMotionPaths', 'frame_after', 'frame_after'),
+ ('AnimVizMotionPaths', 'frame_before', 'frame_before'),
+ ('AnimVizOnionSkinning', 'frame_after', 'frame_after'),
+ ]
+
+ update_data_paths(replace_ls)
diff --git a/release/scripts/modules/blend_render_info.py b/release/scripts/modules/blend_render_info.py
new file mode 100755
index 00000000000..dcd1f9cbee3
--- /dev/null
+++ b/release/scripts/modules/blend_render_info.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python
+
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# This module can get render info without running from inside blender.
+#
+# This struct wont change according to Ton.
+# Note that the size differs on 32/64bit
+#
+# typedef struct BHead {
+# int code, len;
+# void *old;
+# int SDNAnr, nr;
+# } BHead;
+
+
+def read_blend_rend_chunk(path):
+
+ import struct
+
+ blendfile = open(path, 'rb')
+
+ head = blendfile.read(7)
+
+ if head[0:2] == b'\x1f\x8b': # gzip magic
+ import gzip
+ blendfile.close()
+ blendfile = gzip.open(path, 'rb')
+ head = blendfile.read(7)
+
+ if head != b'BLENDER':
+ print("not a blend file:", path)
+ blendfile.close()
+ return []
+
+ is_64_bit = (blendfile.read(1) == b'-')
+
+ # true for PPC, false for X86
+ is_big_endian = (blendfile.read(1) == b'V')
+
+ # Now read the bhead chunk!!!
+ blendfile.read(3) # skip the version
+
+ scenes = []
+
+ sizeof_bhead = 24 if is_64_bit else 20
+
+ while blendfile.read(4) == b'REND':
+ sizeof_bhead_left = sizeof_bhead - 4
+
+ struct.unpack('>i' if is_big_endian else '<i', blendfile.read(4))[0]
+ sizeof_bhead_left -= 4
+
+ # We dont care about the rest of the bhead struct
+ blendfile.read(sizeof_bhead_left)
+
+ # Now we want the scene name, start and end frame. this is 32bites long
+ start_frame, end_frame = struct.unpack('>2i' if is_big_endian else '<2i', blendfile.read(8))
+
+ scene_name = blendfile.read(24)
+
+ scene_name = scene_name[:scene_name.index(b'\0')]
+
+ try:
+ scene_name = str(scene_name, 'utf8')
+ except TypeError:
+ pass
+
+ scenes.append((start_frame, end_frame, scene_name))
+
+ return scenes
+
+
+def main():
+ import sys
+ for arg in sys.argv[1:]:
+ if arg.lower().endswith('.blend'):
+ for value in read_blend_rend_chunk(arg):
+ print("%d %d %s" % value)
+
+if __name__ == '__main__':
+ main()
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index f0025290f09..5b7d5a76336 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -26,7 +26,7 @@ data = _bpy.data
context = _bpy.context
# python modules
-from bpy import utils
+from bpy import utils, path
from bpy import ops as _ops_module
@@ -43,18 +43,12 @@ def _main():
## people need to explain how this is even a fix.
# _sys.path[:] = filter(None, _sys.path)
- # a bit nasty but this prevents help() and input() from locking blender
- # Ideally we could have some way for the console to replace sys.stdin but
- # python would lock blender while waiting for a return value, not easy :|
-
- if not app.debug:
- _sys.stdin = None
-
# because of how the console works. we need our own help() pager func.
# replace the bold function because it adds crazy chars
import pydoc
pydoc.getpager = lambda: pydoc.plainpager
- pydoc.TextDoc.bold = lambda self, text: text
+ pydoc.Helper.getline = lambda self, prompt: None
+ pydoc.TextDoc.use_bold = lambda self, text: text
# if "-d" in sys.argv: # Enable this to measure startup speed
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
new file mode 100644
index 00000000000..63149f2fce8
--- /dev/null
+++ b/release/scripts/modules/bpy/path.py
@@ -0,0 +1,174 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+"""
+This module has a similar scope to os.path, containing utility
+functions for dealing with paths in Blender.
+"""
+
+import bpy as _bpy
+import os as _os
+
+def abspath(path):
+ """
+ Returns the absolute path relative to the current blend file using the "//" prefix.
+ """
+ if path.startswith("//"):
+ return _os.path.join(_os.path.dirname(_bpy.data.filepath), path[2:])
+
+ return path
+
+
+def relpath(path, start=None):
+ """
+ Returns the path relative to the current blend file using the "//" prefix.
+
+ :arg start: Relative to this path, when not set the current filename is used.
+ :type start: string
+ """
+ if not path.startswith("//"):
+ if start is None:
+ start = _os.path.dirname(_bpy.data.filepath)
+ return "//" + _os.path.relpath(path, start)
+
+ return path
+
+
+def clean_name(name, replace="_"):
+ """
+ Returns a name with characters replaced that may cause problems under various circumstances, such as writing to a file.
+ All characters besides A-Z/a-z, 0-9 are replaced with "_"
+ or the replace argument if defined.
+ """
+
+ unclean_chars = \
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\
+ \x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\
+ \x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\
+ \x2e\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x40\x5b\x5c\x5d\x5e\x60\x7b\
+ \x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\
+ \x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\
+ \x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\
+ \xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\
+ \xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\
+ \xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\
+ \xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\
+ \xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\
+ \xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe"
+
+ for ch in unclean_chars:
+ name = name.replace(ch, replace)
+ return name
+
+
+def display_name(name):
+ """
+ Creates a display string from name to be used menus and the user interface.
+ Capitalize the first letter in all lowercase names, mixed case names are kept as is.
+ Intended for use with filenames and module names.
+ """
+
+ name_base = _os.path.splitext(name)[0]
+
+ # string replacements
+ name_base = name_base.replace("_colon_", ":")
+
+ name_base = name_base.replace("_", " ")
+
+ if name_base.islower():
+ return name_base.capitalize()
+ else:
+ return name_base
+
+
+def resolve_ncase(path):
+ """
+ Resolve a case insensitive path on a case sensitive system,
+ returning a string with the path if found else return the original path.
+ """
+
+ import os
+
+ def _ncase_path_found(path):
+ if path=='' or os.path.exists(path):
+ return path, True
+
+ filename = os.path.basename(path) # filename may be a directory or a file
+ dirpath = os.path.dirname(path)
+
+ suffix = ""
+ if not filename: # dir ends with a slash?
+ if len(dirpath) < len(path):
+ suffix = path[:len(path)-len(dirpath)]
+
+ filename = os.path.basename(dirpath)
+ dirpath = os.path.dirname(dirpath)
+
+ if not os.path.exists(dirpath):
+ dirpath, found = _ncase_path_found(dirpath)
+
+ if not found:
+ return path, False
+
+ # at this point, the directory exists but not the file
+
+ # we are expecting 'dirpath' to be a directory, but it could be a file
+ if os.path.isdir(dirpath):
+ files = os.listdir(dirpath)
+ else:
+ return path, False
+
+ filename_low = filename.lower()
+ f_iter_nocase = None
+
+ for f_iter in files:
+ if f_iter.lower() == filename_low:
+ f_iter_nocase = f_iter
+ break
+
+ if f_iter_nocase:
+ return os.path.join(dirpath, f_iter_nocase) + suffix, True
+ else:
+ # cant find the right one, just return the path as is.
+ return path, False
+
+ ncase_path, found = _ncase_path_found(path)
+ return ncase_path if found else path
+
+
+def ensure_ext(filepath, ext, case_sensitive=False):
+ """
+ Return the path with the extension added its its not alredy set.
+
+ :arg ext: The extension to check for.
+ :type ext: string
+ :arg case_sensitive: Check for matching case when comparing extensions.
+ :type case_sensitive: bool
+ """
+ import os
+ fn_base, fn_ext = os.path.splitext(filepath)
+ if fn_base and fn_ext:
+ if (case_sensitive and ext == fn_ext) or (ext.lower() == fn_ext.lower()):
+ return filepath
+ else:
+ return fn_base + ext
+
+ else:
+ return filepath + ext
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index 5b0599fe25f..7cfe476c2e7 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -19,7 +19,7 @@
# <pep8 compliant>
"""
-This module contains utility functions spesific to blender but
+This module contains utility functions specific to blender but
not assosiated with blenders internal data.
"""
@@ -27,8 +27,8 @@ import bpy as _bpy
import os as _os
import sys as _sys
-from _bpy import home_paths
-
+from _bpy import blend_paths
+from _bpy import script_paths as _bpy_script_paths
def _test_import(module_name, loaded_modules):
import traceback
@@ -59,7 +59,7 @@ def modules_from_path(path, loaded_modules):
:arg path: this path is scanned for scripts and packages.
:type path: string
- :arg loaded_modules: alredy loaded module names, files matching these names will be ignored.
+ :arg loaded_modules: already loaded module names, files matching these names will be ignored.
:type loaded_modules: set
:return: all loaded modules.
:rtype: list
@@ -83,9 +83,9 @@ def modules_from_path(path, loaded_modules):
modules.append(mod)
return modules
-
-_loaded = [] # store loaded modules for reloading.
-_bpy_types = __import__("bpy_types") # keep for comparisons, never ever reload this.
+
+_global_loaded_modules = [] # store loaded module names for reloading.
+import bpy_types as _bpy_types # keep for comparisons, never ever reload this.
def load_scripts(reload_scripts=False, refresh_scripts=False):
@@ -100,12 +100,39 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
import traceback
import time
+ # must be set back to True on exits
+ _bpy_types._register_immediate = False
+
t_main = time.time()
loaded_modules = set()
if refresh_scripts:
original_modules = _sys.modules.values()
+
+ if reload_scripts:
+ _bpy_types.TypeMap.clear()
+ _bpy_types.PropertiesMap.clear()
+
+ def register_module_call(mod):
+ _bpy_types._register_module(mod.__name__)
+ register = getattr(mod, "register", None)
+ if register:
+ try:
+ register()
+ except:
+ traceback.print_exc()
+ else:
+ print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__)
+
+ def unregister_module_call(mod):
+ _bpy_types._unregister_module(mod.__name__)
+ unregister = getattr(mod, "unregister", None)
+ if unregister:
+ try:
+ unregister()
+ except:
+ traceback.print_exc()
def sys_path_ensure(path):
if path not in _sys.path: # reloading would add twice
@@ -133,63 +160,45 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
mod = test_reload(mod)
if mod:
- register = getattr(mod, "register", None)
- if register:
- try:
- register()
- except:
- traceback.print_exc()
- else:
- print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__)
- _loaded.append(mod)
+ register_module_call(mod)
+ _global_loaded_modules.append(mod.__name__)
if reload_scripts:
- # reload modules that may not be directly included
- for type_class_name in dir(_bpy.types):
- type_class = getattr(_bpy.types, type_class_name)
- module_name = getattr(type_class, "__module__", "")
-
- if module_name and module_name != "bpy.types": # hard coded for C types
- loaded_modules.add(module_name)
- # sorting isnt needed but rather it be pradictable
- for module_name in sorted(loaded_modules):
- print("Reloading:", module_name)
- test_reload(_sys.modules[module_name])
+ # module names -> modules
+ _global_loaded_modules[:] = [_sys.modules[mod_name] for mod_name in _global_loaded_modules]
# loop over and unload all scripts
- _loaded.reverse()
- for mod in _loaded:
- unregister = getattr(mod, "unregister", None)
- if unregister:
- try:
- unregister()
- except:
- traceback.print_exc()
- _loaded[:] = []
-
- for base_path in script_paths(user=False):
- for path_subdir in ("ui", "op", "io", "cfg", "keyingsets"):
- path = _os.path.join(base_path, path_subdir)
- if _os.path.isdir(path):
- sys_path_ensure(path)
+ _global_loaded_modules.reverse()
+ for mod in _global_loaded_modules:
+ unregister_module_call(mod)
- for mod in modules_from_path(path, loaded_modules):
- test_register(mod)
+ for mod in _global_loaded_modules:
+ test_reload(mod)
+
+ _global_loaded_modules[:] = []
user_path = user_script_path()
- if user_path:
- for path_subdir in ("", "ui", "op", "io", "cfg", "keyingsets"):
- path = _os.path.join(user_path, path_subdir)
+
+ for base_path in script_paths():
+ for path_subdir in ("", "ui", "op", "io", "cfg", "keyingsets", "modules"):
+ path = _os.path.join(base_path, path_subdir)
if _os.path.isdir(path):
sys_path_ensure(path)
+ # only add this to sys.modules, dont run
+ if path_subdir == "modules":
+ continue
+
+ if user_path != base_path and path_subdir == "":
+ continue # avoid loading 2.4x scripts
+
for mod in modules_from_path(path, loaded_modules):
test_register(mod)
# load addons
used_ext = {ext.module for ext in _bpy.context.user_preferences.addons}
- paths = script_paths("addons")
+ paths = script_paths("addons") + script_paths("addons_contrib")
for path in paths:
sys_path_ensure(path)
@@ -202,61 +211,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
print("gc.collect() -> %d" % gc.collect())
if _bpy.app.debug:
- print("Time %.4f" % (time.time() - t_main))
-
-
-def expandpath(path):
- if path.startswith("//"):
- return _os.path.join(_os.path.dirname(_bpy.data.filename), path[2:])
-
- return path
-
+ print("Python Script Load Time %.4f" % (time.time() - t_main))
+
+ _bpy_types._register_immediate = True
-_unclean_chars = [0, 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, 46, 47, 58, 59, 60, 61, 62, 63, \
- 64, 91, 92, 93, 94, 96, 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, 171, 172, 173, 174, \
- 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, \
- 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, \
- 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, \
- 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, \
- 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, \
- 245, 246, 247, 248, 249, 250, 251, 252, 253, 254]
-_unclean_chars = ''.join([chr(i) for i in _unclean_chars])
-
-
-def clean_name(name, replace="_"):
- """
- Returns a name with characters replaced that may cause problems under various circumstances, such as writing to a file.
- All characters besides A-Z/a-z, 0-9 are replaced with "_"
- or the replace argument if defined.
- """
- for ch in _unclean_chars:
- name = name.replace(ch, replace)
- return name
-
-
-def display_name(name):
- """
- Creates a display string from name to be used menus and the user interface.
- Capitalize the first letter in all lowercase names, mixed case names are kept as is.
- Intended for use with filenames and module names.
- """
- name_base = _os.path.splitext(name)[0]
-
- # string replacements
- name_base = name_base.replace("_colon_", ":")
-
- name_base = name_base.replace("_", " ")
-
- if name_base.islower():
- return name_base.capitalize()
- else:
- return name_base
# base scripts
@@ -265,7 +224,7 @@ _scripts = (_os.path.normpath(_scripts), )
def user_script_path():
- path = _bpy.context.user_preferences.filepaths.python_scripts_directory
+ path = _bpy.context.user_preferences.filepaths.script_directory
if path:
path = _os.path.normpath(path)
@@ -284,11 +243,11 @@ def script_paths(subdir=None, user=True):
# add user scripts dir
if user:
- user_script_path = _bpy.context.user_preferences.filepaths.python_scripts_directory
+ user_script_path = _bpy.context.user_preferences.filepaths.script_directory
else:
user_script_path = None
- for path in home_paths("scripts") + (user_script_path, ):
+ for path in _bpy_script_paths() + (user_script_path, ):
if path:
path = _os.path.normpath(path)
if path not in scripts and _os.path.isdir(path):
@@ -311,7 +270,55 @@ _presets = _os.path.join(_scripts[0], "presets") # FIXME - multiple paths
def preset_paths(subdir):
'''
- Returns a list of paths for a spesific preset.
+ Returns a list of paths for a specific preset.
'''
return (_os.path.join(_presets, subdir), )
+
+
+def smpte_from_seconds(time, fps=None):
+ '''
+ Returns an SMPTE formatted string from the time in seconds: "HH:MM:SS:FF".
+
+ If the fps is not given the current scene is used.
+ '''
+ import math
+
+ if fps is None:
+ fps = _bpy.context.scene.render.fps
+
+ hours = minutes = seconds = frames = 0
+
+ if time < 0:
+ time = - time
+ neg = "-"
+ else:
+ neg = ""
+
+ if time >= 3600.0: # hours
+ hours = int(time / 3600.0)
+ time = time % 3600.0
+ if time >= 60.0: # mins
+ minutes = int(time / 60.0)
+ time = time % 60.0
+
+ seconds = int(time)
+ frames = int(round(math.floor(((time - seconds) * fps))))
+
+ return "%s%02d:%02d:%02d:%02d" % (neg, hours, minutes, seconds, frames)
+
+
+def smpte_from_frame(frame, fps=None, fps_base=None):
+ '''
+ Returns an SMPTE formatted string from the frame: "HH:MM:SS:FF".
+
+ If the fps and fps_base are not given the current scene is used.
+ '''
+
+ if fps is None:
+ fps = _bpy.context.scene.render.fps
+
+ if fps_base is None:
+ fps_base = _bpy.context.scene.render.fps_base
+
+ return smpte_from_seconds((frame * fps_base) / fps, fps)
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 16fac74b9d0..84d05a7a48d 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -19,7 +19,8 @@
# <pep8 compliant>
from _bpy import types as bpy_types
-from Mathutils import Vector
+import _bpy
+from mathutils import Vector
StructRNA = bpy_types.Struct.__bases__[0]
# StructRNA = bpy_types.Struct
@@ -29,15 +30,62 @@ class Context(StructRNA):
__slots__ = ()
def copy(self):
+ from types import BuiltinMethodType
new_context = {}
- generic_keys = StructRNA.__dict__.keys()
- for item in dir(self):
- if item not in generic_keys:
- new_context[item] = getattr(self, item)
+ generic_attrs = list(StructRNA.__dict__.keys()) + ["bl_rna", "rna_type", "copy"]
+ for attr in dir(self):
+ if not (attr.startswith("_") or attr in generic_attrs):
+ value = getattr(self, attr)
+ if type(value) != BuiltinMethodType:
+ new_context[attr] = value
return new_context
+class Library(bpy_types.ID):
+ __slots__ = ()
+
+ @property
+ def users_id(self):
+ """ID datablocks which use this library"""
+ import bpy
+
+ # See: readblenentry.c, IDTYPE_FLAGS_ISLINKABLE, we could make this an attribute in rna.
+ attr_links = "actions", "armatures", "brushes", "cameras", \
+ "curves", "grease_pencil", "groups", "images", \
+ "lamps", "lattices", "materials", "metaballs", \
+ "meshes", "node_groups", "objects", "scenes", \
+ "sounds", "textures", "texts", "fonts", "worlds"
+
+ return tuple(id_block for attr in attr_links for id_block in getattr(bpy.data, attr) if id_block.library == self)
+
+
+class Texture(bpy_types.ID):
+ __slots__ = ()
+
+ @property
+ def users_material(self):
+ """Materials that use this texture"""
+ import bpy
+ return tuple(mat for mat in bpy.data.materials if self in [slot.texture for slot in mat.texture_slots if slot])
+
+ @property
+ def users_object_modifier(self):
+ """Object modifiers that use this texture"""
+ import bpy
+ return tuple(obj for obj in bpy.data.objects if self in [mod.texture for mod in obj.modifiers if mod.type == 'DISPLACE'])
+
+
+class Group(bpy_types.ID):
+ __slots__ = ()
+
+ @property
+ def users_dupli_group(self):
+ """The dupli group this group is used in"""
+ import bpy
+ return tuple(obj for obj in bpy.data.objects if self == obj.dupli_group)
+
+
class Object(bpy_types.ID):
__slots__ = ()
@@ -45,21 +93,19 @@ class Object(bpy_types.ID):
def children(self):
"""All the children of this object"""
import bpy
- return [child for child in bpy.data.objects if child.parent == self]
+ return tuple(child for child in bpy.data.objects if child.parent == self)
@property
- def group_users(self):
+ def users_group(self):
"""The groups this object is in"""
import bpy
- name = self.name
- return [group for group in bpy.data.groups if name in group.objects]
+ return tuple(group for group in bpy.data.groups if self in group.objects[:])
@property
- def scene_users(self):
+ def users_scene(self):
"""The scenes this object is in"""
import bpy
- name = self.name
- return [scene for scene in bpy.data.scenes if name in scene.objects]
+ return tuple(scene for scene in bpy.data.scenes if self in scene.objects[:])
class _GenericBone:
@@ -95,19 +141,19 @@ class _GenericBone:
def x_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
- return self.matrix.rotation_part() * Vector(1.0, 0.0, 0.0)
+ return self.matrix.rotation_part() * Vector((1.0, 0.0, 0.0))
@property
def y_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
- return self.matrix.rotation_part() * Vector(0.0, 1.0, 0.0)
+ return self.matrix.rotation_part() * Vector((0.0, 1.0, 0.0))
@property
def z_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
- return self.matrix.rotation_part() * Vector(0.0, 0.0, 1.0)
+ return self.matrix.rotation_part() * Vector((0.0, 0.0, 1.0))
@property
def basename(self):
@@ -236,8 +282,8 @@ class EditBone(StructRNA, _GenericBone):
Transform the the bones head, tail, roll and envalope (when the matrix has a scale component).
Expects a 4x4 or 3x3 matrix.
"""
- from Mathutils import Vector
- z_vec = self.matrix.rotation_part() * Vector(0.0, 0.0, 1.0)
+ from mathutils import Vector
+ z_vec = self.matrix.rotation_part() * Vector((0.0, 0.0, 1.0))
self.tail = matrix * self.tail
self.head = matrix * self.head
scalar = matrix.median_scale
@@ -260,25 +306,30 @@ class Mesh(bpy_types.ID):
Make a mesh from a list of verts/edges/faces
Until we have a nicer way to make geometry, use this.
"""
- self.add_geometry(len(verts), len(edges), len(faces))
+ self.vertices.add(len(verts))
+ self.edges.add(len(edges))
+ self.faces.add(len(faces))
verts_flat = [f for v in verts for f in v]
- self.verts.foreach_set("co", verts_flat)
+ self.vertices.foreach_set("co", verts_flat)
del verts_flat
edges_flat = [i for e in edges for i in e]
- self.edges.foreach_set("verts", edges_flat)
+ self.edges.foreach_set("vertices", edges_flat)
del edges_flat
def treat_face(f):
if len(f) == 3:
- return f[0], f[1], f[2], 0
- elif f[3] == 0:
+ if f[2] == 0:
+ return f[2], f[0], f[1], 0
+ else:
+ return f[0], f[1], f[2], 0
+ elif f[2] == 0 or f[3] == 0:
return f[3], f[0], f[1], f[2]
return f
faces_flat = [v for f in faces for v in treat_face(f)]
- self.faces.foreach_set("verts_raw", faces_flat)
+ self.faces.foreach_set("vertices_raw", faces_flat)
del faces_flat
@property
@@ -303,7 +354,7 @@ class Mesh(bpy_types.ID):
edge_face_count_dict = self.edge_face_count_dict
return [edge_face_count_dict.get(ed.key, 0) for ed in self.edges]
- def edge_loops(self, faces=None, seams=()):
+ def edge_loops_from_faces(self, faces=None, seams=()):
"""
Edge loops defined by faces
@@ -314,7 +365,7 @@ class Mesh(bpy_types.ID):
return a list of edge key lists
[ [(0,1), (4, 8), (3,8)], ...]
- optionaly, seams are edge keys that will be removed
+ return a list of edge vertex index lists
"""
OTHER_INDEX = 2, 3, 0, 1 # opposite face index
@@ -326,7 +377,7 @@ class Mesh(bpy_types.ID):
for f in faces:
# if len(f) == 4:
- if f.verts_raw[3] != 0:
+ if f.vertices_raw[3] != 0:
edge_keys = f.edge_keys
for i, edkey in enumerate(f.edge_keys):
edges.setdefault(edkey, []).append(edge_keys[OTHER_INDEX[i]])
@@ -379,13 +430,77 @@ class Mesh(bpy_types.ID):
return edge_loops
+ def edge_loops_from_edges(self, edges=None):
+ """
+ Edge loops defined by edges
+
+ Takes me.edges or a list of edges and returns the edge loops
+
+ return a list of vertex indices.
+ [ [1, 6, 7, 2], ...]
+
+ closed loops have matching start and end values.
+ """
+ line_polys = []
+
+ # Get edges not used by a face
+ if edges is None:
+ edges = self.edges
+
+ if not hasattr(edges, "pop"):
+ edges = edges[:]
+
+ edge_dict = {ed.key: ed for ed in self.edges if ed.select}
+
+ while edges:
+ current_edge = edges.pop()
+ vert_end, vert_start = current_edge.vertices[:]
+ line_poly = [vert_start, vert_end]
+
+ ok = True
+ while ok:
+ ok = False
+ #for i, ed in enumerate(edges):
+ i = len(edges)
+ while i:
+ i -= 1
+ ed = edges[i]
+ v1, v2 = ed.vertices
+ if v1 == vert_end:
+ line_poly.append(v2)
+ vert_end = line_poly[-1]
+ ok = 1
+ del edges[i]
+ # break
+ elif v2 == vert_end:
+ line_poly.append(v1)
+ vert_end = line_poly[-1]
+ ok = 1
+ del edges[i]
+ #break
+ elif v1 == vert_start:
+ line_poly.insert(0, v2)
+ vert_start = line_poly[0]
+ ok = 1
+ del edges[i]
+ # break
+ elif v2 == vert_start:
+ line_poly.insert(0, v1)
+ vert_start = line_poly[0]
+ ok = 1
+ del edges[i]
+ #break
+ line_polys.append(line_poly)
+
+ return line_polys
+
class MeshEdge(StructRNA):
__slots__ = ()
@property
def key(self):
- return ord_ind(*tuple(self.verts))
+ return ord_ind(*tuple(self.vertices))
class MeshFace(StructRNA):
@@ -394,8 +509,8 @@ class MeshFace(StructRNA):
@property
def center(self):
"""The midpoint of the face."""
- face_verts = self.verts[:]
- mesh_verts = self.id_data.verts
+ face_verts = self.vertices[:]
+ mesh_verts = self.id_data.vertices
if len(face_verts) == 3:
return (mesh_verts[face_verts[0]].co + mesh_verts[face_verts[1]].co + mesh_verts[face_verts[2]].co) / 3.0
else:
@@ -403,17 +518,110 @@ class MeshFace(StructRNA):
@property
def edge_keys(self):
- verts = self.verts[:]
+ verts = self.vertices[:]
if len(verts) == 3:
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[0])
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[3]), ord_ind(verts[3], verts[0])
+class Text(bpy_types.ID):
+ __slots__ = ()
+
+ def as_string(self):
+ """Return the text as a string."""
+ return "\n".join(line.body for line in self.lines)
+
+ def from_string(self, string):
+ """Replace text with this string."""
+ self.clear()
+ self.write(string)
+
+ @property
+ def users_logic(self):
+ """Logic bricks that use this text"""
+ import bpy
+ return tuple(obj for obj in bpy.data.objects if self in [cont.text for cont in obj.game.controllers if cont.type == 'PYTHON'])
+
import collections
+TypeMap = {}
+# Properties (IDPropertyGroup) are different from types because they need to be registered
+# before adding sub properties to them, so they are registered on definition
+# and unregistered on unload
+PropertiesMap = {}
+
+# Using our own loading function we set this to false
+# so when running a script directly in the text editor
+# registers moduals instantly.
+_register_immediate = True
+
+def _unregister_module(module, free=True):
+ for t in TypeMap.get(module, ()):
+ try:
+ bpy_types.unregister(t)
+ except:
+ import traceback
+ print("bpy.utils._unregister_module(): Module '%s' failed to unregister class '%s.%s'" % (module, t.__module__, t.__name__))
+ traceback.print_exc()
+
+ if free == True and module in TypeMap:
+ del TypeMap[module]
+
-class OrderedMeta(type):
+ for t in PropertiesMap.get(module, ()):
+ try:
+ bpy_types.unregister(t)
+ except:
+ import traceback
+ print("bpy.utils._unload_module(): Module '%s' failed to unregister class '%s.%s'" % (module, t.__module__, t.__name__))
+ traceback.print_exc()
+
+ if free == True and module in PropertiesMap:
+ del PropertiesMap[module]
+
+
+def _register_module(module):
+ for t in TypeMap.get(module, ()):
+ try:
+ bpy_types.register(t)
+ except:
+ import traceback
+ print("bpy.utils._register_module(): Module '%s' failed to register class '%s.%s'" % (module, t.__module__, t.__name__))
+ traceback.print_exc()
+
+
+class RNAMeta(type):
+ @classmethod
+ def _register_immediate(cls):
+ return _register_immediate
+
+ def __new__(cls, name, bases, classdict, **args):
+ result = type.__new__(cls, name, bases, classdict)
+ if bases and bases[0] != StructRNA:
+ module = result.__module__
+
+ ClassMap = TypeMap
+
+ # Register right away if needed
+ if cls._register_immediate():
+ bpy_types.register(result)
+ ClassMap = PropertiesMap
+
+ # first part of packages only
+ if "." in module:
+ module = module[:module.index(".")]
+
+ ClassMap.setdefault(module, []).append(result)
+
+ return result
+
+class RNAMetaRegister(RNAMeta):
+ @classmethod
+ def _register_immediate(cls):
+ return True
+
+class OrderedMeta(RNAMeta):
def __init__(cls, name, bases, attributes):
super(OrderedMeta, cls).__init__(name, bases, attributes)
@@ -422,7 +630,6 @@ class OrderedMeta(type):
def __prepare__(name, bases, **kwargs):
return collections.OrderedDict()
-
# Only defined so operators members can be used by accessing self.order
class Operator(StructRNA, metaclass=OrderedMeta):
__slots__ = ()
@@ -437,7 +644,12 @@ class Macro(StructRNA, metaclass=OrderedMeta):
def define(self, opname):
from _bpy import ops
return ops.macro_define(self, opname)
+
+class IDPropertyGroup(StructRNA, metaclass=RNAMetaRegister):
+ __slots__ = ()
+class RenderEngine(StructRNA, metaclass=RNAMeta):
+ __slots__ = ()
class _GenericUI:
__slots__ = ()
@@ -479,20 +691,20 @@ class _GenericUI:
pass
-class Panel(StructRNA, _GenericUI):
+class Panel(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
-class Header(StructRNA, _GenericUI):
+class Header(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
-class Menu(StructRNA, _GenericUI):
+class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
def path_menu(self, searchpaths, operator, props_default={}):
layout = self.layout
- # hard coded to set the operators 'path' to the filename.
+ # hard coded to set the operators 'filepath' to the filename.
import os
import bpy.utils
@@ -501,22 +713,26 @@ class Menu(StructRNA, _GenericUI):
# collect paths
files = []
- for path in searchpaths:
- files.extend([(f, os.path.join(path, f)) for f in os.listdir(path)])
+ for directory in searchpaths:
+ files.extend([(f, os.path.join(directory, f)) for f in os.listdir(directory)])
files.sort()
- for f, path in files:
+ for f, filepath in files:
if f.startswith("."):
continue
- props = layout.operator(operator, text=bpy.utils.display_name(f))
+ preset_name = bpy.path.display_name(f)
+ props = layout.operator(operator, text=preset_name)
for attr, value in props_default.items():
setattr(props, attr, value)
- props.path = path
+ props.filepath = filepath
+ if operator == "script.execute_preset":
+ props.menu_idname = self.bl_idname
+ props.preset_name = preset_name
def draw_preset(self, context):
"""Define these on the subclass
diff --git a/release/scripts/modules/bpyml.py b/release/scripts/modules/bpyml.py
new file mode 100644
index 00000000000..a2ba9ec8006
--- /dev/null
+++ b/release/scripts/modules/bpyml.py
@@ -0,0 +1,204 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+"""
+This module translates a python like XML representation into XML
+or simple python blender/ui function calls.
+
+ sometag(arg=10) [
+ another()
+ another(key="value")
+ ]
+
+# converts into ...
+
+ <sometag arg="10">
+ <another/>
+ <another key="value" />
+ </sometag>
+
+"""
+
+TAG, ARGS, CHILDREN = range(3)
+class ReturnStore(tuple):
+ def __getitem__(self, key):
+
+ # single item get's
+ if type(key) is ReturnStore:
+ key = (key, )
+
+ if type(key) is tuple:
+ children = self[CHILDREN]
+ if children:
+ raise Exception("Only a single __getitem__ is allowed on the ReturnStore")
+ else:
+ children[:] = key
+ return self
+ else:
+ return tuple.__getitem__(self, key)
+
+
+class FunctionStore(object):
+ def __call__(self, **kwargs):
+ return ReturnStore((self.__class__.__name__, kwargs, []))
+
+
+def tag_vars(tags, module=__name__):
+ return {tag: type(tag, (FunctionStore, ), {"__module__": module})() for tag in tags}
+
+
+def tag_module(mod_name, tags):
+ import sys
+ from types import ModuleType
+ mod = ModuleType(mod_name)
+ sys.modules[mod_name] = mod
+ dict_values = tag_vars(tags, mod_name)
+ mod.__dict__.update(dict_values)
+ return mod
+
+
+def toxml(py_data, indent=" "):
+
+ if len(py_data) != 1 or type(py_data) != list:
+ raise Exception("Expected a list with one member")
+
+ def _to_xml(py_item, xml_node=None):
+ if xml_node is None:
+ xml_node = newdoc.createElement(py_item[TAG])
+
+ for key, value in py_item[ARGS].items():
+ xml_node.setAttribute(key, str(value))
+
+ for py_item_child in py_item[CHILDREN]:
+ xml_node.appendChild(_to_xml(py_item_child))
+
+ return xml_node
+
+ def _to_xml_iter(xml_parent, data_ls):
+ for py_item in data_ls:
+ xml_node = newdoc.createElement(py_item[TAG])
+
+
+ # ok if its empty
+ _to_xml_iter(xml_node, py_item[CHILDREN])
+
+ import xml.dom.minidom
+ impl = xml.dom.minidom.getDOMImplementation()
+ newdoc = impl.createDocument(None, py_data[0][TAG], None)
+
+ _to_xml(py_data[0], newdoc.documentElement)
+
+ return newdoc.documentElement.toprettyxml(indent=" ")
+
+
+def fromxml(data):
+ def _fromxml_kwargs(xml_node):
+ kwargs = {}
+ for key, value in xml_node.attributes.items():
+ kwargs[key] = value
+ return kwargs
+
+
+ def _fromxml(xml_node):
+ py_item = (xml_node.tagName, _fromxml_kwargs(xml_node), [])
+ #_fromxml_iter(py_item, xml_node.childNodes)
+ for xml_node_child in xml_node.childNodes:
+ if xml_node_child.nodeType not in (xml_node_child.TEXT_NODE, xml_node_child.COMMENT_NODE):
+ py_item[CHILDREN].append(_fromxml(xml_node_child))
+ return py_item
+
+ import xml.dom.minidom
+ xml_doc = xml.dom.minidom.parseString(data)
+ return [_fromxml(xml_doc.documentElement)]
+
+
+def topretty_py(py_data, indent=" "):
+
+ if len(py_data) != 1:
+ raise Exception("Expected a list with one member")
+
+ lines = []
+
+ def _to_kwargs(kwargs):
+ return ", ".join([("%s=%s" % (key, repr(value))) for key, value in sorted(kwargs.items())])
+
+ def _topretty(py_item, indent_ctx, last):
+ if py_item[CHILDREN]:
+ lines.append("%s%s(%s) [" % (indent_ctx, py_item[TAG], _to_kwargs(py_item[ARGS])))
+ py_item_last = py_item[CHILDREN][-1]
+ for py_item_child in py_item[CHILDREN]:
+ _topretty(py_item_child, indent_ctx + indent, (py_item_child is py_item_last))
+ lines.append("%s]%s" % (indent_ctx, ("" if last else ",")))
+ else:
+ lines.append("%s%s(%s)%s" % (indent_ctx, py_item[TAG], _to_kwargs(py_item[ARGS]), ("" if last else ",")))
+
+ _topretty(py_data[0], "", True)
+
+ return "\n".join(lines)
+
+if __name__ == "__main__":
+ # testing code.
+
+ tag_module("bpyml_test", ("ui", "prop", "row", "column", "active", "separator", "split"))
+ from bpyml_test import *
+
+ draw = [
+ ui() [
+ split() [
+ column() [
+ prop(data='context.scene.render', property='use_stamp_time', text='Time'),
+ prop(data='context.scene.render', property='use_stamp_date', text='Date'),
+ prop(data='context.scene.render', property='use_stamp_render_time', text='RenderTime'),
+ prop(data='context.scene.render', property='use_stamp_frame', text='Frame'),
+ prop(data='context.scene.render', property='use_stamp_scene', text='Scene'),
+ prop(data='context.scene.render', property='use_stamp_camera', text='Camera'),
+ prop(data='context.scene.render', property='use_stamp_filename', text='Filename'),
+ prop(data='context.scene.render', property='use_stamp_marker', text='Marker'),
+ prop(data='context.scene.render', property='use_stamp_sequencer_strip', text='Seq. Strip')
+ ],
+ column() [
+ active(expr='context.scene.render.use_stamp'),
+ prop(data='context.scene.render', property='stamp_foreground', slider=True),
+ prop(data='context.scene.render', property='stamp_background', slider=True),
+ separator(),
+ prop(data='context.scene.render', property='stamp_font_size', text='Font Size')
+ ]
+ ],
+ split(percentage=0.2) [
+ prop(data='context.scene.render', property='use_stamp_note', text='Note'),
+ row() [
+ active(expr='context.scene.render.use_stamp_note'),
+ prop(data='context.scene.render', property='stamp_note_text', text='')
+ ]
+ ]
+ ]
+ ]
+
+ xml_data = toxml(draw)
+ print(xml_data) # xml version
+
+ py_data = fromxml(xml_data)
+ print(py_data) # converted back to py
+
+ xml_data = toxml(py_data)
+ print(xml_data) # again back to xml
+
+ py_data = fromxml(xml_data) # pretty python version
+ print(topretty_py(py_data))
diff --git a/release/scripts/modules/bpyml_ui.py b/release/scripts/modules/bpyml_ui.py
new file mode 100644
index 00000000000..ad68d1b0d7e
--- /dev/null
+++ b/release/scripts/modules/bpyml_ui.py
@@ -0,0 +1,100 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+
+import bpy as _bpy
+import bpyml
+from bpyml import TAG, ARGS, CHILDREN
+from types import ModuleType
+
+_uilayout_rna = _bpy.types.UILayout.bl_rna
+
+_uilayout_tags = ["ui"] + \
+ _uilayout_rna.properties.keys() + \
+ _uilayout_rna.functions.keys()
+
+# these need to be imported directly
+# >>> from bpyml_ui.locals import *
+locals = bpyml.tag_module("%s.locals" % __name__ , _uilayout_tags)
+
+
+def _parse_rna(prop, value):
+ if prop.type == 'FLOAT':
+ value = float(value)
+ elif prop.type == 'INT':
+ value = int(value)
+ elif prop.type == 'BOOLEAN':
+ if value in (True, False):
+ pass
+ else:
+ if value not in ("True", "False"):
+ raise Exception("invalid bool value: %s" % value)
+ value = bool(value == "True")
+ elif prop.type in ('STRING', 'ENUM'):
+ pass
+ elif prop.type == 'POINTER':
+ value = eval("_bpy." + value)
+ else:
+ raise Exception("type not supported %s.%s" % (prop.identifier, prop.type))
+ return value
+
+
+def _parse_rna_args(base, py_node):
+ rna_params = base.bl_rna.functions[py_node[TAG]].parameters
+ args = {}
+ for key, value in py_node[ARGS].items():
+ args[key] = _parse_rna(rna_params[key], value)
+ return args
+
+
+def _call_recursive(context, base, py_node):
+ prop = base.bl_rna.properties.get(py_node[TAG])
+ if py_node[TAG] in base.bl_rna.properties:
+ value = py_node[ARGS].get("expr")
+ if value:
+ value = eval(value, {"context": _bpy.context})
+ setattr(base, py_node[TAG], value)
+ else:
+ value = py_node[ARGS]['value'] # have to have this
+ setattr(base, name, value)
+ else:
+ args = _parse_rna_args(base, py_node)
+ func_new = getattr(base, py_node[TAG])
+ base_new = func_new(**args) # call blender func
+ if base_new is not None:
+ for py_node_child in py_node[CHILDREN]:
+ _call_recursive(context, base_new, py_node_child)
+
+
+class BPyML_BaseUI():
+ '''
+ This is a mix-in class that defines a draw function
+ which checks for draw_data
+ '''
+
+ def draw(self, context):
+ layout = self.layout
+ for py_node in self.draw_data[CHILDREN]:
+ _call_recursive(context, layout, py_node)
+
+ def draw_header(self, context):
+ layout = self.layout
+ for py_node in self.draw_header_data[CHILDREN]:
+ _call_recursive(context, layout, py_node)
diff --git a/release/scripts/modules/console/complete_calltip.py b/release/scripts/modules/console/complete_calltip.py
index c4687b4f10b..87fac9f4c07 100644
--- a/release/scripts/modules/console/complete_calltip.py
+++ b/release/scripts/modules/console/complete_calltip.py
@@ -124,7 +124,7 @@ def get_argspec(func, strip_self=True, doc=None, source=None):
if source is None:
try:
source = inspect.getsource(func)
- except TypeError:
+ except (TypeError, IOError):
source = ''
if source:
match = re.search(DEF_SOURCE % func_name, source, RE_FLAG)
diff --git a/release/scripts/modules/console/complete_import.py b/release/scripts/modules/console/complete_import.py
index 875c557f497..4b50cf6deb8 100644
--- a/release/scripts/modules/console/complete_import.py
+++ b/release/scripts/modules/console/complete_import.py
@@ -32,6 +32,7 @@ changes have been made:
- limit list of modules to prefix in case of "from w"
- sorted modules
- added sphinx documentation
+- complete() returns a blank list of the module isnt found
"""
@@ -183,3 +184,8 @@ def complete(line):
if len(words) >= 3 and words[0] == 'from':
mod = words[1]
return filter_prefix(try_import(mod), words[-1])
+
+ # get here if the import is not found
+ # import invalidmodule
+ # ^, in this case return nothing
+ return []
diff --git a/release/scripts/modules/graphviz_export.py b/release/scripts/modules/graphviz_export.py
index 1e7c7adfb7f..2389e1f9020 100644
--- a/release/scripts/modules/graphviz_export.py
+++ b/release/scripts/modules/graphviz_export.py
@@ -51,13 +51,13 @@ def compat_str(text, line_length=0):
return text
-def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True, XTRA_INFO=True):
+def graph_armature(obj, filepath, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True, XTRA_INFO=True):
CONSTRAINTS = DRIVERS = True
- fileobject = open(path, "w")
+ fileobject = open(filepath, "w")
fw = fileobject.write
fw(header)
- fw('label = "%s::%s" ;' % (bpy.data.filename.split("/")[-1].split("\\")[-1], obj.name))
+ fw('label = "%s::%s" ;' % (bpy.data.filepath.split("/")[-1].split("\\")[-1], obj.name))
arm = obj.data
@@ -66,7 +66,7 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
print("")
for bone in bones:
b = arm.bones[bone]
- print(">>", bone, ["*>", "->"][b.connected], getattr(getattr(b, "parent", ""), "name", ""))
+ print(">>", bone, ["*>", "->"][b.use_connect], getattr(getattr(b, "parent", ""), "name", ""))
label = [bone]
bone = arm.bones[bone]
@@ -103,7 +103,7 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
parent = bone.parent
if parent:
parent_name = parent.name
- connected = bone.connected
+ connected = bone.use_connect
elif FAKE_PARENT:
parent_name = 'Object::%s' % obj.name
connected = False
@@ -157,17 +157,18 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
pbone = rna_path_as_pbone(rna_path)
if pbone:
- for target in fcurve_driver.driver.targets:
- pbone_target = rna_path_as_pbone(target.data_path)
- rna_path_target = target.data_path
- if pbone_target:
- opts = ['dir=forward', "weight=1", "arrowhead=normal", "arrowtail=none", "constraint=false", 'color="blue"', "labelfontsize=4"] # ,
- display_source = rna_path.replace("pose.bones", "")
- display_target = rna_path_target.replace("pose.bones", "")
- if XTRA_INFO:
- label = "%s\\n%s" % (display_source, display_target)
- opts.append('label="%s"' % compat_str(label))
- fw('"%s" -> "%s" [%s] ;\n' % (pbone_target.name, pbone.name, ','.join(opts)))
+ for var in fcurve_driver.driver.variables:
+ for target in var.targets:
+ pbone_target = rna_path_as_pbone(target.data_path)
+ rna_path_target = target.data_path
+ if pbone_target:
+ opts = ['dir=forward', "weight=1", "arrowhead=normal", "arrowtail=none", "constraint=false", 'color="blue"', "labelfontsize=4"] # ,
+ display_source = rna_path.replace("pose.bones", "")
+ display_target = rna_path_target.replace("pose.bones", "")
+ if XTRA_INFO:
+ label = "%s\\n%s" % (display_source, display_target)
+ opts.append('label="%s"' % compat_str(label))
+ fw('"%s" -> "%s" [%s] ;\n' % (pbone_target.name, pbone.name, ','.join(opts)))
fw(footer)
fileobject.close()
@@ -177,7 +178,7 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
import sys
sys.stdout.flush()
'''
- print("\nSaved:", path)
+ print("\nSaved:", filepath)
return True
if __name__ == "__main__":
diff --git a/release/scripts/modules/rigify/__init__.py b/release/scripts/modules/rigify/__init__.py
index ee6cc934c1b..98d9bb235a2 100644
--- a/release/scripts/modules/rigify/__init__.py
+++ b/release/scripts/modules/rigify/__init__.py
@@ -19,7 +19,7 @@
# <pep8 compliant>
import bpy
-from Mathutils import Vector
+from mathutils import Vector
# TODO, have these in a more general module
from rna_prop_ui import rna_idprop_ui_prop_get
@@ -159,8 +159,8 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
# Not needed but catches any errors before duplicating
validate_rig(context, obj_orig)
- global_undo = context.user_preferences.edit.global_undo
- context.user_preferences.edit.global_undo = False
+ use_global_undo = context.user_preferences.edit.use_global_undo
+ context.user_preferences.edit.use_global_undo = False
mode_orig = context.mode
rest_backup = obj_orig.data.pose_position
obj_orig.data.pose_position = 'REST'
@@ -191,8 +191,8 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
obj.animation_data_clear()
# Select generated rig object
- obj_orig.selected = False
- obj.selected = True
+ obj_orig.select = False
+ obj.select = True
scene.objects.active = obj
# Remove all bones from the generated rig armature.
@@ -212,9 +212,9 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
# Select the temp rigs for merging
for objt in scene.objects:
- objt.selected = False # deselect all objects
- temp_rig_1.selected = True
- temp_rig_2.selected = True
+ objt.select = False # deselect all objects
+ temp_rig_1.select = True
+ temp_rig_2.select = True
scene.objects.active = temp_rig_2
# Merge the temporary rigs
@@ -225,8 +225,8 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
# Select the generated rig
for objt in scene.objects:
- objt.selected = False # deselect all objects
- obj.selected = True
+ objt.select = False # deselect all objects
+ obj.select = True
scene.objects.active = obj
# Copy over the pose_bone properties
@@ -282,7 +282,7 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
edit_bone.head = (0.0, 0.0, 0.0)
edit_bone.tail = (0.0, 1.0, 0.0)
edit_bone.roll = 0.0
- edit_bone.layer = ROOT_LAYERS
+ edit_bone.layers = ROOT_LAYERS
bpy.ops.object.mode_set(mode='OBJECT')
# key: bone name
@@ -412,7 +412,7 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
else:
root_ebone_tmp = root_ebone
- ebone.connected = False
+ ebone.use_connect = False
ebone.parent = root_ebone_tmp
'''
@@ -429,7 +429,7 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
con.target = obj
con.subtarget = bone_name
- if not pbone.bone.connected:
+ if not pbone.bone.use_connect:
con = pbone.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = bone_name
@@ -445,33 +445,33 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
layer_second_last[30] = True
for bone_name, bone in arm.bones.items():
- bone.deform = False # Non DEF bones shouldn't deform
+ bone.use_deform = False # Non DEF bones shouldn't deform
if bone_name.startswith(ORG_PREFIX):
- bone.layer = ORG_LAYERS
+ bone.layers = ORG_LAYERS
elif bone_name.startswith(MCH_PREFIX): # XXX fixme
- bone.layer = MCH_LAYERS
+ bone.layers = MCH_LAYERS
elif bone_name.startswith(DEF_PREFIX): # XXX fixme
- bone.layer = DEF_LAYERS
- bone.deform = True
+ bone.layers = DEF_LAYERS
+ bone.use_deform = True
else:
# Assign bone appearance if there is a widget for it
obj.pose.bones[bone_name].custom_shape = context.scene.objects.get(WGT_PREFIX + bone_name)
- layer_tot[:] = [max(lay) for lay in zip(layer_tot, bone.layer)]
+ layer_tot[:] = [max(lay) for lay in zip(layer_tot, bone.layers)]
# Only for demo'ing
layer_show = [a and not (b or c or d) for a, b, c, d in zip(layer_tot, ORG_LAYERS, MCH_LAYERS, DEF_LAYERS)]
- arm.layer = layer_show
+ arm.layers = layer_show
- # obj.restrict_view = True
- obj.data.draw_axes = False
+ # obj.hide = True
+ obj.data.show_axes = False
bpy.ops.object.mode_set(mode=mode_orig)
obj_orig.data.pose_position = rest_backup
obj.data.pose_position = 'POSE'
obj_orig.data.pose_position = 'POSE'
- context.user_preferences.edit.global_undo = global_undo
+ context.user_preferences.edit.use_global_undo = use_global_undo
print("Done.\n")
@@ -490,8 +490,8 @@ def generate_test(context, metarig_type="", GENERATE_FINAL=True):
scene.objects.link(obj_new)
scene.objects.active = obj_new
for obj in scene.objects:
- obj.selected = False
- obj_new.selected = True
+ obj.select = False
+ obj_new.select = True
for module_name in get_submodule_types():
if (metarig_type and module_name != metarig_type):
@@ -534,10 +534,10 @@ def generate_test_all(context, GRAPH=False):
new_objects = rigify.generate_test(context)
if GRAPH:
- base_name = os.path.splitext(bpy.data.filename)[0]
+ base_name = os.path.splitext(bpy.data.filepath)[0]
for obj, obj_new in new_objects:
for obj in (obj, obj_new):
- fn = base_name + "-" + bpy.utils.clean_name(obj.name)
+ fn = base_name + "-" + bpy.path.clean_name(obj.name)
path_dot = fn + ".dot"
path_png = fn + ".png"
@@ -548,11 +548,11 @@ def generate_test_all(context, GRAPH=False):
i = 0
for obj, obj_new in new_objects:
- obj.data.drawtype = 'STICK'
+ obj.data.draw_type = 'STICK'
obj.location[1] += i
obj_new.location[1] += i
- obj_new.selected = False
- obj.selected = True
+ obj_new.select = False
+ obj.select = True
i += 4
diff --git a/release/scripts/modules/rigify/arm_biped.py b/release/scripts/modules/rigify/arm_biped.py
index 7aa6a37304a..ac878c3c076 100644
--- a/release/scripts/modules/rigify/arm_biped.py
+++ b/release/scripts/modules/rigify/arm_biped.py
@@ -23,7 +23,7 @@ from math import radians, pi
from rigify import RigifyError, ORG_PREFIX
from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to, blend_bone_list, get_side_name, get_base_name
from rna_prop_ui import rna_idprop_ui_prop_get
-from Mathutils import Vector
+from mathutils import Vector
METARIG_NAMES = "shoulder", "arm", "forearm", "hand"
@@ -37,24 +37,24 @@ def metarig_template():
bone.head[:] = 0.0000, -0.0425, 0.0000
bone.tail[:] = 0.0942, -0.0075, 0.0333
bone.roll = -0.2227
- bone.connected = False
+ bone.use_connect = False
bone = arm.edit_bones.new('upper_arm')
bone.head[:] = 0.1066, -0.0076, -0.0010
bone.tail[:] = 0.2855, 0.0206, -0.0104
bone.roll = 1.6152
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['shoulder']
bone = arm.edit_bones.new('forearm')
bone.head[:] = 0.2855, 0.0206, -0.0104
bone.tail[:] = 0.4550, -0.0076, -0.0023
bone.roll = 1.5153
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['upper_arm']
bone = arm.edit_bones.new('hand')
bone.head[:] = 0.4550, -0.0076, -0.0023
bone.tail[:] = 0.5423, -0.0146, -0.0131
bone.roll = -3.0083
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['forearm']
bpy.ops.object.mode_set(mode='OBJECT')
@@ -78,7 +78,7 @@ def metarig_definition(obj, orig_bone_name):
hands = []
for pbone in obj.pose.bones:
index = pbone.parent_index(mt.arm_p)
- if index == 2 and pbone.bone.connected and pbone.bone.parent.connected:
+ if index == 2 and pbone.bone.use_connect and pbone.bone.parent.use_connect:
hands.append(pbone)
if len(hands) != 1:
@@ -106,12 +106,12 @@ def ik(obj, definitions, base_names, options):
ik_chain = mt.copy(to_fmt="MCH-%s_ik", base_names=base_names, exclude_attrs=["shoulder"])
# IK needs no parent_index
- ik_chain.hand_e.connected = False
+ ik_chain.hand_e.use_connect = False
ik_chain.hand_e.parent = None
- ik_chain.hand_e.local_location = False
+ ik_chain.hand_e.use_local_location = False
ik_chain.rename("hand", get_base_name(base_names[mt.hand]) + "_ik" + get_side_name(mt.hand))
- ik_chain.arm_e.connected = False
+ ik_chain.arm_e.use_connect = False
ik_chain.arm_e.parent = mt.shoulder_e
# Add the bone used for the arms poll target
@@ -119,7 +119,7 @@ def ik(obj, definitions, base_names, options):
ik.pole = add_pole_target_bone(obj, mt.forearm, "elbow_target" + get_side_name(mt.forearm), mode='ZAVERAGE')
ik.update()
- ik.pole_e.local_location = False
+ ik.pole_e.use_local_location = False
# option: elbow_parent
elbow_parent_name = options.get("elbow_parent", "")
@@ -137,8 +137,8 @@ def ik(obj, definitions, base_names, options):
ik.pole_vis = add_stretch_to(obj, mt.forearm, ik.pole, "VIS-%s_ik" % base_names[mt.forearm])
ik.update()
- ik.hand_vis_e.restrict_select = True
- ik.pole_vis_e.restrict_select = True
+ ik.hand_vis_e.hide_select = True
+ ik.pole_vis_e.hide_select = True
bpy.ops.object.mode_set(mode='OBJECT')
@@ -147,9 +147,9 @@ def ik(obj, definitions, base_names, options):
ik_chain.update()
# Set IK dof
- ik_chain.forearm_p.ik_dof_x = True
- ik_chain.forearm_p.ik_dof_y = False
- ik_chain.forearm_p.ik_dof_z = False
+ ik_chain.forearm_p.lock_ik_x = False
+ ik_chain.forearm_p.lock_ik_y = True
+ ik_chain.forearm_p.lock_ik_z = True
con = ik_chain.forearm_p.constraints.new('IK')
con.target = obj
@@ -161,18 +161,18 @@ def ik(obj, definitions, base_names, options):
con.use_stretch = True
con.use_target = True
con.use_rotation = False
- con.chain_length = 2
+ con.chain_count = 2
con.pole_angle = -pi/2
# last step setup layers
if "ik_layer" in options:
layer = [n==options["ik_layer"] for n in range(0,32)]
else:
- layer = list(mt.arm_b.layer)
- ik_chain.hand_b.layer = layer
- ik.hand_vis_b.layer = layer
- ik.pole_b.layer = layer
- ik.pole_vis_b.layer = layer
+ layer = list(mt.arm_b.layers)
+ ik_chain.hand_b.layers = layer
+ ik.hand_vis_b.layers = layer
+ ik.pole_b.layers = layer
+ ik.pole_vis_b.layers = layer
bpy.ops.object.mode_set(mode='EDIT')
# don't blend the shoulder
@@ -192,12 +192,12 @@ def fk(obj, definitions, base_names, options):
# shoulder is used as a hinge
fk_chain.rename("shoulder", "MCH-%s_hinge" % base_names[mt.arm])
- fk_chain.shoulder_e.translate(Vector(0.0, fk_chain.shoulder_e.length / 2, 0.0))
+ fk_chain.shoulder_e.translate(Vector((0.0, fk_chain.shoulder_e.length / 2, 0.0)))
# upper arm constrains to this.
ex.socket_e = copy_bone_simple(arm, mt.arm, "MCH-%s_socket" % base_names[mt.arm])
ex.socket = ex.socket_e.name
- ex.socket_e.connected = False
+ ex.socket_e.use_connect = False
ex.socket_e.parent = mt.shoulder_e
ex.socket_e.length *= 0.5
@@ -206,11 +206,11 @@ def fk(obj, definitions, base_names, options):
ex.hand_delta_e = copy_bone_simple(arm, fk_chain.hand, "MCH-delta_%s" % base_names[mt.hand], parent=True)
ex.hand_delta = ex.hand_delta_e.name
ex.hand_delta_e.length *= 0.5
- ex.hand_delta_e.connected = False
+ ex.hand_delta_e.use_connect = False
if "hand_roll" in options:
ex.hand_delta_e.roll += radians(options["hand_roll"])
- fk_chain.hand_e.connected = False
+ fk_chain.hand_e.use_connect = False
fk_chain.hand_e.parent = ex.hand_delta_e
bpy.ops.object.mode_set(mode='OBJECT')
@@ -240,11 +240,11 @@ def fk(obj, definitions, base_names, options):
con.name = "hinge"
con.target = obj
con.subtarget = mt.shoulder
- driver_fcurve = con.driver_add("influence", 0)
+ driver_fcurve = con.driver_add("influence")
driver = driver_fcurve.driver
- controller_path = fk_chain.arm_p.path_to_id()
+ controller_path = fk_chain.arm_p.path_from_id()
# add custom prop
fk_chain.arm_p["hinge"] = 0.0
prop = rna_idprop_ui_prop_get(fk_chain.arm_p, "hinge", create=True)
@@ -273,10 +273,10 @@ def fk(obj, definitions, base_names, options):
if "fk_layer" in options:
layer = [n==options["fk_layer"] for n in range(0,32)]
else:
- layer = list(mt.arm_b.layer)
- fk_chain.arm_b.layer = layer
- fk_chain.forearm_b.layer = layer
- fk_chain.hand_b.layer = layer
+ layer = list(mt.arm_b.layers)
+ fk_chain.arm_b.layers = layer
+ fk_chain.forearm_b.layers = layer
+ fk_chain.hand_b.layers = layer
# Forearm was getting wrong roll somehow. Hack to fix that.
bpy.ops.object.mode_set(mode='EDIT')
@@ -295,8 +295,8 @@ def deform(obj, definitions, base_names, options):
# Create upper arm bones: two bones, each half of the upper arm.
uarm1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
uarm2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
- uarm1.connected = False
- uarm2.connected = False
+ uarm1.use_connect = False
+ uarm2.use_connect = False
uarm2.parent = uarm1
center = uarm1.center
uarm1.tail = center
@@ -305,8 +305,8 @@ def deform(obj, definitions, base_names, options):
# Create forearm bones: two bones, each half of the forearm.
farm1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
farm2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
- farm1.connected = False
- farm2.connected = False
+ farm1.use_connect = False
+ farm2.use_connect = False
farm2.parent = farm1
center = farm1.center
farm1.tail = center
@@ -314,7 +314,7 @@ def deform(obj, definitions, base_names, options):
# Create twist bone
twist = copy_bone_simple(obj.data, definitions[2], "MCH-arm_twist")
- twist.connected = False
+ twist.use_connect = False
twist.parent = obj.data.edit_bones[definitions[3]]
twist.length /= 2
diff --git a/release/scripts/modules/rigify/copy.py b/release/scripts/modules/rigify/copy.py
index e0bff555a9b..c051e5bb7f6 100644
--- a/release/scripts/modules/rigify/copy.py
+++ b/release/scripts/modules/rigify/copy.py
@@ -33,7 +33,7 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
@@ -98,7 +98,7 @@ def control(obj, definitions, base_names, options):
cp.cpy_p.lock_scale = tuple(mt.cpy_p.lock_scale)
# Layers
- cp.cpy_b.layer = list(mt.cpy_b.layer)
+ cp.cpy_b.layers = list(mt.cpy_b.layers)
return (mt.cpy,)
diff --git a/release/scripts/modules/rigify/delta.py b/release/scripts/modules/rigify/delta.py
index dce03b5f412..d0b4fbccce9 100644
--- a/release/scripts/modules/rigify/delta.py
+++ b/release/scripts/modules/rigify/delta.py
@@ -34,18 +34,18 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = -0.0000, 0.7382, 0.1895
bone.roll = -0.0000
- bone.connected = False
+ bone.use_connect = False
bone = arm.edit_bones.new('delta')
bone.head[:] = -0.0497, 0.8414, 0.3530
bone.tail[:] = -0.2511, 1.1588, 0.9653
bone.roll = 2.6044
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['bonesker']
bone = arm.edit_bones.new('boney')
bone.head[:] = 0.7940, 2.5592, 0.4134
bone.tail[:] = 0.7940, 3.3975, 0.4890
bone.roll = 3.1416
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['delta']
bpy.ops.object.mode_set(mode='OBJECT')
@@ -67,7 +67,7 @@ def metarig_definition(obj, orig_bone_name):
if len(children) != 1:
raise RigifyError("only 1 child supported for delta on bone '%s'" % delta.name)
- if delta.connected:
+ if delta.use_connect:
raise RigifyError("bone cannot be connected to its parent '%s'" % delta.name)
bone_definition = [delta.name, children[0].name]
diff --git a/release/scripts/modules/rigify/eye_balls.py b/release/scripts/modules/rigify/eye_balls.py
index 8c126151024..f65d56b9f2b 100644
--- a/release/scripts/modules/rigify/eye_balls.py
+++ b/release/scripts/modules/rigify/eye_balls.py
@@ -20,13 +20,92 @@
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
-from Mathutils import Vector
+from mathutils import Vector
from rigify import RigifyError
from rigify_utils import copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "eye_balls"
+def addget_shape_key(obj, name="Key"):
+ """ Fetches a shape key, or creates it if it doesn't exist
+ """
+ # Create a shapekey set if it doesn't already exist
+ if obj.data.shape_keys is None:
+ shape = obj.add_shape_key(name="Basis", from_mix=False)
+ obj.active_shape_key_index = 0
+
+ # Get the shapekey, or create it if it doesn't already exist
+ if name in obj.data.shape_keys.keys:
+ shape_key = obj.data.shape_keys.keys[name]
+ else:
+ shape_key = obj.add_shape_key(name=name, from_mix=False)
+
+ return shape_key
+
+
+def addget_shape_key_driver(obj, name="Key"):
+ """ Fetches the driver for the shape key, or creates it if it doesn't
+ already exist.
+ """
+ driver_path = 'keys["' + name + '"].value'
+ fcurve = None
+ driver = None
+ new = False
+ if obj.data.shape_keys.animation_data is not None:
+ for driver_s in obj.data.shape_keys.animation_data.drivers:
+ if driver_s.data_path == driver_path:
+ fcurve = driver_s
+ if fcurve == None:
+ fcurve = obj.data.shape_keys.keys[name].driver_add("value")
+ fcurve.driver.type = 'AVERAGE'
+ new = True
+
+ return fcurve, new
+
+
+def create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, expression):
+ """ Creates/gets a shape key and sets up a driver for it.
+
+ obj = armature object
+ bone = driving bone name
+ meshes = list of meshes to create the shapekey/driver on
+ shape_name = name of the shape key
+ var_name = name of the driving variable
+ var_path = path to the property on the bone to drive with
+ expression = python expression for the driver
+ """
+ pb = obj.pose.bones
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ for mesh_name in meshes:
+ mesh_obj = bpy.data.objects[mesh_name]
+
+ # Add/get the shape key
+ shape = addget_shape_key(mesh_obj, name=shape_name)
+
+ # Add/get the shape key driver
+ fcurve, a = addget_shape_key_driver(mesh_obj, name=shape_name)
+
+ # Set up the driver
+ driver = fcurve.driver
+ driver.type = 'SCRIPTED'
+ driver.expression = expression
+
+ # Get the variable, or create it if it doesn't already exist
+ if var_name in driver.variables:
+ var = driver.variables[var_name]
+ else:
+ var = driver.variables.new()
+ var.name = var_name
+
+ # Set up the variable
+ var.type = "SINGLE_PROP"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = obj
+ var.targets[0].data_path = 'pose.bones["' + bone + '"]' + var_path
+
+
def mark_actions():
for action in bpy.data.actions:
action.tag = True
@@ -55,7 +134,7 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
@@ -120,6 +199,12 @@ def control(obj, definitions, base_names, options):
head = definitions[0]
eye_target = definitions[1]
+ # Get list of pupil mesh objects
+ if "mesh" in options:
+ pupil_meshes = options["mesh"].replace(" ", "").split(",")
+ else:
+ pupil_meshes = []
+
# Get list of eyes
if "eyes" in options:
eye_base_names = options["eyes"].replace(" ", "").split(",")
@@ -132,7 +217,7 @@ def control(obj, definitions, base_names, options):
eyes += ["ORG-"+name]
# Get the average position of the eyes
- center = Vector(0,0,0)
+ center = Vector((0, 0, 0))
for eye in eyes:
center += eb[eye].head
if len(eyes) != 0:
@@ -197,7 +282,7 @@ def control(obj, definitions, base_names, options):
prop["min"] = 0.0
prop["max"] = 1.0
- free_driver_path = pb[target_ctrl].path_to_id() + '["free"]'
+ free_driver_path = pb[target_ctrl].path_from_id() + '["free"]'
# Constraints
# Mind's eye tracks eye target control
@@ -210,7 +295,7 @@ def control(obj, definitions, base_names, options):
con.target = obj
con.subtarget = head
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
mod = fcurve.modifiers[0]
@@ -243,22 +328,66 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_X'
con.frame_start = -20
con.frame_end = 20
- con.minimum = 0.0
- con.maximum = 2.0
+ con.min = 0.0
+ con.max = 2.0
con.target_space = 'LOCAL'
+
+
+ # Get/create the shape keys and drivers for pupil dilation
+ shape_names = ["PUPILS-dilate_wide", "PUPILS-dilate_narrow"]
+ slider_name = "pupil_dilate"
+
+ # Set up the custom property on the bone
+ prop = rna_idprop_ui_prop_get(pb[target_ctrl], slider_name, create=True)
+ pb[target_ctrl][slider_name] = 0.0
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ if len(shape_names) > 1:
+ prop["min"] = -1.0
+ prop["soft_min"] = -1.0
+
+ # Add the shape drivers
+ # Positive
+ if shape_names[0] != "":
+ # Set up the variables for creating the shape key driver
+ shape_name = shape_names[0]
+ var_name = slider_name.replace(".", "_").replace("-", "_")
+ var_path = '["' + slider_name + '"]'
+ if slider_name + "_fac" in options:
+ fac = options[slider_name + "_fac"]
+ else:
+ fac = 1.0
+ expression = var_name + " * " + str(fac)
+ # Create the shape key driver
+ create_shape_and_driver(obj, target_ctrl, pupil_meshes, shape_name, var_name, var_path, expression)
+ # Negative
+ if shape_names[0] != "" and len(shape_names) > 1:
+ # Set up the variables for creating the shape key driver
+ shape_name = shape_names[1]
+ var_name = slider_name.replace(".", "_").replace("-", "_")
+ var_path = '["' + slider_name + '"]'
+ if slider_name + "_fac" in options:
+ fac = options[slider_name + "_fac"]
+ else:
+ fac = 1.0
+ expression = var_name + " * " + str(fac) + " * -1"
+ # Create the shape key driver
+ create_shape_and_driver(obj, target_ctrl, pupil_meshes, shape_name, var_name, var_path, expression)
# Set layers
- #layer = list(bb[definitions[2]].layer)
- #bb[lid1].layer = layer
- #bb[lid2].layer = layer
- #bb[lid3].layer = layer
- #bb[lid4].layer = layer
- #bb[lid5].layer = layer
- #bb[lid6].layer = layer
- #bb[lid7].layer = layer
- #bb[lid8].layer = layer
+ #layer = list(bb[definitions[2]].layers)
+ #bb[lid1].layers = layer
+ #bb[lid2].layers = layer
+ #bb[lid3].layers = layer
+ #bb[lid4].layers = layer
+ #bb[lid5].layers = layer
+ #bb[lid6].layers = layer
+ #bb[lid7].layers = layer
+ #bb[lid8].layers = layer
return (None,)
diff --git a/release/scripts/modules/rigify/eye_lid.py b/release/scripts/modules/rigify/eye_lid.py
index 6eb1ff87d82..3f336e268c6 100644
--- a/release/scripts/modules/rigify/eye_lid.py
+++ b/release/scripts/modules/rigify/eye_lid.py
@@ -21,7 +21,7 @@
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos
-from Mathutils import Vector
+from mathutils import Vector
from rigify import RigifyError
from rigify_utils import copy_bone_simple
@@ -56,7 +56,7 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
@@ -148,10 +148,10 @@ def deform(obj, definitions, base_names, options):
eb[dlid3].parent = eb[dlid4]
eb[dlid33].parent = eb[dlid3]
- eb[dlid2].connected = True
- eb[dlid22].connected = True
- eb[dlid3].connected = True
- eb[dlid33].connected = True
+ eb[dlid2].use_connect = True
+ eb[dlid22].use_connect = True
+ eb[dlid3].use_connect = True
+ eb[dlid33].use_connect = True
eb[dlid1].bbone_segments = 8
eb[dlid2].bbone_segments = 8
@@ -170,10 +170,10 @@ def deform(obj, definitions, base_names, options):
eb[dlid7].parent = eb[dlid8]
eb[dlid77].parent = eb[dlid7]
- eb[dlid6].connected = True
- eb[dlid66].connected = True
- eb[dlid7].connected = True
- eb[dlid77].connected = True
+ eb[dlid6].use_connect = True
+ eb[dlid66].use_connect = True
+ eb[dlid7].use_connect = True
+ eb[dlid77].use_connect = True
eb[dlid5].bbone_segments = 8
eb[dlid6].bbone_segments = 8
@@ -299,14 +299,15 @@ def control(obj, definitions, base_names, options):
lid8 = copy_bone_simple(obj.data, definitions[9], base_names[definitions[9]]).name
size = eb[lid1].length
- eb[lid1].tail = eb[lid1].head + Vector(0,size,0)
- eb[lid2].tail = eb[lid2].head + Vector(0,size,0)
- eb[lid3].tail = eb[lid3].head + Vector(0,size,0)
- eb[lid4].tail = eb[lid4].head + Vector(0,size,0)
- eb[lid5].tail = eb[lid5].head + Vector(0,size,0)
- eb[lid6].tail = eb[lid6].head + Vector(0,size,0)
- eb[lid7].tail = eb[lid7].head + Vector(0,size,0)
- eb[lid8].tail = eb[lid8].head + Vector(0,size,0)
+ size_y = Vector(0.0, size, 0.0)
+ eb[lid1].tail = eb[lid1].head + size_y
+ eb[lid2].tail = eb[lid2].head + size_y
+ eb[lid3].tail = eb[lid3].head + size_y
+ eb[lid4].tail = eb[lid4].head + size_y
+ eb[lid5].tail = eb[lid5].head + size_y
+ eb[lid6].tail = eb[lid6].head + size_y
+ eb[lid7].tail = eb[lid7].head + size_y
+ eb[lid8].tail = eb[lid8].head + size_y
eb[lid1].roll = 0
eb[lid2].roll = 0
@@ -355,7 +356,7 @@ def control(obj, definitions, base_names, options):
prop["min"] = 0.0
prop["max"] = 1.0
- close_driver_path = pb[upper_lid_ctrl].path_to_id() + '["close_action"]'
+ close_driver_path = pb[upper_lid_ctrl].path_from_id() + '["close_action"]'
# Constraints
@@ -435,10 +436,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance*2
- con.maximum = distance
+ con.min = -distance*2
+ con.max = distance
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -454,10 +455,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance*2
- con.maximum = distance
+ con.min = -distance*2
+ con.max = distance
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -472,10 +473,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance*2
- con.maximum = distance
+ con.min = -distance*2
+ con.max = distance
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -490,10 +491,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance*2
- con.maximum = distance
+ con.min = -distance*2
+ con.max = distance
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -508,10 +509,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance*2
- con.maximum = distance
+ con.min = -distance*2
+ con.max = distance
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -527,10 +528,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance
- con.maximum = distance*2
+ con.min = -distance
+ con.max = distance*2
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -545,10 +546,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance
- con.maximum = distance*2
+ con.min = -distance
+ con.max = distance*2
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -563,10 +564,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance
- con.maximum = distance*2
+ con.min = -distance
+ con.max = distance*2
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -581,10 +582,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance
- con.maximum = distance*2
+ con.min = -distance
+ con.max = distance*2
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -599,10 +600,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
- con.minimum = -distance
- con.maximum = distance*2
+ con.min = -distance
+ con.max = distance*2
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -614,15 +615,15 @@ def control(obj, definitions, base_names, options):
# Set layers
- layer = list(bb[definitions[2]].layer)
- bb[lid1].layer = layer
- bb[lid2].layer = layer
- bb[lid3].layer = layer
- bb[lid4].layer = layer
- bb[lid5].layer = layer
- bb[lid6].layer = layer
- bb[lid7].layer = layer
- bb[lid8].layer = layer
+ layer = list(bb[definitions[2]].layers)
+ bb[lid1].layers = layer
+ bb[lid2].layers = layer
+ bb[lid3].layers = layer
+ bb[lid4].layers = layer
+ bb[lid5].layers = layer
+ bb[lid6].layers = layer
+ bb[lid7].layers = layer
+ bb[lid8].layers = layer
return (None,)
@@ -647,7 +648,7 @@ def make_lid_stretch_bone(obj, name, bone1, bone2, roll_alpha):
# Create the bone, pointing from bone1 to bone2
bone_e = copy_bone_simple(obj.data, bone1, name, parent=True)
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.tail = eb[bone2].head
bone = bone_e.name
diff --git a/release/scripts/modules/rigify/finger_curl.py b/release/scripts/modules/rigify/finger_curl.py
index fcf57f81d3e..947ec75c9f8 100644
--- a/release/scripts/modules/rigify/finger_curl.py
+++ b/release/scripts/modules/rigify/finger_curl.py
@@ -35,18 +35,18 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0353, -0.0184, -0.0053
bone.roll = -2.8722
- bone.connected = False
+ bone.use_connect = False
bone = arm.edit_bones.new('finger.02')
bone.head[:] = 0.0353, -0.0184, -0.0053
bone.tail[:] = 0.0702, -0.0364, -0.0146
bone.roll = -2.7099
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['finger.01']
bone = arm.edit_bones.new('finger.03')
bone.head[:] = 0.0702, -0.0364, -0.0146
bone.tail[:] = 0.0903, -0.0461, -0.0298
bone.roll = -2.1709
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['finger.02']
bpy.ops.object.mode_set(mode='OBJECT')
@@ -57,31 +57,20 @@ def metarig_template():
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the first in a chain
- Expects a chain of at least 2 children.
+ Expects a chain with at least 1 child of the same base name.
eg.
- finger -> finger_01 -> finger_02
+ finger_01 -> finger_02
'''
- bone_definition = []
-
orig_bone = obj.data.bones[orig_bone_name]
- bone_definition.append(orig_bone.name)
-
- bone = orig_bone
- chain = 0
- while chain < 2: # first 2 bones only have 1 child
- children = bone.children
-
- if len(children) != 1:
- raise RigifyError("expected the chain to have 2 children from bone '%s' without a fork" % orig_bone_name)
- bone = children[0]
- bone_definition.append(bone.name) # finger_02, finger_03
- chain += 1
-
- if len(bone_definition) != len(METARIG_NAMES):
- raise RigifyError("internal problem, expected %d bones" % len(METARIG_NAMES))
-
+ bone_definition = [orig_bone.name]
+
+ bone_definition.extend([child.name for child in orig_bone.children_recursive_basename])
+
+ if len(bone_definition) < 2:
+ raise RigifyError("expected the chain to have at least 1 child from bone '%s' without the same base name" % orig_bone_name)
+
return bone_definition
@@ -90,11 +79,13 @@ def deform(obj, definitions, base_names, options):
"""
bpy.ops.object.mode_set(mode='EDIT')
+ three_digits = True if len(definitions) > 2 else False
+
# Create base digit bones: two bones, each half of the base digit.
f1a = copy_bone_simple(obj.data, definitions[0], "DEF-%s.01" % base_names[definitions[0]], parent=True)
f1b = copy_bone_simple(obj.data, definitions[0], "DEF-%s.02" % base_names[definitions[0]], parent=True)
- f1a.connected = False
- f1b.connected = False
+ f1a.use_connect = False
+ f1b.use_connect = False
f1b.parent = f1a
center = f1a.center
f1a.tail = center
@@ -102,13 +93,15 @@ def deform(obj, definitions, base_names, options):
# Create the other deform bones.
f2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s" % base_names[definitions[1]], parent=True)
- f3 = copy_bone_simple(obj.data, definitions[2], "DEF-%s" % base_names[definitions[2]], parent=True)
+ if three_digits:
+ f3 = copy_bone_simple(obj.data, definitions[2], "DEF-%s" % base_names[definitions[2]], parent=True)
# Store names before leaving edit mode
f1a_name = f1a.name
f1b_name = f1b.name
f2_name = f2.name
- f3_name = f3.name
+ if three_digits:
+ f3_name = f3.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
@@ -117,7 +110,8 @@ def deform(obj, definitions, base_names, options):
f1a = obj.pose.bones[f1a_name]
f1b = obj.pose.bones[f1b_name]
f2 = obj.pose.bones[f2_name]
- f3 = obj.pose.bones[f3_name]
+ if three_digits:
+ f3 = obj.pose.bones[f3_name]
# Constrain the base digit's bones
con = f1a.constraints.new('DAMPED_TRACK')
@@ -141,15 +135,18 @@ def deform(obj, definitions, base_names, options):
con.target = obj
con.subtarget = definitions[1]
- con = f3.constraints.new('COPY_TRANSFORMS')
- con.name = "copy_transforms"
- con.target = obj
- con.subtarget = definitions[2]
+ if three_digits:
+ con = f3.constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = obj
+ con.subtarget = definitions[2]
def main(obj, bone_definition, base_names, options):
# *** EDITMODE
bpy.ops.object.mode_set(mode='EDIT')
+
+ three_digits = True if len(bone_definition) > 2 else False
# get assosiated data
arm = obj.data
@@ -159,7 +156,8 @@ def main(obj, bone_definition, base_names, options):
org_f1 = bone_definition[0] # Original finger bone 01
org_f2 = bone_definition[1] # Original finger bone 02
- org_f3 = bone_definition[2] # Original finger bone 03
+ if three_digits:
+ org_f3 = bone_definition[2] # Original finger bone 03
# Check options
if "bend_ratio" in options:
@@ -179,35 +177,42 @@ def main(obj, bone_definition, base_names, options):
# Create the control bone
base_name = base_names[bone_definition[0]].split(".", 1)[0]
- tot_len = eb[org_f1].length + eb[org_f2].length + eb[org_f3].length
+ if three_digits:
+ tot_len = eb[org_f1].length + eb[org_f2].length + eb[org_f3].length
+ else:
+ tot_len = eb[org_f1].length + eb[org_f2].length
control = copy_bone_simple(arm, bone_definition[0], base_name + get_side_name(base_names[bone_definition[0]]), parent=True).name
- eb[control].connected = eb[org_f1].connected
+ eb[control].use_connect = eb[org_f1].use_connect
eb[control].parent = eb[org_f1].parent
eb[control].length = tot_len
# Create secondary control bones
f1 = copy_bone_simple(arm, bone_definition[0], base_names[bone_definition[0]]).name
f2 = copy_bone_simple(arm, bone_definition[1], base_names[bone_definition[1]]).name
- f3 = copy_bone_simple(arm, bone_definition[2], base_names[bone_definition[2]]).name
+ if three_digits:
+ f3 = copy_bone_simple(arm, bone_definition[2], base_names[bone_definition[2]]).name
# Create driver bones
df1 = copy_bone_simple(arm, bone_definition[0], "MCH-" + base_names[bone_definition[0]]).name
eb[df1].length /= 2
df2 = copy_bone_simple(arm, bone_definition[1], "MCH-" + base_names[bone_definition[1]]).name
eb[df2].length /= 2
- df3 = copy_bone_simple(arm, bone_definition[2], "MCH-" + base_names[bone_definition[2]]).name
- eb[df3].length /= 2
+ if three_digits:
+ df3 = copy_bone_simple(arm, bone_definition[2], "MCH-" + base_names[bone_definition[2]]).name
+ eb[df3].length /= 2
# Set parents of the bones, interleaving the driver bones with the secondary control bones
- eb[f3].connected = False
- eb[df3].connected = False
- eb[f2].connected = False
- eb[df2].connected = False
- eb[f1].connected = False
- eb[df1].connected = eb[org_f1].connected
-
- eb[f3].parent = eb[df3]
- eb[df3].parent = eb[f2]
+ if three_digits:
+ eb[f3].use_connect = False
+ eb[df3].use_connect = False
+ eb[f2].use_connect = False
+ eb[df2].use_connect = False
+ eb[f1].use_connect = False
+ eb[df1].use_connect = eb[org_f1].use_connect
+
+ if three_digits:
+ eb[f3].parent = eb[df3]
+ eb[df3].parent = eb[f2]
eb[f2].parent = eb[df2]
eb[df2].parent = eb[f1]
eb[f1].parent = eb[df1]
@@ -215,10 +220,10 @@ def main(obj, bone_definition, base_names, options):
# Set up bones for hinge
if make_hinge:
- socket = copy_bone_simple(arm, org_f1, "MCH-socket_" + control, parent=True).name
- hinge = copy_bone_simple(arm, eb[org_f1].parent.name, "MCH-hinge_" + control).name
+ socket = copy_bone_simple(arm, org_f1, "MCH-socket_"+control, parent=True).name
+ hinge = copy_bone_simple(arm, eb[org_f1].parent.name, "MCH-hinge_"+control).name
- eb[control].connected = False
+ eb[control].use_connect = False
eb[control].parent = eb[hinge]
# Create the deform rig while we're still in edit mode
@@ -234,12 +239,15 @@ def main(obj, bone_definition, base_names, options):
pb[control].lock_scale = True, False, True
pb[f1].rotation_mode = 'YZX'
pb[f2].rotation_mode = 'YZX'
- pb[f3].rotation_mode = 'YZX'
+ if three_digits:
+ pb[f3].rotation_mode = 'YZX'
pb[f1].lock_location = True, True, True
pb[f2].lock_location = True, True, True
- pb[f3].lock_location = True, True, True
+ if three_digits:
+ pb[f3].lock_location = True, True, True
pb[df2].rotation_mode = 'YZX'
- pb[df3].rotation_mode = 'YZX'
+ if three_digits:
+ pb[df3].rotation_mode = 'YZX'
# Add the bend_ratio property to the control bone
pb[control]["bend_ratio"] = bend_ratio
@@ -271,18 +279,19 @@ def main(obj, bone_definition, base_names, options):
con.target = obj
con.subtarget = f2
- con = pb[org_f3].constraints.new('COPY_TRANSFORMS')
- con.target = obj
- con.subtarget = f3
+ if three_digits:
+ con = pb[org_f3].constraints.new('COPY_TRANSFORMS')
+ con.target = obj
+ con.subtarget = f3
if make_hinge:
con = pb[hinge].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = bb[org_f1].parent.name
- hinge_driver_path = pb[control].path_to_id() + '["hinge"]'
+ hinge_driver_path = pb[control].path_from_id() + '["hinge"]'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -301,10 +310,15 @@ def main(obj, bone_definition, base_names, options):
con.subtarget = socket
# Create the drivers for the driver bones (control bone scale rotates driver bones)
- controller_path = pb[control].path_to_id() # 'pose.bones["%s"]' % control_bone_name
+ controller_path = pb[control].path_from_id() # 'pose.bones["%s"]' % control_bone_name
+
+ if three_digits:
+ finger_digits = [df2, df3]
+ else:
+ finger_digits = [df2]
i = 0
- for bone in [df2, df3]:
+ for bone in finger_digits:
# XXX - todo, any number
if i == 2:
@@ -334,23 +348,31 @@ def main(obj, bone_definition, base_names, options):
var.targets[0].data_path = controller_path + '["bend_ratio"]'
# XXX - todo, any number
- if i == 0:
- driver.expression = '(-scale+1.0)*pi*2.0*(1.0-br)'
- elif i == 1:
- driver.expression = '(-scale+1.0)*pi*2.0*br'
+ if three_digits:
+ if i == 0:
+ driver.expression = '(-scale+1.0)*pi*2.0*(1.0-br)'
+ elif i == 1:
+ driver.expression = '(-scale+1.0)*pi*2.0*br'
+ else:
+ driver.expression = driver.expression = '(-scale+1.0)*pi*2.0'
i += 1
# Last step setup layers
if "ex_layer" in options:
- layer = [n == options["ex_layer"] for n in range(0, 32)]
+ layer = [n==options["ex_layer"] for n in range(0,32)]
else:
- layer = list(arm.bones[bone_definition[0]].layer)
- for bone_name in [f1, f2, f3]:
- arm.bones[bone_name].layer = layer
+ layer = list(arm.bones[bone_definition[0]].layers)
+ #for bone_name in [f1, f2, f3]:
+ # arm.bones[bone_name].layers = layer
+ arm.bones[f1].layers = layer
+ arm.bones[f2].layers = layer
+ if three_digits:
+ arm.bones[f3].layers = layer
- layer = list(arm.bones[bone_definition[0]].layer)
- bb[control].layer = layer
+ layer = list(arm.bones[bone_definition[0]].layers)
+ bb[control].layers = layer
# no blending the result of this
return None
+
diff --git a/release/scripts/modules/rigify/leg_biped.py b/release/scripts/modules/rigify/leg_biped.py
index 0d3fbabba68..d2ddba9f549 100644
--- a/release/scripts/modules/rigify/leg_biped.py
+++ b/release/scripts/modules/rigify/leg_biped.py
@@ -36,36 +36,36 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 0.2506
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bone = arm.edit_bones.new('thigh')
bone.head[:] = 0.1253, 0.0000, -0.0000
bone.tail[:] = 0.0752, -0.0251, -0.4260
bone.roll = 0.1171
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['hips']
bone = arm.edit_bones.new('shin')
bone.head[:] = 0.0752, -0.0251, -0.4260
bone.tail[:] = 0.0752, 0.0000, -0.8771
bone.roll = 0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['thigh']
bone = arm.edit_bones.new('foot')
bone.head[:] = 0.0752, 0.0000, -0.8771
bone.tail[:] = 0.1013, -0.1481, -0.9773
bone.roll = -0.4662
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['shin']
bone = arm.edit_bones.new('toe')
bone.head[:] = 0.1013, -0.1481, -0.9773
bone.tail[:] = 0.1100, -0.2479, -0.9773
bone.roll = 3.1416
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['foot']
bone = arm.edit_bones.new('heel')
bone.head[:] = 0.0652, 0.0501, -1.0024
bone.tail[:] = 0.0927, -0.1002, -1.0024
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['foot']
bpy.ops.object.mode_set(mode='OBJECT')
@@ -109,11 +109,11 @@ def metarig_definition(obj, orig_bone_name):
if len(children) != 2:
raise RigifyError("expected the foot bone:'%s' to have 2 children" % bone.name)
- if children[0].connected == children[1].connected:
+ if children[0].use_connect == children[1].use_connect:
raise RigifyError("expected one bone to be connected")
toe, heel = children
- if heel.connected:
+ if heel.use_connect:
toe, heel = heel, toe
@@ -154,7 +154,7 @@ def ik(obj, bone_definition, base_names, options):
ik.foot_e = copy_bone_simple(arm, mt.heel, base_foot_name + "_ik" + get_side_name(base_names[mt_chain.foot]))
ik.foot = ik.foot_e.name
ik.foot_e.translate(mt_chain.foot_e.head - ik.foot_e.head)
- ik.foot_e.local_location = False
+ ik.foot_e.use_local_location = False
# foot roll: heel pointing backwards, half length
ik.foot_roll_e = copy_bone_simple(arm, mt.heel, base_foot_name + "_roll" + get_side_name(base_names[mt_chain.foot]))
@@ -180,11 +180,11 @@ def ik(obj, bone_definition, base_names, options):
# rename 'MCH-toe' --> to 'toe_ik' and make the child of ik.foot_roll_01
# ------------------ FK or IK?
ik_chain.rename("toe", get_base_name(base_names[mt_chain.toe]) + "_ik" + get_side_name(base_names[mt_chain.toe]))
- ik_chain.toe_e.connected = False
+ ik_chain.toe_e.use_connect = False
ik_chain.toe_e.parent = ik.foot_roll_01_e
# re-parent ik_chain.foot to the
- ik_chain.foot_e.connected = False
+ ik_chain.foot_e.use_connect = False
ik_chain.foot_e.parent = ik.foot_roll_02_e
@@ -198,10 +198,10 @@ def ik(obj, bone_definition, base_names, options):
ik.knee_target_e.translate(offset)
ik.knee_target_e.length *= 0.5
ik.knee_target_e.parent = ik.foot_e
- ik.knee_target_e.local_location = False
+ ik.knee_target_e.use_local_location = False
# roll the bone to point up... could also point in the same direction as ik.foot_roll
- # ik.foot_roll_02_e.matrix * Vector(0.0, 0.0, 1.0) # ACK!, no rest matrix in editmode
+ # ik.foot_roll_02_e.matrix * Vector((0.0, 0.0, 1.0)) # ACK!, no rest matrix in editmode
ik.foot_roll_01_e.align_roll((0.0, 0.0, -1.0))
bpy.ops.object.mode_set(mode='OBJECT')
@@ -211,9 +211,9 @@ def ik(obj, bone_definition, base_names, options):
ik_chain.update()
# Set IK dof
- ik_chain.shin_p.ik_dof_x = True
- ik_chain.shin_p.ik_dof_y = False
- ik_chain.shin_p.ik_dof_z = False
+ ik_chain.shin_p.lock_ik_x = False
+ ik_chain.shin_p.lock_ik_y = True
+ ik_chain.shin_p.lock_ik_z = True
# Set rotation modes and axis locks
ik.foot_roll_p.rotation_mode = 'XYZ'
@@ -225,7 +225,7 @@ def ik(obj, bone_definition, base_names, options):
# IK
con = ik_chain.shin_p.constraints.new('IK')
- con.chain_length = 2
+ con.chain_count = 2
con.iterations = 500
con.pole_angle = -pi / 2.0
con.use_tail = True
@@ -256,22 +256,22 @@ def ik(obj, bone_definition, base_names, options):
con.owner_space = 'LOCAL'
if con_l is cons[-1][-1]:
- con.minimum_x = 0.0
- con.maximum_x = 180.0 # XXX -deg
+ con.min_x = 0.0
+ con.max_x = 180.0 # XXX -deg
else:
- con.minimum_x = -180.0 # XXX -deg
- con.maximum_x = 0.0
+ con.min_x = -180.0 # XXX -deg
+ con.max_x = 0.0
# last step setup layers
if "ik_layer" in options:
layer = [n == options["ik_layer"] for n in range(0, 32)]
else:
- layer = list(mt_chain.thigh_b.layer)
+ layer = list(mt_chain.thigh_b.layers)
for attr in ik_chain.attr_names:
- getattr(ik_chain, attr + "_b").layer = layer
+ getattr(ik_chain, attr + "_b").layers = layer
for attr in ik.attr_names:
- getattr(ik, attr + "_b").layer = layer
+ getattr(ik, attr + "_b").layers = layer
bpy.ops.object.mode_set(mode='EDIT')
@@ -279,7 +279,7 @@ def ik(obj, bone_definition, base_names, options):
def fk(obj, bone_definition, base_names, options):
- from Mathutils import Vector
+ from mathutils import Vector
arm = obj.data
# these account for all bones in METARIG_NAMES
@@ -298,7 +298,7 @@ def fk(obj, bone_definition, base_names, options):
ex.thigh_socket_e = copy_bone_simple(arm, mt_chain.thigh, "MCH-%s_socket" % base_names[mt_chain.thigh], parent=True)
ex.thigh_socket = ex.thigh_socket_e.name
- ex.thigh_socket_e.tail = ex.thigh_socket_e.head + Vector(0.0, 0.0, ex.thigh_socket_e.length / 4.0)
+ ex.thigh_socket_e.tail = ex.thigh_socket_e.head + Vector((0.0, 0.0, ex.thigh_socket_e.length / 4.0))
ex.thigh_hinge_e = copy_bone_simple(arm, mt.hips, "MCH-%s_hinge" % base_names[mt_chain.thigh], parent=False)
ex.thigh_hinge = ex.thigh_hinge_e.name
@@ -312,11 +312,11 @@ def fk(obj, bone_definition, base_names, options):
foot = foot_e.name
foot_e.translate(mt_chain.foot_e.head - foot_e.head)
foot_e.parent = fk_chain.shin_e
- foot_e.connected = fk_chain.foot_e.connected
- fk_chain.foot_e.connected = False
+ foot_e.use_connect = fk_chain.foot_e.use_connect
+ fk_chain.foot_e.use_connect = False
fk_chain.foot_e.parent = foot_e
- fk_chain.thigh_e.connected = False
+ fk_chain.thigh_e.use_connect = False
fk_chain.thigh_e.parent = ex.thigh_hinge_e
bpy.ops.object.mode_set(mode='OBJECT')
@@ -349,9 +349,9 @@ def fk(obj, bone_definition, base_names, options):
con.subtarget = mt.hips
# add driver
- hinge_driver_path = fk_chain.thigh_p.path_to_id() + '["hinge"]'
+ hinge_driver_path = fk_chain.thigh_p.path_from_id() + '["hinge"]'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -370,12 +370,12 @@ def fk(obj, bone_definition, base_names, options):
if "fk_layer" in options:
layer = [n == options["fk_layer"] for n in range(0, 32)]
else:
- layer = list(mt_chain.thigh_b.layer)
+ layer = list(mt_chain.thigh_b.layers)
for attr in fk_chain.attr_names:
- getattr(fk_chain, attr + "_b").layer = layer
+ getattr(fk_chain, attr + "_b").layers = layer
for attr in ex.attr_names:
- getattr(ex, attr + "_b").layer = layer
- arm.bones[foot].layer = layer
+ getattr(ex, attr + "_b").layers = layer
+ arm.bones[foot].layers = layer
bpy.ops.object.mode_set(mode='EDIT')
@@ -390,8 +390,8 @@ def deform(obj, definitions, base_names, options):
# Create upper leg bones: two bones, each half of the upper leg.
uleg1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
uleg2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
- uleg1.connected = False
- uleg2.connected = False
+ uleg1.use_connect = False
+ uleg2.use_connect = False
uleg2.parent = uleg1
center = uleg1.center
uleg1.tail = center
@@ -400,8 +400,8 @@ def deform(obj, definitions, base_names, options):
# Create lower leg bones: two bones, each half of the lower leg.
lleg1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
lleg2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
- lleg1.connected = False
- lleg2.connected = False
+ lleg1.use_connect = False
+ lleg2.use_connect = False
lleg2.parent = lleg1
center = lleg1.center
lleg1.tail = center
@@ -410,7 +410,7 @@ def deform(obj, definitions, base_names, options):
# Create a bone for the second lower leg deform bone to twist with
twist = copy_bone_simple(obj.data, lleg2.name, "MCH-leg_twist")
twist.length /= 4
- twist.connected = False
+ twist.use_connect = False
twist.parent = obj.data.edit_bones[definitions[3]]
# Create foot bone
diff --git a/release/scripts/modules/rigify/leg_quadruped.py b/release/scripts/modules/rigify/leg_quadruped.py
index c21680740bd..739a6402c4b 100644
--- a/release/scripts/modules/rigify/leg_quadruped.py
+++ b/release/scripts/modules/rigify/leg_quadruped.py
@@ -23,7 +23,7 @@ from rna_prop_ui import rna_idprop_ui_prop_get
from math import pi
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple, get_side_name, get_base_name
-from Mathutils import Vector
+from mathutils import Vector
METARIG_NAMES = "hips", "thigh", "shin", "foot", "toe"
@@ -37,30 +37,30 @@ def metarig_template():
bone.head[:] = -0.0728, -0.2427, 0.0000
bone.tail[:] = -0.0728, -0.2427, 0.2427
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bone = arm.edit_bones.new('thigh')
bone.head[:] = 0.0000, 0.0000, -0.0000
bone.tail[:] = 0.0813, -0.2109, -0.3374
bone.roll = -0.4656
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['body']
bone = arm.edit_bones.new('shin')
bone.head[:] = 0.0813, -0.2109, -0.3374
bone.tail[:] = 0.0714, -0.0043, -0.5830
bone.roll = -0.2024
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['thigh']
bone = arm.edit_bones.new('foot')
bone.head[:] = 0.0714, -0.0043, -0.5830
bone.tail[:] = 0.0929, -0.0484, -0.7652
bone.roll = -0.3766
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['shin']
bone = arm.edit_bones.new('toe')
bone.head[:] = 0.0929, -0.0484, -0.7652
bone.tail[:] = 0.1146, -0.1244, -0.7652
bone.roll = -0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['foot']
bpy.ops.object.mode_set(mode='OBJECT')
@@ -120,7 +120,7 @@ def ik(obj, bone_definition, base_names, options):
ik_chain = mt_chain.copy(to_fmt="MCH-%s.ik", base_names=base_names)
- ik_chain.thigh_e.connected = False
+ ik_chain.thigh_e.use_connect = False
ik_chain.thigh_e.parent = mt.hips_e
ik_chain.foot_e.parent = None
@@ -128,10 +128,10 @@ def ik(obj, bone_definition, base_names, options):
ik_chain.rename("toe", get_base_name(base_names[bone_definition[4]]) + "_ik" + get_side_name(base_names[bone_definition[4]]))
# keep the foot_ik as the parent
- ik_chain.toe_e.connected = False
+ ik_chain.toe_e.use_connect = False
# Foot uses pose space, not local space, for translation
- ik_chain.foot_e.local_location = False
+ ik_chain.foot_e.use_local_location = False
# must be after disconnecting the toe
ik_chain.foot_e.align_orientation(mt_chain.toe_e)
@@ -141,7 +141,7 @@ def ik(obj, bone_definition, base_names, options):
# knee rotator
knee_rotator = copy_bone_simple(arm, mt_chain.toe, "knee_rotator" + get_side_name(base_names[mt_chain.foot]), parent=True).name
- eb[knee_rotator].connected = False
+ eb[knee_rotator].use_connect = False
eb[knee_rotator].parent = eb[mt.hips]
eb[knee_rotator].head = eb[ik_chain.thigh].head
eb[knee_rotator].tail = eb[knee_rotator].head + eb[mt_chain.toe].vector
@@ -156,11 +156,11 @@ def ik(obj, bone_definition, base_names, options):
# then align it with the foot but reverse direction.
ik.foot_roll_e = copy_bone_simple(arm, mt_chain.toe, get_base_name(base_names[mt_chain.foot]) + "_roll" + get_side_name(base_names[mt_chain.foot]))
ik.foot_roll = ik.foot_roll_e.name
- ik.foot_roll_e.connected = False
+ ik.foot_roll_e.use_connect = False
ik.foot_roll_e.parent = ik_chain.foot_e
ik.foot_roll_e.head -= mt_chain.toe_e.vector.normalize() * mt_chain.foot_e.length
ik.foot_roll_e.tail = ik.foot_roll_e.head - (mt_chain.foot_e.vector.normalize() * mt_chain.toe_e.length)
- ik.foot_roll_e.align_roll(mt_chain.foot_e.matrix.rotation_part() * Vector(0.0, 0.0, -1.0))
+ ik.foot_roll_e.align_roll(mt_chain.foot_e.matrix.rotation_part() * Vector((0.0, 0.0, -1.0)))
# MCH-foot
ik.foot_roll_01_e = copy_bone_simple(arm, mt_chain.foot, "MCH-" + base_names[mt_chain.foot])
@@ -175,7 +175,7 @@ def ik(obj, bone_definition, base_names, options):
ik.foot_target_e.parent = ik.foot_roll_01_e
ik.foot_target_e.align_orientation(ik_chain.foot_e)
ik.foot_target_e.length = ik_chain.foot_e.length / 2.0
- ik.foot_target_e.connected = True
+ ik.foot_target_e.use_connect = True
# MCH-foot.02 child of MCH-foot
ik.foot_roll_02_e = copy_bone_simple(arm, mt_chain.foot, "MCH-%s_02" % base_names[mt_chain.foot])
@@ -207,13 +207,13 @@ def ik(obj, bone_definition, base_names, options):
prop["min"] = 0.0
prop["max"] = 1.0
- ik_driver_path = pb[ik_chain.foot].path_to_id() + '["ik"]'
+ ik_driver_path = pb[ik_chain.foot].path_from_id() + '["ik"]'
# simple constraining of orig bones
con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.thigh
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -225,7 +225,7 @@ def ik(obj, bone_definition, base_names, options):
con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.shin
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -237,7 +237,7 @@ def ik(obj, bone_definition, base_names, options):
con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik.foot_roll_02
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -249,7 +249,7 @@ def ik(obj, bone_definition, base_names, options):
con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.toe
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -268,7 +268,7 @@ def ik(obj, bone_definition, base_names, options):
# IK
con = ik_chain.shin_p.constraints.new('IK')
- con.chain_length = 2
+ con.chain_count = 2
con.iterations = 500
con.pole_angle = -90.0 # XXX - in deg!
con.use_tail = True
@@ -289,12 +289,12 @@ def ik(obj, bone_definition, base_names, options):
if "ik_layer" in options:
layer = [n==options["ik_layer"] for n in range(0,32)]
else:
- layer = list(mt_chain.thigh_b.layer)
+ layer = list(mt_chain.thigh_b.layers)
for attr in ik_chain.attr_names:
- obj.data.bones[getattr(ik_chain, attr)].layer = layer
+ obj.data.bones[getattr(ik_chain, attr)].layers = layer
for attr in ik.attr_names:
- obj.data.bones[getattr(ik, attr)].layer = layer
- obj.data.bones[knee_rotator].layer = layer
+ obj.data.bones[getattr(ik, attr)].layers = layer
+ obj.data.bones[knee_rotator].layers = layer
return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe
@@ -325,7 +325,7 @@ def fk(obj, bone_definition, base_names, options):
eb[hinge].length = eb[mt.hips].length / 2
# Make leg child of hinge
- eb[fk_chain.thigh].connected = False
+ eb[fk_chain.thigh].use_connect = False
eb[fk_chain.thigh].parent = eb[hinge]
@@ -369,9 +369,9 @@ def fk(obj, bone_definition, base_names, options):
prop["min"] = 0.0
prop["max"] = 1.0
- hinge_driver_path = pb[fk_chain.thigh].path_to_id() + '["hinge"]'
+ hinge_driver_path = pb[fk_chain.thigh].path_from_id() + '["hinge"]'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -396,8 +396,8 @@ def deform(obj, definitions, base_names, options):
# Create upper leg bones: two bones, each half of the upper leg.
uleg1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
uleg2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
- uleg1.connected = False
- uleg2.connected = False
+ uleg1.use_connect = False
+ uleg2.use_connect = False
uleg2.parent = uleg1
center = uleg1.center
uleg1.tail = center
@@ -406,8 +406,8 @@ def deform(obj, definitions, base_names, options):
# Create lower leg bones: two bones, each half of the lower leg.
lleg1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
lleg2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
- lleg1.connected = False
- lleg2.connected = False
+ lleg1.use_connect = False
+ lleg2.use_connect = False
lleg2.parent = lleg1
center = lleg1.center
lleg1.tail = center
@@ -416,7 +416,7 @@ def deform(obj, definitions, base_names, options):
# Create a bone for the second lower leg deform bone to twist with
twist = copy_bone_simple(obj.data, lleg2.name, "MCH-leg_twist")
twist.length /= 4
- twist.connected = False
+ twist.use_connect = False
twist.parent = obj.data.edit_bones[definitions[3]]
# Create foot bone
diff --git a/release/scripts/modules/rigify/mouth.py b/release/scripts/modules/rigify/mouth.py
index 4defd28f56a..ce232b91e7b 100644
--- a/release/scripts/modules/rigify/mouth.py
+++ b/release/scripts/modules/rigify/mouth.py
@@ -21,7 +21,7 @@
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos, pi
-from Mathutils import Vector
+from mathutils import Vector
from rigify import RigifyError
from rigify_utils import copy_bone_simple
@@ -77,7 +77,7 @@ def addget_shape_key_driver(obj, name="Key"):
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
- fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
+ fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
new = True
@@ -93,7 +93,7 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
@@ -151,8 +151,8 @@ def deform(obj, definitions, base_names, options):
eb[spread_l_2].tail = eb[definitions[5]].head
eb[spread_l_1].roll = 0
eb[spread_l_2].roll = 0
- eb[spread_l_1].connected = False
- eb[spread_l_2].connected = False
+ eb[spread_l_1].use_connect = False
+ eb[spread_l_2].use_connect = False
eb[spread_l_1].parent = eb[definitions[6]]
eb[spread_l_2].parent = eb[definitions[6]]
@@ -162,8 +162,8 @@ def deform(obj, definitions, base_names, options):
eb[spread_r_2].tail = eb[definitions[3]].head
eb[spread_r_1].roll = 0
eb[spread_r_2].roll = 0
- eb[spread_r_1].connected = False
- eb[spread_r_2].connected = False
+ eb[spread_r_1].use_connect = False
+ eb[spread_r_2].use_connect = False
eb[spread_r_1].parent = eb[definitions[2]]
eb[spread_r_2].parent = eb[definitions[2]]
@@ -171,9 +171,9 @@ def deform(obj, definitions, base_names, options):
# Jaw open bones (for driving corrective shape keys)
jopen1 = copy_bone_simple(obj.data, jaw, "MCH-"+base_names[jaw]+".track1", parent=True).name
- eb[jopen1].connected = False
+ eb[jopen1].use_connect = False
eb[jopen1].head = eb[jaw].tail
- eb[jopen1].tail = eb[jopen1].head + Vector(0, 0, eb[jaw].length/4)
+ eb[jopen1].tail = eb[jopen1].head + Vector((0, 0, eb[jaw].length/4))
jopen2 = copy_bone_simple(obj.data, jopen1, "MCH-"+base_names[jaw]+".track2").name
eb[jopen2].parent = eb[jaw]
@@ -426,8 +426,8 @@ def control(obj, definitions, base_names, options):
# Jaw open tracker
jopent = copy_bone_simple(obj.data, jaw_e.name, "MCH-"+base_names[jaw_e.name]+".track", parent=True).name
- eb[jopent].connected = False
- eb[jopent].tail = jaw_e.tail + Vector(0,0,jaw_e.length)
+ eb[jopent].use_connect = False
+ eb[jopent].tail = jaw_e.tail + Vector((0.0, 0.0, jaw_e.length))
eb[jopent].head = jaw_e.tail
bpy.ops.object.mode_set(mode='OBJECT')
@@ -448,7 +448,7 @@ def control(obj, definitions, base_names, options):
prop["min"] = 0.0
prop["max"] = 1.0
- open_driver_path = pb[lip1].path_to_id() + '["open_action"]'
+ open_driver_path = pb[lip1].path_from_id() + '["open_action"]'
# Constraints
@@ -458,7 +458,7 @@ def control(obj, definitions, base_names, options):
con.target = obj
con.subtarget = jaw
con.head_tail = 1.0
- con.original_length = bb[jopent].length
+ con.rest_length = bb[jopent].length
con.volume = 'NO_VOLUME'
# Head lips to jaw lips
@@ -545,10 +545,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
- con.minimum = 0.0
- con.maximum = 1.0
+ con.min = 0.0
+ con.max = 1.0
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -563,10 +563,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
- con.minimum = 0.0
- con.maximum = 1.0
+ con.min = 0.0
+ con.max = 1.0
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -581,10 +581,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
- con.minimum = 0.0
- con.maximum = 1.0
+ con.min = 0.0
+ con.max = 1.0
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -599,10 +599,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
- con.minimum = 0.0
- con.maximum = 1.0
+ con.min = 0.0
+ con.max = 1.0
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -617,10 +617,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
- con.minimum = 0.0
- con.maximum = 1.0
+ con.min = 0.0
+ con.max = 1.0
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -635,10 +635,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
- con.minimum = 0.0
- con.maximum = 1.0
+ con.min = 0.0
+ con.max = 1.0
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -653,10 +653,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
- con.minimum = 0.0
- con.maximum = 1.0
+ con.min = 0.0
+ con.max = 1.0
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -671,10 +671,10 @@ def control(obj, definitions, base_names, options):
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
- con.minimum = 0.0
- con.maximum = 1.0
+ con.min = 0.0
+ con.max = 1.0
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -684,15 +684,15 @@ def control(obj, definitions, base_names, options):
# Set layers
- layer = list(bb[definitions[2]].layer)
- bb[lip1].layer = layer
- bb[lip2].layer = layer
- bb[lip3].layer = layer
- bb[lip4].layer = layer
- bb[lip5].layer = layer
- bb[lip6].layer = layer
- bb[lip7].layer = layer
- bb[lip8].layer = layer
+ layer = list(bb[definitions[2]].layers)
+ bb[lip1].layers = layer
+ bb[lip2].layers = layer
+ bb[lip3].layers = layer
+ bb[lip4].layers = layer
+ bb[lip5].layers = layer
+ bb[lip6].layers = layer
+ bb[lip7].layers = layer
+ bb[lip8].layers = layer
return (None,)
@@ -717,7 +717,7 @@ def make_lip_stretch_bone(obj, name, bone1, bone2, roll_alpha):
# Create the bone, pointing from bone1 to bone2
bone_e = copy_bone_simple(obj.data, bone1, name, parent=True)
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.tail = eb[bone2].head
bone = bone_e.name
diff --git a/release/scripts/modules/rigify/neck.py b/release/scripts/modules/rigify/neck.py
new file mode 100644
index 00000000000..56717f0ebb0
--- /dev/null
+++ b/release/scripts/modules/rigify/neck.py
@@ -0,0 +1,344 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import bpy
+from rigify import RigifyError
+from rigify_utils import bone_class_instance, copy_bone_simple
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+
+
+def metarig_template():
+ # TODO:
+ ## generated by rigify.write_meta_rig
+ #bpy.ops.object.mode_set(mode='EDIT')
+ #obj = bpy.context.active_object
+ #arm = obj.data
+ #bone = arm.edit_bones.new('body')
+ #bone.head[:] = 0.0000, -0.0276, -0.1328
+ #bone.tail[:] = 0.0000, -0.0170, -0.0197
+ #bone.roll = 0.0000
+ #bone.use_connect = False
+ #bone = arm.edit_bones.new('head')
+ #bone.head[:] = 0.0000, -0.0170, -0.0197
+ #bone.tail[:] = 0.0000, 0.0726, 0.1354
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['body']
+ #bone = arm.edit_bones.new('neck.01')
+ #bone.head[:] = 0.0000, -0.0170, -0.0197
+ #bone.tail[:] = 0.0000, -0.0099, 0.0146
+ #bone.roll = 0.0000
+ #bone.use_connect = False
+ #bone.parent = arm.edit_bones['head']
+ #bone = arm.edit_bones.new('neck.02')
+ #bone.head[:] = 0.0000, -0.0099, 0.0146
+ #bone.tail[:] = 0.0000, -0.0242, 0.0514
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['neck.01']
+ #bone = arm.edit_bones.new('neck.03')
+ #bone.head[:] = 0.0000, -0.0242, 0.0514
+ #bone.tail[:] = 0.0000, -0.0417, 0.0868
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['neck.02']
+ #bone = arm.edit_bones.new('neck.04')
+ #bone.head[:] = 0.0000, -0.0417, 0.0868
+ #bone.tail[:] = 0.0000, -0.0509, 0.1190
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['neck.03']
+ #bone = arm.edit_bones.new('neck.05')
+ #bone.head[:] = 0.0000, -0.0509, 0.1190
+ #bone.tail[:] = 0.0000, -0.0537, 0.1600
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['neck.04']
+ #
+ #bpy.ops.object.mode_set(mode='OBJECT')
+ #pbone = obj.pose.bones['head']
+ #pbone['type'] = 'neck_flex'
+ pass
+
+
+def metarig_definition(obj, orig_bone_name):
+ '''
+ The bone given is neck_01, its parent is the body
+ eg.
+ body -> neck_01 -> neck_02 -> neck_03.... etc
+ '''
+ arm = obj.data
+ neck = arm.bones[orig_bone_name]
+ body = neck.parent
+
+ bone_definition = [body.name, neck.name]
+ bone_definition.extend([child.name for child in neck.children_recursive_basename])
+ return bone_definition
+
+
+def deform(obj, definitions, base_names, options):
+ for org_bone_name in definitions[1:]:
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Create deform bone.
+ bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True)
+
+ # Store name before leaving edit mode
+ bone_name = bone.name
+
+ # Leave edit mode
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Get the pose bone
+ bone = obj.pose.bones[bone_name]
+
+ # Constrain to the original bone
+ # XXX. Todo, is this needed if the bone is connected to its parent?
+ con = bone.constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_loc"
+ con.target = obj
+ con.subtarget = org_bone_name
+
+
+def main(obj, bone_definition, base_names, options):
+ from mathutils import Vector
+
+ arm = obj.data
+ eb = obj.data.edit_bones
+ bb = obj.data.bones
+ pb = obj.pose.bones
+
+ body = bone_definition[0]
+
+ # Create the neck and head control bones
+ if "head_name" in options:
+ head_name = options["head_name"]
+ else:
+ head_name = "head"
+
+ neck_name = base_names[bone_definition[1]].split(".")[0]
+
+ neck_ctrl = copy_bone_simple(arm, bone_definition[1], neck_name).name
+ head_ctrl = copy_bone_simple(arm, bone_definition[len(bone_definition)-1], head_name).name
+ eb[head_ctrl].tail += eb[neck_ctrl].head - eb[head_ctrl].head
+ eb[head_ctrl].head = eb[neck_ctrl].head
+
+ # Create hinge and socket bones
+ neck_hinge = copy_bone_simple(arm, bone_definition[0], "MCH-" + neck_name + "_hinge").name
+ head_hinge = copy_bone_simple(arm, neck_ctrl, "MCH-" + head_name + "_hinge").name
+ eb[neck_hinge].tail += eb[neck_ctrl].head - eb[neck_hinge].head
+ eb[neck_hinge].head = eb[neck_ctrl].head
+ eb[head_hinge].tail += eb[neck_ctrl].head - eb[head_hinge].head
+ eb[head_hinge].head = eb[neck_ctrl].head
+
+ neck_socket = copy_bone_simple(arm, bone_definition[1], "MCH-" + neck_name + "_socket").name
+ head_socket = copy_bone_simple(arm, bone_definition[1], "MCH-" + head_name + "_socket").name
+
+ # Parent-child relationships between the body, hinges, controls, and sockets
+ eb[neck_ctrl].parent = eb[neck_hinge]
+ eb[head_ctrl].parent = eb[head_hinge]
+
+ eb[neck_socket].parent = eb[body]
+ eb[head_socket].parent = eb[body]
+
+ # Create neck bones
+ neck = [] # neck bones
+ neck_neck = [] # bones constrained to neck control
+ neck_head = [] # bones constrained to head control
+ for i in range(1, len(bone_definition)):
+ # Create bones
+ neck_bone = copy_bone_simple(arm, bone_definition[i], base_names[bone_definition[i]]).name
+ neck_neck_bone = copy_bone_simple(arm, neck_ctrl, "MCH-" + base_names[bone_definition[i]] + ".neck").name
+ neck_head_bone = copy_bone_simple(arm, head_ctrl, "MCH-" + base_names[bone_definition[i]] + ".head").name
+
+ # Move them all to the same place
+ eb[neck_neck_bone].tail += eb[neck_bone].head - eb[neck_neck_bone].head
+ eb[neck_head_bone].tail += eb[neck_bone].head - eb[neck_neck_bone].head
+ eb[neck_neck_bone].head = eb[neck_bone].head
+ eb[neck_head_bone].head = eb[neck_bone].head
+
+ # Parent/child relationships
+ eb[neck_bone].parent = eb[neck_head_bone]
+ eb[neck_head_bone].parent = eb[neck_neck_bone]
+
+ if i > 1:
+ eb[neck_neck_bone].parent = eb[neck[i-2]]
+ else:
+ eb[neck_neck_bone].parent = eb[body]
+
+ # Add them to the lists
+ neck += [neck_bone]
+ neck_neck += [neck_neck_bone]
+ neck_head += [neck_head_bone]
+
+ # Create deformation rig
+ deform(obj, bone_definition, base_names, options)
+
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Axis locks
+ pb[neck_ctrl].lock_location = True, True, True
+ pb[head_ctrl].lock_location = True, True, True
+
+ for bone in neck:
+ pb[bone].lock_location = True, True, True
+
+ # Neck hinge
+ prop = rna_idprop_ui_prop_get(pb[neck_ctrl], "hinge", create=True)
+ pb[neck_ctrl]["hinge"] = 0.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["hard_min"] = 0.0
+ prop["hard_max"] = 1.0
+
+ con = pb[neck_hinge].constraints.new('COPY_LOCATION')
+ con.name = "socket"
+ con.target = obj
+ con.subtarget = neck_socket
+
+ con = pb[neck_hinge].constraints.new('COPY_ROTATION')
+ con.name = "hinge"
+ con.target = obj
+ con.subtarget = body
+
+ hinge_driver_path = pb[neck_ctrl].path_from_id() + '["hinge"]'
+
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = obj
+ var.targets[0].data_path = hinge_driver_path
+
+ mod = fcurve.modifiers[0]
+ mod.poly_order = 1
+ mod.coefficients[0] = 1.0
+ mod.coefficients[1] = -1.0
+
+ # Head hinge
+ prop = rna_idprop_ui_prop_get(pb[head_ctrl], "hinge", create=True)
+ pb[head_ctrl]["hinge"] = 0.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["hard_min"] = 0.0
+ prop["hard_max"] = 1.0
+
+ con = pb[head_hinge].constraints.new('COPY_LOCATION')
+ con.name = "socket"
+ con.target = obj
+ con.subtarget = head_socket
+
+ con = pb[head_hinge].constraints.new('COPY_ROTATION')
+ con.name = "hinge"
+ con.target = obj
+ con.subtarget = neck_ctrl
+
+ hinge_driver_path = pb[head_ctrl].path_from_id() + '["hinge"]'
+
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = obj
+ var.targets[0].data_path = hinge_driver_path
+
+ mod = fcurve.modifiers[0]
+ mod.poly_order = 1
+ mod.coefficients[0] = 1.0
+ mod.coefficients[1] = -1.0
+
+ # Neck rotation constraints
+ for i in range(0, len(neck_neck)):
+ con = pb[neck_neck[i]].constraints.new('COPY_ROTATION')
+ con.name = "neck rotation"
+ con.target = obj
+ con.subtarget = neck_ctrl
+ con.influence = (i+1) / len(neck_neck)
+
+
+ # Head rotation constraints/drivers
+ prop = rna_idprop_ui_prop_get(pb[head_ctrl], "extent", create=True)
+ if "extent" in options:
+ pb[head_ctrl]["extent"] = options["extent"]
+ else:
+ pb[head_ctrl]["extent"] = 0.5
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["hard_min"] = 0.0
+ prop["hard_max"] = 1.0
+
+ extent_prop_path = pb[head_ctrl].path_from_id() + '["extent"]'
+
+ for i in range(0, len(neck_head)):
+ con = pb[neck_head[i]].constraints.new('COPY_ROTATION')
+ con.name = "head rotation"
+ con.target = obj
+ con.subtarget = head_ctrl
+
+ if i < (len(neck_head)-1):
+ inf = (i+1) / len(neck_head)
+
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ var.name = "ext"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = obj
+ var.targets[0].data_path = extent_prop_path
+
+ driver.expression = "0 if ext == 0 else (((%s-1)/ext)+1)" % inf
+ else:
+ con.influence = 1.0
+
+ # Constrain original bones to the neck bones
+ for i in range(0, len(neck)):
+ con = pb[bone_definition[i+1]].constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transform"
+ con.target = obj
+ con.subtarget = neck[i]
+
+
+ # Set the controls' custom shapes to use other bones for transforms
+ pb[neck_ctrl].custom_shape_transform = pb[bone_definition[len(bone_definition)//2]]
+ pb[head_ctrl].custom_shape_transform = pb[bone_definition[len(bone_definition)-1]]
+
+
+ # last step setup layers
+ if "ex_layer" in options:
+ layer = [n==options["ex_layer"] for n in range(0,32)]
+ else:
+ layer = list(arm.bones[bone_definition[1]].layers)
+ for bone in neck:
+ bb[bone].layers = layer
+
+ layer = list(arm.bones[bone_definition[1]].layers)
+ bb[neck_ctrl].layers = layer
+ bb[head_ctrl].layers = layer
+
+
+ # no blending the result of this
+ return None
+
diff --git a/release/scripts/modules/rigify/neck_flex.py b/release/scripts/modules/rigify/neck_flex.py
index e45d128433a..7daf3d3bb4b 100644
--- a/release/scripts/modules/rigify/neck_flex.py
+++ b/release/scripts/modules/rigify/neck_flex.py
@@ -36,42 +36,42 @@ def metarig_template():
bone.head[:] = 0.0000, -0.0276, -0.1328
bone.tail[:] = 0.0000, -0.0170, -0.0197
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bone = arm.edit_bones.new('head')
bone.head[:] = 0.0000, -0.0170, -0.0197
bone.tail[:] = 0.0000, 0.0726, 0.1354
bone.roll = 0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['body']
bone = arm.edit_bones.new('neck.01')
bone.head[:] = 0.0000, -0.0170, -0.0197
bone.tail[:] = 0.0000, -0.0099, 0.0146
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['head']
bone = arm.edit_bones.new('neck.02')
bone.head[:] = 0.0000, -0.0099, 0.0146
bone.tail[:] = 0.0000, -0.0242, 0.0514
bone.roll = 0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['neck.01']
bone = arm.edit_bones.new('neck.03')
bone.head[:] = 0.0000, -0.0242, 0.0514
bone.tail[:] = 0.0000, -0.0417, 0.0868
bone.roll = 0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['neck.02']
bone = arm.edit_bones.new('neck.04')
bone.head[:] = 0.0000, -0.0417, 0.0868
bone.tail[:] = 0.0000, -0.0509, 0.1190
bone.roll = 0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['neck.03']
bone = arm.edit_bones.new('neck.05')
bone.head[:] = 0.0000, -0.0509, 0.1190
bone.tail[:] = 0.0000, -0.0537, 0.1600
bone.roll = 0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['neck.04']
bpy.ops.object.mode_set(mode='OBJECT')
@@ -125,7 +125,7 @@ def deform(obj, definitions, base_names, options):
def main(obj, bone_definition, base_names, options):
- from Mathutils import Vector
+ from mathutils import Vector
arm = obj.data
@@ -156,7 +156,7 @@ def main(obj, bone_definition, base_names, options):
# Copy the head bone and offset
ex.head_e = copy_bone_simple(arm, mt.head, "MCH-%s" % base_names[mt.head], parent=True)
- ex.head_e.connected = False
+ ex.head_e.use_connect = False
ex.head = ex.head_e.name
# offset
head_length = ex.head_e.length
@@ -165,7 +165,7 @@ def main(obj, bone_definition, base_names, options):
# Yes, use the body bone but call it a head hinge
ex.head_hinge_e = copy_bone_simple(arm, mt.body, "MCH-%s_hinge" % base_names[mt.head], parent=False)
- ex.head_hinge_e.connected = False
+ ex.head_hinge_e.use_connect = False
ex.head_hinge = ex.head_hinge_e.name
ex.head_hinge_e.head.y += head_length / 4.0
ex.head_hinge_e.tail.y += head_length / 4.0
@@ -173,10 +173,10 @@ def main(obj, bone_definition, base_names, options):
# Insert the neck socket, the head copys this loation
ex.neck_socket_e = arm.edit_bones.new("MCH-%s_socked" % neck_chain_basename)
ex.neck_socket = ex.neck_socket_e.name
- ex.neck_socket_e.connected = False
+ ex.neck_socket_e.use_connect = False
ex.neck_socket_e.parent = mt.body_e
ex.neck_socket_e.head = mt.head_e.head
- ex.neck_socket_e.tail = mt.head_e.head - Vector(0.0, neck_chain_segment_length / 2.0, 0.0)
+ ex.neck_socket_e.tail = mt.head_e.head - Vector((0.0, neck_chain_segment_length / 2.0, 0.0))
ex.neck_socket_e.roll = 0.0
@@ -195,9 +195,9 @@ def main(obj, bone_definition, base_names, options):
neck_e_parent.roll = mt.head_e.roll
orig_parent = neck_e.parent
- neck_e.connected = False
+ neck_e.use_connect = False
neck_e.parent = neck_e_parent
- neck_e_parent.connected = False
+ neck_e_parent.use_connect = False
if i == 0:
neck_e_parent.parent = mt.body_e
@@ -237,9 +237,9 @@ def main(obj, bone_definition, base_names, options):
con.subtarget = mt.body
# add driver
- hinge_driver_path = ex.head_ctrl_p.path_to_id() + '["hinge"]'
+ hinge_driver_path = ex.head_ctrl_p.path_from_id() + '["hinge"]'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -254,15 +254,15 @@ def main(obj, bone_definition, base_names, options):
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
- head_driver_path = ex.head_ctrl_p.path_to_id()
+ head_driver_path = ex.head_ctrl_p.path_from_id()
target_names = [("b%.2d" % (i + 1)) for i in range(len(neck_chain))]
ex.head_ctrl_p["bend_tot"] = 0.0
- fcurve = ex.head_ctrl_p.driver_add('["bend_tot"]', 0)
+ fcurve = ex.head_ctrl_p.driver_add('["bend_tot"]')
driver = fcurve.driver
driver.type = 'SUM'
- fcurve.modifiers.remove(0) # grr dont need a modifier
+ fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
for i in range(len(neck_chain)):
var = driver.variables.new()
@@ -296,12 +296,12 @@ def main(obj, bone_definition, base_names, options):
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'SCRIPTED'
driver.expression = "bend/bend_tot"
- fcurve.modifiers.remove(0) # grr dont need a modifier
+ fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
# add target
@@ -334,14 +334,14 @@ def main(obj, bone_definition, base_names, options):
if "ex_layer" in options:
layer = [n == options["ex_layer"] for n in range(0, 32)]
else:
- layer = list(arm.bones[bone_definition[1]].layer)
+ layer = list(arm.bones[bone_definition[1]].layers)
for attr in ex_chain.attr_names:
- getattr(ex_chain, attr + "_b").layer = layer
+ getattr(ex_chain, attr + "_b").layers = layer
for attr in ex.attr_names:
- getattr(ex, attr + "_b").layer = layer
+ getattr(ex, attr + "_b").layers = layer
- layer = list(arm.bones[bone_definition[1]].layer)
- ex.head_ctrl_b.layer = layer
+ layer = list(arm.bones[bone_definition[1]].layers)
+ ex.head_ctrl_b.layers = layer
# no blending the result of this
diff --git a/release/scripts/modules/rigify/palm_curl.py b/release/scripts/modules/rigify/palm_curl.py
index 6626438709d..c063e2b31c9 100644
--- a/release/scripts/modules/rigify/palm_curl.py
+++ b/release/scripts/modules/rigify/palm_curl.py
@@ -35,42 +35,42 @@ def metarig_template():
bone.head[:] = 0.0004, -0.0629, 0.0000
bone.tail[:] = 0.0021, -0.0209, 0.0000
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bone = arm.edit_bones.new('palm.03')
bone.head[:] = -0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0025, 0.0644, -0.0065
bone.roll = -3.1396
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('palm.02')
bone.head[:] = 0.0252, -0.0000, 0.0000
bone.tail[:] = 0.0324, 0.0627, -0.0065
bone.roll = -3.1357
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('palm.01')
bone.head[:] = 0.0504, 0.0000, 0.0000
bone.tail[:] = 0.0703, 0.0508, -0.0065
bone.roll = -3.1190
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('palm.04')
bone.head[:] = -0.0252, 0.0000, 0.0000
bone.tail[:] = -0.0286, 0.0606, -0.0065
bone.roll = 3.1386
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('palm.05')
bone.head[:] = -0.0504, 0.0000, 0.0000
bone.tail[:] = -0.0669, 0.0534, -0.0065
bone.roll = 3.1239
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('thumb')
bone.head[:] = 0.0682, -0.0148, 0.0000
bone.tail[:] = 0.1063, 0.0242, -0.0065
bone.roll = -3.0929
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bpy.ops.object.mode_set(mode='OBJECT')
@@ -156,7 +156,7 @@ def main(obj, bone_definition, base_names, options):
driver_fcurves = pinky_pbone.driver_add("rotation_euler")
- controller_path = control_pbone.path_to_id()
+ controller_path = control_pbone.path_from_id()
# add custom prop
control_pbone["spread"] = 0.0
@@ -194,7 +194,7 @@ def main(obj, bone_definition, base_names, options):
driver.expression = "(1.0-cos(x))-s"
for fcurve in driver_fcurves:
- fcurve.modifiers.remove(0) # grr dont need a modifier
+ fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
var = driver.variables.new()
var.name = "x"
@@ -248,13 +248,13 @@ def main(obj, bone_definition, base_names, options):
# NOTE: the direction of the Z rotation depends on which side the palm is on.
# we could do a simple side-of-x test but better to work out the direction
# the hand is facing.
- from Mathutils import Vector
+ from mathutils import Vector
from math import degrees
child_pbone_01 = obj.pose.bones[children[0]].bone
child_pbone_02 = obj.pose.bones[children[1]].bone
rel_vec = child_pbone_01.head - child_pbone_02.head
- x_vec = child_pbone_01.matrix.rotation_part() * Vector(1.0, 0.0, 0.0)
+ x_vec = child_pbone_01.matrix.rotation_part() * Vector((1.0, 0.0, 0.0))
return degrees(rel_vec.angle(x_vec)) > 90.0
@@ -263,7 +263,7 @@ def main(obj, bone_definition, base_names, options):
# last step setup layers
- arm.bones[control_name].layer = list(arm.bones[bone_definition[1]].layer)
+ arm.bones[control_name].layers = list(arm.bones[bone_definition[1]].layers)
# no blending the result of this
diff --git a/release/scripts/modules/rigify/shape_key_control.py b/release/scripts/modules/rigify/shape_key_control.py
index fd0e900a7b5..1bfca60255d 100644
--- a/release/scripts/modules/rigify/shape_key_control.py
+++ b/release/scripts/modules/rigify/shape_key_control.py
@@ -57,7 +57,7 @@ def addget_shape_key_driver(obj, name="Key"):
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
- fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
+ fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
new = True
@@ -74,7 +74,7 @@ def metarig_template():
#bone.head[:] = 0.0000, 0.0000, 0.0000
#bone.tail[:] = 0.0000, 0.0000, 1.0000
#bone.roll = 0.0000
- #bone.connected = False
+ #bone.use_connect = False
#
#bpy.ops.object.mode_set(mode='OBJECT')
#pbone = obj.pose.bones['Bone']
diff --git a/release/scripts/modules/rigify/shape_key_distance.py b/release/scripts/modules/rigify/shape_key_distance.py
index 68501ac829b..7d69517216f 100644
--- a/release/scripts/modules/rigify/shape_key_distance.py
+++ b/release/scripts/modules/rigify/shape_key_distance.py
@@ -54,7 +54,7 @@ def addget_shape_key_driver(obj, name="Key"):
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
- fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
+ fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
return fcurve
@@ -71,7 +71,7 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
diff --git a/release/scripts/modules/rigify/shape_key_rotdiff.py b/release/scripts/modules/rigify/shape_key_rotdiff.py
index 2c30d95e666..dfc3b914a6a 100644
--- a/release/scripts/modules/rigify/shape_key_rotdiff.py
+++ b/release/scripts/modules/rigify/shape_key_rotdiff.py
@@ -54,7 +54,7 @@ def addget_shape_key_driver(obj, name="Key"):
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
- fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
+ fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
return fcurve
@@ -71,7 +71,7 @@ def metarig_template():
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
diff --git a/release/scripts/modules/rigify/spine_pivot_flex.py b/release/scripts/modules/rigify/spine_pivot_flex.py
index 422c632e95a..7782380eedb 100644
--- a/release/scripts/modules/rigify/spine_pivot_flex.py
+++ b/release/scripts/modules/rigify/spine_pivot_flex.py
@@ -36,54 +36,54 @@ def metarig_template():
bone.head[:] = 0.0000, -0.0306, 0.1039
bone.tail[:] = 0.0000, -0.0306, -0.0159
bone.roll = 0.0000
- bone.connected = False
+ bone.use_connect = False
bone = arm.edit_bones.new('rib_cage')
bone.head[:] = 0.0000, -0.0306, 0.1039
bone.tail[:] = 0.0000, -0.0306, 0.2236
bone.roll = -0.0000
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['pelvis']
bone = arm.edit_bones.new('spine.01')
bone.head[:] = 0.0000, 0.0000, -0.0000
bone.tail[:] = 0.0000, -0.0306, 0.1039
bone.roll = -0.0000
- bone.connected = False
+ bone.use_connect = False
bone.parent = arm.edit_bones['rib_cage']
bone = arm.edit_bones.new('spine.02')
bone.head[:] = 0.0000, -0.0306, 0.1039
bone.tail[:] = -0.0000, -0.0398, 0.2045
bone.roll = -0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['spine.01']
bone = arm.edit_bones.new('spine.03')
bone.head[:] = -0.0000, -0.0398, 0.2045
bone.tail[:] = -0.0000, -0.0094, 0.2893
bone.roll = -0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['spine.02']
bone = arm.edit_bones.new('spine.04')
bone.head[:] = -0.0000, -0.0094, 0.2893
bone.tail[:] = -0.0000, 0.0335, 0.3595
bone.roll = -0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['spine.03']
bone = arm.edit_bones.new('spine.05')
bone.head[:] = -0.0000, 0.0335, 0.3595
bone.tail[:] = -0.0000, 0.0555, 0.4327
bone.roll = -0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['spine.04']
bone = arm.edit_bones.new('spine.06')
bone.head[:] = -0.0000, 0.0555, 0.4327
bone.tail[:] = -0.0000, 0.0440, 0.5207
bone.roll = -0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['spine.05']
bone = arm.edit_bones.new('spine.07')
bone.head[:] = -0.0000, 0.0440, 0.5207
bone.tail[:] = -0.0000, 0.0021, 0.5992
bone.roll = -0.0000
- bone.connected = True
+ bone.use_connect = True
bone.parent = arm.edit_bones['spine.06']
bpy.ops.object.mode_set(mode='OBJECT')
@@ -147,7 +147,7 @@ def deform(obj, definitions, base_names, options):
def main(obj, bone_definition, base_names, options):
- from Mathutils import Vector, RotationMatrix
+ from mathutils import Vector, Matrix
from math import radians, pi
arm = obj.data
@@ -172,17 +172,17 @@ def main(obj, bone_definition, base_names, options):
ex.pelvis_copy_e = copy_bone_simple(arm, mt.pelvis, base_names[mt.pelvis]) # no parent
ex.pelvis_copy = ex.pelvis_copy_e.name
- ex.pelvis_copy_e.local_location = False
+ ex.pelvis_copy_e.use_local_location = False
# copy the pelvis, offset to make MCH-spine_rotate and MCH-ribcage_hinge
ex.ribcage_hinge_e = copy_bone_simple(arm, mt.pelvis, "MCH-%s_hinge" % base_names[mt.ribcage])
ex.ribcage_hinge = ex.ribcage_hinge_e.name
- ex.ribcage_hinge_e.translate(Vector(0.0, spine_chain_segment_length / 4.0, 0.0))
+ ex.ribcage_hinge_e.translate(Vector((0.0, spine_chain_segment_length / 4.0, 0.0)))
ex.spine_rotate_e = copy_bone_simple(arm, mt.ribcage, "MCH-%s_rotate" % spine_chain_basename)
ex.spine_rotate = ex.spine_rotate_e.name
- ex.spine_rotate_e.translate(Vector(0.0, spine_chain_segment_length / 2.0, 0.0))
- ex.spine_rotate_e.connected = False
+ ex.spine_rotate_e.translate(Vector((0.0, spine_chain_segment_length / 2.0, 0.0)))
+ ex.spine_rotate_e.use_connect = False
ex.spine_rotate_e.parent = ex.pelvis_copy_e
@@ -191,7 +191,7 @@ def main(obj, bone_definition, base_names, options):
ex.ribcage_copy_e = copy_bone_simple(arm, mt.ribcage, base_names[mt.ribcage])
ex.ribcage_copy = ex.ribcage_copy_e.name
- ex.ribcage_copy_e.connected = False
+ ex.ribcage_copy_e.use_connect = False
ex.ribcage_copy_e.parent = ex.ribcage_hinge_e
spine_chain = [child.name for child in spine_chain]
@@ -219,7 +219,7 @@ def main(obj, bone_definition, base_names, options):
ebone = copy_bone_simple(arm, child_name, "MCH-rev_%s" % child_name_orig)
setattr(rv_chain, attr, ebone.name)
- ebone.connected = False
+ ebone.use_connect = False
mt_chain.update()
ex_chain.update()
@@ -230,13 +230,13 @@ def main(obj, bone_definition, base_names, options):
attr = ex_chain.attr_names[i] + "_e"
ebone = getattr(ex_chain, attr)
if i == 0:
- ebone.connected = False
+ ebone.use_connect = False
ebone.parent = ex.pelvis_copy_e
else:
attr_parent = ex_chain.attr_names[i - 1] + "_e"
ebone.parent = getattr(ex_chain, attr_parent)
- # intentional! get the parent from the other paralelle chain member
+ # intentional! get the parent from the other parallel chain member
getattr(rv_chain, attr).parent = ebone
@@ -255,16 +255,16 @@ def main(obj, bone_definition, base_names, options):
spine_e = getattr(ex_chain, ex_chain.attr_names[i] + "_e")
orig_parent = spine_e.parent
- spine_e.connected = False
+ spine_e.use_connect = False
spine_e.parent = spine_e_parent
- spine_e_parent.connected = False
+ spine_e_parent.use_connect = False
spine_e_parent.parent = orig_parent
# Rotate the rev chain 180 about the by the first bones center point
pivot = (rv_chain.spine_01_e.head + rv_chain.spine_01_e.tail) * 0.5
- matrix = RotationMatrix(radians(180), 3, 'X')
+ matrix = Matrix.Rotation(radians(180), 3, 'X')
for i, attr in enumerate(rv_chain.attr_names): # similar to neck
spine_e = getattr(rv_chain, attr + "_e")
# use the first bone as the pivot
@@ -294,14 +294,14 @@ def main(obj, bone_definition, base_names, options):
con.subtarget = ex.pelvis_copy
# add driver
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
- var.targets[0].data_path = ex.ribcage_copy_p.path_to_id() + '["hinge"]'
+ var.targets[0].data_path = ex.ribcage_copy_p.path_from_id() + '["hinge"]'
mod = fcurve.modifiers[0]
mod.poly_order = 1
@@ -347,13 +347,13 @@ def main(obj, bone_definition, base_names, options):
# Constrain 'inbetween' bones
target_names = [("b%.2d" % (i + 1)) for i in range(spine_chain_len - 1)]
- rib_driver_path = ex.ribcage_copy_p.path_to_id()
+ rib_driver_path = ex.ribcage_copy_p.path_from_id()
ex.ribcage_copy_p["bend_tot"] = 0.0
- fcurve = ex.ribcage_copy_p.driver_add('["bend_tot"]', 0)
+ fcurve = ex.ribcage_copy_p.driver_add('["bend_tot"]')
driver = fcurve.driver
driver.type = 'SUM'
- fcurve.modifiers.remove(0) # grr dont need a modifier
+ fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
for i in range(spine_chain_len - 1):
var = driver.variables.new()
@@ -385,12 +385,12 @@ def main(obj, bone_definition, base_names, options):
del spine_p
# add driver
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'SCRIPTED'
driver.expression = "bend/bend_tot"
- fcurve.modifiers.remove(0) # grr dont need a modifier
+ fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
# add target
@@ -440,7 +440,7 @@ def main(obj, bone_definition, base_names, options):
if i == spine_chain_len:
con.head_tail = 1.0
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
@@ -465,17 +465,17 @@ def main(obj, bone_definition, base_names, options):
if "ex_layer" in options:
layer = [n == options["ex_layer"] for n in range(0, 32)]
else:
- layer = list(arm.bones[bone_definition[1]].layer)
+ layer = list(arm.bones[bone_definition[1]].layers)
for attr in ex.attr_names:
- getattr(ex, attr + "_b").layer = layer
+ getattr(ex, attr + "_b").layers = layer
for attr in ex_chain.attr_names:
- getattr(ex_chain, attr + "_b").layer = layer
+ getattr(ex_chain, attr + "_b").layers = layer
for attr in rv_chain.attr_names:
- getattr(rv_chain, attr + "_b").layer = layer
+ getattr(rv_chain, attr + "_b").layers = layer
- layer = list(arm.bones[bone_definition[1]].layer)
- arm.bones[ex.pelvis_copy].layer = layer
- arm.bones[ex.ribcage_copy].layer = layer
+ layer = list(arm.bones[bone_definition[1]].layers)
+ arm.bones[ex.pelvis_copy].layers = layer
+ arm.bones[ex.ribcage_copy].layers = layer
# no support for blending chains
return None
diff --git a/release/scripts/modules/rigify/stretch.py b/release/scripts/modules/rigify/stretch.py
index 1c3d317b4b1..6a498e5aa29 100644
--- a/release/scripts/modules/rigify/stretch.py
+++ b/release/scripts/modules/rigify/stretch.py
@@ -35,7 +35,7 @@ RIG_TYPE = "stretch"
# bone.head[:] = 0.0000, 0.0000, 0.0000
# bone.tail[:] = 0.0000, 0.0000, 1.0000
# bone.roll = 0.0000
-# bone.connected = False
+# bone.use_connect = False
#
# bpy.ops.object.mode_set(mode='OBJECT')
# pbone = obj.pose.bones['Bone']
@@ -84,7 +84,7 @@ def main(obj, bone_definition, base_names, options):
mbone2 = "ORG-" + options["to"]
bone_e = copy_bone_simple(obj.data, mbone1, "DEF-%s" % base_names[bone_definition[0]])
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = eb[mbone2].head
bone = bone_e.name
@@ -100,7 +100,7 @@ def main(obj, bone_definition, base_names, options):
con = pb[bone].constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = mbone2
- con.original_length = bb[bone].length
+ con.rest_length = bb[bone].length
if preserve_volume:
con.volume = 'VOLUME_XZX'
else:
diff --git a/release/scripts/modules/rigify/stretch_twist.py b/release/scripts/modules/rigify/stretch_twist.py
index 66719d80d42..07ce031967f 100644
--- a/release/scripts/modules/rigify/stretch_twist.py
+++ b/release/scripts/modules/rigify/stretch_twist.py
@@ -35,7 +35,7 @@ RIG_TYPE = "stretch_twist"
# bone.head[:] = 0.0000, 0.0000, 0.0000
# bone.tail[:] = 0.0000, 0.0000, 1.0000
# bone.roll = 0.0000
-# bone.connected = False
+# bone.use_connect = False
#
# bpy.ops.object.mode_set(mode='OBJECT')
# pbone = obj.pose.bones['Bone']
@@ -86,20 +86,20 @@ def main(obj, bone_definition, base_names, options):
mbone2 = "ORG-" + options["to"]
bone_e = copy_bone_simple(obj.data, mbone1, "MCH-%s" % base_names[bone_definition[0]])
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.parent = None
bone_e.head = (eb[mbone1].head + eb[mbone2].head) / 2
bone_e.tail = (bone_e.head[0], bone_e.head[1], bone_e.head[2]+0.1)
mid_bone = bone_e.name
bone_e = copy_bone_simple(obj.data, mbone1, "DEF-%s.01" % base_names[bone_definition[0]])
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = eb[mid_bone].head
bone1 = bone_e.name
bone_e = copy_bone_simple(obj.data, mbone2, "DEF-%s.02" % base_names[bone_definition[0]])
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.parent = eb[mbone2]
bone_e.tail = eb[mid_bone].head
bone2 = bone_e.name
@@ -128,7 +128,7 @@ def main(obj, bone_definition, base_names, options):
con = pb[bone1].constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = mid_bone
- con.original_length = bb[bone1].length
+ con.rest_length = bb[bone1].length
if preserve_volume:
con.volume = 'VOLUME_XZX'
else:
@@ -142,7 +142,7 @@ def main(obj, bone_definition, base_names, options):
con = pb[bone2].constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = mid_bone
- con.original_length = bb[bone2].length
+ con.rest_length = bb[bone2].length
if preserve_volume:
con.volume = 'VOLUME_XZX'
else:
diff --git a/release/scripts/modules/rigify/tail_control.py b/release/scripts/modules/rigify/tail_control.py
index c0addf97a52..50a9bb236da 100644
--- a/release/scripts/modules/rigify/tail_control.py
+++ b/release/scripts/modules/rigify/tail_control.py
@@ -12,7 +12,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
@@ -22,7 +22,7 @@ import bpy
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple
from rna_prop_ui import rna_idprop_ui_prop_get
-from Mathutils import Vector, RotationMatrix
+from mathutils import Vector, Matrix
from math import radians, pi
# not used, defined for completeness
@@ -40,7 +40,7 @@ def metarig_template():
#bone.head[:] = 0.0000, -0.0306, 0.1039
#bone.tail[:] = 0.0000, -0.0306, -0.0159
#bone.roll = 0.0000
- #bone.connected = False
+ #bone.use_connect = False
#bpy.ops.object.mode_set(mode='OBJECT')
#pbone = obj.pose.bones['tail.01']
@@ -85,9 +85,9 @@ def main(obj, bone_definitions, base_names, options):
for bone_def in bone_definitions:
bone = copy_bone_simple(arm, bone_def, base_names[bone_def], parent=True).name
if i == 1: # Don't change parent of first tail bone
- eb[bone].connected = False
+ eb[bone].use_connect = False
eb[bone].parent = eb[hinge2]
- eb[bone].local_location = False
+ eb[bone].use_local_location = False
i = 1
bones += [bone]
@@ -133,9 +133,9 @@ def main(obj, bone_definitions, base_names, options):
con_h.subtarget = hinge1
# Add drivers
- bone_path = pb[bones[0]].path_to_id()
+ bone_path = pb[bones[0]].path_from_id()
- driver_fcurve = con_f.driver_add("influence", 0)
+ driver_fcurve = con_f.driver_add("influence")
driver = driver_fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
@@ -148,7 +148,7 @@ def main(obj, bone_definitions, base_names, options):
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
- driver_fcurve = con_h.driver_add("influence", 0)
+ driver_fcurve = con_h.driver_add("influence")
driver = driver_fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
diff --git a/release/scripts/modules/rigify/tongue.py b/release/scripts/modules/rigify/tongue.py
new file mode 100644
index 00000000000..36c4316adc5
--- /dev/null
+++ b/release/scripts/modules/rigify/tongue.py
@@ -0,0 +1,361 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import bpy
+from rigify import RigifyError
+from rigify_utils import bone_class_instance, copy_bone_simple
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+# not used, defined for completeness
+METARIG_NAMES = ("body", "head")
+
+
+def metarig_template():
+ # TODO:
+ ## generated by rigify.write_meta_rig
+ #bpy.ops.object.mode_set(mode='EDIT')
+ #obj = bpy.context.active_object
+ #arm = obj.data
+ #bone = arm.edit_bones.new('body')
+ #bone.head[:] = 0.0000, -0.0276, -0.1328
+ #bone.tail[:] = 0.0000, -0.0170, -0.0197
+ #bone.roll = 0.0000
+ #bone.use_connect = False
+ #bone = arm.edit_bones.new('head')
+ #bone.head[:] = 0.0000, -0.0170, -0.0197
+ #bone.tail[:] = 0.0000, 0.0726, 0.1354
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['body']
+ #bone = arm.edit_bones.new('neck.01')
+ #bone.head[:] = 0.0000, -0.0170, -0.0197
+ #bone.tail[:] = 0.0000, -0.0099, 0.0146
+ #bone.roll = 0.0000
+ #bone.use_connect = False
+ #bone.parent = arm.edit_bones['head']
+ #bone = arm.edit_bones.new('neck.02')
+ #bone.head[:] = 0.0000, -0.0099, 0.0146
+ #bone.tail[:] = 0.0000, -0.0242, 0.0514
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['neck.01']
+ #bone = arm.edit_bones.new('neck.03')
+ #bone.head[:] = 0.0000, -0.0242, 0.0514
+ #bone.tail[:] = 0.0000, -0.0417, 0.0868
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['neck.02']
+ #bone = arm.edit_bones.new('neck.04')
+ #bone.head[:] = 0.0000, -0.0417, 0.0868
+ #bone.tail[:] = 0.0000, -0.0509, 0.1190
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['neck.03']
+ #bone = arm.edit_bones.new('neck.05')
+ #bone.head[:] = 0.0000, -0.0509, 0.1190
+ #bone.tail[:] = 0.0000, -0.0537, 0.1600
+ #bone.roll = 0.0000
+ #bone.use_connect = True
+ #bone.parent = arm.edit_bones['neck.04']
+ #
+ #bpy.ops.object.mode_set(mode='OBJECT')
+ #pbone = obj.pose.bones['head']
+ #pbone['type'] = 'neck_flex'
+ pass
+
+
+def metarig_definition(obj, orig_bone_name):
+ '''
+ The bone given is the tongue control, its parent is the body,
+ # its only child the first of a chain with matching basenames.
+ eg.
+ body -> tongue_control -> tongue_01 -> tongue_02 -> tongue_03.... etc
+ '''
+ arm = obj.data
+ tongue = arm.bones[orig_bone_name]
+ body = tongue.parent
+
+ children = tongue.children
+ if len(children) != 1:
+ raise RigifyError("expected the tongue bone '%s' to have only 1 child." % orig_bone_name)
+
+ child = children[0]
+ bone_definition = [body.name, tongue.name, child.name]
+ bone_definition.extend([child.name for child in child.children_recursive_basename])
+ return bone_definition
+
+
+def deform(obj, definitions, base_names, options):
+ for org_bone_name in definitions[2:]:
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Create deform bone.
+ bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True)
+
+ # Store name before leaving edit mode
+ bone_name = bone.name
+
+ # Leave edit mode
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Get the pose bone
+ bone = obj.pose.bones[bone_name]
+
+ # Constrain to the original bone
+ # XXX. Todo, is this needed if the bone is connected to its parent?
+ con = bone.constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_loc"
+ con.target = obj
+ con.subtarget = org_bone_name
+
+
+# TODO: rename all of the head/neck references to tongue
+def main(obj, bone_definition, base_names, options):
+ from mathutils import Vector
+
+ arm = obj.data
+
+ # Initialize container classes for convenience
+ mt = bone_class_instance(obj, ["body", "head"]) # meta
+ mt.body = bone_definition[0]
+ mt.head = bone_definition[1]
+ mt.update()
+
+ neck_chain = bone_definition[2:]
+
+ mt_chain = bone_class_instance(obj, [("neck_%.2d" % (i + 1)) for i in range(len(neck_chain))]) # 99 bones enough eh?
+ for i, attr in enumerate(mt_chain.attr_names):
+ setattr(mt_chain, attr, neck_chain[i])
+ mt_chain.update()
+
+ neck_chain_basename = base_names[mt_chain.neck_01_e.name].split(".")[0]
+ neck_chain_segment_length = mt_chain.neck_01_e.length
+
+ ex = bone_class_instance(obj, ["head", "head_hinge", "neck_socket", "head_ctrl"]) # hinge & extras
+
+ # Add the head hinge at the bodys location, becomes the parent of the original head
+
+ # apply everything to this copy of the chain
+ ex_chain = mt_chain.copy(base_names=base_names)
+ ex_chain.neck_01_e.parent = mt_chain.neck_01_e.parent
+
+
+ # Copy the head bone and offset
+ ex.head_e = copy_bone_simple(arm, mt.head, "MCH-%s" % base_names[mt.head], parent=True)
+ ex.head_e.use_connect = False
+ ex.head = ex.head_e.name
+ # offset
+ head_length = ex.head_e.length
+ ex.head_e.head.y += head_length / 2.0
+ ex.head_e.tail.y += head_length / 2.0
+
+ # Yes, use the body bone but call it a head hinge
+ ex.head_hinge_e = copy_bone_simple(arm, mt.body, "MCH-%s_hinge" % base_names[mt.head], parent=False)
+ ex.head_hinge_e.use_connect = False
+ ex.head_hinge = ex.head_hinge_e.name
+ ex.head_hinge_e.head.y += head_length / 4.0
+ ex.head_hinge_e.tail.y += head_length / 4.0
+
+ # Insert the neck socket, the head copys this loation
+ ex.neck_socket_e = arm.edit_bones.new("MCH-%s_socked" % neck_chain_basename)
+ ex.neck_socket = ex.neck_socket_e.name
+ ex.neck_socket_e.use_connect = False
+ ex.neck_socket_e.parent = mt.body_e
+ ex.neck_socket_e.head = mt.head_e.head
+ ex.neck_socket_e.tail = mt.head_e.head - Vector((0.0, neck_chain_segment_length / 2.0, 0.0))
+ ex.neck_socket_e.roll = 0.0
+
+
+ # copy of the head for controling
+ ex.head_ctrl_e = copy_bone_simple(arm, mt.head, base_names[mt.head])
+ ex.head_ctrl = ex.head_ctrl_e.name
+ ex.head_ctrl_e.parent = ex.head_hinge_e
+
+ for i, attr in enumerate(ex_chain.attr_names):
+ neck_e = getattr(ex_chain, attr + "_e")
+
+ # dont store parent names, re-reference as each chain bones parent.
+ neck_e_parent = arm.edit_bones.new("MCH-rot_%s" % base_names[getattr(mt_chain, attr)])
+ neck_e_parent.head = neck_e.head
+ neck_e_parent.tail = neck_e.head + (mt.head_e.vector.normalize() * neck_chain_segment_length / 2.0)
+ neck_e_parent.roll = mt.head_e.roll
+
+ orig_parent = neck_e.parent
+ neck_e.use_connect = False
+ neck_e.parent = neck_e_parent
+ neck_e_parent.use_connect = False
+
+ if i == 0:
+ neck_e_parent.parent = mt.body_e
+ else:
+ neck_e_parent.parent = orig_parent
+
+ deform(obj, bone_definition, base_names, options)
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ mt.update()
+ mt_chain.update()
+ ex_chain.update()
+ ex.update()
+
+ # Axis locks
+ ex.head_ctrl_p.lock_location = True, True, True
+ ex.head_ctrl_p.lock_scale = True, False, True
+
+ # Simple one off constraints, no drivers
+ con = ex.head_ctrl_p.constraints.new('COPY_LOCATION')
+ con.target = obj
+ con.subtarget = ex.neck_socket
+
+ con = ex.head_p.constraints.new('COPY_ROTATION')
+ con.target = obj
+ con.subtarget = ex.head_ctrl
+
+ # driven hinge
+ prop = rna_idprop_ui_prop_get(ex.head_ctrl_p, "hinge", create=True)
+ ex.head_ctrl_p["hinge"] = 0.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+
+ con = ex.head_hinge_p.constraints.new('COPY_ROTATION')
+ con.name = "hinge"
+ con.target = obj
+ con.subtarget = mt.body
+
+ # add driver
+ hinge_driver_path = ex.head_ctrl_p.path_to_id() + '["hinge"]'
+
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = obj
+ var.targets[0].data_path = hinge_driver_path
+
+ #mod = fcurve_driver.modifiers.new('GENERATOR')
+ mod = fcurve.modifiers[0]
+ mod.poly_order = 1
+ mod.coefficients[0] = 1.0
+ mod.coefficients[1] = -1.0
+
+ head_driver_path = ex.head_ctrl_p.path_to_id()
+
+ target_names = [("b%.2d" % (i + 1)) for i in range(len(neck_chain))]
+
+ ex.head_ctrl_p["bend_tot"] = 0.0
+ fcurve = ex.head_ctrl_p.driver_add('["bend_tot"]')
+ driver = fcurve.driver
+ driver.type = 'SUM'
+ fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
+
+ for i in range(len(neck_chain)):
+ var = driver.variables.new()
+ var.name = target_names[i]
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = obj
+ var.targets[0].data_path = head_driver_path + ('["bend_%.2d"]' % (i + 1))
+
+
+ for i, attr in enumerate(ex_chain.attr_names):
+ neck_p = getattr(ex_chain, attr + "_p")
+ neck_p.lock_location = True, True, True
+ neck_p.lock_location = True, True, True
+ neck_p.lock_rotations_4d = True
+
+ # Add bend prop
+ prop_name = "bend_%.2d" % (i + 1)
+ prop = rna_idprop_ui_prop_get(ex.head_ctrl_p, prop_name, create=True)
+ ex.head_ctrl_p[prop_name] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+
+ # add parent constraint
+ neck_p_parent = neck_p.parent
+
+ # add constraints
+ if i == 0:
+ con = neck_p.constraints.new('COPY_SCALE')
+ con.name = "Copy Scale"
+ con.target = obj
+ con.subtarget = ex.head_ctrl
+ con.owner_space = 'LOCAL'
+ con.target_space = 'LOCAL'
+
+ con = neck_p_parent.constraints.new('COPY_ROTATION')
+ con.name = "Copy Rotation"
+ con.target = obj
+ con.subtarget = ex.head
+ con.owner_space = 'LOCAL'
+ con.target_space = 'LOCAL'
+
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ driver.type = 'SCRIPTED'
+ driver.expression = "bend/bend_tot"
+
+ fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
+
+
+ # add target
+ var = driver.variables.new()
+ var.name = "bend_tot"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = obj
+ var.targets[0].data_path = head_driver_path + ('["bend_tot"]')
+
+ var = driver.variables.new()
+ var.name = "bend"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = obj
+ var.targets[0].data_path = head_driver_path + ('["%s"]' % prop_name)
+
+
+ # finally constrain the original bone to this one
+ orig_neck_p = getattr(mt_chain, attr + "_p")
+ con = orig_neck_p.constraints.new('COPY_TRANSFORMS')
+ con.target = obj
+ con.subtarget = neck_p.name
+
+
+ # Set the head control's custom shape to use the last
+ # org neck bone for its transform
+ ex.head_ctrl_p.custom_shape_transform = obj.pose.bones[bone_definition[len(bone_definition)-1]]
+
+
+ # last step setup layers
+ if "ex_layer" in options:
+ layer = [n==options["ex_layer"] for n in range(0,32)]
+ else:
+ layer = list(arm.bones[bone_definition[1]].layers)
+ for attr in ex_chain.attr_names:
+ getattr(ex_chain, attr + "_b").layers = layer
+ for attr in ex.attr_names:
+ getattr(ex, attr + "_b").layers = layer
+
+ layer = list(arm.bones[bone_definition[1]].layers)
+ ex.head_ctrl_b.layers = layer
+
+
+ # no blending the result of this
+ return None
+
diff --git a/release/scripts/modules/rigify/track_dual.py b/release/scripts/modules/rigify/track_dual.py
index 38c2a86ab32..f9c48a3bfcb 100644
--- a/release/scripts/modules/rigify/track_dual.py
+++ b/release/scripts/modules/rigify/track_dual.py
@@ -35,7 +35,7 @@ RIG_TYPE = "track_dual"
# bone.head[:] = 0.0000, 0.0000, 0.0000
# bone.tail[:] = 0.0000, 0.0000, 1.0000
# bone.roll = 0.0000
-# bone.connected = False
+# bone.use_connect = False
#
# bpy.ops.object.mode_set(mode='OBJECT')
# pbone = obj.pose.bones['Bone']
@@ -76,13 +76,13 @@ def main(obj, bone_definition, base_names, options):
mbone2 = "ORG-" + options["to"]
bone_e = copy_bone_simple(obj.data, mbone1, "DEF-%s.01" % base_names[bone_definition[0]])
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = (eb[mbone1].head + eb[mbone2].head) / 2
bone1 = bone_e.name
bone_e = copy_bone_simple(obj.data, mbone2, "DEF-%s.02" % base_names[bone_definition[0]])
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = (eb[mbone1].head + eb[mbone2].head) / 2
bone2 = bone_e.name
diff --git a/release/scripts/modules/rigify/track_reverse.py b/release/scripts/modules/rigify/track_reverse.py
index 21d38c28920..a65ac0e9416 100644
--- a/release/scripts/modules/rigify/track_reverse.py
+++ b/release/scripts/modules/rigify/track_reverse.py
@@ -35,7 +35,7 @@ RIG_TYPE = "track_reverse"
# bone.head[:] = 0.0000, 0.0000, 0.0000
# bone.tail[:] = 0.0000, 0.0000, 1.0000
# bone.roll = 0.0000
-# bone.connected = False
+# bone.use_connect = False
#
# bpy.ops.object.mode_set(mode='OBJECT')
# pbone = obj.pose.bones['Bone']
@@ -78,7 +78,7 @@ def main(obj, bone_definition, base_names, options):
mbone2 = "ORG-" + options["to"]
bone_e = copy_bone_simple(obj.data, mbone2, "DEF-%s.02" % base_names[bone_definition[0]])
- bone_e.connected = False
+ bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = eb[mbone1].head
bone = bone_e.name
diff --git a/release/scripts/modules/rigify_utils.py b/release/scripts/modules/rigify_utils.py
index 812342b3ebc..1ffe366e0d5 100644
--- a/release/scripts/modules/rigify_utils.py
+++ b/release/scripts/modules/rigify_utils.py
@@ -26,7 +26,7 @@
# that a generic function would need to check for.
import bpy
-from Mathutils import Vector
+from mathutils import Vector
from rna_prop_ui import rna_idprop_ui_prop_get
DELIMITER = '-._'
@@ -67,7 +67,7 @@ def add_stretch_to(obj, from_name, to_name, name):
con = stretch_pbone.constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = to_name
- con.original_length = (head - tail).length
+ con.rest_length = (head - tail).length
con.keep_axis = 'PLANE_X'
con.volume = 'NO_VOLUME'
@@ -81,13 +81,13 @@ def copy_bone_simple(arm, from_bone, name, parent=False):
ebone_new = arm.edit_bones.new(name)
if parent:
- ebone_new.connected = ebone.connected
+ ebone_new.use_connect = ebone.use_connect
ebone_new.parent = ebone.parent
ebone_new.head = ebone.head
ebone_new.tail = ebone.tail
ebone_new.roll = ebone.roll
- ebone_new.layer = list(ebone.layer)
+ ebone_new.layers = list(ebone.layers)
return ebone_new
@@ -136,7 +136,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
- driver_path = prop_pbone.path_to_id() + ('["%s"]' % target_prop)
+ driver_path = prop_pbone.path_from_id() + ('["%s"]' % target_prop)
def blend_target(driver):
var = driver.variables.new()
@@ -154,10 +154,10 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
con.target = obj
con.subtarget = to_bone_name
- fcurve = con.driver_add("influence", 0)
+ fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
- fcurve.modifiers.remove(0) # grr dont need a modifier
+ fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
blend_target(driver)
@@ -204,12 +204,12 @@ def add_pole_target_bone(obj, base_bone_name, name, mode='CROSS'):
offset.length = distance
elif mode == 'ZAVERAGE':
# between both bones Z axis
- z_axis_a = base_ebone.matrix.copy().rotation_part() * Vector(0.0, 0.0, -1.0)
- z_axis_b = parent_ebone.matrix.copy().rotation_part() * Vector(0.0, 0.0, -1.0)
+ z_axis_a = base_ebone.matrix.copy().rotation_part() * Vector((0.0, 0.0, -1.0))
+ z_axis_b = parent_ebone.matrix.copy().rotation_part() * Vector((0.0, 0.0, -1.0))
offset = (z_axis_a + z_axis_b).normalize() * distance
else:
# preset axis
- offset = Vector(0, 0, 0)
+ offset = Vector((0.0, 0.0, 0.0))
if mode[0] == "+":
val = distance
else:
@@ -276,7 +276,7 @@ def write_meta_rig(obj, func_name="metarig_template"):
code.append(" bone.head[:] = %.4f, %.4f, %.4f" % bone.head.to_tuple(4))
code.append(" bone.tail[:] = %.4f, %.4f, %.4f" % bone.tail.to_tuple(4))
code.append(" bone.roll = %.4f" % bone.roll)
- code.append(" bone.connected = %s" % str(bone.connected))
+ code.append(" bone.use_connect = %s" % str(bone.use_connect))
if bone.parent:
code.append(" bone.parent = arm.edit_bones['%s']" % bone.parent.name)
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index 8a93f98815c..0a93121c559 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -25,6 +25,44 @@ import bpy
# use to strip python paths
script_paths = bpy.utils.script_paths()
+_FAKE_STRUCT_SUBCLASS = True
+
+
+def _get_direct_attr(rna_type, attr):
+ props = getattr(rna_type, attr)
+ base = rna_type.base
+
+ if not base:
+ return [prop for prop in props]
+ else:
+ props_base = getattr(base, attr).values()
+ return [prop for prop in props if prop not in props_base]
+
+
+def get_direct_properties(rna_type):
+ return _get_direct_attr(rna_type, "properties")
+
+
+def get_direct_functions(rna_type):
+ return _get_direct_attr(rna_type, "functions")
+
+
+def rna_id_ignore(rna_id):
+ if rna_id == "rna_type":
+ return True
+
+ if "_OT_" in rna_id:
+ return True
+ if "_MT_" in rna_id:
+ return True
+ if "_PT_" in rna_id:
+ return True
+ if "_HT_" in rna_id:
+ return True
+ if "_KSI_" in rna_id:
+ return True
+ return False
+
def range_str(val):
if val < -10000000:
@@ -67,8 +105,8 @@ class InfoStructRNA:
def build(self):
rna_type = self.bl_rna
parent_id = self.identifier
- self.properties[:] = [GetInfoPropertyRNA(rna_prop, parent_id) for rna_id, rna_prop in rna_type.properties.items() if rna_id != "rna_type"]
- self.functions[:] = [GetInfoFunctionRNA(rna_prop, parent_id) for rna_prop in rna_type.functions.values()]
+ self.properties[:] = [GetInfoPropertyRNA(rna_prop, parent_id) for rna_prop in get_direct_properties(rna_type) if rna_prop.identifier != "rna_type"]
+ self.functions[:] = [GetInfoFunctionRNA(rna_prop, parent_id) for rna_prop in get_direct_functions(rna_type)]
def get_bases(self):
bases = []
@@ -116,17 +154,17 @@ class InfoStructRNA:
def __repr__(self):
- txt = ''
+ txt = ""
txt += self.identifier
if self.base:
- txt += '(%s)' % self.base.identifier
- txt += ': ' + self.description + '\n'
+ txt += "(%s)" % self.base.identifier
+ txt += ": " + self.description + "\n"
for prop in self.properties:
- txt += prop.__repr__() + '\n'
+ txt += prop.__repr__() + "\n"
for func in self.functions:
- txt += func.__repr__() + '\n'
+ txt += func.__repr__() + "\n"
return txt
@@ -163,40 +201,40 @@ class InfoPropertyRNA:
if self.type == "enum":
self.enum_items[:] = rna_prop.items.keys()
+
if self.array_length:
self.default = tuple(getattr(rna_prop, "default_array", ()))
+ else:
+ self.default = getattr(rna_prop, "default", None)
+ self.default_str = "" # fallback
+
+
+ if self.type == "pointer":
+ # pointer has no default, just set as None
+ self.default = None
+ self.default_str = "None"
+ elif self.type == "string":
+ self.default_str = "\"%s\"" % self.default
+ elif self.type == "enum":
+ self.default_str = "'%s'" % self.default
+ elif self.array_length:
self.default_str = ''
# special case for floats
if len(self.default) > 0:
- if type(self.default[0]) is float:
+ if self.type == "float":
self.default_str = "(%s)" % ", ".join([float_as_string(f) for f in self.default])
if not self.default_str:
self.default_str = str(self.default)
else:
- self.default = getattr(rna_prop, "default", "")
- if type(self.default) is float:
+ if self.type == "float":
self.default_str = float_as_string(self.default)
else:
self.default_str = str(self.default)
self.srna = GetInfoStructRNA(rna_prop.srna) # valid for pointer/collections
- def get_default_string(self):
- # pointer has no default, just set as None
- if self.type == "pointer":
- return "None"
- elif self.type == "string":
- return '"' + self.default_str + '"'
- elif self.type == "enum":
- if self.default_str:
- return "'" + self.default_str + "'"
- else:
- return ""
-
- return self.default_str
-
def get_arg_default(self, force=True):
- default = self.get_default_string()
+ default = self.default_str
if default and (force or self.is_required == False):
return "%s=%s" % (self.identifier, default)
return self.identifier
@@ -212,6 +250,13 @@ class InfoPropertyRNA:
type_str += " in [%s, %s]" % (range_str(self.min), range_str(self.max))
elif self.type == "enum":
type_str += " in [%s]" % ', '.join([("'%s'" % s) for s in self.enum_items])
+
+ if not (as_arg or as_ret):
+ # write default property, ignore function args for this
+ if self.type != "pointer":
+ if self.default_str:
+ type_str += ", default %s" % self.default_str
+
else:
if self.type == "collection":
if self.collection_type:
@@ -223,17 +268,22 @@ class InfoPropertyRNA:
type_str += collection_str + (class_fmt % self.fixed_type.identifier)
+ # setup qualifiers for this value.
+ type_info = []
if as_ret:
pass
elif as_arg:
if not self.is_required:
- type_str += ", (optional)"
+ type_info.append("optional")
else: # readonly is only useful for selfs, not args
if self.is_readonly:
- type_str += ", (readonly)"
+ type_info.append("readonly")
if self.is_never_none:
- type_str += ", (never None)"
+ type_info.append("never None")
+
+ if type_info:
+ type_str += (", (%s)" % ", ".join(type_info))
return type_str
@@ -252,6 +302,7 @@ class InfoFunctionRNA:
self.identifier = rna_func.identifier
# self.name = rna_func.name # functions have no name!
self.description = rna_func.description.strip()
+ self.is_classmethod = not rna_func.use_self
self.args = []
self.return_values = ()
@@ -263,7 +314,7 @@ class InfoFunctionRNA:
for rna_prop in rna_func.parameters.values():
prop = GetInfoPropertyRNA(rna_prop, parent_id)
- if rna_prop.use_output:
+ if rna_prop.is_output:
self.return_values.append(prop)
else:
self.args.append(prop)
@@ -366,21 +417,7 @@ def BuildRNAInfo():
rna_full_path_dict = {} # store the result of full_rna_struct_path(rna_struct)
rna_children_dict = {} # store all rna_structs nested from here
rna_references_dict = {} # store a list of rna path strings that reference this type
- rna_functions_dict = {} # store all functions directly in this type (not inherited)
-
- def rna_id_ignore(rna_id):
- if rna_id == "rna_type":
- return True
-
- if "_OT_" in rna_id:
- return True
- if "_MT_" in rna_id:
- return True
- if "_PT_" in rna_id:
- return True
- if "_HT_" in rna_id:
- return True
- return False
+ # rna_functions_dict = {} # store all functions directly in this type (not inherited)
def full_rna_struct_path(rna_struct):
'''
@@ -426,7 +463,8 @@ def BuildRNAInfo():
rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct)
# Store a list of functions, remove inherited later
- rna_functions_dict[identifier] = list(rna_struct.functions)
+ # NOT USED YET
+ ## rna_functions_dict[identifier] = get_direct_functions(rna_struct)
# fill in these later
@@ -438,12 +476,6 @@ def BuildRNAInfo():
print("Ignoring", rna_type_name)
- # Sucks but we need to copy this so we can check original parent functions
- rna_functions_dict__copy = {}
- for key, val in rna_functions_dict.items():
- rna_functions_dict__copy[key] = val[:]
-
-
structs.sort() # not needed but speeds up sort below, setting items without an inheritance first
# Arrange so classes are always defined in the correct order
@@ -478,41 +510,27 @@ def BuildRNAInfo():
# precalc vars to avoid a lot of looping
for (rna_base, identifier, rna_struct) in structs:
- if rna_base:
- rna_base_prop_keys = rna_struct_dict[rna_base].properties.keys() # could cache
- rna_base_func_keys = [f.identifier for f in rna_struct_dict[rna_base].functions]
- else:
- rna_base_prop_keys = []
- rna_base_func_keys = []
-
# rna_struct_path = full_rna_struct_path(rna_struct)
rna_struct_path = rna_full_path_dict[identifier]
- for rna_prop_identifier, rna_prop in rna_struct.properties.items():
+ for rna_prop in get_direct_properties(rna_struct):
+ rna_prop_identifier = rna_prop.identifier
- if rna_prop_identifier == 'RNA' or \
- rna_id_ignore(rna_prop_identifier) or \
- rna_prop_identifier in rna_base_prop_keys:
+ if rna_prop_identifier == 'RNA' or rna_id_ignore(rna_prop_identifier):
continue
-
for rna_prop_ptr in (getattr(rna_prop, "fixed_type", None), getattr(rna_prop, "srna", None)):
# Does this property point to me?
if rna_prop_ptr:
rna_references_dict[rna_prop_ptr.identifier].append("%s.%s" % (rna_struct_path, rna_prop_identifier))
- for rna_func in rna_struct.functions:
+ for rna_func in get_direct_functions(rna_struct):
for rna_prop_identifier, rna_prop in rna_func.parameters.items():
- if rna_prop_identifier == 'RNA' or \
- rna_id_ignore(rna_prop_identifier) or \
- rna_prop_identifier in rna_base_func_keys:
+ if rna_prop_identifier == 'RNA' or rna_id_ignore(rna_prop_identifier):
continue
- try:
- rna_prop_ptr = rna_prop.fixed_type
- except AttributeError:
- rna_prop_ptr = None
+ rna_prop_ptr = getattr(rna_prop, "fixed_type", None)
# Does this property point to me?
if rna_prop_ptr:
@@ -525,16 +543,6 @@ def BuildRNAInfo():
rna_children_dict[nested.identifier].append(rna_struct)
- if rna_base:
- rna_funcs = rna_functions_dict[identifier]
- if rna_funcs:
- # Remove inherited functions if we have any
- rna_base_funcs = rna_functions_dict__copy[rna_base]
- rna_funcs[:] = [f for f in rna_funcs if f not in rna_base_funcs]
-
- rna_functions_dict__copy.clear()
- del rna_functions_dict__copy
-
# Sort the refs, just reads nicer
for rna_refs in rna_references_dict.values():
rna_refs.sort()
@@ -573,11 +581,21 @@ def BuildRNAInfo():
for prop in func.return_values:
prop.build()
+ if 1:
+ for rna_info in InfoStructRNA.global_lookup.values():
+ for prop in rna_info.properties:
+ # ERROR CHECK
+ default = prop.default
+ if type(default) in (float, int):
+ if default < prop.min or default > prop.max:
+ print("\t %s.%s, %s not in [%s - %s]" % (rna_info.identifier, prop.identifier, default, prop.min, prop.max))
+
+
# now for operators
op_mods = dir(bpy.ops)
for op_mod_name in sorted(op_mods):
- if op_mod_name.startswith('__') or op_mod_name in ("add", "remove"):
+ if op_mod_name.startswith('__'):
continue
op_mod = getattr(bpy.ops, op_mod_name)
@@ -603,3 +621,33 @@ def BuildRNAInfo():
# print(rna_info)
return InfoStructRNA.global_lookup, InfoFunctionRNA.global_lookup, InfoOperatorRNA.global_lookup, InfoPropertyRNA.global_lookup
+
+
+if __name__ == "__main__":
+ import rna_info
+ struct = rna_info.BuildRNAInfo()[0]
+ data = []
+ for struct_id, v in sorted(struct.items()):
+ struct_id_str = v.identifier # "".join(sid for sid in struct_id if struct_id)
+
+ for base in v.get_bases():
+ struct_id_str = base.identifier + "|" + struct_id_str
+
+ props = [(prop.identifier, prop) for prop in v.properties]
+ for prop_id, prop in sorted(props):
+ # if prop.type == 'boolean':
+ # continue
+ prop_type = prop.type
+ if prop.array_length > 0:
+ prop_type += "[%d]" % prop.array_length
+
+ data.append("%s.%s -> %s: %s%s %s" % (struct_id_str, prop.identifier, prop.identifier, prop_type, ", (read-only)" if prop.is_readonly else "", prop.description))
+ data.sort()
+
+ if bpy.app.background:
+ import sys
+ sys.stderr.write("\n".join(data))
+ sys.stderr.write("\n\nEOF\n")
+ else:
+ text = bpy.data.texts.new(name="api.py")
+ text.from_string(data)
diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index 246fa4bdb7d..4ee0b40faa8 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -61,7 +61,7 @@ def rna_idprop_ui_prop_clear(item, prop):
def draw(layout, context, context_member, use_edit=True):
def assign_props(prop, val, key):
- prop.path = context_member
+ prop.data_path = context_member
prop.property = key
try:
@@ -81,7 +81,7 @@ def draw(layout, context, context_member, use_edit=True):
if use_edit:
row = layout.row()
props = row.operator("wm.properties_add", text="Add")
- props.path = context_member
+ props.data_path = context_member
del row
for key, val in items:
@@ -124,141 +124,18 @@ def draw(layout, context, context_member, use_edit=True):
assign_props(prop, val_draw, key)
-class PropertyPanel(bpy.types.Panel):
+class PropertyPanel():
"""
The subclass should have its own poll function
and the variable '_context_path' MUST be set.
"""
bl_label = "Custom Properties"
- bl_default_closed = True
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return bool(eval("context.%s" % cls._context_path))
def draw(self, context):
draw(self.layout, context, self._context_path)
-
-from bpy.props import *
-
-
-rna_path = StringProperty(name="Property Edit",
- description="Property path edit", maxlen=1024, default="", options={'HIDDEN'})
-
-rna_value = StringProperty(name="Property Value",
- description="Property value edit", maxlen=1024, default="")
-
-rna_property = StringProperty(name="Property Name",
- description="Property name edit", maxlen=1024, default="")
-
-rna_min = FloatProperty(name="Min", default=0.0, precision=3)
-rna_max = FloatProperty(name="Max", default=1.0, precision=3)
-
-
-class WM_OT_properties_edit(bpy.types.Operator):
- '''Internal use (edit a property path)'''
- bl_idname = "wm.properties_edit"
- bl_label = "Edit Property"
-
- path = rna_path
- property = rna_property
- value = rna_value
- min = rna_min
- max = rna_max
- description = StringProperty(name="Tip", default="")
-
- def execute(self, context):
- path = self.properties.path
- value = self.properties.value
- prop = self.properties.property
- prop_old = self._last_prop[0]
-
- try:
- value_eval = eval(value)
- except:
- value_eval = value
-
- # First remove
- item = eval("context.%s" % path)
-
- rna_idprop_ui_prop_clear(item, prop_old)
- exec_str = "del item['%s']" % prop_old
- # print(exec_str)
- exec(exec_str)
-
-
- # Reassign
- exec_str = "item['%s'] = %s" % (prop, repr(value_eval))
- # print(exec_str)
- exec(exec_str)
- self._last_prop[:] = [prop]
-
- prop_type = type(item[prop])
-
- prop_ui = rna_idprop_ui_prop_get(item, prop)
-
- if prop_type in (float, int):
-
- prop_ui['soft_min'] = prop_ui['min'] = prop_type(self.properties.min)
- prop_ui['soft_max'] = prop_ui['max'] = prop_type(self.properties.max)
-
- prop_ui['description'] = self.properties.description
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
-
- self._last_prop = [self.properties.property]
-
- item = eval("context.%s" % self.properties.path)
-
- # setup defaults
- prop_ui = rna_idprop_ui_prop_get(item, self.properties.property, False) # dont create
- if prop_ui:
- self.properties.min = prop_ui.get("min", -1000000000)
- self.properties.max = prop_ui.get("max", 1000000000)
- self.properties.description = prop_ui.get("description", "")
-
- wm = context.manager
- # This crashes, TODO - fix
- #return wm.invoke_props_popup(self, event)
-
- wm.invoke_props_popup(self, event)
- return {'RUNNING_MODAL'}
-
-
-class WM_OT_properties_add(bpy.types.Operator):
- '''Internal use (edit a property path)'''
- bl_idname = "wm.properties_add"
- bl_label = "Add Property"
-
- path = rna_path
-
- def execute(self, context):
- item = eval("context.%s" % self.properties.path)
-
- def unique_name(names):
- prop = 'prop'
- prop_new = prop
- i = 1
- while prop_new in names:
- prop_new = prop + str(i)
- i += 1
-
- return prop_new
-
- property = unique_name(item.keys())
-
- item[property] = 1.0
- return {'FINISHED'}
-
-
-class WM_OT_properties_remove(bpy.types.Operator):
- '''Internal use (edit a property path)'''
- bl_idname = "wm.properties_remove"
- bl_label = "Add Property"
-
- path = rna_path
- property = rna_property
-
- def execute(self, context):
- item = eval("context.%s" % self.properties.path)
- del item[self.properties.property]
- return {'FINISHED'}