diff --git a/doc/python_api/examples/bpy.app.handlers.1.py b/doc/python_api/examples/bpy.app.handlers.1.py new file mode 100644 index 00000000000..a6591f6b83f --- /dev/null +++ b/doc/python_api/examples/bpy.app.handlers.1.py @@ -0,0 +1,20 @@ +""" +Persistent Handler Example +++++++++++++++++++++++++++ + +By default handlers are freed when loading new files, in some cases you may +wan't the handler stay running across multiple files (when the handler is +part of an addon for example). + +For this the :data:`bpy.app.handlers.persistent` decorator needs to be used. +""" + +import bpy +from bpy.app.handlers import persistent + + +@persistent +def load_handler(dummy): + print("Load Handler:", bpy.data.filepath) + +bpy.app.handlers.load_post.append(load_handler) diff --git a/doc/python_api/examples/bpy.app.handlers.py b/doc/python_api/examples/bpy.app.handlers.py new file mode 100644 index 00000000000..7c176063b7c --- /dev/null +++ b/doc/python_api/examples/bpy.app.handlers.py @@ -0,0 +1,12 @@ +""" +Basic Handler Example ++++++++++++++++++++++ +This script shows the most simple example of adding a handler. +""" + +import bpy + +def my_handler(scene): + print("Frame Change", scene.frame_current) + +bpy.app.handlers.frame_change_pre.append(my_handler) \ No newline at end of file diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 5843e5ddb6c..b0127c50b29 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -50,7 +50,7 @@ For PDF generation # Check we're running in blender if __import__("sys").modules.get("bpy") is None: - print("\nError, this script must run from inside blender2.5") + print("\nError, this script must run from inside blender") print(script_help_msg) import sys @@ -70,13 +70,14 @@ else: # for testing so doc-builds dont take so long. EXCLUDE_MODULES = ( "bpy.context", - "bpy.app", + #"bpy.app", + #"bpy.app.handlers", "bpy.path", "bpy.data", "bpy.props", "bpy.utils", "bpy.context", - # "bpy.types", # supports filtering + "bpy.types", # supports filtering "bpy.ops", # supports filtering "bpy_extras", "bge", @@ -109,6 +110,18 @@ INFO_DOCS = ( ("info_gotcha.rst", "Gotcha's: some of the problems you may come up against when writing scripts"), ) + +# ----------------------------------------------------------------------------- +# configure compile time options + +try: + __import__("aud") +except ImportError: + print("Warning: Built without 'aud' module, docs incomplete...") + EXCLUDE_MODULES = EXCLUDE_MODULES + ("aud", ) + + + # import rpdb2; rpdb2.start_embedded_debugger('test') import os @@ -120,6 +133,7 @@ import rna_info ClassMethodDescriptorType = type(dict.__dict__['fromkeys']) MethodDescriptorType = type(dict.get) GetSetDescriptorType = type(int.real) +from types import MemberDescriptorType EXAMPLE_SET = set() EXAMPLE_SET_USED = set() @@ -134,6 +148,14 @@ else: _BPY_PROP_COLLECTION_ID = "collection" +def is_struct_seq(value): + return isinstance(value, tuple) and type(tuple) != tuple and hasattr(value, "n_fields") + + +def module_id_as_ref(name): + return "mod_" + name.replace(".", "__") + + def undocumented_message(module_name, type_name, identifier): if str(type_name).startswith('").split(" ", 1)[-1][1:-1] # "" --> bpy.app.handlers + if type(descr) == types.GetSetDescriptorType: + py_descr2sphinx("", fw, descr, module_name, type_name, key) attribute_set.add(key) + descr_sorted = [] for key, descr in sorted(type(module).__dict__.items()): if key.startswith("__"): continue - if type(descr) == types.MemberDescriptorType: + if type(descr) == MemberDescriptorType: if descr.__doc__: - fw(".. data:: %s\n\n" % key) - write_indented_lines(" ", fw, descr.__doc__, False) - fw("\n") - attribute_set.add(key) + value = getattr(module, key, None) + value_type = type(value) + descr_sorted.append((key, descr, value, type(value))) + # sort by the valye type + descr_sorted.sort(key=lambda descr_data: str(descr_data[3])) + for key, descr, value, value_type in descr_sorted: + type_name = value_type.__name__ + py_descr2sphinx("", fw, descr, module_name, type_name, key) - del key, descr + if is_struct_seq(value): + # ack, cant use typical reference because we double up once here + # and one fort he module! + full_name = "%s.%s" % (module_name, type_name) + fw(" :ref:`%s submodule details <%s>`\n\n\n" % (full_name, module_id_as_ref(full_name))) # % (module_name, type_name) + del full_name + + attribute_set.add(key) + + del key, descr, descr_sorted classes = [] submodules = [] + # use this list so we can sort by type + module_dir_value_type = [] + for attribute in module_dir: - if not attribute.startswith("_"): - if attribute in attribute_set: - continue + if attribute.startswith("_"): + continue - if attribute.startswith("n_"): # annoying exception, needed for bpy.app - continue + if attribute in attribute_set: + continue - value = getattr(module, attribute) + if attribute.startswith("n_"): # annoying exception, needed for bpy.app + continue - value_type = type(value) + # workaround for bpy.app documenting .index() and .count() + if isinstance(module, tuple) and hasattr(tuple, attribute): + continue - if value_type == types.FunctionType: - pyfunc2sphinx("", fw, attribute, value, is_class=False) - elif value_type in (types.BuiltinMethodType, types.BuiltinFunctionType): # both the same at the moment but to be future proof - # note: can't get args from these, so dump the string as is - # this means any module used like this must have fully formatted docstrings. - py_c_func2sphinx("", fw, module_name, None, attribute, value, is_class=False) - elif value_type == type: - classes.append((attribute, value)) - elif issubclass(value_type, types.ModuleType): - submodules.append((attribute, value)) - elif value_type in (bool, int, float, str, tuple): - # constant, not much fun we can do here except to list it. - # TODO, figure out some way to document these! - fw(".. data:: %s\n\n" % attribute) - write_indented_lines(" ", fw, "constant value %s" % repr(value), False) - fw("\n") - else: - print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__)) - continue + value = getattr(module, attribute) - attribute_set.add(attribute) - # TODO, more types... + module_dir_value_type.append((attribute, value, type(value))) + + # sort by str of each type + # this way lists, functions etc are grouped. + module_dir_value_type.sort(key=lambda triple: str(triple[2])) + + for attribute, value, value_type in module_dir_value_type: + if value_type == types.FunctionType: + pyfunc2sphinx("", fw, attribute, value, is_class=False) + elif value_type in (types.BuiltinMethodType, types.BuiltinFunctionType): # both the same at the moment but to be future proof + # note: can't get args from these, so dump the string as is + # this means any module used like this must have fully formatted docstrings. + py_c_func2sphinx("", fw, module_name, None, attribute, value, is_class=False) + elif value_type == type: + classes.append((attribute, value)) + elif issubclass(value_type, types.ModuleType): + submodules.append((attribute, value)) + elif value_type in (bool, int, float, str, tuple): + # constant, not much fun we can do here except to list it. + # TODO, figure out some way to document these! + #fw(".. data:: %s\n\n" % attribute) + write_indented_lines(" ", fw, "constant value %s" % repr(value), False) + fw("\n") + else: + print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__)) + continue + + attribute_set.add(attribute) + # TODO, more types... + del module_dir_value_type # TODO, bpy_extras does this already, mathutils not. """ @@ -1103,6 +1165,8 @@ def rna2sphinx(BASEPATH): fw(" bpy.path.rst\n\n") if "bpy.app" not in EXCLUDE_MODULES: fw(" bpy.app.rst\n\n") + if "bpy.app.handlers" not in EXCLUDE_MODULES: + fw(" bpy.app.handlers.rst\n\n") # C modules if "bpy.props" not in EXCLUDE_MODULES: @@ -1242,6 +1306,10 @@ def rna2sphinx(BASEPATH): from bpy import app as module pymodule2sphinx(BASEPATH, "bpy.app", module, "Application Data") + if "bpy.app.handlers" not in EXCLUDE_MODULES: + from bpy.app import handlers as module + pymodule2sphinx(BASEPATH, "bpy.app.handlers", module, "Application Handlers") + if "bpy.props" not in EXCLUDE_MODULES: from bpy import props as module pymodule2sphinx(BASEPATH, "bpy.props", module, "Property Definitions") diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index b7f49bbab47..3d28e45f6b7 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -361,7 +361,7 @@ struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype for(sa= sc->areabase.first; sa; sa= sa->next) { if ((spacetype == -1) || sa->spacetype == spacetype) { - if (min >= sa->winx && min >= sa->winy) { + if (min <= sa->winx && min <= sa->winy) { size= sa->winx*sa->winy; if (size > maxsize) { maxsize= size; diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 5b8c20bb12d..f130a4bcc5c 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -38,21 +38,21 @@ void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg); static PyTypeObject BlenderAppCbType; static PyStructSequence_Field app_cb_info_fields[]= { - {(char *)"frame_change_pre", NULL}, - {(char *)"frame_change_post", NULL}, - {(char *)"render_pre", NULL}, - {(char *)"render_post", NULL}, - {(char *)"render_stats", NULL}, - {(char *)"load_pre", NULL}, - {(char *)"load_post", NULL}, - {(char *)"save_pre", NULL}, - {(char *)"save_post", NULL}, - {(char *)"scene_update_pre", NULL}, - {(char *)"scene_update_post", NULL}, + {(char *)"frame_change_pre", (char *)"Callback list - on frame change for playback and rendering (before)"}, + {(char *)"frame_change_post", (char *)"Callback list - on frame change for playback and rendering (after)"}, + {(char *)"render_pre", (char *)"Callback list - on render (before)"}, + {(char *)"render_post", (char *)"Callback list - on render (after)"}, + {(char *)"render_stats", (char *)"Callback list - on printing render statistics"}, + {(char *)"load_pre", (char *)"Callback list - on loading a new blend file (before)"}, + {(char *)"load_post", (char *)"Callback list - on loading a new blend file (after)"}, + {(char *)"save_pre", (char *)"Callback list - on saving a blend file (before)"}, + {(char *)"save_post", (char *)"Callback list - on saving a blend file (after)"}, + {(char *)"scene_update_pre", (char *)"Callback list - on updating the scenes data (before)"}, + {(char *)"scene_update_post", (char *)"Callback list - on updating the scenes data (after)"}, /* sets the permanent tag */ # define APP_CB_OTHER_FIELDS 1 - {(char *)"persistent", NULL}, + {(char *)"persistent", (char *)"Function decorator for callback functions not to be removed when loading new files"}, {NULL} }; diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index c3a141e7405..02e6ebea71b 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -815,7 +815,7 @@ static struct PyMethodDef game_methods[] = { {"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (const char *)"Gets the estimated average frame rate"}, {"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, (const char *)"Gets a list of blend files in the same directory as the current blend file"}, {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (const char *)"Prints GL Extension Info"}, - {"PrintMemInfo", (PyCFunction)pyPrintStats, METH_NOARGS, (const char *)"Print engine stastics"}, + {"PrintMemInfo", (PyCFunction)pyPrintStats, METH_NOARGS, (const char *)"Print engine statistics"}, /* library functions */ {"LibLoad", (PyCFunction)gLibLoad, METH_VARARGS|METH_KEYWORDS, (const char *)""},