Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/asset/intern/asset_ops.cc')
-rw-r--r--source/blender/editors/asset/intern/asset_ops.cc304
1 files changed, 304 insertions, 0 deletions
diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc
new file mode 100644
index 00000000000..f18cf9712db
--- /dev/null
+++ b/source/blender/editors/asset/intern/asset_ops.cc
@@ -0,0 +1,304 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup edasset
+ */
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+
+#include "BLI_vector.hh"
+
+#include "ED_asset.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* -------------------------------------------------------------------- */
+
+using PointerRNAVec = blender::Vector<PointerRNA>;
+
+static bool asset_operation_poll(bContext * /*C*/)
+{
+ return U.experimental.use_asset_browser;
+}
+
+/**
+ * Return the IDs to operate on as PointerRNA vector. Either a single one ("id" context member) or
+ * multiple ones ("selected_ids" context member).
+ */
+static PointerRNAVec asset_operation_get_ids_from_context(const bContext *C)
+{
+ PointerRNAVec ids;
+
+ PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID);
+ if (idptr.data) {
+ /* Single ID. */
+ ids.append(idptr);
+ }
+ else {
+ ListBase list;
+ CTX_data_selected_ids(C, &list);
+ LISTBASE_FOREACH (CollectionPointerLink *, link, &list) {
+ ids.append(link->ptr);
+ }
+ BLI_freelistN(&list);
+ }
+
+ return ids;
+}
+
+/* -------------------------------------------------------------------- */
+
+class AssetMarkHelper {
+ public:
+ void operator()(const bContext &C, PointerRNAVec &ids);
+
+ void reportResults(ReportList &reports) const;
+ bool wasSuccessful() const;
+
+ private:
+ struct Stats {
+ int tot_created = 0;
+ int tot_already_asset = 0;
+ ID *last_id = nullptr;
+ };
+
+ Stats stats;
+};
+
+void AssetMarkHelper::operator()(const bContext &C, PointerRNAVec &ids)
+{
+ for (PointerRNA &ptr : ids) {
+ BLI_assert(RNA_struct_is_ID(ptr.type));
+
+ ID *id = static_cast<ID *>(ptr.data);
+ if (id->asset_data) {
+ stats.tot_already_asset++;
+ continue;
+ }
+
+ if (ED_asset_mark_id(&C, id)) {
+ stats.last_id = id;
+ stats.tot_created++;
+ }
+ }
+}
+
+bool AssetMarkHelper::wasSuccessful() const
+{
+ return stats.tot_created > 0;
+}
+
+void AssetMarkHelper::reportResults(ReportList &reports) const
+{
+ /* User feedback on failure. */
+ if (!wasSuccessful()) {
+ if ((stats.tot_already_asset > 0)) {
+ BKE_report(&reports,
+ RPT_ERROR,
+ "Selected data-blocks are already assets (or do not support use as assets)");
+ }
+ else {
+ BKE_report(&reports,
+ RPT_ERROR,
+ "No data-blocks to create assets for found (or do not support use as assets)");
+ }
+ }
+ /* User feedback on success. */
+ else if (stats.tot_created == 1) {
+ /* If only one data-block: Give more useful message by printing asset name. */
+ BKE_reportf(&reports, RPT_INFO, "Data-block '%s' is now an asset", stats.last_id->name + 2);
+ }
+ else {
+ BKE_reportf(&reports, RPT_INFO, "%i data-blocks are now assets", stats.tot_created);
+ }
+}
+
+static int asset_mark_exec(bContext *C, wmOperator *op)
+{
+ PointerRNAVec ids = asset_operation_get_ids_from_context(C);
+
+ AssetMarkHelper mark_helper;
+ mark_helper(*C, ids);
+ mark_helper.reportResults(*op->reports);
+
+ if (!mark_helper.wasSuccessful()) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_main_add_notifier(NC_ID | NA_EDITED, nullptr);
+ WM_main_add_notifier(NC_ASSET | NA_ADDED, nullptr);
+
+ return OPERATOR_FINISHED;
+}
+
+static void ASSET_OT_mark(wmOperatorType *ot)
+{
+ ot->name = "Mark as Asset";
+ ot->description =
+ "Enable easier reuse of selected data-blocks through the Asset Browser, with the help of "
+ "customizable metadata (like previews, descriptions and tags)";
+ ot->idname = "ASSET_OT_mark";
+
+ ot->exec = asset_mark_exec;
+ ot->poll = asset_operation_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* -------------------------------------------------------------------- */
+
+class AssetClearHelper {
+ public:
+ void operator()(PointerRNAVec &ids);
+
+ void reportResults(const bContext *C, ReportList &reports) const;
+ bool wasSuccessful() const;
+
+ private:
+ struct Stats {
+ int tot_cleared = 0;
+ ID *last_id = nullptr;
+ };
+
+ Stats stats;
+};
+
+void AssetClearHelper::operator()(PointerRNAVec &ids)
+{
+ for (PointerRNA &ptr : ids) {
+ BLI_assert(RNA_struct_is_ID(ptr.type));
+
+ ID *id = static_cast<ID *>(ptr.data);
+ if (!id->asset_data) {
+ continue;
+ }
+
+ if (ED_asset_clear_id(id)) {
+ stats.tot_cleared++;
+ stats.last_id = id;
+ }
+ }
+}
+
+void AssetClearHelper::reportResults(const bContext *C, ReportList &reports) const
+{
+ if (!wasSuccessful()) {
+ bool is_valid;
+ /* Dedicated error message for when there is an active asset detected, but it's not an ID local
+ * to this file. Helps users better understanding what's going on. */
+ if (AssetHandle active_asset = CTX_wm_asset_handle(C, &is_valid);
+ is_valid && !ED_asset_handle_get_local_id(&active_asset)) {
+ BKE_report(&reports,
+ RPT_ERROR,
+ "No asset data-blocks from the current file selected (assets must be stored in "
+ "the current file to be able to edit or clear them)");
+ }
+ else {
+ BKE_report(&reports, RPT_ERROR, "No asset data-blocks selected/focused");
+ }
+ }
+ else if (stats.tot_cleared == 1) {
+ /* If only one data-block: Give more useful message by printing asset name. */
+ BKE_reportf(
+ &reports, RPT_INFO, "Data-block '%s' is no asset anymore", stats.last_id->name + 2);
+ }
+ else {
+ BKE_reportf(&reports, RPT_INFO, "%i data-blocks are no assets anymore", stats.tot_cleared);
+ }
+}
+
+bool AssetClearHelper::wasSuccessful() const
+{
+ return stats.tot_cleared > 0;
+}
+
+static int asset_clear_exec(bContext *C, wmOperator *op)
+{
+ PointerRNAVec ids = asset_operation_get_ids_from_context(C);
+
+ AssetClearHelper clear_helper;
+ clear_helper(ids);
+ clear_helper.reportResults(C, *op->reports);
+
+ if (!clear_helper.wasSuccessful()) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_main_add_notifier(NC_ID | NA_EDITED, nullptr);
+ WM_main_add_notifier(NC_ASSET | NA_REMOVED, nullptr);
+
+ return OPERATOR_FINISHED;
+}
+
+static void ASSET_OT_clear(wmOperatorType *ot)
+{
+ ot->name = "Clear Asset";
+ ot->description =
+ "Delete all asset metadata and turn the selected asset data-blocks back into normal "
+ "data-blocks";
+ ot->idname = "ASSET_OT_clear";
+
+ ot->exec = asset_clear_exec;
+ ot->poll = asset_operation_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* -------------------------------------------------------------------- */
+
+static bool asset_list_refresh_poll(bContext *C)
+{
+ const AssetLibraryReference *library = CTX_wm_asset_library(C);
+ if (!library) {
+ return false;
+ }
+
+ return ED_assetlist_storage_has_list_for_library(library);
+}
+
+static int asset_list_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
+{
+ const AssetLibraryReference *library = CTX_wm_asset_library(C);
+ ED_assetlist_clear(library, C);
+ return OPERATOR_FINISHED;
+}
+
+static void ASSET_OT_list_refresh(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Refresh Asset List";
+ ot->description = "Trigger a reread of the assets";
+ ot->idname = "ASSET_OT_list_refresh";
+
+ /* api callbacks */
+ ot->exec = asset_list_refresh_exec;
+ ot->poll = asset_list_refresh_poll;
+}
+
+/* -------------------------------------------------------------------- */
+
+void ED_operatortypes_asset(void)
+{
+ WM_operatortype_append(ASSET_OT_mark);
+ WM_operatortype_append(ASSET_OT_clear);
+
+ WM_operatortype_append(ASSET_OT_list_refresh);
+}