Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c192
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c1
3 files changed, 113 insertions, 82 deletions
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index c43f3d7eaf4..7448c4b65ce 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -81,7 +81,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te)
TreeStoreElem *tselem = TREESTORE(te);
if (!tselem) {
- return false;
+ return NULL;
}
if (tselem->type == TSE_LAYER_COLLECTION) {
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index 4a1e720fe2a..66052166bf7 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -50,6 +50,7 @@
#include "BKE_material.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_object.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -192,18 +193,32 @@ static TreeElement *outliner_drop_insert_find(
}
}
+static Collection *outliner_collection_from_tree_element_and_parents(TreeElement *te, TreeElement **r_te)
+{
+ while (te != NULL) {
+ Collection *collection = outliner_collection_from_tree_element(te);
+ if (collection) {
+ *r_te = te;
+ return collection;
+ }
+ te = te->parent;
+ }
+ return NULL;
+}
+
static TreeElement *outliner_drop_insert_collection_find(
bContext *C, const wmEvent *event,
TreeElementInsertType *r_insert_type)
{
TreeElement *te = outliner_drop_insert_find(C, event, r_insert_type);
- if (!te) {
- return NULL;
- }
+ if (!te) return NULL;
- Collection *collection = outliner_collection_from_tree_element(te);
- if (!collection) {
- return NULL;
+ TreeElement *collection_te;
+ Collection *collection = outliner_collection_from_tree_element_and_parents(te, &collection_te);
+ if (!collection) return NULL;
+
+ if (collection_te != te) {
+ *r_insert_type = TE_INSERT_INTO;
}
/* We can't insert before/after master collection. */
@@ -211,54 +226,80 @@ static TreeElement *outliner_drop_insert_collection_find(
*r_insert_type = TE_INSERT_INTO;
}
- return te;
+ return collection_te;
}
/* ******************** Parent Drop Operator *********************** */
-static bool parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+static bool parent_drop_allowed(SpaceOops *soops, TreeElement *te, Object *potential_child)
{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
- if (!ob) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (te->idcode != ID_OB || tselem->type != 0) {
return false;
}
- /* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_drop_find(C, event);
- TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
+ Object *potential_parent = (Object *)tselem->id;
- if (!te) {
- /* pass */
+ if (potential_parent == potential_child) return false;
+ if (BKE_object_is_child_recursive(potential_child, potential_parent)) return false;
+ if (potential_parent == potential_child->parent) return false;
+
+ /* check that parent/child are both in the same scene */
+ Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
+
+ /* 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)
+ */
+ if (scene) {
+ for (ViewLayer *view_layer = scene->view_layers.first;
+ view_layer;
+ view_layer = view_layer->next)
+ {
+ if (BKE_view_layer_base_find(view_layer, potential_child)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ else {
+ return true;
}
- else if (te->idcode == ID_OB && tselem->type == 0) {
- Scene *scene;
- ID *te_id = tselem->id;
+}
- /* check if dropping self or parent */
- if (te_id == &ob->id || (Object *)te_id == ob->parent)
+static bool allow_parenting_without_modifier_key(SpaceOops *soops)
+{
+ switch (soops->outlinevis) {
+ case SO_VIEW_LAYER:
+ return soops->filter & SO_FILTER_NO_COLLECTION;
+ case SO_SCENES:
+ return true;
+ default:
return false;
+ }
+}
- /* check that parent/child are both in the same scene */
- scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
+static bool parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
- /* 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)
- */
- if (!scene) {
- return true;
- }
- else {
- for (ViewLayer *view_layer = scene->view_layers.first;
- view_layer;
- view_layer = view_layer->next)
- {
- if (BKE_view_layer_base_find(view_layer, ob)) {
- return true;
- }
- }
- }
+ bool changed = outliner_flag_set(&soops->tree, TSE_DRAG_ANY, false);
+ if (changed) ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
+
+ Object *potential_child = (Object *)WM_drag_ID(drag, ID_OB);
+ if (!potential_child) return false;
+
+ if (!allow_parenting_without_modifier_key(soops)) {
+ if (!event->shift) return false;
+ }
+
+ TreeElement *te = outliner_drop_find(C, event);
+ if (!te) return false;
+
+ if (parent_drop_allowed(soops, te, potential_child)) {
+ TREESTORE(te)->flag |= TSE_DRAG_INTO;
+ ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
+ return true;
}
return false;
@@ -436,52 +477,38 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
}
-static bool parenting_poll(bContext *C)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
- if (soops) {
- if (soops->outlinevis == SO_SCENES) {
- return true;
- }
- else if ((soops->outlinevis == SO_VIEW_LAYER) &&
- (soops->filter & SO_FILTER_NO_COLLECTION))
- {
- return true;
- }
- }
-
- return false;
-}
-
/* ******************** Parent Clear Operator *********************** */
static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
{
SpaceOops *soops = CTX_wm_space_outliner(C);
- if (!ELEM(soops->outlinevis, SO_VIEW_LAYER)) {
- return false;
+ if (!allow_parenting_without_modifier_key(soops)) {
+ if (!event->shift) return false;
}
Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
- if (!(ob && ob->parent)) {
- return false;
- }
+ if (!ob) return false;
+ if (!ob->parent) return false;
TreeElement *te = outliner_drop_find(C, event);
if (te) {
TreeStoreElem *tselem = TREESTORE(te);
+ ID *id = tselem->id;
+ if (!id) return true;
- switch (te->idcode) {
- case ID_SCE:
- return (ELEM(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER));
+ switch (GS(id->name)) {
case ID_OB:
- return (ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE));
- /* Other codes to ignore? */
+ return ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE);
+ case ID_GR:
+ return event->shift;
+ default:
+ return true;
}
}
- return (te == NULL);
+ else {
+ return true;
+ }
}
static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
@@ -511,7 +538,7 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot)
/* api callbacks */
ot->invoke = parent_clear_invoke;
- ot->poll = parenting_poll;
+ ot->poll = ED_operator_outliner_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -655,6 +682,8 @@ static Collection *collection_parent_from_ID(ID *id)
static bool collection_drop_init(bContext *C, wmDrag *drag, const wmEvent *event, CollectionDrop *data)
{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
/* Get collection to drop into. */
TreeElementInsertType insert_type;
TreeElement *te = outliner_drop_insert_collection_find(C, event, &insert_type);
@@ -685,7 +714,7 @@ static bool collection_drop_init(bContext *C, wmDrag *drag, const wmEvent *event
/* Get collection to drag out of. */
ID *parent = drag_id->from_parent;
Collection *from_collection = collection_parent_from_ID(parent);
- if (event->ctrl) {
+ if (event->ctrl || soops->outlinevis == SO_SCENES) {
from_collection = NULL;
}
@@ -714,14 +743,15 @@ static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event
bool changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
CollectionDrop data;
- if (collection_drop_init(C, drag, event, &data)) {
+ if (!event->shift && collection_drop_init(C, drag, event, &data)) {
+ TreeElement *te = data.te;
+ TreeStoreElem *tselem = TREESTORE(te);
if (!data.from || event->ctrl) {
+ tselem->flag |= TSE_DRAG_INTO;
+ changed = true;
*tooltip = IFACE_("Link inside Collection");
}
else {
- TreeElement *te = data.te;
- TreeStoreElem *tselem = TREESTORE(te);
-
switch (data.insert_type) {
case TE_INSERT_BEFORE:
tselem->flag |= TSE_DRAG_BEFORE;
@@ -746,17 +776,17 @@ static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event
case TE_INSERT_INTO:
tselem->flag |= TSE_DRAG_INTO;
changed = true;
- *tooltip = TIP_("Move inside collection (Ctrl to link)");
+ *tooltip = TIP_("Move inside collection (Ctrl to link, Shift to parent)");
break;
}
}
+ if (changed) ED_region_tag_redraw_no_rebuild(ar);
+ return true;
}
-
- if (changed) {
- ED_region_tag_redraw_no_rebuild(ar);
+ else {
+ if (changed) ED_region_tag_redraw_no_rebuild(ar);
+ return false;
}
-
- return true;
}
static int collection_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 2794c79eeb2..089b153fa26 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -156,6 +156,7 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "OUTLINER_OT_operation", RIGHTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_item_drag_drop", EVT_TWEAK_L, KM_ANY, 0, 0);
+ WM_keymap_add_item(keymap, "OUTLINER_OT_item_drag_drop", EVT_TWEAK_L, KM_ANY, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_show_hierarchy", HOMEKEY, KM_PRESS, 0, 0);