[Bf-blender-cvs] [222fd1abf09] master: Asset Browser: Disable metadata editing for external asset libraries

Julian Eisel noreply at git.blender.org
Thu Sep 23 14:46:23 CEST 2021


Commit: 222fd1abf09ae65b7082f58bf2ac43422c77162c
Author: Julian Eisel
Date:   Thu Sep 23 14:43:21 2021 +0200
Branches: master
https://developer.blender.org/rB222fd1abf09ae65b7082f58bf2ac43422c77162c

Asset Browser: Disable metadata editing for external asset libraries

Buttons to edit asset metadata are now disabled for assets from an
external library (i.e. assets not stored in the current .blend file).
Their tooltips explain why they are disabled.

Had to do some RNA trickery to disable the metadata properties at RNA
level, not at UI script level.
The basic idea is:
* Local data-block assets set the data-block as owning ID for the asset
  metadata RNA pointer now.
* That way we can use the owner ID to see where the metadata belongs to
  and decide if it's editable that way.
* Additionaly, some Python operators needed better polling so they show
  as grayed out, and don't just fail.

One important thing: Custom properties of the metadata can still be
edited. The edits won't be saved however. Would be nice to disable that,
but it's currently not supported on BPY/IDProperty/RNA level.

Addresses T82943.

Differential Revision: https://developer.blender.org/D12127

===================================================================

M	release/scripts/startup/bl_operators/assets.py
M	source/blender/makesrna/intern/rna_asset.c
M	source/blender/makesrna/intern/rna_internal.h
M	source/blender/makesrna/intern/rna_space.c

===================================================================

diff --git a/release/scripts/startup/bl_operators/assets.py b/release/scripts/startup/bl_operators/assets.py
index b241e537c38..de46e5c85fb 100644
--- a/release/scripts/startup/bl_operators/assets.py
+++ b/release/scripts/startup/bl_operators/assets.py
@@ -27,17 +27,28 @@ from bpy_extras.asset_utils import (
 )
 
 
-class ASSET_OT_tag_add(Operator):
+class AssetBrowserMetadataOperator:
+    @classmethod
+    def poll(cls, context):
+        if not SpaceAssetInfo.is_asset_browser_poll(context) or not context.asset_file_handle:
+            return False
+
+        if not context.asset_file_handle.local_id:
+            Operator.poll_message_set(
+                "Asset metadata from external asset libraries can't be "
+                "edited, only assets stored in the current file can"
+            )
+            return False
+        return True
+
+
+class ASSET_OT_tag_add(AssetBrowserMetadataOperator, Operator):
     """Add a new keyword tag to the active asset"""
 
     bl_idname = "asset.tag_add"
     bl_label = "Add Asset Tag"
     bl_options = {'REGISTER', 'UNDO'}
 
-    @classmethod
-    def poll(cls, context):
-        return SpaceAssetInfo.is_asset_browser_poll(context) and SpaceAssetInfo.get_active_asset(context)
-
     def execute(self, context):
         active_asset = SpaceAssetInfo.get_active_asset(context)
         active_asset.tags.new("Unnamed Tag")
@@ -45,7 +56,7 @@ class ASSET_OT_tag_add(Operator):
         return {'FINISHED'}
 
 
-class ASSET_OT_tag_remove(Operator):
+class ASSET_OT_tag_remove(AssetBrowserMetadataOperator, Operator):
     """Remove an existing keyword tag from the active asset"""
 
     bl_idname = "asset.tag_remove"
@@ -54,21 +65,20 @@ class ASSET_OT_tag_remove(Operator):
 
     @classmethod
     def poll(cls, context):
-        if not SpaceAssetInfo.is_asset_browser_poll(context):
+        if not super().poll(context):
             return False
 
-        active_asset = SpaceAssetInfo.get_active_asset(context)
-        if not active_asset:
-            return False
-
-        return active_asset.active_tag in range(len(active_asset.tags))
+        active_asset_file = context.asset_file_handle
+        asset_metadata = active_asset_file.asset_data
+        return asset_metadata.active_tag in range(len(asset_metadata.tags))
 
     def execute(self, context):
-        active_asset = SpaceAssetInfo.get_active_asset(context)
-        tag = active_asset.tags[active_asset.active_tag]
+        active_asset_file = context.asset_file_handle
+        asset_metadata = active_asset_file.asset_data
+        tag = asset_metadata.tags[asset_metadata.active_tag]
 
-        active_asset.tags.remove(tag)
-        active_asset.active_tag -= 1
+        asset_metadata.tags.remove(tag)
+        asset_metadata.active_tag -= 1
 
         return {'FINISHED'}
 
diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c
index 1e583f4ca52..dcef88d2e79 100644
--- a/source/blender/makesrna/intern/rna_asset.c
+++ b/source/blender/makesrna/intern/rna_asset.c
@@ -40,11 +40,54 @@
 
 #  include "RNA_access.h"
 
-static AssetTag *rna_AssetMetaData_tag_new(AssetMetaData *asset_data,
-                                           ReportList *reports,
-                                           const char *name,
-                                           bool skip_if_exists)
+static bool rna_AssetMetaData_editable_from_owner_id(const ID *owner_id,
+                                                     const AssetMetaData *asset_data,
+                                                     const char **r_info)
 {
+  if (owner_id && asset_data && (owner_id->asset_data == asset_data)) {
+    return true;
+  }
+
+  if (r_info) {
+    *r_info =
+        "Asset metadata from external asset libraries can't be edited, only assets stored in the "
+        "current file can";
+  }
+  return false;
+}
+
+int rna_AssetMetaData_editable(PointerRNA *ptr, const char **r_info)
+{
+  AssetMetaData *asset_data = ptr->data;
+
+  return rna_AssetMetaData_editable_from_owner_id(ptr->owner_id, asset_data, r_info) ?
+             PROP_EDITABLE :
+             0;
+}
+
+static int rna_AssetTag_editable(PointerRNA *ptr, const char **r_info)
+{
+  AssetTag *asset_tag = ptr->data;
+  ID *owner_id = ptr->owner_id;
+  if (owner_id && owner_id->asset_data) {
+    BLI_assert_msg(BLI_findindex(&owner_id->asset_data->tags, asset_tag) != -1,
+                   "The owner of the asset tag pointer is not the asset ID containing the tag");
+  }
+
+  return rna_AssetMetaData_editable_from_owner_id(ptr->owner_id, owner_id->asset_data, r_info) ?
+             PROP_EDITABLE :
+             0;
+}
+
+static AssetTag *rna_AssetMetaData_tag_new(
+    ID *id, AssetMetaData *asset_data, ReportList *reports, const char *name, bool skip_if_exists)
+{
+  const char *disabled_info = NULL;
+  if (!rna_AssetMetaData_editable_from_owner_id(id, asset_data, &disabled_info)) {
+    BKE_report(reports, RPT_WARNING, disabled_info);
+    return NULL;
+  }
+
   AssetTag *tag = NULL;
 
   if (skip_if_exists) {
@@ -64,10 +107,17 @@ static AssetTag *rna_AssetMetaData_tag_new(AssetMetaData *asset_data,
   return tag;
 }
 
-static void rna_AssetMetaData_tag_remove(AssetMetaData *asset_data,
+static void rna_AssetMetaData_tag_remove(ID *id,
+                                         AssetMetaData *asset_data,
                                          ReportList *reports,
                                          PointerRNA *tag_ptr)
 {
+  const char *disabled_info = NULL;
+  if (!rna_AssetMetaData_editable_from_owner_id(id, asset_data, &disabled_info)) {
+    BKE_report(reports, RPT_WARNING, disabled_info);
+    return;
+  }
+
   AssetTag *tag = tag_ptr->data;
   if (BLI_findindex(&asset_data->tags, tag) == -1) {
     BKE_reportf(reports, RPT_ERROR, "Tag '%s' not found in given asset", tag->name);
@@ -185,6 +235,7 @@ static void rna_def_asset_tag(BlenderRNA *brna)
   RNA_def_struct_ui_text(srna, "Asset Tag", "User defined tag (name token)");
 
   prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+  RNA_def_property_editable_func(prop, "rna_AssetTag_editable");
   RNA_def_property_string_maxlength(prop, MAX_NAME);
   RNA_def_property_ui_text(prop, "Name", "The identifier that makes up this tag");
   RNA_def_struct_name_property(srna, prop);
@@ -205,7 +256,7 @@ static void rna_def_asset_tags_api(BlenderRNA *brna, PropertyRNA *cprop)
   /* Tag collection */
   func = RNA_def_function(srna, "new", "rna_AssetMetaData_tag_new");
   RNA_def_function_ui_description(func, "Add a new tag to this asset");
-  RNA_def_function_flag(func, FUNC_USE_REPORTS);
+  RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
   parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", "");
   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
   parm = RNA_def_boolean(func,
@@ -219,7 +270,7 @@ static void rna_def_asset_tags_api(BlenderRNA *brna, PropertyRNA *cprop)
 
   func = RNA_def_function(srna, "remove", "rna_AssetMetaData_tag_remove");
   RNA_def_function_ui_description(func, "Remove an existing tag from this asset");
-  RNA_def_function_flag(func, FUNC_USE_REPORTS);
+  RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
   /* tag to remove */
   parm = RNA_def_pointer(func, "tag", "AssetTag", "", "Removed tag");
   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
@@ -239,6 +290,7 @@ static void rna_def_asset_data(BlenderRNA *brna)
   RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); /* Mandatory! */
 
   prop = RNA_def_property(srna, "description", PROP_STRING, PROP_NONE);
+  RNA_def_property_editable_func(prop, "rna_AssetMetaData_editable");
   RNA_def_property_string_funcs(prop,
                                 "rna_AssetMetaData_description_get",
                                 "rna_AssetMetaData_description_length",
@@ -248,7 +300,7 @@ static void rna_def_asset_data(BlenderRNA *brna)
 
   prop = RNA_def_property(srna, "tags", PROP_COLLECTION, PROP_NONE);
   RNA_def_property_struct_type(prop, "AssetTag");
-  RNA_def_property_flag(prop, PROP_EDITABLE);
+  RNA_def_property_editable_func(prop, "rna_AssetMetaData_editable");
   RNA_def_property_ui_text(prop,
                            "Tags",
                            "Custom tags (name tokens) for the asset, used for filtering and "
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 0bb76fd933a..fd6664ff0de 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -267,6 +267,7 @@ void rna_def_mtex_common(struct BlenderRNA *brna,
 void rna_def_texpaint_slots(struct BlenderRNA *brna, struct StructRNA *srna);
 void rna_def_view_layer_common(struct BlenderRNA *brna, struct StructRNA *srna, const bool scene);
 
+int rna_AssetMetaData_editable(struct PointerRNA *ptr, const char **r_info);
 PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna,
                                                     const char *get,
                                                     const char *set);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index a05cef7a1cd..7b57c0fd6a5 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2616,6 +2616,40 @@ static uint64_t rna_FileAssetSelectParams_asset_category_get(PointerRNA *ptr)
   return params->filter_id;
 }
 
+static PointerRNA rna_FileBrowser_FileSelectEntry_asset_data_get(PointerRNA *ptr)
+{
+  const FileDirEntry *entry = ptr->data;
+
+  /* Note that the owning ID of the RNA pointer (`ptr->owner_id`) has to be set carefully:
+   * Local IDs (`entry->id`) own their asset metadata themselves. Asset metadata from other blend
+   * files are owned by the file browser (`entry`). Only if this is set correctly, we can tell from
+   * the metadata RNA pointer if the metadata is stored locally and can thus be edited or not. */
+
+  if (entry->id) {
+    PointerRNA id_ptr;
+    RNA_id_pointer_create(entry->id, &id_ptr);
+    return rna_pointer_inherit_refine(&id_ptr, &RNA_AssetMetaData, entry->asset_data

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list