|
|
|
|
@@ -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);
|
|
|
|
|
|