UI: Region polling support #105088

Merged
Julian Eisel merged 39 commits from JulianEisel/blender:temp-region-poll into main 2023-04-05 15:30:46 +02:00
7 changed files with 96 additions and 6 deletions
Showing only changes of commit 747a9ea263 - Show all commits

View File

@ -45,11 +45,17 @@ class AssetCatalogService {
Vector<std::unique_ptr<AssetCatalogCollection>> undo_snapshots_;
Vector<std::unique_ptr<AssetCatalogCollection>> redo_snapshots_;
const bool is_read_only_ = false;
public:
static const CatalogFilePath DEFAULT_CATALOG_FILENAME;
struct read_only_tag {
};
public:
AssetCatalogService();
explicit AssetCatalogService(read_only_tag);
explicit AssetCatalogService(const CatalogFilePath &asset_library_root);
/**
@ -62,6 +68,13 @@ class AssetCatalogService {
void tag_has_unsaved_changes(AssetCatalog *edited_catalog);
bool has_unsaved_changes() const;
/**
* Check if this is a read-only service meaning the user shouldn't be able to do edits. This is
* not enforced by internal catalog code, the catalog service user is responsible for it. For
* example the UI should disallow edits.
*/
bool is_read_only() const;
/** Load asset catalog definitions from the files found in the asset library. */
void load_from_disk();
/** Load asset catalog definitions from the given file or directory. */

View File

@ -44,6 +44,11 @@ AssetCatalogService::AssetCatalogService()
{
}
AssetCatalogService::AssetCatalogService(read_only_tag) : AssetCatalogService()
{
const_cast<bool &>(is_read_only_) = true;
}
AssetCatalogService::AssetCatalogService(const CatalogFilePath &asset_library_root)
: AssetCatalogService()
{
@ -52,6 +57,8 @@ AssetCatalogService::AssetCatalogService(const CatalogFilePath &asset_library_ro
void AssetCatalogService::tag_has_unsaved_changes(AssetCatalog *edited_catalog)
{
BLI_assert(!is_read_only_);
if (edited_catalog) {
edited_catalog->flags.has_unsaved_changes = true;
}
@ -86,6 +93,11 @@ bool AssetCatalogService::has_unsaved_changes() const
return catalog_collection_->has_unsaved_changes_;
}
bool AssetCatalogService::is_read_only() const
{
return is_read_only_;
}
void AssetCatalogService::tag_all_catalogs_as_unsaved_changes()
{
for (auto &catalog : catalog_collection_->catalogs_.values()) {
@ -458,6 +470,8 @@ bool AssetCatalogService::is_catalog_known_with_unsaved_changes(const CatalogID
bool AssetCatalogService::write_to_disk(const CatalogFilePath &blend_file_path)
{
BLI_assert(!is_read_only_);
if (!write_to_disk_ex(blend_file_path)) {
return false;
}
@ -631,6 +645,7 @@ void AssetCatalogService::undo()
void AssetCatalogService::redo()
{
BLI_assert(!is_read_only_);
BLI_assert_msg(is_redo_possbile(), "Redo stack is empty");
undo_snapshots_.append(std::move(catalog_collection_));
@ -640,6 +655,7 @@ void AssetCatalogService::redo()
void AssetCatalogService::undo_push()
{
BLI_assert(!is_read_only_);
std::unique_ptr<AssetCatalogCollection> snapshot = catalog_collection_->deep_copy();
undo_snapshots_.append(std::move(snapshot));
redo_snapshots_.clear();

View File

@ -157,7 +157,8 @@ AssetLibrary *AssetLibraryService::get_asset_library_all(const Main *bmain)
AssetLibrary &all_library = *all_library_;
auto build_catalogs_fn = [&all_library](const bool is_first_load) {
/* Start with empty catalog storage. */
all_library.catalog_service = std::make_unique<AssetCatalogService>();
all_library.catalog_service = std::make_unique<AssetCatalogService>(
AssetCatalogService::read_only_tag());
/* (Re-)load catalogs on refresh. */
AssetLibrary::foreach_loaded(

View File

@ -6,6 +6,9 @@
* UI/Editor level API for catalog operations, creating richer functionality than the asset system
* catalog API provides (which this uses internally).
*
* Functions can be expected to not perform any change when #ED_asset_catalogs_read_only() returns
* true. The caller should check.
*
* Note that `ED_asset_catalog.h` is part of this API.
*/
@ -19,6 +22,8 @@
struct AssetLibrary;
[[nodiscard]] bool ED_asset_catalogs_read_only(const AssetLibrary &library);
blender::asset_system::AssetCatalog *ED_asset_catalog_add(
AssetLibrary *library, blender::StringRefNull name, blender::StringRef parent_path = nullptr);
void ED_asset_catalog_remove(AssetLibrary *library,

View File

@ -19,6 +19,13 @@
using namespace blender;
using namespace blender::asset_system;
bool ED_asset_catalogs_read_only(const ::AssetLibrary &library)
{
asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
&library);
return catalog_service->is_read_only();
}
struct CatalogUniqueNameFnData {
const AssetCatalogService &catalog_service;
StringRef parent_path;
@ -53,6 +60,9 @@ asset_system::AssetCatalog *ED_asset_catalog_add(::AssetLibrary *library,
if (!catalog_service) {
return nullptr;
}
if (ED_asset_catalogs_read_only(*library)) {
return nullptr;
}
std::string unique_name = catalog_name_ensure_unique(*catalog_service, name, parent_path);
AssetCatalogPath fullpath = AssetCatalogPath(parent_path) / unique_name;
@ -76,6 +86,9 @@ void ED_asset_catalog_remove(::AssetLibrary *library, const CatalogID &catalog_i
BLI_assert_unreachable();
return;
}
if (ED_asset_catalogs_read_only(*library)) {
return;
}
catalog_service->undo_push();
catalog_service->tag_has_unsaved_changes(nullptr);
@ -93,6 +106,9 @@ void ED_asset_catalog_rename(::AssetLibrary *library,
BLI_assert_unreachable();
return;
}
if (ED_asset_catalogs_read_only(*library)) {
return;
}
AssetCatalog *catalog = catalog_service->find_catalog(catalog_id);
@ -120,6 +136,9 @@ void ED_asset_catalog_move(::AssetLibrary *library,
BLI_assert_unreachable();
return;
}
if (ED_asset_catalogs_read_only(*library)) {
return;
}
AssetCatalog *src_catalog = catalog_service->find_catalog(src_catalog_id);
if (!src_catalog) {
@ -161,6 +180,9 @@ void ED_asset_catalogs_save_from_main_path(::AssetLibrary *library, const Main *
BLI_assert_unreachable();
return;
}
if (ED_asset_catalogs_read_only(*library)) {
return;
}
/* Since writing to disk also means loading any on-disk changes, it may be a good idea to store
* an undo step. */

View File

@ -438,7 +438,18 @@ static void ASSET_OT_library_refresh(struct wmOperatorType *ot)
static bool asset_catalog_operator_poll(bContext *C)
{
const SpaceFile *sfile = CTX_wm_space_file(C);
return sfile && ED_fileselect_active_asset_library_get(sfile);
if (!sfile) {
return false;
}
const AssetLibrary *asset_library = ED_fileselect_active_asset_library_get(sfile);
if (!asset_library) {
return false;
}
if (ED_asset_catalogs_read_only(*asset_library)) {
CTX_wm_operator_poll_msg_set(C, "Asset catalogs cannot be edited in this asset library");
return false;
}
return true;
}
static int asset_catalog_new_exec(bContext *C, wmOperator *op)

View File

@ -119,6 +119,8 @@ class AssetCatalogDropController : public ui::AbstractViewItemDropController {
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 can_modify_catalogs(const ::AssetLibrary &asset_library,
const char **r_disabled_hint);
static bool drop_assets_into_catalog(struct bContext *C,
const AssetCatalogTreeView &tree_view,
const wmDrag &drag,
@ -321,7 +323,9 @@ void AssetCatalogTreeViewItem::build_context_menu(bContext &C, uiLayout &column)
bool AssetCatalogTreeViewItem::supports_renaming() const
{
return true;
const AssetCatalogTreeView &tree_view = static_cast<const AssetCatalogTreeView &>(
get_tree_view());
return !ED_asset_catalogs_read_only(*tree_view.asset_library_);
}
bool AssetCatalogTreeViewItem::rename(StringRefNull new_name)
@ -360,7 +364,12 @@ 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, get_asset_library());
const ::AssetLibrary &library = get_asset_library();
if (!can_modify_catalogs(library, r_disabled_hint)) {
return false;
}
const AssetCatalog *drag_catalog = get_drag_catalog(drag, 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. */
@ -512,6 +521,16 @@ bool AssetCatalogDropController::has_droppable_asset(const wmDrag &drag,
return false;
}
bool AssetCatalogDropController::can_modify_catalogs(const ::AssetLibrary &library,
const char **r_disabled_hint)
{
if (ED_asset_catalogs_read_only(library)) {
*r_disabled_hint = "Catalogs cannot be edited in this asset library";
return false;
}
return true;
}
::AssetLibrary &AssetCatalogDropController::get_asset_library() const
{
return *get_view<AssetCatalogTreeView>().asset_library_;
@ -579,9 +598,12 @@ bool AssetCatalogTreeViewAllItem::DropController::can_drop(const wmDrag &drag,
if (drag.type != WM_DRAG_ASSET_CATALOG) {
return false;
}
::AssetLibrary &library = *get_view<AssetCatalogTreeView>().asset_library_;
if (!AssetCatalogDropController::can_modify_catalogs(library, r_disabled_hint)) {
return false;
}
const AssetCatalog *drag_catalog = AssetCatalogDropController::get_drag_catalog(
drag, *get_view<AssetCatalogTreeView>().asset_library_);
const AssetCatalog *drag_catalog = AssetCatalogDropController::get_drag_catalog(drag, library);
if (drag_catalog->path.parent() == "") {
*r_disabled_hint = "Catalog is already placed at the highest level";
return false;