Cleanup outliner_dropzone code
* deduplicated a bunch of code and moved it into outliner_dropzone_find() * moved all the per-dropzone checks into the poll functions * one functional change, disable drop parenting on self & self->parent The basic assumption: if poll() == true then outliner_dropzone_find() will return a valid TreeElement
This commit is contained in:
@@ -113,6 +113,37 @@ static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *te
|
||||
}
|
||||
#endif
|
||||
|
||||
static TreeElement *outliner_dropzone_element(const SpaceOops *soops, TreeElement *te, const float fmval[2], const int children)
|
||||
{
|
||||
if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
|
||||
/* name and first icon */
|
||||
if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend))
|
||||
return te;
|
||||
}
|
||||
/* Not it. Let's look at its children. */
|
||||
if (children && (TREESTORE(te)->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
|
||||
for (te = te->subtree.first; te; te = te->next) {
|
||||
TreeElement *te_valid = outliner_dropzone_element(soops, te, fmval, children);
|
||||
if (te_valid)
|
||||
return te_valid;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Used for drag and drop parenting */
|
||||
TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const int children)
|
||||
{
|
||||
TreeElement *te;
|
||||
|
||||
for (te = soops->tree.first; te; te = te->next) {
|
||||
TreeElement *te_valid = outliner_dropzone_element(soops, te, fmval, children);
|
||||
if (te_valid)
|
||||
return te_valid;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ************************************************************** */
|
||||
/* Click Activated */
|
||||
|
||||
@@ -1447,36 +1478,6 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/* Used for drag and drop parenting */
|
||||
TreeElement *outliner_dropzone_parent(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2])
|
||||
{
|
||||
SpaceOops *soops = CTX_wm_space_outliner(C);
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
|
||||
/* name and first icon */
|
||||
if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) {
|
||||
/* always makes active object */
|
||||
if (te->idcode == ID_OB && tselem->type == 0) {
|
||||
return te;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not it. Let's look at its children. */
|
||||
if ((tselem->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
|
||||
for (te = te->subtree.first; te; te = te->next) {
|
||||
TreeElement *te_valid;
|
||||
te_valid = outliner_dropzone_parent(C, event, te, fmval);
|
||||
if (te_valid) return te_valid;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Object *par = NULL;
|
||||
@@ -1486,7 +1487,6 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = NULL;
|
||||
TreeElement *te = NULL;
|
||||
TreeElement *te_found = NULL;
|
||||
char childname[MAX_ID_NAME];
|
||||
char parname[MAX_ID_NAME];
|
||||
int partype = 0;
|
||||
@@ -1495,13 +1495,10 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
|
||||
|
||||
/* Find object hovered over */
|
||||
for (te = soops->tree.first; te; te = te->next) {
|
||||
te_found = outliner_dropzone_parent(C, event, te, fmval);
|
||||
if (te_found) break;
|
||||
}
|
||||
te = outliner_dropzone_find(soops, fmval, 1);
|
||||
|
||||
if (te_found) {
|
||||
RNA_string_set(op->ptr, "parent", te_found->name);
|
||||
if (te) {
|
||||
RNA_string_set(op->ptr, "parent", te->name);
|
||||
/* Identify parent and child */
|
||||
RNA_string_get(op->ptr, "child", childname);
|
||||
ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
|
||||
@@ -1516,7 +1513,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
scene = (Scene *)outliner_search_back(soops, te_found, ID_SCE);
|
||||
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
|
||||
@@ -1651,44 +1648,6 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
|
||||
RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
|
||||
}
|
||||
|
||||
int outliner_dropzone_parent_clear(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2])
|
||||
{
|
||||
SpaceOops *soops = CTX_wm_space_outliner(C);
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
/* Check for row */
|
||||
if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
|
||||
/* Ignore drop on scene tree elements */
|
||||
if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) {
|
||||
if ((te->idcode == ID_SCE) &&
|
||||
!ELEM3(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Other codes to ignore?
|
||||
}
|
||||
|
||||
/* Left or right of: (+), first icon, and name */
|
||||
if ((fmval[0] < (te->xs + UI_UNIT_X)) || (fmval[0] > te->xend)) {
|
||||
return 1;
|
||||
}
|
||||
else if (te->idcode != ID_OB || ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0; // ID_OB, but mouse in undefined dropzone.
|
||||
}
|
||||
|
||||
/* Not this row. Let's look at its children. */
|
||||
if ((tselem->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
|
||||
for (te = te->subtree.first; te; te = te->next) {
|
||||
if (outliner_dropzone_parent_clear(C, event, te, fmval))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
@@ -1738,22 +1697,6 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot)
|
||||
RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
|
||||
}
|
||||
|
||||
TreeElement *outliner_dropzone_scene(bContext *C, const wmEvent *UNUSED(event), TreeElement *te, const float fmval[2])
|
||||
{
|
||||
SpaceOops *soops = CTX_wm_space_outliner(C);
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
|
||||
/* name and first icon */
|
||||
if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) {
|
||||
if (te->idcode == ID_SCE && tselem->type == 0) {
|
||||
return te;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Scene *scene = NULL;
|
||||
@@ -1762,24 +1705,19 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
Main *bmain = CTX_data_main(C);
|
||||
TreeElement *te = NULL;
|
||||
TreeElement *te_found = NULL;
|
||||
char obname[MAX_ID_NAME];
|
||||
float fmval[2];
|
||||
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
|
||||
|
||||
/* Find object hovered over */
|
||||
for (te = soops->tree.first; te; te = te->next) {
|
||||
te_found = outliner_dropzone_scene(C, event, te, fmval);
|
||||
if (te_found)
|
||||
break;
|
||||
}
|
||||
te = outliner_dropzone_find(soops, fmval, 0);
|
||||
|
||||
if (te_found) {
|
||||
if (te) {
|
||||
Base *base;
|
||||
|
||||
RNA_string_set(op->ptr, "scene", te_found->name);
|
||||
scene = (Scene *)BKE_libblock_find_name(ID_SCE, te_found->name);
|
||||
RNA_string_set(op->ptr, "scene", te->name);
|
||||
scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name);
|
||||
|
||||
RNA_string_get(op->ptr, "object", obname);
|
||||
ob = (Object *)BKE_libblock_find_name(ID_OB, obname);
|
||||
@@ -1837,22 +1775,17 @@ static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
||||
SpaceOops *soops = CTX_wm_space_outliner(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
TreeElement *te = NULL;
|
||||
TreeElement *te_found = NULL;
|
||||
char mat_name[MAX_ID_NAME - 2];
|
||||
float fmval[2];
|
||||
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
|
||||
|
||||
/* Find object hovered over */
|
||||
for (te = soops->tree.first; te; te = te->next) {
|
||||
te_found = outliner_dropzone_parent(C, event, te, fmval);
|
||||
if (te_found)
|
||||
break;
|
||||
}
|
||||
te = outliner_dropzone_find(soops, fmval, 1);
|
||||
|
||||
if (te_found) {
|
||||
RNA_string_set(op->ptr, "object", te_found->name);
|
||||
ob = (Object *)BKE_libblock_find_name(ID_OB, te_found->name);
|
||||
if (te) {
|
||||
RNA_string_set(op->ptr, "object", te->name);
|
||||
ob = (Object *)BKE_libblock_find_name(ID_OB, te->name);
|
||||
|
||||
RNA_string_get(op->ptr, "material", mat_name);
|
||||
ma = (Material *)BKE_libblock_find_name(ID_MA, mat_name);
|
||||
|
||||
@@ -190,9 +190,7 @@ void group_toggle_renderability_cb(struct bContext *C, struct Scene *scene, Tree
|
||||
|
||||
void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem);
|
||||
|
||||
TreeElement *outliner_dropzone_parent(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
|
||||
int outliner_dropzone_parent_clear(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
|
||||
TreeElement *outliner_dropzone_scene(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
|
||||
TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const int children);
|
||||
/* ...................................................... */
|
||||
|
||||
void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
|
||||
|
||||
@@ -94,7 +94,6 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
|
||||
{
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
SpaceOops *soops = CTX_wm_space_outliner(C);
|
||||
TreeElement *te = NULL;
|
||||
float fmval[2];
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
|
||||
|
||||
@@ -102,25 +101,25 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
|
||||
ID *id = (ID *)drag->poin;
|
||||
if (GS(id->name) == ID_OB) {
|
||||
/* Ensure item under cursor is valid drop target */
|
||||
/* Find object hovered over */
|
||||
for (te = soops->tree.first; te; te = te->next) {
|
||||
TreeElement *te_valid;
|
||||
te_valid = outliner_dropzone_parent(C, event, te, fmval);
|
||||
if (te_valid) {
|
||||
/* check that parent/child are both in the same scene */
|
||||
Scene *scene = (Scene *)outliner_search_back(soops, te_valid, ID_SCE);
|
||||
TreeElement *te = outliner_dropzone_find(soops, fmval, 1);
|
||||
|
||||
if (!scene) {
|
||||
/* 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)
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
if (te && te->idcode == ID_OB && TREESTORE(te)->type == 0) {
|
||||
Scene *scene;
|
||||
ID *te_id = TREESTORE(te)->id;
|
||||
|
||||
if (scene && BKE_scene_base_find(scene, (Object *)id)) {
|
||||
return 1;
|
||||
}
|
||||
/* check if dropping self or parent */
|
||||
if (te_id == id || (Object *)te_id == ((Object *)id)->parent)
|
||||
return 0;
|
||||
|
||||
/* check that parent/child are both in the same 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 || BKE_scene_base_find(scene, (Object *)id)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,19 +146,20 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
|
||||
if (drag->type == WM_DRAG_ID) {
|
||||
ID *id = (ID *)drag->poin;
|
||||
if (GS(id->name) == ID_OB) {
|
||||
if (((Object *)id)->parent == NULL) {
|
||||
return 0;
|
||||
if (((Object *)id)->parent) {
|
||||
if ((te = outliner_dropzone_find(soops, fmval, 1))) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
switch (te->idcode) {
|
||||
case ID_SCE:
|
||||
return (ELEM3(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS));
|
||||
case ID_OB:
|
||||
return (ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE));
|
||||
/* Other codes to ignore? */
|
||||
}
|
||||
}
|
||||
return (te == NULL);
|
||||
}
|
||||
/* Ensure location under cursor is valid dropzone */
|
||||
for (te = soops->tree.first; te; te = te->next) {
|
||||
if (outliner_dropzone_parent_clear(C, event, te, fmval)) return 1;
|
||||
}
|
||||
/* Check if mouse cursor is below the tree */
|
||||
te = soops->tree.last;
|
||||
while (((te->flag & TE_LAZY_CLOSED) == 0) && (te->subtree.last)) {
|
||||
te = te->subtree.last;
|
||||
}
|
||||
if (fmval[1] < te->ys) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -180,7 +180,6 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
|
||||
{
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
SpaceOops *soops = CTX_wm_space_outliner(C);
|
||||
TreeElement *te = NULL;
|
||||
float fmval[2];
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
|
||||
|
||||
@@ -188,11 +187,8 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
|
||||
ID *id = (ID *)drag->poin;
|
||||
if (GS(id->name) == ID_OB) {
|
||||
/* Ensure item under cursor is valid drop target */
|
||||
/* Find object hovered over */
|
||||
for (te = soops->tree.first; te; te = te->next) {
|
||||
if (outliner_dropzone_scene(C, event, te, fmval))
|
||||
return 1;
|
||||
}
|
||||
TreeElement *te = outliner_dropzone_find(soops, fmval, 0);
|
||||
return (te && te->idcode == ID_SCE && TREESTORE(te)->type == 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -209,7 +205,6 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
|
||||
{
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
SpaceOops *soops = CTX_wm_space_outliner(C);
|
||||
TreeElement *te = NULL;
|
||||
float fmval[2];
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
|
||||
|
||||
@@ -217,11 +212,8 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
|
||||
ID *id = (ID *)drag->poin;
|
||||
if (GS(id->name) == ID_MA) {
|
||||
/* Ensure item under cursor is valid drop target */
|
||||
/* Find object hovered over */
|
||||
for (te = soops->tree.first; te; te = te->next) {
|
||||
if (outliner_dropzone_parent(C, event, te, fmval))
|
||||
return 1;
|
||||
}
|
||||
TreeElement *te = outliner_dropzone_find(soops, fmval, 1);
|
||||
return (te && te->idcode == ID_OB && TREESTORE(te)->type == 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user