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:
@@ -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" */
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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*/
|
||||
}
|
||||
|
||||
|
||||
1026
source/blender/python/generic/IDProp.c
Normal file
1026
source/blender/python/generic/IDProp.c
Normal 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 );
|
||||
}
|
||||
64
source/blender/python/generic/IDProp.h
Normal file
64
source/blender/python/generic/IDProp.h
Normal 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
|
||||
@@ -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( );
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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) );
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
Reference in New Issue
Block a user