Merge branch 'blender-v3.0-release'

This commit is contained in:
Julian Eisel 2021-11-24 18:37:33 +01:00
commit 338408772a
5 changed files with 176 additions and 25 deletions

View File

@ -20,6 +20,8 @@
#pragma once
#include <optional>
#include "BKE_asset_catalog.hh"
#include "BLI_string_ref.hh"
@ -37,6 +39,18 @@ void ED_asset_catalog_remove(AssetLibrary *library, const blender::bke::CatalogI
void ED_asset_catalog_rename(AssetLibrary *library,
blender::bke::CatalogID catalog_id,
blender::StringRefNull new_name);
void ED_asset_catalog_move(AssetLibrary *library,
blender::bke::CatalogID src_catalog_id,
blender::bke::CatalogID dst_parent_catalog_id);
/**
* Reinsert catalog identified by \a src_catalog_id as child to catalog identified by \a
* dst_parent_catalog_id. If \a dst_parent_catalog_id is not set, the catalog is moved to the root
* level of the tree.
* The name of the reinserted catalog is made unique within the parent. Note that moving a catalog
* to the same level it was before will also change its name, since the name uniqueness check isn't
* smart enough to ignore the item to be reinserted. So the caller is expected to handle this case
* to avoid unwanted renames.
*
* Nothing is done (debug builds run into an assert) if the given catalog IDs can't be identified.
*/
void ED_asset_catalog_move(
AssetLibrary *library,
blender::bke::CatalogID src_catalog_id,
std::optional<blender::bke::CatalogID> dst_parent_catalog_id = std::nullopt);

View File

@ -122,7 +122,7 @@ void ED_asset_catalog_rename(::AssetLibrary *library,
void ED_asset_catalog_move(::AssetLibrary *library,
const CatalogID src_catalog_id,
const CatalogID dst_parent_catalog_id)
const std::optional<CatalogID> dst_parent_catalog_id)
{
bke::AssetCatalogService *catalog_service = BKE_asset_library_get_catalog_service(library);
if (!catalog_service) {
@ -131,9 +131,24 @@ void ED_asset_catalog_move(::AssetLibrary *library,
}
AssetCatalog *src_catalog = catalog_service->find_catalog(src_catalog_id);
AssetCatalog *dst_catalog = catalog_service->find_catalog(dst_parent_catalog_id);
if (!src_catalog) {
BLI_assert_unreachable();
return;
}
AssetCatalog *dst_catalog = dst_parent_catalog_id ?
catalog_service->find_catalog(*dst_parent_catalog_id) :
nullptr;
if (!dst_catalog && dst_parent_catalog_id) {
BLI_assert_unreachable();
return;
}
const AssetCatalogPath new_path = dst_catalog->path / StringRef(src_catalog->path.name());
std::string unique_name = catalog_name_ensure_unique(
*catalog_service, src_catalog->path.name(), dst_catalog ? dst_catalog->path.c_str() : "");
/* If a destination catalog was given, construct the path using that. Otherwise, the path is just
* the name of the catalog to be moved, which means it ends up at the root level. */
const AssetCatalogPath new_path = dst_catalog ? (dst_catalog->path / unique_name) :
AssetCatalogPath{unique_name};
const AssetCatalogPath clean_new_path = new_path.cleanup();
if (new_path == src_catalog->path || clean_new_path == src_catalog->path) {

View File

@ -360,11 +360,18 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
* custom implementation of #AbstractTreeViewItem::create_drag_controller().
*/
class AbstractTreeViewItemDragController {
protected:
AbstractTreeView &tree_view_;
public:
AbstractTreeViewItemDragController(AbstractTreeView &tree_view);
virtual ~AbstractTreeViewItemDragController() = default;
virtual int get_drag_type() const = 0;
virtual void *create_drag_data() const = 0;
virtual void on_drag_start();
template<class TreeViewType> inline TreeViewType &tree_view() const;
};
/**
@ -463,6 +470,13 @@ inline ItemT &TreeViewItemContainer::add_tree_item(Args &&...args)
add_tree_item(std::make_unique<ItemT>(std::forward<Args>(args)...)));
}
template<class TreeViewType> TreeViewType &AbstractTreeViewItemDragController::tree_view() const
{
static_assert(std::is_base_of<AbstractTreeView, TreeViewType>::value,
"Type must derive from and implement the AbstractTreeView interface");
return static_cast<TreeViewType &>(tree_view_);
}
template<class TreeViewType> TreeViewType &AbstractTreeViewItemDropController::tree_view() const
{
static_assert(std::is_base_of<AbstractTreeView, TreeViewType>::value,

View File

@ -562,6 +562,19 @@ void AbstractTreeViewItem::change_state_delayed()
activate();
}
}
/* ---------------------------------------------------------------------- */
AbstractTreeViewItemDragController::AbstractTreeViewItemDragController(AbstractTreeView &tree_view)
: tree_view_(tree_view)
{
}
void AbstractTreeViewItemDragController::on_drag_start()
{
/* Do nothing by default. */
}
/* ---------------------------------------------------------------------- */
AbstractTreeViewItemDropController::AbstractTreeViewItemDropController(AbstractTreeView &tree_view)
@ -739,6 +752,8 @@ bool UI_tree_view_item_drag_start(bContext *C, uiTreeViewItemHandle *item_)
drag_controller->create_drag_data(),
0,
WM_DRAG_FREE_DATA);
drag_controller->on_drag_start();
return true;
}

View File

@ -52,6 +52,8 @@ using namespace blender::bke;
namespace blender::ed::asset_browser {
class AssetCatalogTreeViewAllItem;
class AssetCatalogTreeView : public ui::AbstractTreeView {
::AssetLibrary *asset_library_;
/** The asset catalog tree this tree-view represents. */
@ -61,6 +63,7 @@ class AssetCatalogTreeView : public ui::AbstractTreeView {
friend class AssetCatalogTreeViewItem;
friend class AssetCatalogDropController;
friend class AssetCatalogTreeViewAllItem;
public:
AssetCatalogTreeView(::AssetLibrary *library,
@ -69,6 +72,8 @@ class AssetCatalogTreeView : public ui::AbstractTreeView {
void build_tree() override;
void activate_catalog_by_id(CatalogID catalog_id);
private:
ui::BasicTreeViewItem &build_catalog_items_recursive(ui::TreeViewItemContainer &view_parent_item,
AssetCatalogTreeItem &catalog);
@ -105,10 +110,12 @@ class AssetCatalogDragController : public ui::AbstractTreeViewItemDragController
AssetCatalogTreeItem &catalog_item_;
public:
explicit AssetCatalogDragController(AssetCatalogTreeItem &catalog_item);
explicit AssetCatalogDragController(AssetCatalogTreeView &tree_view,
AssetCatalogTreeItem &catalog_item);
int get_drag_type() const override;
void *create_drag_data() const override;
void on_drag_start() override;
};
class AssetCatalogDropController : public ui::AbstractTreeViewItemDropController {
@ -122,16 +129,22 @@ class AssetCatalogDropController : public ui::AbstractTreeViewItemDropController
bool on_drop(const wmDrag &drag) override;
::AssetLibrary &get_asset_library() const;
AssetCatalog *get_drag_catalog(const wmDrag &drag) const;
static AssetCatalog *get_drag_catalog(const wmDrag &drag, const ::AssetLibrary &asset_library);
static bool has_droppable_asset(const wmDrag &drag, const char **r_disabled_hint);
static bool drop_assets_into_catalog(const AssetCatalogTreeView &tree_view,
const wmDrag &drag,
CatalogID catalog_id,
StringRefNull simple_name = "");
/**
* \param drop_catalog_id: Can be unset to drop into the root level of the tree.
*/
static bool drop_asset_catalog_into_catalog(
const wmDrag &drag,
AssetCatalogTreeView &tree_view,
const std::optional<CatalogID> drop_catalog_id = std::nullopt);
private:
bool drop_asset_catalog_into_catalog(const wmDrag &drag);
std::string drop_tooltip_asset_list(const wmDrag &drag) const;
std::string drop_tooltip_asset_catalog(const wmDrag &drag) const;
};
@ -142,6 +155,16 @@ class AssetCatalogTreeViewAllItem : public ui::BasicTreeViewItem {
using BasicTreeViewItem::BasicTreeViewItem;
void build_row(uiLayout &row) override;
struct DropController : public ui::AbstractTreeViewItemDropController {
DropController(AssetCatalogTreeView &tree_view);
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
std::string drop_tooltip(const wmDrag &drag) const override;
bool on_drop(const wmDrag &drag) override;
};
std::unique_ptr<ui::AbstractTreeViewItemDropController> create_drop_controller() const override;
};
class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
@ -229,6 +252,13 @@ void AssetCatalogTreeView::add_unassigned_item()
[params]() { return params->asset_catalog_visibility == FILE_SHOW_ASSETS_WITHOUT_CATALOG; });
}
void AssetCatalogTreeView::activate_catalog_by_id(CatalogID catalog_id)
{
params_->asset_catalog_visibility = FILE_SHOW_ASSETS_FROM_CATALOG;
params_->catalog_id = catalog_id;
WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
}
bool AssetCatalogTreeView::is_active_catalog(CatalogID catalog_id) const
{
return (params_->asset_catalog_visibility == FILE_SHOW_ASSETS_FROM_CATALOG) &&
@ -244,11 +274,8 @@ AssetCatalogTreeViewItem::AssetCatalogTreeViewItem(AssetCatalogTreeItem *catalog
void AssetCatalogTreeViewItem::on_activate()
{
const AssetCatalogTreeView &tree_view = static_cast<const AssetCatalogTreeView &>(
get_tree_view());
tree_view.params_->asset_catalog_visibility = FILE_SHOW_ASSETS_FROM_CATALOG;
tree_view.params_->catalog_id = catalog_item_.get_catalog_id();
WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
AssetCatalogTreeView &tree_view = static_cast<AssetCatalogTreeView &>(get_tree_view());
tree_view.activate_catalog_by_id(catalog_item_.get_catalog_id());
}
void AssetCatalogTreeViewItem::build_row(uiLayout &row)
@ -331,7 +358,8 @@ std::unique_ptr<ui::AbstractTreeViewItemDropController> AssetCatalogTreeViewItem
std::unique_ptr<ui::AbstractTreeViewItemDragController> AssetCatalogTreeViewItem::
create_drag_controller() const
{
return std::make_unique<AssetCatalogDragController>(catalog_item_);
return std::make_unique<AssetCatalogDragController>(
static_cast<AssetCatalogTreeView &>(get_tree_view()), catalog_item_);
}
/* ---------------------------------------------------------------------- */
@ -345,7 +373,7 @@ AssetCatalogDropController::AssetCatalogDropController(AssetCatalogTreeView &tre
bool AssetCatalogDropController::can_drop(const wmDrag &drag, const char **r_disabled_hint) const
{
if (drag.type == WM_DRAG_ASSET_CATALOG) {
const AssetCatalog *drag_catalog = get_drag_catalog(drag);
const AssetCatalog *drag_catalog = get_drag_catalog(drag, get_asset_library());
/* Note: Technically it's not an issue to allow this (the catalog will just receive a new
* path and the catalog system will generate missing parents from the path). But it does
* appear broken to users, so disabling entirely. */
@ -353,6 +381,10 @@ bool AssetCatalogDropController::can_drop(const wmDrag &drag, const char **r_dis
*r_disabled_hint = "Catalog cannot be dropped into itself";
return false;
}
if (catalog_item_.catalog_path() == drag_catalog->path.parent()) {
*r_disabled_hint = "Catalog is already placed inside this catalog";
return false;
}
return true;
}
if (drag.type == WM_DRAG_ASSET_LIST) {
@ -372,7 +404,7 @@ std::string AssetCatalogDropController::drop_tooltip(const wmDrag &drag) const
std::string AssetCatalogDropController::drop_tooltip_asset_catalog(const wmDrag &drag) const
{
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
const AssetCatalog *src_catalog = get_drag_catalog(drag);
const AssetCatalog *src_catalog = get_drag_catalog(drag, get_asset_library());
return std::string(TIP_("Move Catalog")) + " '" + src_catalog->path.name() + "' " +
TIP_("into") + " '" + catalog_item_.get_name() + "'";
@ -397,7 +429,8 @@ std::string AssetCatalogDropController::drop_tooltip_asset_list(const wmDrag &dr
bool AssetCatalogDropController::on_drop(const wmDrag &drag)
{
if (drag.type == WM_DRAG_ASSET_CATALOG) {
return drop_asset_catalog_into_catalog(drag);
return drop_asset_catalog_into_catalog(
drag, tree_view<AssetCatalogTreeView>(), catalog_item_.get_catalog_id());
}
return drop_assets_into_catalog(tree_view<AssetCatalogTreeView>(),
drag,
@ -405,12 +438,15 @@ bool AssetCatalogDropController::on_drop(const wmDrag &drag)
catalog_item_.get_simple_name());
}
bool AssetCatalogDropController::drop_asset_catalog_into_catalog(const wmDrag &drag)
bool AssetCatalogDropController::drop_asset_catalog_into_catalog(
const wmDrag &drag,
AssetCatalogTreeView &tree_view,
const std::optional<CatalogID> drop_catalog_id)
{
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
wmDragAssetCatalog *catalog_drag = WM_drag_get_asset_catalog_data(&drag);
ED_asset_catalog_move(
&get_asset_library(), catalog_drag->drag_catalog_id, catalog_item_.get_catalog_id());
ED_asset_catalog_move(tree_view.asset_library_, catalog_drag->drag_catalog_id, drop_catalog_id);
tree_view.activate_catalog_by_id(catalog_drag->drag_catalog_id);
WM_main_add_notifier(NC_ASSET | ND_ASSET_CATALOGS, nullptr);
return true;
@ -444,13 +480,14 @@ bool AssetCatalogDropController::drop_assets_into_catalog(const AssetCatalogTree
return true;
}
AssetCatalog *AssetCatalogDropController::get_drag_catalog(const wmDrag &drag) const
AssetCatalog *AssetCatalogDropController::get_drag_catalog(const wmDrag &drag,
const ::AssetLibrary &asset_library)
{
if (drag.type != WM_DRAG_ASSET_CATALOG) {
return nullptr;
}
const bke::AssetCatalogService *catalog_service = BKE_asset_library_get_catalog_service(
&get_asset_library());
&asset_library);
const wmDragAssetCatalog *catalog_drag = WM_drag_get_asset_catalog_data(&drag);
return catalog_service->find_catalog(catalog_drag->drag_catalog_id);
@ -480,8 +517,9 @@ bool AssetCatalogDropController::has_droppable_asset(const wmDrag &drag,
/* ---------------------------------------------------------------------- */
AssetCatalogDragController::AssetCatalogDragController(AssetCatalogTreeItem &catalog_item)
: catalog_item_(catalog_item)
AssetCatalogDragController::AssetCatalogDragController(AssetCatalogTreeView &tree_view,
AssetCatalogTreeItem &catalog_item)
: ui::AbstractTreeViewItemDragController(tree_view), catalog_item_(catalog_item)
{
}
@ -498,6 +536,12 @@ void *AssetCatalogDragController::create_drag_data() const
return drag_catalog;
}
void AssetCatalogDragController::on_drag_start()
{
AssetCatalogTreeView &tree_view_ = tree_view<AssetCatalogTreeView>();
tree_view_.activate_catalog_by_id(catalog_item_.get_catalog_id());
}
/* ---------------------------------------------------------------------- */
void AssetCatalogTreeViewAllItem::build_row(uiLayout &row)
@ -515,6 +559,55 @@ void AssetCatalogTreeViewAllItem::build_row(uiLayout &row)
RNA_string_set(props, "parent_path", nullptr);
}
std::unique_ptr<ui::AbstractTreeViewItemDropController> AssetCatalogTreeViewAllItem::
create_drop_controller() const
{
return std::make_unique<AssetCatalogTreeViewAllItem::DropController>(
static_cast<AssetCatalogTreeView &>(get_tree_view()));
}
AssetCatalogTreeViewAllItem::DropController::DropController(AssetCatalogTreeView &tree_view)
: ui::AbstractTreeViewItemDropController(tree_view)
{
}
bool AssetCatalogTreeViewAllItem::DropController::can_drop(const wmDrag &drag,
const char **r_disabled_hint) const
{
if (drag.type != WM_DRAG_ASSET_CATALOG) {
return false;
}
const AssetCatalog *drag_catalog = AssetCatalogDropController::get_drag_catalog(
drag, *tree_view<AssetCatalogTreeView>().asset_library_);
if (drag_catalog->path.parent() == "") {
*r_disabled_hint = "Catalog is already placed at the highest level";
return false;
}
return true;
}
std::string AssetCatalogTreeViewAllItem::DropController::drop_tooltip(const wmDrag &drag) const
{
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
const AssetCatalog *drag_catalog = AssetCatalogDropController::get_drag_catalog(
drag, *tree_view<AssetCatalogTreeView>().asset_library_);
return std::string(TIP_("Move Catalog")) + " '" + drag_catalog->path.name() + "' " +
TIP_("to the top level of the tree");
}
bool AssetCatalogTreeViewAllItem::DropController::on_drop(const wmDrag &drag)
{
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
return AssetCatalogDropController::drop_asset_catalog_into_catalog(
drag,
tree_view<AssetCatalogTreeView>(),
/* No value to drop into the root level. */
std::nullopt);
}
/* ---------------------------------------------------------------------- */
std::unique_ptr<ui::AbstractTreeViewItemDropController> AssetCatalogTreeViewUnassignedItem::