diff options
Diffstat (limited to 'source/blender/editors/space_outliner/outliner.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner.c | 1805 |
1 files changed, 1314 insertions, 491 deletions
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 8017b8437ff..a1fdbab9ccc 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -82,6 +82,8 @@ #include "BKE_sequence.h" #include "BKE_utildefines.h" +#include "ED_armature.h" +#include "ED_object.h" #include "ED_screen.h" #include "ED_util.h" #include "ED_types.h" @@ -98,11 +100,14 @@ #include "UI_view2d.h" #include "RNA_access.h" +#include "RNA_define.h" #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_object.h" +#include "ED_particle.h" #include "ED_screen.h" +#include "ED_view3d.h" #include "outliner_intern.h" @@ -128,18 +133,15 @@ /* ************* XXX **************** */ -static void BIF_undo_push() {} -static void BIF_preview_changed() {} static void error() {} -static int pupmenu() {return 0;} /* ********************************** */ /* ******************** PROTOTYPES ***************** */ -static void outliner_draw_tree_element(Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty); -static void outliner_do_object_operation(Scene *scene, SpaceOops *soops, ListBase *lb, - void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *)); +static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty); +static void outliner_do_object_operation(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, + void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *)); /* ******************** PERSISTANT DATA ***************** */ @@ -551,16 +553,6 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s } outliner_add_element(soops, lb, sce->world, te, 0, 0); - - if(sce->scriptlink.scripts) { - int a= 0; - tenla= outliner_add_element(soops, lb, sce, te, TSE_SCRIPT_BASE, 0); - tenla->name= "Scripts"; - for (a=0; a<sce->scriptlink.totscript; a++) { - outliner_add_element(soops, &tenla->subtree, sce->scriptlink.scripts[a], tenla, 0, 0); - } - } - } static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv, @@ -569,7 +561,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i TreeElement *te; TreeStoreElem *tselem; ID *id= idv; - int a; + int a = 0; if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { id= ((PointerRNA*)idv)->id.data; @@ -628,7 +620,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i tenla->name= "Pose"; - if(arm->edbo==NULL && (ob->flag & OB_POSEMODE)) { // channels undefined in editmode, but we want the 'tenla' pose icon itself + if(arm->edbo==NULL && (ob->mode & OB_MODE_POSE)) { // channels undefined in editmode, but we want the 'tenla' pose icon itself int a= 0, const_index= 1000; /* ensure unique id for bone constraints */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, a++) { @@ -767,15 +759,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i ten->directdata= defgroup; } } - if(ob->scriptlink.scripts) { - TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_SCRIPT_BASE, 0); - int a= 0; - - tenla->name= "Scripts"; - for (a=0; a<ob->scriptlink.totscript; a++) { /* ** */ - outliner_add_element(soops, &tenla->subtree, ob->scriptlink.scripts[a], te, 0, 0); - } - } if(ob->dup_group) outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0); @@ -904,7 +887,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i else { /* do not extend Armature when we have posemode */ tselem= TREESTORE(te->parent); - if( GS(tselem->id->name)==ID_OB && ((Object *)tselem->id)->flag & OB_POSEMODE); + if( GS(tselem->id->name)==ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE); else { Bone *curBone; for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ @@ -949,7 +932,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i /* NLA Data */ if (adt->nla_tracks.first) { -#if 0 TreeElement *tenla= outliner_add_element(soops, &te->subtree, adt, te, TSE_NLA, 0); NlaTrack *nlt; int a= 0; @@ -957,17 +939,18 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i tenla->name= "NLA Tracks"; for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { - TreeElement *tenlt= outliner_add_element(soops, &te->subtree, nlt, te, TSE_NLA_TRACK, a); - bActionStrip *strip; + TreeElement *tenlt= outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a); + NlaStrip *strip; TreeElement *ten; int b= 0; - for (strip=nlt->strips.first; strip; strip=strip->next, a++) { - ten= outliner_add_element(soops, &tenla->subtree, strip->act, tenla, TSE_NLA_ACTION, a); + tenlt->name= nlt->name; + + for (strip=nlt->strips.first; strip; strip=strip->next, b++) { + ten= outliner_add_element(soops, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b); if(ten) ten->directdata= strip; } } -#endif } } else if(type==TSE_SEQUENCE) { @@ -1033,7 +1016,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i PointerRNA pptr, propptr, *ptr= (PointerRNA*)idv; PropertyRNA *prop, *iterprop; PropertyType proptype; - PropertySubType propsubtype; int a, tot; /* we do lazy build, for speed and to avoid infinite recusion */ @@ -1102,7 +1084,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i te->flag |= TE_LAZY_CLOSED; } else if(ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { - tot= RNA_property_array_length(prop); + tot= RNA_property_array_length(ptr, prop); if(!(tselem->flag & TSE_CLOSED)) { for(a=0; a<tot; a++) @@ -1113,32 +1095,61 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i } } else if(type == TSE_RNA_ARRAY_ELEM) { - /* array property element */ - static char *vectoritem[4]= {" x", " y", " z", " w"}; - static char *quatitem[4]= {" w", " x", " y", " z"}; - static char *coloritem[4]= {" r", " g", " b", " a"}; + char c; prop= parent->directdata; - proptype= RNA_property_type(prop); - propsubtype= RNA_property_subtype(prop); - tot= RNA_property_array_length(prop); te->directdata= prop; te->rnaptr= *ptr; te->index= index; - if(tot == 4 && propsubtype == PROP_ROTATION) - te->name= quatitem[index]; - else if(tot <= 4 && (propsubtype == PROP_VECTOR || propsubtype == PROP_ROTATION)) - te->name= vectoritem[index]; - else if(tot <= 4 && propsubtype == PROP_COLOR) - te->name= coloritem[index]; - else { - te->name= MEM_callocN(sizeof(char)*20, "OutlinerRNAArrayName"); - sprintf(te->name, " %d", index+1); - te->flag |= TE_FREE_NAME; + c= RNA_property_array_item_char(prop, index); + + te->name= MEM_callocN(sizeof(char)*20, "OutlinerRNAArrayName"); + if(c) sprintf(te->name, " %c", c); + else sprintf(te->name, " %d", index+1); + te->flag |= TE_FREE_NAME; + } + } + else if(type == TSE_KEYMAP) { + wmKeyMap *km= (wmKeyMap *)idv; + wmKeymapItem *kmi; + char opname[OP_MAX_TYPENAME]; + + te->directdata= idv; + te->name= km->nameid; + + if(!(tselem->flag & TSE_CLOSED)) { + a= 0; + + for (kmi= km->keymap.first; kmi; kmi= kmi->next, a++) { + const char *key= WM_key_event_string(kmi->type); + + if(key[0]) { + wmOperatorType *ot= NULL; + + if(kmi->propvalue); + else ot= WM_operatortype_find(kmi->idname, 0); + + if(ot || kmi->propvalue) { + TreeElement *ten= outliner_add_element(soops, &te->subtree, kmi, te, TSE_KEYMAP_ITEM, a); + + ten->directdata= kmi; + + if(kmi->propvalue) { + ten->name= "Modal map, not yet"; + } + else { + WM_operator_py_idname(opname, ot->idname); + ten->name= BLI_strdup(opname); + ten->flag |= TE_FREE_NAME; + } + } + } } } + else + te->flag |= TE_LAZY_CLOSED; } return te; @@ -1393,6 +1404,14 @@ static void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) tselem->flag &= ~TSE_CLOSED; } } + else if(soops->outlinevis==SO_KEYMAP) { + wmWindowManager *wm= mainvar->wm.first; + wmKeyMap *km; + + for(km= wm->keymaps.first; km; km= km->next) { + ten= outliner_add_element(soops, &soops->tree, (void*)km, NULL, TSE_KEYMAP, 0); + } + } else { ten= outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0); if(ten) ten->directdata= BASACT; @@ -1445,9 +1464,10 @@ static void outliner_set_flag(SpaceOops *soops, ListBase *lb, short flag, short } } -void object_toggle_visibility_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +/* --- */ + +void object_toggle_visibility_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { - Scene *scene= NULL; // XXX Base *base= (Base *)te->directdata; if(base==NULL) base= object_in_scene((Object *)tselem->id, scene); @@ -1456,18 +1476,37 @@ void object_toggle_visibility_cb(TreeElement *te, TreeStoreElem *tsep, TreeStore } } -void outliner_toggle_visibility(Scene *scene, SpaceOops *soops) +static int outliner_toggle_visibility_exec(bContext *C, wmOperator *op) { - - outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_visibility_cb); + SpaceOops *soops= CTX_wm_space_outliner(C); + Scene *scene= CTX_data_scene(C); + ARegion *ar= CTX_wm_region(C); + + outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb); - BIF_undo_push("Outliner toggle selectability"); + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} +void OUTLINER_OT_visibility_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Toggle Visability"; + ot->idname= "OUTLINER_OT_visibility_toggle"; + ot->description= "Toggle the visibility of selected items."; + + /* callbacks */ + ot->exec= outliner_toggle_visibility_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -static void object_toggle_selectability_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +/* --- */ + +static void object_toggle_selectability_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { - Scene *scene= NULL; // XXX Base *base= (Base *)te->directdata; if(base==NULL) base= object_in_scene((Object *)tselem->id, scene); @@ -1476,18 +1515,37 @@ static void object_toggle_selectability_cb(TreeElement *te, TreeStoreElem *tsep, } } -void outliner_toggle_selectability(Scene *scene, SpaceOops *soops) +static int outliner_toggle_selectability_exec(bContext *C, wmOperator *op) { + SpaceOops *soops= CTX_wm_space_outliner(C); + Scene *scene= CTX_data_scene(C); + ARegion *ar= CTX_wm_region(C); - outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_selectability_cb); + outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_selectability_cb); - BIF_undo_push("Outliner toggle selectability"); + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} +void OUTLINER_OT_selectability_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Toggle Selectability"; + ot->idname= "OUTLINER_OT_selectability_toggle"; + ot->description= "Toggle the selectability"; + + /* callbacks */ + ot->exec= outliner_toggle_selectability_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -void object_toggle_renderability_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +/* --- */ + +void object_toggle_renderability_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { - Scene *scene= NULL; // XXX Base *base= (Base *)te->directdata; if(base==NULL) base= object_in_scene((Object *)tselem->id, scene); @@ -1496,39 +1554,100 @@ void object_toggle_renderability_cb(TreeElement *te, TreeStoreElem *tsep, TreeSt } } -void outliner_toggle_renderability(Scene *scene, SpaceOops *soops) +static int outliner_toggle_renderability_exec(bContext *C, wmOperator *op) { - - outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_renderability_cb); + SpaceOops *soops= CTX_wm_space_outliner(C); + Scene *scene= CTX_data_scene(C); + ARegion *ar= CTX_wm_region(C); - BIF_undo_push("Outliner toggle renderability"); + outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb); + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} +void OUTLINER_OT_renderability_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Toggle Renderability"; + ot->idname= "OUTLINER_OT_renderability_toggle"; + ot->description= "Toggle the renderbility of selected items."; + + /* callbacks */ + ot->exec= outliner_toggle_renderability_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -void outliner_toggle_visible(SpaceOops *soops) +/* --- */ + +static int outliner_toggle_expanded_exec(bContext *C, wmOperator *op) { + SpaceOops *soops= CTX_wm_space_outliner(C); + ARegion *ar= CTX_wm_region(C); - if( outliner_has_one_flag(soops, &soops->tree, TSE_CLOSED, 1)) + if (outliner_has_one_flag(soops, &soops->tree, TSE_CLOSED, 1)) outliner_set_flag(soops, &soops->tree, TSE_CLOSED, 0); else outliner_set_flag(soops, &soops->tree, TSE_CLOSED, 1); + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} - BIF_undo_push("Outliner toggle visible"); +void OUTLINER_OT_expanded_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Expand/Collapse All"; + ot->idname= "OUTLINER_OT_expanded_toggle"; + ot->description= "Expand/Collapse all items."; + + /* callbacks */ + ot->exec= outliner_toggle_expanded_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -void outliner_toggle_selected(ARegion *ar, SpaceOops *soops) +/* --- */ + +static int outliner_toggle_selected_exec(bContext *C, wmOperator *op) { + SpaceOops *soops= CTX_wm_space_outliner(C); + ARegion *ar= CTX_wm_region(C); - if( outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1)) + 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); - BIF_undo_push("Outliner toggle selected"); soops->storeflag |= SO_TREESTORE_REDRAW; + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; } +void OUTLINER_OT_selected_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Toggle Selected"; + ot->idname= "OUTLINER_OT_selected_toggle"; + ot->description= "Toggle the Outliner selection of items."; + + /* callbacks */ + ot->exec= outliner_toggle_selected_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} +/* --- */ + +/* helper function for Show/Hide one level operator */ static void outliner_openclose_level(SpaceOops *soops, ListBase *lb, int curlevel, int level, int open) { TreeElement *te; @@ -1548,6 +1667,43 @@ static void outliner_openclose_level(SpaceOops *soops, ListBase *lb, int curleve } } +static int outliner_one_level_exec(bContext *C, wmOperator *op) +{ + SpaceOops *soops= CTX_wm_space_outliner(C); + ARegion *ar= CTX_wm_region(C); + int add= RNA_boolean_get(op->ptr, "open"); + int level; + + 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); + } + else { + if(level==0) level= outliner_count_levels(soops, &soops->tree, 0); + if(level) outliner_openclose_level(soops, &soops->tree, 1, level-1, 0); + } + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_show_one_level(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Show/Hide One Level"; + ot->idname= "OUTLINER_OT_show_one_level"; + + /* callbacks */ + ot->exec= outliner_one_level_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep."); +} + /* return 1 when levels were opened */ static int outliner_open_back(SpaceOops *soops, TreeElement *te) { @@ -1590,22 +1746,7 @@ static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *te } #endif -void outliner_one_level(SpaceOops *soops, int add) -{ - int level; - - 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); - } - else { - if(level==0) level= outliner_count_levels(soops, &soops->tree, 0); - if(level) outliner_openclose_level(soops, &soops->tree, 1, level-1, 0); - } - - BIF_undo_push("Outliner show/hide one level"); -} - +// XXX just use View2D ops for this? void outliner_page_up_down(Scene *scene, ARegion *ar, SpaceOops *soops, int up) { int dy= ar->v2d.mask.ymax-ar->v2d.mask.ymin; @@ -1619,7 +1760,7 @@ void outliner_page_up_down(Scene *scene, ARegion *ar, SpaceOops *soops, int up) /* **** do clicks on items ******* */ -static int tree_element_active_renderlayer(TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_renderlayer(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set) { Scene *sce; @@ -1630,6 +1771,7 @@ static int tree_element_active_renderlayer(TreeElement *te, TreeStoreElem *tsele if(set) { sce->r.actlay= tselem->nr; + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, sce); } else { return sce->r.actlay==tselem->nr; @@ -1637,13 +1779,12 @@ static int tree_element_active_renderlayer(TreeElement *te, TreeStoreElem *tsele return 0; } -static void tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te) +static void tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) { TreeStoreElem *tselem= TREESTORE(te); Scene *sce; Base *base; Object *ob= NULL; - int shift= 0; // XXX /* if id is not object, we search back */ if(te->idcode==ID_OB) ob= (Object *)tselem->id; @@ -1662,7 +1803,7 @@ static void tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops for(base= FIRSTBASE; base; base= base->next) if(base->object==ob) break; if(base) { - if(shift) { + if(set==2) { /* swap select */ if(base->flag & SELECT) ED_base_object_select(base, BA_DESELECT); @@ -1682,11 +1823,14 @@ static void tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops ED_base_object_activate(C, base); /* adds notifier */ } -// XXX if(ob!=obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); -// else countall(); /* exit_editmode calls f() */ + if(ob!=scene->obedit) + ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); + + WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); + } -static int tree_element_active_material(Scene *scene, SpaceOops *soops, TreeElement *te, int set) +static int tree_element_active_material(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) { TreeElement *tes; Object *ob; @@ -1700,32 +1844,33 @@ static int tree_element_active_material(Scene *scene, SpaceOops *soops, TreeElem if(tes->idcode==ID_OB) { if(set) { ob->actcol= te->index+1; - ob->colbits |= (1<<te->index); // make ob material active too + ob->matbits[te->index]= 1; // make ob material active too + ob->colbits |= (1<<te->index); } else { if(ob->actcol == te->index+1) - if(ob->colbits & (1<<te->index)) return 1; + if(ob->matbits[te->index]) return 1; } } /* or we search for obdata material */ else { if(set) { ob->actcol= te->index+1; - ob->colbits &= ~(1<<te->index); // make obdata material active too + ob->matbits[te->index]= 0; // make obdata material active too + ob->colbits &= ~(1<<te->index); } else { if(ob->actcol == te->index+1) - if( (ob->colbits & (1<<te->index))==0 ) return 1; + if(ob->matbits[te->index]==0) return 1; } } if(set) { -// XXX extern_set_butspace(F5KEY, 0); // force shading buttons - BIF_preview_changed(ID_MA); + WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, NULL); } return 0; } -static int tree_element_active_texture(Scene *scene, SpaceOops *soops, TreeElement *te, int set) +static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) { TreeElement *tep; TreeStoreElem *tselem, *tselemp; @@ -1749,7 +1894,7 @@ static int tree_element_active_texture(Scene *scene, SpaceOops *soops, TreeEleme if(set) { if(sbuts) { // XXX sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c - sbuts->texfrom= 1; + // XXX sbuts->texfrom= 1; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture wrld->texact= te->index; @@ -1763,7 +1908,7 @@ static int tree_element_active_texture(Scene *scene, SpaceOops *soops, TreeEleme if(set) { if(sbuts) { // XXX sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c - sbuts->texfrom= 2; + // XXX sbuts->texfrom= 2; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture la->texact= te->index; @@ -1779,7 +1924,7 @@ static int tree_element_active_texture(Scene *scene, SpaceOops *soops, TreeEleme if(set) { if(sbuts) { //sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c - sbuts->texfrom= 0; + // XXX sbuts->texfrom= 0; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture ma->texact= (char)te->index; @@ -1796,7 +1941,7 @@ static int tree_element_active_texture(Scene *scene, SpaceOops *soops, TreeEleme } -static int tree_element_active_lamp(Scene *scene, SpaceOops *soops, TreeElement *te, int set) +static int tree_element_active_lamp(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) { Object *ob; @@ -1806,14 +1951,13 @@ static int tree_element_active_lamp(Scene *scene, SpaceOops *soops, TreeElement if(set) { // XXX extern_set_butspace(F5KEY, 0); - BIF_preview_changed(ID_LA); } else return 1; return 0; } -static int tree_element_active_world(Scene *scene, SpaceOops *soops, TreeElement *te, int set) +static int tree_element_active_world(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) { TreeElement *tep; TreeStoreElem *tselem=NULL; @@ -1827,7 +1971,7 @@ static int tree_element_active_world(Scene *scene, SpaceOops *soops, TreeElement if(set) { // make new scene active if(sce && scene != sce) { - // XXX ED_screen_set_scene(C, sce); + ED_screen_set_scene(C, sce); } } @@ -1842,7 +1986,7 @@ static int tree_element_active_world(Scene *scene, SpaceOops *soops, TreeElement return 0; } -static int tree_element_active_defgroup(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_defgroup(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { Object *ob; @@ -1850,7 +1994,8 @@ static int tree_element_active_defgroup(Scene *scene, TreeElement *te, TreeStore ob= (Object *)tselem->id; if(set) { ob->actdef= te->index+1; - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); } else { if(ob==OBACT) @@ -1859,13 +2004,14 @@ static int tree_element_active_defgroup(Scene *scene, TreeElement *te, TreeStore return 0; } -static int tree_element_active_posegroup(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_posegroup(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { Object *ob= (Object *)tselem->id; if(set) { if (ob->pose) { ob->pose->active_group= te->index+1; + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); } } else { @@ -1876,7 +2022,7 @@ static int tree_element_active_posegroup(Scene *scene, TreeElement *te, TreeStor return 0; } -static int tree_element_active_posechannel(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { Object *ob= (Object *)tselem->id; bPoseChannel *pchan= te->directdata; @@ -1884,10 +2030,16 @@ static int tree_element_active_posechannel(Scene *scene, TreeElement *te, TreeSt if(set) { if(!(pchan->bone->flag & BONE_HIDDEN_P)) { -// XXX if(G.qual & LR_SHIFTKEY) deselectall_posearmature(ob, 2, 0); // 2 = clear active tag -// else deselectall_posearmature(ob, 0, 0); // 0 = deselect - pchan->bone->flag |= BONE_SELECTED|BONE_ACTIVE; + if(set==2) ED_pose_deselectall(ob, 2, 0); // 2 = clear active tag + else ED_pose_deselectall(ob, 0, 0); // 0 = deselect + + if(set==2 && (pchan->bone->flag & BONE_SELECTED)) + pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE); + else + pchan->bone->flag |= BONE_SELECTED|BONE_ACTIVE; + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, ob); + } } else { @@ -1898,17 +2050,22 @@ static int tree_element_active_posechannel(Scene *scene, TreeElement *te, TreeSt return 0; } -static int tree_element_active_bone(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { bArmature *arm= (bArmature *)tselem->id; Bone *bone= te->directdata; if(set) { if(!(bone->flag & BONE_HIDDEN_P)) { -// XXX if(G.qual & LR_SHIFTKEY) deselectall_posearmature(OBACT, 2, 0); // 2 is clear active tag -// else deselectall_posearmature(OBACT, 0, 0); - bone->flag |= BONE_SELECTED|BONE_ACTIVE; + if(set==2) ED_pose_deselectall(OBACT, 2, 0); // 2 is clear active tag + else ED_pose_deselectall(OBACT, 0, 0); + if(set==2 && (bone->flag & BONE_SELECTED)) + bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE); + else + bone->flag |= BONE_SELECTED|BONE_ACTIVE; + + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, OBACT); } } else { @@ -1923,21 +2080,21 @@ static int tree_element_active_bone(Scene *scene, TreeElement *te, TreeStoreElem /* ebones only draw in editmode armature */ -static int tree_element_active_ebone(TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { EditBone *ebone= te->directdata; -// int shift= 0; // XXX if(set) { if(!(ebone->flag & BONE_HIDDEN_A)) { -// XXX if(shift) deselectall_armature(2, 0); // only clear active tag -// else deselectall_armature(0, 0); // deselect + if(set==2) ED_armature_deselectall(scene->obedit, 2, 0); // only clear active tag + else ED_armature_deselectall(scene->obedit, 0, 0); // deselect ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_ACTIVE; // flush to parent? if(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag |= BONE_TIPSEL; + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, scene->obedit); } } else { @@ -1946,78 +2103,90 @@ static int tree_element_active_ebone(TreeElement *te, TreeStoreElem *tselem, int return 0; } -static int tree_element_active_modifier(TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_modifier(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set) { if(set) { + Object *ob= (Object *)tselem->id; + + WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); + // XXX extern_set_butspace(F9KEY, 0); } return 0; } -static int tree_element_active_psys(TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_psys(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { if(set) { -// Object *ob= (Object *)tselem->id; -// ParticleSystem *psys= te->directdata; + Object *ob= (Object *)tselem->id; + + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, ob); -// XXX PE_change_act_psys(ob, psys); // XXX extern_set_butspace(F7KEY, 0); } return 0; } -static int tree_element_active_constraint(TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_constraint(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set) { if(set) { + Object *ob= (Object *)tselem->id; + + WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); // XXX extern_set_butspace(F7KEY, 0); } return 0; } -static int tree_element_active_text(Scene *scene, SpaceOops *soops, TreeElement *te, int set) +static int tree_element_active_text(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) { // XXX removed return 0; } /* generic call for ID data check or make/check active in UI */ -static int tree_element_active(Scene *scene, SpaceOops *soops, TreeElement *te, int set) +static int tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) { switch(te->idcode) { case ID_MA: - return tree_element_active_material(scene, soops, te, set); + return tree_element_active_material(C, scene, soops, te, set); case ID_WO: - return tree_element_active_world(scene, soops, te, set); + return tree_element_active_world(C, scene, soops, te, set); case ID_LA: - return tree_element_active_lamp(scene, soops, te, set); + return tree_element_active_lamp(C, scene, soops, te, set); case ID_TE: - return tree_element_active_texture(scene, soops, te, set); + return tree_element_active_texture(C, scene, soops, te, set); case ID_TXT: - return tree_element_active_text(scene, soops, te, set); + return tree_element_active_text(C, scene, soops, te, set); } return 0; } -static int tree_element_active_pose(TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_pose(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { Object *ob= (Object *)tselem->id; + Base *base= object_in_scene(ob, scene); if(set) { -// XXX if(obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); -// if(ob->flag & OB_POSEMODE) exit_posemode(); -// else enter_posemode(); + if(scene->obedit) + ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); + + if(ob->mode & OB_MODE_POSE) + ED_armature_exit_posemode(C, base); + else + ED_armature_enter_posemode(C, base); } else { - if(ob->flag & OB_POSEMODE) return 1; + if(ob->mode & OB_MODE_POSE) return 1; } return 0; } -static int tree_element_active_sequence(TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_sequence(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set) { Sequence *seq= (Sequence*) te->directdata; @@ -2031,7 +2200,7 @@ static int tree_element_active_sequence(TreeElement *te, TreeStoreElem *tselem, return(0); } -static int tree_element_active_sequence_dup(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_sequence_dup(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { Sequence *seq, *p; Editing *ed= seq_give_editing(scene, FALSE); @@ -2058,6 +2227,21 @@ static int tree_element_active_sequence_dup(Scene *scene, TreeElement *te, TreeS return(0); } +static int tree_element_active_keymap_item(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set) +{ + wmKeymapItem *kmi= te->directdata; + + if(set==0) { + if(kmi->inactive) return 0; + return 1; + } + else { + kmi->inactive= !kmi->inactive; + } + return 0; +} + + /* generic call for non-id data to make/check active in UI */ /* Context can be NULL when set==0 */ static int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, int set) @@ -2065,59 +2249,56 @@ static int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops, switch(tselem->type) { case TSE_DEFGROUP: - return tree_element_active_defgroup(scene, te, tselem, set); + return tree_element_active_defgroup(C, scene, te, tselem, set); case TSE_BONE: - return tree_element_active_bone(scene, te, tselem, set); + return tree_element_active_bone(C, scene, te, tselem, set); case TSE_EBONE: - return tree_element_active_ebone(te, tselem, set); + return tree_element_active_ebone(C, scene, te, tselem, set); case TSE_MODIFIER: - return tree_element_active_modifier(te, tselem, set); + return tree_element_active_modifier(C, te, tselem, set); case TSE_LINKED_OB: - if(set) tree_element_set_active_object(C, scene, soops, te); + if(set) tree_element_set_active_object(C, scene, soops, te, set); else if(tselem->id==(ID *)OBACT) return 1; break; case TSE_LINKED_PSYS: - return tree_element_active_psys(te, tselem, set); - break; + return tree_element_active_psys(C, scene, te, tselem, set); case TSE_POSE_BASE: - return tree_element_active_pose(te, tselem, set); - break; + return tree_element_active_pose(C, scene, te, tselem, set); case TSE_POSE_CHANNEL: - return tree_element_active_posechannel(scene, te, tselem, set); + return tree_element_active_posechannel(C, scene, te, tselem, set); case TSE_CONSTRAINT: - return tree_element_active_constraint(te, tselem, set); + return tree_element_active_constraint(C, te, tselem, set); case TSE_R_LAYER: - return tree_element_active_renderlayer(te, tselem, set); + return tree_element_active_renderlayer(C, te, tselem, set); case TSE_POSEGRP: - return tree_element_active_posegroup(scene, te, tselem, set); + return tree_element_active_posegroup(C, scene, te, tselem, set); case TSE_SEQUENCE: - return tree_element_active_sequence(te, tselem, set); - break; + return tree_element_active_sequence(C, te, tselem, set); case TSE_SEQUENCE_DUP: - return tree_element_active_sequence_dup(scene, te, tselem, set); - break; + return tree_element_active_sequence_dup(C, scene, te, tselem, set); + case TSE_KEYMAP_ITEM: + return tree_element_active_keymap_item(C, te, tselem, set); + } return 0; } -static int do_outliner_mouse_event(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, short event, float *mval) +static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int extend, float *mval) { - int shift= 0, ctrl= 0; // XXX if(mval[1]>te->ys && mval[1]<te->ys+OL_H) { TreeStoreElem *tselem= TREESTORE(te); int openclose= 0; - /* open close icon, three things to check */ - if(event==RETKEY || event==PADENTER) openclose= 1; // enter opens/closes always - else if((te->flag & TE_ICONROW)==0) { // hidden icon, no open/close - if( mval[0]>te->xs && mval[0]<te->xs+OL_X) openclose= 1; + /* open close icon */ + if((te->flag & TE_ICONROW)==0) { // hidden icon, no open/close + if( mval[0]>te->xs && mval[0]<te->xs+OL_X) + openclose= 1; } if(openclose) { - /* all below close/open? */ - if(shift) { + if(extend) { tselem->flag &= ~TSE_CLOSED; outliner_set_flag(soops, &te->subtree, TSE_CLOSED, !outliner_has_one_flag(soops, &te->subtree, TSE_CLOSED, 1)); } @@ -2126,95 +2307,66 @@ static int do_outliner_mouse_event(bContext *C, Scene *scene, ARegion *ar, Space else tselem->flag |= TSE_CLOSED; } - + return 1; } /* name and first icon */ else if(mval[0]>te->xs && mval[0]<te->xend) { - /* activate a name button? */ - if(event==LEFTMOUSE) { + /* always makes active object */ + if(tselem->type!=TSE_SEQUENCE && tselem->type!=TSE_SEQ_STRIP && tselem->type!=TSE_SEQUENCE_DUP) + tree_element_set_active_object(C, scene, soops, te, 1 + (extend!=0 && tselem->type==0)); - if (ctrl) { - if(ELEM10(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE, TSE_SCRIPT_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS)) - error("Cannot edit builtin name"); - else if(ELEM3(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) - error("Cannot edit sequence name"); - else if(tselem->id->lib) { -// XXX error_libdata(); - } else if(te->idcode == ID_LI && te->parent) { - error("Cannot edit the path of an indirectly linked library"); - } else { - tselem->flag |= TSE_TEXTBUT; - } - } else { - /* always makes active object */ - if(tselem->type!=TSE_SEQUENCE && tselem->type!=TSE_SEQ_STRIP && tselem->type!=TSE_SEQUENCE_DUP) - tree_element_set_active_object(C, scene, soops, te); - - if(tselem->type==0) { // the lib blocks - /* editmode? */ - if(te->idcode==ID_SCE) { - if(scene!=(Scene *)tselem->id) { - ED_screen_set_scene(C, (Scene *)tselem->id); - } - } - else if(ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) { -// XXX if(obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); -// else { -// enter_editmode(EM_WAITCURSOR); -// extern_set_butspace(F9KEY, 0); -// } - } else { // rest of types - tree_element_active(scene, soops, te, 1); - } - + if(tselem->type==0) { // the lib blocks + /* editmode? */ + if(te->idcode==ID_SCE) { + if(scene!=(Scene *)tselem->id) { + ED_screen_set_scene(C, (Scene *)tselem->id); } - else tree_element_type_active(C, scene, soops, te, tselem, 1); } - } - else if(event==RIGHTMOUSE) { - /* select object that's clicked on and popup context menu */ - if (!(tselem->flag & TSE_SELECTED)) { - - if ( outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1) ) - outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0); - - tselem->flag |= TSE_SELECTED; - /* redraw, same as outliner_select function */ - soops->storeflag |= SO_TREESTORE_REDRAW; -// XXX screen_swapbuffers(); + else if(ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) { + Object *obedit= CTX_data_edit_object(C); + if(obedit) + ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); + else { + ED_object_enter_editmode(C, EM_WAITCURSOR); + // XXX extern_set_butspace(F9KEY, 0); + } + } else { // rest of types + tree_element_active(C, scene, soops, te, 1); } - outliner_operation_menu(scene, ar, soops); } + else tree_element_type_active(C, scene, soops, te, tselem, 1+(extend!=0)); + return 1; } } for(te= te->subtree.first; te; te= te->next) { - if(do_outliner_mouse_event(C, scene, ar, soops, te, event, mval)) return 1; + if(do_outliner_item_activate(C, scene, ar, soops, te, extend, mval)) return 1; } return 0; } /* event can enterkey, then it opens/closes */ -static int outliner_activate_click(bContext *C, wmOperator *op, wmEvent *event) +static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event) { Scene *scene= CTX_data_scene(C); ARegion *ar= CTX_wm_region(C); - SpaceOops *soops= (SpaceOops*)CTX_wm_space_data(C); + SpaceOops *soops= CTX_wm_space_outliner(C); TreeElement *te; float fmval[2]; + int extend= RNA_boolean_get(op->ptr, "extend"); UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1); for(te= soops->tree.first; te; te= te->next) { - if(do_outliner_mouse_event(C, scene, ar, soops, te, event->type, fmval)) break; + if(do_outliner_item_activate(C, scene, ar, soops, te, extend, fmval)) break; } if(te) { - BIF_undo_push("Outliner click event"); + ED_undo_push(C, "Outliner click event"); } else { short selecting= -1; @@ -2227,10 +2379,9 @@ static int outliner_activate_click(bContext *C, wmOperator *op, wmEvent *event) /* select relevant row */ outliner_select(soops, &soops->tree, &row, &selecting); - // XXX old flag found in old code, do we still use this? - //soops->storeflag |= SO_TREESTORE_REDRAW; + soops->storeflag |= SO_TREESTORE_REDRAW; - BIF_undo_push("Outliner selection event"); + ED_undo_push(C, "Outliner selection event"); } ED_region_tag_redraw(ar); @@ -2238,12 +2389,138 @@ static int outliner_activate_click(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -void OUTLINER_OT_activate_click(wmOperatorType *ot) +void OUTLINER_OT_item_activate(wmOperatorType *ot) { - ot->name= "Activate Click"; - ot->idname= "OUTLINER_OT_activate_click"; + ot->name= "Activate Item"; + ot->idname= "OUTLINER_OT_item_activate"; - ot->invoke= outliner_activate_click; + ot->invoke= outliner_item_activate; + + ot->poll= ED_operator_outliner_active; + + RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection for activation."); +} + +/* *********** */ + +static int do_outliner_item_openclose(bContext *C, SpaceOops *soops, TreeElement *te, int all, float *mval) +{ + + if(mval[1]>te->ys && mval[1]<te->ys+OL_H) { + TreeStoreElem *tselem= TREESTORE(te); + + /* all below close/open? */ + if(all) { + tselem->flag &= ~TSE_CLOSED; + 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; + else tselem->flag |= TSE_CLOSED; + } + + return 1; + } + + for(te= te->subtree.first; te; te= te->next) { + if(do_outliner_item_openclose(C, soops, te, all, mval)) + return 1; + } + return 0; + +} + +/* event can enterkey, then it opens/closes */ +static int outliner_item_openclose(bContext *C, wmOperator *op, wmEvent *event) +{ + ARegion *ar= CTX_wm_region(C); + SpaceOops *soops= CTX_wm_space_outliner(C); + TreeElement *te; + float fmval[2]; + int all= RNA_boolean_get(op->ptr, "all"); + + UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1); + + for(te= soops->tree.first; te; te= te->next) { + if(do_outliner_item_openclose(C, soops, te, all, fmval)) + break; + } + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_item_openclose(wmOperatorType *ot) +{ + ot->name= "Open/Close Item"; + ot->idname= "OUTLINER_OT_item_openclose"; + + ot->invoke= outliner_item_openclose; + + ot->poll= ED_operator_outliner_active; + + RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items."); + +} + + +/* ********************************************** */ + +static int do_outliner_item_rename(bContext *C, ARegion *ar, SpaceOops *soops, TreeElement *te, float *mval) +{ + + if(mval[1]>te->ys && mval[1]<te->ys+OL_H) { + TreeStoreElem *tselem= TREESTORE(te); + + /* name and first icon */ + if(mval[0]>te->xs && mval[0]<te->xend) { + + if(ELEM10(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE, TSE_SCRIPT_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS)) + error("Cannot edit builtin name"); + else if(ELEM3(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) + error("Cannot edit sequence name"); + else if(tselem->id->lib) { + // XXX error_libdata(); + } else if(te->idcode == ID_LI && te->parent) { + error("Cannot edit the path of an indirectly linked library"); + } else { + tselem->flag |= TSE_TEXTBUT; + ED_region_tag_redraw(ar); + } + } + return 1; + } + + for(te= te->subtree.first; te; te= te->next) { + if(do_outliner_item_rename(C, ar, soops, te, mval)) return 1; + } + return 0; +} + +static int outliner_item_rename(bContext *C, wmOperator *op, wmEvent *event) +{ + ARegion *ar= CTX_wm_region(C); + SpaceOops *soops= CTX_wm_space_outliner(C); + TreeElement *te; + float fmval[2]; + + UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1); + + for(te= soops->tree.first; te; te= te->next) { + if(do_outliner_item_rename(C, ar, soops, te, fmval)) break; + } + + return OPERATOR_FINISHED; +} + + +void OUTLINER_OT_item_rename(wmOperatorType *ot) +{ + ot->name= "Rename Item"; + ot->idname= "OUTLINER_OT_item_rename"; + + ot->invoke= outliner_item_rename; ot->poll= ED_operator_outliner_active; } @@ -2300,53 +2577,56 @@ static TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, ID *id) return NULL; } -void outliner_show_active(Scene *scene, ARegion *ar, SpaceOops *so) +static int outliner_show_active_exec(bContext *C, wmOperator *op) { + SpaceOops *so= CTX_wm_space_outliner(C); + Scene *scene= CTX_data_scene(C); + ARegion *ar= CTX_wm_region(C); + View2D *v2d= &ar->v2d; + TreeElement *te; int xdelta, ytop; - if(OBACT == NULL) return; + // TODO: make this get this info from context instead... + if (OBACT == NULL) + return OPERATOR_CANCELLED; te= outliner_find_id(so, &so->tree, (ID *)OBACT); - if(te) { + if (te) { /* make te->ys center of view */ - ytop= (int)(te->ys + (ar->v2d.mask.ymax-ar->v2d.mask.ymin)/2); - if(ytop>0) ytop= 0; - ar->v2d.cur.ymax= (float)ytop; - ar->v2d.cur.ymin= (float)(ytop-(ar->v2d.mask.ymax-ar->v2d.mask.ymin)); + ytop= (int)(te->ys + (v2d->mask.ymax - v2d->mask.ymin)/2); + if (ytop>0) ytop= 0; + + v2d->cur.ymax= (float)ytop; + v2d->cur.ymin= (float)(ytop-(v2d->mask.ymax - v2d->mask.ymin)); /* make te->xs ==> te->xend center of view */ - xdelta = (int)(te->xs - ar->v2d.cur.xmin); - ar->v2d.cur.xmin += xdelta; - ar->v2d.cur.xmax += xdelta; + xdelta = (int)(te->xs - v2d->cur.xmin); + v2d->cur.xmin += xdelta; + v2d->cur.xmax += xdelta; so->storeflag |= SO_TREESTORE_REDRAW; } + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; } -void outliner_show_selected(Scene *scene, ARegion *ar, SpaceOops *so) +void OUTLINER_OT_show_active(wmOperatorType *ot) { - TreeElement *te; - int xdelta, ytop; + /* identifiers */ + ot->name= "Show Active"; + ot->idname= "OUTLINER_OT_show_active"; + ot->description= "Adjust the view so that the active Object is shown centered."; - te= outliner_find_id(so, &so->tree, (ID *)OBACT); - if(te) { - /* make te->ys center of view */ - ytop= (int)(te->ys + (ar->v2d.mask.ymax-ar->v2d.mask.ymin)/2); - if(ytop>0) ytop= 0; - ar->v2d.cur.ymax= (float)ytop; - ar->v2d.cur.ymin= (float)(ytop-(ar->v2d.mask.ymax-ar->v2d.mask.ymin)); - - /* make te->xs ==> te->xend center of view */ - xdelta = (int)(te->xs - ar->v2d.cur.xmin); - ar->v2d.cur.xmin += xdelta; - ar->v2d.cur.xmax += xdelta; - - so->storeflag |= SO_TREESTORE_REDRAW; - } + /* callbacks */ + ot->exec= outliner_show_active_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } - /* find next element that has this name */ static TreeElement *outliner_find_named(SpaceOops *soops, ListBase *lb, char *name, int flags, TreeElement *prev, int *prevFound) { @@ -2486,6 +2766,7 @@ void outliner_find_panel(Scene *scene, ARegion *ar, SpaceOops *soops, int again, } } +/* helper function for tree_element_shwo_hierarchy() - recursively checks whether subtrees have any objects*/ static int subtree_has_objects(SpaceOops *soops, ListBase *lb) { TreeElement *te; @@ -2499,6 +2780,7 @@ static int subtree_has_objects(SpaceOops *soops, ListBase *lb) return 0; } +/* recursive helper function for Show Hierarchy operator */ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase *lb) { TreeElement *te; @@ -2519,19 +2801,38 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase } } else tselem->flag |= TSE_CLOSED; - + if(tselem->flag & TSE_CLOSED); else tree_element_show_hierarchy(scene, soops, &te->subtree); } - } /* show entire object level hierarchy */ -void outliner_show_hierarchy(Scene *scene, SpaceOops *soops) +static int outliner_show_hierarchy_exec(bContext *C, wmOperator *op) { + SpaceOops *soops= CTX_wm_space_outliner(C); + ARegion *ar= CTX_wm_region(C); + Scene *scene= CTX_data_scene(C); + /* recursively open/close levels */ tree_element_show_hierarchy(scene, soops, &soops->tree); - BIF_undo_push("Outliner show hierarchy"); + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_show_hierarchy(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Show Hierarchy"; + ot->idname= "OUTLINER_OT_show_hierarchy"; + ot->description= "Open all object entries and close all others."; + + /* callbacks */ + ot->exec= outliner_show_hierarchy_exec; + ot->poll= ED_operator_outliner_active; // TODO: shouldn't be allowed in RNA views... + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } void outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting) @@ -2591,13 +2892,10 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb, tselem= TREESTORE(te); if(tselem->flag & TSE_SELECTED) { if(tselem->type) { - if(tselem->type==TSE_SEQUENCE) - *datalevel= TSE_SEQUENCE; - else if(tselem->type==TSE_SEQ_STRIP) - *datalevel= TSE_SEQ_STRIP; - else if(tselem->type==TSE_SEQUENCE_DUP) - *datalevel= TSE_SEQUENCE_DUP; - else if(*datalevel!=tselem->type) *datalevel= -1; + if(*datalevel==0) + *datalevel= tselem->type; + else if(*datalevel!=tselem->type) + *datalevel= -1; } else { int idcode= GS(tselem->id->name); @@ -2627,7 +2925,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb, } } -static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +static void unlink_material_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { Material **matar=NULL; int a, totcol=0; @@ -2661,7 +2959,7 @@ static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreEl } } -static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +static void unlink_texture_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { MTex **mtex= NULL; int a; @@ -2690,7 +2988,7 @@ static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreEle } } -static void unlink_group_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +static void unlink_group_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { Group *group= (Group *)tselem->id; @@ -2706,8 +3004,8 @@ static void unlink_group_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem } } -static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb, - void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *)) +static void outliner_do_libdata_operation(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, + void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *)) { TreeElement *te; TreeStoreElem *tselem; @@ -2717,20 +3015,19 @@ static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb, if(tselem->flag & TSE_SELECTED) { if(tselem->type==0) { TreeStoreElem *tsep= TREESTORE(te->parent); - operation_cb(te, tsep, tselem); + operation_cb(C, scene, te, tsep, tselem); } } if((tselem->flag & TSE_CLOSED)==0) { - outliner_do_libdata_operation(soops, &te->subtree, operation_cb); + outliner_do_libdata_operation(C, scene, soops, &te->subtree, operation_cb); } } } /* */ -static void object_select_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +static void object_select_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { - Scene *scene= NULL; // XXX Base *base= (Base *)te->directdata; if(base==NULL) base= object_in_scene((Object *)tselem->id, scene); @@ -2740,9 +3037,8 @@ static void object_select_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem } } -static void object_deselect_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +static void object_deselect_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { - Scene *scene= NULL; Base *base= (Base *)te->directdata; if(base==NULL) base= object_in_scene((Object *)tselem->id, scene); @@ -2752,28 +3048,27 @@ static void object_deselect_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreEl } } -static void object_delete_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +static void object_delete_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { - Scene *scene= NULL; Base *base= (Base *)te->directdata; - if(base==NULL) base= object_in_scene((Object *)tselem->id, scene); + if(base==NULL) + base= object_in_scene((Object *)tselem->id, scene); if(base) { // check also library later -// XXX if(obedit==base->object) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); + if(scene->obedit==base->object) + ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); - if(base==BASACT) { - G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE); -// XXX setcursor_space(SPACE_VIEW3D, CURSOR_STD); - } - -// XXX free_and_unlink_base(base); + ED_base_object_free_and_unlink(scene, base); te->directdata= NULL; tselem->id= NULL; } + + WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); + } -static void id_local_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +static void id_local_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { if(tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) { tselem->id->lib= NULL; @@ -2782,9 +3077,8 @@ static void id_local_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tse } } -static void group_linkobs2scene_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +static void group_linkobs2scene_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { - Scene *scene= NULL; Group *group= (Group *)tselem->id; GroupObject *gob; Base *base; @@ -2807,8 +3101,8 @@ static void group_linkobs2scene_cb(TreeElement *te, TreeStoreElem *tsep, TreeSto } } -static void outliner_do_object_operation(Scene *scene, SpaceOops *soops, ListBase *lb, - void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *)) +static void outliner_do_object_operation(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, + void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *)) { TreeElement *te; TreeStoreElem *tselem; @@ -2820,18 +3114,20 @@ static void outliner_do_object_operation(Scene *scene, SpaceOops *soops, ListBas // when objects selected in other scenes... dunno if that should be allowed Scene *sce= (Scene *)outliner_search_back(soops, te, ID_SCE); if(sce && scene != sce) { -// XXX ED_screen_set_scene(C, sce); + ED_screen_set_scene(C, sce); } - operation_cb(te, NULL, tselem); + operation_cb(C, scene, te, NULL, tselem); } } if((tselem->flag & TSE_CLOSED)==0) { - outliner_do_object_operation(scene, soops, &te->subtree, operation_cb); + outliner_do_object_operation(C, scene, soops, &te->subtree, operation_cb); } } } +/* ******************************************** */ + static void pchan_cb(int event, TreeElement *te, TreeStoreElem *tselem) { bPoseChannel *pchan= (bPoseChannel *)te->directdata; @@ -2907,145 +3203,387 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li } } -void outliner_del(Scene *scene, ARegion *ar, SpaceOops *soops) +void outliner_del(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops) +{ + + if(soops->outlinevis==SO_SEQUENCE) + ;// del_seq(); + else { + outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_cb); + DAG_scene_sort(scene); + ED_undo_push(C, "Delete Objects"); + } +} + +/* **************************************** */ + +static EnumPropertyItem prop_object_op_types[] = { + {1, "SELECT", 0, "Select", ""}, + {2, "DESELECT", 0, "Deselect", ""}, + {4, "DELETE", 0, "Delete", ""}, + {6, "TOGVIS", 0, "Toggle Visible", ""}, + {7, "TOGSEL", 0, "Toggle Selectable", ""}, + {8, "TOGREN", 0, "Toggle Renderable", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static int outliner_object_operation_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SpaceOops *soops= CTX_wm_space_outliner(C); + int event; + char *str= NULL; + + /* check for invalid states */ + if (soops == NULL) + return OPERATOR_CANCELLED; + + event= RNA_enum_get(op->ptr, "type"); + + if(event==1) { + Scene *sce= scene; // to be able to delete, scenes are set... + outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_cb); + if(scene != sce) { + ED_screen_set_scene(C, sce); + } + + str= "Select Objects"; + } + else if(event==2) { + outliner_do_object_operation(C, scene, soops, &soops->tree, object_deselect_cb); + str= "Deselect Objects"; + } + else if(event==4) { + outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_cb); + DAG_scene_sort(scene); + str= "Delete Objects"; + } + else if(event==5) { /* disabled, see above (ton) */ + outliner_do_object_operation(C, scene, soops, &soops->tree, id_local_cb); + str= "Localized Objects"; + } + else if(event==6) { + outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb); + str= "Toggle Visibility"; + } + else if(event==7) { + outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_selectability_cb); + str= "Toggle Selectability"; + } + else if(event==8) { + outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb); + str= "Toggle Renderability"; + } + + WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); + + ED_undo_push(C, str); + + return OPERATOR_FINISHED; +} + + +void OUTLINER_OT_object_operation(wmOperatorType *ot) { + /* identifiers */ + ot->name= "Outliner Object Operation"; + ot->idname= "OUTLINER_OT_object_operation"; + ot->description= ""; -// XXX if(soops->outlinevis==SO_SEQUENCE) -// del_seq(); -// else { -// outliner_do_object_operation(scene, soops, &soops->tree, object_delete_cb); -// DAG_scene_sort(scene); -// BIF_undo_push("Delete Objects"); -// } + /* callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= outliner_object_operation_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= 0; + + RNA_def_enum(ot->srna, "type", prop_object_op_types, 0, "Object Operation", ""); } +/* **************************************** */ + +static EnumPropertyItem prop_group_op_types[] = { + {1, "UNLINK", 0, "Unlink", ""}, + {2, "LOCAL", 0, "Make Local", ""}, + {3, "LINK", 0, "Link Group Objects to Scene", ""}, + {0, NULL, 0, NULL, NULL} +}; -void outliner_operation_menu(Scene *scene, ARegion *ar, SpaceOops *soops) +static int outliner_group_operation_exec(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); + SpaceOops *soops= CTX_wm_space_outliner(C); + int event; + + /* check for invalid states */ + if (soops == NULL) + return OPERATOR_CANCELLED; + + event= RNA_enum_get(op->ptr, "type"); + + if(event==1) { + outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_group_cb); + ED_undo_push(C, "Unlink group"); + } + else if(event==2) { + outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb); + ED_undo_push(C, "Localized Data"); + } + else if(event==3) { + outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_linkobs2scene_cb); + ED_undo_push(C, "Link Group Objects to Scene"); + } + + + WM_event_add_notifier(C, NC_GROUP, NULL); + + return OPERATOR_FINISHED; +} + + +void OUTLINER_OT_group_operation(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Outliner Group Operation"; + ot->idname= "OUTLINER_OT_group_operation"; + ot->description= ""; + + /* callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= outliner_group_operation_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= 0; + + RNA_def_enum(ot->srna, "type", prop_group_op_types, 0, "Group Operation", ""); +} + +/* **************************************** */ + +static EnumPropertyItem prop_id_op_types[] = { + {1, "UNLINK", 0, "Unlink", ""}, + {2, "LOCAL", 0, "Make Local", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static int outliner_id_operation_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SpaceOops *soops= CTX_wm_space_outliner(C); int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0; + int event; + + /* check for invalid states */ + if (soops == NULL) + return OPERATOR_CANCELLED; set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); - if(scenelevel) { - if(objectlevel || datalevel || idlevel) error("Mixed selection"); - else pupmenu("Scene Operations%t|Delete"); + event= RNA_enum_get(op->ptr, "type"); + + if(event==1) { + switch(idlevel) { + case ID_MA: + outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_material_cb); + ED_undo_push(C, "Unlink material"); + break; + case ID_TE: + outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_texture_cb); + ED_undo_push(C, "Unlink texture"); + break; + default: + BKE_report(op->reports, RPT_WARNING, "Not Yet"); + } } - else if(objectlevel) { - short event= pupmenu("Select%x1|Deselect%x2|Delete%x4|Toggle Visible%x6|Toggle Selectable%x7|Toggle Renderable%x8"); /* make local: does not work... it doesn't set lib_extern flags... so data gets lost */ + else if(event==2) { + outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb); + ED_undo_push(C, "Localized Data"); + } + + /* wrong notifier still... */ + WM_event_add_notifier(C, NC_OBJECT, NULL); + + return OPERATOR_FINISHED; +} + + +void OUTLINER_OT_id_operation(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Outliner ID data Operation"; + ot->idname= "OUTLINER_OT_id_operation"; + ot->description= ""; + + /* callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= outliner_id_operation_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= 0; + + RNA_def_enum(ot->srna, "type", prop_id_op_types, 0, "ID data Operation", ""); +} + +/* **************************************** */ + +static EnumPropertyItem prop_data_op_types[] = { + {1, "SELECT", 0, "Select", ""}, + {2, "DESELECT", 0, "Deselect", ""}, + {3, "HIDE", 0, "Hide", ""}, + {4, "UNHIDE", 0, "Unhide", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static int outliner_data_operation_exec(bContext *C, wmOperator *op) +{ + SpaceOops *soops= CTX_wm_space_outliner(C); + int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0; + int event; + + /* check for invalid states */ + if (soops == NULL) + return OPERATOR_CANCELLED; + + event= RNA_enum_get(op->ptr, "type"); + set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); + + if(datalevel==TSE_POSE_CHANNEL) { if(event>0) { - char *str=""; - - if(event==1) { - Scene *sce= scene; // to be able to delete, scenes are set... - outliner_do_object_operation(scene, soops, &soops->tree, object_select_cb); - if(scene != sce) { -// XXX ED_screen_set_scene(C, sce); - } - - str= "Select Objects"; - } - else if(event==2) { - outliner_do_object_operation(scene, soops, &soops->tree, object_deselect_cb); - str= "Deselect Objects"; - } - else if(event==4) { - outliner_do_object_operation(scene, soops, &soops->tree, object_delete_cb); - DAG_scene_sort(scene); - str= "Delete Objects"; - } - else if(event==5) { /* disabled, see above (ton) */ - outliner_do_object_operation(scene, soops, &soops->tree, id_local_cb); - str= "Localized Objects"; - } - else if(event==6) { - outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_visibility_cb); - str= "Toggle Visibility"; - } - else if(event==7) { - outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_selectability_cb); - str= "Toggle Selectability"; - } - else if(event==8) { - outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_renderability_cb); - str= "Toggle Renderability"; - } - - BIF_undo_push(str); + outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb); + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); + ED_undo_push(C, "PoseChannel operation"); } } - else if(idlevel) { - if(idlevel==-1 || datalevel) error("Mixed selection"); - else { - short event; - if (idlevel==ID_GR) - event = pupmenu("Unlink %x1|Make Local %x2|Link Group Objects to Scene%x3"); - else - event = pupmenu("Unlink %x1|Make Local %x2"); + else if(datalevel==TSE_BONE) { + if(event>0) { + outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb); + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); + ED_undo_push(C, "Bone operation"); + } + } + else if(datalevel==TSE_EBONE) { + if(event>0) { + outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb); + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); + ED_undo_push(C, "EditBone operation"); + } + } + else if(datalevel==TSE_SEQUENCE) { + if(event>0) { + outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb); + } + } + + return OPERATOR_FINISHED; +} + + +void OUTLINER_OT_data_operation(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Outliner Data Operation"; + ot->idname= "OUTLINER_OT_data_operation"; + ot->description= ""; + + /* callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= outliner_data_operation_exec; + ot->poll= ED_operator_outliner_active; + + ot->flag= 0; + + RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", ""); +} + + +/* ******************** */ + + +static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, wmEvent *event, float *mval) +{ + + if(mval[1]>te->ys && mval[1]<te->ys+OL_H) { + int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0; + TreeStoreElem *tselem= TREESTORE(te); + + /* select object that's clicked on and popup context menu */ + if (!(tselem->flag & TSE_SELECTED)) { + if ( outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1) ) + outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0); - if(event==1) { - switch(idlevel) { - case ID_MA: - outliner_do_libdata_operation(soops, &soops->tree, unlink_material_cb); - BIF_undo_push("Unlink material"); - break; - case ID_TE: - outliner_do_libdata_operation(soops, &soops->tree, unlink_texture_cb); - BIF_undo_push("Unlink texture"); - break; - case ID_GR: - outliner_do_libdata_operation(soops, &soops->tree, unlink_group_cb); - BIF_undo_push("Unlink group"); - break; - default: - error("Not yet..."); - } - } - else if(event==2) { - outliner_do_libdata_operation(soops, &soops->tree, id_local_cb); - BIF_undo_push("Localized Data"); + tselem->flag |= TSE_SELECTED; + /* redraw, same as outliner_select function */ + soops->storeflag |= SO_TREESTORE_REDRAW; + ED_region_tag_redraw(ar); + } + + set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); + + if(scenelevel) { + //if(objectlevel || datalevel || idlevel) error("Mixed selection"); + //else pupmenu("Scene Operations%t|Delete"); + } + else if(objectlevel) { + WM_operator_name_call(C, "OUTLINER_OT_object_operation", WM_OP_INVOKE_REGION_WIN, NULL); + } + else if(idlevel) { + if(idlevel==-1 || datalevel) error("Mixed selection"); + else { + if (idlevel==ID_GR) + WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL); + else + WM_operator_name_call(C, "OUTLINER_OT_id_operation", WM_OP_INVOKE_REGION_WIN, NULL); } - else if(event==3 && idlevel==ID_GR) { - outliner_do_libdata_operation(soops, &soops->tree, group_linkobs2scene_cb); - BIF_undo_push("Link Group Objects to Scene"); + } + else if(datalevel) { + if(datalevel==-1) error("Mixed selection"); + else { + WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL); } } + + return 1; } - else if(datalevel) { - if(datalevel==-1) error("Mixed selection"); - else { - if(datalevel==TSE_POSE_CHANNEL) { - short event= pupmenu("PoseChannel Operations%t|Select%x1|Deselect%x2|Hide%x3|Unhide%x4"); - if(event>0) { - outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb); - BIF_undo_push("PoseChannel operation"); - } - } - else if(datalevel==TSE_BONE) { - short event= pupmenu("Bone Operations%t|Select%x1|Deselect%x2|Hide%x3|Unhide%x4"); - if(event>0) { - outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb); - BIF_undo_push("Bone operation"); - } - } - else if(datalevel==TSE_EBONE) { - short event= pupmenu("EditBone Operations%t|Select%x1|Deselect%x2|Hide%x3|Unhide%x4"); - if(event>0) { - outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb); - BIF_undo_push("EditBone operation"); - } - } - else if(datalevel==TSE_SEQUENCE) { - short event= pupmenu("Sequence Operations %t|Select %x1"); - if(event>0) { - outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb); - } - } + + for(te= te->subtree.first; te; te= te->next) { + if(do_outliner_operation_event(C, scene, ar, soops, te, event, mval)) + return 1; + } + return 0; +} - } + +static int outliner_operation(bContext *C, wmOperator *op, wmEvent *event) +{ + Scene *scene= CTX_data_scene(C); + ARegion *ar= CTX_wm_region(C); + SpaceOops *soops= CTX_wm_space_outliner(C); + TreeElement *te; + float fmval[2]; + + UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1); + + for(te= soops->tree.first; te; te= te->next) { + if(do_outliner_operation_event(C, scene, ar, soops, te, event, fmval)) break; } + + return OPERATOR_FINISHED; } +/* Menu only! Calls other operators */ +void OUTLINER_OT_operation(wmOperatorType *ot) +{ + ot->name= "Execute Operation"; + ot->idname= "OUTLINER_OT_operation"; + + ot->invoke= outliner_operation; + + ot->poll= ED_operator_outliner_active; +} + + + /* ***************** ANIMATO OPERATIONS ********************************** */ /* KeyingSet and Driver Creation - Helper functions */ @@ -3054,7 +3592,7 @@ static int ed_operator_outliner_datablocks_active(bContext *C) { ScrArea *sa= CTX_wm_area(C); if ((sa) && (sa->spacetype==SPACE_OUTLINER)) { - SpaceOops *so= (SpaceOops *)CTX_wm_space_data(C); + SpaceOops *so= CTX_wm_space_outliner(C); return (so->outlinevis == SO_DATABLOCKS); } return 0; @@ -3118,7 +3656,7 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle } else if(RNA_property_type(prop) == PROP_COLLECTION) { char buf[128], *name; - + temnext= (TreeElement*)(ld->next->data); tsenext= TREESTORE(temnext); @@ -3181,7 +3719,7 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle /* item is part of an array, so must set the array_index */ *array_index= te->index; } - else if (RNA_property_array_length(prop)) { + else if (RNA_property_array_length(ptr, prop)) { /* entire array was selected, so keyframe all */ *flag |= KSP_FLAG_WHOLE_ARRAY; } @@ -3239,7 +3777,7 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, short m case DRIVERS_EDITMODE_ADD: { /* add a new driver with the information obtained (only if valid) */ - ANIM_add_driver(id, path, array_index, flag); + ANIM_add_driver(id, path, array_index, flag, DRIVER_TYPE_AVERAGE); } break; case DRIVERS_EDITMODE_REMOVE: @@ -3267,7 +3805,7 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, short m static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op) { - SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C); + SpaceOops *soutliner= CTX_wm_space_outliner(C); /* check for invalid states */ if (soutliner == NULL) @@ -3302,7 +3840,7 @@ void OUTLINER_OT_drivers_add(wmOperatorType *ot) static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op) { - SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C); + SpaceOops *soutliner= CTX_wm_space_outliner(C); /* check for invalid states */ if (soutliner == NULL) @@ -3361,7 +3899,7 @@ static KeyingSet *verify_active_keyingset(Scene *scene, short add) /* add if none found */ // XXX the default settings have yet to evolve if ((add) && (ks==NULL)) { - ks= BKE_keyingset_add(&scene->keyingsets, "Keying Set", KEYINGSET_ABSOLUTE, 0); + ks= BKE_keyingset_add(&scene->keyingsets, NULL, KEYINGSET_ABSOLUTE, 0); scene->active_keyingset= BLI_countlist(&scene->keyingsets); } @@ -3386,7 +3924,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa short groupmode= KSP_GROUP_KSNAME; /* check if RNA-property described by this selected element is an animateable prop */ - if ((tselem->type == TSE_RNA_PROPERTY) && RNA_property_animateable(&te->rnaptr, te->directdata)) { + if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) && RNA_property_animateable(&te->rnaptr, te->directdata)) { /* get id + path + index info from the selected element */ tree_element_to_path(soops, te, tselem, &id, &path, &array_index, &flag, &groupmode); @@ -3423,8 +3961,6 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa /* free path, since it had to be generated */ MEM_freeN(path); } - - } /* go over sub-tree */ @@ -3437,7 +3973,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op) { - SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C); + SpaceOops *soutliner= CTX_wm_space_outliner(C); Scene *scene= CTX_data_scene(C); KeyingSet *ks= verify_active_keyingset(scene, 1); @@ -3477,7 +4013,7 @@ void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot) static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *op) { - SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C); + SpaceOops *soutliner= CTX_wm_space_outliner(C); Scene *scene= CTX_data_scene(C); KeyingSet *ks= verify_active_keyingset(scene, 1); @@ -3518,6 +4054,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx case TSE_NLA: UI_icon_draw(x, y, ICON_NLA); break; + case TSE_NLA_TRACK: + UI_icon_draw(x, y, ICON_NLA); break; // XXX case TSE_NLA_ACTION: UI_icon_draw(x, y, ICON_ACTION); break; case TSE_DEFGROUP_BASE: @@ -3620,13 +4158,13 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen case TSE_POSEGRP_BASE: UI_icon_draw(x, y, ICON_VERTEXSEL); break; case TSE_SEQUENCE: - if((te->idcode==SEQ_MOVIE) || (te->idcode==SEQ_MOVIE_AND_HD_SOUND)) + if(te->idcode==SEQ_MOVIE) UI_icon_draw(x, y, ICON_SEQUENCE); else if(te->idcode==SEQ_META) UI_icon_draw(x, y, ICON_DOT); else if(te->idcode==SEQ_SCENE) UI_icon_draw(x, y, ICON_SCENE); - else if((te->idcode==SEQ_RAM_SOUND) || (te->idcode==SEQ_HD_SOUND)) + else if(te->idcode==SEQ_SOUND) UI_icon_draw(x, y, ICON_SOUND); else if(te->idcode==SEQ_IMAGE) UI_icon_draw(x, y, ICON_IMAGE_COL); @@ -3734,7 +4272,7 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen } } -static void outliner_draw_iconrow(Scene *scene, SpaceOops *soops, ListBase *lb, int level, int *offsx, int ys) +static void outliner_draw_iconrow(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, int level, int *offsx, int ys) { TreeElement *te; TreeStoreElem *tselem; @@ -3751,7 +4289,7 @@ static void outliner_draw_iconrow(Scene *scene, SpaceOops *soops, ListBase *lb, if(tselem->type==0) { if(te->idcode==ID_OB) active= (OBACT==(Object *)tselem->id); else if(scene->obedit && scene->obedit->data==tselem->id) active= 1; // XXX use context? - else active= tree_element_active(scene, soops, te, 0); + else active= tree_element_active(C, scene, soops, te, 0); } else active= tree_element_type_active(NULL, scene, soops, te, tselem, 0); @@ -3773,12 +4311,12 @@ static void outliner_draw_iconrow(Scene *scene, SpaceOops *soops, ListBase *lb, /* this tree element always has same amount of branches, so dont draw */ if(tselem->type!=TSE_R_LAYER) - outliner_draw_iconrow(scene, soops, &te->subtree, level+1, offsx, ys); + outliner_draw_iconrow(C, scene, soops, &te->subtree, level+1, offsx, ys); } } -static void outliner_draw_tree_element(Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty) +static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty) { TreeElement *ten; TreeStoreElem *tselem; @@ -3816,12 +4354,12 @@ static void outliner_draw_tree_element(Scene *scene, ARegion *ar, SpaceOops *soo } } -// XXX context? else if(obedit && obedit->data==tselem->id) { -// glColor4ub(255, 255, 255, 100); -// active= 2; -// } + else if(scene->obedit && scene->obedit->data==tselem->id) { + glColor4ub(255, 255, 255, 100); + active= 2; + } else { - if(tree_element_active(scene, soops, te, 0)) { + if(tree_element_active(C, scene, soops, te, 0)) { glColor4ub(220, 220, 255, 100); active= 2; } @@ -3900,7 +4438,7 @@ static void outliner_draw_tree_element(Scene *scene, ARegion *ar, SpaceOops *soo glEnable(GL_BLEND); glPixelTransferf(GL_ALPHA_SCALE, 0.5); - outliner_draw_iconrow(scene, soops, &te->subtree, 0, &tempx, *starty+2); + outliner_draw_iconrow(C, scene, soops, &te->subtree, 0, &tempx, *starty+2); glPixelTransferf(GL_ALPHA_SCALE, 1.0); glDisable(GL_BLEND); @@ -3917,7 +4455,7 @@ static void outliner_draw_tree_element(Scene *scene, ARegion *ar, SpaceOops *soo if((tselem->flag & TSE_CLOSED)==0) { for(ten= te->subtree.first; ten; ten= ten->next) { - outliner_draw_tree_element(scene, ar, soops, ten, startx+OL_X, starty); + outliner_draw_tree_element(C, scene, ar, soops, ten, startx+OL_X, starty); } } } @@ -3996,20 +4534,12 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, } -static void outliner_draw_tree(Scene *scene, ARegion *ar, SpaceOops *soops) +static void outliner_draw_tree(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops) { TreeElement *te; int starty, startx; float col[4]; - -#if 0 // XXX was #ifdef INTERNATIONAL - /* Maybe the INTERNATIONAL was really for check about freetype2 ? - * anyway I think that we can remove this now - Diego - */ - FTF_SetFontSize('l'); - BIF_SetScale(1.0); -#endif - + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) { @@ -4036,7 +4566,7 @@ static void outliner_draw_tree(Scene *scene, ARegion *ar, SpaceOops *soops) starty= (int)ar->v2d.tot.ymax-OL_H; startx= 0; for(te= soops->tree.first; te; te= te->next) { - outliner_draw_tree_element(scene, ar, soops, te, startx, &starty); + outliner_draw_tree_element(C, scene, ar, soops, te, startx, &starty); } } @@ -4111,6 +4641,7 @@ static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2) } } } + WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); } @@ -4132,16 +4663,18 @@ static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2) } } } + WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); } static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2) { + WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, poin); } static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *poin2) { - /* XXX redraws */ + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, poin); } static void restrictbutton_modifier_cb(bContext *C, void *poin, void *poin2) @@ -4149,29 +4682,43 @@ static void restrictbutton_modifier_cb(bContext *C, void *poin, void *poin2) Scene *scene = (Scene *)poin; Object *ob = (Object *)poin2; - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); object_handle_update(scene, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); } static void restrictbutton_bone_cb(bContext *C, void *poin, void *poin2) { - /* XXX redraws */ + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); } -static void namebutton_cb(bContext *C, void *tep, void *oldnamep) +static void namebutton_cb(bContext *C, void *tsep, char *oldname) { - SpaceOops *soops= NULL; // XXXcurarea->spacedata.first; - Scene *scene= NULL; // XXX + SpaceOops *soops= CTX_wm_space_outliner(C); + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); TreeStore *ts= soops->treestore; - TreeElement *te= tep; + TreeStoreElem *tselem= tsep; - if(ts && te) { - TreeStoreElem *tselem= TREESTORE(te); + if(ts && tselem) { + TreeElement *te= outliner_find_tse(soops, tselem); if(tselem->type==0) { test_idbutton(tselem->id->name+2); // library.c, unique name and alpha sort + switch(GS(tselem->id->name)) { + case ID_MA: + WM_event_add_notifier(C, NC_MATERIAL, NULL); break; + case ID_TE: + WM_event_add_notifier(C, NC_TEXTURE, NULL); break; + case ID_IM: + WM_event_add_notifier(C, NC_IMAGE, NULL); break; + case ID_SCE: + WM_event_add_notifier(C, NC_SCENE, NULL); break; + default: + WM_event_add_notifier(C, NC_MATERIAL, NULL); break; + } /* Check the library target exists */ if (te->idcode == ID_LI) { char expanded[FILE_MAXDIR + FILE_MAXFILE]; @@ -4199,8 +4746,9 @@ static void namebutton_cb(bContext *C, void *tep, void *oldnamep) /* restore bone name */ BLI_strncpy(newname, ebone->name, 32); - BLI_strncpy(ebone->name, oldnamep, 32); -// XXX armature_bone_rename(obedit->data, oldnamep, newname); + BLI_strncpy(ebone->name, oldname, 32); + ED_armature_bone_rename(obedit->data, oldname, newname); + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, OBACT); } } break; @@ -4212,13 +4760,14 @@ static void namebutton_cb(bContext *C, void *tep, void *oldnamep) char newname[32]; // always make current object active - tree_element_set_active_object(C, scene, soops, te); + tree_element_set_active_object(C, scene, soops, te, 1); ob= OBACT; /* restore bone name */ BLI_strncpy(newname, bone->name, 32); - BLI_strncpy(bone->name, oldnamep, 32); -// XXX armature_bone_rename(ob->data, oldnamep, newname); + BLI_strncpy(bone->name, oldname, 32); + ED_armature_bone_rename(ob->data, oldname, newname); + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); } break; case TSE_POSE_CHANNEL: @@ -4228,13 +4777,14 @@ static void namebutton_cb(bContext *C, void *tep, void *oldnamep) char newname[32]; // always make current object active - tree_element_set_active_object(C, scene, soops, te); + tree_element_set_active_object(C, scene, soops, te, 1); ob= OBACT; /* restore bone name */ BLI_strncpy(newname, pchan->name, 32); - BLI_strncpy(pchan->name, oldnamep, 32); -// XXX armature_bone_rename(ob->data, oldnamep, newname); + BLI_strncpy(pchan->name, oldname, 32); + ED_armature_bone_rename(ob->data, oldname, newname); + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); } break; case TSE_POSEGRP: @@ -4243,6 +4793,7 @@ static void namebutton_cb(bContext *C, void *tep, void *oldnamep) bActionGroup *grp= te->directdata; BLI_uniquename(&ob->pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), 32); + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); } break; case TSE_R_LAYER: @@ -4258,7 +4809,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar TreeElement *te; TreeStoreElem *tselem; Object *ob = NULL; - + for(te= lb->first; te; te= te->next) { tselem= TREESTORE(te); if(te->ys >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { @@ -4277,7 +4828,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar bt= uiDefIconButBitS(block, ICONTOG, OB_RESTRICT_RENDER, 0, ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (short)te->ys, 17, OL_H-1, &(ob->restrictflag), 0, 0, 0, 0, "Restrict/Allow renderability"); - uiButSetFunc(bt, restrictbutton_rend_cb, NULL, NULL); + uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -4287,7 +4838,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar bt= uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT-1, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, te->directdata, 0, 0, 0, 0, "Render this RenderLayer"); - uiButSetFunc(bt, restrictbutton_r_lay_cb, NULL, NULL); + uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -4298,13 +4849,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar /* NOTE: tselem->nr is short! */ bt= uiDefIconButBitI(block, ICONTOG, tselem->nr, 0, ICON_CHECKBOX_HLT-1, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, layflag, 0, 0, 0, 0, "Render this Pass"); - uiButSetFunc(bt, restrictbutton_r_lay_cb, NULL, NULL); + uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); layflag++; /* is lay_xor */ if(ELEM6(tselem->nr, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT, SCE_PASS_RADIO)) bt= uiDefIconButBitI(block, TOG, tselem->nr, 0, (*layflag & tselem->nr)?ICON_DOT:ICON_BLANK1, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined"); - uiButSetFunc(bt, restrictbutton_r_lay_cb, NULL, NULL); + uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -4393,7 +4944,271 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa } } -static void outliner_buttons(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb) +static void operator_call_cb(struct bContext *C, void *arg_kmi, void *arg2) +{ + wmOperatorType *ot= arg2; + wmKeymapItem *kmi= arg_kmi; + + if(ot) + BLI_strncpy(kmi->idname, ot->idname, OP_MAX_TYPENAME); +} + +static void operator_search_cb(const struct bContext *C, void *arg_kmi, char *str, uiSearchItems *items) +{ + wmOperatorType *ot = WM_operatortype_first(); + + for(; ot; ot= ot->next) { + + if(BLI_strcasestr(ot->idname, str)) { + char name[OP_MAX_TYPENAME]; + + /* display name for menu */ + WM_operator_py_idname(name, ot->idname); + + if(0==uiSearchItemAdd(items, name, ot, 0)) + break; + } + } +} + +/* operator Search browse menu, open */ +static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi) +{ + static char search[OP_MAX_TYPENAME]; + wmEvent event; + wmWindow *win= CTX_wm_window(C); + wmKeymapItem *kmi= arg_kmi; + wmOperatorType *ot= WM_operatortype_find(kmi->idname, 0); + uiBlock *block; + uiBut *but; + + /* clear initial search string, then all items show */ + search[0]= 0; + + block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); + uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1); + + /* fake button, it holds space for search items */ + uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, ""); + uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot); + + uiBoundsBlock(block, 6); + uiBlockSetDirection(block, UI_DOWN); + uiEndBlock(C, block); + + event= *(win->eventstate); /* XXX huh huh? make api call */ + event.type= EVT_BUT_OPEN; + event.val= KM_PRESS; + event.customdata= but; + event.customdatafree= FALSE; + wm_event_add(win, &event); + + return block; +} + +#define OL_KM_KEYBOARD 0 +#define OL_KM_MOUSE 1 +#define OL_KM_TWEAK 2 +#define OL_KM_SPECIALS 3 + +static short keymap_menu_type(short type) +{ + if(ISKEYBOARD(type)) return OL_KM_KEYBOARD; + if(WM_key_event_is_tweak(type)) return OL_KM_TWEAK; + if(type >= LEFTMOUSE && type <= WHEELOUTMOUSE) return OL_KM_MOUSE; +// return OL_KM_SPECIALS; + return 0; +} + +static char *keymap_type_menu(void) +{ + static char string[500]; + static char formatstr[] = "|%s %%x%d"; + char *str= string; + + str += sprintf(str, "Event Type %%t"); + + str += sprintf(str, formatstr, "Keyboard", OL_KM_KEYBOARD); + str += sprintf(str, formatstr, "Mouse", OL_KM_MOUSE); + str += sprintf(str, formatstr, "Tweak", OL_KM_TWEAK); +// str += sprintf(str, formatstr, "Specials", OL_KM_SPECIALS); + + return string; +} + +static char *keymap_mouse_menu(void) +{ + static char string[500]; + static char formatstr[] = "|%s %%x%d"; + char *str= string; + + str += sprintf(str, "Mouse Event %%t"); + + str += sprintf(str, formatstr, "Left Mouse", LEFTMOUSE); + str += sprintf(str, formatstr, "Middle Mouse", MIDDLEMOUSE); + str += sprintf(str, formatstr, "Right Mouse", RIGHTMOUSE); + str += sprintf(str, formatstr, "Button4 Mouse ", BUTTON4MOUSE); + str += sprintf(str, formatstr, "Button5 Mouse ", BUTTON5MOUSE); + str += sprintf(str, formatstr, "Action Mouse", ACTIONMOUSE); + str += sprintf(str, formatstr, "Select Mouse", SELECTMOUSE); + str += sprintf(str, formatstr, "Mouse Move", MOUSEMOVE); + str += sprintf(str, formatstr, "Wheel Up", WHEELUPMOUSE); + str += sprintf(str, formatstr, "Wheel Down", WHEELDOWNMOUSE); + str += sprintf(str, formatstr, "Wheel In", WHEELINMOUSE); + str += sprintf(str, formatstr, "Wheel Out", WHEELOUTMOUSE); + + return string; +} + +static char *keymap_tweak_menu(void) +{ + static char string[500]; + static char formatstr[] = "|%s %%x%d"; + char *str= string; + + str += sprintf(str, "Tweak Event %%t"); + + str += sprintf(str, formatstr, "Left Mouse", EVT_TWEAK_L); + str += sprintf(str, formatstr, "Middle Mouse", EVT_TWEAK_M); + str += sprintf(str, formatstr, "Right Mouse", EVT_TWEAK_R); + str += sprintf(str, formatstr, "Button4 Mouse ", BUTTON4MOUSE); + str += sprintf(str, formatstr, "Button5 Mouse ", BUTTON5MOUSE); + str += sprintf(str, formatstr, "Action Mouse", EVT_TWEAK_A); + str += sprintf(str, formatstr, "Select Mouse", EVT_TWEAK_S); + + return string; +} + +static char *keymap_tweak_dir_menu(void) +{ + static char string[500]; + static char formatstr[] = "|%s %%x%d"; + char *str= string; + + str += sprintf(str, "Tweak Direction %%t"); + + str += sprintf(str, formatstr, "Any", KM_ANY); + str += sprintf(str, formatstr, "North", EVT_GESTURE_N); + str += sprintf(str, formatstr, "North-East", EVT_GESTURE_NE); + str += sprintf(str, formatstr, "East", EVT_GESTURE_E); + str += sprintf(str, formatstr, "Sout-East", EVT_GESTURE_SE); + str += sprintf(str, formatstr, "South", EVT_GESTURE_S); + str += sprintf(str, formatstr, "South-West", EVT_GESTURE_SW); + str += sprintf(str, formatstr, "West", EVT_GESTURE_W); + str += sprintf(str, formatstr, "North-West", EVT_GESTURE_NW); + + return string; +} + + +static void keymap_type_cb(bContext *C, void *kmi_v, void *unused_v) +{ + wmKeymapItem *kmi= kmi_v; + short maptype= keymap_menu_type(kmi->type); + + if(maptype!=kmi->maptype) { + switch(kmi->maptype) { + case OL_KM_KEYBOARD: + kmi->type= AKEY; + kmi->val= KM_PRESS; + break; + case OL_KM_MOUSE: + kmi->type= LEFTMOUSE; + kmi->val= KM_PRESS; + break; + case OL_KM_TWEAK: + kmi->type= EVT_TWEAK_L; + kmi->val= KM_ANY; + break; + case OL_KM_SPECIALS: + kmi->type= AKEY; + kmi->val= KM_PRESS; + } + ED_region_tag_redraw(CTX_wm_region(C)); + } +} + +static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb) +{ + TreeElement *te; + TreeStoreElem *tselem; + + uiBlockSetEmboss(block, UI_EMBOSST); + + for(te= lb->first; te; te= te->next) { + tselem= TREESTORE(te); + if(te->ys >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { + uiBut *but; + char *str; + int xstart= 240; + int butw1= 20; /* operator */ + int butw2= 90; /* event type, menus */ + int butw3= 43; /* modifiers */ + + if(tselem->type == TSE_KEYMAP_ITEM) { + wmKeymapItem *kmi= te->directdata; + + /* modal map? */ + if(kmi->propvalue); + else { + uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys+1, butw1, OL_H-1, "Assign new Operator"); + } + xstart+= butw1+10; + + /* map type button */ + kmi->maptype= keymap_menu_type(kmi->type); + + str= keymap_type_menu(); + but= uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->maptype, 0, 0, 0, 0, "Event type"); + uiButSetFunc(but, keymap_type_cb, kmi, NULL); + xstart+= butw2+5; + + /* edit actual event */ + switch(kmi->maptype) { + case OL_KM_KEYBOARD: + uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->type, "Key code"); + xstart+= butw2+5; + break; + case OL_KM_MOUSE: + str= keymap_mouse_menu(); + uiDefButS(block, MENU, 0, str, xstart,(int)te->ys+1, butw2, OL_H-1, &kmi->type, 0, 0, 0, 0, "Mouse button"); + xstart+= butw2+5; + break; + case OL_KM_TWEAK: + str= keymap_tweak_menu(); + uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->type, 0, 0, 0, 0, "Tweak gesture"); + xstart+= butw2+5; + str= keymap_tweak_dir_menu(); + uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->val, 0, 0, 0, 0, "Tweak gesture direction"); + xstart+= butw2+5; + break; + } + + /* modifiers */ + uiDefButS(block, OPTION, 0, "Shift", xstart, (int)te->ys+1, butw3+5, OL_H-1, &kmi->shift, 0, 0, 0, 0, "Modifier"); xstart+= butw3+5; + uiDefButS(block, OPTION, 0, "Ctrl", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->ctrl, 0, 0, 0, 0, "Modifier"); xstart+= butw3; + uiDefButS(block, OPTION, 0, "Alt", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->alt, 0, 0, 0, 0, "Modifier"); xstart+= butw3; + uiDefButS(block, OPTION, 0, "Cmd", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->oskey, 0, 0, 0, 0, "Modifier"); xstart+= butw3; + xstart+= 5; + uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->keymodifier, "Key Modifier code"); + xstart+= butw3+5; + + /* rna property */ + if(kmi->ptr && kmi->ptr->data) + uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->oskey, 0, 0, 0, 0, ""); xstart+= butw2; + + + } + } + + if((tselem->flag & TSE_CLOSED)==0) outliner_draw_keymapbuts(block, ar, soops, &te->subtree); + } +} + + +static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb) { uiBut *bt; TreeElement *te; @@ -4405,6 +5220,7 @@ static void outliner_buttons(uiBlock *block, ARegion *ar, SpaceOops *soops, List if(te->ys >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if(tselem->flag & TSE_TEXTBUT) { + /* If we add support to rename Sequence. * need change this. */ @@ -4419,17 +5235,15 @@ static void outliner_buttons(uiBlock *block, ARegion *ar, SpaceOops *soops, List if(dx<50) dx= 50; bt= uiDefBut(block, TEX, OL_NAMEBUTTON, "", (short)te->xs+2*OL_X-4, (short)te->ys, dx+10, OL_H-1, te->name, 1.0, (float)len-1, 0, 0, ""); - uiButSetFunc(bt, namebutton_cb, te, NULL); - - // signal for button to open -// XXX addqueue(curarea->win, BUT_ACTIVATE, OL_NAMEBUTTON); + uiButSetRenameFunc(bt, namebutton_cb, tselem); - /* otherwise keeps open on ESC */ - tselem->flag &= ~TSE_TEXTBUT; + /* returns false if button got removed */ + if( 0 == uiButActiveOnly(C, block, bt) ) + tselem->flag &= ~TSE_TEXTBUT; } } - if((tselem->flag & TSE_CLOSED)==0) outliner_buttons(block, ar, soops, &te->subtree); + if((tselem->flag & TSE_CLOSED)==0) outliner_buttons(C, block, ar, soops, &te->subtree); } } @@ -4439,7 +5253,7 @@ void draw_outliner(const bContext *C) Scene *scene= CTX_data_scene(C); ARegion *ar= CTX_wm_region(C); View2D *v2d= &ar->v2d; - SpaceOops *soops= (SpaceOops*)CTX_wm_space_data(C); + SpaceOops *soops= CTX_wm_space_outliner(C); uiBlock *block; int sizey= 0, sizex= 0, sizex_rna= 0; @@ -4448,7 +5262,7 @@ void draw_outliner(const bContext *C) /* get extents of data */ outliner_height(soops, &soops->tree, &sizey); - if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) { + if (ELEM3(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF, SO_KEYMAP)) { /* RNA has two columns: * - column 1 is (max_width + OL_RNA_COL_SPACEX) or * (OL_RNA_COL_X), whichever is wider... @@ -4462,7 +5276,10 @@ void draw_outliner(const bContext *C) sizex_rna= MAX2(OL_RNA_COLX, sizex_rna+OL_RNA_COL_SPACEX); /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */ - sizex= sizex_rna + OL_RNA_COL_SIZEX + 50; + if (soops->outlinevis == SO_KEYMAP) + sizex= sizex_rna + OL_RNA_COL_SIZEX*3 + 50; // XXX this is only really a quick hack to make this wide enough... + else + sizex= sizex_rna + OL_RNA_COL_SIZEX + 50; } else { /* width must take into account restriction columns (if visible) so that entries will still be visible */ @@ -4475,6 +5292,9 @@ void draw_outliner(const bContext *C) sizex += OL_TOGW*3; } + /* tweak to display last line (when list bigger than window) */ + sizey += V2D_SCROLL_HEIGHT; + /* update size of tot-rect (extents of data/viewable area) */ UI_view2d_totRect_set(v2d, sizex, sizey); @@ -4483,17 +5303,20 @@ void draw_outliner(const bContext *C) /* draw outliner stuff (background and hierachy lines) */ outliner_back(ar, soops); - outliner_draw_tree(scene, ar, soops); + outliner_draw_tree((bContext *)C, scene, ar, soops); /* draw icons and names */ block= uiBeginBlock(C, ar, "outliner buttons", UI_EMBOSS); - outliner_buttons(block, ar, soops, &soops->tree); + outliner_buttons(C, block, ar, soops, &soops->tree); if(ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) { /* draw rna buttons */ outliner_draw_rnacols(ar, soops, sizex_rna); outliner_draw_rnabuts(block, scene, ar, soops, sizex_rna, &soops->tree); } + else if(soops->outlinevis == SO_KEYMAP) { + outliner_draw_keymapbuts(block, ar, soops, &soops->tree); + } else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) { /* draw restriction columns */ outliner_draw_restrictcols(ar, soops); |