From 0fff238150d076576053c25b646f653d6e3b0edb Mon Sep 17 00:00:00 2001 From: Colin Basnett Date: Mon, 20 Jun 2022 16:52:14 -0700 Subject: Moved some things around, finally have a global hash table for registered image formats --- source/blender/blentranslation/BLT_translation.h | 3 + source/blender/makesdna/DNA_image_types.h | 3 - source/blender/makesrna/intern/rna_image.c | 212 -------------------- source/blender/makesrna/intern/rna_wm.c | 220 +++++++++++++++++++++ .../blender/python/intern/bpy_imageformat_wrap.c | 40 ++++ .../blender/python/intern/bpy_imageformat_wrap.h | 24 +++ source/blender/windowmanager/WM_api.h | 22 +++ .../windowmanager/intern/wm_imageformat_type.c | 201 +++++++++++++++++++ source/blender/windowmanager/intern/wm_init_exit.c | 2 + 9 files changed, 512 insertions(+), 215 deletions(-) create mode 100644 source/blender/python/intern/bpy_imageformat_wrap.c create mode 100644 source/blender/python/intern/bpy_imageformat_wrap.h create mode 100644 source/blender/windowmanager/intern/wm_imageformat_type.c diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h index 129eba3de2f..247be831aad 100644 --- a/source/blender/blentranslation/BLT_translation.h +++ b/source/blender/blentranslation/BLT_translation.h @@ -69,6 +69,9 @@ const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid /* Default context for operator names/labels. */ #define BLT_I18NCONTEXT_OPERATOR_DEFAULT "Operator" +/* Default context for image format names/labels. */ +#define BLT_I18CONTEXT_IMAGEFORMAT_DEFAULT "Image Format" + /* Context for events/keymaps (necessary, since those often use one or two letters, * easy to get collisions with other areas...). */ #define BLT_I18NCONTEXT_UI_EVENTS "UI_Events_KeyMaps" diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index e521dae219d..07b1928717a 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -276,9 +276,6 @@ enum { typedef struct imfImageFormat { struct imfImageFormat *next, *prev; - - const char *bl_extensions; - struct imfImageFormatType *type; } imfImageFormat; diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 38706606997..abf3d5cfcde 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -53,45 +53,6 @@ static const EnumPropertyItem image_source_items[] = { {0, NULL, 0, NULL, NULL}, }; -#ifdef WITH_PYTHON - -static bool rna_imageformat_is_a_bytes_cb(const struct bContext *C, - struct imfImageFormatType *ift, - const char *bytes) -{ - extern FunctionRNA rna_ImageFormat_is_a_bytes_func; - - PointerRNA ptr; - ParameterList list; - FunctionRNA *func; - void *ret; - bool is_a_bytes; - - /* seems to be some sort of temporary rna pointer?? */ - RNA_pointer_create(NULL, ift->rna_ext.srna, NULL, &ptr); - func = &rna_ImageFormat_is_a_bytes_func; - - /* set up arguments */ - RNA_parameter_list_create(&list, &ptr, func); - RNA_parameter_set_lookup(&list, "data", bytes); - - /* call function */ - ift->rna_ext.call((struct bContext *)C, &ptr, func, &list); - - /* get return value */ - RNA_parameter_get_lookup(&list, "result", &ret); - is_a_bytes = *(bool *)ret; - - return is_a_bytes; -} - -static Image *rna_imageformat_load_cb(struct imfImageFormatType *ift, const char *bytes) -{ - return NULL; -} - -#endif /* WITH_PYTHON */ - #ifdef RNA_RUNTIME @@ -731,129 +692,6 @@ static void rna_UDIMTile_remove(Image *image, PointerRNA *ptr) WM_main_add_notifier(NC_IMAGE | ND_DRAW, NULL); } -static StructRNA *rna_ImageFormat_register(Main *bmain, - ReportList *reports, - void *data, - const char *identifier, - StructValidateFunc validate, - StructCallbackFunc call, - StructFreeFunc free) -{ - struct { - char idname[MAX_NAME]; - char extensions[MAX_NAME]; - } temp_buffers; - - imfImageFormatType dummy_type = {NULL}; - imfImageFormat dummy = {NULL}; - PointerRNA mnp_ptr; - - /* TODO: how is the size determined? magic of rna defs? */ - int have_function[2]; - - /* setup dummy gizmo & gizmo type to store static properties in */ - dummy.type = &dummy_type; - dummy_type.idname = temp_buffers.idname; - dummy_type.extensions = temp_buffers.extensions; - RNA_pointer_create(NULL, &RNA_ImageFormat, &dummy, &mnp_ptr); - - /* Clear so we can detect if it's left unset. */ - temp_buffers.idname[0] = '\0'; - temp_buffers.extensions[0] = '\0'; - - /* validate the python class */ - if (validate(&mnp_ptr, data, have_function) != 0) { - return NULL; - } - - /* make sure the id does not exceeed buffer length */ - if (strlen(identifier) >= sizeof(temp_buffers.idname)) { - BKE_reportf(reports, - RPT_ERROR, - "Registering image format class: '%s' is too long, maximum length is %d", - identifier, - (int)sizeof(temp_buffers.idname)); - return NULL; - } - - // TODO: check if we've added this gizmo before, remove it if so. - { - } - - if (!RNA_struct_available_or_report(reports, dummy_type.idname)) { - return NULL; - } - - if (!RNA_struct_bl_idname_ok_or_report(reports, dummy_type.idname, "_IF_")) { - return NULL; - } - - { - /* allocate the idname */ - dummy_type.idname = BLI_strdup(temp_buffers.idname); - } - - /* Create a new ImageFormat type. */ - dummy_type.rna_ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummy_type.idname, &RNA_ImageFormat); - dummy_type.rna_ext.data = data; - dummy_type.rna_ext.call = call; - dummy_type.rna_ext.free = free; - RNA_def_struct_flag(dummy_type.rna_ext.srna, STRUCT_NO_IDPROPERTIES | STRUCT_RUNTIME); - - // function callbacks - { - int i = 0; - dummy_type.is_a_bytes = (have_function[i++]) ? rna_imageformat_is_a_bytes_cb : NULL; - dummy_type.load = (have_function[i++]) ? rna_imageformat_load_cb : NULL; - BLI_assert(i == ARRAY_SIZE(have_function)); - } - - // TODO: actually register the type in a list somewhere! (wm, probably) - - /* update while blender is running */ - WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); - - return dummy_type.rna_ext.srna; -} - -static void rna_ImageFormat_unregister(Main *UNUSED(bmain), StructRNA *type) -{ - imfImageFormatType *ift = RNA_struct_blender_type_get(type); - - if (!ift) { - return; - } - - //WM_gizmotype_remove_ptr(NULL, bmain, gzt); - - /* Free extension after removing instances so `__del__` doesn't crash, see: T85567. */ - RNA_struct_free_extension(type, &ift->rna_ext); - RNA_struct_free(&BLENDER_RNA, type); - - /* Free gizmo group after the extension as it owns the identifier memory. */ - //WM_gizmotype_free_ptr(gzt); - - WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); -} - -static StructRNA *rna_ImageFormat_refine(PointerRNA *ptr) -{ - imfImageFormat *imf = (imfImageFormat *)ptr->data; - return (imf->type && imf->type->rna_ext.srna) ? imf->type->rna_ext.srna : &RNA_ImageFormat; -} - -static void rna_ImageFormat_bl_extensions_set(PointerRNA *ptr, const char *value) -{ - imfImageFormat *data = ptr->data; - char *str = (char *)data->type->extensions; - if (!str[0]) { - BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */ - } - else { - BLI_assert_msg(0, "setting the bl_idname on a non-builtin operator"); - } -} - #else static void rna_def_imageuser(BlenderRNA *brna) @@ -1115,55 +953,6 @@ static void rna_def_udim_tiles(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); } -static void rna_def_imageformat(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - FunctionRNA *func; - - // TODO: are we just missing a text thingy? - srna = RNA_def_struct(brna, "ImageFormat", NULL); - RNA_def_struct_sdna(srna, "imfImageFormat"); - RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); - RNA_def_struct_register_funcs(srna, "rna_ImageFormat_register", "rna_ImageFormat_unregister", NULL); - RNA_def_struct_refine_func(srna, "rna_ImageFormat_refine"); - - /* - TODO: ideally we want a list of these instead of a single string, - but we'll have to deal with this for now - */ - /* extensions (semicolon separated) */ - prop = RNA_def_property(srna, "bl_extensions", PROP_STRING, PROP_NONE); - //RNA_def_property_string_sdna(prop, NULL, "type->extensions"); - RNA_def_property_string_maxlength(prop, MAX_NAME); - RNA_def_property_flag(prop, PROP_NEVER_NULL | PROP_REGISTER); - RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ImageFormat_bl_extensions_set"); - - /* idname */ - prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "type->idname"); - RNA_def_property_string_maxlength(prop, MAX_NAME); - RNA_def_property_flag(prop, PROP_REGISTER); - - /* is_a_bytes */ - func = RNA_def_function(srna, "is_a_bytes", NULL); - RNA_def_function_ui_description(func, "FILLMEIN"); - RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER); - prop = RNA_def_property(func, "data", PROP_STRING, PROP_BYTESTRING); - RNA_def_parameter_flags(prop, PROP_NEVER_NULL, PARM_REQUIRED); - prop = RNA_def_boolean(func, "result", false, "", ""); - RNA_def_function_return(func, prop); - - /* load */ - func = RNA_def_function(srna, "load", NULL); - RNA_def_function_ui_description(func, "FILLMEIN"); - RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER); - prop = RNA_def_property(func, "data", PROP_STRING, PROP_BYTESTRING); - RNA_def_parameter_flags(prop, PROP_NEVER_NULL, PARM_REQUIRED); - prop = RNA_def_pointer(func, "result", "Image", "", ""); // TODO: this should return an imbuf! - RNA_def_function_return(func, prop); -} - static void rna_def_image(BlenderRNA *brna) { StructRNA *srna; @@ -1466,7 +1255,6 @@ void RNA_def_image(BlenderRNA *brna) { rna_def_render_slot(brna); rna_def_udim_tile(brna); - rna_def_imageformat(brna); rna_def_image(brna); rna_def_imageuser(brna); rna_def_image_packed_files(brna); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 3ff9e6be3ce..a76524e934c 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -504,6 +504,45 @@ const EnumPropertyItem rna_enum_wm_report_items[] = { {0, NULL, 0, NULL, NULL}, }; +#ifdef WITH_PYTHON + +static bool rna_imageformat_is_a_bytes_cb(const struct bContext *C, + struct imfImageFormatType *ift, + const char *bytes) +{ + extern FunctionRNA rna_ImageFormat_is_a_bytes_func; + + PointerRNA ptr; + ParameterList list; + FunctionRNA *func; + void *ret; + bool is_a_bytes; + + /* seems to be some sort of temporary rna pointer?? */ + RNA_pointer_create(NULL, ift->rna_ext.srna, NULL, &ptr); + func = &rna_ImageFormat_is_a_bytes_func; + + /* set up arguments */ + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "data", bytes); + + /* call function */ + ift->rna_ext.call((struct bContext *)C, &ptr, func, &list); + + /* get return value */ + RNA_parameter_get_lookup(&list, "result", &ret); + is_a_bytes = *(bool *)ret; + + return is_a_bytes; +} + +static Image *rna_imageformat_load_cb(struct imfImageFormatType *ift, const char *bytes) +{ + return NULL; +} + +#endif /* WITH_PYTHON */ + #ifdef RNA_RUNTIME # include "BLI_string_utils.h" @@ -1434,6 +1473,10 @@ static void rna_Operator_unregister(struct Main *bmain, StructRNA *type); extern void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata); extern void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata); +/* bpy_imageformat_wrap.c */ + +extern void BPY_RNA_imageformat_wrapper(imfImageFormatType *ift, void *userdata); + static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *data, @@ -1783,6 +1826,132 @@ static void rna_KeyMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi WM_keyconfig_update_tag(NULL, kmi); } +static void rna_ImageFormat_unregister(Main *UNUSED(bmain), StructRNA *type) +{ + imfImageFormatType *ift = RNA_struct_blender_type_get(type); + + if (!ift) { + return; + } + + // WM_gizmotype_remove_ptr(NULL, bmain, gzt); + + /* Free extension after removing instances so `__del__` doesn't crash, see: T85567. */ + RNA_struct_free_extension(type, &ift->rna_ext); + RNA_struct_free(&BLENDER_RNA, type); + + /* Free image format type after the extension as it owns the identifier memory. */ + wm_imageformattype_remove_ptr(ift); + + WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); +} + +static StructRNA *rna_ImageFormat_register(Main *bmain, + ReportList *reports, + void *data, + const char *identifier, + StructValidateFunc validate, + StructCallbackFunc call, + StructFreeFunc free) +{ + struct { + char idname[MAX_NAME]; + char extensions[MAX_NAME]; + } temp_buffers; + + imfImageFormatType dummy_type = {NULL}; + imfImageFormat dummy = {NULL}; + PointerRNA mnp_ptr; + + /* TODO: how is the size determined? magic of rna defs? */ + int have_function[2]; + + /* setup dummy gizmo & gizmo type to store static properties in */ + dummy.type = &dummy_type; + dummy_type.idname = temp_buffers.idname; + dummy_type.extensions = temp_buffers.extensions; + RNA_pointer_create(NULL, &RNA_ImageFormat, &dummy, &mnp_ptr); + + /* Clear so we can detect if it's left unset. */ + temp_buffers.idname[0] = '\0'; + temp_buffers.extensions[0] = '\0'; + + /* validate the python class */ + if (validate(&mnp_ptr, data, have_function) != 0) { + return NULL; + } + + /* make sure the id does not exceeed buffer length */ + if (strlen(identifier) >= sizeof(temp_buffers.idname)) { + BKE_reportf(reports, + RPT_ERROR, + "Registering image format class: '%s' is too long, maximum length is %d", + identifier, + (int)sizeof(temp_buffers.idname)); + return NULL; + } + + /* unregister image format type with same ID */ + imfImageFormatType *ift = WM_imageformattype_find(dummy_type.idname, true); + if (ift && ift->rna_ext.srna) { + rna_ImageFormat_unregister(bmain, ift->rna_ext.srna); + } + + if (!RNA_struct_available_or_report(reports, dummy_type.idname)) { + return NULL; + } + + if (!RNA_struct_bl_idname_ok_or_report(reports, dummy_type.idname, "_IF_")) { + return NULL; + } + + { + /* allocate the idname */ + dummy_type.idname = BLI_strdup(temp_buffers.idname); + } + + /* Create a new ImageFormat type. */ + dummy_type.rna_ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummy_type.idname, &RNA_ImageFormat); + dummy_type.rna_ext.data = data; + dummy_type.rna_ext.call = call; + dummy_type.rna_ext.free = free; + RNA_def_struct_flag(dummy_type.rna_ext.srna, STRUCT_NO_IDPROPERTIES | STRUCT_RUNTIME); + + // function callbacks + { + int i = 0; + dummy_type.is_a_bytes = (have_function[i++]) ? rna_imageformat_is_a_bytes_cb : NULL; + dummy_type.load = (have_function[i++]) ? rna_imageformat_load_cb : NULL; + BLI_assert(i == ARRAY_SIZE(have_function)); + } + + // register the image format type + wm_imageformattype_append_ptr(BPY_RNA_imageformat_wrapper, (void *)&dummy_type); + + /* update while blender is running */ + WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); + + return dummy_type.rna_ext.srna; +} + +static StructRNA *rna_ImageFormat_refine(PointerRNA *ptr) +{ + imfImageFormat *imf = (imfImageFormat *)ptr->data; + return (imf->type && imf->type->rna_ext.srna) ? imf->type->rna_ext.srna : &RNA_ImageFormat; +} + +static void rna_ImageFormat_bl_extensions_set(PointerRNA *ptr, const char *value) +{ + imfImageFormat *data = ptr->data; + char *str = (char *)data->type->extensions; + if (!str[0]) { + BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */ + } + else { + BLI_assert_msg(0, "setting the bl_idname on a non-builtin operator"); + } +} + #else /* RNA_RUNTIME */ /** @@ -2784,6 +2953,56 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_api_keymapitem(srna); } +static void rna_def_imageformat(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + FunctionRNA *func; + + // TODO: are we just missing a text thingy? + srna = RNA_def_struct(brna, "ImageFormat", NULL); + RNA_def_struct_sdna(srna, "imfImageFormat"); + RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); + RNA_def_struct_register_funcs( + srna, "rna_ImageFormat_register", "rna_ImageFormat_unregister", NULL); + RNA_def_struct_refine_func(srna, "rna_ImageFormat_refine"); + + /* + TODO: ideally we want a list of these instead of a single string, + but we'll have to deal with this for now + */ + /* extensions (semicolon separated) */ + prop = RNA_def_property(srna, "bl_extensions", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->extensions"); + RNA_def_property_string_maxlength(prop, MAX_NAME); + RNA_def_property_flag(prop, PROP_NEVER_NULL | PROP_REGISTER); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ImageFormat_bl_extensions_set"); + + /* idname */ + prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->idname"); + RNA_def_property_string_maxlength(prop, MAX_NAME); + RNA_def_property_flag(prop, PROP_REGISTER); + + /* is_a_bytes */ + func = RNA_def_function(srna, "is_a_bytes", NULL); + RNA_def_function_ui_description(func, "FILLMEIN"); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER); + prop = RNA_def_property(func, "data", PROP_STRING, PROP_BYTESTRING); + RNA_def_parameter_flags(prop, PROP_NEVER_NULL, PARM_REQUIRED); + prop = RNA_def_boolean(func, "result", false, "", ""); + RNA_def_function_return(func, prop); + + /* load */ + func = RNA_def_function(srna, "load", NULL); + RNA_def_function_ui_description(func, "FILLMEIN"); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER); + prop = RNA_def_property(func, "data", PROP_STRING, PROP_BYTESTRING); + RNA_def_parameter_flags(prop, PROP_NEVER_NULL, PARM_REQUIRED); + prop = RNA_def_pointer(func, "result", "Image", "", ""); // TODO: this should return an imbuf! + RNA_def_function_return(func, prop); +} + void RNA_def_wm(BlenderRNA *brna) { rna_def_operator(brna); @@ -2801,6 +3020,7 @@ void RNA_def_wm(BlenderRNA *brna) rna_def_windowmanager(brna); rna_def_keyconfig_prefs(brna); rna_def_keyconfig(brna); + rna_def_imageformat(brna); } #endif /* RNA_RUNTIME */ diff --git a/source/blender/python/intern/bpy_imageformat_wrap.c b/source/blender/python/intern/bpy_imageformat_wrap.c new file mode 100644 index 00000000000..988292b01f7 --- /dev/null +++ b/source/blender/python/intern/bpy_imageformat_wrap.c @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup pythonintern + * + * This file exposes functionality for defining to define operators that C can call into. + * The generic callback functions for python operators are defines in + * 'rna_wm.c', some calling into functions here to do python specific + * functionality. + */ + +#include + +#include "BLI_utildefines.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_prototypes.h" + +#include "bpy_intern_string.h" +#include "bpy_imageformat_wrap.h" /* own include */ +#include "bpy_rna.h" + +void BPY_RNA_imageformat_wrapper(imfImageFormatType *ift, void *userdata) +{ + /* take care not to overwrite anything set in + * WM_imageformattype_append_ptr before opfunc() is called */ + StructRNA *srna = ift->srna; + *ift = *((imfImageFormatType *)userdata); + ift->srna = srna; /* restore */ + + /* Use i18n context from rna_ext.srna if possible (py image formats). */ + if (ift->rna_ext.srna) { + RNA_def_struct_translation_context(ift->srna, + RNA_struct_translation_context(ift->rna_ext.srna)); + } +} diff --git a/source/blender/python/intern/bpy_imageformat_wrap.h b/source/blender/python/intern/bpy_imageformat_wrap.h new file mode 100644 index 00000000000..61ccc6613ba --- /dev/null +++ b/source/blender/python/intern/bpy_imageformat_wrap.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup pythonintern + */ + +#pragma once + +struct imfImageFormatType; + +#ifdef __cplusplus +extern "C" { +#endif + +/* exposed to rna/wm api */ +/** + * Generic function used by all Python defined image formats + * it's passed as an argument to #WM_imageformattype_append_ptr in for image format registration. + */ +void BPY_RNA_imageformat_wrapper(struct imfImageFormatType *ift, void *userdata); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 60cded3b869..208704caf49 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -1792,6 +1792,28 @@ bool WM_xr_actionmap_binding_remove(XrActionMapItem *ami, XrActionMapBinding *am XrActionMapBinding *WM_xr_actionmap_binding_find(XrActionMapItem *ami, const char *name); #endif /* WITH_XR_OPENXR */ +/** + * Image Formats + */ + +imfImageFormatType *WM_imageformattype_find(const char *idname, bool quiet); +void wm_imageformattype_iter(struct GHashIterator *ghi); +static imfImageFormatType *wm_imageformattype_append__begin(void); +static void wm_imageformattype_append__end(imfImageFormatType *ift); +void wm_imageformattype_append(void (*opfunc)(imfImageFormatType *)); +void wm_imageformattype_append_ptr(void (*opfunc)(imfImageFormatType *, void *), void *userdata); +void wm_imageformattype_remove_ptr(imfImageFormatType *ift); +bool wm_imageformattype_remove(const char *idname); +void wm_imageformattype_init(void); +static void imageformattype_ghash_free_cb(imfImageFormatType *ift); +void wm_imageformattype_free(void); +void wm_imageformattype_idname_visit_for_search(const struct bContext *C, + PointerRNA *ptr, + PropertyRNA *prop, + const char *edit_text, + StringPropertySearchVisitFunc visit_fn, + void *visit_user_data); + #ifdef __cplusplus } #endif diff --git a/source/blender/windowmanager/intern/wm_imageformat_type.c b/source/blender/windowmanager/intern/wm_imageformat_type.c new file mode 100644 index 00000000000..5efdf67ed56 --- /dev/null +++ b/source/blender/windowmanager/intern/wm_imageformat_type.c @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup wm + * + * Operator Registry. + */ + +#include "MEM_guardedalloc.h" + +#include "CLG_log.h" + +#include "DNA_ID.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" + +#include "BLT_translation.h" + +#include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_idprop.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" +#include "RNA_prototypes.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "wm.h" +#include "wm_event_system.h" + +#define UNDOCUMENTED_IMAGEFORMAT_TIP N_("(undocumented image format)") + +/* -------------------------------------------------------------------- */ +/** \name Image Format Type Registry + * \{ */ + +static GHash *global_imageformat_hash = NULL; +// TODO: no idea what this is for +/** Counter for operator-properties that should not be tagged with #OP_PROP_TAG_ADVANCED. */ +static int ot_prop_basic_count = -1; + +struct imfImageFormatType *WM_imageformattype_find(const char *idname, bool quiet) +{ + if (idname[0]) { + imfImageFormatType *ift; + + /* needed to support python style names without the _OT_ syntax */ + char idname_bl[OP_MAX_TYPENAME]; + WM_operator_bl_idname(idname_bl, idname); // TODO: remove this or reimplement?? not sure if needed yet. + + ift = BLI_ghash_lookup(global_imageformat_hash, idname_bl); + if (ift) { + return ift; + } + + if (!quiet) { + CLOG_INFO( + WM_LOG_OPERATORS, 0, "search for unknown image format '%s', '%s'\n", idname_bl, idname); + } + } + else { + if (!quiet) { + CLOG_INFO(WM_LOG_OPERATORS, 0, "search for empty image format"); + } + } + + return NULL; +} + +void wm_imageformattype_iter(GHashIterator *ghi) +{ + BLI_ghashIterator_init(ghi, global_imageformat_hash); +} + +/* -------------------------------------------------------------------- */ +/** \name Image Format Type Append + * \{ */ + +static imfImageFormatType *wm_imageformattype_append__begin(void) +{ + imfImageFormatType *ift = MEM_callocN(sizeof(imfImageFormatType), "imageformattype"); + + ift->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_ImageFormat); // TODO: wrong type?? use other function + /* Set the default i18n context now, so that opfunc can redefine it if needed! */ + RNA_def_struct_translation_context(ift->srna, BLT_I18CONTEXT_IMAGEFORMAT_DEFAULT); + ift->translation_context = BLT_I18CONTEXT_IMAGEFORMAT_DEFAULT; + + return ift; +} + +static void wm_imageformattype_append__end(imfImageFormatType *ift) +{ + if (ift->name == NULL) { + CLOG_ERROR(WM_LOG_OPERATORS, "ImageFormat '%s' has no name property", ift->idname); // TODO: change error clgref + } + BLI_assert((ift->description == NULL) || (ift->description[0])); + + /* XXX All ops should have a description but for now allow them not to. */ + RNA_def_struct_ui_text( + ift->srna, ift->name, ift->description ? ift->description : UNDOCUMENTED_IMAGEFORMAT_TIP); + RNA_def_struct_identifier(&BLENDER_RNA, ift->srna, ift->idname); + + BLI_ghash_insert(global_imageformat_hash, (void *)ift->idname, ift); +} + +/* All ops in 1 list (for time being... needs evaluation later). */ + +void wm_imageformattype_append(void (*opfunc)(imfImageFormatType *)) +{ + imfImageFormatType *ift = wm_imageformattype_append__begin(); + opfunc(ift); + wm_imageformattype_append__end(ift); +} + +void wm_imageformattype_append_ptr(void (*opfunc)(imfImageFormatType *, void *), void *userdata) +{ + imfImageFormatType *ift = wm_imageformattype_append__begin(); + opfunc(ift, userdata); + wm_imageformattype_append__end(ift); +} + +/** \} */ + +void wm_imageformattype_remove_ptr(imfImageFormatType *ift) +{ + BLI_assert(ift == WM_imageformattype_find(otiftidname, false)); + + RNA_struct_free(&BLENDER_RNA, ift->srna); + + BLI_ghash_remove(global_imageformat_hash, ift->idname, NULL, NULL); + + MEM_freeN(ift); +} + +bool wm_imageformattype_remove(const char *idname) +{ + imfImageFormatType *ift = WM_imageformattype_find(idname, 0); + + if (ift == NULL) { + return false; + } + + wm_imageformattype_remove_ptr(ift); + + return true; +} + +void wm_imageformattype_init(void) +{ + /* reserve size is set based on blender default setup */ + global_imageformat_hash = BLI_ghash_str_new_ex("wm_imageformattype_init gh", 64); +} + +static void imageformattype_ghash_free_cb(imfImageFormatType *ift) +{ + if (ift->rna_ext.srna) { + /* python image format, allocs own string */ + // TODO: delete more of these things that alloc their own strings + MEM_freeN((void *)ift->idname); + } + + MEM_freeN(ift); +} + +void wm_imageformattype_free(void) +{ + BLI_ghash_free(global_imageformat_hash, NULL, (GHashValFreeFP)imageformattype_ghash_free_cb); + global_imageformat_hash = NULL; +} + +// TODO: probably remove +void wm_imageformattype_idname_visit_for_search(const bContext *UNUSED(C), + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + const char *UNUSED(edit_text), + StringPropertySearchVisitFunc visit_fn, + void *visit_user_data) +{ + GHashIterator gh_iter; + GHASH_ITER (gh_iter, global_imageformat_hash) { + imfImageFormatType *ift = BLI_ghashIterator_getValue(&gh_iter); + + char idname_py[OP_MAX_TYPENAME]; + WM_operator_py_idname(idname_py, ift->idname); + + StringPropertySearchVisitParams visit_params = {NULL}; + visit_params.text = idname_py; + visit_params.info = ift->name; + visit_fn(visit_user_data, &visit_params); + } +} + +/** \} */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index f77aad24719..d56b14a4d4b 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -222,6 +222,8 @@ void WM_init(bContext *C, int argc, const char **argv) wm_operatortype_init(); wm_operatortypes_register(); + wm_imageformattype_init(); + WM_paneltype_init(); /* Lookup table only. */ WM_menutype_init(); WM_uilisttype_init(); -- cgit v1.2.3