diff options
20 files changed, 704 insertions, 24 deletions
diff --git a/source/blender/blenkernel/BKE_asset_engine.h b/source/blender/blenkernel/BKE_asset_engine.h new file mode 100644 index 00000000000..6ad9de6918d --- /dev/null +++ b/source/blender/blenkernel/BKE_asset_engine.h @@ -0,0 +1,65 @@ +/* + * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BKE_asset_engine.h + * \ingroup bke + */ + +#ifndef __BKE_ASSET_ENGINE_H__ +#define __BKE_ASSET_ENGINE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct AssetUUID; +struct Main; + +#define ASSETUUID_SUB_EQUAL(_uuida, _uuidb, _member) \ + (memcmp((_uuida)->_member, (_uuidb)->_member, sizeof((_uuida)->_member)) == 0) + +#define ASSETUUID_EQUAL(_uuida, _uuidb) \ + (ASSETUUID_SUB_EQUAL(_uuida, _uuidb, uuid_repository) && \ + ASSETUUID_SUB_EQUAL(_uuida, _uuidb, uuid_asset) && \ + ASSETUUID_SUB_EQUAL(_uuida, _uuidb, uuid_variant) && \ + ASSETUUID_SUB_EQUAL(_uuida, _uuidb, uuid_revision) && \ + ASSETUUID_SUB_EQUAL(_uuida, _uuidb, uuid_view)) + +/* Various helpers */ +void BKE_asset_uuid_runtime_reset(struct AssetUUID *uuid); + +unsigned int BKE_asset_uuid_hash(const void *key); +bool BKE_asset_uuid_cmp(const void *a, const void *b); +void BKE_asset_uuid_print(const struct AssetUUID *uuid); + +void BKE_asset_main_search(struct Main *bmain, struct AssetUUID *uuid); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_ASSET_ENGINE_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b9054d29752..92e0904c568 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -76,6 +76,7 @@ set(SRC intern/armature.c intern/armature_deform.c intern/armature_update.c + intern/asset_engine.c intern/autoexec.c intern/blender.c intern/blender_copybuffer.c @@ -266,6 +267,7 @@ set(SRC BKE_animsys.h BKE_appdir.h BKE_armature.h + BKE_asset_engine.h BKE_autoexec.h BKE_blender.h BKE_blender_copybuffer.h diff --git a/source/blender/blenkernel/intern/asset_engine.c b/source/blender/blenkernel/intern/asset_engine.c new file mode 100644 index 00000000000..b309db81f88 --- /dev/null +++ b/source/blender/blenkernel/intern/asset_engine.c @@ -0,0 +1,127 @@ +/* + * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/asset_engine.c + * \ingroup bke + */ + +#include <string.h> + +#include "BLI_utildefines.h" +#include "BLI_hash_mm2a.h" +#include "BLI_listbase.h" + +#include "BKE_asset_engine.h" +#include "BKE_main.h" + +#include "IMB_imbuf.h" + +#include "DNA_ID.h" + +#include "MEM_guardedalloc.h" + +#ifdef WITH_PYTHON +# include "BPY_extern.h" +#endif + +/* Various helpers */ +void BKE_asset_uuid_runtime_reset(AssetUUID *uuid) { + uuid->preview_image_buffer = NULL; + uuid->preview_width = uuid->preview_height = 0; + uuid->tag = 0; + uuid->id = NULL; +} + +unsigned int BKE_asset_uuid_hash(const void *key) +{ + BLI_HashMurmur2A mm2a; + const AssetUUID *uuid = key; + BLI_hash_mm2a_init(&mm2a, 0); + BLI_hash_mm2a_add(&mm2a, (const uchar *)uuid->uuid_repository, sizeof(uuid->uuid_repository)); + BLI_hash_mm2a_add(&mm2a, (const uchar *)uuid->uuid_asset, sizeof(uuid->uuid_asset)); + BLI_hash_mm2a_add(&mm2a, (const uchar *)uuid->uuid_variant, sizeof(uuid->uuid_variant)); + BLI_hash_mm2a_add(&mm2a, (const uchar *)uuid->uuid_revision, sizeof(uuid->uuid_revision)); + BLI_hash_mm2a_add(&mm2a, (const uchar *)uuid->uuid_view, sizeof(uuid->uuid_view)); + return BLI_hash_mm2a_end(&mm2a); +} + +bool BKE_asset_uuid_cmp(const void *a, const void *b) +{ + const AssetUUID *uuid1 = a; + const AssetUUID *uuid2 = b; + return !ASSETUUID_EQUAL(uuid1, uuid2); /* Expects false when compared equal. */ +} + +void BKE_asset_uuid_print(const AssetUUID *uuid) +{ + /* TODO print nicer (as 128bit hexadecimal?). */ + printf("[%.10d,%.10d,%.10d,%.10d]" + "[%.10d,%.10d,%.10d,%.10d]" + "[%.10d,%.10d,%.10d,%.10d]" + "[%.10d,%.10d,%.10d,%.10d]" + "[%.10d,%.10d,%.10d,%.10d]\n", + uuid->uuid_repository[0], + uuid->uuid_repository[1], + uuid->uuid_repository[2], + uuid->uuid_repository[3], + uuid->uuid_asset[0], + uuid->uuid_asset[1], + uuid->uuid_asset[2], + uuid->uuid_asset[3], + uuid->uuid_variant[0], + uuid->uuid_variant[1], + uuid->uuid_variant[2], + uuid->uuid_variant[3], + uuid->uuid_revision[0], + uuid->uuid_revision[1], + uuid->uuid_revision[2], + uuid->uuid_revision[3], + uuid->uuid_view[0], + uuid->uuid_view[1], + uuid->uuid_view[2], + uuid->uuid_view[3]); +} + +/** Search the whole Main for a given asset uuid. + * + * \note if found, ID is put into uuid->id pointer. */ +void BKE_asset_main_search(Main *bmain, AssetUUID *uuid) +{ + uuid->id = NULL; + + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (id->uuid == NULL) { + continue; + } + if (ASSETUUID_EQUAL(id->uuid, uuid)) { + uuid->id = id; + return; + } + } + FOREACH_MAIN_ID_END; +} diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index b4f2caac861..9d7671322ea 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -63,6 +63,8 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user) } BKE_animdata_free(id, do_id_user); + + MEM_SAFE_FREE(id->uuid); } void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag)) diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index d4246056efe..777a4fb9dfa 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -29,6 +29,7 @@ #include "BKE_armature.h" #include "BKE_collection.h" #include "BKE_curve.h" +#include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e4822c4cb7f..9a5f6ac6bbc 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -108,11 +108,14 @@ #include "BLI_mempool.h" #include "BLI_threads.h" +#include "RNA_types.h" + #include "BLT_translation.h" #include "BKE_action.h" #include "BKE_anim_data.h" #include "BKE_armature.h" +#include "BKE_asset_engine.h" #include "BKE_brush.h" #include "BKE_collection.h" #include "BKE_colortools.h" @@ -2876,6 +2879,12 @@ static void direct_link_id_common( BLI_listbase_clear((ListBase *)drawdata); } + if (id->uuid) { + BLO_read_data_address(reader, &id->uuid); + /* Make sure runtime fields are always zeroed out. */ + BKE_asset_uuid_runtime_reset(id->uuid); + } + /* Handle 'private IDs'. */ direct_link_id_embedded_id(reader, current_library, id, id_old); } @@ -9555,6 +9564,18 @@ static BHead *read_libblock(FileData *fd, } } + if (id->uuid) { + /* Read all data into fd->datamap. */ + bhead = read_data_into_datamap(fd, bhead, __func__); + + id->uuid = newdataadr(fd, id->uuid); + /* Make sure runtime fields are always zeroed out. */ + BKE_asset_uuid_runtime_reset(id->uuid); + + oldnewmap_clear(fd->datamap); + return bhead; + } + direct_link_id(fd, main, id_tag, id, id_old); return blo_bhead_next(fd, bhead); } @@ -12134,6 +12155,21 @@ static void read_library_linked_ids(FileData *basefd, * (known case: some directly linked shapekey from a missing lib...). */ /* BLI_assert(*realid != NULL); */ + if (*realid && id->uuid) { + /* it is important to keep the UUID we stored in that .blend file, not the (potentially + * different) one we get from the library, updating UUID should be handled by asset + * engine later - even though changing UUID is not recommended in any case. */ + if ((*realid)->uuid != NULL) { + MEM_SAFE_FREE((*realid)->uuid); + } + /* We can give ownership of that pointer to new ID. */ + (*realid)->uuid = id->uuid; + id->uuid = NULL; + } + else { + MEM_SAFE_FREE(id->uuid); + } + /* Now that we have a real ID, replace all pointers to placeholders in * fd->libmap with pointers to the real data-blocks. We do this for all * libraries since multiple might be referencing this ID. */ @@ -12148,6 +12184,8 @@ static void read_library_linked_ids(FileData *basefd, /* Clear GHash and free link placeholder IDs of the current type. */ BLI_ghash_clear(loaded_ids, NULL, NULL); + /* Note: this is currently just freeing ID struct itself, assuming there is no remaining + * allocated sub-data owned by this ID. */ BLI_freelistN(&pending_free_ids); } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 4e0325e72fa..d8576b4c6de 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -738,6 +738,9 @@ static void write_iddata(BlendWriter *writer, ID *id) if (id->properties && !ELEM(GS(id->name), ID_WM)) { IDP_WriteProperty(id->properties, writer); } + if (id->uuid) { + BLO_write_struct(writer, AssetUUID, id->uuid); + } if (id->override_library) { BLO_write_struct(writer, IDOverrideLibrary, id->override_library); @@ -3926,6 +3929,11 @@ static void write_libraries(WriteData *wd, Main *main) BLI_assert(0); } writestruct(wd, ID_LINK_PLACEHOLDER, ID, 1, id); + /* It is mandatory to write id's asset uuid reference for placeholders too, otherwise + * the whole asset info would be completely lost when reloading the linked data-block, + * especially in case it is not immediately found and needs to go through the whole + * 'asset engine update' process after main .blend read process is finished. */ + write_iddata(&writer, id); } } } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 6ea1d74112d..5eee97e3fee 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -3116,6 +3116,34 @@ static void outliner_draw_tree_element(bContext *C, (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, lib_icon, alpha_fac); offsx += UI_UNIT_X + 4 * ufac; } + else { + UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, + (float)*starty + 2 * ufac, + ICON_LIBRARY_DATA_DIRECT, + alpha_fac); + } + if (tselem->id->uuid) { + offsx += UI_UNIT_X; + UI_icon_draw_alpha((float)startx + offsx - 0.5f * ufac, + (float)*starty + 1.5f * ufac, + ICON_SOLO_ON, + alpha_fac); + if (tselem->id->uuid->tag & UUID_TAG_ENGINE_MISSING) { + UI_icon_draw_alpha( + (float)startx + offsx, (float)*starty + 2 * ufac, ICON_GHOST_ENABLED, alpha_fac); + } + else if (tselem->id->uuid->tag & UUID_TAG_ASSET_MISSING) { + /* Nothing special (underlying icon is already 'broken' one)... */ + } + else if (tselem->id->uuid->tag & UUID_TAG_ASSET_RELOAD) { + UI_icon_draw_alpha( + (float)startx + offsx, (float)*starty + 2 * ufac, ICON_FILE_REFRESH, alpha_fac); + } + else { + /* Nothing special (underlying icon is already 'OK' one)... */ + } + } + offsx += UI_UNIT_X + 4 * ufac; } GPU_blend(false); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index d04402f989c..51b919cd0dc 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -729,7 +729,9 @@ static void id_local_cb(bContext *C, if (ID_IS_LINKED(tselem->id) && (tselem->id->tag & LIB_TAG_EXTERN)) { Main *bmain = CTX_data_main(C); /* if the ID type has no special local function, - * just clear the lib */ + * just clear the lib. */ + /* XXX This is very, very, **very** suspicious - should not be handled that way at all. + * Probably best thing to do here is to simply not do anything. */ if (BKE_lib_id_make_local(bmain, tselem->id, false, 0) == false) { BKE_lib_id_clear_library_data(bmain, tselem->id); } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 60cedfe3c8a..660f0121699 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -233,6 +233,61 @@ typedef struct IDOverrideLibrary { IDOverrideLibraryRuntime *runtime; } IDOverrideLibrary; +/** + * About Unique identifier. + * + * Stored in a CustomProps once imported. + * Each engine is free to use it as it likes - it will be the only thing passed to it by blender to + * identify repository/asset/variant/version/view. + * Assumed to be 128bits (16 bytes) each, handled as four integers due to lack of real + * bytes proptype in RNA. + */ +#define ASSET_UUID_LENGTH 16 + +/* Used to communicate with asset engines outside of 'import' context. */ +typedef struct AssetUUID { + int uuid_repository[4]; + int uuid_asset[4]; + int uuid_variant[4]; + int uuid_revision[4]; + int uuid_view[4]; + short flag; + + /* Everything below this comment is runtime data. */ + short tag; + + /* Preview. */ + short preview_width; + short preview_height; + char *preview_image_buffer; /* RGBA 8bits. */ + + /* Used for load_post and other temporary storage of the ID itself in its AssetUUID. + * Usage and scope are similar to the `ID.newid` pointer. */ + struct ID *id; +} AssetUUID; + +/** + * uuid->flag (persitent, saved in .blend files). + */ +enum { + UUID_FLAG_LAST_REVISION = 1 << 0, /* This asset should always use latest available revision. */ +}; + +/** + * uuid->tag (runtime only). + */ +enum { + UUID_TAG_ENGINE_MISSING = + 1 << 0, /* The asset engine used for this asset is not known by Blender. */ + UUID_TAG_ASSET_MISSING = + 1 << 1, /* The asset engine was found but does not know about this asset (anymore). */ + + UUID_TAG_ASSET_RELOAD = + 1 << 8, /* Set by the asset engine to indicate that this asset has to be reloaded. */ + UUID_TAG_ASSET_NOPREVIEW = + 1 << 9, /* Set by the asset engine to indicate that this asset has no preview. */ +}; + /* watch it: Sequence has identical beginning. */ /** * ID is the first thing included in all serializable types. It @@ -285,6 +340,9 @@ typedef struct ID { /** Reference linked ID which this one overrides. */ IDOverrideLibrary *override_library; + AssetUUID *uuid; + void *pad_v; + /** * Only set for data-blocks which are coming from copy-on-write, points to * the original version of it. @@ -547,6 +605,8 @@ enum { /* RESET_NEVER Datablock is from a library, * and is only used (linked) indirectly through other libraries. */ LIB_TAG_INDIRECT = 1 << 1, + /* RESET_NEVER Datablock is (or is used by) an asset. */ + LIB_TAG_ASSET = 1 << 19, /* RESET_AFTER_USE Flag used internally in readfile.c, * to mark IDs needing to be expanded (only done once). */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 1cb42b333c7..83489477a8f 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -874,27 +874,6 @@ typedef enum eDirEntry_SelectFlag { FILE_SEL_EDITING = (1 << 4), } eDirEntry_SelectFlag; -/* ***** Related to file browser, but never saved in DNA, only here to help with RNA. ***** */ - -/** - * About Unique identifier. - * - * Stored in a CustomProps once imported. - * Each engine is free to use it as it likes - it will be the only thing passed to it by blender to - * identify asset/variant/version (concatenating the three into a single 48 bytes one). - * Assumed to be 128bits, handled as four integers due to lack of real bytes proptype in RNA :|. - */ -#define ASSET_UUID_LENGTH 16 - -/* Used to communicate with asset engines outside of 'import' context. */ -# -# -typedef struct AssetUUID { - int uuid_asset[4]; - int uuid_variant[4]; - int uuid_revision[4]; -} AssetUUID; - # # typedef struct AssetUUIDList { diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 53bb8899855..ce53454319a 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -67,6 +67,7 @@ extern StructRNA RNA_ArmatureGpencilModifier; extern StructRNA RNA_ArmatureModifier; extern StructRNA RNA_ArrayGpencilModifier; extern StructRNA RNA_ArrayModifier; +extern StructRNA RNA_AssetUUID; extern StructRNA RNA_BackgroundImage; extern StructRNA RNA_BevelModifier; extern StructRNA RNA_BezierSplinePoint; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 980e3eadd34..eaea895746e 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -30,6 +30,7 @@ set(DEFSRC rna_animation.c rna_animviz.c rna_armature.c + rna_asset.c rna_boid.c rna_brush.c rna_cachefile.c diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 59087df16dd..8d61b21759f 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -4258,6 +4258,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_animation.c", "rna_animation_api.c", RNA_def_animation}, {"rna_animviz.c", NULL, RNA_def_animviz}, {"rna_armature.c", "rna_armature_api.c", RNA_def_armature}, + {"rna_asset.c", NULL, RNA_def_asset}, {"rna_boid.c", NULL, RNA_def_boid}, {"rna_brush.c", NULL, RNA_def_brush}, {"rna_cachefile.c", NULL, RNA_def_cachefile}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 46001f27fef..bb67783622b 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -89,8 +89,10 @@ const EnumPropertyItem rna_enum_id_type_items[] = { # include "DNA_anim_types.h" +# include "BLI_hash_mm2a.h" # include "BLI_listbase.h" # include "BLI_math_base.h" +# include "PIL_time.h" # include "BKE_anim_data.h" # include "BKE_font.h" @@ -627,6 +629,24 @@ static void rna_ID_animation_data_free(ID *id, Main *bmain) DEG_relations_tag_update(bmain); } +static void rna_ID_asset_uuid_free(ID *id) +{ + MEM_SAFE_FREE(id->uuid); + id->tag &= ~LIB_TAG_ASSET; +} + +static void rna_ID_asset_uuid_create(ID *id) +{ + rna_ID_asset_uuid_free(id); + id->uuid = MEM_callocN(sizeof(*id->uuid), __func__); + /* Add some dummy init for the asset part of the uuid. */ + for (int i = 0; i < 4; i++) { + id->uuid->uuid_asset[i] = (int)BLI_hash_mm2( + id->name + i, sizeof(id->name) - i, (uint)PIL_check_seconds_timer_i()); + } + id->tag |= LIB_TAG_ASSET; +} + # ifdef WITH_PYTHON void **rna_ID_instance(PointerRNA *ptr) { @@ -1526,6 +1546,15 @@ static void rna_def_ID(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_pointer_funcs(prop, "rna_IDPreview_get", NULL, NULL, NULL); + prop = RNA_def_pointer( + srna, + "asset_uuid", + "AssetUUID", + "Asset UUID", + "Unique identifier of the asset represented by that ID (NULL if not an asset)"); + RNA_def_property_pointer_sdna(prop, NULL, "uuid"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + /* functions */ func = RNA_def_function(srna, "evaluated_get", "rna_ID_evaluated_get"); RNA_def_function_ui_description( @@ -1619,6 +1648,12 @@ static void rna_def_ID(BlenderRNA *brna) "e.g. when calling :class:`bpy.types.Scene.update`"); RNA_def_enum_flag(func, "refresh", update_flag_items, 0, "", "Type of updates to perform"); + func = RNA_def_function(srna, "asset_uuid_create", "rna_ID_asset_uuid_create"); + RNA_def_function_ui_description(func, "Create asset uuid data to this ID"); + + func = RNA_def_function(srna, "asset_uuid_clear", "rna_ID_asset_uuid_free"); + RNA_def_function_ui_description(func, "Clear asset uuid from this ID"); + # ifdef WITH_PYTHON RNA_def_struct_register_funcs(srna, NULL, NULL, "rna_ID_instance"); # endif diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c new file mode 100644 index 00000000000..9edb623914b --- /dev/null +++ b/source/blender/makesrna/intern/rna_asset.c @@ -0,0 +1,214 @@ +/* + * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation (2015) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/makesrna/intern/rna_asset.c + * \ingroup RNA + */ + +#include "BLI_utildefines.h" + +#include "DNA_ID.h" + +#include "RNA_define.h" + +#include "rna_internal.h" + +#include "BKE_asset_engine.h" + +#ifdef RNA_RUNTIME + +# include "MEM_guardedalloc.h" + +# include "RNA_access.h" + +/* AssetUUID */ + +static void rna_AssetUUID_preview_size_get(PointerRNA *ptr, int *values) +{ + AssetUUID *uuid = ptr->data; + + values[0] = uuid->preview_width; + values[1] = uuid->preview_height; +} + +static void rna_AssetUUID_preview_size_set(PointerRNA *ptr, const int *values) +{ + AssetUUID *uuid = ptr->data; + + uuid->preview_width = values[0]; + uuid->preview_height = values[1]; + + MEM_SAFE_FREE(uuid->preview_image_buffer); +} + +static int rna_AssetUUID_preview_pixels_get_length(PointerRNA *ptr, + int length[RNA_MAX_ARRAY_DIMENSION]) +{ + AssetUUID *uuid = ptr->data; + + length[0] = (uuid->preview_image_buffer == NULL) ? 0 : uuid->preview_width * uuid->preview_height; + + return length[0]; +} + +static void rna_AssetUUID_preview_pixels_get(PointerRNA *ptr, int *values) +{ + AssetUUID *uuid = ptr->data; + + memcpy(values, uuid->preview_image_buffer, uuid->preview_width * uuid->preview_height * sizeof(unsigned int)); +} + +static void rna_AssetUUID_preview_pixels_set(PointerRNA *ptr, const int *values) +{ + AssetUUID *uuid = ptr->data; + + if (!uuid->preview_image_buffer) { + uuid->preview_image_buffer = MEM_mallocN(sizeof(*uuid->preview_image_buffer) * 4 * uuid->preview_width * uuid->preview_height, __func__); + } + + memcpy(uuid->preview_image_buffer, values, uuid->preview_width * uuid->preview_height * sizeof(unsigned int)); +} + +#else /* RNA_RUNTIME */ + +/* Much lighter version of asset/variant/revision identifier. */ +static void rna_def_asset_uuid(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + int null_uuid[4] = {0}; + + srna = RNA_def_struct(brna, "AssetUUID", NULL); + RNA_def_struct_sdna(srna, "AssetUUID"); + RNA_def_struct_ui_text( + srna, "Asset UUID", "A unique identifier of an asset (asset engine dependent!)"); + + RNA_def_int_vector(srna, + "uuid_repository", + 4, + null_uuid, + INT_MIN, + INT_MAX, + "Repository UUID", + "Unique identifier of the repository of this asset", + INT_MIN, + INT_MAX); + + RNA_def_int_vector(srna, + "uuid_asset", + 4, + null_uuid, + INT_MIN, + INT_MAX, + "Asset UUID", + "Unique identifier of this asset", + INT_MIN, + INT_MAX); + + RNA_def_int_vector(srna, + "uuid_variant", + 4, + null_uuid, + INT_MIN, + INT_MAX, + "Variant UUID", + "Unique identifier of this asset's variant", + INT_MIN, + INT_MAX); + + RNA_def_int_vector(srna, + "uuid_revision", + 4, + null_uuid, + INT_MIN, + INT_MAX, + "Revision UUID", + "Unique identifier of this asset's revision", + INT_MIN, + INT_MAX); + + RNA_def_int_vector(srna, + "uuid_view", + 4, + null_uuid, + INT_MIN, + INT_MAX, + "View UUID", + "Unique identifier of this asset's view", + INT_MIN, + INT_MAX); + + prop = RNA_def_boolean(srna, + "is_unknown_engine", + false, + "Unknown Asset Engine", + "This AssetUUID is referencing an unknown asset engine"); + RNA_def_property_boolean_sdna(prop, NULL, "tag", UUID_TAG_ENGINE_MISSING); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_boolean(srna, + "is_asset_missing", + false, + "Missing Asset", + "This AssetUUID is no more known by its asset engine"); + RNA_def_property_boolean_sdna(prop, NULL, "tag", UUID_TAG_ASSET_MISSING); + + prop = RNA_def_boolean(srna, + "use_asset_reload", + false, + "Reload Asset", + "The data matching this AssetUUID should be reloaded"); + RNA_def_property_boolean_sdna(prop, NULL, "tag", UUID_TAG_ASSET_RELOAD); + + prop = RNA_def_boolean( + srna, "has_asset_preview", false, "Valid Preview", "This asset has a valid preview"); + RNA_def_property_boolean_negative_sdna(prop, NULL, "tag", UUID_TAG_ASSET_NOPREVIEW); + + prop = RNA_def_int_vector( + srna, "preview_size", 2, NULL, 0, 0, "Preview Size", "Width and height in pixels", 0, 0); + RNA_def_property_subtype(prop, PROP_PIXEL); + RNA_def_property_int_funcs( + prop, "rna_AssetUUID_preview_size_get", "rna_AssetUUID_preview_size_set", NULL); + + prop = RNA_def_property(srna, "preview_pixels", PROP_INT, PROP_NONE); + RNA_def_property_flag(prop, PROP_DYNAMIC); + RNA_def_property_multi_array(prop, 1, NULL); + RNA_def_property_ui_text( + prop, "Preview Pixels", "Preview pixels, as bytes (always RGBA 32bits)"); + RNA_def_property_dynamic_array_funcs(prop, "rna_AssetUUID_preview_pixels_get_length"); + RNA_def_property_int_funcs( + prop, "rna_AssetUUID_preview_pixels_get", "rna_AssetUUID_preview_pixels_set", NULL); + + prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ID"); + RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP); + RNA_def_property_ui_text( + prop, "Loaded ID", "Pointer to linked/appended data-block, for load_post callback only"); +} + +void RNA_def_asset(BlenderRNA *brna) +{ + rna_def_asset_uuid(brna); +} + +#endif /* RNA_RUNTIME */ diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 0783addd78b..71971cf3cca 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -150,6 +150,7 @@ void RNA_def_action(struct BlenderRNA *brna); void RNA_def_animation(struct BlenderRNA *brna); void RNA_def_animviz(struct BlenderRNA *brna); void RNA_def_armature(struct BlenderRNA *brna); +void RNA_def_asset(struct BlenderRNA *brna); void RNA_def_boid(struct BlenderRNA *brna); void RNA_def_brush(struct BlenderRNA *brna); void RNA_def_cachefile(struct BlenderRNA *brna); diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c index b607f1635e6..bd194a6293d 100644 --- a/source/blender/python/intern/bpy_rna_id_collection.c +++ b/source/blender/python/intern/bpy_rna_id_collection.c @@ -28,6 +28,11 @@ #include "BLI_bitmap.h" #include "BLI_utildefines.h" +#include "RNA_access.h" +#include "RNA_enum_types.h" +#include "RNA_types.h" + +#include "BKE_asset_engine.h" #include "BKE_global.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" @@ -348,6 +353,107 @@ error: return ret; } +PyDoc_STRVAR( + bpy_asset_uuid_search_doc, + ".. method:: asset_uuid_search([uuid_repository=(0,0,0,0)], [uuid_asset=(0,0,0,0)], " + "[uuid_variant=(0,0,0,0)], [uuid_revision=(0,0,0,0)], [uuid_view=(0,0,0,0)])\n" + "\n" + " Search for a given set of uuid elements (defining a single asset) in current list of " + "IDs.\n" + "\n" + " :arg uuid_repository: The uuid of the repository, as an iterable of four integers.\n" + " :type uuid_repository: sequence\n" + " :arg uuid_asset: The uuid of the asset, as an iterable of four integers.\n" + " :type uuid_asset: sequence\n" + " :arg uuid_variant: The uuid of the variant, as an iterable of four integers.\n" + " :type uuid_variant: sequence\n" + " :arg uuid_revision: The uuid of the revision, as an iterable of four integers.\n" + " :type uuid_revision: sequence\n" + " :arg uuid_view: The uuid of the view, as an iterable of four integers.\n" + " :type uuid_view: sequence\n" + " :return: Found ID or None.\n" + " :rtype: ID\n"); +static PyObject *bpy_asset_uuid_search(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) +{ +#if 0 /* TODO: Find a proper way of getting bmain from `self ` in this case. */ + BPy_StructRNA *pyrna = (BPy_StructRNA *)self; + Main *bmain = pyrna->ptr.data; +#else + Main *bmain = G_MAIN; /* XXX Ugly, but should work! */ +#endif + + PyObject *uuid_tupples[5] = {NULL, NULL, NULL, NULL, NULL}; + + PyObject *ret = NULL; + + static const char *_keywords[] = { + "uuid_repository", "uuid_asset", "uuid_variant", "uuid_revision", "uuid_view", NULL}; + static _PyArg_Parser _parser = {"|OOOOO:asset_uuid_search", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kwds, + &_parser, + &uuid_tupples[0], + &uuid_tupples[1], + &uuid_tupples[2], + &uuid_tupples[3], + &uuid_tupples[4])) { + return ret; + } + + int uuid_int_array[5][4] = {0}; + + for (int i = 0; i < 5; i++) { + if (uuid_tupples[i] == NULL) { + continue; + } + + PyObject *uuid_items_fast = PySequence_Fast(uuid_tupples[i], __func__); + if (uuid_items_fast == NULL) { + goto error; + } + + PyObject **uuid_items = PySequence_Fast_ITEMS(uuid_items_fast); + Py_ssize_t uuid_items_len = PySequence_Fast_GET_SIZE(uuid_items_fast); + + if (uuid_items_len != 4) { + PyErr_Format(PyExc_TypeError, + "Expected an uuid item to be an iterable of four integers, not %d %.200s", + uuid_items_len, + Py_TYPE(*uuid_items)->tp_name); + Py_DECREF(uuid_items_fast); + goto error; + } + + int *it = uuid_int_array[i]; + for (; uuid_items_len; uuid_items++, it++, uuid_items_len--) { + *it = PyLong_AsLong(*uuid_items); + } + Py_DECREF(uuid_items_fast); + } + + AssetUUID asset_uuid = { + .uuid_repository = {UNPACK4(uuid_int_array[0])}, + .uuid_asset = {UNPACK4(uuid_int_array[1])}, + .uuid_variant = {UNPACK4(uuid_int_array[2])}, + .uuid_revision = {UNPACK4(uuid_int_array[3])}, + .uuid_view = {UNPACK4(uuid_int_array[4])}, + }; + + BKE_asset_main_search(bmain, &asset_uuid); + + if (asset_uuid.id != NULL) { + ret = pyrna_id_CreatePyObject(asset_uuid.id); + } + + else { + Py_INCREF(Py_None); + ret = Py_None; + } + +error: + return ret; +} + PyDoc_STRVAR(bpy_orphans_purge_doc, ".. method:: orphans_purge()\n" "\n" @@ -403,3 +509,9 @@ PyMethodDef BPY_rna_id_collection_orphans_purge_method_def = { METH_STATIC | METH_VARARGS | METH_KEYWORDS, bpy_orphans_purge_doc, }; +PyMethodDef BPY_rna_id_collection_asset_uuid_search_method_def = { + "asset_uuid_search", + (PyCFunction)bpy_asset_uuid_search, + METH_STATIC | METH_VARARGS | METH_KEYWORDS, + bpy_asset_uuid_search_doc, +}; diff --git a/source/blender/python/intern/bpy_rna_id_collection.h b/source/blender/python/intern/bpy_rna_id_collection.h index ee8f4c666a8..9d8bd67b211 100644 --- a/source/blender/python/intern/bpy_rna_id_collection.h +++ b/source/blender/python/intern/bpy_rna_id_collection.h @@ -24,5 +24,6 @@ extern PyMethodDef BPY_rna_id_collection_user_map_method_def; extern PyMethodDef BPY_rna_id_collection_batch_remove_method_def; extern PyMethodDef BPY_rna_id_collection_orphans_purge_method_def; +extern PyMethodDef BPY_rna_id_collection_asset_uuid_search_method_def; #endif /* __BPY_RNA_ID_COLLECTION_H__ */ diff --git a/source/blender/python/intern/bpy_rna_types_capi.c b/source/blender/python/intern/bpy_rna_types_capi.c index 5a2ba4a5cdb..477f1e98d7b 100644 --- a/source/blender/python/intern/bpy_rna_types_capi.c +++ b/source/blender/python/intern/bpy_rna_types_capi.c @@ -55,6 +55,7 @@ static struct PyMethodDef pyrna_blenddata_methods[] = { {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_user_map_method_def */ {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_batch_remove_method_def */ {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_orphans_purge_method_def */ + {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_asset_uuid_search_method_def */ {NULL, NULL, 0, NULL}, }; @@ -195,8 +196,9 @@ void BPY_rna_types_extend_capi(void) ARRAY_SET_ITEMS(pyrna_blenddata_methods, BPY_rna_id_collection_user_map_method_def, BPY_rna_id_collection_batch_remove_method_def, - BPY_rna_id_collection_orphans_purge_method_def); - BLI_assert(ARRAY_SIZE(pyrna_blenddata_methods) == 4); + BPY_rna_id_collection_orphans_purge_method_def, + BPY_rna_id_collection_asset_uuid_search_method_def); + BLI_assert(ARRAY_SIZE(pyrna_blenddata_methods) == 5); pyrna_struct_type_extend_capi(&RNA_BlendData, pyrna_blenddata_methods, NULL); /* BlendDataLibraries */ |