diff options
author | Julian Eisel <julian@blender.org> | 2021-07-21 21:17:34 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2021-07-21 21:41:29 +0300 |
commit | 64bb49fa4e3c8bd7e02fd6e5252e40f089d787de (patch) | |
tree | 67c1855bd624ae605ec08ba1295ed2a3b4c2d487 /source/blender/editors/asset/intern/asset_ops.cc | |
parent | 178086d5810a0de9e1d95c7fbd6c443cd53af40d (diff) |
Cleanup: Move reorganize asset files
I'm trying to move away from general files with lots of things in them,
and instead have many small & focused files. I find that easier to
work with since everything has clear responsibilities, even if there is
some minor overhead in managing all these files.
I also try to differentiate more clearly between public and internal
files. So source files and internal headers are in a `intern/`
sub-directory, public functions are in a number of headers one level
higher.
For convenience and to make this compatible with our existing general
headers in `editors/include`, I made the `ED_asset.h` there include all
these public headers.
This is of course a bit of an experiment, let's see how it works in
practice.
Also corrected the name of `ED_asset_can_make_single_from_context()`.
Diffstat (limited to 'source/blender/editors/asset/intern/asset_ops.cc')
-rw-r--r-- | source/blender/editors/asset/intern/asset_ops.cc | 292 |
1 files changed, 292 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..79edd1f8a6a --- /dev/null +++ b/source/blender/editors/asset/intern/asset_ops.cc @@ -0,0 +1,292 @@ +/* + * 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 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(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(ReportList &reports) const +{ + if (!wasSuccessful()) { + 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(*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); +} |