PyAPI: extend save/load handlers, optionally take a filepath argument

Add a filepath argument to load/save pre/post.
Also add save_post_failed and load_post_failed handlers so it's always
possible to for the pre handlers to run a matching post action.

This makes it possible to know the filepath of the blend file mean
loaded/saved as well as supporting running an action when load/save
operations fail.

When loading and saving the startup-file, the path argument is set to
an empty string.

Details:

New RNA types were added to support storing primitive values in
PointerRNA. Primitive{String/Int/Float/Boolean}RNA. These will likely
only be used in some limited cases, in the case of BKE_callback_exec it
allows strings to be included as part of the PointerRNA **pointers
argument.

Ref !104769.
This commit is contained in:
2023-03-09 10:46:49 +11:00
parent 1cc072b1a7
commit 46be42f6b1
8 changed files with 218 additions and 28 deletions

View File

@@ -14,7 +14,9 @@
#include "BKE_callbacks.h"
#include "RNA_access.h"
#include "RNA_prototypes.h"
#include "RNA_types.h"
#include "bpy_app_handlers.h"
#include "bpy_rna.h"
@@ -29,6 +31,13 @@ void bpy_app_generic_callback(struct Main *main,
static PyTypeObject BlenderAppCbType;
#define FILEPATH_SAVE_ARG \
"Accepts one argument: " \
"the file being saved, an empty string for the startup-file."
#define FILEPATH_LOAD_ARG \
"Accepts one argument: " \
"the file being loaded, an empty string for the startup-file."
/**
* See `BKE_callbacks.h` #eCbEvent declaration for the policy on naming.
*/
@@ -50,10 +59,15 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{"render_init", "on initialization of a render job"},
{"render_complete", "on completion of render job"},
{"render_cancel", "on canceling a render job"},
{"load_pre", "on loading a new blend file (before)"},
{"load_post", "on loading a new blend file (after)"},
{"save_pre", "on saving a blend file (before)"},
{"save_post", "on saving a blend file (after)"},
{"load_pre", "on loading a new blend file (before)." FILEPATH_LOAD_ARG},
{"load_post", "on loading a new blend file (after). " FILEPATH_LOAD_ARG},
{"load_post_fail", "on failure to load a new blend file (after). " FILEPATH_LOAD_ARG},
{"save_pre", "on saving a blend file (before). " FILEPATH_SAVE_ARG},
{"save_post", "on saving a blend file (after). " FILEPATH_SAVE_ARG},
{"save_post_fail", "on failure to save a blend file (after). " FILEPATH_SAVE_ARG},
{"undo_pre", "on loading an undo step (before)"},
{"undo_post", "on loading an undo step (after)"},
{"redo_pre", "on loading a redo step (before)"},
@@ -344,7 +358,8 @@ void bpy_app_generic_callback(struct Main *UNUSED(main),
/* setup arguments */
for (int i = 0; i < pointers_num; ++i) {
PyTuple_SET_ITEM(args_all, i, pyrna_struct_CreatePyObject(pointers[i]));
PyTuple_SET_ITEM(
args_all, i, pyrna_struct_CreatePyObject_with_primitive_support(pointers[i]));
}
for (int i = pointers_num; i < num_arguments; ++i) {
PyTuple_SET_ITEM(args_all, i, Py_INCREF_RET(Py_None));
@@ -354,7 +369,8 @@ void bpy_app_generic_callback(struct Main *UNUSED(main),
PyTuple_SET_ITEM(args_single, 0, Py_INCREF_RET(Py_None));
}
else {
PyTuple_SET_ITEM(args_single, 0, pyrna_struct_CreatePyObject(pointers[0]));
PyTuple_SET_ITEM(
args_single, 0, pyrna_struct_CreatePyObject_with_primitive_support(pointers[0]));
}
/* Iterate the list and run the callbacks