Add copy/paste of any IDs in Outliner.
This adds entries to copy/paste (selected) IDs in the Outliner, as well as usual ctrl-C/ctrl-V shortcuts. Note that the clipboard is shared with other IDs copying (currently, the one for objects in 3DView). Reviewers: brecht, dfelinto, billreynish, pablovazquez Differential Revision: https://developer.blender.org/D4568
This commit is contained in:
parent
c1f8b9753a
commit
94388d69bb
|
@ -698,6 +698,9 @@ def km_outliner(params):
|
|||
("outliner.collection_exclude_clear", {"type": 'E', "value": 'PRESS', "alt": True}, None),
|
||||
("outliner.hide", {"type": 'H', "value": 'PRESS'}, None),
|
||||
("outliner.unhide_all", {"type": 'H', "value": 'PRESS', "alt": True}, None),
|
||||
# Copy/paste.
|
||||
("outliner.id_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
|
||||
("outliner.id_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_appdir.h"
|
||||
#include "BKE_blender_copybuffer.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_idcode.h"
|
||||
|
@ -592,6 +594,104 @@ void id_remap_cb(
|
|||
WM_operator_properties_free(&op_props);
|
||||
}
|
||||
|
||||
/* ID copy/Paste ------------------------------------------------------------- */
|
||||
|
||||
static int outliner_id_copy_tag(SpaceOutliner *soops, ListBase *tree)
|
||||
{
|
||||
TreeElement *te;
|
||||
TreeStoreElem *tselem;
|
||||
int num_ids = 0;
|
||||
|
||||
for (te = tree->first; te; te = te->next) {
|
||||
tselem = TREESTORE(te);
|
||||
|
||||
/* if item is selected and is an ID, tag it as needing to be copied. */
|
||||
if (tselem->flag & TSE_SELECTED && ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
|
||||
ID *id = tselem->id;
|
||||
if (!(id->tag & LIB_TAG_DOIT)) {
|
||||
BKE_copybuffer_tag_ID(tselem->id);
|
||||
num_ids++;
|
||||
}
|
||||
}
|
||||
|
||||
/* go over sub-tree */
|
||||
if (TSELEM_OPEN(tselem, soops)) {
|
||||
num_ids += outliner_id_copy_tag(soops, &te->subtree);
|
||||
}
|
||||
}
|
||||
|
||||
return num_ids;
|
||||
}
|
||||
|
||||
static int outliner_id_copy_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
SpaceOutliner *soops = CTX_wm_space_outliner(C);
|
||||
char str[FILE_MAX];
|
||||
|
||||
BKE_copybuffer_begin(bmain);
|
||||
|
||||
const int num_ids = outliner_id_copy_tag(soops, &soops->tree);
|
||||
if (num_ids == 0) {
|
||||
BKE_report(op->reports, RPT_INFO, "No selected data-blocks to copy");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
|
||||
BKE_copybuffer_save(bmain, str, op->reports);
|
||||
|
||||
BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-blocks", num_ids);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void OUTLINER_OT_id_copy(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Outliner ID Data Copy";
|
||||
ot->idname = "OUTLINER_OT_id_copy";
|
||||
ot->description = "Selected data-blocks are copied to the clipboard";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = outliner_id_copy_exec;
|
||||
ot->poll = ED_operator_outliner_active;
|
||||
|
||||
ot->flag = 0;
|
||||
}
|
||||
|
||||
static int outliner_id_paste_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char str[FILE_MAX];
|
||||
const short flag = FILE_AUTOSELECT | FILE_ACTIVE_COLLECTION;
|
||||
|
||||
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
|
||||
|
||||
const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, 0);
|
||||
if (num_pasted == 0) {
|
||||
BKE_report(op->reports, RPT_INFO, "No data to paste");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
|
||||
BKE_reportf(op->reports, RPT_INFO, "%d data-blocks pasted", num_pasted);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void OUTLINER_OT_id_paste(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Outliner ID Data Paste";
|
||||
ot->idname = "OUTLINER_OT_id_paste";
|
||||
ot->description = "Data-blocks from the clipboard are pasted";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = outliner_id_paste_exec;
|
||||
ot->poll = ED_operator_outliner_active;
|
||||
|
||||
ot->flag = 0;
|
||||
}
|
||||
|
||||
/* Library relocate/reload --------------------------------------------------- */
|
||||
|
||||
static int lib_relocate(
|
||||
|
|
|
@ -297,6 +297,8 @@ void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
|
|||
void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
|
||||
void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
|
||||
void OUTLINER_OT_id_remap(struct wmOperatorType *ot);
|
||||
void OUTLINER_OT_id_copy(struct wmOperatorType *ot);
|
||||
void OUTLINER_OT_id_paste(struct wmOperatorType *ot);
|
||||
void OUTLINER_OT_data_operation(struct wmOperatorType *ot);
|
||||
void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
|
||||
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
|
||||
|
|
|
@ -63,6 +63,8 @@ void outliner_operatortypes(void)
|
|||
WM_operatortype_append(OUTLINER_OT_id_operation);
|
||||
WM_operatortype_append(OUTLINER_OT_id_delete);
|
||||
WM_operatortype_append(OUTLINER_OT_id_remap);
|
||||
WM_operatortype_append(OUTLINER_OT_id_copy);
|
||||
WM_operatortype_append(OUTLINER_OT_id_paste);
|
||||
WM_operatortype_append(OUTLINER_OT_data_operation);
|
||||
WM_operatortype_append(OUTLINER_OT_animdata_operation);
|
||||
WM_operatortype_append(OUTLINER_OT_action_set);
|
||||
|
|
|
@ -1152,6 +1152,9 @@ typedef enum eOutlinerIdOpTypes {
|
|||
OUTLINER_IDOP_DELETE,
|
||||
OUTLINER_IDOP_REMAP,
|
||||
|
||||
OUTLINER_IDOP_COPY,
|
||||
OUTLINER_IDOP_PASTE,
|
||||
|
||||
OUTLINER_IDOP_FAKE_ADD,
|
||||
OUTLINER_IDOP_FAKE_CLEAR,
|
||||
OUTLINER_IDOP_RENAME,
|
||||
|
@ -1169,6 +1172,10 @@ static const EnumPropertyItem prop_id_op_types[] = {
|
|||
{OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""},
|
||||
{OUTLINER_IDOP_REMAP, "REMAP", 0, "Remap Users",
|
||||
"Make all users of selected data-blocks to use instead current (clicked) one"},
|
||||
{0, "", 0, NULL, NULL},
|
||||
{OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""},
|
||||
{OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""},
|
||||
{0, "", 0, NULL, NULL},
|
||||
{OUTLINER_IDOP_FAKE_ADD, "ADD_FAKE", 0, "Add Fake User",
|
||||
"Ensure data-block gets saved even if it isn't in use (e.g. for motion and material libraries)"},
|
||||
{OUTLINER_IDOP_FAKE_CLEAR, "CLEAR_FAKE", 0, "Clear Fake User", ""},
|
||||
|
@ -1320,6 +1327,17 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_COPY:
|
||||
{
|
||||
WM_operator_name_call(C, "OUTLINER_OT_id_copy", WM_OP_INVOKE_DEFAULT, NULL);
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_PASTE:
|
||||
{
|
||||
WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, NULL);
|
||||
ED_undo_push(C, "Paste");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_FAKE_ADD:
|
||||
{
|
||||
/* set fake user */
|
||||
|
|
Loading…
Reference in New Issue