Merge branch 'blender-v4.0-release'

This commit is contained in:
Julian Eisel
2023-10-23 19:19:38 +02:00
4 changed files with 93 additions and 34 deletions

View File

@@ -95,7 +95,8 @@ void ED_assets_pre_save(Main *bmain)
bool ED_asset_can_mark_single_from_context(const bContext *C)
{
/* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */
/* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_mark_single() and
* #ASSET_OT_clear()/#ASSET_OT_clear_single() to use. */
const ID *id = static_cast<ID *>(CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data);
if (!id) {
return false;

View File

@@ -47,6 +47,16 @@ using namespace blender;
using PointerRNAVec = blender::Vector<PointerRNA>;
static PointerRNAVec get_single_id_vec_from_context(const bContext *C)
{
PointerRNAVec ids;
PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID);
if (idptr.data) {
ids.append(idptr);
}
return ids;
}
/**
* Return the IDs to operate on as PointerRNA vector. Prioritizes multiple selected ones
* ("selected_ids" context member) over a single active one ("id" context member), since usually
@@ -71,12 +81,7 @@ static PointerRNAVec asset_operation_get_ids_from_context(const bContext *C)
}
/* "id" context member. */
PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID);
if (idptr.data) {
ids.append(idptr);
}
return ids;
return get_single_id_vec_from_context(C);
}
/**
@@ -93,14 +98,13 @@ struct IDVecStats {
* Helper to report stats about the IDs in context. Operator polls use this, also to report a
* helpful disabled hint to the user.
*/
static IDVecStats asset_operation_get_id_vec_stats_from_context(const bContext *C)
static IDVecStats asset_operation_get_id_vec_stats_from_ids(const PointerRNAVec &id_pointers)
{
PointerRNAVec pointers = asset_operation_get_ids_from_context(C);
IDVecStats stats;
stats.is_single = pointers.size() == 1;
stats.is_single = id_pointers.size() == 1;
for (PointerRNA &ptr : pointers) {
for (const PointerRNA &ptr : id_pointers) {
BLI_assert(RNA_struct_is_ID(ptr.type));
ID *id = static_cast<ID *>(ptr.data);
@@ -130,7 +134,7 @@ static const char *asset_operation_unsupported_type_msg(const bool is_single)
class AssetMarkHelper {
public:
void operator()(const bContext &C, PointerRNAVec &ids);
void operator()(const bContext &C, const PointerRNAVec &ids);
void reportResults(ReportList &reports) const;
bool wasSuccessful() const;
@@ -145,9 +149,9 @@ class AssetMarkHelper {
Stats stats;
};
void AssetMarkHelper::operator()(const bContext &C, PointerRNAVec &ids)
void AssetMarkHelper::operator()(const bContext &C, const PointerRNAVec &ids)
{
for (PointerRNA &ptr : ids) {
for (const PointerRNA &ptr : ids) {
BLI_assert(RNA_struct_is_ID(ptr.type));
ID *id = static_cast<ID *>(ptr.data);
@@ -195,10 +199,8 @@ void AssetMarkHelper::reportResults(ReportList &reports) const
}
}
static int asset_mark_exec(bContext *C, wmOperator *op)
static int asset_mark_exec(const bContext *C, const wmOperator *op, const PointerRNAVec &ids)
{
PointerRNAVec ids = asset_operation_get_ids_from_context(C);
AssetMarkHelper mark_helper;
mark_helper(*C, ids);
mark_helper.reportResults(*op->reports);
@@ -213,9 +215,9 @@ static int asset_mark_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static bool asset_mark_poll(bContext *C)
static bool asset_mark_poll(bContext *C, const PointerRNAVec &ids)
{
IDVecStats ctx_stats = asset_operation_get_id_vec_stats_from_context(C);
IDVecStats ctx_stats = asset_operation_get_id_vec_stats_from_ids(ids);
if (!ctx_stats.has_supported_type) {
CTX_wm_operator_poll_msg_set(C, asset_operation_unsupported_type_msg(ctx_stats.is_single));
@@ -233,8 +235,33 @@ static void ASSET_OT_mark(wmOperatorType *ot)
"customizable metadata (like previews, descriptions and tags)";
ot->idname = "ASSET_OT_mark";
ot->exec = asset_mark_exec;
ot->poll = asset_mark_poll;
ot->exec = [](bContext *C, wmOperator *op) -> int {
return asset_mark_exec(C, op, asset_operation_get_ids_from_context(C));
};
ot->poll = [](bContext *C) -> bool {
return asset_mark_poll(C, asset_operation_get_ids_from_context(C));
};
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/**
* Variant of #ASSET_OT_mark that only works on the "id" context member.
*/
static void ASSET_OT_mark_single(wmOperatorType *ot)
{
ot->name = "Mark as Single Asset";
ot->description =
"Enable easier reuse of a data-block through the Asset Browser, with the help of "
"customizable metadata (like previews, descriptions and tags)";
ot->idname = "ASSET_OT_mark_single";
ot->exec = [](bContext *C, wmOperator *op) -> int {
return asset_mark_exec(C, op, get_single_id_vec_from_context(C));
};
ot->poll = [](bContext *C) -> bool {
return asset_mark_poll(C, get_single_id_vec_from_context(C));
};
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -247,7 +274,7 @@ class AssetClearHelper {
public:
AssetClearHelper(const bool set_fake_user) : set_fake_user_(set_fake_user) {}
void operator()(PointerRNAVec &ids);
void operator()(const PointerRNAVec &ids);
void reportResults(const bContext *C, ReportList &reports) const;
bool wasSuccessful() const;
@@ -261,9 +288,9 @@ class AssetClearHelper {
Stats stats;
};
void AssetClearHelper::operator()(PointerRNAVec &ids)
void AssetClearHelper::operator()(const PointerRNAVec &ids)
{
for (PointerRNA &ptr : ids) {
for (const PointerRNA &ptr : ids) {
BLI_assert(RNA_struct_is_ID(ptr.type));
ID *id = static_cast<ID *>(ptr.data);
@@ -314,10 +341,8 @@ bool AssetClearHelper::wasSuccessful() const
return stats.tot_cleared > 0;
}
static int asset_clear_exec(bContext *C, wmOperator *op)
static int asset_clear_exec(const bContext *C, const wmOperator *op, const PointerRNAVec &ids)
{
PointerRNAVec ids = asset_operation_get_ids_from_context(C);
const bool set_fake_user = RNA_boolean_get(op->ptr, "set_fake_user");
AssetClearHelper clear_helper(set_fake_user);
clear_helper(ids);
@@ -333,9 +358,9 @@ static int asset_clear_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static bool asset_clear_poll(bContext *C)
static bool asset_clear_poll(bContext *C, const PointerRNAVec &ids)
{
IDVecStats ctx_stats = asset_operation_get_id_vec_stats_from_context(C);
IDVecStats ctx_stats = asset_operation_get_id_vec_stats_from_ids(ids);
if (!ctx_stats.has_asset) {
const char *msg_single = TIP_("Data-block is not marked as asset");
@@ -364,6 +389,9 @@ static std::string asset_clear_get_description(bContext * /*C*/,
"data-blocks, and set Fake User to ensure the data-blocks will still be saved");
}
/**
* Variant of #ASSET_OT_clear that only works on the "id" context member.
*/
static void ASSET_OT_clear(wmOperatorType *ot)
{
ot->name = "Clear Asset";
@@ -373,8 +401,36 @@ static void ASSET_OT_clear(wmOperatorType *ot)
ot->get_description = asset_clear_get_description;
ot->idname = "ASSET_OT_clear";
ot->exec = asset_clear_exec;
ot->poll = asset_clear_poll;
ot->exec = [](bContext *C, wmOperator *op) -> int {
return asset_clear_exec(C, op, asset_operation_get_ids_from_context(C));
};
ot->poll = [](bContext *C) -> bool {
return asset_clear_poll(C, asset_operation_get_ids_from_context(C));
};
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna,
"set_fake_user",
false,
"Set Fake User",
"Ensure the data-block is saved, even when it is no longer marked as asset");
}
static void ASSET_OT_clear_single(wmOperatorType *ot)
{
ot->name = "Clear Single Asset";
ot->description =
"Delete all asset metadata and turn the asset data-block back into a normal data-block";
ot->get_description = asset_clear_get_description;
ot->idname = "ASSET_OT_clear_single";
ot->exec = [](bContext *C, wmOperator *op) -> int {
return asset_clear_exec(C, op, get_single_id_vec_from_context(C));
};
ot->poll = [](bContext *C) -> bool {
return asset_clear_poll(C, get_single_id_vec_from_context(C));
};
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -955,7 +1011,9 @@ static bool has_external_files(Main *bmain, ReportList *reports)
void ED_operatortypes_asset()
{
WM_operatortype_append(ASSET_OT_mark);
WM_operatortype_append(ASSET_OT_mark_single);
WM_operatortype_append(ASSET_OT_clear);
WM_operatortype_append(ASSET_OT_clear_single);
WM_operatortype_append(ASSET_OT_catalog_new);
WM_operatortype_append(ASSET_OT_catalog_delete);

View File

@@ -979,10 +979,10 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
* which isn't cheap to check. */
uiLayout *sub = uiLayoutColumn(layout, true);
uiLayoutSetEnabled(sub, !id->asset_data);
uiItemO(sub, nullptr, ICON_ASSET_MANAGER, "ASSET_OT_mark");
uiItemO(sub, IFACE_("Mark as Asset"), ICON_ASSET_MANAGER, "ASSET_OT_mark_single");
sub = uiLayoutColumn(layout, true);
uiLayoutSetEnabled(sub, id->asset_data);
uiItemO(sub, nullptr, ICON_NONE, "ASSET_OT_clear");
uiItemO(sub, IFACE_("Clear Asset"), ICON_NONE, "ASSET_OT_clear_single");
uiItemS(layout);
}

View File

@@ -1471,7 +1471,7 @@ static void template_ID(const bContext *C,
uiDefIconButO(block,
/* Using `_N` version allows us to get the 'active' state by default. */
UI_BTYPE_ICON_TOGGLE_N,
"ASSET_OT_clear",
"ASSET_OT_clear_single",
WM_OP_INVOKE_DEFAULT,
/* 'active' state of a toggle button uses icon + 1, so to get proper asset
* icon we need to pass its value - 1 here. */