Outliner: set parent for entire selection

Set and clear parents for all elements in the selection in the outliner.

This also removes the popup menu for setting the parent to curves,
armatures, and lattices. It makes more sense to keep the outliner
simple and only do object parenting.
This commit is contained in:
Nathan Craddock 2019-08-09 13:55:58 -06:00
parent 1e51411db4
commit 7ba2de8f8f
Notes: blender-bot 2023-02-14 05:01:19 +01:00
Referenced by issue #57855, Outliner. Drag and drop to parent should support multiple objects
1 changed files with 55 additions and 126 deletions

View File

@ -326,38 +326,57 @@ static bool parent_drop_poll(bContext *C,
return false;
}
static int parent_drop_exec(bContext *C, wmOperator *op)
static void parent_drop_set_parents(
bContext *C, ReportList *reports, wmDragID *drag, Object *parent, short parent_type)
{
Object *par = NULL, *ob = NULL;
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
int partype = -1;
char parname[MAX_NAME], childname[MAX_NAME];
SpaceOutliner *soops = CTX_wm_space_outliner(C);
partype = RNA_enum_get(op->ptr, "type");
RNA_string_get(op->ptr, "parent", parname);
par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname);
RNA_string_get(op->ptr, "child", childname);
ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
TreeElement *te = outliner_find_id(soops, &soops->tree, &parent->id);
Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (ID_IS_LINKED(ob)) {
BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
return OPERATOR_CANCELLED;
if (scene == NULL) {
/* currently outliner organized in a way, that if there's no parent scene
* element for object it means that all displayed objects belong to
* active scene and parenting them is allowed (sergey)
*/
scene = CTX_data_scene(C);
}
ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
bool parent_set = false;
bool linked_objects = false;
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
for (wmDragID *drag_id = drag; drag_id; drag_id = drag_id->next) {
if (GS(drag_id->id->name) == ID_OB) {
Object *object = (Object *)drag_id->id;
return OPERATOR_FINISHED;
/* Do nothing to linked data */
if (ID_IS_LINKED(object)) {
linked_objects = true;
continue;
}
if (ED_object_parent_set(
reports, C, scene, object, parent, parent_type, false, false, NULL)) {
parent_set = true;
}
}
}
if (linked_objects) {
BKE_report(reports, RPT_INFO, "Can't edit library linked object(s)");
}
if (parent_set) {
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
}
}
static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te = outliner_drop_find(C, event);
TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
@ -374,107 +393,15 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (ob == par) {
return OPERATOR_CANCELLED;
}
if (ID_IS_LINKED(ob)) {
BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
if (event->custom != EVT_DATA_DRAGDROP) {
return OPERATOR_CANCELLED;
}
char childname[MAX_NAME];
char parname[MAX_NAME];
STRNCPY(childname, ob->id.name + 2);
STRNCPY(parname, par->id.name + 2);
RNA_string_set(op->ptr, "child", childname);
RNA_string_set(op->ptr, "parent", parname);
ListBase *lb = event->customdata;
wmDrag *drag = lb->first;
Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (scene == NULL) {
/* currently outlier organized in a way, that if there's no parent scene
* element for object it means that all displayed objects belong to
* active scene and parenting them is allowed (sergey)
*/
scene = CTX_data_scene(C);
}
if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
int partype = 0;
if (ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL)) {
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
}
}
else {
/* Menu creation */
wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false);
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
PointerRNA ptr;
/* Cannot use uiItemEnumO()... have multiple properties to set. */
uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_OBJECT);
/* par becomes parent, make the associated menus */
if (par->type == OB_ARMATURE) {
uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE);
uiItemFullO_ptr(
layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME);
uiItemFullO_ptr(
layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE);
uiItemFullO_ptr(
layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO);
uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_BONE);
}
else if (par->type == OB_CURVE) {
uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_CURVE);
uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_FOLLOW);
uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_PATH_CONST);
}
else if (par->type == OB_LATTICE) {
uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_LATTICE);
}
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
}
parent_drop_set_parents(C, op->reports, drag->ids.first, par, PAR_OBJECT);
return OPERATOR_FINISHED;
}
@ -488,17 +415,11 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
/* api callbacks */
ot->invoke = parent_drop_invoke;
ot->exec = parent_drop_exec;
ot->poll = ED_operator_outliner_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
RNA_def_string(ot->srna, "child", "Object", MAX_NAME, "Child", "Child Object");
RNA_def_string(ot->srna, "parent", "Object", MAX_NAME, "Parent", "Parent Object");
RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
}
/* ******************** Parent Clear Operator *********************** */
@ -549,13 +470,21 @@ static bool parent_clear_poll(bContext *C,
static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
if (ob == NULL) {
if (event->custom != EVT_DATA_DRAGDROP) {
return OPERATOR_CANCELLED;
}
ED_object_parent_clear(ob, 0);
ListBase *lb = event->customdata;
wmDrag *drag = lb->first;
for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) {
if (GS(drag_id->id->name) == ID_OB) {
Object *object = (Object *)drag_id->id;
ED_object_parent_clear(object, 0);
}
}
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);