Blender  V2.59
outliner_draw.c
Go to the documentation of this file.
00001 /*
00002  * $Id: outliner_draw.c 39294 2011-08-11 06:40:04Z gsrb3d $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2004 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): Joshua Leung
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00034 #include <string.h>
00035 #include <stdlib.h>
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "DNA_anim_types.h"
00040 #include "DNA_armature_types.h"
00041 #include "DNA_camera_types.h"
00042 #include "DNA_group_types.h"
00043 #include "DNA_key_types.h"
00044 #include "DNA_lamp_types.h"
00045 #include "DNA_material_types.h"
00046 #include "DNA_mesh_types.h"
00047 #include "DNA_meta_types.h"
00048 #include "DNA_particle_types.h"
00049 #include "DNA_scene_types.h"
00050 #include "DNA_world_types.h"
00051 #include "DNA_sequence_types.h"
00052 #include "DNA_object_types.h"
00053 
00054 #include "BLI_blenlib.h"
00055 #include "BLI_utildefines.h"
00056 
00057 #include "BKE_animsys.h"
00058 #include "BKE_context.h"
00059 #include "BKE_deform.h"
00060 #include "BKE_depsgraph.h"
00061 #include "BKE_fcurve.h"
00062 #include "BKE_global.h"
00063 #include "BKE_group.h"
00064 #include "BKE_library.h"
00065 #include "BKE_main.h"
00066 #include "BKE_modifier.h"
00067 #include "BKE_report.h"
00068 #include "BKE_scene.h"
00069 #include "BKE_sequencer.h"
00070 
00071 #include "BLI_ghash.h"
00072 
00073 #include "ED_armature.h"
00074 #include "ED_object.h"
00075 #include "ED_screen.h"
00076 #include "ED_util.h"
00077 
00078 #include "WM_api.h"
00079 #include "WM_types.h"
00080 
00081 #include "BIF_gl.h"
00082 #include "BIF_glutil.h"
00083 
00084 #include "UI_interface.h"
00085 #include "UI_interface_icons.h"
00086 #include "UI_resources.h"
00087 #include "UI_view2d.h"
00088 
00089 #include "RNA_access.h"
00090 #include "RNA_define.h"
00091 
00092 #include "outliner_intern.h"
00093 
00094 /* ****************************************************** */
00095 /* Tree Size Functions */
00096 
00097 static void outliner_height(SpaceOops *soops, ListBase *lb, int *h)
00098 {
00099         TreeElement *te= lb->first;
00100         while(te) {
00101                 TreeStoreElem *tselem= TREESTORE(te);
00102                 if((tselem->flag & TSE_CLOSED)==0) 
00103                         outliner_height(soops, &te->subtree, h);
00104                 (*h) += UI_UNIT_Y;
00105                 te= te->next;
00106         }
00107 }
00108 
00109 #if 0  // XXX this is currently disabled until te->xend is set correctly
00110 static void outliner_width(SpaceOops *soops, ListBase *lb, int *w)
00111 {
00112         TreeElement *te= lb->first;
00113         while(te) {
00114 //              TreeStoreElem *tselem= TREESTORE(te);
00115                 
00116                 // XXX fixme... te->xend is not set yet
00117                 if(tselem->flag & TSE_CLOSED) {
00118                         if (te->xend > *w)
00119                                 *w = te->xend;
00120                 }
00121                 outliner_width(soops, &te->subtree, w);
00122                 te= te->next;
00123         }
00124 }
00125 #endif
00126 
00127 static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int startx)
00128 {
00129         TreeElement *te= lb->first;
00130         while(te) {
00131                 TreeStoreElem *tselem= TREESTORE(te);
00132                         // XXX fixme... (currently, we're using a fixed length of 100)!
00133                 /*if(te->xend) {
00134                         if(te->xend > *w)
00135                                 *w = te->xend;
00136                 }*/
00137                 if(startx+100 > *w)
00138                         *w = startx+100;
00139 
00140                 if((tselem->flag & TSE_CLOSED)==0)
00141                         outliner_rna_width(soops, &te->subtree, w, startx+UI_UNIT_X);
00142                 te= te->next;
00143         }
00144 }
00145 
00146 /* ****************************************************** */
00147 
00148 static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
00149 {
00150         Scene *scene = (Scene *)poin;
00151         Object *ob = (Object *)poin2;
00152 
00153         if(!common_restrict_check(C, ob)) return;
00154         
00155         /* deselect objects that are invisible */
00156         if (ob->restrictflag & OB_RESTRICT_VIEW) {
00157                 /* Ouch! There is no backwards pointer from Object to Base, 
00158                  * so have to do loop to find it. */
00159                 ED_base_object_select(object_in_scene(ob, scene), BA_DESELECT);
00160         }
00161         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
00162 
00163 }
00164 
00165 static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2)
00166 {
00167         Scene *scene = (Scene *)poin;
00168         Object *ob = (Object *)poin2;
00169         
00170         if(!common_restrict_check(C, ob)) return;
00171         
00172         /* if select restriction has just been turned on */
00173         if (ob->restrictflag & OB_RESTRICT_SELECT) {
00174                 /* Ouch! There is no backwards pointer from Object to Base, 
00175                  * so have to do loop to find it. */
00176                 ED_base_object_select(object_in_scene(ob, scene), BA_DESELECT);
00177         }
00178         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
00179 
00180 }
00181 
00182 static void restrictbutton_rend_cb(bContext *C, void *poin, void *UNUSED(poin2))
00183 {
00184         WM_event_add_notifier(C, NC_SCENE|ND_OB_RENDER, poin);
00185 }
00186 
00187 static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2))
00188 {
00189         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, poin);
00190 }
00191 
00192 static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *poin2)
00193 {
00194         Object *ob = (Object *)poin2;
00195         
00196         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00197 
00198         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
00199 }
00200 
00201 static void restrictbutton_bone_cb(bContext *C, void *UNUSED(poin), void *poin2)
00202 {
00203         Bone *bone= (Bone *)poin2;
00204         if(bone && (bone->flag & BONE_HIDDEN_P))
00205                 bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
00206         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
00207 }
00208 
00209 static void restrictbutton_ebone_cb(bContext *C, void *UNUSED(poin), void *poin2)
00210 {
00211         EditBone *ebone= (EditBone *)poin2;
00212         if(ebone && (ebone->flag & BONE_HIDDEN_A))
00213                 ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
00214 
00215         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
00216 }
00217 
00218 static int group_restrict_flag(Group *gr, int flag)
00219 {
00220         GroupObject *gob;
00221 
00222         for(gob= gr->gobject.first; gob; gob= gob->next) {
00223                 if((gob->ob->restrictflag & flag) == 0)
00224                         return 0;
00225         }
00226 
00227         return 1;
00228 }
00229 
00230 static int group_select_flag(Group *gr)
00231 {
00232         GroupObject *gob;
00233 
00234         for(gob= gr->gobject.first; gob; gob= gob->next)
00235                 if((gob->ob->flag & SELECT))
00236                         return 1;
00237 
00238         return 0;
00239 }
00240 
00241 static void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag)
00242 {       
00243         Scene *scene = (Scene *)poin;           
00244         GroupObject *gob;
00245         Group *gr = (Group *)poin2;     
00246 
00247         if(group_restrict_flag(gr, flag)) {
00248                 for(gob= gr->gobject.first; gob; gob= gob->next) {
00249                         gob->ob->restrictflag &= ~flag;
00250                         
00251                         if(flag==OB_RESTRICT_VIEW)
00252                                 if(gob->ob->flag & SELECT)
00253                                         ED_base_object_select(object_in_scene(gob->ob, scene), BA_DESELECT);
00254                 }
00255         }
00256         else {
00257                 for(gob= gr->gobject.first; gob; gob= gob->next) {
00258                         /* not in editmode */
00259                         if(scene->obedit!=gob->ob) {
00260                                 gob->ob->restrictflag |= flag;
00261                                 
00262                                 if(flag==OB_RESTRICT_VIEW)
00263                                         if((gob->ob->flag & SELECT) == 0)
00264                                                 ED_base_object_select(object_in_scene(gob->ob, scene), BA_SELECT);
00265                         }
00266                 }
00267         }
00268 } 
00269 
00270 static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2)
00271 {
00272         restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_VIEW);
00273         WM_event_add_notifier(C, NC_GROUP, NULL);
00274 }
00275 static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2)
00276 {
00277         restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_SELECT);
00278         WM_event_add_notifier(C, NC_GROUP, NULL);
00279 }
00280 static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poin2)
00281 {
00282         restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_RENDER);
00283         WM_event_add_notifier(C, NC_GROUP, NULL);
00284 }
00285 
00286 
00287 static void namebutton_cb(bContext *C, void *tsep, char *oldname)
00288 {
00289         SpaceOops *soops= CTX_wm_space_outliner(C);
00290         Scene *scene= CTX_data_scene(C);
00291         Object *obedit= CTX_data_edit_object(C);
00292         TreeStore *ts= soops->treestore;
00293         TreeStoreElem *tselem= tsep;
00294         
00295         if(ts && tselem) {
00296                 TreeElement *te= outliner_find_tse(soops, tselem);
00297                 
00298                 if(tselem->type==0) {
00299                         test_idbutton(tselem->id->name+2);      // library.c, unique name and alpha sort
00300                         
00301                         switch(GS(tselem->id->name)) {
00302                                 case ID_MA:
00303                                         WM_event_add_notifier(C, NC_MATERIAL, NULL); break;
00304                                 case ID_TE:
00305                                         WM_event_add_notifier(C, NC_TEXTURE, NULL); break;
00306                                 case ID_IM:
00307                                         WM_event_add_notifier(C, NC_IMAGE, NULL); break;
00308                                 case ID_SCE:
00309                                         WM_event_add_notifier(C, NC_SCENE, NULL); break;
00310                                 default:
00311                                         WM_event_add_notifier(C, NC_ID|NA_RENAME, NULL); break;
00312                         }                                       
00313                         /* Check the library target exists */
00314                         if (te->idcode == ID_LI) {
00315                                 char expanded[FILE_MAXDIR + FILE_MAXFILE];
00316                                 BLI_strncpy(expanded, ((Library *)tselem->id)->name, FILE_MAXDIR + FILE_MAXFILE);
00317                                 BLI_path_abs(expanded, G.main->name);
00318                                 if (!BLI_exists(expanded)) {
00319                                         BKE_report(CTX_wm_reports(C), RPT_ERROR, "This path does not exist, correct this before saving");
00320                                 }
00321                         }
00322                 }
00323                 else {
00324                         switch(tselem->type) {
00325                         case TSE_DEFGROUP:
00326                                 defgroup_unique_name(te->directdata, (Object *)tselem->id); //  id = object
00327                                 break;
00328                         case TSE_NLA_ACTION:
00329                                 test_idbutton(tselem->id->name+2);
00330                                 break;
00331                         case TSE_EBONE:
00332                         {
00333                                 bArmature *arm= (bArmature *)tselem->id;
00334                                 if(arm->edbo) {
00335                                         EditBone *ebone= te->directdata;
00336                                         char newname[sizeof(ebone->name)];
00337                                         
00338                                         /* restore bone name */
00339                                         BLI_strncpy(newname, ebone->name, sizeof(ebone->name));
00340                                         BLI_strncpy(ebone->name, oldname, sizeof(ebone->name));
00341                                         ED_armature_bone_rename(obedit->data, oldname, newname);
00342                                         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, OBACT);
00343                                 }
00344                         }
00345                                 break;
00346 
00347                         case TSE_BONE:
00348                                 {
00349                                         Bone *bone= te->directdata;
00350                                         Object *ob;
00351                                         char newname[sizeof(bone->name)];
00352                                         
00353                                         // always make current object active
00354                                         tree_element_active(C, scene, soops, te, 1); // was set_active_object()
00355                                         ob= OBACT;
00356                                         
00357                                         /* restore bone name */
00358                                         BLI_strncpy(newname, bone->name, sizeof(bone->name));
00359                                         BLI_strncpy(bone->name, oldname, sizeof(bone->name));
00360                                         ED_armature_bone_rename(ob->data, oldname, newname);
00361                                         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
00362                                 }
00363                                 break;
00364                         case TSE_POSE_CHANNEL:
00365                                 {
00366                                         bPoseChannel *pchan= te->directdata;
00367                                         Object *ob;
00368                                         char newname[sizeof(pchan->name)];
00369                                         
00370                                         // always make current object active
00371                                         tree_element_active(C, scene, soops, te, 1); // was set_active_object()
00372                                         ob= OBACT;
00373                                         
00374                                         /* restore bone name */
00375                                         BLI_strncpy(newname, pchan->name, sizeof(pchan->name));
00376                                         BLI_strncpy(pchan->name, oldname, sizeof(pchan->name));
00377                                         ED_armature_bone_rename(ob->data, oldname, newname);
00378                                         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
00379                                 }
00380                                 break;
00381                         case TSE_POSEGRP:
00382                                 {
00383                                         Object *ob= (Object *)tselem->id; // id = object
00384                                         bActionGroup *grp= te->directdata;
00385                                         
00386                                         BLI_uniquename(&ob->pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name));
00387                                         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
00388                                 }
00389                                 break;
00390                         case TSE_R_LAYER:
00391                                 break;
00392                         }
00393                 }
00394                 tselem->flag &= ~TSE_TEXTBUT;
00395         }
00396 }
00397 
00398 static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, ListBase *lb)
00399 {       
00400         uiBut *bt;
00401         TreeElement *te;
00402         TreeStoreElem *tselem;
00403         Object *ob = NULL;
00404         Group  *gr = NULL;
00405 
00406         for(te= lb->first; te; te= te->next) {
00407                 tselem= TREESTORE(te);
00408                 if(te->ys+2*UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {      
00409                         /* objects have toggle-able restriction flags */
00410                         if(tselem->type==0 && te->idcode==ID_OB) {
00411                                 PointerRNA ptr;
00412                                 
00413                                 ob = (Object *)tselem->id;
00414                                 RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr);
00415                                 
00416                                 uiBlockSetEmboss(block, UI_EMBOSSN);
00417                                 bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_VIEW_OFF,
00418                                                           (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1,
00419                                                           &ptr, "hide", -1, 0, 0, -1, -1, NULL);
00420                                 uiButSetFunc(bt, restrictbutton_view_cb, scene, ob);
00421                                 
00422                                 bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_SELECT_OFF,
00423                                                                   (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1,
00424                                                                   &ptr, "hide_select", -1, 0, 0, -1, -1, NULL);
00425                                 uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob);
00426                                 
00427                                 bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_RENDER_OFF,
00428                                                                   (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1,
00429                                                                   &ptr, "hide_render", -1, 0, 0, -1, -1, NULL);
00430                                 uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob);
00431                                 
00432                                 uiBlockSetEmboss(block, UI_EMBOSS);
00433                                 
00434                         }
00435                         if(tselem->type==0 && te->idcode==ID_GR){ 
00436                                 int restrict_bool;
00437                                 gr = (Group *)tselem->id;
00438                                 
00439                                 uiBlockSetEmboss(block, UI_EMBOSSN);
00440                                 
00441                                 restrict_bool= group_restrict_flag(gr, OB_RESTRICT_VIEW);
00442                                 bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
00443                                 uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr);
00444 
00445                                 restrict_bool= group_restrict_flag(gr, OB_RESTRICT_SELECT);
00446                                 bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
00447                                 uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr);
00448         
00449                                 restrict_bool= group_restrict_flag(gr, OB_RESTRICT_RENDER);
00450                                 bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, NULL, 0, 0, 0, 0, "Restrict/Allow renderability");
00451                                 uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr);
00452 
00453                                 uiBlockSetEmboss(block, UI_EMBOSS);
00454                         }
00455                         /* scene render layers and passes have toggle-able flags too! */
00456                         else if(tselem->type==TSE_R_LAYER) {
00457                                 uiBlockSetEmboss(block, UI_EMBOSSN);
00458                                 
00459                                 bt= uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT-1, 
00460                                                                          (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
00461                                 uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
00462                                 
00463                                 uiBlockSetEmboss(block, UI_EMBOSS);
00464                         }
00465                         else if(tselem->type==TSE_R_PASS) {
00466                                 int *layflag= te->directdata;
00467                                 int passflag= 1<<tselem->nr;
00468                                 
00469                                 uiBlockSetEmboss(block, UI_EMBOSSN);
00470                                 
00471                                 
00472                                 bt= uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT-1, 
00473                                                                          (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, layflag, 0, 0, 0, 0, "Render this Pass");
00474                                 uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
00475                                 
00476                                 layflag++;      /* is lay_xor */
00477                                 if(ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT, SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
00478                                         bt= uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag)?ICON_DOT:ICON_BLANK1, 
00479                                                                          (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
00480                                 uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
00481                                 
00482                                 uiBlockSetEmboss(block, UI_EMBOSS);
00483                         }
00484                         else if(tselem->type==TSE_MODIFIER)  {
00485                                 ModifierData *md= (ModifierData *)te->directdata;
00486                                 ob = (Object *)tselem->id;
00487                                 
00488                                 uiBlockSetEmboss(block, UI_EMBOSSN);
00489                                 bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF, 
00490                                                 (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
00491                                 uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
00492                                 
00493                                 bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF, 
00494                                                 (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
00495                                 uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
00496                         }
00497                         else if(tselem->type==TSE_POSE_CHANNEL)  {
00498                                 bPoseChannel *pchan= (bPoseChannel *)te->directdata;
00499                                 Bone *bone = pchan->bone;
00500                                 
00501                                 uiBlockSetEmboss(block, UI_EMBOSSN);
00502                                 bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF, 
00503                                                 (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
00504                                 uiButSetFunc(bt, restrictbutton_bone_cb, NULL, bone);
00505                                 
00506                                 bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, 
00507                                                 (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
00508                                 uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
00509                         }
00510                         else if(tselem->type==TSE_EBONE)  {
00511                                 EditBone *ebone= (EditBone *)te->directdata;
00512                                 
00513                                 uiBlockSetEmboss(block, UI_EMBOSSN);
00514                                 bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF, 
00515                                                 (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
00516                                 uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, ebone);
00517                                 
00518                                 bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, 
00519                                                 (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
00520                                 uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, NULL);
00521                         }
00522                 }
00523                 
00524                 if((tselem->flag & TSE_CLOSED)==0) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
00525         }
00526 }
00527 
00528 static void outliner_draw_rnacols(ARegion *ar, int sizex)
00529 {
00530         View2D *v2d= &ar->v2d;
00531 
00532         float miny = v2d->cur.ymin-V2D_SCROLL_HEIGHT;
00533         if(miny<v2d->tot.ymin) miny = v2d->tot.ymin;
00534 
00535         UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
00536 
00537         /* draw column separator lines */
00538         fdrawline((float)sizex,
00539                 v2d->cur.ymax,
00540                 (float)sizex,
00541                 miny);
00542 
00543         fdrawline((float)sizex+OL_RNA_COL_SIZEX,
00544                 v2d->cur.ymax,
00545                 (float)sizex+OL_RNA_COL_SIZEX,
00546                 miny);
00547 }
00548 
00549 static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
00550 {       
00551         TreeElement *te;
00552         TreeStoreElem *tselem;
00553         PointerRNA *ptr;
00554         PropertyRNA *prop;
00555         
00556         uiBlockSetEmboss(block, UI_EMBOSST);
00557 
00558         for(te= lb->first; te; te= te->next) {
00559                 tselem= TREESTORE(te);
00560                 if(te->ys+2*UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {      
00561                         if(tselem->type == TSE_RNA_PROPERTY) {
00562                                 ptr= &te->rnaptr;
00563                                 prop= te->directdata;
00564                                 
00565                                 if(!(RNA_property_type(prop) == PROP_POINTER && (tselem->flag & TSE_CLOSED)==0))
00566                                         uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y-1);
00567                         }
00568                         else if(tselem->type == TSE_RNA_ARRAY_ELEM) {
00569                                 ptr= &te->rnaptr;
00570                                 prop= te->directdata;
00571                                 
00572                                 uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y-1);
00573                         }
00574                 }
00575                 
00576                 if((tselem->flag & TSE_CLOSED)==0) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
00577         }
00578 }
00579 
00580 static void operator_call_cb(struct bContext *UNUSED(C), void *arg_kmi, void *arg2)
00581 {
00582         wmOperatorType *ot= arg2;
00583         wmKeyMapItem *kmi= arg_kmi;
00584         
00585         if(ot)
00586                 BLI_strncpy(kmi->idname, ot->idname, OP_MAX_TYPENAME);
00587 }
00588 
00589 static void operator_search_cb(const struct bContext *UNUSED(C), void *UNUSED(arg_kmi), const char *str, uiSearchItems *items)
00590 {
00591         GHashIterator *iter= WM_operatortype_iter();
00592 
00593         for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
00594                 wmOperatorType *ot= BLI_ghashIterator_getValue(iter);
00595                 
00596                 if(BLI_strcasestr(ot->idname, str)) {
00597                         char name[OP_MAX_TYPENAME];
00598                         
00599                         /* display name for menu */
00600                         WM_operator_py_idname(name, ot->idname);
00601                         
00602                         if(0==uiSearchItemAdd(items, name, ot, 0))
00603                                 break;
00604                 }
00605         }
00606         BLI_ghashIterator_free(iter);
00607 }
00608 
00609 /* operator Search browse menu, open */
00610 static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi)
00611 {
00612         static char search[OP_MAX_TYPENAME];
00613         wmEvent event;
00614         wmWindow *win= CTX_wm_window(C);
00615         wmKeyMapItem *kmi= arg_kmi;
00616         wmOperatorType *ot= WM_operatortype_find(kmi->idname, 0);
00617         uiBlock *block;
00618         uiBut *but;
00619         
00620         /* clear initial search string, then all items show */
00621         search[0]= 0;
00622         
00623         block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
00624         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
00625         
00626         /* fake button, it holds space for search items */
00627         uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
00628         
00629         but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, UI_UNIT_Y, 0, 0, "");
00630         uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot);
00631         
00632         uiBoundsBlock(block, 6);
00633         uiBlockSetDirection(block, UI_DOWN);    
00634         uiEndBlock(C, block);
00635         
00636         event= *(win->eventstate);      /* XXX huh huh? make api call */
00637         event.type= EVT_BUT_OPEN;
00638         event.val= KM_PRESS;
00639         event.customdata= but;
00640         event.customdatafree= FALSE;
00641         wm_event_add(win, &event);
00642         
00643         return block;
00644 }
00645 
00646 #define OL_KM_KEYBOARD          0
00647 #define OL_KM_MOUSE                     1
00648 #define OL_KM_TWEAK                     2
00649 #define OL_KM_SPECIALS          3
00650 
00651 static short keymap_menu_type(short type)
00652 {
00653         if(ISKEYBOARD(type)) return OL_KM_KEYBOARD;
00654         if(ISTWEAK(type)) return OL_KM_TWEAK;
00655         if(ISMOUSE(type)) return OL_KM_MOUSE;
00656 //      return OL_KM_SPECIALS;
00657         return 0;
00658 }
00659 
00660 static const char *keymap_type_menu(void)
00661 {
00662         static const char string[]=
00663         "Event Type%t"
00664         "|Keyboard%x" STRINGIFY(OL_KM_KEYBOARD)
00665         "|Mouse%x" STRINGIFY(OL_KM_MOUSE)
00666         "|Tweak%x" STRINGIFY(OL_KM_TWEAK)
00667 //      "|Specials%x" STRINGIFY(OL_KM_SPECIALS)
00668         ;
00669 
00670         return string;
00671 }
00672 
00673 static const char *keymap_mouse_menu(void)
00674 {
00675         static const char string[]=
00676         "Mouse Event%t"
00677         "|Left Mouse%x" STRINGIFY(LEFTMOUSE)
00678         "|Middle Mouse%x" STRINGIFY(MIDDLEMOUSE)
00679         "|Right Mouse%x" STRINGIFY(RIGHTMOUSE)
00680         "|Middle Mouse%x" STRINGIFY(MIDDLEMOUSE)
00681         "|Right Mouse%x" STRINGIFY(RIGHTMOUSE)
00682         "|Button4 Mouse%x" STRINGIFY(BUTTON4MOUSE)
00683         "|Button5 Mouse%x" STRINGIFY(BUTTON5MOUSE)
00684         "|Action Mouse%x" STRINGIFY(ACTIONMOUSE)
00685         "|Select Mouse%x" STRINGIFY(SELECTMOUSE)
00686         "|Mouse Move%x" STRINGIFY(MOUSEMOVE)
00687         "|Wheel Up%x" STRINGIFY(WHEELUPMOUSE)
00688         "|Wheel Down%x" STRINGIFY(WHEELDOWNMOUSE)
00689         "|Wheel In%x" STRINGIFY(WHEELINMOUSE)
00690         "|Wheel Out%x" STRINGIFY(WHEELOUTMOUSE)
00691         "|Mouse/Trackpad Pan%x" STRINGIFY(MOUSEPAN)
00692         "|Mouse/Trackpad Zoom%x" STRINGIFY(MOUSEZOOM)
00693         "|Mouse/Trackpad Rotate%x" STRINGIFY(MOUSEROTATE)
00694         ;
00695 
00696         return string;
00697 }
00698 
00699 static const char *keymap_tweak_menu(void)
00700 {
00701         static const char string[]=
00702         "Tweak Event%t"
00703         "|Left Mouse%x" STRINGIFY(EVT_TWEAK_L)
00704         "|Middle Mouse%x" STRINGIFY(EVT_TWEAK_M)
00705         "|Right Mouse%x" STRINGIFY(EVT_TWEAK_R)
00706         "|Action Mouse%x" STRINGIFY(EVT_TWEAK_A)
00707         "|Select Mouse%x" STRINGIFY(EVT_TWEAK_S)
00708         ;
00709 
00710         return string;
00711 }
00712 
00713 static const char *keymap_tweak_dir_menu(void)
00714 {
00715         static const char string[]=
00716         "Tweak Direction%t"
00717         "|Any%x" STRINGIFY(KM_ANY)
00718         "|North%x" STRINGIFY(EVT_GESTURE_N)
00719         "|North-East%x" STRINGIFY(EVT_GESTURE_NE)
00720         "|East%x" STRINGIFY(EVT_GESTURE_E)
00721         "|Sout-East%x" STRINGIFY(EVT_GESTURE_SE)
00722         "|South%x" STRINGIFY(EVT_GESTURE_S)
00723         "|South-West%x" STRINGIFY(EVT_GESTURE_SW)
00724         "|West%x" STRINGIFY(EVT_GESTURE_W)
00725         "|North-West%x" STRINGIFY(EVT_GESTURE_NW)
00726         ;
00727 
00728         return string;
00729 }
00730 
00731 
00732 static void keymap_type_cb(bContext *C, void *kmi_v, void *UNUSED(arg_v))
00733 {
00734         wmKeyMapItem *kmi= kmi_v;
00735         short maptype= keymap_menu_type(kmi->type);
00736         
00737         if(maptype!=kmi->maptype) {
00738                 switch(kmi->maptype) {
00739                         case OL_KM_KEYBOARD:
00740                                 kmi->type= AKEY;
00741                                 kmi->val= KM_PRESS;
00742                                 break;
00743                         case OL_KM_MOUSE:
00744                                 kmi->type= LEFTMOUSE;
00745                                 kmi->val= KM_PRESS;
00746                                 break;
00747                         case OL_KM_TWEAK:
00748                                 kmi->type= EVT_TWEAK_L;
00749                                 kmi->val= KM_ANY;
00750                                 break;
00751                         case OL_KM_SPECIALS:
00752                                 kmi->type= AKEY;
00753                                 kmi->val= KM_PRESS;
00754                 }
00755                 ED_region_tag_redraw(CTX_wm_region(C));
00756         }
00757 }
00758 
00759 static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
00760 {
00761         TreeElement *te;
00762         TreeStoreElem *tselem;
00763         
00764         uiBlockSetEmboss(block, UI_EMBOSST);
00765         
00766         for(te= lb->first; te; te= te->next) {
00767                 tselem= TREESTORE(te);
00768                 if(te->ys+2*UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
00769                         uiBut *but;
00770                         const char *str;
00771                         int xstart= 240;
00772                         int butw1= UI_UNIT_X; /* operator */
00773                         int butw2= 90; /* event type, menus */
00774                         int butw3= 43; /* modifiers */
00775 
00776                         if(tselem->type == TSE_KEYMAP_ITEM) {
00777                                 wmKeyMapItem *kmi= te->directdata;
00778                                 
00779                                 /* modal map? */
00780                                 if(kmi->propvalue);
00781                                 else {
00782                                         uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys+1, butw1, UI_UNIT_Y-1, "Assign new Operator");
00783                                 }
00784                                 xstart+= butw1+10;
00785                                 
00786                                 /* map type button */
00787                                 kmi->maptype= keymap_menu_type(kmi->type);
00788                                 
00789                                 str= keymap_type_menu();
00790                                 but= uiDefButS(block, MENU, 0, str,     xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->maptype, 0, 0, 0, 0, "Event type");
00791                                 uiButSetFunc(but, keymap_type_cb, kmi, NULL);
00792                                 xstart+= butw2+5;
00793                                 
00794                                 /* edit actual event */
00795                                 switch(kmi->maptype) {
00796                                         case OL_KM_KEYBOARD:
00797                                                 uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->type, "Key code");
00798                                                 xstart+= butw2+5;
00799                                                 break;
00800                                         case OL_KM_MOUSE:
00801                                                 str= keymap_mouse_menu();
00802                                                 uiDefButS(block, MENU, 0, str, xstart,(int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->type, 0, 0, 0, 0,  "Mouse button");      
00803                                                 xstart+= butw2+5;
00804                                                 break;
00805                                         case OL_KM_TWEAK:
00806                                                 str= keymap_tweak_menu();
00807                                                 uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->type, 0, 0, 0, 0,  "Tweak gesture");    
00808                                                 xstart+= butw2+5;
00809                                                 str= keymap_tweak_dir_menu();
00810                                                 uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->val, 0, 0, 0, 0,  "Tweak gesture direction");   
00811                                                 xstart+= butw2+5;
00812                                                 break;
00813                                 }
00814                                 
00815                                 /* modifiers */
00816                                 uiDefButS(block, OPTION, 0, "Shift",    xstart, (int)te->ys+1, butw3+5, UI_UNIT_Y-1, &kmi->shift, 0, 0, 0, 0, "Modifier"); xstart+= butw3+5;
00817                                 uiDefButS(block, OPTION, 0, "Ctrl",     xstart, (int)te->ys+1, butw3, UI_UNIT_Y-1, &kmi->ctrl, 0, 0, 0, 0, "Modifier"); xstart+= butw3;
00818                                 uiDefButS(block, OPTION, 0, "Alt",      xstart, (int)te->ys+1, butw3, UI_UNIT_Y-1, &kmi->alt, 0, 0, 0, 0, "Modifier"); xstart+= butw3;
00819                                 uiDefButS(block, OPTION, 0, "OS",       xstart, (int)te->ys+1, butw3, UI_UNIT_Y-1, &kmi->oskey, 0, 0, 0, 0, "Modifier"); xstart+= butw3;
00820                                 xstart+= 5;
00821                                 uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw3, UI_UNIT_Y-1, &kmi->keymodifier, "Key Modifier code");
00822                                 xstart+= butw3+5;
00823                                 
00824                                 /* rna property */
00825                                 if(kmi->ptr && kmi->ptr->data) {
00826                                         uiDefBut(block, LABEL, 0, "(RNA property)",     xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->oskey, 0, 0, 0, 0, ""); xstart+= butw2;
00827                                 }
00828 
00829                                 (void)xstart;
00830                         }
00831                 }
00832                 
00833                 if((tselem->flag & TSE_CLOSED)==0) outliner_draw_keymapbuts(block, ar, soops, &te->subtree);
00834         }
00835 }
00836 
00837 
00838 static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
00839 {
00840         uiBut *bt;
00841         TreeElement *te;
00842         TreeStoreElem *tselem;
00843         int spx, dx, len;
00844         
00845         for(te= lb->first; te; te= te->next) {
00846                 tselem= TREESTORE(te);
00847                 if(te->ys+2*UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
00848                         
00849                         if(tselem->flag & TSE_TEXTBUT) {
00850                                 
00851                                 /* If we add support to rename Sequence.
00852                                  * need change this.
00853                                  */
00854                                 if(tselem->type == TSE_POSE_BASE) continue; // prevent crash when trying to rename 'pose' entry of armature
00855                                 
00856                                 if(tselem->type==TSE_EBONE) len = sizeof(((EditBone*) 0)->name);
00857                                 else if (tselem->type==TSE_MODIFIER) len = sizeof(((ModifierData*) 0)->name);
00858                                 else if(tselem->id && GS(tselem->id->name)==ID_LI) len = sizeof(((Library*) 0)->name);
00859                                 else len= MAX_ID_NAME-2;
00860                                 
00861 
00862                                 dx= (int)UI_GetStringWidth(te->name);
00863                                 if(dx<100) dx= 100;
00864                                 spx=te->xs+2*UI_UNIT_X-4;
00865                                 if(spx+dx+10>ar->v2d.cur.xmax) dx = ar->v2d.cur.xmax-spx-10;
00866 
00867                                 bt= uiDefBut(block, TEX, OL_NAMEBUTTON, "", spx, (int)te->ys, dx+10, UI_UNIT_Y-1, (void *)te->name, 1.0, (float)len, 0, 0, "");
00868                                 uiButSetRenameFunc(bt, namebutton_cb, tselem);
00869                                 
00870                                 /* returns false if button got removed */
00871                                 if( 0 == uiButActiveOnly(C, block, bt) )
00872                                         tselem->flag &= ~TSE_TEXTBUT;
00873                         }
00874                 }
00875                 
00876                 if((tselem->flag & TSE_CLOSED)==0) outliner_buttons(C, block, ar, soops, &te->subtree);
00877         }
00878 }
00879 
00880 /* ****************************************************** */
00881 /* Normal Drawing... */
00882 
00883 /* make function calls a bit compacter */
00884 struct DrawIconArg {
00885         uiBlock *block;
00886         ID *id;
00887         int xmax, x, y;
00888         float alpha;
00889 };
00890 
00891 static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
00892 {
00893         /* restrict collumn clip... it has been coded by simply overdrawing, doesnt work for buttons */
00894         if(arg->x >= arg->xmax) 
00895                 UI_icon_draw(arg->x, arg->y, icon);
00896         else {
00897                 /* XXX investigate: button placement of icons is way different than UI_icon_draw? */
00898                 float ufac= UI_UNIT_X/20.0f;
00899                 uiBut *but= uiDefIconBut(arg->block, LABEL, 0, icon, arg->x-3.0f*ufac, arg->y, UI_UNIT_X-4.0f*ufac, UI_UNIT_Y-4.0f*ufac, NULL, 0.0, 0.0, 1.0, arg->alpha, (arg->id && arg->id->lib) ? arg->id->lib->name : "");
00900                 
00901                 if(arg->id)
00902                         uiButSetDragID(but, arg->id);
00903         }
00904 
00905 }
00906 
00907 static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, float alpha)
00908 {
00909         struct DrawIconArg arg;
00910         
00911         /* make function calls a bit compacter */
00912         arg.block= block;
00913         arg.id= tselem->id;
00914         arg.xmax= xmax;
00915         arg.x= x;
00916         arg.y= y;
00917         arg.alpha= alpha;
00918         
00919         if(tselem->type) {
00920                 switch( tselem->type) {
00921                         case TSE_ANIM_DATA:
00922                                 UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx
00923                         case TSE_NLA:
00924                                 UI_icon_draw(x, y, ICON_NLA); break;
00925                         case TSE_NLA_TRACK:
00926                                 UI_icon_draw(x, y, ICON_NLA); break; // XXX
00927                         case TSE_NLA_ACTION:
00928                                 UI_icon_draw(x, y, ICON_ACTION); break;
00929                         case TSE_DRIVER_BASE:
00930 
00931 #if 0           // GSOC_PEPPER
00932 
00933                                 UI_icon_draw(x, y, ICON_DRIVER); break;
00934 
00935 #endif          // GSOC_PEPPER
00936 
00937                         case TSE_DEFGROUP_BASE:
00938                                 UI_icon_draw(x, y, ICON_GROUP_VERTEX); break;
00939                         case TSE_BONE:
00940                         case TSE_EBONE:
00941                                 UI_icon_draw(x, y, ICON_BONE_DATA); break;
00942                         case TSE_CONSTRAINT_BASE:
00943                                 UI_icon_draw(x, y, ICON_CONSTRAINT); break;
00944                         case TSE_MODIFIER_BASE:
00945                                 UI_icon_draw(x, y, ICON_MODIFIER); break;
00946                         case TSE_LINKED_OB:
00947                                 UI_icon_draw(x, y, ICON_OBJECT_DATA); break;
00948                         case TSE_LINKED_PSYS:
00949                                 UI_icon_draw(x, y, ICON_PARTICLES); break;
00950                         case TSE_MODIFIER:
00951                         {
00952                                 Object *ob= (Object *)tselem->id;
00953                                 ModifierData *md= BLI_findlink(&ob->modifiers, tselem->nr);
00954                                 switch(md->type) {
00955                                         case eModifierType_Subsurf: 
00956                                                 UI_icon_draw(x, y, ICON_MOD_SUBSURF); break;
00957                                         case eModifierType_Armature: 
00958                                                 UI_icon_draw(x, y, ICON_MOD_ARMATURE); break;
00959                                         case eModifierType_Lattice: 
00960                                                 UI_icon_draw(x, y, ICON_MOD_LATTICE); break;
00961                                         case eModifierType_Curve: 
00962                                                 UI_icon_draw(x, y, ICON_MOD_CURVE); break;
00963                                         case eModifierType_Build: 
00964                                                 UI_icon_draw(x, y, ICON_MOD_BUILD); break;
00965                                         case eModifierType_Mirror: 
00966                                                 UI_icon_draw(x, y, ICON_MOD_MIRROR); break;
00967                                         case eModifierType_Decimate: 
00968                                                 UI_icon_draw(x, y, ICON_MOD_DECIM); break;
00969                                         case eModifierType_Wave: 
00970                                                 UI_icon_draw(x, y, ICON_MOD_WAVE); break;
00971                                         case eModifierType_Hook: 
00972                                                 UI_icon_draw(x, y, ICON_HOOK); break;
00973                                         case eModifierType_Softbody: 
00974                                                 UI_icon_draw(x, y, ICON_MOD_SOFT); break;
00975                                         case eModifierType_Boolean: 
00976                                                 UI_icon_draw(x, y, ICON_MOD_BOOLEAN); break;
00977                                         case eModifierType_ParticleSystem: 
00978                                                 UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
00979                                         case eModifierType_ParticleInstance:
00980                                                 UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
00981                                         case eModifierType_EdgeSplit:
00982                                                 UI_icon_draw(x, y, ICON_MOD_EDGESPLIT); break;
00983                                         case eModifierType_Array:
00984                                                 UI_icon_draw(x, y, ICON_MOD_ARRAY); break;
00985                                         case eModifierType_UVProject:
00986                                                 UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break;
00987                                         case eModifierType_Displace:
00988                                                 UI_icon_draw(x, y, ICON_MOD_DISPLACE); break;
00989                                         case eModifierType_Shrinkwrap:
00990                                                 UI_icon_draw(x, y, ICON_MOD_SHRINKWRAP); break;
00991                                         case eModifierType_Cast:
00992                                                 UI_icon_draw(x, y, ICON_MOD_CAST); break;
00993                                         case eModifierType_MeshDeform:
00994                                                 UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break;
00995                                         case eModifierType_Bevel:
00996                                                 UI_icon_draw(x, y, ICON_MOD_BEVEL); break;
00997                                         case eModifierType_Smooth:
00998                                                 UI_icon_draw(x, y, ICON_MOD_SMOOTH); break;
00999                                         case eModifierType_SimpleDeform:
01000                                                 UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break;
01001                                         case eModifierType_Mask:
01002                                                 UI_icon_draw(x, y, ICON_MOD_MASK); break;
01003                                         case eModifierType_Cloth:
01004                                                 UI_icon_draw(x, y, ICON_MOD_CLOTH); break;
01005                                         case eModifierType_Explode:
01006                                                 UI_icon_draw(x, y, ICON_MOD_EXPLODE); break;
01007                                         case eModifierType_Collision:
01008                                                 UI_icon_draw(x, y, ICON_MOD_PHYSICS); break;
01009                                         case eModifierType_Fluidsim:
01010                                                 UI_icon_draw(x, y, ICON_MOD_FLUIDSIM); break;
01011                                         case eModifierType_Multires:
01012                                                 UI_icon_draw(x, y, ICON_MOD_MULTIRES); break;
01013                                         case eModifierType_Smoke:
01014                                                 UI_icon_draw(x, y, ICON_MOD_SMOKE); break;
01015                                         case eModifierType_Solidify:
01016                                                 UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break;
01017                                         case eModifierType_Screw:
01018                                                 UI_icon_draw(x, y, ICON_MOD_SCREW); break;
01019                                         default:
01020                                                 UI_icon_draw(x, y, ICON_DOT); break;
01021                                 }
01022                                 break;
01023                         }
01024                         case TSE_SCRIPT_BASE:
01025                                 UI_icon_draw(x, y, ICON_TEXT); break;
01026                         case TSE_POSE_BASE:
01027                                 UI_icon_draw(x, y, ICON_ARMATURE_DATA); break;
01028                         case TSE_POSE_CHANNEL:
01029                                 UI_icon_draw(x, y, ICON_BONE_DATA); break;
01030                         case TSE_PROXY:
01031                                 UI_icon_draw(x, y, ICON_GHOST); break;
01032                         case TSE_R_LAYER_BASE:
01033                                 UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
01034                         case TSE_R_LAYER:
01035                                 UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
01036                         case TSE_LINKED_LAMP:
01037                                 UI_icon_draw(x, y, ICON_LAMP_DATA); break;
01038                         case TSE_LINKED_MAT:
01039                                 UI_icon_draw(x, y, ICON_MATERIAL_DATA); break;
01040                         case TSE_POSEGRP_BASE:
01041                                 UI_icon_draw(x, y, ICON_VERTEXSEL); break;
01042                         case TSE_SEQUENCE:
01043                                 if(te->idcode==SEQ_MOVIE)
01044                                         UI_icon_draw(x, y, ICON_SEQUENCE);
01045                                 else if(te->idcode==SEQ_META)
01046                                         UI_icon_draw(x, y, ICON_DOT);
01047                                 else if(te->idcode==SEQ_SCENE)
01048                                         UI_icon_draw(x, y, ICON_SCENE);
01049                                 else if(te->idcode==SEQ_SOUND)
01050                                         UI_icon_draw(x, y, ICON_SOUND);
01051                                 else if(te->idcode==SEQ_IMAGE)
01052                                         UI_icon_draw(x, y, ICON_IMAGE_COL);
01053                                 else
01054                                         UI_icon_draw(x, y, ICON_PARTICLES);
01055                                 break;
01056                         case TSE_SEQ_STRIP:
01057                                 UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT);
01058                                 break;
01059                         case TSE_SEQUENCE_DUP:
01060                                 UI_icon_draw(x, y, ICON_OBJECT_DATA);
01061                                 break;
01062                         case TSE_RNA_STRUCT:
01063                                 if(RNA_struct_is_ID(te->rnaptr.type)) {
01064                                         arg.id= (ID *)te->rnaptr.data;
01065                                         tselem_draw_icon_uibut(&arg, RNA_struct_ui_icon(te->rnaptr.type));
01066                                 }
01067                                 else
01068                                         UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type));
01069                                 break;
01070                         default:
01071                                 UI_icon_draw(x, y, ICON_DOT); break;
01072                 }
01073         }
01074         else if (GS(tselem->id->name) == ID_OB) {
01075                 Object *ob= (Object *)tselem->id;
01076                 switch (ob->type) {
01077                         case OB_LAMP:
01078                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
01079                         case OB_MESH: 
01080                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
01081                         case OB_CAMERA: 
01082                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
01083                         case OB_CURVE: 
01084                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
01085                         case OB_MBALL: 
01086                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
01087                         case OB_LATTICE: 
01088                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
01089                         case OB_ARMATURE: 
01090                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
01091                         case OB_FONT: 
01092                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
01093                         case OB_SURF: 
01094                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
01095 
01096 #if 0           // GSOC_PEPPER
01097 
01098                         case OB_SPEAKER:
01099                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break;
01100 
01101 #endif          // GSOC_PEPPER
01102 
01103                         case OB_EMPTY: 
01104                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
01105                 
01106                 }
01107         }
01108         else {
01109                 switch( GS(tselem->id->name)) {
01110                         case ID_SCE:
01111                                 tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
01112                         case ID_ME:
01113                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break;
01114                         case ID_CU:
01115                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break;
01116                         case ID_MB:
01117                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break;
01118                         case ID_LT:
01119                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break;
01120                         case ID_LA:
01121                         {
01122                                 Lamp *la= (Lamp *)tselem->id;
01123                                 
01124                                 switch(la->type) {
01125                                         case LA_LOCAL:
01126                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break;
01127                                         case LA_SUN:
01128                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break;
01129                                         case LA_SPOT:
01130                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break;
01131                                         case LA_HEMI:
01132                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break;
01133                                         case LA_AREA:
01134                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break;
01135                                         default:
01136                                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break;
01137                                 }
01138                                 break;
01139                         }
01140                         case ID_MA:
01141                                 tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break;
01142                         case ID_TE:
01143                                 tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break;
01144                         case ID_IM:
01145                                 tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break;
01146 
01147 #if 0           // GSOC_PEPPER
01148 
01149                         case ID_SPK:
01150                         case ID_SO:
01151                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break;
01152 
01153 #endif          // GSOC_PEPPER
01154 
01155                         case ID_AR:
01156                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break;
01157                         case ID_CA:
01158                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break;
01159                         case ID_KE:
01160                                 tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break;
01161                         case ID_WO:
01162                                 tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break;
01163                         case ID_AC:
01164                                 tselem_draw_icon_uibut(&arg, ICON_ACTION); break;
01165                         case ID_NLA:
01166                                 tselem_draw_icon_uibut(&arg, ICON_NLA); break;
01167                         case ID_TXT:
01168                                 tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break;
01169                         case ID_GR:
01170                                 tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
01171                         case ID_LI:
01172                                 tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
01173                 }
01174         }
01175 }
01176 
01177 static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys)
01178 {
01179         TreeElement *te;
01180         TreeStoreElem *tselem;
01181         int active;
01182 
01183         for(te= lb->first; te; te= te->next) {
01184                 
01185                 /* exit drawing early */
01186                 if((*offsx) - UI_UNIT_X > xmax)
01187                         break;
01188 
01189                 tselem= TREESTORE(te);
01190                 
01191                 /* object hierarchy always, further constrained on level */
01192                 if(level<1 || (tselem->type==0 && te->idcode==ID_OB)) {
01193 
01194                         /* active blocks get white circle */
01195                         if(tselem->type==0) {
01196                                 if(te->idcode==ID_OB) active= (OBACT==(Object *)tselem->id);
01197                                 else if(scene->obedit && scene->obedit->data==tselem->id) active= 1;    // XXX use context?
01198                                 else active= tree_element_active(C, scene, soops, te, 0);
01199                         }
01200                         else active= tree_element_type_active(NULL, scene, soops, te, tselem, 0);
01201                         
01202                         if(active) {
01203                                 float ufac= UI_UNIT_X/20.0f;
01204 
01205                                 uiSetRoundBox(15);
01206                                 glColor4ub(255, 255, 255, 100);
01207                                 uiRoundBox( (float)*offsx-0.5f*ufac, (float)ys-1.0f*ufac, (float)*offsx+UI_UNIT_Y-3.0f*ufac, (float)ys+UI_UNIT_Y-3.0f*ufac, UI_UNIT_Y/2.0f-2.0f*ufac);
01208                                 glEnable(GL_BLEND); /* roundbox disables */
01209                         }
01210                         
01211                         tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f);
01212                         te->xs= (float)*offsx;
01213                         te->ys= (float)ys;
01214                         te->xend= (short)*offsx+UI_UNIT_X;
01215                         te->flag |= TE_ICONROW; // for click
01216                         
01217                         (*offsx) += UI_UNIT_X;
01218                 }
01219                 
01220                 /* this tree element always has same amount of branches, so dont draw */
01221                 if(tselem->type!=TSE_R_LAYER)
01222                         outliner_draw_iconrow(C, block, scene, soops, &te->subtree, level+1, xmax, offsx, ys);
01223         }
01224         
01225 }
01226 
01227 /* closed tree element */
01228 static void outliner_set_coord_tree_element(SpaceOops *soops, TreeElement *te, int startx, int *starty)
01229 {
01230         TreeElement *ten;
01231         
01232         /* store coord and continue, we need coordinates for elements outside view too */
01233         te->xs= (float)startx;
01234         te->ys= (float)(*starty);
01235         
01236         for(ten= te->subtree.first; ten; ten= ten->next) {
01237                 outliner_set_coord_tree_element(soops, ten, startx+UI_UNIT_X, starty);
01238         }       
01239 }
01240 
01241 
01242 static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty)
01243 {
01244         TreeElement *ten;
01245         TreeStoreElem *tselem;
01246         float ufac= UI_UNIT_X/20.0f;
01247         int offsx= 0, active=0; // active=1 active obj, else active data
01248         
01249         tselem= TREESTORE(te);
01250 
01251         if(*starty+2*UI_UNIT_Y >= ar->v2d.cur.ymin && *starty<= ar->v2d.cur.ymax) {
01252                 int xmax= ar->v2d.cur.xmax;
01253                 
01254                 /* icons can be ui buts, we dont want it to overlap with restrict */
01255                 if((soops->flag & SO_HIDE_RESTRICTCOLS)==0)
01256                         xmax-= OL_TOGW+UI_UNIT_X;
01257                 
01258                 glEnable(GL_BLEND);
01259 
01260                 /* colors for active/selected data */
01261                 if(tselem->type==0) {
01262                         if(te->idcode==ID_SCE) {
01263                                 if(tselem->id == (ID *)scene) {
01264                                         glColor4ub(255, 255, 255, 100);
01265                                         active= 2;
01266                                 }
01267                         }
01268                         else if(te->idcode==ID_GR) {
01269                                 Group *gr = (Group *)tselem->id;
01270                                 
01271                                 if(group_select_flag(gr)) {
01272                                         char col[4];
01273                                         UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
01274                                         col[3]= 100;
01275                                         glColor4ubv((GLubyte *)col);
01276                                         
01277                                         active= 2;
01278                                 }
01279                         }
01280                         else if(te->idcode==ID_OB) {
01281                                 Object *ob= (Object *)tselem->id;
01282                                 
01283                                 if(ob==OBACT || (ob->flag & SELECT)) {
01284                                         char col[4]= {0, 0, 0, 0};
01285                                         
01286                                         /* outliner active ob: always white text, circle color now similar to view3d */
01287                                         
01288                                         active= 2; /* means it draws a color circle */
01289                                         if(ob==OBACT) {
01290                                                 if(ob->flag & SELECT) {
01291                                                         UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
01292                                                         col[3]= 100;
01293                                                 }
01294                                                 
01295                                                 active= 1; /* means it draws white text */
01296                                         }
01297                                         else if(ob->flag & SELECT) {
01298                                                 UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
01299                                                 col[3]= 100;
01300                                         }
01301                                         
01302                                         glColor4ubv((GLubyte *)col);
01303                                 }
01304                         
01305                         }
01306                         else if(scene->obedit && scene->obedit->data==tselem->id) {
01307                                 glColor4ub(255, 255, 255, 100);
01308                                 active= 2;
01309                         }
01310                         else {
01311                                 if(tree_element_active(C, scene, soops, te, 0)) {
01312                                         glColor4ub(220, 220, 255, 100);
01313                                         active= 2;
01314                                 }
01315                         }
01316                 }
01317                 else {
01318                         if( tree_element_type_active(NULL, scene, soops, te, tselem, 0) ) active= 2;
01319                         glColor4ub(220, 220, 255, 100);
01320                 }
01321                 
01322                 /* active circle */
01323                 if(active) {
01324                         uiSetRoundBox(15);
01325                         uiRoundBox( (float)startx+UI_UNIT_Y-1.5f*ufac, (float)*starty+2.0f*ufac, (float)startx+2.0f*UI_UNIT_Y-4.0f*ufac, (float)*starty+UI_UNIT_Y-1.0f*ufac, UI_UNIT_Y/2.0f-2.0f*ufac);
01326                         glEnable(GL_BLEND);     /* roundbox disables it */
01327                         
01328                         te->flag |= TE_ACTIVE; // for lookup in display hierarchies
01329                 }
01330                 
01331                 /* open/close icon, only when sublevels, except for scene */
01332                 if(te->subtree.first || (tselem->type==0 && te->idcode==ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
01333                         int icon_x;
01334                         if(tselem->type==0 && ELEM(te->idcode, ID_OB, ID_SCE))
01335                                 icon_x = startx;
01336                         else
01337                                 icon_x = startx+5*ufac;
01338                         
01339                                 // icons a bit higher
01340                         if(tselem->flag & TSE_CLOSED) 
01341                                 UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_RIGHT);
01342                         else
01343                                 UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_DOWN);
01344                 }
01345                 offsx+= UI_UNIT_X;
01346                 
01347                 /* datatype icon */
01348                 
01349                 if(!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
01350                         // icons a bit higher
01351                         tselem_draw_icon(block, xmax, (float)startx+offsx - 0.5f*ufac, (float)*starty+2.0f*ufac, tselem, te, 1.0f);
01352                         
01353                         offsx+= UI_UNIT_X;
01354                 }
01355                 else
01356                         offsx+= 2*ufac;
01357                 
01358                 if(tselem->type==0 && tselem->id->lib) {
01359                         glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
01360                         if(tselem->id->flag & LIB_INDIRECT)
01361                                 UI_icon_draw((float)startx+offsx, (float)*starty+2*ufac, ICON_LIBRARY_DATA_INDIRECT);
01362                         else
01363                                 UI_icon_draw((float)startx+offsx, (float)*starty+2*ufac, ICON_LIBRARY_DATA_DIRECT);
01364                         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
01365                         offsx+= UI_UNIT_X;
01366                 }               
01367                 glDisable(GL_BLEND);
01368                 
01369                 /* name */
01370                 if(active==1) UI_ThemeColor(TH_TEXT_HI);
01371                 else if(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
01372                 else UI_ThemeColor(TH_TEXT);
01373                 
01374                 UI_DrawString(startx+offsx, *starty+5*ufac, te->name);
01375                 
01376                 offsx+= (int)(UI_UNIT_X + UI_GetStringWidth(te->name));
01377                 
01378                 /* closed item, we draw the icons, not when it's a scene, or master-server list though */
01379                 if(tselem->flag & TSE_CLOSED) {
01380                         if(te->subtree.first) {
01381                                 if(tselem->type==0 && te->idcode==ID_SCE);
01382                                 else if(tselem->type!=TSE_R_LAYER) { /* this tree element always has same amount of branches, so dont draw */
01383                                         int tempx= startx+offsx;
01384                                         
01385                                         // divider
01386                                         UI_ThemeColorShade(TH_BACK, -40);
01387                                         glRecti(tempx -10, *starty+4, tempx -8, *starty+UI_UNIT_Y-4);
01388                                         
01389                                         glEnable(GL_BLEND);
01390                                         glPixelTransferf(GL_ALPHA_SCALE, 0.5);
01391                                         
01392                                         outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty+2);
01393                                         
01394                                         glPixelTransferf(GL_ALPHA_SCALE, 1.0);
01395                                         glDisable(GL_BLEND);
01396                                 }
01397                         }
01398                 }
01399         }       
01400         /* store coord and continue, we need coordinates for elements outside view too */
01401         te->xs= (float)startx;
01402         te->ys= (float)*starty;
01403         te->xend= startx+offsx;
01404                 
01405         if((tselem->flag & TSE_CLOSED)==0) {
01406                 *starty-= UI_UNIT_Y;
01407                 
01408                 for(ten= te->subtree.first; ten; ten= ten->next)
01409                         outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx+UI_UNIT_X, starty);
01410         }       
01411         else {
01412                 for(ten= te->subtree.first; ten; ten= ten->next)
01413                         outliner_set_coord_tree_element(soops, te, startx, starty);
01414                 
01415                 *starty-= UI_UNIT_Y;
01416         }
01417 }
01418 
01419 static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, int *starty)
01420 {
01421         TreeElement *te;
01422         TreeStoreElem *tselem;
01423         int y1, y2;
01424         
01425         if(lb->first==NULL) return;
01426         
01427         y1=y2= *starty; /* for vertical lines between objects */
01428         for(te=lb->first; te; te= te->next) {
01429                 y2= *starty;
01430                 tselem= TREESTORE(te);
01431                 
01432                 /* horizontal line? */
01433                 if(tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE))
01434                         glRecti(startx, *starty, startx+UI_UNIT_X, *starty-1);
01435                         
01436                 *starty-= UI_UNIT_Y;
01437                 
01438                 if((tselem->flag & TSE_CLOSED)==0)
01439                         outliner_draw_hierarchy(soops, &te->subtree, startx+UI_UNIT_X, starty);
01440         }
01441         
01442         /* vertical line */
01443         te= lb->last;
01444         if(te->parent || lb->first!=lb->last) {
01445                 tselem= TREESTORE(te);
01446                 if(tselem->type==0 && te->idcode==ID_OB) {
01447                         
01448                         glRecti(startx, y1+UI_UNIT_Y, startx+1, y2);
01449                 }
01450         }
01451 }
01452 
01453 static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) 
01454 {
01455         TreeElement *te;
01456         TreeStoreElem *tselem;
01457         
01458         for(te= lb->first; te; te= te->next) {
01459                 tselem= TREESTORE(te);
01460                 
01461                 /* selection status */
01462                 if((tselem->flag & TSE_CLOSED)==0)
01463                         if(tselem->type == TSE_RNA_STRUCT)
01464                                 glRecti(0, *starty+1, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, *starty+UI_UNIT_Y-1);
01465 
01466                 *starty-= UI_UNIT_Y;
01467                 if((tselem->flag & TSE_CLOSED)==0) {
01468                         outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
01469                         if(tselem->type == TSE_RNA_STRUCT)
01470                                 fdrawline(0, (float)*starty+UI_UNIT_Y, ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, (float)*starty+UI_UNIT_Y);
01471                 }
01472         }
01473 }
01474 
01475 static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) 
01476 {
01477         TreeElement *te;
01478         TreeStoreElem *tselem;
01479         
01480         for(te= lb->first; te; te= te->next) {
01481                 tselem= TREESTORE(te);
01482                 
01483                 /* selection status */
01484                 if(tselem->flag & TSE_SELECTED) {
01485                         glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+UI_UNIT_Y-1);
01486                 }
01487                 *starty-= UI_UNIT_Y;
01488                 if((tselem->flag & TSE_CLOSED)==0) outliner_draw_selection(ar, soops, &te->subtree, starty);
01489         }
01490 }
01491 
01492 
01493 static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops)
01494 {
01495         TreeElement *te;
01496         int starty, startx;
01497         float col[4];
01498                 
01499         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); // only once
01500         
01501         if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
01502                 /* struct marks */
01503                 UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
01504                 //UI_ThemeColorShade(TH_BACK, -20);
01505                 starty= (int)ar->v2d.tot.ymax-UI_UNIT_Y-OL_Y_OFFSET;
01506                 outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
01507         }
01508         
01509         /* always draw selection fill before hierarchy */
01510         UI_GetThemeColor3fv(TH_BACK, col);
01511         glColor3f(col[0]+0.06f, col[1]+0.08f, col[2]+0.10f);
01512         starty= (int)ar->v2d.tot.ymax-UI_UNIT_Y-OL_Y_OFFSET;
01513         outliner_draw_selection(ar, soops, &soops->tree, &starty);
01514         
01515         // grey hierarchy lines
01516         UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f);
01517         starty= (int)ar->v2d.tot.ymax-UI_UNIT_Y/2-OL_Y_OFFSET;
01518         startx= 6;
01519         outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
01520         
01521         // items themselves
01522         starty= (int)ar->v2d.tot.ymax-UI_UNIT_Y-OL_Y_OFFSET;
01523         startx= 0;
01524         for(te= soops->tree.first; te; te= te->next) {
01525                 outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty);
01526         }
01527 }
01528 
01529 
01530 static void outliner_back(ARegion *ar)
01531 {
01532         int ystart;
01533         
01534         UI_ThemeColorShade(TH_BACK, 6);
01535         ystart= (int)ar->v2d.tot.ymax;
01536         ystart= UI_UNIT_Y*(ystart/(UI_UNIT_Y))-OL_Y_OFFSET;
01537         
01538         while(ystart+2*UI_UNIT_Y > ar->v2d.cur.ymin) {
01539                 glRecti(0, ystart, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, ystart+UI_UNIT_Y);
01540                 ystart-= 2*UI_UNIT_Y;
01541         }
01542 }
01543 
01544 static void outliner_draw_restrictcols(ARegion *ar)
01545 {
01546         int ystart;
01547         
01548         /* background underneath */
01549         UI_ThemeColor(TH_BACK);
01550         glRecti((int)ar->v2d.cur.xmax-OL_TOGW, (int)ar->v2d.cur.ymin-V2D_SCROLL_HEIGHT-1, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, (int)ar->v2d.cur.ymax);
01551         
01552         UI_ThemeColorShade(TH_BACK, 6);
01553         ystart= (int)ar->v2d.tot.ymax;
01554         ystart= UI_UNIT_Y*(ystart/(UI_UNIT_Y))-OL_Y_OFFSET;
01555         
01556         while(ystart+2*UI_UNIT_Y > ar->v2d.cur.ymin) {
01557                 glRecti((int)ar->v2d.cur.xmax-OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart+UI_UNIT_Y);
01558                 ystart-= 2*UI_UNIT_Y;
01559         }
01560         
01561         UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
01562 
01563         /* view */
01564         fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX,
01565                 ar->v2d.cur.ymax,
01566                 ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX,
01567                 ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
01568 
01569         /* render */
01570         fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX,
01571                 ar->v2d.cur.ymax,
01572                 ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX,
01573                 ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
01574 
01575         /* render */
01576         fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX,
01577                 ar->v2d.cur.ymax,
01578                 ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX,
01579                 ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
01580 }
01581 
01582 /* ****************************************************** */
01583 /* Main Entrypoint - Draw contents of Outliner editor */
01584  
01585 void draw_outliner(const bContext *C)
01586 {
01587         Main *mainvar= CTX_data_main(C);
01588         Scene *scene= CTX_data_scene(C);
01589         ARegion *ar= CTX_wm_region(C);
01590         View2D *v2d= &ar->v2d;
01591         SpaceOops *soops= CTX_wm_space_outliner(C);
01592         uiBlock *block;
01593         int sizey= 0, sizex= 0, sizex_rna= 0;
01594         
01595         outliner_build_tree(mainvar, scene, soops); // always 
01596         
01597         /* get extents of data */
01598         outliner_height(soops, &soops->tree, &sizey);
01599 
01600         if (ELEM3(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF, SO_KEYMAP)) {
01601                 /* RNA has two columns:
01602                  *      - column 1 is (max_width + OL_RNA_COL_SPACEX) or
01603                  *                               (OL_RNA_COL_X), whichever is wider...
01604                  *      - column 2 is fixed at OL_RNA_COL_SIZEX
01605                  *
01606                  *  (*) XXX max width for now is a fixed factor of UI_UNIT_X*(max_indention+100)
01607                  */
01608                  
01609                 /* get actual width of column 1 */
01610                 outliner_rna_width(soops, &soops->tree, &sizex_rna, 0);
01611                 sizex_rna= MAX2(OL_RNA_COLX, sizex_rna+OL_RNA_COL_SPACEX);
01612                 
01613                 /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
01614                 if (soops->outlinevis == SO_KEYMAP) 
01615                         sizex= sizex_rna + OL_RNA_COL_SIZEX*3 + 50; // XXX this is only really a quick hack to make this wide enough...
01616                 else
01617                         sizex= sizex_rna + OL_RNA_COL_SIZEX + 50;
01618         }
01619         else {
01620                 /* width must take into account restriction columns (if visible) so that entries will still be visible */
01621                 //outliner_width(soops, &soops->tree, &sizex);
01622                 outliner_rna_width(soops, &soops->tree, &sizex, 0); // XXX should use outliner_width instead when te->xend will be set correctly...
01623                 
01624                 /* constant offset for restriction columns */
01625                 // XXX this isn't that great yet...
01626                 if ((soops->flag & SO_HIDE_RESTRICTCOLS)==0)
01627                         sizex += OL_TOGW*3;
01628         }
01629         
01630         /* tweak to display last line (when list bigger than window) */
01631         sizey += V2D_SCROLL_HEIGHT;
01632         
01633         /* adds vertical offset */
01634         sizey += OL_Y_OFFSET;
01635 
01636         /* update size of tot-rect (extents of data/viewable area) */
01637         UI_view2d_totRect_set(v2d, sizex, sizey);
01638 
01639         /* force display to pixel coords */
01640         v2d->flag |= (V2D_PIXELOFS_X|V2D_PIXELOFS_Y);
01641         /* set matrix for 2d-view controls */
01642         UI_view2d_view_ortho(v2d);
01643 
01644         /* draw outliner stuff (background, hierachy lines and names) */
01645         outliner_back(ar);
01646         block= uiBeginBlock(C, ar, "outliner buttons", UI_EMBOSS);
01647         outliner_draw_tree((bContext *)C, block, scene, ar, soops);
01648         
01649         if(ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
01650                 /* draw rna buttons */
01651                 outliner_draw_rnacols(ar, sizex_rna);
01652                 outliner_draw_rnabuts(block, scene, ar, soops, sizex_rna, &soops->tree);
01653         }
01654         else if(soops->outlinevis == SO_KEYMAP) {
01655                 outliner_draw_keymapbuts(block, ar, soops, &soops->tree);
01656         }
01657         else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) {
01658                 /* draw restriction columns */
01659                 outliner_draw_restrictcols(ar);
01660                 outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree);
01661         }
01662 
01663         /* draw edit buttons if nessecery */
01664         outliner_buttons(C, block, ar, soops, &soops->tree);    
01665 
01666         uiEndBlock(C, block);
01667         uiDrawBlock(C, block);
01668         
01669         /* clear flag that allows quick redraws */
01670         soops->storeflag &= ~SO_TREESTORE_REDRAW;
01671 }