forked from blender/blender
main sync #3
@ -83,8 +83,10 @@ typedef enum {
|
||||
BKE_CB_EVT_RENDER_CANCEL,
|
||||
BKE_CB_EVT_LOAD_PRE,
|
||||
BKE_CB_EVT_LOAD_POST,
|
||||
BKE_CB_EVT_LOAD_POST_FAIL,
|
||||
BKE_CB_EVT_SAVE_PRE,
|
||||
BKE_CB_EVT_SAVE_POST,
|
||||
BKE_CB_EVT_SAVE_POST_FAIL,
|
||||
BKE_CB_EVT_UNDO_PRE,
|
||||
BKE_CB_EVT_UNDO_POST,
|
||||
BKE_CB_EVT_REDO_PRE,
|
||||
@ -123,6 +125,7 @@ void BKE_callback_exec_id_depsgraph(struct Main *bmain,
|
||||
struct ID *id,
|
||||
struct Depsgraph *depsgraph,
|
||||
eCbEvent evt);
|
||||
void BKE_callback_exec_string(struct Main *bmain, eCbEvent evt, const char *str);
|
||||
void BKE_callback_add(bCallbackFuncStore *funcstore, eCbEvent evt);
|
||||
void BKE_callback_remove(bCallbackFuncStore *funcstore, eCbEvent evt);
|
||||
|
||||
|
@ -69,6 +69,18 @@ void BKE_callback_exec_id_depsgraph(struct Main *bmain,
|
||||
BKE_callback_exec(bmain, pointers, 2, evt);
|
||||
}
|
||||
|
||||
void BKE_callback_exec_string(struct Main *bmain, eCbEvent evt, const char *str)
|
||||
{
|
||||
PointerRNA str_ptr;
|
||||
PrimitiveStringRNA data = {};
|
||||
data.value = str;
|
||||
RNA_pointer_create(NULL, &RNA_PrimitiveString, &data, &str_ptr);
|
||||
|
||||
PointerRNA *pointers[1] = {&str_ptr};
|
||||
|
||||
BKE_callback_exec(bmain, pointers, 1, evt);
|
||||
}
|
||||
|
||||
void BKE_callback_add(bCallbackFuncStore *funcstore, eCbEvent evt)
|
||||
{
|
||||
ASSERT_CALLBACKS_INITIALIZED();
|
||||
|
@ -774,6 +774,24 @@ typedef struct ExtensionRNA {
|
||||
StructFreeFunc free;
|
||||
} ExtensionRNA;
|
||||
|
||||
/* Primitive types. */
|
||||
|
||||
typedef struct PrimitiveStringRNA {
|
||||
const char *value;
|
||||
} PrimitiveStringRNA;
|
||||
|
||||
typedef struct PrimitiveIntRNA {
|
||||
int value;
|
||||
} PrimitiveIntRNA;
|
||||
|
||||
typedef struct PrimitiveFloatRNA {
|
||||
float value;
|
||||
} PrimitiveFloatRNA;
|
||||
|
||||
typedef struct PrimitiveBooleanRNA {
|
||||
bool value;
|
||||
} PrimitiveBooleanRNA;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -2775,6 +2775,52 @@ bool rna_property_override_apply_default(Main *bmain,
|
||||
# undef RNA_PROPERTY_GET_SINGLE
|
||||
# undef RNA_PROPERTY_SET_SINGLE
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Primitive Values
|
||||
* \{ */
|
||||
|
||||
/* Primitive String. */
|
||||
|
||||
static void rna_PrimitiveString_value_get(PointerRNA *ptr, char *result)
|
||||
{
|
||||
const PrimitiveStringRNA *data = ptr->data;
|
||||
strcpy(result, data->value ? data->value : "");
|
||||
}
|
||||
|
||||
static int rna_PrimitiveString_value_length(PointerRNA *ptr)
|
||||
{
|
||||
const PrimitiveStringRNA *data = ptr->data;
|
||||
return data->value ? strlen(data->value) : 0;
|
||||
}
|
||||
|
||||
/* Primitive Int. */
|
||||
|
||||
static int rna_PrimitiveInt_value_get(PointerRNA *ptr)
|
||||
{
|
||||
const PrimitiveIntRNA *data = ptr->data;
|
||||
return data->value;
|
||||
}
|
||||
|
||||
/* Primitive Float. */
|
||||
|
||||
static float rna_PrimitiveFloat_value_get(PointerRNA *ptr)
|
||||
{
|
||||
const PrimitiveFloatRNA *data = ptr->data;
|
||||
return data->value;
|
||||
}
|
||||
|
||||
/* Primitive Boolean. */
|
||||
|
||||
static bool rna_PrimitiveBoolean_value_get(PointerRNA *ptr)
|
||||
{
|
||||
const PrimitiveBooleanRNA *data = ptr->data;
|
||||
return data->value;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_struct(BlenderRNA *brna)
|
||||
@ -3367,6 +3413,40 @@ static void rna_def_pointer_property(StructRNA *srna, PropertyType type)
|
||||
RNA_def_property_ui_text(prop, "Pointer Type", "Fixed pointer type, empty if variable type");
|
||||
}
|
||||
|
||||
static void rna_def_rna_primitive(BlenderRNA *brna)
|
||||
{
|
||||
/* Primitive Values, use when passing #PointerRNA is used for primitive types.
|
||||
* For the rare cases we want to pass a value as RNA which wraps a primitive data. */
|
||||
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "PrimitiveString", NULL);
|
||||
RNA_def_struct_ui_text(srna, "String Value", "RNA wrapped string");
|
||||
prop = RNA_def_property(srna, "value", PROP_STRING, PROP_BYTESTRING);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_string_funcs(
|
||||
prop, "rna_PrimitiveString_value_get", "rna_PrimitiveString_value_length", NULL);
|
||||
|
||||
srna = RNA_def_struct(brna, "PrimitiveInt", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Primitive Int", "RNA wrapped int");
|
||||
prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_int_funcs(prop, "rna_PrimitiveInt_value_get", NULL, NULL);
|
||||
|
||||
srna = RNA_def_struct(brna, "PrimitiveFloat", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Primitive Float", "RNA wrapped float");
|
||||
prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_float_funcs(prop, "rna_PrimitiveFloat_value_get", NULL, NULL);
|
||||
|
||||
srna = RNA_def_struct(brna, "PrimitiveBoolean", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Primitive Boolean", "RNA wrapped boolean");
|
||||
prop = RNA_def_property(srna, "value", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_PrimitiveBoolean_value_get", NULL);
|
||||
}
|
||||
|
||||
void RNA_def_rna(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@ -3451,6 +3531,8 @@ void RNA_def_rna(BlenderRNA *brna)
|
||||
# endif
|
||||
|
||||
RNA_def_property_ui_text(prop, "Structs", "");
|
||||
|
||||
rna_def_rna_primitive(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -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
|
||||
|
@ -7407,6 +7407,27 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
|
||||
return (PyObject *)pyrna;
|
||||
}
|
||||
|
||||
PyObject *pyrna_struct_CreatePyObject_with_primitive_support(PointerRNA *ptr)
|
||||
{
|
||||
if (ptr->type == &RNA_PrimitiveString) {
|
||||
const PrimitiveStringRNA *data = ptr->data;
|
||||
return PyC_UnicodeFromBytes(data->value);
|
||||
}
|
||||
if (ptr->type == &RNA_PrimitiveInt) {
|
||||
const PrimitiveIntRNA *data = ptr->data;
|
||||
return PyLong_FromLong(data->value);
|
||||
}
|
||||
if (ptr->type == &RNA_PrimitiveFloat) {
|
||||
const PrimitiveFloatRNA *data = ptr->data;
|
||||
return PyFloat_FromDouble(data->value);
|
||||
}
|
||||
if (ptr->type == &RNA_PrimitiveBoolean) {
|
||||
const PrimitiveBooleanRNA *data = ptr->data;
|
||||
return PyBool_FromLong(data->value);
|
||||
}
|
||||
return pyrna_struct_CreatePyObject(ptr);
|
||||
}
|
||||
|
||||
PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop)
|
||||
{
|
||||
BPy_PropertyRNA *pyrna;
|
||||
|
@ -173,6 +173,7 @@ void BPY_update_rna_module(void);
|
||||
// PyObject *BPY_rna_doc(void);
|
||||
PyObject *BPY_rna_types(void);
|
||||
|
||||
PyObject *pyrna_struct_CreatePyObject_with_primitive_support(PointerRNA *ptr);
|
||||
PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr);
|
||||
PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop);
|
||||
|
||||
|
@ -632,10 +632,9 @@ void wm_file_read_report(bContext *C, Main *bmain)
|
||||
* \note In the case of #WM_file_read the file may fail to load.
|
||||
* Change here shouldn't cause user-visible changes in that case.
|
||||
*/
|
||||
static void wm_file_read_pre(bContext *C, bool use_data, bool /*use_userdef*/)
|
||||
static void wm_file_read_pre(bool use_data, bool /*use_userdef*/)
|
||||
{
|
||||
if (use_data) {
|
||||
BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE);
|
||||
BLI_timer_on_file_load();
|
||||
}
|
||||
|
||||
@ -656,6 +655,10 @@ struct wmFileReadPost_Params {
|
||||
uint is_startup_file : 1;
|
||||
uint is_factory_startup : 1;
|
||||
uint reset_app_template : 1;
|
||||
|
||||
/* Used by #wm_homefile_read_post */
|
||||
uint success : 1;
|
||||
uint is_alloc : 1;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -747,7 +750,6 @@ static void wm_file_read_post(bContext *C, const struct wmFileReadPost_Params *p
|
||||
if (use_data) {
|
||||
/* important to do before nullptr'ing the context */
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_VERSION_UPDATE);
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_LOAD_POST);
|
||||
if (is_factory_startup) {
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_LOAD_FACTORY_STARTUP_POST);
|
||||
}
|
||||
@ -944,6 +946,10 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
|
||||
const bool use_data = true;
|
||||
const bool use_userdef = false;
|
||||
|
||||
/* NOTE: either #BKE_CB_EVT_LOAD_POST or #BKE_CB_EVT_LOAD_POST_FAIL must run.
|
||||
* Runs at the end of this function, don't return beforehand. */
|
||||
BKE_callback_exec_string(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE, filepath);
|
||||
|
||||
/* so we can get the error message */
|
||||
errno = 0;
|
||||
|
||||
@ -968,7 +974,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
|
||||
bf_reports.duration.whole = PIL_check_seconds_timer();
|
||||
struct BlendFileData *bfd = BKE_blendfile_read(filepath, ¶ms, &bf_reports);
|
||||
if (bfd != nullptr) {
|
||||
wm_file_read_pre(C, use_data, use_userdef);
|
||||
wm_file_read_pre(use_data, use_userdef);
|
||||
|
||||
/* Put aside screens to match with persistent windows later,
|
||||
* also exit screens and editors. */
|
||||
@ -1004,6 +1010,8 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
|
||||
read_file_post_params.is_startup_file = false;
|
||||
read_file_post_params.is_factory_startup = false;
|
||||
read_file_post_params.reset_app_template = false;
|
||||
read_file_post_params.success = true;
|
||||
read_file_post_params.is_alloc = false;
|
||||
wm_file_read_post(C, &read_file_post_params);
|
||||
|
||||
bf_reports.duration.whole = PIL_check_seconds_timer() - bf_reports.duration.whole;
|
||||
@ -1048,7 +1056,11 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
|
||||
|
||||
WM_cursor_wait(false);
|
||||
|
||||
BLI_assert(BKE_main_namemap_validate(CTX_data_main(C)));
|
||||
Main *bmain = CTX_data_main(C);
|
||||
BKE_callback_exec_string(
|
||||
bmain, success ? BKE_CB_EVT_LOAD_POST : BKE_CB_EVT_LOAD_POST_FAIL, filepath);
|
||||
|
||||
BLI_assert(BKE_main_namemap_validate(bmain));
|
||||
|
||||
return success;
|
||||
}
|
||||
@ -1178,10 +1190,16 @@ void wm_homefile_read_ex(bContext *C,
|
||||
#endif /* WITH_PYTHON */
|
||||
}
|
||||
|
||||
if (use_data) {
|
||||
/* NOTE: either #BKE_CB_EVT_LOAD_POST or #BKE_CB_EVT_LOAD_POST_FAIL must run.
|
||||
* This runs from #wm_homefile_read_post. */
|
||||
BKE_callback_exec_string(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE, "");
|
||||
}
|
||||
|
||||
/* For regular file loading this only runs after the file is successfully read.
|
||||
* In the case of the startup file, the in-memory startup file is used as a fallback
|
||||
* so we know this will work if all else fails. */
|
||||
wm_file_read_pre(C, use_data, use_userdef);
|
||||
wm_file_read_pre(use_data, use_userdef);
|
||||
|
||||
if (use_data) {
|
||||
/* put aside screens to match with persistent windows later */
|
||||
@ -1392,10 +1410,14 @@ void wm_homefile_read_ex(bContext *C,
|
||||
params_file_read_post.is_factory_startup = is_factory_startup;
|
||||
params_file_read_post.reset_app_template = reset_app_template;
|
||||
|
||||
params_file_read_post.success = success;
|
||||
params_file_read_post.is_alloc = false;
|
||||
|
||||
if (r_params_file_read_post == nullptr) {
|
||||
wm_file_read_post(C, ¶ms_file_read_post);
|
||||
wm_homefile_read_post(C, ¶ms_file_read_post);
|
||||
}
|
||||
else {
|
||||
params_file_read_post.is_alloc = true;
|
||||
*r_params_file_read_post = static_cast<wmFileReadPost_Params *>(
|
||||
MEM_mallocN(sizeof(wmFileReadPost_Params), __func__));
|
||||
**r_params_file_read_post = params_file_read_post;
|
||||
@ -1417,7 +1439,17 @@ void wm_homefile_read_post(struct bContext *C,
|
||||
const struct wmFileReadPost_Params *params_file_read_post)
|
||||
{
|
||||
wm_file_read_post(C, params_file_read_post);
|
||||
|
||||
if (params_file_read_post->use_data) {
|
||||
BKE_callback_exec_string(CTX_data_main(C),
|
||||
params_file_read_post->success ? BKE_CB_EVT_LOAD_POST :
|
||||
BKE_CB_EVT_LOAD_POST_FAIL,
|
||||
"");
|
||||
}
|
||||
|
||||
if (params_file_read_post->is_alloc) {
|
||||
MEM_freeN((void *)params_file_read_post);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@ -1820,7 +1852,10 @@ static bool wm_file_write(bContext *C,
|
||||
|
||||
/* Call pre-save callbacks before writing preview,
|
||||
* that way you can generate custom file thumbnail. */
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_SAVE_PRE);
|
||||
|
||||
/* NOTE: either #BKE_CB_EVT_SAVE_POST or #BKE_CB_EVT_SAVE_POST_FAIL must run.
|
||||
* Runs at the end of this function, don't return beforehand. */
|
||||
BKE_callback_exec_string(bmain, BKE_CB_EVT_SAVE_PRE, filepath);
|
||||
ED_assets_pre_save(bmain);
|
||||
|
||||
/* Enforce full override check/generation on file save. */
|
||||
@ -1906,8 +1941,6 @@ static bool wm_file_write(bContext *C,
|
||||
wm_history_file_update();
|
||||
}
|
||||
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_SAVE_POST);
|
||||
|
||||
/* run this function after because the file can't be written before the blend is */
|
||||
if (ibuf_thumb) {
|
||||
IMB_thumb_delete(filepath, THB_FAIL); /* without this a failed thumb overrides */
|
||||
@ -1921,6 +1954,8 @@ static bool wm_file_write(bContext *C,
|
||||
ok = true;
|
||||
}
|
||||
|
||||
BKE_callback_exec_string(bmain, ok ? BKE_CB_EVT_SAVE_POST : BKE_CB_EVT_SAVE_POST_FAIL, filepath);
|
||||
|
||||
if (ibuf_thumb) {
|
||||
IMB_freeImBuf(ibuf_thumb);
|
||||
}
|
||||
@ -2154,7 +2189,9 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_SAVE_PRE);
|
||||
/* NOTE: either #BKE_CB_EVT_SAVE_POST or #BKE_CB_EVT_SAVE_POST_FAIL must run.
|
||||
* Runs at the end of this function, don't return beforehand. */
|
||||
BKE_callback_exec_string(bmain, BKE_CB_EVT_SAVE_PRE, "");
|
||||
ED_assets_pre_save(bmain);
|
||||
|
||||
/* check current window and close it if temp */
|
||||
@ -2181,17 +2218,17 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
|
||||
blend_write_params.remap_mode = BLO_WRITE_PATH_REMAP_ABSOLUTE;
|
||||
/* Don't apply any path changes to the current blend file. */
|
||||
blend_write_params.use_save_as_copy = true;
|
||||
if (BLO_write_file(bmain, filepath, fileflags, &blend_write_params, op->reports) == 0) {
|
||||
printf("fail\n");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
const bool ok = BLO_write_file(bmain, filepath, fileflags, &blend_write_params, op->reports);
|
||||
|
||||
BKE_callback_exec_string(bmain, ok ? BKE_CB_EVT_SAVE_POST : BKE_CB_EVT_SAVE_POST_FAIL, "");
|
||||
|
||||
if (ok) {
|
||||
printf("ok\n");
|
||||
BKE_report(op->reports, RPT_INFO, "Startup file saved");
|
||||
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_SAVE_POST);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
printf("fail\n");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void WM_OT_save_homefile(wmOperatorType *ot)
|
||||
|
Loading…
Reference in New Issue
Block a user