- use reverse order for palm fingers (pointer first) - allow copying bone class instances to exclude some bones - doc generation had a python error (incedently updated online docs linked from the splash)
		
			
				
	
	
		
			761 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			761 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
						|
 #
 | 
						|
 # Contributor(s): Campbell Barton
 | 
						|
 #
 | 
						|
 # #**** END GPL LICENSE BLOCK #****
 | 
						|
 | 
						|
script_help_msg = '''
 | 
						|
Usage,
 | 
						|
run this script from blenders root path once you have compiled blender
 | 
						|
    ./blender.bin -P source/blender/python/epy_doc_gen.py
 | 
						|
 | 
						|
This will generate python files in "./source/blender/python/doc/bpy"
 | 
						|
Generate html docs  by running...
 | 
						|
 | 
						|
    epydoc source/blender/python/doc/bpy/ -v \\
 | 
						|
            -o source/blender/python/doc/html \\
 | 
						|
            --inheritance=included \\
 | 
						|
            --no-sourcecode \\
 | 
						|
            --graph=classtree \\
 | 
						|
            --graph-font-size=8
 | 
						|
 | 
						|
'''
 | 
						|
 | 
						|
# if you dont have graphvis installed ommit the --graph arg.
 | 
						|
 | 
						|
# GLOBALS['BASEDIR'] = './source/blender/python/doc'
 | 
						|
 | 
						|
import os
 | 
						|
 | 
						|
SUBMODULES = {}
 | 
						|
INIT_SUBMODULES = {}			# store initialized files
 | 
						|
 | 
						|
INIT_SUBMODULES_IMPORTS = {}	# dont import the same module twice
 | 
						|
 | 
						|
def append_package(package_path, mod_name):
 | 
						|
 | 
						|
    init_path =	os.path.join(os.path.dirname(package_path), "__init__.py")
 | 
						|
 | 
						|
    # avoid double ups
 | 
						|
    if mod_name:
 | 
						|
        imports = INIT_SUBMODULES_IMPORTS.setdefault(init_path, [])
 | 
						|
        if mod_name in imports:
 | 
						|
            return
 | 
						|
        imports.append(mod_name)
 | 
						|
 | 
						|
    try:
 | 
						|
        os.makedirs(os.path.dirname(init_path)) # make the dirs if they are not there
 | 
						|
    except:
 | 
						|
        pass
 | 
						|
 | 
						|
    # Open the new file for the first time, otherwise keep it open.
 | 
						|
    f = INIT_SUBMODULES.get(init_path)
 | 
						|
    if f == None:
 | 
						|
        f = INIT_SUBMODULES[init_path] = open(init_path, 'w')
 | 
						|
 | 
						|
    if mod_name:
 | 
						|
        f.write("import %s\n" % mod_name)
 | 
						|
 | 
						|
    return f
 | 
						|
 | 
						|
def append_package_recursive(package_path, BASEPATH):
 | 
						|
    '''
 | 
						|
    assume the last item of package_path will be a file (not a dir thats created)
 | 
						|
    '''
 | 
						|
 | 
						|
    package_path = os.path.splitext(package_path)[0] # incase of .py
 | 
						|
 | 
						|
    try:
 | 
						|
        os.makedirs(os.path.join(BASEPATH, os.path.dirname(package_path))) # make the dirs if they are not there
 | 
						|
    except:
 | 
						|
        pass
 | 
						|
 | 
						|
    new_path = BASEPATH
 | 
						|
 | 
						|
    for mod_name in package_path.split(os.sep):
 | 
						|
        init_path =	os.path.join(new_path, "__init__.py")
 | 
						|
        new_path = os.path.join(new_path, mod_name)
 | 
						|
        append_package(init_path, mod_name)
 | 
						|
 | 
						|
 | 
						|
def open_submodule(subpath, BASEPATH):
 | 
						|
    '''
 | 
						|
    This is a utility function that lets us quickly add submodules
 | 
						|
    '''
 | 
						|
 | 
						|
    # create all the package paths leading up to this module
 | 
						|
    append_package_recursive(subpath, BASEPATH)
 | 
						|
 | 
						|
    module_name =		os.path.basename( os.path.splitext(subpath)[0] )
 | 
						|
    mod_path =	os.path.join(BASEPATH, subpath)
 | 
						|
 | 
						|
    # Open the new file for the first time, otherwise keep it open.
 | 
						|
    f = SUBMODULES.get(mod_path)
 | 
						|
    if f == None:
 | 
						|
        f = SUBMODULES[mod_path] = open(mod_path, 'w')
 | 
						|
 | 
						|
    f = open(mod_path, 'w')
 | 
						|
    return f
 | 
						|
 | 
						|
def close_all():
 | 
						|
    for files in (INIT_SUBMODULES.values(), SUBMODULES.values()):
 | 
						|
        for f in files:
 | 
						|
            if f.name.endswith('.py'):
 | 
						|
                f_name = f.name
 | 
						|
                f.close()
 | 
						|
 | 
						|
                f = open(f_name, 'a')
 | 
						|
                f.write("\ndel __package__\n") # annoying, no need do show this
 | 
						|
 | 
						|
 | 
						|
            f.close()
 | 
						|
 | 
						|
 | 
						|
def range_str(val):
 | 
						|
    if val < -10000000:	return '-inf'
 | 
						|
    if val >  10000000:	return 'inf'
 | 
						|
    if type(val)==float:
 | 
						|
        return '%g'  % val
 | 
						|
    else:
 | 
						|
        return str(val)
 | 
						|
 | 
						|
def get_array_str(length):
 | 
						|
    if length > 0:	return ' array of %d items' % length
 | 
						|
    else:		return ''
 | 
						|
 | 
						|
def full_rna_struct_path(rna_struct):
 | 
						|
    '''
 | 
						|
    Needed when referencing one struct from another
 | 
						|
    '''
 | 
						|
    nested = rna_struct.nested
 | 
						|
    if nested:
 | 
						|
        return "%s.%s" % (full_rna_struct_path(nested), rna_struct.identifier)
 | 
						|
    else:
 | 
						|
        return rna_struct.identifier
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
    return False
 | 
						|
 | 
						|
def write_func(rna, ident, out, func_type):
 | 
						|
    # Keyword attributes
 | 
						|
    kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
 | 
						|
    kw_arg_attrs = [] # "@type mode: int"
 | 
						|
 | 
						|
    rna_struct= rna.rna_type
 | 
						|
 | 
						|
    # Operators and functions work differently
 | 
						|
    if func_type=='OPERATOR':
 | 
						|
        rna_func_name = rna_struct.identifier.split("_OT_")[-1]
 | 
						|
        rna_func_desc = rna_struct.description.strip()
 | 
						|
        items = rna_struct.properties.items()
 | 
						|
    else:
 | 
						|
        rna_func_name = rna.identifier
 | 
						|
        rna_func_desc = rna.description.strip()
 | 
						|
        items = rna.parameters.items()
 | 
						|
 | 
						|
 | 
						|
    for rna_prop_identifier, rna_prop in items:
 | 
						|
        if rna_id_ignore(rna_prop_identifier):
 | 
						|
            continue
 | 
						|
 | 
						|
        # clear vars
 | 
						|
        val = val_error = val_str = rna_prop_type = None
 | 
						|
 | 
						|
        # ['rna_type', 'name', 'array_length', 'description', 'hard_max', 'hard_min', 'identifier', 'precision', 'readonly', 'soft_max', 'soft_min', 'step', 'subtype', 'type']
 | 
						|
        #rna_prop=  op_rna.rna_type.properties[attr]
 | 
						|
        rna_prop_type = rna_prop.type.lower() # enum, float, int, boolean
 | 
						|
 | 
						|
 | 
						|
        # only for rna functions, operators should not get pointers as args
 | 
						|
        if rna_prop_type=='pointer':
 | 
						|
            rna_prop_type_refine = "L{%s}" % rna_prop.fixed_type.identifier
 | 
						|
        else:
 | 
						|
            # Collections/Arrays can have a srna type
 | 
						|
            rna_prop_srna_type = rna_prop.srna
 | 
						|
            if rna_prop_srna_type:
 | 
						|
                print(rna_prop_srna_type.identifier)
 | 
						|
                rna_prop_type_refine = "L{%s}" % rna_prop_srna_type.identifier
 | 
						|
            else:
 | 
						|
                rna_prop_type_refine = rna_prop_type
 | 
						|
            
 | 
						|
            del rna_prop_srna_type
 | 
						|
 | 
						|
 | 
						|
        try:		length = rna_prop.array_length
 | 
						|
        except:	length = 0
 | 
						|
 | 
						|
        array_str = get_array_str(length)
 | 
						|
 | 
						|
        if rna_prop.use_return:
 | 
						|
            kw_type_str= "@rtype: %s%s" % (rna_prop_type_refine, array_str)
 | 
						|
            kw_param_str= "@return: %s" % (rna_prop.description.strip())
 | 
						|
        else:
 | 
						|
            kw_type_str= "@type %s: %s%s" % (rna_prop_identifier, rna_prop_type_refine, array_str)
 | 
						|
            kw_param_str= "@param %s: %s" % (rna_prop_identifier, rna_prop.description.strip())
 | 
						|
 | 
						|
        kw_param_set = False
 | 
						|
 | 
						|
        if func_type=='OPERATOR':
 | 
						|
            try:
 | 
						|
                val = getattr(rna, rna_prop_identifier)
 | 
						|
                val_error = False
 | 
						|
            except:
 | 
						|
                val = "'<UNDEFINED>'"
 | 
						|
                val_error = True
 | 
						|
 | 
						|
 | 
						|
            if val_error:
 | 
						|
                val_str = val
 | 
						|
            elif rna_prop_type=='float':
 | 
						|
                if length==0:
 | 
						|
                    val_str= '%g' % val
 | 
						|
                    if '.' not in val_str and '-' not in val_str: # value could be 1e-05
 | 
						|
                        val_str += '.0'
 | 
						|
                else:
 | 
						|
                    # array
 | 
						|
                    val_str = str(tuple(val))
 | 
						|
 | 
						|
                kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
 | 
						|
                kw_param_set= True
 | 
						|
 | 
						|
            elif rna_prop_type=='int':
 | 
						|
                if length==0:
 | 
						|
                    val_str='%d' % val
 | 
						|
                else:
 | 
						|
                    val_str = str(tuple(val))
 | 
						|
 | 
						|
                # print(dir(rna_prop))
 | 
						|
                kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
 | 
						|
                # These strings dont have a max length???
 | 
						|
                #kw_param_str += ' (maximum length of %s)' %  (rna_prop.max_length)
 | 
						|
                kw_param_set= True
 | 
						|
 | 
						|
            elif rna_prop_type=='boolean':
 | 
						|
                if length==0:
 | 
						|
                    if val:	val_str='True'
 | 
						|
                    else:	val_str='False'
 | 
						|
                else:
 | 
						|
                    val_str = str(tuple(val))
 | 
						|
 | 
						|
            elif rna_prop_type=='enum':
 | 
						|
                # no array here?
 | 
						|
                val_str="'%s'" % val
 | 
						|
                # Too cramped
 | 
						|
                kw_param_str += (' in (%s)' % ', '.join(rna_prop.items.keys()))
 | 
						|
 | 
						|
                kw_param_set= True
 | 
						|
 | 
						|
            elif rna_prop_type=='string':
 | 
						|
                # no array here?
 | 
						|
                val_str='"%s"' % val
 | 
						|
 | 
						|
            # todo - collection - array
 | 
						|
            # print (rna_prop.type)
 | 
						|
 | 
						|
            kw_args.append('%s = %s' % (rna_prop_identifier, val_str))
 | 
						|
 | 
						|
            # stora
 | 
						|
        else:
 | 
						|
            # currently functions dont have a default value
 | 
						|
            if not rna_prop.use_return:
 | 
						|
                kw_args.append('%s' % (rna_prop_identifier))
 | 
						|
            else:
 | 
						|
                kw_param_set = True
 | 
						|
 | 
						|
 | 
						|
        # Same for operators and functions
 | 
						|
        kw_arg_attrs.append(kw_type_str)
 | 
						|
        if kw_param_set:
 | 
						|
            kw_arg_attrs.append(kw_param_str)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    out.write(ident+'def %s(%s):\n' % (rna_func_name, ', '.join(kw_args)))
 | 
						|
    out.write(ident+'\t"""\n')
 | 
						|
    
 | 
						|
    # Descriptions could be multiline
 | 
						|
    for rna_func_desc_line in rna_func_desc.split('\n'):
 | 
						|
        out.write(ident+'\t%s\n' % rna_func_desc_line.strip())
 | 
						|
    
 | 
						|
    for desc in kw_arg_attrs:
 | 
						|
        out.write(ident+'\t%s\n' % desc)
 | 
						|
 | 
						|
    # out.write(ident+'\t@rtype: None\n') # implicit
 | 
						|
    out.write(ident+'\t"""\n')
 | 
						|
 | 
						|
 | 
						|
 | 
						|
def rna2epy(BASEPATH):
 | 
						|
 | 
						|
    # Use for faster lookups
 | 
						|
    # use rna_struct.identifier as the key for each dict
 | 
						|
    rna_struct_dict =		{}  # store identifier:rna lookups
 | 
						|
    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)
 | 
						|
    rna_words = set()
 | 
						|
 | 
						|
    # def write_func(rna_func, ident):
 | 
						|
 | 
						|
 | 
						|
    def write_struct(rna_struct, ident):
 | 
						|
        identifier = rna_struct.identifier
 | 
						|
 | 
						|
        rna_base = rna_struct.base
 | 
						|
 | 
						|
        if rna_base:
 | 
						|
            out.write(ident+ 'class %s(%s):\n' % (identifier, rna_base.identifier))
 | 
						|
            rna_base_prop_keys = rna_base.properties.keys() # could be cached
 | 
						|
            rna_base_func_keys = [f.identifier for f in rna_base.functions]
 | 
						|
        else:
 | 
						|
            out.write(ident+ 'class %s:\n' % identifier)
 | 
						|
            rna_base_prop_keys = []
 | 
						|
            rna_base_func_keys = []
 | 
						|
 | 
						|
        out.write(ident+ '\t"""\n')
 | 
						|
 | 
						|
        title = 'The %s Object' % rna_struct.name
 | 
						|
        description = rna_struct.description.strip()
 | 
						|
        out.write(ident+ '\t%s\n' %  title)
 | 
						|
        out.write(ident+ '\t%s\n' %  ('=' * len(title)))
 | 
						|
        out.write(ident+ '\t\t%s\n' %  description)
 | 
						|
        rna_words.update(description.split())
 | 
						|
 | 
						|
 | 
						|
        # For convenience, give a list of all places were used.
 | 
						|
        rna_refs= rna_references_dict[identifier]
 | 
						|
 | 
						|
        if rna_refs:
 | 
						|
            out.write(ident+ '\t\t\n')
 | 
						|
            out.write(ident+ '\t\tReferences\n')
 | 
						|
            out.write(ident+ '\t\t==========\n')
 | 
						|
 | 
						|
            for rna_ref_string in rna_refs:
 | 
						|
                out.write(ident+ '\t\t\t- L{%s}\n' % rna_ref_string)
 | 
						|
 | 
						|
            out.write(ident+ '\t\t\n')
 | 
						|
 | 
						|
        else:
 | 
						|
            out.write(ident+ '\t\t\n')
 | 
						|
            out.write(ident+ '\t\t(no references to this struct found)\n')
 | 
						|
            out.write(ident+ '\t\t\n')
 | 
						|
 | 
						|
        for rna_prop_identifier, rna_prop in rna_struct.properties.items():
 | 
						|
 | 
						|
            if rna_prop_identifier=='RNA':					continue
 | 
						|
            if rna_id_ignore(rna_prop_identifier):			continue
 | 
						|
            if rna_prop_identifier in rna_base_prop_keys:	continue # does this prop exist in our parent class, if so skip
 | 
						|
 | 
						|
            rna_desc = rna_prop.description.strip()
 | 
						|
 | 
						|
            if rna_desc: rna_words.update(rna_desc.split())
 | 
						|
            if not rna_desc: rna_desc = rna_prop.name
 | 
						|
            if not rna_desc: rna_desc = 'Note - No documentation for this property!'
 | 
						|
 | 
						|
            rna_prop_type = rna_prop.type.lower()
 | 
						|
 | 
						|
            if rna_prop_type=='collection':	collection_str = 'Collection of '
 | 
						|
            else:							collection_str = ''
 | 
						|
            
 | 
						|
            # some collections have a srna for their own properties
 | 
						|
            # TODO - arrays, however this isnt used yet
 | 
						|
            rna_prop_srna_type = rna_prop.srna
 | 
						|
            if rna_prop_srna_type:
 | 
						|
                collection_str =  "L{%s} %s" % (rna_prop_srna_type.identifier, collection_str)
 | 
						|
            del rna_prop_srna_type
 | 
						|
 | 
						|
            try:		rna_prop_ptr = rna_prop.fixed_type
 | 
						|
            except:	rna_prop_ptr = None
 | 
						|
 | 
						|
            try:		length = rna_prop.array_length
 | 
						|
            except:	length = 0
 | 
						|
 | 
						|
            array_str = get_array_str(length)
 | 
						|
 | 
						|
            if rna_prop.editable:	readonly_str = ''
 | 
						|
            else:				readonly_str = ' (readonly)'
 | 
						|
 | 
						|
            if rna_prop_ptr: # Use the pointer type
 | 
						|
                out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
 | 
						|
                out.write(ident+ '\t@type %s: %sL{%s}%s%s\n' %  (rna_prop_identifier, collection_str, rna_prop_ptr.identifier, array_str, readonly_str))
 | 
						|
            else:
 | 
						|
                if rna_prop_type == 'enum':
 | 
						|
                    if 0:
 | 
						|
                        out.write(ident+ '\t@ivar %s: %s in (%s)\n' %  (rna_prop_identifier, rna_desc, ', '.join(rna_prop.items.keys())))
 | 
						|
                    else:
 | 
						|
                        out.write(ident+ '\t@ivar %s: %s in...\n' %  (rna_prop_identifier, rna_desc))
 | 
						|
                        for e, e_rna_prop in rna_prop.items.items():
 | 
						|
                            #out.write(ident+ '\t\t- %s: %s\n' % (e, e_rna_prop.description)) # XXX - segfaults, FIXME
 | 
						|
                            out.write(ident+ '\t\t- %s\n' % e)
 | 
						|
 | 
						|
                    out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type,  array_str, readonly_str))
 | 
						|
                elif rna_prop_type == 'int' or rna_prop_type == 'float':
 | 
						|
                    out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
 | 
						|
                    out.write(ident+ '\t@type %s: %s%s%s in [%s, %s]\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str, range_str(rna_prop.hard_min), range_str(rna_prop.hard_max) ))
 | 
						|
                elif rna_prop_type == 'string':
 | 
						|
                    out.write(ident+ '\t@ivar %s: %s (maximum length of %s)\n' %  (rna_prop_identifier, rna_desc, rna_prop.max_length))
 | 
						|
                    out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
 | 
						|
                else:
 | 
						|
                    out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
 | 
						|
                    out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
 | 
						|
 | 
						|
 | 
						|
        out.write(ident+ '\t"""\n\n')
 | 
						|
 | 
						|
 | 
						|
        # Write functions
 | 
						|
        # for rna_func in rna_struct.functions: # Better ignore inherited (line below)
 | 
						|
        for rna_func in rna_functions_dict[identifier]:
 | 
						|
            if rna_func not in rna_base_func_keys:
 | 
						|
                write_func(rna_func, ident+'\t', out, 'FUNCTION')
 | 
						|
 | 
						|
        out.write('\n')
 | 
						|
 | 
						|
        # Now write children recursively
 | 
						|
        for child in rna_children_dict[identifier]:
 | 
						|
            write_struct(child, ident + '\t')
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    # out = open(target_path, 'w')
 | 
						|
    out = open_submodule("types.py", BASEPATH) # bpy.types
 | 
						|
 | 
						|
    def base_id(rna_struct):
 | 
						|
        try:		return rna_struct.base.identifier
 | 
						|
        except:	return '' # invalid id
 | 
						|
 | 
						|
    #structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpy.doc.structs.values()]
 | 
						|
    '''
 | 
						|
    structs = []
 | 
						|
    for rna_struct in bpy.doc.structs.values():
 | 
						|
        structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )
 | 
						|
    '''
 | 
						|
    structs = []
 | 
						|
    for rna_type_name in dir(bpy.types):
 | 
						|
        rna_type = getattr(bpy.types, rna_type_name)
 | 
						|
 | 
						|
        try:		rna_struct = rna_type.bl_rna
 | 
						|
        except:	rna_struct = None
 | 
						|
 | 
						|
        if rna_struct:
 | 
						|
            #if not rna_type_name.startswith('__'):
 | 
						|
 | 
						|
            identifier = rna_struct.identifier
 | 
						|
 | 
						|
            if not rna_id_ignore(identifier):
 | 
						|
                structs.append( (base_id(rna_struct), identifier, rna_struct) )
 | 
						|
 | 
						|
                # Simple lookup
 | 
						|
                rna_struct_dict[identifier] = rna_struct
 | 
						|
 | 
						|
                # Store full rna path 'GameObjectSettings' -> 'Object.GameObjectSettings'
 | 
						|
                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)
 | 
						|
 | 
						|
 | 
						|
                # fill in these later
 | 
						|
                rna_children_dict[identifier]= []
 | 
						|
                rna_references_dict[identifier]= []
 | 
						|
 | 
						|
 | 
						|
        else:
 | 
						|
            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
 | 
						|
    deps_ok = False
 | 
						|
    while deps_ok == False:
 | 
						|
        deps_ok = True
 | 
						|
        rna_done = set()
 | 
						|
 | 
						|
        for i, (rna_base, identifier, rna_struct) in enumerate(structs):
 | 
						|
 | 
						|
            rna_done.add(identifier)
 | 
						|
 | 
						|
            if rna_base and rna_base not in rna_done:
 | 
						|
                deps_ok = False
 | 
						|
                data = structs.pop(i)
 | 
						|
                ok = False
 | 
						|
                while i < len(structs):
 | 
						|
                    if structs[i][1]==rna_base:
 | 
						|
                        structs.insert(i+1, data) # insert after the item we depend on.
 | 
						|
                        ok = True
 | 
						|
                        break
 | 
						|
                    i+=1
 | 
						|
 | 
						|
                if not ok:
 | 
						|
                    print('Dependancy "%s" could not be found for "%s"' % (identifier, rna_base))
 | 
						|
 | 
						|
                break
 | 
						|
 | 
						|
    # Done ordering structs
 | 
						|
 | 
						|
 | 
						|
    # 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():
 | 
						|
 | 
						|
            if rna_prop_identifier=='RNA':					continue
 | 
						|
            if rna_id_ignore(rna_prop_identifier):			continue
 | 
						|
            if rna_prop_identifier in rna_base_prop_keys:	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_prop_identifier, rna_prop in rna_func.parameters.items():
 | 
						|
 | 
						|
                if rna_prop_identifier=='RNA':					continue
 | 
						|
                if rna_id_ignore(rna_prop_identifier):			continue
 | 
						|
                if rna_prop_identifier in rna_base_func_keys:	continue
 | 
						|
 | 
						|
 | 
						|
                try:		rna_prop_ptr = rna_prop.fixed_type
 | 
						|
                except:	rna_prop_ptr = 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_func.identifier) )
 | 
						|
 | 
						|
 | 
						|
        # Store nested children
 | 
						|
        nested = rna_struct.nested
 | 
						|
        if nested:
 | 
						|
            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()
 | 
						|
 | 
						|
    for (rna_base, identifier, rna_struct) in structs:
 | 
						|
        if rna_struct.nested:
 | 
						|
            continue
 | 
						|
 | 
						|
        write_struct(rna_struct, '')
 | 
						|
 | 
						|
 | 
						|
    out.write('\n')
 | 
						|
    out.close()
 | 
						|
 | 
						|
    # # We could also just run....
 | 
						|
    # os.system('epydoc source/blender/python/doc/rna.py -o ./source/blender/python/doc/html -v')
 | 
						|
 | 
						|
    target_path = os.path.join(BASEPATH, "dump.py") # XXX - used for other funcs
 | 
						|
 | 
						|
    # Write graphviz
 | 
						|
    out= open(target_path.replace('.py', '.dot'), 'w')
 | 
						|
    out.write('digraph "rna data api" {\n')
 | 
						|
    out.write('\tnode [style=filled, shape = "box"];\n')
 | 
						|
    out.write('\toverlap=false;\n')
 | 
						|
    out.write('\trankdir = LR;\n')
 | 
						|
    out.write('\tsplines=true;\n')
 | 
						|
    out.write('\tratio=auto;\n')
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    out.write('\tsize="10,10"\n')
 | 
						|
    #out.write('\tpage="8.5,11"\n')
 | 
						|
    #out.write('\tcenter=""\n')
 | 
						|
 | 
						|
    def isop(rna_struct):
 | 
						|
        return '_OT_' in rna_struct.identifier
 | 
						|
 | 
						|
 | 
						|
    for (rna_base, identifier, rna_struct) in structs:
 | 
						|
        if isop(rna_struct):
 | 
						|
            continue
 | 
						|
 | 
						|
        base = rna_struct.base
 | 
						|
 | 
						|
 | 
						|
        out.write('\t"%s";\n' % identifier)
 | 
						|
 | 
						|
    for (rna_base, identifier, rna_struct) in structs:
 | 
						|
 | 
						|
        if isop(rna_struct):
 | 
						|
            continue
 | 
						|
 | 
						|
        base = rna_struct.base
 | 
						|
 | 
						|
        if base and not isop(base):
 | 
						|
            out.write('\t"%s" -> "%s" [label="(base)" weight=1.0];\n' % (base.identifier, identifier))
 | 
						|
 | 
						|
        nested = rna_struct.nested
 | 
						|
        if nested and not isop(nested):
 | 
						|
            out.write('\t"%s" -> "%s" [label="(nested)"  weight=1.0];\n' % (nested.identifier, identifier))
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        rna_refs= rna_references_dict[identifier]
 | 
						|
 | 
						|
        for rna_ref_string in rna_refs:
 | 
						|
 | 
						|
            if '_OT_' in rna_ref_string:
 | 
						|
                continue
 | 
						|
 | 
						|
            ref = rna_ref_string.split('.')[-2]
 | 
						|
            out.write('\t"%s" -> "%s" [label="%s" weight=0.01];\n' % (ref, identifier, rna_ref_string))
 | 
						|
 | 
						|
 | 
						|
    out.write('}\n')
 | 
						|
    out.close()
 | 
						|
 | 
						|
    # # We could also just run....
 | 
						|
    # os.system('dot source/blender/python/doc/rna.dot -Tsvg -o ./source/blender/python/doc/rna.svg')
 | 
						|
 | 
						|
 | 
						|
    out= open(target_path.replace('.py', '.words'), 'w')
 | 
						|
    rna_words = list(rna_words)
 | 
						|
    rna_words.sort()
 | 
						|
    for w in rna_words:
 | 
						|
        out.write('%s\n' % w)
 | 
						|
 | 
						|
 | 
						|
def op2epy(BASEPATH):
 | 
						|
    # out = open(target_path, 'w')
 | 
						|
 | 
						|
    op_mods = dir(bpy.ops)
 | 
						|
    op_mods.remove('add')
 | 
						|
    op_mods.remove('remove')
 | 
						|
 | 
						|
    for op_mod_name in sorted(op_mods):
 | 
						|
        if op_mod_name.startswith('__'):
 | 
						|
            continue
 | 
						|
 | 
						|
        # open the submodule
 | 
						|
        mod_path = os.path.join("ops", op_mod_name + ".py")
 | 
						|
        out = open_submodule(mod_path, BASEPATH)
 | 
						|
 | 
						|
 | 
						|
        op_mod = getattr(bpy.ops, op_mod_name)
 | 
						|
        operators = dir(op_mod)
 | 
						|
        for op in sorted(operators):
 | 
						|
            # rna = getattr(bpy.types, op).bl_rna
 | 
						|
            try:
 | 
						|
                rna = getattr(op_mod, op).get_rna()
 | 
						|
            except AttributeError:
 | 
						|
                rna = None
 | 
						|
            except TypeError:
 | 
						|
                rna = None
 | 
						|
 | 
						|
            if rna:
 | 
						|
                write_func(rna, '', out, 'OPERATOR')
 | 
						|
 | 
						|
        out.write('\n')
 | 
						|
        out.close()
 | 
						|
 | 
						|
def misc2epy(BASEPATH):
 | 
						|
    '''
 | 
						|
    Hard coded modules, try to avoid adding stuff here
 | 
						|
    '''
 | 
						|
 | 
						|
    f = append_package(os.path.join(BASEPATH, ""), ""); # add a slash on the end of the base path
 | 
						|
    f.write('''
 | 
						|
"""
 | 
						|
@type data: L{bpy.types.Main}
 | 
						|
@var  data: blender data is accessed from here
 | 
						|
"""
 | 
						|
''')
 | 
						|
 | 
						|
    f = open_submodule("props.py", BASEPATH)
 | 
						|
    f.write('''
 | 
						|
MAX_INT= 2**31
 | 
						|
MAX_FLOAT= 1e+37
 | 
						|
def BoolProperty(attr, name="", description="", default=False):
 | 
						|
    """
 | 
						|
    return a new bool property
 | 
						|
    """
 | 
						|
def IntProperty(attr, name="", description="", min=-MAX_INT, max=MAX_INT, soft_min=-MAX_INT, soft_max=MAX_INT, default=0):
 | 
						|
    """
 | 
						|
    return a new int property
 | 
						|
    """
 | 
						|
def FloatProperty(attr, name="", description="", min=-MAX_FLOAT, max=MAX_FLOAT, soft_min=-MAX_FLOAT, soft_max=MAX_FLOAT, default=0.0):
 | 
						|
    """
 | 
						|
    return a new float property
 | 
						|
    """
 | 
						|
def StringProperty(attr, name="", description="", maxlen=0, default=""):
 | 
						|
    """
 | 
						|
    return a new string property
 | 
						|
    """
 | 
						|
def EnumProperty(attr, items, name="", description="", default=""):
 | 
						|
    """
 | 
						|
    return a new enum property
 | 
						|
    """
 | 
						|
''')
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    if 'bpy' not in dir():
 | 
						|
        print("\nError, this script must run from inside blender2.5")
 | 
						|
        print(script_help_msg)
 | 
						|
    else:
 | 
						|
        misc2epy('source/blender/python/doc/bpy') # first to write in info in some of the modules.
 | 
						|
        rna2epy('source/blender/python/doc/bpy')
 | 
						|
        op2epy('source/blender/python/doc/bpy')
 | 
						|
 | 
						|
 | 
						|
    close_all()
 | 
						|
 | 
						|
    import sys
 | 
						|
    sys.exit()
 |