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/blenkernel/intern/object.c8
-rw-r--r--source/blender/include/BIF_outliner.h6
-rw-r--r--source/blender/makesdna/DNA_oops_types.h2
-rw-r--r--source/blender/src/header_oops.c2
-rw-r--r--source/blender/src/outliner.c482
-rw-r--r--source/blender/src/space.c10
6 files changed, 453 insertions, 57 deletions
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 40cc3b1fa61..c40b64295f6 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -349,11 +349,19 @@ void unlink_object(Object *ob)
else if(sl->spacetype==SPACE_OOPS) {
SpaceOops *so= (SpaceOops *)sl;
Oops *oops;
+
oops= so->oops.first;
while(oops) {
if(oops->id==(ID *)ob) oops->id= NULL;
oops= oops->next;
}
+ if(so->treestore) {
+ TreeStoreElem *tselem= so->treestore->data;
+ int a;
+ for(a=0; a<so->treestore->usedelem; a++, tselem++) {
+ if(tselem->id==(ID *)ob) tselem->id= NULL;
+ }
+ }
}
}
diff --git a/source/blender/include/BIF_outliner.h b/source/blender/include/BIF_outliner.h
index 22830009e1c..ec44e9aa3f4 100644
--- a/source/blender/include/BIF_outliner.h
+++ b/source/blender/include/BIF_outliner.h
@@ -33,6 +33,7 @@
#ifndef BIF_OUTLINER_H
#define BIF_OUTLINER_H
+struct TreeStoreElem;
typedef struct TreeElement {
struct TreeElement *next, *prev, *parent;
@@ -43,7 +44,7 @@ typedef struct TreeElement {
short idcode; // from TreeStore id
short xend; // width of item display, for select
char *name;
- void *directdata; // Armature Bones, ...
+ void *directdata; // Armature Bones, Base, ...
} TreeElement;
/* TreeElement->flag */
@@ -69,6 +70,9 @@ extern void outliner_toggle_visible(struct ScrArea *sa);
extern void outliner_show_active(struct ScrArea *sa);
extern void outliner_show_hierarchy(struct ScrArea *sa);
extern void outliner_one_level(struct ScrArea *sa, int add);
+extern void outliner_select(struct ScrArea *sa);
+extern void outliner_toggle_selected(struct ScrArea *sa);
+extern void outliner_operation_menu(struct ScrArea *sa);
#endif
diff --git a/source/blender/makesdna/DNA_oops_types.h b/source/blender/makesdna/DNA_oops_types.h
index 5e6707577d7..6b4ed9a3128 100644
--- a/source/blender/makesdna/DNA_oops_types.h
+++ b/source/blender/makesdna/DNA_oops_types.h
@@ -77,7 +77,7 @@ typedef struct OopsLink {
/* TreeStoreElem->flag */
#define TSE_CLOSED 1
-#define TSE_LASTCLICKED 2
+#define TSE_SELECTED 2
/* TreeStoreElem types in BIF_outliner.h */
diff --git a/source/blender/src/header_oops.c b/source/blender/src/header_oops.c
index c38534f471a..32752c63b55 100644
--- a/source/blender/src/header_oops.c
+++ b/source/blender/src/header_oops.c
@@ -169,7 +169,7 @@ static uiBlock *oops_viewmenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show/Hide All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show/Hide All", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hierarchy|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Active|NumPad .", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
}
diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c
index 698cd5d196f..7ff20484635 100644
--- a/source/blender/src/outliner.c
+++ b/source/blender/src/outliner.c
@@ -76,7 +76,9 @@
#include "BIF_editarmature.h"
#include "BIF_editnla.h"
#include "BIF_editview.h"
+#include "BIF_editconstraint.h"
#include "BIF_gl.h"
+#include "BIF_graphics.h"
#include "BIF_interface.h"
#include "BIF_mywindow.h"
#include "BIF_outliner.h"
@@ -87,6 +89,7 @@
#include "BIF_resources.h"
#include "BIF_screen.h"
#include "BIF_space.h"
+#include "BIF_toolbox.h"
#ifdef INTERNATIONAL
#include "FTF_Api.h"
@@ -94,6 +97,7 @@
#include "BDR_editobject.h"
#include "BSE_drawipo.h"
+#include "BSE_edit.h"
#include "BSE_editaction.h"
#include "blendef.h"
@@ -112,40 +116,45 @@
/* ******************** PERSISTANT DATA ***************** */
-/* for now only called after reading file or undo step */
static void outliner_storage_cleanup(SpaceOops *soops)
{
TreeStore *ts= soops->treestore;
- if(ts && (soops->storeflag & SO_TREESTORE_CLEANUP)) {
- TreeStoreElem *tselem= ts->data;
+ if(ts) {
+ TreeStoreElem *tselem;
int a, unused= 0;
- for(a=0; a<ts->usedelem; a++, tselem++) {
- if(tselem->id==NULL) unused++;
- }
-
- if(unused) {
- if(ts->usedelem == unused) {
- MEM_freeN(ts->data);
- ts->data= NULL;
- ts->usedelem= ts->totelem= 0;
+ /* each element used once, for ID blocks with more users to have each a treestore */
+ for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) tselem->used= 0;
+
+ /* cleanup only after reading file or undo step */
+ if(soops->storeflag & SO_TREESTORE_CLEANUP) {
+
+ for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) {
+ if(tselem->id==NULL) unused++;
}
- else {
- TreeStoreElem *tsnewar, *tsnew;
-
- tsnew=tsnewar= MEM_mallocN((ts->usedelem-unused)*sizeof(TreeStoreElem), "new tselem");
- tselem= ts->data;
- for(a=0; a<ts->usedelem; a++, tselem++) {
- if(tselem->id) {
- *tsnew= *tselem;
- tsnew++;
+
+ if(unused) {
+ if(ts->usedelem == unused) {
+ MEM_freeN(ts->data);
+ ts->data= NULL;
+ ts->usedelem= ts->totelem= 0;
+ }
+ else {
+ TreeStoreElem *tsnewar, *tsnew;
+
+ tsnew=tsnewar= MEM_mallocN((ts->usedelem-unused)*sizeof(TreeStoreElem), "new tselem");
+ for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) {
+ if(tselem->id) {
+ *tsnew= *tselem;
+ tsnew++;
+ }
}
+ MEM_freeN(ts->data);
+ ts->data= tsnewar;
+ ts->usedelem-= unused;
+ ts->totelem= ts->usedelem;
}
- MEM_freeN(ts->data);
- ts->data= tsnewar;
- ts->usedelem-= unused;
- ts->totelem= ts->usedelem;
}
}
}
@@ -166,9 +175,10 @@ static void check_persistant(SpaceOops *soops, TreeElement *te, ID *id, short ty
/* check if 'te' is in treestore */
tselem= ts->data;
for(a=0; a<ts->usedelem; a++, tselem++) {
- if(tselem->id==id) {
+ if(tselem->id==id && tselem->used==0) {
if(type==0 ||(tselem->type==type && tselem->nr==nr)) {
te->store_index= a;
+ tselem->used= 1;
return;
}
}
@@ -423,7 +433,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
tenla->name= "Hooks";
for(hook=ob->hooks.first; hook; hook= hook->next, a++) {
ten= outliner_add_element(soops, &tenla->subtree, hook->parent, tenla, TE_HOOK, a);
- ten->name= hook->name;
+ if(ten) ten->name= hook->name;
}
}
if(ob->defbase.first) {
@@ -593,6 +603,8 @@ static void outliner_make_hierarchy(SpaceOops *soops, ListBase *lb)
BLI_remlink(lb, te);
tep= (TreeElement *)ob->parent->id.newid;
BLI_addtail(&tep->subtree, te);
+ // set correct parent pointers
+ for(te=tep->subtree.first; te; te= te->next) te->parent= tep;
}
}
te= ten;
@@ -604,7 +616,7 @@ static void outliner_build_tree(SpaceOops *soops)
Scene *sce;
Base *base;
Object *ob;
- TreeElement *te;
+ TreeElement *te, *ten;
TreeStoreElem *tselem;
outliner_free_tree(&soops->tree);
@@ -620,7 +632,8 @@ static void outliner_build_tree(SpaceOops *soops)
tselem= TREESTORE(te);
for(base= sce->base.first; base; base= base->next) {
- outliner_add_element(soops, &te->subtree, base->object, te, 0, 0);
+ ten= outliner_add_element(soops, &te->subtree, base->object, te, 0, 0);
+ ten->directdata= base;
}
outliner_make_hierarchy(soops, &te->subtree);
}
@@ -629,7 +642,8 @@ static void outliner_build_tree(SpaceOops *soops)
outliner_add_element(soops, &soops->tree, G.scene->world, NULL, 0, 0);
for(base= G.scene->base.first; base; base= base->next) {
- outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata= base;
}
outliner_make_hierarchy(soops, &soops->tree);
}
@@ -645,7 +659,8 @@ static void outliner_build_tree(SpaceOops *soops)
if(ob) {
for(base= G.scene->base.first; base; base= base->next) {
if(base->object->type==ob->type) {
- outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata= base;
}
}
outliner_make_hierarchy(soops, &soops->tree);
@@ -654,14 +669,17 @@ static void outliner_build_tree(SpaceOops *soops)
else if(soops->outlinevis == SO_SELECTED) {
for(base= G.scene->base.first; base; base= base->next) {
if(base->lay & G.scene->lay) {
- if(base==BASACT || (base->flag & SELECT))
- outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ if(base==BASACT || (base->flag & SELECT)) {
+ ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata= base;
+ }
}
}
outliner_make_hierarchy(soops, &soops->tree);
}
else {
- outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
+ ten= outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
+ if(ten) ten->directdata= BASACT;
}
outliner_sort(soops, &soops->tree);
@@ -682,7 +700,7 @@ static int outliner_count_levels(SpaceOops *soops, ListBase *lb, int curlevel)
return level;
}
-static int outliner_has_one_closed(SpaceOops *soops, ListBase *lb, int curlevel)
+static int outliner_has_one_flag(SpaceOops *soops, ListBase *lb, short flag, short curlevel)
{
TreeElement *te;
TreeStoreElem *tselem;
@@ -690,24 +708,24 @@ static int outliner_has_one_closed(SpaceOops *soops, ListBase *lb, int curlevel)
for(te= lb->first; te; te= te->next) {
tselem= TREESTORE(te);
- if(tselem->flag & TSE_CLOSED) return curlevel;
+ if(tselem->flag & flag) return curlevel;
- level= outliner_has_one_closed(soops, &te->subtree, curlevel+1);
+ level= outliner_has_one_flag(soops, &te->subtree, flag, curlevel+1);
if(level) return level;
}
return 0;
}
-static void outliner_open_close(SpaceOops *soops, ListBase *lb, int open)
+static void outliner_set_flag(SpaceOops *soops, ListBase *lb, short flag, short set)
{
TreeElement *te;
TreeStoreElem *tselem;
for(te= lb->first; te; te= te->next) {
tselem= TREESTORE(te);
- if(open) tselem->flag &= ~TSE_CLOSED;
- else tselem->flag |= TSE_CLOSED;
- outliner_open_close(soops, &te->subtree, open);
+ if(set==0) tselem->flag &= ~flag;
+ else tselem->flag |= flag;
+ outliner_set_flag(soops, &te->subtree, flag, set);
}
}
@@ -715,14 +733,27 @@ void outliner_toggle_visible(struct ScrArea *sa)
{
SpaceOops *soops= sa->spacedata.first;
- if( outliner_has_one_closed(soops, &soops->tree, 1))
- outliner_open_close(soops, &soops->tree, 1);
+ if( outliner_has_one_flag(soops, &soops->tree, TSE_CLOSED, 1))
+ outliner_set_flag(soops, &soops->tree, TSE_CLOSED, 0);
else
- outliner_open_close(soops, &soops->tree, 0);
+ outliner_set_flag(soops, &soops->tree, TSE_CLOSED, 1);
scrarea_queue_redraw(curarea);
}
+void outliner_toggle_selected(struct ScrArea *sa)
+{
+ SpaceOops *soops= sa->spacedata.first;
+
+ if( outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1))
+ outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0);
+ else
+ outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 1);
+
+ scrarea_queue_redraw(curarea);
+}
+
+
static void outliner_openclose_level(SpaceOops *soops, ListBase *lb, int curlevel, int level, int open)
{
TreeElement *te;
@@ -747,7 +778,7 @@ void outliner_one_level(struct ScrArea *sa, int add)
SpaceOops *soops= sa->spacedata.first;
int level;
- level= outliner_has_one_closed(soops, &soops->tree, 1);
+ level= outliner_has_one_flag(soops, &soops->tree, TSE_CLOSED, 1);
if(add==1) {
if(level) outliner_openclose_level(soops, &soops->tree, 1, level, 1);
}
@@ -778,12 +809,13 @@ static void tree_element_active_object(SpaceOops *soops, TreeElement *te)
if(ob==NULL) return;
sce= (Scene *)outliner_search_back(soops, te, ID_SCE);
- if(G.scene != sce) {
+ if(sce && G.scene != sce) {
if(G.obedit) exit_editmode(2);
+ if(G.obpose) exit_posemode(1);
set_scene(sce);
}
- /* find associated base */
+ /* find associated base in current scene */
for(base= FIRSTBASE; base; base= base->next)
if(base->object==ob) break;
if(base) {
@@ -811,6 +843,7 @@ static void tree_element_active_object(SpaceOops *soops, TreeElement *te)
}
if(ob!=G.obedit) exit_editmode(2);
+ if(ob!=G.obpose) exit_posemode(1);
}
static int tree_element_active_material(SpaceOops *soops, TreeElement *te, int set)
@@ -1157,7 +1190,7 @@ static int do_outliner_mouse_event(SpaceOops *soops, TreeElement *te, short even
/* all below close/open? */
if( (G.qual & LR_SHIFTKEY) ) {
tselem->flag &= ~TSE_CLOSED;
- outliner_open_close(soops, &te->subtree, outliner_has_one_closed(soops, &te->subtree, 1));
+ outliner_set_flag(soops, &te->subtree, TSE_CLOSED, !outliner_has_one_flag(soops, &te->subtree, TSE_CLOSED, 1));
}
else {
if(tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
@@ -1178,10 +1211,12 @@ static int do_outliner_mouse_event(SpaceOops *soops, TreeElement *te, short even
if(te->idcode==ID_SCE) {
if(G.scene!=(Scene *)tselem->id) {
if(G.obedit) exit_editmode(2);
+ if(G.obpose) exit_posemode(1);
set_scene((Scene *)tselem->id);
}
}
else if(ELEM4(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT)) {
+ if(G.obpose) exit_posemode(1);
if(G.obedit) exit_editmode(2);
else {
enter_editmode();
@@ -1311,6 +1346,320 @@ void outliner_show_hierarchy(struct ScrArea *sa)
scrarea_queue_redraw(sa);
}
+static void do_outliner_select(SpaceOops *soops, ListBase *lb, float y1, float y2, short *selecting)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ if(y1>y2) SWAP(float, y1, y2);
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+
+ if(te->ys + OL_H < y1) return;
+ if(te->ys < y2) {
+ if((te->flag & TE_ICONROW)==0) {
+ if(*selecting == -1) {
+ if( tselem->flag & TSE_SELECTED) *selecting= 0;
+ else *selecting= 1;
+ }
+ if(*selecting) tselem->flag |= TSE_SELECTED;
+ else tselem->flag &= ~TSE_SELECTED;
+ }
+ }
+ if((tselem->flag & TSE_CLOSED)==0) do_outliner_select(soops, &te->subtree, y1, y2, selecting);
+ }
+}
+
+/* its own redraw loop... urm */
+void outliner_select(struct ScrArea *sa )
+{
+ SpaceOops *so= sa->spacedata.first;
+ float fmval[2], y1, y2;
+ short mval[2], yo=-1, selecting= -1;
+
+ getmouseco_areawin(mval);
+ fmval[0]= mval[0];
+ fmval[1]= mval[1];
+ areamouseco_to_ipoco(&so->v2d, mval, fmval, fmval+1);
+ y1= fmval[1];
+
+ while (get_mbut() & R_MOUSE) {
+ getmouseco_areawin(mval);
+ fmval[0]= mval[0];
+ fmval[1]= mval[1];
+ areamouseco_to_ipoco(&so->v2d, mval, fmval, fmval+1);
+ y2= fmval[1];
+ if(yo!=mval[1]) {
+ do_outliner_select(so, &so->tree, y1, y2, &selecting);
+ yo= mval[1];
+ scrarea_do_windraw(sa);
+ screen_swapbuffers();
+
+ y1= y2;
+ }
+ }
+
+}
+
+/* ************ SELECTION OPERATIONS ********* */
+
+static int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0; // globals, euh... you can do better
+
+static void set_operation_types(SpaceOops *soops, ListBase *lb)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->flag & TSE_SELECTED) {
+ if(tselem->type) {
+ if(datalevel==0) datalevel= tselem->type;
+ else if(datalevel!=tselem->type) datalevel= -1;
+ }
+ else {
+ int idcode= GS(tselem->id->name);
+ switch(idcode) {
+ case ID_SCE:
+ scenelevel= 1;
+ break;
+ case ID_OB:
+ objectlevel= 1;
+ break;
+
+ case ID_ME: case ID_CU: case ID_MB: case ID_LT:
+ case ID_LA: case ID_AR: case ID_CA:
+ idlevel= -2;
+ break;
+
+ case ID_MA: case ID_TE: case ID_IP: case ID_IM:
+ case ID_SO: case ID_KE: case ID_WO: case ID_AC:
+ case ID_NLA: case ID_TXT:
+ if(idlevel==0) idlevel= idcode;
+ else if(idlevel!=idcode) idlevel= -1;
+ break;
+ }
+ }
+ }
+ if((tselem->flag & TSE_CLOSED)==0) set_operation_types(soops, &te->subtree);
+ }
+}
+
+static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep)
+{
+ Material **matar=NULL;
+ int a, totcol=0;
+
+ if( GS(tsep->id->name)==ID_OB) {
+ Object *ob= (Object *)tsep->id;
+ totcol= ob->totcol;
+ matar= ob->mat;
+ }
+ else if( GS(tsep->id->name)==ID_ME) {
+ Mesh *me= (Mesh *)tsep->id;
+ totcol= me->totcol;
+ matar= me->mat;
+ }
+ else if( GS(tsep->id->name)==ID_CU) {
+ Curve *cu= (Curve *)tsep->id;
+ totcol= cu->totcol;
+ matar= cu->mat;
+ }
+ else if( GS(tsep->id->name)==ID_MB) {
+ MetaBall *mb= (MetaBall *)tsep->id;
+ totcol= mb->totcol;
+ matar= mb->mat;
+ }
+
+ for(a=0; a<totcol; a++) {
+ if(a==te->index && matar[a]) {
+ matar[a]->id.us--;
+ matar[a]= NULL;
+ }
+ }
+}
+
+static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep)
+{
+ MTex **mtex= NULL;
+ int tottex= 0;
+ int a;
+
+ if( GS(tsep->id->name)==ID_MA) {
+ Material *ma= (Material *)tsep->id;
+ mtex= ma->mtex;
+ tottex= 8;
+ }
+ else if( GS(tsep->id->name)==ID_LA) {
+ Lamp *la= (Lamp *)tsep->id;
+ mtex= la->mtex;
+ tottex= 6;
+ }
+ else if( GS(tsep->id->name)==ID_WO) {
+ World *wrld= (World *)tsep->id;
+ mtex= wrld->mtex;
+ tottex= 6;
+ }
+ for(a=0; a<tottex; a++) {
+ if(a==te->index && mtex[a]) {
+ if(mtex[a]->tex) {
+ mtex[a]->tex->id.us--;
+ mtex[a]->tex= NULL;
+ }
+ }
+ }
+}
+
+static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb,
+ void (*operation_cb)(TreeElement *, TreeStoreElem *))
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te=lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->flag & TSE_SELECTED) {
+ if(tselem->type==0) {
+ TreeStoreElem *tsep= TREESTORE(te->parent);
+ operation_cb(te, tsep);
+ }
+ }
+ if((tselem->flag & TSE_CLOSED)==0) {
+ outliner_do_libdata_operation(soops, &te->subtree, operation_cb);
+ }
+ }
+}
+
+/* */
+
+static void object_select_cb(TreeElement *te, TreeStoreElem *tselem)
+{
+ Base *base= (Base *)te->directdata;
+
+ base->flag |= SELECT;
+ base->object->flag |= SELECT;
+}
+
+static void object_deselect_cb(TreeElement *te, TreeStoreElem *tselem)
+{
+ Base *base= (Base *)te->directdata;
+
+ base->flag &= ~SELECT;
+ base->object->flag &= ~SELECT;
+}
+
+static void object_delete_cb(TreeElement *te, TreeStoreElem *tselem)
+{
+ Base *base= (Base *)te->directdata;
+
+ if(base) {
+ // check also library later
+ if(G.obpose==base->object) exit_posemode(1);
+ if(G.obedit==base->object) exit_editmode(2);
+
+ if(base==BASACT) {
+ G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT);
+ setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+ }
+
+ free_and_unlink_base(base);
+ te->directdata= NULL;
+ tselem->id= NULL;
+ }
+}
+
+
+static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb,
+ void (*operation_cb)(TreeElement *, TreeStoreElem *))
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te=lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->flag & TSE_SELECTED) {
+ if(tselem->type==0 && te->idcode==ID_OB)
+ operation_cb(te, tselem);
+ }
+ if((tselem->flag & TSE_CLOSED)==0) {
+ outliner_do_object_operation(soops, &te->subtree, operation_cb);
+ }
+ }
+}
+
+void outliner_operation_menu(ScrArea *sa)
+{
+ SpaceOops *soops= sa->spacedata.first;
+
+ // globals
+ scenelevel= objectlevel= idlevel= datalevel=0;
+
+ set_operation_types(soops, &soops->tree);
+
+ if(scenelevel) {
+ if(objectlevel || datalevel || idlevel) error("Mixed selection");
+ else pupmenu("Scene Operations%t|Delete");
+ }
+ else if(objectlevel) {
+ short event= pupmenu("Object Operations%t|Select%x1|Deselect%x2|Delete%x4");
+ if(event>0) {
+ char *str="";
+
+ if(event==1) {
+ outliner_do_object_operation(soops, &soops->tree, object_select_cb);
+ str= "Select Objects";
+ }
+ else if(event==2) {
+ outliner_do_object_operation(soops, &soops->tree, object_deselect_cb);
+ str= "Deselect Objects";
+ }
+ else if(event==4) {
+ outliner_do_object_operation(soops, &soops->tree, object_delete_cb);
+ str= "Delete Objects";
+ }
+
+ countall();
+ test_scene_constraints(); // for delete
+
+ BIF_undo_push(str);
+ allqueue(REDRAWALL, 0); // yah... to be sure :)
+ }
+ }
+ else if(idlevel) {
+ if(idlevel==-1 || datalevel) error("Mixed selection");
+ else if(idlevel==-2) error("No operations available");
+ else {
+ short event= pupmenu("Data Operations%t|Unlink");
+
+ if(event==1) {
+ switch(idlevel) {
+ case ID_MA:
+ outliner_do_libdata_operation(soops, &soops->tree, unlink_material_cb);
+ allqueue(REDRAWBUTSSHADING, 1);
+ break;
+ case ID_TE:
+ outliner_do_libdata_operation(soops, &soops->tree, unlink_texture_cb);
+ allqueue(REDRAWBUTSSHADING, 1);
+ break;
+ default:
+ error("Not yet...");
+ }
+ allqueue(REDRAWOOPS, 0);
+ }
+ }
+ }
+ else if(datalevel) {
+ if(datalevel==-1) error("Mixed selection");
+ else {
+ pupmenu("Data Operations%t|Delete");
+ }
+ }
+ else error("Nothing selected");
+
+}
+
+
/* ***************** DRAW *************** */
static void tselem_draw_icon(TreeStoreElem *tselem)
@@ -1492,7 +1841,10 @@ static void outliner_draw_tree_element(SpaceOops *soops, TreeElement *te, int st
/* open/close icon, only when sublevels, except for scene */
if(te->subtree.first || te->idcode==ID_SCE) {
- glRasterPos2i(startx, *starty+2); // icons a bit higher
+ if(tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE))
+ glRasterPos2i(startx, *starty+2); // icons a bit higher
+ else
+ glRasterPos2i(startx+5, *starty+2); // icons a bit higher
if(tselem->flag & TSE_CLOSED)
BIF_draw_icon(ICON_TRIA_CLOSED);
else
@@ -1571,10 +1923,31 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx,
outliner_draw_hierarchy(soops, &te->subtree, startx+OL_X, starty);
}
+ /* vertical line */
te= lb->last;
if(te->parent || lb->first!=lb->last) {
tselem= TREESTORE(te);
- if(tselem->type==0 && te->idcode==ID_OB) glRecti(startx, y1+OL_H, startx+1, y2);
+ if(tselem->type==0 && te->idcode==ID_OB) {
+
+ glRecti(startx, y1+OL_H, startx+1, y2);
+ }
+ }
+}
+
+static void outliner_draw_selection(SpaceOops *soops, ListBase *lb, int *starty)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+
+ /* selection status */
+ if(tselem->flag & TSE_SELECTED) {
+ glRecti(0, *starty+1, (int)soops->v2d.mask.xmax, *starty+OL_H-1);
+ }
+ *starty-= OL_H;
+ if((tselem->flag & TSE_CLOSED)==0) outliner_draw_selection(soops, &te->subtree, starty);
}
}
@@ -1588,13 +1961,19 @@ static void outliner_draw_tree(SpaceOops *soops)
#endif
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once
+
+ // selection first
+ glColor3ub(125, 150, 175);
+ starty= soops->v2d.tot.ymax-OL_H;
+ outliner_draw_selection(soops, &soops->tree, &starty);
- //BIF_ThemeColorShade(TH_BACK, -20);
+ // black hierarchy lines
glColor3ub(0,0,0);
starty= soops->v2d.tot.ymax-OL_H/2;
startx= 6;
outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
+ // items themselves
starty= soops->v2d.tot.ymax-OL_H;
startx= 0;
for(te= soops->tree.first; te; te= te->next) {
@@ -1617,7 +1996,6 @@ static void outliner_back(SpaceOops *soops)
}
}
-
void draw_outliner(ScrArea *sa, SpaceOops *soops)
{
int sizey;
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index fc9df9f94e2..5c786927491 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -3802,11 +3802,17 @@ static void winqreadoopsspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case WHEELDOWNMOUSE:
view2dmove(event); /* in drawipo.c */
break;
+ case RIGHTMOUSE:
+ outliner_select(sa);
+ break;
case AKEY:
- outliner_toggle_visible(sa);
+ outliner_toggle_selected(sa);
break;
-
+ case WKEY:
+ outliner_operation_menu(sa);
+ break;
+
case HOMEKEY:
outliner_show_hierarchy(sa);
break;