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:
authorCampbell Barton <ideasman42@gmail.com>2009-12-25 17:42:00 +0300
committerCampbell Barton <ideasman42@gmail.com>2009-12-25 17:42:00 +0300
commit4c5a314fef8cb15f1a5990180cf5025597afdd01 (patch)
tree08a233baf408f585be287436aa7a2a76381c385b
parent4f3c477a85aa9c395f21830ed18e89407e9275db (diff)
update rna_info and rna_rna for better introspection
-rw-r--r--release/scripts/modules/bpy_types.py40
-rw-r--r--release/scripts/modules/rna_info.py168
-rw-r--r--source/blender/makesrna/intern/rna_rna.c34
-rw-r--r--source/blender/python/epy_doc_gen.py4
4 files changed, 216 insertions, 30 deletions
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 2351fa8b091..15bf71e017e 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -42,25 +42,27 @@ class Object(bpy_types.ID):
@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 @@ class _GenericBone:
@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 @@ class _GenericBone:
@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 @@ class _GenericBone:
@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 @@ class EditBone(StructRNA, _GenericBone):
__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 @@ class Mesh(bpy_types.ID):
__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 @@ class Mesh(bpy_types.ID):
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 @@ class Mesh(bpy_types.ID):
[ [(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 @@ class Menu(StructRNA):
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)
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index abb7bb35af0..2a70feec9dd 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -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 @@ def range_str(val):
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 @@ class InfoStructRNA:
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 @@ class InfoPropertyRNA:
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 @@ class InfoPropertyRNA:
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 @@ class InfoFunctionRNA:
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 + ', '
+ txt += '): ' + self.description
+ return txt
+'''
+
def _GetInfoRNA(bl_rna, cls, parent_id=''):
if bl_rna == None:
@@ -184,6 +312,8 @@ def GetInfoPropertyRNA(bl_rna, parent_id):
def GetInfoFunctionRNA(bl_rna, parent_id):
return _GetInfoRNA(bl_rna, InfoFunctionRNA, parent_id)
+def GetInfoOperatorRNA(bl_rna):
+ return _GetInfoRNA(bl_rna, InfoOperatorRNA)
def BuildRNAInfo():
# Use for faster lookups
@@ -205,7 +335,8 @@ def BuildRNAInfo():
return True
if "_PT_" in rna_id:
return True
-
+ if "_HT_" in rna_id:
+ return True
return False
def full_rna_struct_path(rna_struct):
@@ -395,9 +526,34 @@ def BuildRNAInfo():
if func.return_value:
func.return_value.build()
-
+ # 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"):
+ continue
+
+ op_mod = getattr(bpy.ops, op_mod_name)
+ operators = dir(op_mod)
+ for op in sorted(operators):
+ try:
+ rna_prop = getattr(op_mod, op).get_rna()
+ except AttributeError:
+ rna_prop = None
+ except TypeError:
+ rna_prop = None
+
+ if rna_prop:
+ GetInfoOperatorRNA(rna_prop.bl_rna)
+
+ for rna_info in InfoOperatorRNA.global_lookup.values():
+ rna_info.build()
+ for rna_prop in rna_info.args:
+ rna_prop.build()
+
+
#for rna_info in InfoStructRNA.global_lookup.values():
# print(rna_info)
- return InfoStructRNA.global_lookup, InfoFunctionRNA.global_lookup, InfoPropertyRNA.global_lookup
+ return InfoStructRNA.global_lookup, InfoFunctionRNA.global_lookup, InfoOperatorRNA.global_lookup, InfoPropertyRNA.global_lookup
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 5fd87728fb8..e6c21d8fede 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -425,7 +425,7 @@ static int rna_Property_unit_get(PointerRNA *ptr)
return RNA_SUBTYPE_UNIT(prop->subtype);
}
-static int rna_Property_editable_get(PointerRNA *ptr)
+static int rna_Property_readonly_get(PointerRNA *ptr)
{
PropertyRNA *prop= (PropertyRNA*)ptr->data;
@@ -433,7 +433,7 @@ static int rna_Property_editable_get(PointerRNA *ptr)
* data for introspection we only need to know if it can be edited so the
* flag is better for this */
// return RNA_property_editable(ptr, prop);
- return prop->flag & PROP_EDITABLE ? 1:0;
+ return prop->flag & PROP_EDITABLE ? 0:1;
}
static int rna_Property_use_return_get(PointerRNA *ptr)
@@ -442,6 +442,18 @@ static int rna_Property_use_return_get(PointerRNA *ptr)
return prop->flag & PROP_RETURN ? 1:0;
}
+static int rna_Property_is_required_get(PointerRNA *ptr)
+{
+ PropertyRNA *prop= (PropertyRNA*)ptr->data;
+ return prop->flag & PROP_REQUIRED ? 1:0;
+}
+
+static int rna_Property_is_never_none_get(PointerRNA *ptr)
+{
+ PropertyRNA *prop= (PropertyRNA*)ptr->data;
+ return prop->flag & PROP_NEVER_NULL ? 1:0;
+}
+
static int rna_Property_array_length_get(PointerRNA *ptr)
{
PropertyRNA *prop= (PropertyRNA*)ptr->data;
@@ -934,15 +946,25 @@ static void rna_def_property(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, "rna_Property_unit_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Unit", "Type of units for this property.");
- prop= RNA_def_property(srna, "editable", PROP_BOOLEAN, PROP_NONE);
+ prop= RNA_def_property(srna, "is_readonly", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Property_readonly_get", NULL);
+ RNA_def_property_ui_text(prop, "Read Only", "Property is editable through RNA.");
+
+ prop= RNA_def_property(srna, "is_required", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Property_is_required_get", NULL);
+ RNA_def_property_ui_text(prop, "Required", "False when this property is an optional argument in an rna function.");
+
+ prop= RNA_def_property(srna, "is_never_none", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_funcs(prop, "rna_Property_editable_get", NULL);
- RNA_def_property_ui_text(prop, "Editable", "Property is editable through RNA.");
+ RNA_def_property_boolean_funcs(prop, "rna_Property_is_never_none_get", NULL);
+ RNA_def_property_ui_text(prop, "Never None", "True when this value can't be set to None.");
prop= RNA_def_property(srna, "use_return", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Property_use_return_get", NULL);
- RNA_def_property_ui_text(prop, "Return", "True when this property is a return value from an rna function..");
+ RNA_def_property_ui_text(prop, "Return", "True when this property is a return value from an rna function.");
prop= RNA_def_property(srna, "registered", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/python/epy_doc_gen.py b/source/blender/python/epy_doc_gen.py
index 8783cec93ab..7e32b29aa1f 100644
--- a/source/blender/python/epy_doc_gen.py
+++ b/source/blender/python/epy_doc_gen.py
@@ -397,8 +397,8 @@ def rna2epy(BASEPATH):
array_str = get_array_str(length)
- if rna_prop.editable: readonly_str = ''
- else: readonly_str = ' (readonly)'
+ if rna_prop.is_readonly: readonly_str = ' (readonly)'
+ else: readonly_str = ''
if rna_prop_ptr: # Use the pointer type
out.write(ident+ '\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc))