[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25550] trunk/blender: update rna_info and rna_rna for better introspection
Campbell Barton
ideasman42 at gmail.com
Fri Dec 25 15:42:00 CET 2009
Revision: 25550
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25550
Author: campbellbarton
Date: 2009-12-25 15:42:00 +0100 (Fri, 25 Dec 2009)
Log Message:
-----------
update rna_info and rna_rna for better introspection
Modified Paths:
--------------
trunk/blender/release/scripts/modules/bpy_types.py
trunk/blender/release/scripts/modules/rna_info.py
trunk/blender/source/blender/makesrna/intern/rna_rna.c
trunk/blender/source/blender/python/epy_doc_gen.py
Modified: trunk/blender/release/scripts/modules/bpy_types.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_types.py 2009-12-25 09:01:23 UTC (rev 25549)
+++ trunk/blender/release/scripts/modules/bpy_types.py 2009-12-25 14:42:00 UTC (rev 25550)
@@ -42,25 +42,27 @@
@property
def children(self):
+ """All the children of this object"""
import bpy
return [child for child in bpy.data.objects if child.parent == self]
class _GenericBone:
- '''
+ """
functions for bones, common between Armature/Pose/Edit bones.
internal subclassing use only.
- '''
+ """
__slots__ = ()
def translate(self, vec):
+ """Utility function to add *vec* to the head and tail of this bone."""
self.head += vec
self.tail += vec
def parent_index(self, parent_test):
- '''
+ """
The same as 'bone in other_bone.parent_recursive' but saved generating a list.
- '''
+ """
# use the name so different types can be tested.
name = parent_test.name
@@ -76,11 +78,13 @@
@property
def basename(self):
+ """The name of this bone before any '.' character"""
#return self.name.rsplit(".", 1)[0]
return self.name.split(".")[0]
@property
def parent_recursive(self):
+ """A list of parents, starting with the immediate parent"""
parent_list = []
parent = self.parent
@@ -94,23 +98,26 @@
@property
def length(self):
+ """The distance from head to tail, when set the head is moved to fit the length."""
return self.vector.length
@length.setter
def length(self, value):
- """The distance from head to tail"""
self.tail = self.head + ((self.tail - self.head).normalize() * value)
@property
def vector(self):
+ """The direction this bone is pointing. Utility function for (tail - head)"""
return (self.tail - self.head)
@property
def children(self):
+ """A list of all the bones children."""
return [child for child in self._other_bones if child.parent == self]
@property
def children_recursive(self):
+ """a list of all children from this bone."""
bones_children = []
for bone in self._other_bones:
index = bone.parent_index(self)
@@ -123,10 +130,11 @@
@property
def children_recursive_basename(self):
- '''
+ """
Returns a chain of children with the same base name as this bone
- Only direct chains are supported, forks caused by multiple children with matching basenames will.
- '''
+ Only direct chains are supported, forks caused by multiple children with matching basenames will
+ terminate the function and not be returned.
+ """
basename = self.basename
chain = []
@@ -177,10 +185,10 @@
__slots__ = ()
def align_orientation(self, other):
- '''
+ """
Align this bone to another by moving its tail and settings its roll
the length of the other bone is not used.
- '''
+ """
vec = other.vector.normalize() * self.length
self.tail = self.head + vec
self.roll = other.roll
@@ -196,10 +204,10 @@
__slots__ = ()
def from_pydata(self, verts, edges, faces):
- '''
+ """
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))
verts_flat = [f for v in verts for f in v]
@@ -244,7 +252,7 @@
return [edge_face_count_dict.get(ed.key, 0) for ed in mesh.edges]
def edge_loops(self, faces=None, seams=()):
- '''
+ """
Edge loops defined by faces
Takes me.faces or a list of faces and returns the edge loops
@@ -255,7 +263,7 @@
[ [(0,1), (4, 8), (3,8)], ...]
optionaly, seams are edge keys that will be removed
- '''
+ """
OTHER_INDEX = 2,3,0,1 # opposite face index
@@ -396,9 +404,9 @@
layout.operator(operator, text=bpy.utils.display_name(f)).path = path
def draw_preset(self, context):
- '''Define these on the subclass
+ """Define these on the subclass
- preset_operator
- preset_subdir
- '''
+ """
import bpy
self.path_menu(bpy.utils.preset_paths(self.preset_subdir), self.preset_operator)
Modified: trunk/blender/release/scripts/modules/rna_info.py
===================================================================
--- trunk/blender/release/scripts/modules/rna_info.py 2009-12-25 09:01:23 UTC (rev 25549)
+++ trunk/blender/release/scripts/modules/rna_info.py 2009-12-25 14:42:00 UTC (rev 25550)
@@ -20,6 +20,9 @@
import bpy
+# use to strip python paths
+script_paths = bpy.utils.script_paths()
+
def range_str(val):
if val < -10000000: return '-inf'
if val > 10000000: return 'inf'
@@ -28,6 +31,12 @@
else:
return str(val)
+def float_as_string(f):
+ val_str = "%g" % f
+ if '.' not in val_str and '-' not in val_str: # value could be 1e-05
+ val_str += '.0'
+ return val_str
+
class InfoStructRNA:
global_lookup = {}
def __init__(self, rna_type):
@@ -73,6 +82,31 @@
return ls
+ def _get_py_visible_attrs(self):
+ attrs = []
+ py_class = getattr(bpy.types, self.identifier)
+ for attr_str in dir(py_class):
+ if attr_str.startswith("_"):
+ continue
+ attrs.append((attr_str, getattr(py_class, attr_str)))
+ return attrs
+
+
+ def get_py_properties(self):
+ properties = []
+ for identifier, attr in self._get_py_visible_attrs():
+ if type(attr) is property:
+ properties.append((identifier, attr))
+ return properties
+
+ def get_py_functions(self):
+ import types
+ functions = []
+ for identifier, attr in self._get_py_visible_attrs():
+ if type(attr) is types.FunctionType:
+ functions.append((identifier, attr))
+ return functions
+
def __repr__(self):
txt = ''
@@ -106,6 +140,10 @@
self.min = getattr(rna_prop, "hard_min", -1)
self.max = getattr(rna_prop, "hard_max", -1)
self.array_length = getattr(rna_prop, "array_length", 0)
+ self.collection_type = GetInfoStructRNA(rna_prop.srna)
+ self.is_required = rna_prop.is_required
+ self.is_readonly = rna_prop.is_readonly
+ self.is_never_none = rna_prop.is_never_none
self.type = rna_prop.type.lower()
fixed_type = getattr(rna_prop, "fixed_type", "")
@@ -118,12 +156,43 @@
self.enum_items[:] = rna_prop.items.keys()
if self.array_length:
- self.default_str = str(getattr(rna_prop, "default_array", ""))
+ self.default = tuple(getattr(rna_prop, "default_array", ()))
+ self.default_str = ''
+ # special case for floats
+ if len(self.default) > 0:
+ if type(self.default[0]) is 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_str = str(getattr(rna_prop, "default", ""))
+ self.default = getattr(rna_prop, "default", "")
+ if type(self.default) is 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()
+ if default and (force or self.is_required == False):
+ return "%s=%s" % (self.identifier, default)
+ return self.identifier
+
def __repr__(self):
txt = ''
txt += ' * ' + self.identifier + ': ' + self.description
@@ -162,6 +231,65 @@
return txt
+class InfoOperatorRNA:
+ global_lookup = {}
+ def __init__(self, rna_op):
+ self.bl_op = rna_op
+ self.identifier = rna_op.identifier
+
+ mod, name = self.identifier.split("_OT_", 1)
+ self.module_name = mod.lower()
+ self.func_name = name
+
+ # self.name = rna_func.name # functions have no name!
+ self.description = rna_op.description.strip()
+
+ self.args = []
+
+ def build(self):
+ rna_op = self.bl_op
+ parent_id = self.identifier
+ for rna_id, rna_prop in rna_op.properties.items():
+ if rna_id == "rna_type":
+ continue
+
+ prop = GetInfoPropertyRNA(rna_prop, parent_id)
+ self.args.append(prop)
+
+ def get_location(self):
+ op_class = getattr(bpy.types, self.identifier)
+ op_func = getattr(op_class, "execute", None)
+ if op_func is None:
+ op_func = getattr(op_class, "invoke", None)
+ if op_func is None:
+ op_func = getattr(op_class, "poll", None)
+
+ if op_func:
+ op_code = op_func.__code__
+ source_path = op_code.co_filename
+
+ # clear the prefix
+ for p in script_paths:
+ source_path = source_path.split(p)[-1]
+
+ if source_path[0] in "/\\":
+ source_path= source_path[1:]
+
+ return source_path, op_code.co_firstlineno
+ else:
+ return None, None
+
+'''
+ def __repr__(self):
+ txt = ''
+ txt += ' * ' + self.identifier + '('
+
+ for arg in self.args:
+ txt += arg.identifier + ', '
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list