forked from bartvdbraak/blender
update rna_info and rna_rna for better introspection
This commit is contained in:
parent
4f3c477a85
commit
4c5a314fef
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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_editable_get", NULL);
|
||||
RNA_def_property_ui_text(prop, "Editable", "Property is editable through RNA.");
|
||||
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_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);
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user