ok, apparently didn't commit this either. apparently includes a merge with trunk/2.5 at r24811 I thought I'd committed but did not, yeek.

This commit is contained in:
Joseph Eagar
2009-11-29 00:53:23 +00:00
408 changed files with 29688 additions and 17575 deletions

View File

@@ -72,74 +72,73 @@ extern "C" {
This is necassary to avoid blender buttons storing invalid pointers to freed
python data.*/
void BPy_Set_DrawButtonsList(void *list);
void BPy_Free_DrawButtonsList(void);
// void BPy_Set_DrawButtonsList(void *list);
// void BPy_Free_DrawButtonsList(void);
//
void BPY_pyconstraint_eval(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
void BPY_pyconstraint_settings(void *arg1, void *arg2);
// void BPY_pyconstraint_settings(void *arg1, void *arg2);
void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct);
void BPY_pyconstraint_update(struct Object *owner, struct bConstraint *con);
int BPY_is_pyconstraint(struct Text *text);
void BPY_free_pyconstraint_links(struct Text *text);
// void BPY_free_pyconstraint_links(struct Text *text);
//
void BPY_start_python( int argc, char **argv );
void BPY_end_python( void );
void BPY_post_start_python( void );
void init_syspath( int first_time );
void syspath_append( char *dir );
void BPY_rebuild_syspath( void );
int BPY_path_update( void );
int BPY_Err_getLinenumber( void );
const char *BPY_Err_getFilename( void );
int BPY_txt_do_python_Text( struct Text *text );
int BPY_menu_do_python( short menutype, int event );
int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short modifiers );
int BPY_menu_invoke( struct BPyMenu *pym, short menutype );
// void init_syspath( int first_time );
// void syspath_append( char *dir );
// void BPY_rebuild_syspath( void );
// int BPY_path_update( void );
//
// int BPY_Err_getLinenumber( void );
// const char *BPY_Err_getFilename( void );
//
// int BPY_txt_do_python_Text( struct Text *text );
// int BPY_menu_do_python( short menutype, int event );
// int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short modifiers );
// int BPY_menu_invoke( struct BPyMenu *pym, short menutype );
/* 2.5 UI Scripts */
int BPY_run_python_script( struct bContext *C, const char *filename, struct Text *text, struct ReportList *reports ); // 2.5 working
int BPY_run_script_space_draw(const struct bContext *C, struct SpaceScript * sc); // 2.5 working
void BPY_run_ui_scripts(struct bContext *C, int reload);
// int BPY_run_script_space_listener(struct bContext *C, struct SpaceScript * sc, struct ARegion *ar, struct wmNotifier *wmn); // 2.5 working
void BPY_update_modules( void ); // XXX - annoying, need this for pointers that get out of date
//
int BPY_context_get(struct bContext *C, const char *member, struct bContextDataResult *result);
int BPY_run_script(struct Script *script);
//
// int BPY_run_script(struct Script *script);
void BPY_free_compiled_text( struct Text *text );
int BPY_has_onload_script( void );
int BPY_is_spacehandler(struct Text *text, char spacetype);
int BPY_del_spacehandler(struct Text *text, struct ScrArea *sa);
int BPY_add_spacehandler(struct Text *txt, struct ScrArea *sa,char spacetype);
int BPY_has_spacehandler(struct Text *text, struct ScrArea *sa);
void BPY_screen_free_spacehandlers(struct bScreen *sc);
int BPY_do_spacehandlers(struct ScrArea *sa, unsigned short event,
short eventValue, unsigned short space_event);
void BPY_pydriver_update(void);
//
// int BPY_has_onload_script( void );
//
// int BPY_is_spacehandler(struct Text *text, char spacetype);
// int BPY_del_spacehandler(struct Text *text, struct ScrArea *sa);
// int BPY_add_spacehandler(struct Text *txt, struct ScrArea *sa,char spacetype);
// int BPY_has_spacehandler(struct Text *text, struct ScrArea *sa);
// void BPY_screen_free_spacehandlers(struct bScreen *sc);
// int BPY_do_spacehandlers(struct ScrArea *sa, unsigned short event,
// short eventValue, unsigned short space_event);
//
// void BPY_pydriver_update(void);
float BPY_pydriver_eval(struct ChannelDriver *driver);
//
int BPY_button_eval(struct bContext *C, char *expr, double *value);
/* format importer hook */
int BPY_call_importloader( char *name );
void BPY_spacescript_do_pywin_draw( struct SpaceScript *sc );
void BPY_spacescript_do_pywin_event( struct SpaceScript *sc,
unsigned short event, short val, char ascii );
void BPY_clear_script( struct Script *script );
void BPY_free_finished_script( struct Script *script );
void BPY_scripts_clear_pyobjects( void );
void error_pyscript( void );
void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
//
// void BPY_spacescript_do_pywin_draw( struct SpaceScript *sc );
// void BPY_spacescript_do_pywin_event( struct SpaceScript *sc,
// unsigned short event, short val, char ascii );
// void BPY_clear_script( struct Script *script );
// void BPY_free_finished_script( struct Script *script );
// void BPY_scripts_clear_pyobjects( void );
//
// void error_pyscript( void );
// void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
void BPY_set_context(struct bContext *C);
/* void BPY_Err_Handle(struct Text *text); */
/* int BPY_spacetext_is_pywin(struct SpaceText *st); */
void BPY_load_user_modules(struct bContext *C);
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -21,17 +21,17 @@
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
./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
-o source/blender/python/doc/html \\
--inheritance=included \\
--no-sourcecode \\
--graph=classtree \\
--graph-font-size=8
'''
@@ -48,692 +48,706 @@ 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")
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)
# 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
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')
# 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)
if mod_name:
f.write("import %s\n" % mod_name)
return f
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)
'''
'''
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
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
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
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)
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
'''
'''
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)
# 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)
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')
# 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
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'):
for files in (INIT_SUBMODULES.values(), SUBMODULES.values()):
for f in files:
if f.name.endswith('.py'):
f_name = f.name
f.close()
f.close()
f = open(f_name, 'a')
f.write("\ndel __package__\n") # annoying, no need do show this
f = open(f_name, 'a')
f.write("\ndel __package__\n") # annoying, no need do show this
f.close()
f.close()
def range_str(val):
if val < -10000000: return '-inf'
if val > 10000000: return 'inf'
if type(val)==float:
return '%g' % val
else:
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 ''
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
'''
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 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 "_OT_" in rna_id:
return True
if "_MT_" in rna_id:
return True
if "_PT_" in rna_id:
return True
return False
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"
# Keyword attributes
kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
kw_arg_attrs = [] # "@type mode: int"
rna_struct= rna.rna_type
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()
# 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
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
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
# ['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:
rna_prop_type_refine = rna_prop_type
# 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
try: length = rna_prop.array_length
except: length = 0
array_str = get_array_str(length)
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())
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
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 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))
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
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))
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
# 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=='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()))
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
kw_param_set= True
elif rna_prop_type=='string':
# no array here?
val_str='"%s"' % val
elif rna_prop_type=='string':
# no array here?
val_str='"%s"' % val
# todo - collection - array
# print (rna_prop.type)
# todo - collection - array
# print (rna_prop.type)
kw_args.append('%s = %s' % (rna_prop_identifier, val_str))
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
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)
# 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)
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')
# 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()
# 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_func(rna_func, ident):
def write_struct(rna_struct, ident):
identifier = rna_struct.identifier
def write_struct(rna_struct, ident):
identifier = rna_struct.identifier
rna_base = rna_struct.base
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 = []
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')
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())
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]
# 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')
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)
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')
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')
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():
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
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()
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!'
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()
rna_prop_type = rna_prop.type.lower()
if rna_prop_type=='collection': collection_str = 'Collection of '
else: collection_str = ''
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: rna_prop_ptr = rna_prop.fixed_type
except: rna_prop_ptr = None
try: length = rna_prop.array_length
except: length = 0
try: length = rna_prop.array_length
except: length = 0
array_str = get_array_str(length)
array_str = get_array_str(length)
if rna_prop.editable: readonly_str = ''
else: readonly_str = ' (readonly)'
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)
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@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')
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')
# 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')
out.write('\n')
# Now write children recursively
for child in rna_children_dict[identifier]:
write_struct(child, ident + '\t')
# 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
# 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
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)
#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
except: rna_struct = None
if rna_struct:
#if not rna_type_name.startswith('__'):
if rna_struct:
#if not rna_type_name.startswith('__'):
identifier = rna_struct.identifier
identifier = rna_struct.identifier
if not rna_id_ignore(identifier):
if not rna_id_ignore(identifier):
structs.append( (base_id(rna_struct), identifier, rna_struct) )
# Simple lookup
rna_struct_dict[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 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)
# 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]= []
# fill in these later
rna_children_dict[identifier]= []
rna_references_dict[identifier]= []
else:
print("Ignoring", rna_type_name)
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[:]
# 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
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()
# 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):
for i, (rna_base, identifier, rna_struct) in enumerate(structs):
rna_done.add(identifier)
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 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))
if not ok:
print('Dependancy "%s" could not be found for "%s"' % (identifier, rna_base))
break
break
# Done ordering structs
# Done ordering structs
# precalc vars to avoid a lot of looping
for (rna_base, identifier, rna_struct) in 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= []
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]
# 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_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
if rna_prop_identifier=='RNA': continue
if rna_id_ignore(rna_prop_identifier): continue
if rna_prop_identifier in rna_base_prop_keys: continue
try: rna_prop_ptr = rna_prop.fixed_type
except: rna_prop_ptr = None
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) )
# 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():
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
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
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) )
# 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)
# 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]
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
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()
# 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
for (rna_base, identifier, rna_struct) in structs:
if rna_struct.nested:
continue
write_struct(rna_struct, '')
write_struct(rna_struct, '')
out.write('\n')
out.close()
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')
# # 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
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')
# 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')
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
def isop(rna_struct):
return '_OT_' in rna_struct.identifier
for (rna_base, identifier, rna_struct) in structs:
if isop(rna_struct):
continue
for (rna_base, identifier, rna_struct) in structs:
if isop(rna_struct):
continue
base = rna_struct.base
base = rna_struct.base
out.write('\t"%s";\n' % identifier)
out.write('\t"%s";\n' % identifier)
for (rna_base, identifier, rna_struct) in structs:
for (rna_base, identifier, rna_struct) in structs:
if isop(rna_struct):
continue
if isop(rna_struct):
continue
base = rna_struct.base
base = rna_struct.base
if base and not isop(base):
out.write('\t"%s" -> "%s" [label="(base)" weight=1.0];\n' % (base.identifier, identifier))
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))
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]
rna_refs= rna_references_dict[identifier]
for rna_ref_string in rna_refs:
for rna_ref_string in rna_refs:
if '_OT_' in rna_ref_string:
continue
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))
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()
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')
# # 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)
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')
# out = open(target_path, 'w')
op_mods = dir(bpy.ops)
op_mods.remove('add')
op_mods.remove('remove')
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
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)
# 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):
op_mod = getattr(bpy.ops, op_mod_name)
operators = dir(op_mod)
for op in sorted(operators):
# rna = getattr(bpy.types, op).bl_rna
rna = getattr(op_mod, op).get_rna()
write_func(rna, '', out, 'OPERATOR')
rna = getattr(op_mod, op).get_rna()
write_func(rna, '', out, 'OPERATOR')
out.write('\n')
out.close()
out.write('\n')
out.close()
def misc2epy(BASEPATH):
'''
Hard coded modules, try to avoid adding stuff here
'''
'''
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('''
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('''
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
"""
"""
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
"""
"""
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
"""
"""
return a new float property
"""
def StringProperty(attr, name="", description="", maxlen=0, default=""):
"""
return a new string property
"""
"""
return a new string property
"""
def EnumProperty(attr, items, name="", description="", default=""):
"""
return a new enum property
"""
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')
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()
close_all()
import sys
sys.exit()
import sys
sys.exit()

View File

@@ -45,7 +45,7 @@
#include "BLI_math.h"
#define SWAP_FLOAT(a,b,tmp) tmp=a; a=b; b=tmp
#define eul 0.000001
#define eps 0.000001
/*-- forward declarations -- */
static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq );
@@ -252,18 +252,18 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
Py_RETURN_NONE;
}
/* Make sure the hoz/vert line comes first. */
if (fabs(b1x - b2x) < eul || fabs(b1y - b2y) < eul) {
if (fabs(b1x - b2x) < eps || fabs(b1y - b2y) < eps) {
SWAP_FLOAT(a1x, b1x, xi); /*abuse xi*/
SWAP_FLOAT(a1y, b1y, xi);
SWAP_FLOAT(a2x, b2x, xi);
SWAP_FLOAT(a2y, b2y, xi);
}
if (fabs(a1x-a2x) < eul) { /* verticle line */
if (fabs(b1x-b2x) < eul){ /*verticle second line */
if (fabs(a1x-a2x) < eps) { /* verticle line */
if (fabs(b1x-b2x) < eps){ /*verticle second line */
Py_RETURN_NONE; /* 2 verticle lines dont intersect. */
}
else if (fabs(b1y-b2y) < eul) {
else if (fabs(b1y-b2y) < eps) {
/*X of vert, Y of hoz. no calculation needed */
newvec[0]= a1x;
newvec[1]= b1y;
@@ -280,8 +280,8 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
newvec[0]= a1x;
newvec[1]= yi;
return newVectorObject(newvec, 2, Py_NEW, NULL);
} else if (fabs(a2y-a1y) < eul) { /* hoz line1 */
if (fabs(b2y-b1y) < eul) { /*hoz line2*/
} else if (fabs(a2y-a1y) < eps) { /* hoz line1 */
if (fabs(b2y-b1y) < eps) { /*hoz line2*/
Py_RETURN_NONE; /*2 hoz lines dont intersect*/
}

View File

@@ -0,0 +1,1026 @@
/**
* $Id: IDProp.c
*
* ***** 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): Joseph Eagar, Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "DNA_ID.h"
#include "BKE_idprop.h"
#include "IDProp.h"
// #include "gen_utils.h"
#include "MEM_guardedalloc.h"
#define BSTR_EQ(a, b) (*(a) == *(b) && !strcmp(a, b))
/*** Function to wrap ID properties ***/
PyObject *BPy_Wrap_IDProperty(ID *id, IDProperty *prop, IDProperty *parent);
extern PyTypeObject IDArray_Type;
extern PyTypeObject IDGroup_Iter_Type;
/*********************** ID Property Main Wrapper Stuff ***************/
PyObject *IDGroup_repr( BPy_IDProperty *self )
{
return PyUnicode_FromFormat( "<bpy ID property from \"%s\">", self->id->name);
}
extern PyTypeObject IDGroup_Type;
PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
{
switch ( prop->type ) {
case IDP_STRING:
return PyUnicode_FromString( prop->data.pointer );
case IDP_INT:
return PyLong_FromLong( (long)prop->data.val );
case IDP_FLOAT:
return PyFloat_FromDouble( (double)(*(float*)(&prop->data.val)) );
case IDP_DOUBLE:
return PyFloat_FromDouble( (*(double*)(&prop->data.val)) );
case IDP_GROUP:
/*blegh*/
{
BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &IDGroup_Type);
group->id = id;
group->prop = prop;
return (PyObject*) group;
}
case IDP_ARRAY:
{
BPy_IDProperty *array = PyObject_New(BPy_IDProperty, &IDArray_Type);
array->id = id;
array->prop = prop;
return (PyObject*) array;
}
}
Py_RETURN_NONE;
}
int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject *value)
{
switch (prop->type) {
case IDP_STRING:
{
char *st;
if (!PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expected a string!");
return -1;
}
st = _PyUnicode_AsString(value);
IDP_ResizeArray(prop, strlen(st)+1);
strcpy(prop->data.pointer, st);
return 0;
}
case IDP_INT:
{
int ivalue= PyLong_AsSsize_t(value);
if (ivalue==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected an int type");
return -1;
}
prop->data.val = ivalue;
break;
}
case IDP_FLOAT:
{
float fvalue= (float)PyFloat_AsDouble(value);
if (fvalue==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected a float");
return -1;
}
*(float*)&self->prop->data.val = fvalue;
break;
}
case IDP_DOUBLE:
{
double dvalue= PyFloat_AsDouble(value);
if (dvalue==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected a float");
return -1;
}
*(double*)&self->prop->data.val = dvalue;
break;
}
default:
PyErr_SetString(PyExc_AttributeError, "attempt to set read-only attribute!");
return -1;
}
return 0;
}
PyObject *BPy_IDGroup_GetName(BPy_IDProperty *self, void *bleh)
{
return PyUnicode_FromString(self->prop->name);
}
static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *bleh)
{
char *st;
if (!PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expected a string!");
return -1;
}
st = _PyUnicode_AsString(value);
if (strlen(st) >= MAX_IDPROP_NAME) {
PyErr_SetString(PyExc_TypeError, "string length cannot exceed 31 characters!");
return -1;
}
strcpy(self->prop->name, st);
return 0;
}
#if 0
static PyObject *BPy_IDGroup_GetType(BPy_IDProperty *self)
{
return PyLong_FromSsize_t(self->prop->type);
}
#endif
static PyGetSetDef BPy_IDGroup_getseters[] = {
{"name",
(getter)BPy_IDGroup_GetName, (setter)BPy_IDGroup_SetName,
"The name of this Group.",
NULL},
{NULL, NULL, NULL, NULL, NULL}
};
static Py_ssize_t BPy_IDGroup_Map_Len(BPy_IDProperty *self)
{
if (self->prop->type != IDP_GROUP) {
PyErr_SetString( PyExc_TypeError, "len() of unsized object");
return -1;
}
return self->prop->len;
}
static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item)
{
IDProperty *idprop;
char *name;
if (self->prop->type != IDP_GROUP) {
PyErr_SetString( PyExc_TypeError, "unsubscriptable object");
return NULL;
}
name= _PyUnicode_AsString(item);
if (name == NULL) {
PyErr_SetString( PyExc_TypeError, "only strings are allowed as keys of ID properties");
return NULL;
}
idprop= IDP_GetPropertyFromGroup(self->prop, name);
if(idprop==NULL) {
PyErr_SetString( PyExc_KeyError, "key not in subgroup dict");
return NULL;
}
return BPy_IDGroup_WrapData(self->id, idprop);
}
/*returns NULL on success, error string on failure*/
char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObject *ob)
{
IDProperty *prop = NULL;
IDPropertyTemplate val = {0};
if(strlen(name) >= sizeof(group->name))
return "the length of IDProperty names is limited to 31 characters";
if (PyFloat_Check(ob)) {
val.d = PyFloat_AsDouble(ob);
prop = IDP_New(IDP_DOUBLE, val, name);
} else if (PyLong_Check(ob)) {
val.i = (int) PyLong_AsSsize_t(ob);
prop = IDP_New(IDP_INT, val, name);
} else if (PyUnicode_Check(ob)) {
val.str = _PyUnicode_AsString(ob);
prop = IDP_New(IDP_STRING, val, name);
} else if (PySequence_Check(ob)) {
PyObject *item;
int i;
/*validate sequence and derive type.
we assume IDP_INT unless we hit a float
number; then we assume it's */
val.array.type = IDP_INT;
val.array.len = PySequence_Length(ob);
for (i=0; i<val.array.len; i++) {
item = PySequence_GetItem(ob, i);
if (PyFloat_Check(item)) val.array.type = IDP_DOUBLE;
else if (!PyLong_Check(item)) {
Py_XDECREF(item);
return "only floats and ints are allowed in ID property arrays";
}
Py_XDECREF(item);
}
prop = IDP_New(IDP_ARRAY, val, name);
for (i=0; i<val.array.len; i++) {
item = PySequence_GetItem(ob, i);
if (val.array.type == IDP_INT) {
((int*)prop->data.pointer)[i] = (int)PyLong_AsSsize_t(item);
} else {
((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
}
}
} else if (PyMapping_Check(ob)) {
PyObject *keys, *vals, *key, *pval;
int i, len;
/*yay! we get into recursive stuff now!*/
keys = PyMapping_Keys(ob);
vals = PyMapping_Values(ob);
/*we allocate the group first; if we hit any invalid data,
we can delete it easily enough.*/
prop = IDP_New(IDP_GROUP, val, name);
len = PyMapping_Length(ob);
for (i=0; i<len; i++) {
key = PySequence_GetItem(keys, i);
pval = PySequence_GetItem(vals, i);
if (!PyUnicode_Check(key)) {
IDP_FreeProperty(prop);
MEM_freeN(prop);
Py_XDECREF(keys);
Py_XDECREF(vals);
Py_XDECREF(key);
Py_XDECREF(pval);
return "invalid element in subgroup dict template!";
}
if (BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, pval)) {
IDP_FreeProperty(prop);
MEM_freeN(prop);
Py_XDECREF(keys);
Py_XDECREF(vals);
Py_XDECREF(key);
Py_XDECREF(pval);
return "invalid element in subgroup dict template!";
}
Py_XDECREF(key);
Py_XDECREF(pval);
}
Py_XDECREF(keys);
Py_XDECREF(vals);
} else return "invalid property value";
IDP_ReplaceInGroup(group, prop);
return NULL;
}
int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val)
{
if (prop->type != IDP_GROUP) {
PyErr_SetString( PyExc_TypeError, "unsubscriptable object");
return -1;
}
if (val == NULL) { /* del idprop[key] */
IDProperty *pkey = IDP_GetPropertyFromGroup(prop, _PyUnicode_AsString(key));
if (pkey) {
IDP_RemFromGroup(prop, pkey);
IDP_FreeProperty(pkey);
MEM_freeN(pkey);
return 0;
} else {
PyErr_SetString( PyExc_KeyError, "property not found in group" );
return -1;
}
}
else {
char *err;
if (!PyUnicode_Check(key)) {
PyErr_SetString( PyExc_TypeError, "only strings are allowed as subgroup keys" );
return -1;
}
err = BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, val);
if (err) {
PyErr_SetString( PyExc_KeyError, err );
return -1;
}
return 0;
}
}
static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject *val)
{
return BPy_Wrap_SetMapItem(self->prop, key, val);
}
static PyObject *BPy_IDGroup_SpawnIterator(BPy_IDProperty *self)
{
BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &IDGroup_Iter_Type);
iter->group = self;
iter->mode = IDPROP_ITER_KEYS;
iter->cur = self->prop->data.group.first;
Py_XINCREF(iter);
return (PyObject*) iter;
}
static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
{
switch (prop->type) {
case IDP_STRING:
return PyUnicode_FromString(prop->data.pointer);
break;
case IDP_FLOAT:
return PyFloat_FromDouble(*((float*)&prop->data.val));
break;
case IDP_DOUBLE:
return PyFloat_FromDouble(*((double*)&prop->data.val));
break;
case IDP_INT:
return PyLong_FromSsize_t( prop->data.val );
break;
case IDP_ARRAY:
{
PyObject *seq = PyList_New(prop->len);
int i;
if (!seq) {
PyErr_SetString( PyExc_RuntimeError, "PyList_New() failed" );
return NULL;
}
for (i=0; i<prop->len; i++) {
if (prop->subtype == IDP_FLOAT) {
PyList_SET_ITEM(seq, i,
PyFloat_FromDouble(((float*)prop->data.pointer)[i]));
} else if (prop->subtype == IDP_DOUBLE) {
PyList_SET_ITEM(seq, i,
PyFloat_FromDouble(((double*)prop->data.pointer)[i]));
} else {
PyList_SET_ITEM(seq, i,
PyLong_FromLong(((int*)prop->data.pointer)[i]));
}
}
return seq;
}
case IDP_GROUP:
{
PyObject *dict = PyDict_New(), *wrap;
IDProperty *loop;
if (!dict) {
PyErr_SetString( PyExc_RuntimeError, "PyDict_New() failed" );
return NULL;
}
for (loop=prop->data.group.first; loop; loop=loop->next) {
wrap = BPy_IDGroup_MapDataToPy(loop);
if (!wrap) {
PyErr_SetString( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy() failed" );
return NULL;
}
PyDict_SetItemString(dict, loop->name, wrap);
}
return dict;
}
}
PyErr_SetString( PyExc_RuntimeError, "eek!! a property exists with a bad type code!!!" );
return NULL;
}
static PyObject *BPy_IDGroup_Pop(BPy_IDProperty *self, PyObject *value)
{
IDProperty *idprop;
PyObject *pyform;
char *name = _PyUnicode_AsString(value);
if (!name) {
PyErr_SetString( PyExc_TypeError, "pop expected at least 1 argument, got 0" );
return NULL;
}
idprop= IDP_GetPropertyFromGroup(self->prop, name);
if(idprop) {
pyform = BPy_IDGroup_MapDataToPy(idprop);
if (!pyform) {
/*ok something bad happened with the pyobject,
so don't remove the prop from the group. if pyform is
NULL, then it already should have raised an exception.*/
return NULL;
}
IDP_RemFromGroup(self->prop, idprop);
return pyform;
}
PyErr_SetString( PyExc_KeyError, "item not in group" );
return NULL;
}
static PyObject *BPy_IDGroup_IterItems(BPy_IDProperty *self)
{
BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &IDGroup_Iter_Type);
iter->group = self;
iter->mode = IDPROP_ITER_ITEMS;
iter->cur = self->prop->data.group.first;
Py_XINCREF(iter);
return (PyObject*) iter;
}
/* utility function */
static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len)
{
int j;
printf("ID Property Error found and corrected in BPy_IDGroup_GetKeys/Values/Items!\n");
/*fill rest of list with valid references to None*/
for (j=len; j<prop->len; j++) {
Py_INCREF(Py_None);
PyList_SET_ITEM(seq, j, Py_None);
}
/*set correct group length*/
prop->len = len;
}
PyObject *BPy_Wrap_GetKeys(IDProperty *prop)
{
PyObject *seq = PyList_New(prop->len);
IDProperty *loop;
int i;
for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++)
PyList_SET_ITEM(seq, i, PyUnicode_FromString(loop->name));
if (i != prop->len) {
BPy_IDGroup_CorrectListLen(prop, seq, i);
Py_DECREF(seq); /*free the list*/
/*call self again*/
return BPy_Wrap_GetKeys(prop);
}
return seq;
}
PyObject *BPy_Wrap_GetValues(ID *id, IDProperty *prop)
{
PyObject *seq = PyList_New(prop->len);
IDProperty *loop;
int i;
for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++) {
PyList_SET_ITEM(seq, i, BPy_IDGroup_WrapData(id, loop));
}
if (i != prop->len) {
BPy_IDGroup_CorrectListLen(prop, seq, i);
Py_DECREF(seq); /*free the list*/
/*call self again*/
return BPy_Wrap_GetValues(id, prop);
}
return seq;
}
PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop)
{
PyObject *seq = PyList_New(prop->len);
IDProperty *loop;
int i;
for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++) {
PyObject *item= PyTuple_New(2);
PyTuple_SET_ITEM(item, 0, PyUnicode_FromString(loop->name));
PyTuple_SET_ITEM(item, 1, BPy_IDGroup_WrapData(id, loop));
PyList_SET_ITEM(seq, i, item);
}
if (i != prop->len) {
BPy_IDGroup_CorrectListLen(prop, seq, i);
Py_DECREF(seq); /*free the list*/
/*call self again*/
return BPy_Wrap_GetItems(id, prop);
}
return seq;
}
static PyObject *BPy_IDGroup_GetKeys(BPy_IDProperty *self)
{
return BPy_Wrap_GetKeys(self->prop);
}
static PyObject *BPy_IDGroup_GetValues(BPy_IDProperty *self)
{
return BPy_Wrap_GetValues(self->id, self->prop);
}
static PyObject *BPy_IDGroup_GetItems(BPy_IDProperty *self)
{
return BPy_Wrap_GetItems(self->id, self->prop);
}
static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value)
{
char *name = _PyUnicode_AsString(value);
if (!name) {
PyErr_SetString( PyExc_TypeError, "expected a string");
return -1;
}
return IDP_GetPropertyFromGroup(self->prop, name) ? 1:0;
}
static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *value)
{
PyObject *pkey, *pval;
Py_ssize_t i=0;
if (!PyDict_Check(value)) {
PyErr_SetString( PyExc_TypeError, "expected an object derived from dict.");
return NULL;
}
while (PyDict_Next(value, &i, &pkey, &pval)) {
BPy_IDGroup_Map_SetItem(self, pkey, pval);
if (PyErr_Occurred()) return NULL;
}
Py_RETURN_NONE;
}
static PyObject *BPy_IDGroup_ConvertToPy(BPy_IDProperty *self)
{
return BPy_IDGroup_MapDataToPy(self->prop);
}
/* Matches python dict.get(key, [default]) */
PyObject* BPy_IDGroup_Get(BPy_IDProperty *self, PyObject *args)
{
IDProperty *idprop;
char *key;
PyObject* def = Py_None;
if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
return NULL;
idprop= IDP_GetPropertyFromGroup(self->prop, key);
if (idprop) {
PyObject* pyobj = BPy_IDGroup_WrapData(self->id, idprop);
if (pyobj)
return pyobj;
}
Py_INCREF(def);
return def;
}
static struct PyMethodDef BPy_IDGroup_methods[] = {
{"pop", (PyCFunction)BPy_IDGroup_Pop, METH_O,
"pop an item from the group; raises KeyError if the item doesn't exist."},
{"iteritems", (PyCFunction)BPy_IDGroup_IterItems, METH_NOARGS,
"iterate through the items in the dict; behaves like dictionary method iteritems."},
{"keys", (PyCFunction)BPy_IDGroup_GetKeys, METH_NOARGS,
"get the keys associated with this group as a list of strings."},
{"values", (PyCFunction)BPy_IDGroup_GetValues, METH_NOARGS,
"get the values associated with this group."},
{"items", (PyCFunction)BPy_IDGroup_GetItems, METH_NOARGS,
"get the items associated with this group."},
{"update", (PyCFunction)BPy_IDGroup_Update, METH_O,
"updates the values in the group with the values of another or a dict."},
{"get", (PyCFunction)BPy_IDGroup_Get, METH_VARARGS,
"idprop.get(k[,d]) -> idprop[k] if k in idprop, else d. d defaults to None."},
{"convert_to_pyobject", (PyCFunction)BPy_IDGroup_ConvertToPy, METH_NOARGS,
"return a purely python version of the group."},
{0, NULL, 0, NULL}
};
static PySequenceMethods BPy_IDGroup_Seq = {
(lenfunc) BPy_IDGroup_Map_Len, /* lenfunc sq_length */
0, /* binaryfunc sq_concat */
0, /* ssizeargfunc sq_repeat */
0, /* ssizeargfunc sq_item */ /* TODO - setting this will allow PySequence_Check to return True */
0, /* intintargfunc ***was_sq_slice*** */
0, /* intobjargproc sq_ass_item */
0, /* ssizeobjargproc ***was_sq_ass_slice*** */
(objobjproc) BPy_IDGroup_Contains, /* objobjproc sq_contains */
0, /* binaryfunc sq_inplace_concat */
0, /* ssizeargfunc sq_inplace_repeat */
};
PyMappingMethods BPy_IDGroup_Mapping = {
(lenfunc)BPy_IDGroup_Map_Len, /*inquiry mp_length */
(binaryfunc)BPy_IDGroup_Map_GetItem, /*binaryfunc mp_subscript */
(objobjargproc)BPy_IDGroup_Map_SetItem, /*objobjargproc mp_ass_subscript */
};
PyTypeObject IDGroup_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"Blender IDProperty", /* char *tp_name; */
sizeof( BPy_IDProperty ), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
/* Methods to implement standard operations */
NULL, /* destructor tp_dealloc; */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
( reprfunc ) IDGroup_repr, /* reprfunc tp_repr; */
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
&BPy_IDGroup_Seq, /* PySequenceMethods *tp_as_sequence; */
&BPy_IDGroup_Mapping, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0, /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
(getiterfunc)BPy_IDGroup_SpawnIterator, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
BPy_IDGroup_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
BPy_IDGroup_getseters, /* struct PyGetSetDef *tp_getset; */
};
/*********** Main external wrapping function *******/
PyObject *BPy_Wrap_IDProperty(ID *id, IDProperty *prop, IDProperty *parent)
{
BPy_IDProperty *wrap = PyObject_New(BPy_IDProperty, &IDGroup_Type);
wrap->prop = prop;
wrap->parent = parent;
wrap->id = id;
//wrap->destroy = 0;
return (PyObject*) wrap;
}
/********Array Wrapper********/
static PyObject *IDArray_repr(BPy_IDArray *self)
{
return PyUnicode_FromString("(ID Array)");
}
static PyObject *BPy_IDArray_GetType(BPy_IDArray *self)
{
return PyLong_FromSsize_t( self->prop->subtype );
}
static PyObject *BPy_IDArray_GetLen(BPy_IDArray *self)
{
return PyLong_FromSsize_t( self->prop->len );
}
static PyGetSetDef BPy_IDArray_getseters[] = {
{"len",
(getter)BPy_IDArray_GetLen, (setter)NULL,
"The length of the array, can also be gotten with len(array).",
NULL},
{"type",
(getter)BPy_IDArray_GetType, (setter)NULL,
"The type of the data in the array, is an ant.",
NULL},
{NULL, NULL, NULL, NULL, NULL},
};
static PyObject *BPy_IDArray_ConvertToPy(BPy_IDArray *self)
{
return BPy_IDGroup_MapDataToPy(self->prop);
}
static PyMethodDef BPy_IDArray_methods[] = {
{"convert_to_pyobject", (PyCFunction)BPy_IDArray_ConvertToPy, METH_NOARGS,
"return a purely python version of the group."},
{0, NULL, 0, NULL}
};
static int BPy_IDArray_Len(BPy_IDArray *self)
{
return self->prop->len;
}
static PyObject *BPy_IDArray_GetItem(BPy_IDArray *self, int index)
{
if (index < 0 || index >= self->prop->len) {
PyErr_SetString( PyExc_IndexError, "index out of range!");
return NULL;
}
switch (self->prop->subtype) {
case IDP_FLOAT:
return PyFloat_FromDouble( (double)(((float*)self->prop->data.pointer)[index]));
break;
case IDP_DOUBLE:
return PyFloat_FromDouble( (((double*)self->prop->data.pointer)[index]));
break;
case IDP_INT:
return PyLong_FromLong( (long)((int*)self->prop->data.pointer)[index] );
break;
}
PyErr_SetString( PyExc_RuntimeError, "invalid/corrupt array type!");
return NULL;
}
static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value)
{
int i;
float f;
double d;
if (index < 0 || index >= self->prop->len) {
PyErr_SetString( PyExc_RuntimeError, "index out of range!");
return -1;
}
switch (self->prop->subtype) {
case IDP_FLOAT:
f= (float)PyFloat_AsDouble(value);
if (f==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected a float");
return -1;
}
((float*)self->prop->data.pointer)[index] = f;
break;
case IDP_DOUBLE:
d= PyFloat_AsDouble(value);
if (d==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected a float");
return -1;
}
((double*)self->prop->data.pointer)[index] = d;
break;
case IDP_INT:
i= PyLong_AsSsize_t(value);
if (i==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected an int type");
return -1;
}
((int*)self->prop->data.pointer)[index] = i;
break;
}
return 0;
}
static PySequenceMethods BPy_IDArray_Seq = {
(lenfunc) BPy_IDArray_Len, /* inquiry sq_length */
0, /* binaryfunc sq_concat */
0, /* intargfunc sq_repeat */
(ssizeargfunc)BPy_IDArray_GetItem, /* intargfunc sq_item */
0, /* intintargfunc sq_slice */
(ssizeobjargproc)BPy_IDArray_SetItem, /* intobjargproc sq_ass_item */
0, /* intintobjargproc sq_ass_slice */
0, /* objobjproc sq_contains */
/* Added in release 2.0 */
0, /* binaryfunc sq_inplace_concat */
0, /* intargfunc sq_inplace_repeat */
};
PyTypeObject IDArray_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"Blender IDArray", /* char *tp_name; */
sizeof( BPy_IDArray ), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
/* Methods to implement standard operations */
NULL, /* destructor tp_dealloc; */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
( reprfunc ) IDArray_repr, /* reprfunc tp_repr; */
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
&BPy_IDArray_Seq, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0, /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
BPy_IDArray_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
BPy_IDArray_getseters, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
NULL, /* descrsetfunc tp_descr_set; */
0, /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
NULL, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
/* method resolution order */
NULL, /* PyObject *tp_mro; */
NULL, /* PyObject *tp_cache; */
NULL, /* PyObject *tp_subclasses; */
NULL, /* PyObject *tp_weaklist; */
NULL
};
/*********** ID Property Group iterator ********/
static PyObject *IDGroup_Iter_iterself(PyObject *self)
{
Py_XINCREF(self);
return self;
}
static PyObject *IDGroup_Iter_repr(BPy_IDGroup_Iter *self)
{
return PyUnicode_FromString("(ID Property Group)");
}
static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
{
IDProperty *cur=NULL;
PyObject *ret;
if (self->cur) {
cur = self->cur;
self->cur = self->cur->next;
if (self->mode == IDPROP_ITER_ITEMS) {
ret = PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(cur->name));
PyTuple_SET_ITEM(ret, 1, BPy_IDGroup_WrapData(self->group->id, cur));
return ret;
} else {
return PyUnicode_FromString(cur->name);
}
} else {
PyErr_SetString( PyExc_StopIteration, "iterator at end" );
return NULL;
}
}
PyTypeObject IDGroup_Iter_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"Blender IDGroup_Iter", /* char *tp_name; */
sizeof( BPy_IDGroup_Iter ), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
/* Methods to implement standard operations */
NULL, /* destructor tp_dealloc; */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
( reprfunc ) IDGroup_Iter_repr, /* reprfunc tp_repr; */
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0, /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
IDGroup_Iter_iterself, /* getiterfunc tp_iter; */
(iternextfunc) BPy_Group_Iter_Next, /* iternextfunc tp_iternext; */
};
void IDProp_Init_Types(void)
{
PyType_Ready( &IDGroup_Type );
PyType_Ready( &IDGroup_Iter_Type );
PyType_Ready( &IDArray_Type );
}

View File

@@ -0,0 +1,64 @@
/**
* $Id: IDProp.h
*
* ***** 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): Joseph Eagar, Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <Python.h>
struct ID;
struct IDProperty;
struct BPy_IDGroup_Iter;
typedef struct BPy_IDProperty {
PyObject_VAR_HEAD
struct ID *id;
struct IDProperty *prop, *parent;
PyObject *data_wrap;
} BPy_IDProperty;
typedef struct BPy_IDArray {
PyObject_VAR_HEAD
struct ID *id;
struct IDProperty *prop;
} BPy_IDArray;
typedef struct BPy_IDGroup_Iter {
PyObject_VAR_HEAD
BPy_IDProperty *group;
struct IDProperty *cur;
int mode;
} BPy_IDGroup_Iter;
PyObject *BPy_Wrap_IDProperty(struct ID *id, struct IDProperty *prop, struct IDProperty *parent);
PyObject *BPy_Wrap_GetKeys(IDProperty *prop);
PyObject *BPy_Wrap_GetValues(ID *id, IDProperty *prop);
PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop);
int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val);
PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop );
char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObject *ob);
void IDProp_Init_Types(void);
#define IDPROP_ITER_KEYS 0
#define IDPROP_ITER_ITEMS 1

View File

@@ -54,12 +54,35 @@ void bpy_import_main_set(struct Main *maggie)
bpy_import_main= maggie;
}
PyObject *bpy_text_import( Text *text )
{
char *buf = NULL;
char modulename[24];
int len;
PyObject *bpy_text_import( char *name, int *found )
if( !text->compiled ) {
buf = txt_to_buf( text );
text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
MEM_freeN( buf );
if( PyErr_Occurred( ) ) {
PyErr_Print( );
PyErr_Clear( );
PySys_SetObject("last_traceback", NULL);
free_compiled_text( text );
return NULL;
}
}
len= strlen(text->id.name+2) - 3;
strncpy(modulename, text->id.name+2, len);
return PyImport_ExecCodeModule(modulename, text->compiled);
}
PyObject *bpy_text_import_name( char *name, int *found )
{
Text *text;
char txtname[22]; /* 21+NULL */
char *buf = NULL;
int namelen = strlen( name );
//XXX Main *maggie= bpy_import_main ? bpy_import_main:G.main;
Main *maggie= bpy_import_main;
@@ -86,21 +109,7 @@ PyObject *bpy_text_import( char *name, int *found )
else
*found = 1;
if( !text->compiled ) {
buf = txt_to_buf( text );
text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
MEM_freeN( buf );
if( PyErr_Occurred( ) ) {
PyErr_Print( );
PyErr_Clear( );
PySys_SetObject("last_traceback", NULL);
free_compiled_text( text );
return NULL;
}
}
return PyImport_ExecCodeModule( name, text->compiled );
return bpy_text_import(text);
}
@@ -195,7 +204,7 @@ static PyObject *blender_import( PyObject * self, PyObject * args, PyObject * k
PyErr_Fetch( &exception, &err, &tb ); /* get the python error incase we cant import as blender text either */
/* importing from existing modules failed, see if we have this module as blender text */
newmodule = bpy_text_import( name, &found );
newmodule = bpy_text_import_name( name, &found );
if( newmodule ) {/* found module as blender text, ignore above exception */
PyErr_Clear( );

View File

@@ -44,7 +44,10 @@
#include "compile.h" /* for the PyCodeObject */
#include "eval.h" /* for PyEval_EvalCode */
PyObject* bpy_text_import( char *name, int *found );
struct Text;
PyObject* bpy_text_import( struct Text *text );
PyObject* bpy_text_import_name( char *name, int *found );
PyObject* bpy_text_reimport( PyObject *module, int *found );
/* void bpy_text_clear_modules( int clear_all );*/ /* Clear user modules */
extern PyMethodDef bpy_import_meth[];

View File

@@ -65,6 +65,7 @@
#include "BKE_text.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BPY_extern.h"
@@ -74,6 +75,7 @@
#include "../generic/Mathutils.h"
#include "../generic/Geometry.h"
#include "../generic/BGL.h"
#include "../generic/IDProp.h"
/* for internal use, when starting and ending python scripts */
@@ -176,7 +178,7 @@ static BPy_StructRNA *bpy_context_module= NULL; /* for fast access */
static void bpy_init_modules( void )
{
PyObject *mod;
/* Needs to be first since this dir is needed for future modules */
char *modpath= BLI_gethome_folder("scripts/modules", BLI_GETHOME_ALL);
if(modpath) {
@@ -186,10 +188,17 @@ static void bpy_init_modules( void )
Py_DECREF(py_modpath);
}
mod = PyModule_New("bpy");
/* stand alone utility modules not related to blender directly */
Geometry_Init();
Mathutils_Init();
BGL_Init();
IDProp_Init_Types();
mod = PyModule_New("_bpy");
/* add the module so we can import it */
PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
PyDict_SetItemString(PySys_GetObject("modules"), "_bpy", mod);
Py_DECREF(mod);
/* run first, initializes rna types */
@@ -201,7 +210,7 @@ static void bpy_init_modules( void )
bpy_import_test("bpy_types");
/* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
PyModule_AddObject( mod, "props", BPY_rna_props() );
PyModule_AddObject( mod, "__ops__", BPY_operator_module() ); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */
PyModule_AddObject( mod, "ops", BPY_operator_module() ); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */
PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent
@@ -214,16 +223,8 @@ static void bpy_init_modules( void )
PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
}
/* stand alone utility modules not related to blender directly */
Geometry_Init();
Mathutils_Init();
BGL_Init();
/* add our own modules dir */
{
bpy_import_test("bpy_ops"); /* adds its self to bpy.ops */
bpy_import_test("bpy_utils"); /* adds its self to bpy.sys */
}
/* add our own modules dir, this is a python package */
bpy_import_test("bpy");
}
void BPY_update_modules( void )
@@ -242,34 +243,24 @@ void BPY_update_modules( void )
/*****************************************************************************
* Description: This function creates a new Python dictionary object.
*****************************************************************************/
static PyObject *CreateGlobalDictionary( bContext *C )
static PyObject *CreateGlobalDictionary( bContext *C, const char *filename )
{
PyObject *mod;
PyObject *item;
PyObject *dict = PyDict_New( );
PyObject *item = PyUnicode_FromString( "__main__" );
PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins( ) );
item = PyUnicode_FromString( "__main__" );
PyDict_SetItemString( dict, "__name__", item );
Py_DECREF(item);
// XXX - put somewhere more logical
{
PyMethodDef *ml;
static PyMethodDef bpy_prop_meths[] = {
{"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"CollectionProperty", (PyCFunction)BPy_CollectionProperty, METH_VARARGS|METH_KEYWORDS, ""},
{NULL, NULL, 0, NULL}
};
for(ml = bpy_prop_meths; ml->ml_name; ml++) {
PyDict_SetItemString( dict, ml->ml_name, PyCFunction_New(ml, NULL));
}
/* __file__ only for nice UI'ness */
if(filename) {
PyObject *item = PyUnicode_FromString( filename );
PyDict_SetItemString( dict, "__file__", item );
Py_DECREF(item);
}
/* add bpy to global namespace */
mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
PyDict_SetItemString( dict, "bpy", mod );
@@ -303,6 +294,13 @@ void BPY_start_python_path(void)
}
void BPY_set_context(bContext *C)
{
BPy_SetContext(C);
}
/* call BPY_set_context first */
void BPY_start_python( int argc, char **argv )
{
PyThreadState *py_tstate = NULL;
@@ -341,11 +339,6 @@ void BPY_start_python( int argc, char **argv )
PyObject *d = PyEval_GetBuiltins( );
PyDict_SetItemString(d, "reload", item=PyCFunction_New(bpy_reload_meth, NULL)); Py_DECREF(item);
PyDict_SetItemString(d, "__import__", item=PyCFunction_New(bpy_import_meth, NULL)); Py_DECREF(item);
/* 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 :| */
PySys_SetObject("stdin", Py_None);
}
pyrna_alloc_types();
@@ -400,7 +393,7 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
bpy_context_set(C, &gilstate);
py_dict = CreateGlobalDictionary(C);
py_dict = CreateGlobalDictionary(C, text?text->id.name+2:fn);
if (text) {
@@ -420,24 +413,32 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
py_result = PyEval_EvalCode( text->compiled, py_dict, py_dict );
} else {
#if 0
char *pystring;
pystring= malloc(strlen(fn) + 32);
pystring[0]= '\0';
sprintf(pystring, "exec(open(r'%s').read())", fn);
py_result = PyRun_String( pystring, Py_file_input, py_dict, py_dict );
free(pystring);
#else
FILE *fp= fopen(fn, "r");
if(fp) {
#ifdef _WIN32
/* Previously we used PyRun_File to run directly the code on a FILE
* object, but as written in the Python/C API Ref Manual, chapter 2,
* 'FILE structs for different C libraries can be different and
* incompatible'.
* So now we load the script file data to a buffer */
char *pystring;
fclose(fp);
pystring= malloc(strlen(fn) + 32);
pystring[0]= '\0';
sprintf(pystring, "exec(open(r'%s').read())", fn);
py_result = PyRun_String( pystring, Py_file_input, py_dict, py_dict );
free(pystring);
#else
py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict);
fclose(fp);
#endif
}
else {
PyErr_Format(PyExc_SystemError, "Python file \"%s\" could not be opened: %s", fn, strerror(errno));
py_result= NULL;
}
#endif
}
if (!py_result) {
@@ -595,117 +596,6 @@ int BPY_run_python_script_space(const char *modulename, const char *func)
#include "PIL_time.h"
#endif
/* for use by BPY_run_ui_scripts only */
static int bpy_import_module(char *modname, int reload)
{
PyObject *mod= PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0);
if (mod) {
if (reload) {
PyObject *mod_orig= mod;
mod= PyImport_ReloadModule(mod);
Py_DECREF(mod_orig);
}
}
if(mod) {
Py_DECREF(mod); /* could be NULL from reloading */
return 0;
} else {
return -1;
}
}
/* XXX this is temporary, need a proper script registration system for 2.5 */
void BPY_run_ui_scripts(bContext *C, int reload)
{
#ifdef TIME_REGISTRATION
double time = PIL_check_seconds_timer();
#endif
DIR *dir;
struct dirent *de;
char *file_extension;
char *dirname;
char path[FILE_MAX];
char *dirs[] = {"scripts/ui", "scripts/op", "scripts/io", NULL};
int path_flags[] = {BLI_GETHOME_LOCAL|BLI_GETHOME_SYSTEM, BLI_GETHOME_USER}; /* SYSTEM / NON-SYSTEM */
int a, err, flag_iter;
PyGILState_STATE gilstate;
PyObject *sys_path;
bpy_context_set(C, &gilstate);
sys_path= PySys_GetObject("path"); /* borrow */
PyList_Insert(sys_path, 0, Py_None); /* place holder, resizes the list */
/* Scan system scripts first, then local/user */
for(flag_iter=0; flag_iter < sizeof(path_flags)/sizeof(int); flag_iter++) {
for(a=0; dirs[a]; a++) {
dirname= BLI_gethome_folder(dirs[a], path_flags[flag_iter]);
if(!dirname)
continue;
dir = opendir(dirname);
if(!dir)
continue;
/* set the first dir in the sys.path for fast importing of modules */
PyList_SetItem(sys_path, 0, PyUnicode_FromString(dirname)); /* steals the ref */
while((de = readdir(dir)) != NULL) {
/* We could stat the file but easier just to let python
* import it and complain if theres a problem */
err = 0;
if (de->d_name[0] == '.') {
/* do nothing, probably .svn */
}
else if ((file_extension = strstr(de->d_name, ".py"))) {
/* normal py files? */
if(file_extension && file_extension[3] == '\0') {
de->d_name[(file_extension - de->d_name)] = '\0';
err= bpy_import_module(de->d_name, reload);
}
}
#ifndef __linux__
else if( BLI_join_dirfile(path, dirname, de->d_name), S_ISDIR(BLI_exist(path))) {
#else
else if(de->d_type==DT_DIR) {
BLI_join_dirfile(path, dirname, de->d_name);
#endif
/* support packages */
BLI_join_dirfile(path, path, "__init__.py");
if(BLI_exists(path)) {
err= bpy_import_module(de->d_name, reload);
}
}
if(err==-1) {
BPy_errors_to_report(NULL);
fprintf(stderr, "unable to import %s/%s\n", dirname, de->d_name);
}
}
closedir(dir);
}
}
PyList_SetSlice(sys_path, 0, 1, NULL); /* remove the first item */
bpy_context_clear(C, &gilstate);
#ifdef TIME_REGISTRATION
printf("script time %f\n", (PIL_check_seconds_timer()-time));
#endif
/* reset the timer so as not to take loading into the stats */
bpy_timer_count = 0;
}
/* ****************************************** */
/* Drivers - PyExpression Evaluation */
@@ -912,7 +802,7 @@ int BPY_button_eval(bContext *C, char *expr, double *value)
bpy_context_set(C, &gilstate);
dict= CreateGlobalDictionary(C);
dict= CreateGlobalDictionary(C, NULL);
/* import some modules: builtins,math*/
PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
@@ -968,7 +858,28 @@ int BPY_button_eval(bContext *C, char *expr, double *value)
return error_ret;
}
void BPY_load_user_modules(bContext *C)
{
PyGILState_STATE gilstate;
Text *text;
bpy_context_set(C, &gilstate);
for(text=CTX_data_main(C)->text.first; text; text= text->id.next) {
if(text->flags & TXT_ISSCRIPT && BLI_testextensie(text->id.name+2, ".py")) {
PyObject *module= bpy_text_import(text);
if (module==NULL) {
PyErr_Print();
PyErr_Clear();
}
else {
Py_DECREF(module);
}
}
}
bpy_context_clear(C, &gilstate);
}
int BPY_context_get(bContext *C, const char *member, bContextDataResult *result)
{

View File

@@ -57,13 +57,13 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
// XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it...
bContext *C = BPy_GetContext();
if (!PyArg_ParseTuple(args, "sO|O!i:bpy.__ops__.call", &opname, &context_dict, &PyDict_Type, &kw, &context))
if (!PyArg_ParseTuple(args, "sO|O!i:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context))
return NULL;
ot= WM_operatortype_find(opname, TRUE);
if (ot == NULL) {
PyErr_Format( PyExc_SystemError, "bpy.__ops__.call: operator \"%s\"could not be found", opname);
PyErr_Format( PyExc_SystemError, "_bpy.ops.call: operator \"%s\"could not be found", opname);
return NULL;
}
@@ -76,7 +76,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
Py_XINCREF(context_dict); /* so we done loose it */
if(WM_operator_poll((bContext*)C, ot) == FALSE) {
PyErr_SetString( PyExc_SystemError, "bpy.__ops__.call: operator poll() function failed, context is incorrect");
PyErr_SetString( PyExc_SystemError, "_bpy.ops.call: operator poll() function failed, context is incorrect");
error_val= -1;
}
else {
@@ -153,18 +153,18 @@ static PyObject *pyop_as_string( PyObject * self, PyObject * args)
int all_args = 1;
int error_val= 0;
char *buf;
char *buf = NULL;
PyObject *pybuf;
bContext *C = BPy_GetContext();
if (!PyArg_ParseTuple(args, "s|O!i:bpy.__ops__.as_string", &opname, &PyDict_Type, &kw, &all_args))
if (!PyArg_ParseTuple(args, "s|O!i:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args))
return NULL;
ot= WM_operatortype_find(opname, TRUE);
if (ot == NULL) {
PyErr_Format( PyExc_SystemError, "bpy.__ops__.as_string: operator \"%s\"could not be found", opname);
PyErr_Format( PyExc_SystemError, "_bpy.ops.as_string: operator \"%s\"could not be found", opname);
return NULL;
}
@@ -217,12 +217,12 @@ static PyObject *pyop_getrna(PyObject *self, PyObject *value)
BPy_StructRNA *pyrna= NULL;
if(opname==NULL) {
PyErr_SetString(PyExc_TypeError, "bpy.__ops__.get_rna() expects a string argument");
PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_rna() expects a string argument");
return NULL;
}
ot= WM_operatortype_find(opname, TRUE);
if(ot==NULL) {
PyErr_Format(PyExc_KeyError, "bpy.__ops__.get_rna(\"%s\") not found", opname);
PyErr_Format(PyExc_KeyError, "_bpy.ops.get_rna(\"%s\") not found", opname);
return NULL;
}
@@ -245,8 +245,8 @@ PyObject *BPY_operator_module( void )
static PyMethodDef pyop_add_meth = {"add", (PyCFunction) PYOP_wrap_add, METH_O, NULL};
static PyMethodDef pyop_remove_meth = {"remove", (PyCFunction) PYOP_wrap_remove, METH_O, NULL};
PyObject *submodule = PyModule_New("bpy.__ops__");
PyDict_SetItemString(PySys_GetObject("modules"), "bpy.__ops__", submodule);
PyObject *submodule = PyModule_New("_bpy.ops");
PyDict_SetItemString(PySys_GetObject("modules"), "_bpy.ops", submodule);
PyModule_AddObject( submodule, "call", PyCFunction_New(&pyop_call_meth, NULL) );
PyModule_AddObject( submodule, "as_string",PyCFunction_New(&pyop_as_string_meth,NULL) );

View File

@@ -44,7 +44,7 @@
#define PYOP_ATTR_UINAME "bl_label"
#define PYOP_ATTR_IDNAME "bl_idname" /* the name given by python */
#define PYOP_ATTR_IDNAME_BL "_bl_idname" /* our own name converted into blender syntax, users wont see this */
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
#define PYOP_ATTR_REGISTER "bl_register" /* True/False. if this python operator should be registered */
#define PYOP_ATTR_UNDO "bl_undo" /* True/False. if this python operator should be undone */
@@ -106,30 +106,12 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperat
Py_DECREF(args);
if (py_class_instance) { /* Initializing the class worked, now run its invoke function */
PyObject *class_dict= PyObject_GetAttrString(py_class_instance, "__dict__");
/* Assign instance attributes from operator properties */
if(op) {
const char *arg_name;
RNA_STRUCT_BEGIN(op->ptr, prop) {
arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
item = pyrna_prop_to_py(op->ptr, prop);
PyDict_SetItemString(class_dict, arg_name, item);
Py_DECREF(item);
}
RNA_STRUCT_END;
}
RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
if (mode==PYOP_INVOKE) {
item= PyObject_GetAttrString(py_class, "invoke");
args = PyTuple_New(3);
RNA_pointer_create(NULL, &RNA_Event, event, &ptr_event);
// PyTuple_SET_ITEM "steals" object reference, it is
@@ -149,12 +131,11 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperat
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
}
PyTuple_SET_ITEM(args, 0, py_class_instance);
ret = PyObject_Call(item, args, NULL);
Py_DECREF(args);
Py_DECREF(item);
Py_DECREF(class_dict);
}
else {
PyErr_Print();
@@ -308,11 +289,18 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
*/
item= ((PyTypeObject*)py_class)->tp_dict;
if(item) {
/* only call this so pyrna_deferred_register_props gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
RNA_def_struct_identifier(ot->srna, ot->idname);
if(pyrna_deferred_register_props(ot->srna, item)!=0) {
PyErr_Print();
PyErr_Clear();
}
}
/* failed to register operator props */
PyErr_Print();
PyErr_Clear();
}
}
else {
PyErr_Clear();
}
@@ -341,7 +329,11 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
// in python would be...
//PyObject *optype = PyObject_GetAttrString(PyObject_GetAttrString(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), "types"), "Operator");
base_class = PyObject_GetAttrStringArgs(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), 2, "types", "Operator");
//PyObject bpy_mod= PyDict_GetItemString(PyEval_GetGlobals(), "bpy");
PyObject *bpy_mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
base_class = PyObject_GetAttrStringArgs(bpy_mod, 2, "types", "Operator");
Py_DECREF(bpy_mod);
if(BPY_class_validate("Operator", py_class, base_class, pyop_class_attr_values, NULL) < 0) {
return NULL; /* BPY_class_validate sets the error */

View File

@@ -48,6 +48,7 @@
#ifdef USE_MATHUTILS
#include "../generic/Mathutils.h" /* so we can have mathutils callbacks */
#include "../generic/IDProp.h" /* for IDprop lookups */
/* bpyrna vector/euler/quat callbacks */
static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */
@@ -273,7 +274,7 @@ static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
}
/*----------------------repr--------------------------------------------*/
static PyObject *pyrna_struct_repr( BPy_StructRNA * self )
static PyObject *pyrna_struct_repr( BPy_StructRNA *self )
{
PyObject *pyob;
char *name;
@@ -289,7 +290,7 @@ static PyObject *pyrna_struct_repr( BPy_StructRNA * self )
return PyUnicode_FromFormat( "[BPy_StructRNA \"%.200s\"]", RNA_struct_identifier(self->ptr.type));
}
static PyObject *pyrna_prop_repr( BPy_PropertyRNA * self )
static PyObject *pyrna_prop_repr( BPy_PropertyRNA *self )
{
PyObject *pyob;
PointerRNA ptr;
@@ -310,13 +311,13 @@ static PyObject *pyrna_prop_repr( BPy_PropertyRNA * self )
return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%.200s\" -> \"%.200s\"]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop));
}
static long pyrna_struct_hash( BPy_StructRNA * self )
static long pyrna_struct_hash( BPy_StructRNA *self )
{
return (long)self->ptr.data;
}
/* use our own dealloc so we can free a property if we use one */
static void pyrna_struct_dealloc( BPy_StructRNA * self )
static void pyrna_struct_dealloc( BPy_StructRNA *self )
{
if (self->freeptr && self->ptr.data) {
IDP_FreeProperty(self->ptr.data);
@@ -419,10 +420,19 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
ret = PyUnicode_FromString( item->identifier );
}
else {
char *ptr_name= RNA_struct_name_get_alloc(ptr, NULL, FALSE);
/* prefer not fail silently incase of api errors, maybe disable it later */
char error_str[128];
sprintf(error_str, "RNA Warning: Current value \"%d\" matches no enum", val);
printf("RNA Warning: Current value \"%d\" matches no enum in '%s', '%s', '%s'\n", val, RNA_struct_identifier(ptr->type), ptr_name, RNA_property_identifier(prop));
#if 0 // gives python decoding errors while generating docs :(
char error_str[256];
snprintf(error_str, sizeof(error_str), "RNA Warning: Current value \"%d\" matches no enum in '%s', '%s', '%s'", val, RNA_struct_identifier(ptr->type), ptr_name, RNA_property_identifier(prop));
PyErr_Warn(PyExc_RuntimeWarning, error_str);
#endif
if(ptr_name)
MEM_freeN(ptr_name);
ret = PyUnicode_FromString( "" );
}
@@ -517,9 +527,9 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha
return error_val;
}
static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw);
static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw);
PyObject *pyrna_func_to_py(BPy_StructRNA *pyrna, FunctionRNA *func)
PyObject *pyrna_func_to_py(BPy_DummyPointerRNA *pyrna, FunctionRNA *func)
{
static PyMethodDef func_meth = {"<generic rna function>", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"};
PyObject *self;
@@ -581,9 +591,16 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
switch (type) {
case PROP_BOOLEAN:
{
int param = PyObject_IsTrue( value );
int param;
/* prefer not to have an exception here
* however so many poll functions return None or a valid Object.
* its a hassle to convert these into a bool before returning, */
if(RNA_property_flag(prop) & PROP_RETURN)
param = PyObject_IsTrue( value );
else
param = PyLong_AsSsize_t( value );
if( param < 0 ) {
if( param < 0 || param > 1) {
PyErr_Format(PyExc_TypeError, "%.200s expected True/False or 0/1", error_prefix);
return -1;
} else {
@@ -595,7 +612,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
case PROP_INT:
{
int param = PyLong_AsSsize_t(value);
if (PyErr_Occurred()) {
if (param==-1 && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError, "%.200s expected an int type", error_prefix);
return -1;
} else {
@@ -671,7 +688,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
PyErr_Format(PyExc_TypeError, "%.200s expected a %.200s type", error_prefix, RNA_struct_identifier(ptype));
return -1;
} else if((flag & PROP_NEVER_NULL) && value == Py_None) {
PyErr_Format(PyExc_TypeError, "property can't be assigned a None value");
PyErr_Format(PyExc_TypeError, "%.200s does not suppory a 'None' assignment %.200s type", error_prefix, RNA_struct_identifier(ptype));
return -1;
} else {
BPy_StructRNA *param= (BPy_StructRNA*)value;
@@ -803,9 +820,9 @@ static int pyrna_py_to_prop_index(BPy_PropertyRNA *self, int index, PyObject *va
switch (type) {
case PROP_BOOLEAN:
{
int param = PyObject_IsTrue( value );
int param = PyLong_AsSsize_t( value );
if( param < 0 ) {
if( param < 0 || param > 1) {
PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1");
ret = -1;
} else {
@@ -816,7 +833,7 @@ static int pyrna_py_to_prop_index(BPy_PropertyRNA *self, int index, PyObject *va
case PROP_INT:
{
int param = PyLong_AsSsize_t(value);
if (PyErr_Occurred()) {
if (param==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected an int type");
ret = -1;
} else {
@@ -854,7 +871,7 @@ static int pyrna_prop_array_length(BPy_PropertyRNA *self)
return RNA_property_array_length(&self->ptr, self->prop);
}
static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self )
static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA *self )
{
Py_ssize_t len;
@@ -871,7 +888,7 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self )
}
/* internal use only */
static PyObject *prop_subscript_collection_int(BPy_PropertyRNA * self, int keynum)
static PyObject *prop_subscript_collection_int(BPy_PropertyRNA *self, int keynum)
{
PointerRNA newptr;
@@ -884,7 +901,7 @@ static PyObject *prop_subscript_collection_int(BPy_PropertyRNA * self, int keynu
return NULL;
}
static PyObject *prop_subscript_array_int(BPy_PropertyRNA * self, int keynum)
static PyObject *prop_subscript_array_int(BPy_PropertyRNA *self, int keynum)
{
int len= pyrna_prop_array_length(self);
@@ -897,7 +914,7 @@ static PyObject *prop_subscript_array_int(BPy_PropertyRNA * self, int keynum)
return NULL;
}
static PyObject *prop_subscript_collection_str(BPy_PropertyRNA * self, char *keyname)
static PyObject *prop_subscript_collection_str(BPy_PropertyRNA *self, char *keyname)
{
PointerRNA newptr;
if(RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr))
@@ -906,9 +923,9 @@ static PyObject *prop_subscript_collection_str(BPy_PropertyRNA * self, char *key
PyErr_Format(PyExc_KeyError, "key \"%.200s\" not found", keyname);
return NULL;
}
/* static PyObject *prop_subscript_array_str(BPy_PropertyRNA * self, char *keyname) */
/* static PyObject *prop_subscript_array_str(BPy_PropertyRNA *self, char *keyname) */
static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA * self, int start, int stop)
static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA *self, int start, int stop)
{
PointerRNA newptr;
PyObject *list = PyList_New(stop - start);
@@ -930,7 +947,7 @@ static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA * self, int sta
return list;
}
static PyObject *prop_subscript_array_slice(BPy_PropertyRNA * self, int start, int stop)
static PyObject *prop_subscript_array_slice(BPy_PropertyRNA *self, int start, int stop)
{
PyObject *list = PyList_New(stop - start);
int count;
@@ -943,7 +960,7 @@ static PyObject *prop_subscript_array_slice(BPy_PropertyRNA * self, int start, i
return list;
}
static PyObject *prop_subscript_collection(BPy_PropertyRNA * self, PyObject *key)
static PyObject *prop_subscript_collection(BPy_PropertyRNA *self, PyObject *key)
{
if (PyUnicode_Check(key)) {
return prop_subscript_collection_str(self, _PyUnicode_AsString(key));
@@ -979,7 +996,7 @@ static PyObject *prop_subscript_collection(BPy_PropertyRNA * self, PyObject *key
}
}
static PyObject *prop_subscript_array(BPy_PropertyRNA * self, PyObject *key)
static PyObject *prop_subscript_array(BPy_PropertyRNA *self, PyObject *key)
{
/*if (PyUnicode_Check(key)) {
return prop_subscript_array_str(self, _PyUnicode_AsString(key));
@@ -1014,7 +1031,7 @@ static PyObject *prop_subscript_array(BPy_PropertyRNA * self, PyObject *key)
}
}
static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
static PyObject *pyrna_prop_subscript( BPy_PropertyRNA *self, PyObject *key )
{
if (RNA_property_type(self->prop) == PROP_COLLECTION) {
return prop_subscript_collection(self, key);
@@ -1026,7 +1043,7 @@ static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
return NULL;
}
static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int end, PyObject *value)
static int prop_subscript_ass_array_slice(BPy_PropertyRNA *self, int begin, int end, PyObject *value)
{
int count;
@@ -1043,7 +1060,7 @@ static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int
return 0;
}
static int prop_subscript_ass_array_int(BPy_PropertyRNA * self, int keynum, PyObject *value)
static int prop_subscript_ass_array_int(BPy_PropertyRNA *self, int keynum, PyObject *value)
{
int len= pyrna_prop_array_length(self);
@@ -1056,7 +1073,7 @@ static int prop_subscript_ass_array_int(BPy_PropertyRNA * self, int keynum, PyOb
return -1;
}
static int pyrna_prop_ass_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value )
static int pyrna_prop_ass_subscript( BPy_PropertyRNA *self, PyObject *key, PyObject *value )
{
/* char *keyname = NULL; */ /* not supported yet */
@@ -1109,29 +1126,52 @@ static PyMappingMethods pyrna_prop_as_mapping = {
( objobjargproc ) pyrna_prop_ass_subscript, /* mp_ass_subscript */
};
static int pyrna_prop_contains(BPy_PropertyRNA * self, PyObject *value)
static int pyrna_prop_contains(BPy_PropertyRNA *self, PyObject *value)
{
PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */
char *keyname = _PyUnicode_AsString(value);
if(keyname==NULL) {
PyErr_SetString(PyExc_TypeError, "PropertyRNA - key in prop, key must be a string type");
return -1;
}
if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString(PyExc_TypeError, "PropertyRNA - key in prop, is only valid for collection types");
return -1;
}
if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr))
return 1;
return 0;
}
static PyObject *pyrna_prop_item(BPy_PropertyRNA * self, Py_ssize_t index)
static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value)
{
IDProperty *group;
char *name = _PyUnicode_AsString(value);
if (!name) {
PyErr_SetString( PyExc_TypeError, "expected a string");
return -1;
}
if(RNA_struct_idproperties_check(&self->ptr)==0) {
PyErr_SetString( PyExc_TypeError, "this type doesnt support IDProperties");
return -1;
}
group= RNA_struct_idproperties(&self->ptr, 0);
if(!group)
return 0;
return IDP_GetPropertyFromGroup(group, name) ? 1:0;
}
static PyObject *pyrna_prop_item(BPy_PropertyRNA *self, Py_ssize_t index)
{
/* reuse subscript functions */
if (RNA_property_type(self->prop) == PROP_COLLECTION) {
@@ -1155,8 +1195,121 @@ static PySequenceMethods pyrna_prop_as_sequence = {
(objobjproc)pyrna_prop_contains, /* sq_contains */
};
static PySequenceMethods pyrna_struct_as_sequence = {
NULL, /* Cant set the len otherwise it can evaluate as false */
NULL, /* sq_concat */
NULL, /* sq_repeat */
NULL, /* sq_item */ /* Only set this so PySequence_Check() returns True */
NULL, /* sq_slice */
NULL, /* sq_ass_item */
NULL, /* sq_ass_slice */
(objobjproc)pyrna_struct_contains, /* sq_contains */
};
static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA * self, PyObject *args)
static PyObject *pyrna_struct_subscript( BPy_StructRNA *self, PyObject *key )
{
/* mostly copied from BPy_IDGroup_Map_GetItem */
IDProperty *group, *idprop;
char *name= _PyUnicode_AsString(key);
if(RNA_struct_idproperties_check(&self->ptr)==0) {
PyErr_SetString( PyExc_TypeError, "this type doesn't support IDProperties");
return NULL;
}
if(name==NULL) {
PyErr_SetString( PyExc_TypeError, "only strings are allowed as keys of ID properties");
return NULL;
}
group= RNA_struct_idproperties(&self->ptr, 0);
if(group==NULL) {
PyErr_Format( PyExc_KeyError, "key \"%s\" not found", name);
return NULL;
}
idprop= IDP_GetPropertyFromGroup(group, name);
if(idprop==NULL) {
PyErr_Format( PyExc_KeyError, "key \"%s\" not found", name);
return NULL;
}
return BPy_IDGroup_WrapData(self->ptr.id.data, idprop);
}
static int pyrna_struct_ass_subscript( BPy_StructRNA *self, PyObject *key, PyObject *value )
{
IDProperty *group= RNA_struct_idproperties(&self->ptr, 1);
if(group==NULL) {
PyErr_SetString(PyExc_TypeError, "id properties not supported for this type");
return -1;
}
return BPy_Wrap_SetMapItem(group, key, value);
}
static PyMappingMethods pyrna_struct_as_mapping = {
( lenfunc ) NULL, /* mp_length */
( binaryfunc ) pyrna_struct_subscript, /* mp_subscript */
( objobjargproc ) pyrna_struct_ass_subscript, /* mp_ass_subscript */
};
static PyObject *pyrna_struct_keys(BPy_PropertyRNA *self)
{
IDProperty *group;
if(RNA_struct_idproperties_check(&self->ptr)==0) {
PyErr_SetString( PyExc_TypeError, "this type doesnt support IDProperties");
return NULL;
}
group= RNA_struct_idproperties(&self->ptr, 0);
if(group==NULL)
return PyList_New(0);
return BPy_Wrap_GetKeys(group);
}
static PyObject *pyrna_struct_items(BPy_PropertyRNA *self)
{
IDProperty *group;
if(RNA_struct_idproperties_check(&self->ptr)==0) {
PyErr_SetString( PyExc_TypeError, "this type doesnt support IDProperties");
return NULL;
}
group= RNA_struct_idproperties(&self->ptr, 0);
if(group==NULL)
return PyList_New(0);
return BPy_Wrap_GetItems(self->ptr.id.data, group);
}
static PyObject *pyrna_struct_values(BPy_PropertyRNA *self)
{
IDProperty *group;
if(RNA_struct_idproperties_check(&self->ptr)==0) {
PyErr_SetString( PyExc_TypeError, "this type doesnt support IDProperties");
return NULL;
}
group= RNA_struct_idproperties(&self->ptr, 0);
if(group==NULL)
return PyList_New(0);
return BPy_Wrap_GetValues(self->ptr.id.data, group);
}
static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args)
{
char *path, *path_full;
int index= -1; /* default to all */
@@ -1198,7 +1351,7 @@ static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA * self, PyObject *ar
}
static PyObject *pyrna_struct_driver_add(BPy_StructRNA * self, PyObject *args)
static PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
{
char *path, *path_full;
int index= -1; /* default to all */
@@ -1239,7 +1392,7 @@ static PyObject *pyrna_struct_driver_add(BPy_StructRNA * self, PyObject *args)
}
static PyObject *pyrna_struct_is_property_set(BPy_StructRNA * self, PyObject *args)
static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args)
{
char *name;
@@ -1249,7 +1402,7 @@ static PyObject *pyrna_struct_is_property_set(BPy_StructRNA * self, PyObject *ar
return PyBool_FromLong(RNA_property_is_set(&self->ptr, name));
}
static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA * self, PyObject *args)
static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject *args)
{
PropertyRNA *prop;
char *name;
@@ -1264,76 +1417,108 @@ static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA * self, PyObject
return PyBool_FromLong(hidden);
}
static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
static PyObject *pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *value)
{
PyObject *ret, *dict;
PyObject *pystring;
/* for looping over attrs and funcs */
PropertyRNA *iterprop;
/* Include this incase this instance is a subtype of a python class
* In these instances we may want to return a function or variable provided by the subtype
* */
char *path= _PyUnicode_AsString(value);
PointerRNA r_ptr;
PropertyRNA *r_prop;
if (BPy_StructRNA_CheckExact(self)) {
ret = PyList_New(0);
} else {
pystring = PyUnicode_FromString("__dict__");
dict = PyObject_GenericGetAttr((PyObject *)self, pystring);
Py_DECREF(pystring);
if (dict==NULL) {
PyErr_Clear();
ret = PyList_New(0);
}
else {
ret = PyDict_Keys(dict);
Py_DECREF(dict);
}
if(path==NULL) {
PyErr_SetString( PyExc_TypeError, "items() is only valid for collection types" );
return NULL;
}
/* Collect RNA items*/
if (RNA_path_resolve(&self->ptr, path, &r_ptr, &r_prop))
return pyrna_prop_CreatePyObject(&r_ptr, r_prop);
Py_RETURN_NONE;
}
static void pyrna_dir_members_py(PyObject *list, PyObject *self)
{
PyObject *dict;
PyObject **dict_ptr;
PyObject *list_tmp;
dict_ptr= _PyObject_GetDictPtr((PyObject *)self);
if(dict_ptr && (dict=*dict_ptr)) {
list_tmp = PyDict_Keys(dict);
PyList_SetSlice(list, INT_MAX, INT_MAX, list_tmp);
Py_DECREF(list_tmp);
}
dict= ((PyTypeObject *)Py_TYPE(self))->tp_dict;
if(dict) {
list_tmp = PyDict_Keys(dict);
PyList_SetSlice(list, INT_MAX, INT_MAX, list_tmp);
Py_DECREF(list_tmp);
}
}
static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
{
PyObject *pystring;
const char *idname;
/* for looping over attrs and funcs */
PointerRNA tptr;
PropertyRNA *iterprop;
{
RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr);
iterprop= RNA_struct_find_property(&tptr, "functions");
RNA_PROP_BEGIN(&tptr, itemptr, iterprop) {
idname= RNA_function_identifier(itemptr.data);
pystring = PyUnicode_FromString(idname);
PyList_Append(list, pystring);
Py_DECREF(pystring);
}
RNA_PROP_END;
}
{
/*
* Collect RNA attributes
*/
char name[256], *nameptr;
iterprop= RNA_struct_iterator_property(self->ptr.type);
iterprop= RNA_struct_iterator_property(ptr->type);
RNA_PROP_BEGIN(&self->ptr, itemptr, iterprop) {
RNA_PROP_BEGIN(ptr, itemptr, iterprop) {
nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name));
if(nameptr) {
pystring = PyUnicode_FromString(nameptr);
PyList_Append(ret, pystring);
PyList_Append(list, pystring);
Py_DECREF(pystring);
if(name != nameptr)
MEM_freeN(nameptr);
}
}
RNA_PROP_END;
}
{
/*
* Collect RNA function items
*/
PointerRNA tptr;
}
RNA_pointer_create(NULL, &RNA_Struct, self->ptr.type, &tptr);
iterprop= RNA_struct_find_property(&tptr, "functions");
RNA_PROP_BEGIN(&tptr, itemptr, iterprop) {
pystring = PyUnicode_FromString(RNA_function_identifier(itemptr.data));
PyList_Append(ret, pystring);
Py_DECREF(pystring);
}
RNA_PROP_END;
}
static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
{
PyObject *ret;
PyObject *pystring;
/* Include this incase this instance is a subtype of a python class
* In these instances we may want to return a function or variable provided by the subtype
* */
ret = PyList_New(0);
if (!BPy_StructRNA_CheckExact(self))
pyrna_dir_members_py(ret, (PyObject *)self);
pyrna_dir_members_rna(ret, &self->ptr);
if(self->ptr.type == &RNA_Context) {
ListBase lb = CTX_data_dir_get(self->ptr.data);
@@ -1349,7 +1534,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
}
/* Hard coded names */
{
if(self->ptr.id.data) {
pystring = PyUnicode_FromString("id_data");
PyList_Append(ret, pystring);
Py_DECREF(pystring);
@@ -1358,20 +1543,29 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
return ret;
}
//---------------getattr--------------------------------------------
static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname )
{
char *name = _PyUnicode_AsString(pyname);
PyObject *ret;
PropertyRNA *prop;
FunctionRNA *func;
if ((prop = RNA_struct_find_property(&self->ptr, name))) {
if(name[0]=='_') { // rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups
/* annoying exception, maybe we need to have different types for this... */
if((strcmp(name, "__getitem__")==0 || strcmp(name, "__setitem__")==0) && !RNA_struct_idproperties_check(&self->ptr)) {
PyErr_SetString(PyExc_AttributeError, "StructRNA - no __getitem__ support for this type");
ret = NULL;
}
else {
ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
}
}
else if ((prop = RNA_struct_find_property(&self->ptr, name))) {
ret = pyrna_prop_to_py(&self->ptr, prop);
}
else if ((func = RNA_struct_find_function(&self->ptr, name))) {
ret = pyrna_func_to_py(self, func);
ret = pyrna_func_to_py((BPy_DummyPointerRNA *)self, func);
}
else if (self->ptr.type == &RNA_Context) {
PointerRNA newptr;
@@ -1418,7 +1612,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr);
ret = pyrna_struct_CreatePyObject(&id_ptr);
}
else {
else {
ret = Py_None;
Py_INCREF(ret);
}
@@ -1441,8 +1635,19 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
return ret;
}
#if 0
static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname)
{
PyObject *dict= *(_PyObject_GetDictPtr((PyObject *)self));
if (dict==NULL) /* unlikely */
return 0;
return PyDict_Contains(dict, pyname);
}
#endif
//--------------- setattr-------------------------------------------
static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObject * value )
static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObject *value )
{
char *name = _PyUnicode_AsString(pyname);
PropertyRNA *prop = RNA_struct_find_property(&self->ptr, name);
@@ -1450,11 +1655,13 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje
if (prop==NULL) {
// XXX - This currently allows anything to be assigned to an rna prop, need to see how this should be used
// but for now it makes porting scripts confusing since it fails silently.
#if 0
if (!BPy_StructRNA_CheckExact(self) && PyObject_GenericSetAttr((PyObject *)self, pyname, value) >= 0) {
// edit: allowing this for setting classes internal attributes.
// edit: allow this for any attribute that alredy exists as a python attr
if ( (name[0]=='_' /* || pyrna_struct_pydict_contains(self, pyname) */ ) &&
!BPy_StructRNA_CheckExact(self) &&
PyObject_GenericSetAttr((PyObject *)self, pyname, value) >= 0) {
return 0;
} else
#endif
{
PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" not found", name);
return -1;
@@ -1467,57 +1674,127 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje
}
/* pyrna_py_to_prop sets its own exceptions */
return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "StructRNA - Attribute (setattr):");
return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "StructRNA - item.attr = val:");
}
static PyObject *pyrna_prop_getattro( BPy_PropertyRNA * self, PyObject *pyname )
static PyObject *pyrna_prop_dir(BPy_PropertyRNA *self)
{
PyObject *ret;
PointerRNA r_ptr;
/* Include this incase this instance is a subtype of a python class
* In these instances we may want to return a function or variable provided by the subtype
* */
ret = PyList_New(0);
if (!BPy_PropertyRNA_CheckExact(self))
pyrna_dir_members_py(ret, (PyObject *)self);
if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr))
pyrna_dir_members_rna(ret, &r_ptr);
return ret;
}
static PyObject *pyrna_prop_getattro( BPy_PropertyRNA *self, PyObject *pyname )
{
char *name = _PyUnicode_AsString(pyname);
if(strcmp(name, "active")==0) {
PropertyRNA *prop_act;
if(name[0] != '_') {
if (RNA_property_type(self->prop) == PROP_COLLECTION) {
PyObject *ret;
PropertyRNA *prop;
FunctionRNA *func;
if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA object is not a collection");
return NULL;
PointerRNA r_ptr;
if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) {
if ((prop = RNA_struct_find_property(&r_ptr, name))) {
ret = pyrna_prop_to_py(&r_ptr, prop);
return ret;
}
else if ((func = RNA_struct_find_function(&r_ptr, name))) {
PyObject *self_collection= pyrna_struct_CreatePyObject(&r_ptr);
ret = pyrna_func_to_py((BPy_DummyPointerRNA *)self_collection, func);
Py_DECREF(self_collection);
return ret;
}
}
}
prop_act= RNA_property_collection_active(self->prop);
if (prop_act==NULL) {
PyErr_SetString( PyExc_TypeError, "collection has no active");
return NULL;
}
return pyrna_prop_to_py(&self->ptr, prop_act);
}
/* The error raised here will be displayed */
return PyObject_GenericGetAttr((PyObject *)self, pyname);
}
//--------------- setattr-------------------------------------------
static int pyrna_prop_setattro( BPy_PropertyRNA * self, PyObject *pyname, PyObject * value )
static int pyrna_prop_setattro( BPy_PropertyRNA *self, PyObject *pyname, PyObject *value )
{
char *name = _PyUnicode_AsString(pyname);
if(strcmp(name, "active")==0) {
PropertyRNA *prop_act;
PropertyRNA *prop;
if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA object is not a collection");
return -1;
if (RNA_property_type(self->prop) == PROP_COLLECTION) {
PointerRNA r_ptr;
if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) {
if ((prop = RNA_struct_find_property(&r_ptr, name))) {
/* pyrna_py_to_prop sets its own exceptions */
return pyrna_py_to_prop(&r_ptr, prop, NULL, value, "BPy_PropertyRNA - Attribute (setattr):");
}
}
prop_act= RNA_property_collection_active(self->prop);
if (prop_act==NULL) {
PyErr_SetString( PyExc_TypeError, "collection has no active");
return -1;
}
return pyrna_py_to_prop(&self->ptr, prop_act, NULL, value, "StructRNA - Attribute (setattr):");
}
return PyObject_GenericSetAttr((PyObject *)self, pyname, value);
PyErr_Format( PyExc_AttributeError, "BPy_PropertyRNA - Attribute \"%.200s\" not found", name);
return -1;
}
/* odd case, we need to be able return a python method from a tp_getset */
static PyObject *pyrna_prop_add(BPy_PropertyRNA *self)
{
PointerRNA r_ptr;
RNA_property_collection_add(&self->ptr, self->prop, &r_ptr);
if(!r_ptr.data) {
PyErr_SetString( PyExc_TypeError, "add() not supported for this collection");
return NULL;
}
else {
return pyrna_struct_CreatePyObject(&r_ptr);
}
}
static PyObject *pyrna_prop_remove(BPy_PropertyRNA *self, PyObject *value)
{
PyObject *ret;
int key= PyLong_AsSsize_t(value);
if (key==-1 && PyErr_Occurred()) {
PyErr_SetString( PyExc_TypeError, "remove() expected one int argument");
return NULL;
}
if(!RNA_property_collection_remove(&self->ptr, self->prop, key)) {
PyErr_SetString( PyExc_TypeError, "remove() not supported for this collection");
return NULL;
}
ret = Py_None;
Py_INCREF(ret);
return ret;
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
#if 0
static PyGetSetDef pyrna_prop_getseters[] = {
{"active", (getter)pyrna_prop_get_active, (setter)pyrna_prop_set_active, "", NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
#endif
static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self)
{
PyObject *ret;
@@ -1630,40 +1907,6 @@ static PyObject *pyrna_prop_get(BPy_PropertyRNA *self, PyObject *args)
return def;
}
static PyObject *pyrna_prop_add(BPy_PropertyRNA *self, PyObject *args)
{
PointerRNA newptr;
RNA_property_collection_add(&self->ptr, self->prop, &newptr);
if(!newptr.data) {
PyErr_SetString( PyExc_TypeError, "add() not supported for this collection");
return NULL;
}
else {
return pyrna_struct_CreatePyObject(&newptr);
}
}
static PyObject *pyrna_prop_remove(BPy_PropertyRNA *self, PyObject *args)
{
PyObject *ret;
int key= 0;
if (!PyArg_ParseTuple(args, "i:remove", &key))
return NULL;
if(!RNA_property_collection_remove(&self->ptr, self->prop, key)) {
PyErr_SetString( PyExc_TypeError, "remove() not supported for this collection");
return NULL;
}
ret = Py_None;
Py_INCREF(ret);
return ret;
}
static void foreach_attr_type( BPy_PropertyRNA *self, char *attr,
/* values to assign */
RawPropertyType *raw_type, int *attr_tot, int *attr_signed )
@@ -1757,7 +2000,7 @@ static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, cons
static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
{
PyObject *item = NULL;
int i=0, ok, buffer_is_compat;
int i=0, ok=0, buffer_is_compat;
void *array= NULL;
/* get/set both take the same args currently */
@@ -1934,12 +2177,17 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self)
static struct PyMethodDef pyrna_struct_methods[] = {
/* only for PointerRNA's with ID'props */
{"keys", (PyCFunction)pyrna_struct_keys, METH_NOARGS, NULL},
{"values", (PyCFunction)pyrna_struct_values, METH_NOARGS, NULL},
{"items", (PyCFunction)pyrna_struct_items, METH_NOARGS, NULL},
/* maybe this become and ID function */
{"keyframe_insert", (PyCFunction)pyrna_struct_keyframe_insert, METH_VARARGS, NULL},
{"driver_add", (PyCFunction)pyrna_struct_driver_add, METH_VARARGS, NULL},
{"is_property_set", (PyCFunction)pyrna_struct_is_property_set, METH_VARARGS, NULL},
{"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, NULL},
{"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_O, NULL},
{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL}
};
@@ -1951,12 +2199,14 @@ static struct PyMethodDef pyrna_prop_methods[] = {
{"get", (PyCFunction)pyrna_prop_get, METH_VARARGS, NULL},
{"add", (PyCFunction)pyrna_prop_add, METH_VARARGS, NULL},
{"remove", (PyCFunction)pyrna_prop_remove, METH_VARARGS, NULL},
/* moved into a getset */
{"add", (PyCFunction)pyrna_prop_add, METH_NOARGS, NULL},
{"remove", (PyCFunction)pyrna_prop_remove, METH_O, NULL},
/* array accessor function */
{"foreach_get", (PyCFunction)pyrna_prop_foreach_get, METH_VARARGS, NULL},
{"foreach_set", (PyCFunction)pyrna_prop_foreach_set, METH_VARARGS, NULL},
{"__dir__", (PyCFunction)pyrna_prop_dir, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL}
};
@@ -2082,8 +2332,11 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
if(RNA_struct_is_ID(type)) {
RNA_id_pointer_create(*(void**)data, &newptr);
} else {
/* XXX this is missing the ID part! */
RNA_pointer_create(NULL, type, *(void**)data, &newptr);
/* note: this is taken from the function's ID pointer
* and will break if a function returns a pointer from
* another ID block, watch this! - it should at least be
* easy to debug since they are all ID's */
RNA_pointer_create(ptr->id.data, type, *(void**)data, &newptr);
}
}
@@ -2121,9 +2374,10 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
return ret;
}
static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw)
static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
{
PointerRNA *self_ptr= &(((BPy_StructRNA *)PyTuple_GET_ITEM(self, 0))->ptr);
/* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */
PointerRNA *self_ptr= &(((BPy_DummyPointerRNA *)PyTuple_GET_ITEM(self, 0))->ptr);
FunctionRNA *self_func= PyCObject_AsVoidPtr(PyTuple_GET_ITEM(self, 1));
PointerRNA funcptr;
@@ -2146,8 +2400,10 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw)
return NULL;
}
/* setup */
RNA_pointer_create(NULL, &RNA_Function, self_func, &funcptr);
/* include the ID pointer for pyrna_param_to_py() so we can include the
* ID pointer on return values, this only works when returned values have
* the same ID as the functions. */
RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr);
pret= RNA_function_return(self_func);
args_len= PyTuple_GET_SIZE(args);
@@ -2340,8 +2596,8 @@ PyTypeObject pyrna_struct_Type = {
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
&pyrna_struct_as_sequence, /* PySequenceMethods *tp_as_sequence; */
&pyrna_struct_as_mapping, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
@@ -2461,7 +2717,7 @@ PyTypeObject pyrna_prop_Type = {
/*** Attribute descriptor and subclassing stuff ***/
pyrna_prop_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
NULL, /* struct PyGetSetDef *tp_getset; */
NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
@@ -2802,7 +3058,7 @@ PyObject *BPY_rna_doc( void )
/* pyrna_basetype_* - BPy_BaseTypeRNA is just a BPy_PropertyRNA struct with a differnt type
* the self->ptr and self->prop are always set to the "structs" collection */
//---------------getattr--------------------------------------------
static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA * self, PyObject *pyname )
static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA *self, PyObject *pyname )
{
PointerRNA newptr;
PyObject *ret;
@@ -2988,12 +3244,8 @@ static PyObject *bpy_prop_deferred_return(void *func, PyObject *kw)
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
{
static char *kwlist[] = {"attr", "name", "description", "default", NULL};
char *id=NULL, *name="", *description="";
int def=0;
PropertyRNA *prop;
StructRNA *srna;
if (PyTuple_Size(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
return NULL;
@@ -3004,11 +3256,16 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static char *kwlist[] = {"attr", "name", "description", "default", "hidden", NULL};
char *id=NULL, *name="", *description="";
int def=0, hidden=0;
PropertyRNA *prop;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:BoolProperty", kwlist, &id, &name, &description, &def))
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssii:BoolProperty", kwlist, &id, &name, &description, &def, &hidden))
return NULL;
prop= RNA_def_boolean(srna, id, def, name, description);
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
@@ -3019,12 +3276,8 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
{
static char *kwlist[] = {"attr", "name", "description", "min", "max", "soft_min", "soft_max", "default", NULL};
char *id=NULL, *name="", *description="";
int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, def=0;
PropertyRNA *prop;
StructRNA *srna;
if (PyTuple_Size(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
return NULL;
@@ -3035,11 +3288,18 @@ PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "hidden", NULL};
char *id=NULL, *name="", *description="";
int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def=0;
int hidden=0;
PropertyRNA *prop;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiii:IntProperty", kwlist, &id, &name, &description, &min, &max, &soft_min, &soft_max, &def))
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiiiii:IntProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &hidden))
return NULL;
prop= RNA_def_int(srna, id, def, min, max, name, description, soft_min, soft_max);
RNA_def_property_ui_range(prop, min, max, step, 0);
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
@@ -3050,12 +3310,8 @@ PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
{
static char *kwlist[] = {"attr", "name", "description", "min", "max", "soft_min", "soft_max", "default", NULL};
char *id=NULL, *name="", *description="";
float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, def=0.0f;
PropertyRNA *prop;
StructRNA *srna;
if (PyTuple_Size(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
return NULL;
@@ -3066,11 +3322,18 @@ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "hidden", NULL};
char *id=NULL, *name="", *description="";
float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def=0.0f;
int precision= 1, hidden=0;
PropertyRNA *prop;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssfffff:FloatProperty", kwlist, &id, &name, &description, &min, &max, &soft_min, &soft_max, &def))
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssffffffii:FloatProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &hidden))
return NULL;
prop= RNA_def_float(srna, id, def, min, max, name, description, soft_min, soft_max);
RNA_def_property_ui_range(prop, min, max, step, precision);
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
@@ -3081,12 +3344,8 @@ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
{
static char *kwlist[] = {"attr", "name", "description", "maxlen", "default", NULL};
char *id=NULL, *name="", *description="", *def="";
int maxlen=0;
PropertyRNA *prop;
StructRNA *srna;
if (PyTuple_Size(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
return NULL;
@@ -3097,11 +3356,16 @@ PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static char *kwlist[] = {"attr", "name", "description", "default", "maxlen", "hidden", NULL};
char *id=NULL, *name="", *description="", *def="";
int maxlen=0, hidden=0;
PropertyRNA *prop;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssis:StringProperty", kwlist, &id, &name, &description, &maxlen, &def))
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|sssii:StringProperty", kwlist, &id, &name, &description, &def, &maxlen, &hidden))
return NULL;
prop= RNA_def_string(srna, id, def, maxlen, name, description);
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
@@ -3158,14 +3422,8 @@ static EnumPropertyItem *enum_items_from_py(PyObject *value, const char *def, in
PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
{
static char *kwlist[] = {"attr", "items", "name", "description", "default", NULL};
char *id=NULL, *name="", *description="", *def="";
int defvalue=0;
PyObject *items= Py_None;
EnumPropertyItem *eitems;
PropertyRNA *prop;
StructRNA *srna;
if (PyTuple_Size(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
return NULL;
@@ -3176,8 +3434,14 @@ PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static char *kwlist[] = {"attr", "items", "name", "description", "default", "hidden", NULL};
char *id=NULL, *name="", *description="", *def="";
int defvalue=0, hidden=0;
PyObject *items= Py_None;
EnumPropertyItem *eitems;
PropertyRNA *prop;
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sss:EnumProperty", kwlist, &id, &items, &name, &description, &def))
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sssi:EnumProperty", kwlist, &id, &items, &name, &description, &def, &hidden))
return NULL;
eitems= enum_items_from_py(items, def, &defvalue);
@@ -3185,6 +3449,7 @@ PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
prop= RNA_def_enum(srna, id, eitems, defvalue, name, description);
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_duplicate_pointers(prop);
MEM_freeN(eitems);
@@ -3215,12 +3480,8 @@ static StructRNA *pointer_type_from_py(PyObject *value)
PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
{
static char *kwlist[] = {"attr", "type", "name", "description", NULL};
char *id=NULL, *name="", *description="";
PropertyRNA *prop;
StructRNA *srna, *ptype;
PyObject *type= Py_None;
StructRNA *srna;
if (PyTuple_Size(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
return NULL;
@@ -3231,8 +3492,14 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static char *kwlist[] = {"attr", "type", "name", "description", "hidden", NULL};
char *id=NULL, *name="", *description="";
int hidden;
PropertyRNA *prop;
StructRNA *ptype;
PyObject *type= Py_None;
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ss:PointerProperty", kwlist, &id, &type, &name, &description))
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:PointerProperty", kwlist, &id, &type, &name, &description, &hidden))
return NULL;
ptype= pointer_type_from_py(type);
@@ -3240,6 +3507,7 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
prop= RNA_def_pointer_runtime(srna, id, ptype, name, description);
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
@@ -3251,12 +3519,8 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
{
static char *kwlist[] = {"attr", "type", "name", "description", NULL};
char *id=NULL, *name="", *description="";
PropertyRNA *prop;
StructRNA *srna, *ptype;
PyObject *type= Py_None;
StructRNA *srna;
if (PyTuple_Size(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
return NULL;
@@ -3267,8 +3531,14 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static char *kwlist[] = {"attr", "type", "name", "description", "hidden", NULL};
char *id=NULL, *name="", *description="";
int hidden;
PropertyRNA *prop;
StructRNA *ptype;
PyObject *type= Py_None;
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ss:CollectionProperty", kwlist, &id, &type, &name, &description))
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:CollectionProperty", kwlist, &id, &type, &name, &description, &hidden))
return NULL;
ptype= pointer_type_from_py(type);
@@ -3276,6 +3546,7 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
prop= RNA_def_collection_runtime(srna, id, ptype, name, description);
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
@@ -3285,26 +3556,24 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
}
int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
{
PyObject *dummy_args, *item, *key;
Py_ssize_t pos = 0;
dummy_args = PyTuple_New(0);
while (PyDict_Next(class_dict, &pos, &key, &item)) {
static int deferred_register_prop(StructRNA *srna, PyObject *item, PyObject *key, PyObject *dummy_args)
{
/* We only care about results from C which
* are for sure types, save some time with error */
if(PyTuple_CheckExact(item) && PyTuple_GET_SIZE(item)==2) {
PyObject *py_func_ptr, *py_kw, *py_srna_cobject, *py_ret;
/* We only care about results from C which
* are for sure types, save some time with error */
if(PyTuple_CheckExact(item)) {
if(PyArg_ParseTuple(item, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) {
PyObject *(*pyfunc)(PyObject *, PyObject *, PyObject *);
pyfunc = PyCObject_AsVoidPtr(py_func_ptr);
py_srna_cobject = PyCObject_FromVoidPtr(srna, NULL);
/* not 100% nice :/, modifies the dict passed, should be ok */
PyDict_SetItemString(py_kw, "attr", key);
/* not 100% nice :/, modifies the dict passed, should be ok */
PyDict_SetItemString(py_kw, "attr", key);
py_ret = pyfunc(py_srna_cobject, dummy_args, py_kw);
Py_DECREF(py_srna_cobject);
@@ -3313,29 +3582,59 @@ int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
Py_DECREF(py_ret);
}
else {
PyErr_Print();
PyErr_Clear();
PyErr_Print();
PyErr_Clear();
PyLineSpit();
PyErr_Format(PyExc_ValueError, "StructRNA \"%.200s\" registration error: %.200s could not run\n", RNA_struct_identifier(srna), _PyUnicode_AsString(key));
PyErr_Format(PyExc_ValueError, "StructRNA \"%.200s\" registration error: %.200s could not register\n", RNA_struct_identifier(srna), _PyUnicode_AsString(key));
Py_DECREF(dummy_args);
return -1;
return -1;
}
}
else {
/* Since this is a class dict, ignore args that can't be passed */
/* Since this is a class dict, ignore args that can't be passed */
/* for testing only */
/* PyObSpit("Why doesn't this work??", item);
PyErr_Print(); */
/* for testing only */
/* PyObSpit("Why doesn't this work??", item);
PyErr_Print(); */
PyErr_Clear();
}
}
return 0;
}
int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
{
PyObject *item, *key;
PyObject *order;
PyObject *dummy_args;
Py_ssize_t pos = 0;
int ret;
dummy_args = PyTuple_New(0);
order= PyDict_GetItemString(class_dict, "order");
if(order && PyList_Check(order)) {
for(pos= 0; pos<PyList_GET_SIZE(order); pos++) {
key= PyList_GET_ITEM(order, pos);
item= PyDict_GetItem(class_dict, key);
ret= deferred_register_prop(srna, item, key, dummy_args);
if(ret==-1)
break;
}
}
else {
while (PyDict_Next(class_dict, &pos, &key, &item)) {
ret= deferred_register_prop(srna, item, key, dummy_args);
if(ret==-1)
break;
}
}
Py_DECREF(dummy_args);
return 0;
}
@@ -3519,7 +3818,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
pret= RNA_function_return(func);
RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
args = PyTuple_New(rna_function_arg_count(func));
args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */
PyTuple_SET_ITEM(args, 0, py_class_instance);
RNA_parameter_list_begin(parms, &iter);
@@ -3544,7 +3843,8 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
Py_DECREF(args);
}
else {
Py_DECREF(py_class_instance);
PyErr_Print();
PyErr_Clear();
PyErr_Format(PyExc_TypeError, "could not find function %.200s in %.200s to execute callback.", RNA_function_identifier(func), RNA_struct_identifier(ptr->type));
err= -1;
}
@@ -3709,7 +4009,7 @@ PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class)
item= ((PyTypeObject*)py_class)->tp_dict;
if(item) {
if(pyrna_deferred_register_props(srna_new, item)!=0) {
return NULL;
return NULL;
}
}
else {

View File

@@ -39,11 +39,9 @@ extern PyTypeObject pyrna_prop_Type;
#define BPy_PropertyRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_prop_Type)
typedef struct {
void * _a;
void * _b;
PyTypeObject *py_type;
} BPy_StructFakeType;
PyObject_HEAD /* required python macro */
PointerRNA ptr;
} BPy_DummyPointerRNA;
typedef struct {
PyObject_HEAD /* required python macro */

View File

@@ -48,7 +48,7 @@ static struct PyMethodDef ui_methods[] = {
static struct PyModuleDef ui_module = {
PyModuleDef_HEAD_INIT,
"bpy.ui",
"_bpy.ui",
"",
-1,/* multiple "initialization" just copies the module dict. */
ui_methods,

View File

@@ -27,7 +27,6 @@
*/
/* python, will come back */
void BPY_post_start_python() {}
//void BPY_run_python_script() {}
//void BPY_start_python() {}
void BPY_call_importloader() {}