code cleanup: favor braces when blocks have mixed brace use.
[blender.git] / source / blender / editors / space_outliner / outliner_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2004 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_outliner/outliner_draw.c
29  *  \ingroup spoutliner
30  */
31
32 #include "DNA_armature_types.h"
33 #include "DNA_group_types.h"
34 #include "DNA_lamp_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_sequence_types.h"
38
39 #include "BLI_math.h"
40 #include "BLI_blenlib.h"
41 #include "BLI_utildefines.h"
42 #include "BLI_ghash.h"
43
44 #include "BKE_context.h"
45 #include "BKE_deform.h"
46 #include "BKE_depsgraph.h"
47 #include "BKE_global.h"
48 #include "BKE_library.h"
49 #include "BKE_main.h"
50 #include "BKE_modifier.h"
51 #include "BKE_report.h"
52 #include "BKE_scene.h"
53
54 #include "ED_armature.h"
55 #include "ED_object.h"
56 #include "ED_screen.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #include "BIF_gl.h"
62 #include "BIF_glutil.h"
63
64 #include "UI_interface.h"
65 #include "UI_interface_icons.h"
66 #include "UI_resources.h"
67 #include "UI_view2d.h"
68
69 #include "RNA_access.h"
70
71 #include "outliner_intern.h"
72
73 /* disable - this is far too slow - campbell */
74 // #define USE_GROUP_SELECT
75
76 /* ****************************************************** */
77 /* Tree Size Functions */
78
79 static void outliner_height(SpaceOops *soops, ListBase *lb, int *h)
80 {
81         TreeElement *te = lb->first;
82         while (te) {
83                 TreeStoreElem *tselem = TREESTORE(te);
84                 if (TSELEM_OPEN(tselem, soops))
85                         outliner_height(soops, &te->subtree, h);
86                 (*h) += UI_UNIT_Y;
87                 te = te->next;
88         }
89 }
90
91 #if 0  // XXX this is currently disabled until te->xend is set correctly
92 static void outliner_width(SpaceOops *soops, ListBase *lb, int *w)
93 {
94         TreeElement *te = lb->first;
95         while (te) {
96 //              TreeStoreElem *tselem = TREESTORE(te);
97                 
98                 // XXX fixme... te->xend is not set yet
99                 if (!TSELEM_OPEN(tselem, soops)) {
100                         if (te->xend > *w)
101                                 *w = te->xend;
102                 }
103                 outliner_width(soops, &te->subtree, w);
104                 te = te->next;
105         }
106 }
107 #endif
108
109 static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int startx)
110 {
111         TreeElement *te = lb->first;
112         while (te) {
113                 TreeStoreElem *tselem = TREESTORE(te);
114                 // XXX fixme... (currently, we're using a fixed length of 100)!
115 #if 0
116                 if (te->xend) {
117                         if (te->xend > *w)
118                                 *w = te->xend;
119                 }
120 #endif
121                 if (startx + 100 > *w)
122                         *w = startx + 100;
123
124                 if (TSELEM_OPEN(tselem, soops))
125                         outliner_rna_width(soops, &te->subtree, w, startx + UI_UNIT_X);
126                 te = te->next;
127         }
128 }
129
130 /* ****************************************************** */
131
132 static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
133 {
134         Scene *scene = (Scene *)poin;
135         Object *ob = (Object *)poin2;
136
137         if (!common_restrict_check(C, ob)) return;
138         
139         /* deselect objects that are invisible */
140         if (ob->restrictflag & OB_RESTRICT_VIEW) {
141                 /* Ouch! There is no backwards pointer from Object to Base, 
142                  * so have to do loop to find it. */
143                 ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
144         }
145         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
146
147 }
148
149 static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2)
150 {
151         Scene *scene = (Scene *)poin;
152         Object *ob = (Object *)poin2;
153         
154         if (!common_restrict_check(C, ob)) return;
155         
156         /* if select restriction has just been turned on */
157         if (ob->restrictflag & OB_RESTRICT_SELECT) {
158                 /* Ouch! There is no backwards pointer from Object to Base, 
159                  * so have to do loop to find it. */
160                 ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
161         }
162         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
163
164 }
165
166 static void restrictbutton_rend_cb(bContext *C, void *poin, void *UNUSED(poin2))
167 {
168         WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin);
169 }
170
171 static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2))
172 {
173         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin);
174 }
175
176 static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *poin2)
177 {
178         Object *ob = (Object *)poin2;
179         
180         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
181
182         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
183 }
184
185 static void restrictbutton_bone_cb(bContext *C, void *UNUSED(poin), void *poin2)
186 {
187         Bone *bone = (Bone *)poin2;
188         if (bone && (bone->flag & BONE_HIDDEN_P))
189                 bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
190         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
191 }
192
193 static void restrictbutton_ebone_cb(bContext *C, void *UNUSED(poin), void *poin2)
194 {
195         EditBone *ebone = (EditBone *)poin2;
196         if (ebone && (ebone->flag & BONE_HIDDEN_A))
197                 ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
198
199         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
200 }
201
202 static int group_restrict_flag(Group *gr, int flag)
203 {
204         GroupObject *gob;
205
206 #ifdef USE_GROUP_SELECT
207         for (gob = gr->gobject.first; gob; gob = gob->next) {
208                 if ((gob->ob->restrictflag & flag) == 0)
209                         return 0;
210         }
211         return 1;
212 #else
213         /* weak but fast */
214         if ((gob = gr->gobject.first))
215                 if ((gob->ob->restrictflag & flag) == 0)
216                         return 0;
217         return 1;
218 #endif
219 }
220
221 static int group_select_flag(Group *gr)
222 {
223         GroupObject *gob;
224
225 #ifdef USE_GROUP_SELECT
226         for (gob = gr->gobject.first; gob; gob = gob->next)
227                 if ((gob->ob->flag & SELECT))
228                         return 1;
229
230         return 0;
231 #else
232         /* weak but fast */
233         if ((gob = gr->gobject.first))
234                 if (gob->ob->flag & SELECT)
235                         return 1;
236         return 0;
237 #endif
238 }
239
240 void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag)
241 {       
242         Scene *scene = (Scene *)poin;
243         GroupObject *gob;
244         Group *gr = (Group *)poin2;
245
246         if (group_restrict_flag(gr, flag)) {
247                 for (gob = gr->gobject.first; gob; gob = gob->next) {
248                         gob->ob->restrictflag &= ~flag;
249                         
250                         if (flag == OB_RESTRICT_VIEW)
251                                 if (gob->ob->flag & SELECT)
252                                         ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT);
253                 }
254         }
255         else {
256                 for (gob = gr->gobject.first; gob; gob = gob->next) {
257                         /* not in editmode */
258                         if (scene->obedit != gob->ob) {
259                                 gob->ob->restrictflag |= flag;
260
261                                 if (ELEM(flag, OB_RESTRICT_SELECT, OB_RESTRICT_VIEW)) {
262                                         if ((gob->ob->flag & SELECT)) {
263                                                 ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT);
264                                         }
265                                 }
266                         }
267                 }
268         }
269
270
271 static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2)
272 {
273         restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_VIEW);
274         WM_event_add_notifier(C, NC_GROUP, NULL);
275 }
276 static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2)
277 {
278         restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_SELECT);
279         WM_event_add_notifier(C, NC_GROUP, NULL);
280 }
281 static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poin2)
282 {
283         restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_RENDER);
284         WM_event_add_notifier(C, NC_GROUP, NULL);
285 }
286
287
288 static void namebutton_cb(bContext *C, void *tsep, char *oldname)
289 {
290         SpaceOops *soops = CTX_wm_space_outliner(C);
291         Scene *scene = CTX_data_scene(C);
292         Object *obedit = CTX_data_edit_object(C);
293         TreeStore *ts = soops->treestore;
294         TreeStoreElem *tselem = tsep;
295         
296         if (ts && tselem) {
297                 TreeElement *te = outliner_find_tse(soops, tselem);
298                 
299                 if (tselem->type == 0) {
300                         test_idbutton(tselem->id->name + 2);  // library.c, unique name and alpha sort
301                         
302                         switch (GS(tselem->id->name)) {
303                                 case ID_MA:
304                                         WM_event_add_notifier(C, NC_MATERIAL, NULL); break;
305                                 case ID_TE:
306                                         WM_event_add_notifier(C, NC_TEXTURE, NULL); break;
307                                 case ID_IM:
308                                         WM_event_add_notifier(C, NC_IMAGE, NULL); break;
309                                 case ID_SCE:
310                                         WM_event_add_notifier(C, NC_SCENE, NULL); break;
311                                 default:
312                                         WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break;
313                         }
314                         /* Check the library target exists */
315                         if (te->idcode == ID_LI) {
316                                 Library *lib = (Library *)tselem->id;
317                                 char expanded[FILE_MAX];
318
319                                 BKE_library_filepath_set(lib, lib->name);
320
321                                 BLI_strncpy(expanded, lib->name, sizeof(expanded));
322                                 BLI_path_abs(expanded, G.main->name);
323                                 if (!BLI_exists(expanded)) {
324                                         BKE_reportf(CTX_wm_reports(C), RPT_ERROR,
325                                                     "Library path '%s' does not exist, correct this before saving", expanded);
326                                 }
327                         }
328                 }
329                 else {
330                         switch (tselem->type) {
331                                 case TSE_DEFGROUP:
332                                         defgroup_unique_name(te->directdata, (Object *)tselem->id); //  id = object
333                                         break;
334                                 case TSE_NLA_ACTION:
335                                         test_idbutton(tselem->id->name + 2);
336                                         break;
337                                 case TSE_EBONE:
338                                 {
339                                         bArmature *arm = (bArmature *)tselem->id;
340                                         if (arm->edbo) {
341                                                 EditBone *ebone = te->directdata;
342                                                 char newname[sizeof(ebone->name)];
343
344                                                 /* restore bone name */
345                                                 BLI_strncpy(newname, ebone->name, sizeof(ebone->name));
346                                                 BLI_strncpy(ebone->name, oldname, sizeof(ebone->name));
347                                                 ED_armature_bone_rename(obedit->data, oldname, newname);
348                                                 WM_event_add_notifier(C, NC_OBJECT | ND_POSE, OBACT);
349                                         }
350                                 }
351                                 break;
352
353                                 case TSE_BONE:
354                                 {
355                                         Bone *bone = te->directdata;
356                                         Object *ob;
357                                         char newname[sizeof(bone->name)];
358                                         
359                                         // always make current object active
360                                         tree_element_active(C, scene, soops, te, 1); // was set_active_object()
361                                         ob = OBACT;
362                                         
363                                         /* restore bone name */
364                                         BLI_strncpy(newname, bone->name, sizeof(bone->name));
365                                         BLI_strncpy(bone->name, oldname, sizeof(bone->name));
366                                         ED_armature_bone_rename(ob->data, oldname, newname);
367                                         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
368                                 }
369                                 break;
370                                 case TSE_POSE_CHANNEL:
371                                 {
372                                         bPoseChannel *pchan = te->directdata;
373                                         Object *ob;
374                                         char newname[sizeof(pchan->name)];
375                                         
376                                         // always make current object active
377                                         tree_element_active(C, scene, soops, te, 1); // was set_active_object()
378                                         ob = OBACT;
379                                         
380                                         /* restore bone name */
381                                         BLI_strncpy(newname, pchan->name, sizeof(pchan->name));
382                                         BLI_strncpy(pchan->name, oldname, sizeof(pchan->name));
383                                         ED_armature_bone_rename(ob->data, oldname, newname);
384                                         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
385                                 }
386                                 break;
387                                 case TSE_POSEGRP:
388                                 {
389                                         Object *ob = (Object *)tselem->id; // id = object
390                                         bActionGroup *grp = te->directdata;
391                                         
392                                         BLI_uniquename(&ob->pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name));
393                                         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
394                                 }
395                                 break;
396                                 case TSE_R_LAYER:
397                                         break;
398                         }
399                 }
400                 tselem->flag &= ~TSE_TEXTBUT;
401         }
402 }
403
404 static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, ListBase *lb)
405 {       
406         uiBut *bt;
407         TreeElement *te;
408         TreeStoreElem *tselem;
409         Object *ob = NULL;
410         Group  *gr = NULL;
411
412         for (te = lb->first; te; te = te->next) {
413                 tselem = TREESTORE(te);
414                 if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
415                         /* objects have toggle-able restriction flags */
416                         if (tselem->type == 0 && te->idcode == ID_OB) {
417                                 PointerRNA ptr;
418                                 
419                                 ob = (Object *)tselem->id;
420                                 RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr);
421                                 
422                                 uiBlockSetEmboss(block, UI_EMBOSSN);
423                                 bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_VIEW_OFF,
424                                                    (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
425                                                    &ptr, "hide", -1, 0, 0, -1, -1, NULL);
426                                 uiButSetFunc(bt, restrictbutton_view_cb, scene, ob);
427                                 
428                                 bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_SELECT_OFF,
429                                                    (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
430                                                    &ptr, "hide_select", -1, 0, 0, -1, -1, NULL);
431                                 uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob);
432                                 
433                                 bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_RENDER_OFF,
434                                                    (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
435                                                    &ptr, "hide_render", -1, 0, 0, -1, -1, NULL);
436                                 uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob);
437                                 
438                                 uiBlockSetEmboss(block, UI_EMBOSS);
439                                 
440                         }
441                         if (tselem->type == 0 && te->idcode == ID_GR) {
442                                 int restrict_bool;
443                                 gr = (Group *)tselem->id;
444                                 
445                                 uiBlockSetEmboss(block, UI_EMBOSSN);
446
447                                 restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW);
448                                 bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
449                                                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
450                                                   NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
451                                 uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr);
452
453                                 restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
454                                 bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
455                                                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
456                                                   NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
457                                 uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr);
458
459                                 restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
460                                 bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
461                                                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
462                                                   NULL, 0, 0, 0, 0, "Restrict/Allow renderability");
463                                 uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr);
464
465                                 uiBlockSetEmboss(block, UI_EMBOSS);
466                         }
467                         /* scene render layers and passes have toggle-able flags too! */
468                         else if (tselem->type == TSE_R_LAYER) {
469                                 uiBlockSetEmboss(block, UI_EMBOSSN);
470                                 
471                                 bt = uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
472                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
473                                                       te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
474                                 uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
475                                 
476                                 uiBlockSetEmboss(block, UI_EMBOSS);
477                         }
478                         else if (tselem->type == TSE_R_PASS) {
479                                 int *layflag = te->directdata;
480                                 int passflag = 1 << tselem->nr;
481                                 
482                                 uiBlockSetEmboss(block, UI_EMBOSSN);
483                                 
484                                 
485                                 bt = uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT - 1,
486                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
487                                                       layflag, 0, 0, 0, 0, "Render this Pass");
488                                 uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
489                                 
490                                 layflag++;  /* is lay_xor */
491                                 if (ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT,
492                                           SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
493                                 {
494                                         bt = uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag) ? ICON_DOT : ICON_BLANK1,
495                                                               (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
496                                                               layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
497                                 }
498                                 uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
499                                 
500                                 uiBlockSetEmboss(block, UI_EMBOSS);
501                         }
502                         else if (tselem->type == TSE_MODIFIER) {
503                                 ModifierData *md = (ModifierData *)te->directdata;
504                                 ob = (Object *)tselem->id;
505                                 
506                                 uiBlockSetEmboss(block, UI_EMBOSSN);
507                                 bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
508                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
509                                                       &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
510                                 uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
511                                 
512                                 bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
513                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
514                                                       &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
515                                 uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
516                         }
517                         else if (tselem->type == TSE_POSE_CHANNEL) {
518                                 bPoseChannel *pchan = (bPoseChannel *)te->directdata;
519                                 Bone *bone = pchan->bone;
520                                 
521                                 uiBlockSetEmboss(block, UI_EMBOSSN);
522                                 bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF,
523                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
524                                                       &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
525                                 uiButSetFunc(bt, restrictbutton_bone_cb, NULL, bone);
526                                 
527                                 bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
528                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
529                                                       &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
530                                 uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
531                         }
532                         else if (tselem->type == TSE_EBONE) {
533                                 EditBone *ebone = (EditBone *)te->directdata;
534                                 
535                                 uiBlockSetEmboss(block, UI_EMBOSSN);
536                                 bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
537                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
538                                                       &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
539                                 uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, ebone);
540                                 
541                                 bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
542                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
543                                                       &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
544                                 uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, NULL);
545                         }
546                 }
547                 
548                 if (TSELEM_OPEN(tselem, soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
549         }
550 }
551
552 static void outliner_draw_rnacols(ARegion *ar, int sizex)
553 {
554         View2D *v2d = &ar->v2d;
555
556         float miny = v2d->cur.ymin;
557         if (miny < v2d->tot.ymin) miny = v2d->tot.ymin;
558
559         UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
560
561         /* draw column separator lines */
562         fdrawline((float)sizex,
563                   v2d->cur.ymax,
564                   (float)sizex,
565                   miny);
566
567         fdrawline((float)sizex + OL_RNA_COL_SIZEX,
568                   v2d->cur.ymax,
569                   (float)sizex + OL_RNA_COL_SIZEX,
570                   miny);
571 }
572
573 static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
574 {       
575         TreeElement *te;
576         TreeStoreElem *tselem;
577         PointerRNA *ptr;
578         PropertyRNA *prop;
579         
580         uiBlockSetEmboss(block, UI_EMBOSST);
581
582         for (te = lb->first; te; te = te->next) {
583                 tselem = TREESTORE(te);
584                 if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
585                         if (tselem->type == TSE_RNA_PROPERTY) {
586                                 ptr = &te->rnaptr;
587                                 prop = te->directdata;
588                                 
589                                 if (!(RNA_property_type(prop) == PROP_POINTER && (TSELEM_OPEN(tselem, soops))) )
590                                         uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y - 1);
591                         }
592                         else if (tselem->type == TSE_RNA_ARRAY_ELEM) {
593                                 ptr = &te->rnaptr;
594                                 prop = te->directdata;
595                                 
596                                 uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y - 1);
597                         }
598                 }
599                 
600                 if (TSELEM_OPEN(tselem, soops)) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
601         }
602 }
603
604 static void operator_call_cb(struct bContext *UNUSED(C), void *arg_kmi, void *arg2)
605 {
606         wmOperatorType *ot = arg2;
607         wmKeyMapItem *kmi = arg_kmi;
608         
609         if (ot)
610                 BLI_strncpy(kmi->idname, ot->idname, OP_MAX_TYPENAME);
611 }
612
613 static void operator_search_cb(const struct bContext *UNUSED(C), void *UNUSED(arg_kmi),
614                                const char *str, uiSearchItems *items)
615 {
616         GHashIterator *iter = WM_operatortype_iter();
617
618         for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
619                 wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
620                 
621                 if (BLI_strcasestr(ot->idname, str)) {
622                         char name[OP_MAX_TYPENAME];
623                         
624                         /* display name for menu */
625                         WM_operator_py_idname(name, ot->idname);
626                         
627                         if (0 == uiSearchItemAdd(items, name, ot, 0))
628                                 break;
629                 }
630         }
631         BLI_ghashIterator_free(iter);
632 }
633
634 /* operator Search browse menu, open */
635 static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi)
636 {
637         static char search[OP_MAX_TYPENAME];
638         wmEvent event;
639         wmWindow *win = CTX_wm_window(C);
640         wmKeyMapItem *kmi = arg_kmi;
641         wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0);
642         uiBlock *block;
643         uiBut *but;
644         
645         /* clear initial search string, then all items show */
646         search[0] = 0;
647         
648         block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
649         uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU);
650         
651         /* fake button, it holds space for search items */
652         uiDefBut(block, LABEL, 0, "", 10, 15, uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL);
653         
654         but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, UI_UNIT_Y, 0, 0, "");
655         uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot);
656         
657         uiBoundsBlock(block, 6);
658         uiBlockSetDirection(block, UI_DOWN);
659         uiEndBlock(C, block);
660         
661         event = *(win->eventstate);  /* XXX huh huh? make api call */
662         event.type = EVT_BUT_OPEN;
663         event.val = KM_PRESS;
664         event.customdata = but;
665         event.customdatafree = FALSE;
666         wm_event_add(win, &event);
667         
668         return block;
669 }
670
671 #define OL_KM_KEYBOARD      0
672 #define OL_KM_MOUSE         1
673 #define OL_KM_TWEAK         2
674 #define OL_KM_SPECIALS      3
675
676 static short keymap_menu_type(short type)
677 {
678         if (ISKEYBOARD(type)) return OL_KM_KEYBOARD;
679         if (ISTWEAK(type)) return OL_KM_TWEAK;
680         if (ISMOUSE(type)) return OL_KM_MOUSE;
681 //      return OL_KM_SPECIALS;
682         return 0;
683 }
684
685 static const char *keymap_type_menu(void)
686 {
687         static const char string[] =
688             "Event Type%t"
689             "|Keyboard%x" STRINGIFY(OL_KM_KEYBOARD)
690             "|Mouse%x" STRINGIFY(OL_KM_MOUSE)
691             "|Tweak%x" STRINGIFY(OL_KM_TWEAK)
692 //      "|Specials%x" STRINGIFY(OL_KM_SPECIALS)
693         ;
694
695         return string;
696 }
697
698 static const char *keymap_mouse_menu(void)
699 {
700         static const char string[] =
701             "Mouse Event%t"
702             "|Left Mouse%x" STRINGIFY(LEFTMOUSE)
703             "|Middle Mouse%x" STRINGIFY(MIDDLEMOUSE)
704             "|Right Mouse%x" STRINGIFY(RIGHTMOUSE)
705             "|Middle Mouse%x" STRINGIFY(MIDDLEMOUSE)
706             "|Right Mouse%x" STRINGIFY(RIGHTMOUSE)
707             "|Button4 Mouse%x" STRINGIFY(BUTTON4MOUSE)
708             "|Button5 Mouse%x" STRINGIFY(BUTTON5MOUSE)
709             "|Action Mouse%x" STRINGIFY(ACTIONMOUSE)
710             "|Select Mouse%x" STRINGIFY(SELECTMOUSE)
711             "|Mouse Move%x" STRINGIFY(MOUSEMOVE)
712             "|Wheel Up%x" STRINGIFY(WHEELUPMOUSE)
713             "|Wheel Down%x" STRINGIFY(WHEELDOWNMOUSE)
714             "|Wheel In%x" STRINGIFY(WHEELINMOUSE)
715             "|Wheel Out%x" STRINGIFY(WHEELOUTMOUSE)
716             "|Mouse/Trackpad Pan%x" STRINGIFY(MOUSEPAN)
717             "|Mouse/Trackpad Zoom%x" STRINGIFY(MOUSEZOOM)
718             "|Mouse/Trackpad Rotate%x" STRINGIFY(MOUSEROTATE)
719         ;
720
721         return string;
722 }
723
724 static const char *keymap_tweak_menu(void)
725 {
726         static const char string[] =
727             "Tweak Event%t"
728             "|Left Mouse%x" STRINGIFY(EVT_TWEAK_L)
729             "|Middle Mouse%x" STRINGIFY(EVT_TWEAK_M)
730             "|Right Mouse%x" STRINGIFY(EVT_TWEAK_R)
731             "|Action Mouse%x" STRINGIFY(EVT_TWEAK_A)
732             "|Select Mouse%x" STRINGIFY(EVT_TWEAK_S)
733         ;
734
735         return string;
736 }
737
738 static const char *keymap_tweak_dir_menu(void)
739 {
740         static const char string[] =
741             "Tweak Direction%t"
742             "|Any%x" STRINGIFY(KM_ANY)
743             "|North%x" STRINGIFY(EVT_GESTURE_N)
744             "|North-East%x" STRINGIFY(EVT_GESTURE_NE)
745             "|East%x" STRINGIFY(EVT_GESTURE_E)
746             "|Sout-East%x" STRINGIFY(EVT_GESTURE_SE)
747             "|South%x" STRINGIFY(EVT_GESTURE_S)
748             "|South-West%x" STRINGIFY(EVT_GESTURE_SW)
749             "|West%x" STRINGIFY(EVT_GESTURE_W)
750             "|North-West%x" STRINGIFY(EVT_GESTURE_NW)
751         ;
752
753         return string;
754 }
755
756
757 static void keymap_type_cb(bContext *C, void *kmi_v, void *UNUSED(arg_v))
758 {
759         wmKeyMapItem *kmi = kmi_v;
760         short maptype = keymap_menu_type(kmi->type);
761         
762         if (maptype != kmi->maptype) {
763                 switch (kmi->maptype) {
764                         case OL_KM_KEYBOARD:
765                                 kmi->type = AKEY;
766                                 kmi->val = KM_PRESS;
767                                 break;
768                         case OL_KM_MOUSE:
769                                 kmi->type = LEFTMOUSE;
770                                 kmi->val = KM_PRESS;
771                                 break;
772                         case OL_KM_TWEAK:
773                                 kmi->type = EVT_TWEAK_L;
774                                 kmi->val = KM_ANY;
775                                 break;
776                         case OL_KM_SPECIALS:
777                                 kmi->type = AKEY;
778                                 kmi->val = KM_PRESS;
779                 }
780                 ED_region_tag_redraw(CTX_wm_region(C));
781         }
782 }
783
784 static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
785 {
786         TreeElement *te;
787         TreeStoreElem *tselem;
788         
789         uiBlockSetEmboss(block, UI_EMBOSST);
790         
791         for (te = lb->first; te; te = te->next) {
792                 tselem = TREESTORE(te);
793                 if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
794                         uiBut *but;
795                         const char *str;
796                         int xstart = 240;
797                         int butw1 = UI_UNIT_X; /* operator */
798                         int butw2 = 90; /* event type, menus */
799                         int butw3 = 43; /* modifiers */
800
801                         if (tselem->type == TSE_KEYMAP_ITEM) {
802                                 wmKeyMapItem *kmi = te->directdata;
803                                 
804                                 /* modal map? */
805                                 if (kmi->propvalue) {
806                                         /* pass */
807                                 }
808                                 else {
809                                         uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys + 1, butw1, UI_UNIT_Y - 1, "Assign new Operator");
810                                 }
811                                 xstart += butw1 + 10;
812                                 
813                                 /* map type button */
814                                 kmi->maptype = keymap_menu_type(kmi->type);
815                                 
816                                 str = keymap_type_menu();
817                                 but = uiDefButS(block, MENU, 0, str,    xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->maptype, 0, 0, 0, 0, "Event type");
818                                 uiButSetFunc(but, keymap_type_cb, kmi, NULL);
819                                 xstart += butw2 + 5;
820                                 
821                                 /* edit actual event */
822                                 switch (kmi->maptype) {
823                                         case OL_KM_KEYBOARD:
824                                                 uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type, "Key code");
825                                                 xstart += butw2 + 5;
826                                                 break;
827                                         case OL_KM_MOUSE:
828                                                 str = keymap_mouse_menu();
829                                                 uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type, 0, 0, 0, 0,  "Mouse button");
830                                                 xstart += butw2 + 5;
831                                                 break;
832                                         case OL_KM_TWEAK:
833                                                 str = keymap_tweak_menu();
834                                                 uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type, 0, 0, 0, 0,  "Tweak gesture");
835                                                 xstart += butw2 + 5;
836                                                 str = keymap_tweak_dir_menu();
837                                                 uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->val, 0, 0, 0, 0,  "Tweak gesture direction");
838                                                 xstart += butw2 + 5;
839                                                 break;
840                                 }
841                                 
842                                 /* modifiers */
843                                 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;
844                                 uiDefButS(block, OPTION, 0, "Ctrl", xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->ctrl, 0, 0, 0, 0, "Modifier"); xstart += butw3;
845                                 uiDefButS(block, OPTION, 0, "Alt",  xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->alt, 0, 0, 0, 0, "Modifier"); xstart += butw3;
846                                 uiDefButS(block, OPTION, 0, "OS",   xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->oskey, 0, 0, 0, 0, "Modifier"); xstart += butw3;
847                                 xstart += 5;
848                                 uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->keymodifier, "Key Modifier code");
849                                 xstart += butw3 + 5;
850                                 
851                                 /* rna property */
852                                 if (kmi->ptr && kmi->ptr->data) {
853                                         uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, ""); xstart += butw2;
854                                 }
855
856                                 (void)xstart;
857                         }
858                 }
859                 
860                 if (TSELEM_OPEN(tselem, soops)) outliner_draw_keymapbuts(block, ar, soops, &te->subtree);
861         }
862 }
863
864
865 static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
866 {
867         uiBut *bt;
868         TreeElement *te;
869         TreeStoreElem *tselem;
870         int spx, dx, len;
871         
872         for (te = lb->first; te; te = te->next) {
873                 tselem = TREESTORE(te);
874                 if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
875                         
876                         if (tselem->flag & TSE_TEXTBUT) {
877                                 
878                                 /* If we add support to rename Sequence.
879                                  * need change this.
880                                  */
881                                 if (tselem->type == TSE_POSE_BASE) continue;  // prevent crash when trying to rename 'pose' entry of armature
882                                 
883                                 if (tselem->type == TSE_EBONE) len = sizeof(((EditBone *) 0)->name);
884                                 else if (tselem->type == TSE_MODIFIER) len = sizeof(((ModifierData *) 0)->name);
885                                 else if (tselem->id && GS(tselem->id->name) == ID_LI) len = sizeof(((Library *) 0)->name);
886                                 else len = MAX_ID_NAME - 2;
887                                 
888
889                                 dx = (int)UI_GetStringWidth(te->name);
890                                 if (dx < 100) dx = 100;
891                                 spx = te->xs + 2 * UI_UNIT_X - 4;
892                                 if (spx + dx + 10 > ar->v2d.cur.xmax) dx = ar->v2d.cur.xmax - spx - 10;
893
894                                 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, "");
895                                 uiButSetRenameFunc(bt, namebutton_cb, tselem);
896                                 
897                                 /* returns false if button got removed */
898                                 if (0 == uiButActiveOnly(C, block, bt) )
899                                         tselem->flag &= ~TSE_TEXTBUT;
900                         }
901                 }
902                 
903                 if (TSELEM_OPEN(tselem, soops)) outliner_buttons(C, block, ar, soops, &te->subtree);
904         }
905 }
906
907 /* ****************************************************** */
908 /* Normal Drawing... */
909
910 /* make function calls a bit compacter */
911 struct DrawIconArg {
912         uiBlock *block;
913         ID *id;
914         float xmax, x, y, xb, yb;
915         float alpha;
916 };
917
918 static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
919 {
920         /* restrict column clip... it has been coded by simply overdrawing, doesnt work for buttons */
921         if (arg->x >= arg->xmax) {
922                 glEnable(GL_BLEND);
923                 UI_icon_draw_aspect(arg->x, arg->y, icon, 1.0f / UI_DPI_FAC, arg->alpha);
924                 glDisable(GL_BLEND);
925         }
926         else {
927                 uiBut *but = uiDefIconBut(arg->block, LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, arg->alpha, (arg->id && arg->id->lib) ? arg->id->lib->name : "");
928                 
929                 if (arg->id)
930                         uiButSetDragID(but, arg->id);
931         }
932
933 }
934
935 static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, float alpha)
936 {
937         struct DrawIconArg arg;
938         float aspect;
939         
940         /* icons tiny bit away from text */
941         x -= 0.15f * UI_UNIT_Y;
942         
943         /* make function calls a bit compacter */
944         arg.block = block;
945         arg.id = tselem->id;
946         arg.xmax = xmax;
947         arg.xb = x;     /* for ui buttons */
948         arg.yb = y;
949         arg.alpha = alpha;
950         
951         /* placement of icons, copied from interface_widgets.c */
952         aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
953         arg.x = x = x + 4.0f * aspect;
954         arg.y = y = y + 0.1f * UI_UNIT_Y;
955
956         if (tselem->type) {
957                 switch (tselem->type) {
958                         case TSE_ANIM_DATA:
959                                 UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx
960                         case TSE_NLA:
961                                 UI_icon_draw(x, y, ICON_NLA); break;
962                         case TSE_NLA_TRACK:
963                                 UI_icon_draw(x, y, ICON_NLA); break; // XXX
964                         case TSE_NLA_ACTION:
965                                 UI_icon_draw(x, y, ICON_ACTION); break;
966                         case TSE_DRIVER_BASE:
967                                 UI_icon_draw(x, y, ICON_DRIVER); break;
968                         case TSE_DEFGROUP_BASE:
969                                 UI_icon_draw(x, y, ICON_GROUP_VERTEX); break;
970                         case TSE_BONE:
971                         case TSE_EBONE:
972                                 UI_icon_draw(x, y, ICON_BONE_DATA); break;
973                         case TSE_CONSTRAINT_BASE:
974                                 UI_icon_draw(x, y, ICON_CONSTRAINT); break;
975                         case TSE_MODIFIER_BASE:
976                                 UI_icon_draw(x, y, ICON_MODIFIER); break;
977                         case TSE_LINKED_OB:
978                                 UI_icon_draw(x, y, ICON_OBJECT_DATA); break;
979                         case TSE_LINKED_PSYS:
980                                 UI_icon_draw(x, y, ICON_PARTICLES); break;
981                         case TSE_MODIFIER:
982                         {
983                                 Object *ob = (Object *)tselem->id;
984                                 ModifierData *md = BLI_findlink(&ob->modifiers, tselem->nr);
985                                 switch ((ModifierType)md->type) {
986                                         case eModifierType_Subsurf: 
987                                                 UI_icon_draw(x, y, ICON_MOD_SUBSURF); break;
988                                         case eModifierType_Armature: 
989                                                 UI_icon_draw(x, y, ICON_MOD_ARMATURE); break;
990                                         case eModifierType_Lattice: 
991                                                 UI_icon_draw(x, y, ICON_MOD_LATTICE); break;
992                                         case eModifierType_Curve: 
993                                                 UI_icon_draw(x, y, ICON_MOD_CURVE); break;
994                                         case eModifierType_Build: 
995                                                 UI_icon_draw(x, y, ICON_MOD_BUILD); break;
996                                         case eModifierType_Mirror: 
997                                                 UI_icon_draw(x, y, ICON_MOD_MIRROR); break;
998                                         case eModifierType_Decimate: 
999                                                 UI_icon_draw(x, y, ICON_MOD_DECIM); break;
1000                                         case eModifierType_Wave: 
1001                                                 UI_icon_draw(x, y, ICON_MOD_WAVE); break;
1002                                         case eModifierType_Hook: 
1003                                                 UI_icon_draw(x, y, ICON_HOOK); break;
1004                                         case eModifierType_Softbody: 
1005                                                 UI_icon_draw(x, y, ICON_MOD_SOFT); break;
1006                                         case eModifierType_Boolean: 
1007                                                 UI_icon_draw(x, y, ICON_MOD_BOOLEAN); break;
1008                                         case eModifierType_ParticleSystem: 
1009                                                 UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
1010                                         case eModifierType_ParticleInstance:
1011                                                 UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
1012                                         case eModifierType_EdgeSplit:
1013                                                 UI_icon_draw(x, y, ICON_MOD_EDGESPLIT); break;
1014                                         case eModifierType_Array:
1015                                                 UI_icon_draw(x, y, ICON_MOD_ARRAY); break;
1016                                         case eModifierType_UVProject:
1017                                         case eModifierType_UVWarp:  /* TODO, get own icon */
1018                                                 UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break;
1019                                         case eModifierType_Displace:
1020                                                 UI_icon_draw(x, y, ICON_MOD_DISPLACE); break;
1021                                         case eModifierType_Shrinkwrap:
1022                                                 UI_icon_draw(x, y, ICON_MOD_SHRINKWRAP); break;
1023                                         case eModifierType_Cast:
1024                                                 UI_icon_draw(x, y, ICON_MOD_CAST); break;
1025                                         case eModifierType_MeshDeform:
1026                                                 UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break;
1027                                         case eModifierType_Bevel:
1028                                                 UI_icon_draw(x, y, ICON_MOD_BEVEL); break;
1029                                         case eModifierType_Smooth:
1030                                         case eModifierType_LaplacianSmooth:
1031                                                 UI_icon_draw(x, y, ICON_MOD_SMOOTH); break;
1032                                         case eModifierType_SimpleDeform:
1033                                                 UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break;
1034                                         case eModifierType_Mask:
1035                                                 UI_icon_draw(x, y, ICON_MOD_MASK); break;
1036                                         case eModifierType_Cloth:
1037                                                 UI_icon_draw(x, y, ICON_MOD_CLOTH); break;
1038                                         case eModifierType_Explode:
1039                                                 UI_icon_draw(x, y, ICON_MOD_EXPLODE); break;
1040                                         case eModifierType_Collision:
1041                                         case eModifierType_Surface:
1042                                                 UI_icon_draw(x, y, ICON_MOD_PHYSICS); break;
1043                                         case eModifierType_Fluidsim:
1044                                                 UI_icon_draw(x, y, ICON_MOD_FLUIDSIM); break;
1045                                         case eModifierType_Multires:
1046                                                 UI_icon_draw(x, y, ICON_MOD_MULTIRES); break;
1047                                         case eModifierType_Smoke:
1048                                                 UI_icon_draw(x, y, ICON_MOD_SMOKE); break;
1049                                         case eModifierType_Solidify:
1050                                                 UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break;
1051                                         case eModifierType_Screw:
1052                                                 UI_icon_draw(x, y, ICON_MOD_SCREW); break;
1053                                         case eModifierType_Remesh:
1054                                                 UI_icon_draw(x, y, ICON_MOD_REMESH); break;
1055                                         case eModifierType_WeightVGEdit:
1056                                         case eModifierType_WeightVGMix:
1057                                         case eModifierType_WeightVGProximity:
1058                                                 UI_icon_draw(x, y, ICON_MOD_VERTEX_WEIGHT); break;
1059                                         case eModifierType_DynamicPaint:
1060                                                 UI_icon_draw(x, y, ICON_MOD_DYNAMICPAINT); break;
1061                                         case eModifierType_Ocean:
1062                                                 UI_icon_draw(x, y, ICON_MOD_OCEAN); break;
1063                                         case eModifierType_Warp:
1064                                                 UI_icon_draw(x, y, ICON_MOD_WARP); break;
1065                                         case eModifierType_Skin:
1066                                                 UI_icon_draw(x, y, ICON_MOD_SKIN); break;
1067                                         case eModifierType_Triangulate:
1068                                                 UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break;
1069                                         case eModifierType_MeshCache:
1070                                                 UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break;  /* XXX, needs own icon */
1071                                         /* Default */
1072                                         case eModifierType_None:
1073                                         case eModifierType_ShapeKey:
1074                                         case NUM_MODIFIER_TYPES:
1075                                                 UI_icon_draw(x, y, ICON_DOT); break;
1076                                 }
1077                                 break;
1078                         }
1079                         case TSE_SCRIPT_BASE:
1080                                 UI_icon_draw(x, y, ICON_TEXT); break;
1081                         case TSE_POSE_BASE:
1082                                 UI_icon_draw(x, y, ICON_ARMATURE_DATA); break;
1083                         case TSE_POSE_CHANNEL:
1084                                 UI_icon_draw(x, y, ICON_BONE_DATA); break;
1085                         case TSE_PROXY:
1086                                 UI_icon_draw(x, y, ICON_GHOST); break;
1087                         case TSE_R_LAYER_BASE:
1088                                 UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
1089                         case TSE_R_LAYER:
1090                                 UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
1091                         case TSE_LINKED_LAMP:
1092                                 UI_icon_draw(x, y, ICON_LAMP_DATA); break;
1093                         case TSE_LINKED_MAT:
1094                                 UI_icon_draw(x, y, ICON_MATERIAL_DATA); break;
1095                         case TSE_POSEGRP_BASE:
1096                                 UI_icon_draw(x, y, ICON_GROUP_BONE); break;
1097                         case TSE_SEQUENCE:
1098                                 if (te->idcode == SEQ_TYPE_MOVIE)
1099                                         UI_icon_draw(x, y, ICON_SEQUENCE);
1100                                 else if (te->idcode == SEQ_TYPE_META)
1101                                         UI_icon_draw(x, y, ICON_DOT);
1102                                 else if (te->idcode == SEQ_TYPE_SCENE)
1103                                         UI_icon_draw(x, y, ICON_SCENE);
1104                                 else if (te->idcode == SEQ_TYPE_SOUND_RAM)
1105                                         UI_icon_draw(x, y, ICON_SOUND);
1106                                 else if (te->idcode == SEQ_TYPE_IMAGE)
1107                                         UI_icon_draw(x, y, ICON_IMAGE_COL);
1108                                 else
1109                                         UI_icon_draw(x, y, ICON_PARTICLES);
1110                                 break;
1111                         case TSE_SEQ_STRIP:
1112                                 UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT);
1113                                 break;
1114                         case TSE_SEQUENCE_DUP:
1115                                 UI_icon_draw(x, y, ICON_OBJECT_DATA);
1116                                 break;
1117                         case TSE_RNA_STRUCT:
1118                                 if (RNA_struct_is_ID(te->rnaptr.type)) {
1119                                         arg.id = (ID *)te->rnaptr.data;
1120                                         tselem_draw_icon_uibut(&arg, RNA_struct_ui_icon(te->rnaptr.type));
1121                                 }
1122                                 else
1123                                         UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type));
1124                                 break;
1125                         default:
1126                                 UI_icon_draw(x, y, ICON_DOT); break;
1127                 }
1128         }
1129         else if (GS(tselem->id->name) == ID_OB) {
1130                 Object *ob = (Object *)tselem->id;
1131                 switch (ob->type) {
1132                         case OB_LAMP:
1133                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
1134                         case OB_MESH: 
1135                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
1136                         case OB_CAMERA: 
1137                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
1138                         case OB_CURVE: 
1139                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
1140                         case OB_MBALL: 
1141                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
1142                         case OB_LATTICE: 
1143                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
1144                         case OB_ARMATURE: 
1145                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
1146                         case OB_FONT: 
1147                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
1148                         case OB_SURF: 
1149                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
1150                         case OB_SPEAKER:
1151                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break;
1152                         case OB_EMPTY: 
1153                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
1154                 
1155                 }
1156         }
1157         else {
1158                 switch (GS(tselem->id->name)) {
1159                         case ID_SCE:
1160                                 tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
1161                         case ID_ME:
1162                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break;
1163                         case ID_CU:
1164                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break;
1165                         case ID_MB:
1166                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break;
1167                         case ID_LT:
1168                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break;
1169                         case ID_LA:
1170                         {
1171                                 Lamp *la = (Lamp *)tselem->id;
1172                                 
1173                                 switch (la->type) {
1174                                         case LA_LOCAL:
1175                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break;
1176                                         case LA_SUN:
1177                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break;
1178                                         case LA_SPOT:
1179                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break;
1180                                         case LA_HEMI:
1181                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break;
1182                                         case LA_AREA:
1183                                                 tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break;
1184                                         default:
1185                                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break;
1186                                 }
1187                                 break;
1188                         }
1189                         case ID_MA:
1190                                 tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break;
1191                         case ID_TE:
1192                                 tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break;
1193                         case ID_IM:
1194                                 tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break;
1195                         case ID_SPK:
1196                         case ID_SO:
1197                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break;
1198                         case ID_AR:
1199                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break;
1200                         case ID_CA:
1201                                 tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break;
1202                         case ID_KE:
1203                                 tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break;
1204                         case ID_WO:
1205                                 tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break;
1206                         case ID_AC:
1207                                 tselem_draw_icon_uibut(&arg, ICON_ACTION); break;
1208                         case ID_NLA:
1209                                 tselem_draw_icon_uibut(&arg, ICON_NLA); break;
1210                         case ID_TXT:
1211                                 tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break;
1212                         case ID_GR:
1213                                 tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
1214                         case ID_LI:
1215                                 tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
1216                 }
1217         }
1218 }
1219
1220 static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys)
1221 {
1222         TreeElement *te;
1223         TreeStoreElem *tselem;
1224         int active;
1225
1226         for (te = lb->first; te; te = te->next) {
1227                 
1228                 /* exit drawing early */
1229                 if ((*offsx) - UI_UNIT_X > xmax)
1230                         break;
1231
1232                 tselem = TREESTORE(te);
1233                 
1234                 /* object hierarchy always, further constrained on level */
1235                 if (level < 1 || (tselem->type == 0 && te->idcode == ID_OB)) {
1236
1237                         /* active blocks get white circle */
1238                         if (tselem->type == 0) {
1239                                 if (te->idcode == ID_OB) {
1240                                         active = (OBACT == (Object *)tselem->id);
1241                                 }
1242                                 else if (scene->obedit && scene->obedit->data == tselem->id) {
1243                                         active = 1;  // XXX use context?
1244                                 }
1245                                 else {
1246                                         active = tree_element_active(C, scene, soops, te, 0);
1247                                 }
1248                         }
1249                         else {
1250                                 active = tree_element_type_active(NULL, scene, soops, te, tselem, 0);
1251                         }
1252
1253                         if (active) {
1254                                 float ufac = UI_UNIT_X / 20.0f;
1255
1256                                 uiSetRoundBox(UI_CNR_ALL);
1257                                 glColor4ub(255, 255, 255, 100);
1258                                 uiRoundBox((float) *offsx - 1.0f * ufac,
1259                                            (float)ys + 1.0f * ufac,
1260                                            (float)*offsx + UI_UNIT_X - 2.0f * ufac,
1261                                            (float)ys + UI_UNIT_Y - ufac,
1262                                            (float)UI_UNIT_Y / 2.0f - ufac);
1263                                 glEnable(GL_BLEND); /* roundbox disables */
1264                         }
1265                         
1266                         tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f);
1267                         te->xs = (float)*offsx;
1268                         te->ys = (float)ys;
1269                         te->xend = (short)*offsx + UI_UNIT_X;
1270                         te->flag |= TE_ICONROW; // for click
1271                         
1272                         (*offsx) += UI_UNIT_X;
1273                 }
1274                 
1275                 /* this tree element always has same amount of branches, so don't draw */
1276                 if (tselem->type != TSE_R_LAYER)
1277                         outliner_draw_iconrow(C, block, scene, soops, &te->subtree, level + 1, xmax, offsx, ys);
1278         }
1279         
1280 }
1281
1282 /* closed tree element */
1283 static void outliner_set_coord_tree_element(SpaceOops *soops, TreeElement *te, int startx, int *starty)
1284 {
1285         TreeElement *ten;
1286         
1287         /* store coord and continue, we need coordinates for elements outside view too */
1288         te->xs = (float)startx;
1289         te->ys = (float)(*starty);
1290         
1291         for (ten = te->subtree.first; ten; ten = ten->next) {
1292                 outliner_set_coord_tree_element(soops, ten, startx + UI_UNIT_X, starty);
1293         }
1294 }
1295
1296
1297 static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty)
1298 {
1299         TreeElement *ten;
1300         TreeStoreElem *tselem;
1301         float ufac = UI_UNIT_X / 20.0f;
1302         int offsx = 0, active = 0; // active=1 active obj, else active data
1303         
1304         tselem = TREESTORE(te);
1305
1306         if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
1307                 int xmax = ar->v2d.cur.xmax;
1308                 unsigned char alpha = 128;
1309                 
1310                 /* icons can be ui buts, we don't want it to overlap with restrict */
1311                 if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
1312                         xmax -= OL_TOGW + UI_UNIT_X;
1313                 
1314                 glEnable(GL_BLEND);
1315
1316                 /* start by highlighting search matches 
1317                  *      we don't expand items when searching in the datablocks but we 
1318                  *      still want to highlight any filter matches. 
1319                  */
1320                 if ((SEARCHING_OUTLINER(soops) || (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0)) &&
1321                     (tselem->flag & TSE_SEARCHMATCH))
1322                 {
1323                         char col[4];
1324                         UI_GetThemeColorType4ubv(TH_MATCH, SPACE_OUTLINER, col);
1325                         col[3] = alpha;
1326                         glColor4ubv((GLubyte *)col);
1327                         glRecti(startx, *starty + 1, ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
1328                 }
1329
1330                 /* colors for active/selected data */
1331                 if (tselem->type == 0) {
1332                         
1333                         if (te->idcode == ID_SCE) {
1334                                 if (tselem->id == (ID *)scene) {
1335                                         glColor4ub(255, 255, 255, alpha);
1336                                         active = 2;
1337                                 }
1338                         }
1339                         else if (te->idcode == ID_GR) {
1340                                 Group *gr = (Group *)tselem->id;
1341                                 if (group_select_flag(gr)) {
1342                                         char col[4];
1343                                         UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
1344                                         col[3] = alpha;
1345                                         glColor4ubv((GLubyte *)col);
1346                                         
1347                                         active = 2;
1348                                 }
1349                         }
1350                         else if (te->idcode == ID_OB) {
1351                                 Object *ob = (Object *)tselem->id;
1352                                 
1353                                 if (ob == OBACT || (ob->flag & SELECT)) {
1354                                         char col[4] = {0, 0, 0, 0};
1355                                         
1356                                         /* outliner active ob: always white text, circle color now similar to view3d */
1357                                         
1358                                         active = 2; /* means it draws a color circle */
1359                                         if (ob == OBACT) {
1360                                                 if (ob->flag & SELECT) {
1361                                                         UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
1362                                                         col[3] = alpha;
1363                                                 }
1364                                                 
1365                                                 active = 1; /* means it draws white text */
1366                                         }
1367                                         else if (ob->flag & SELECT) {
1368                                                 UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
1369                                                 col[3] = alpha;
1370                                         }
1371                                         
1372                                         glColor4ubv((GLubyte *)col);
1373                                 }
1374                         
1375                         }
1376                         else if (scene->obedit && scene->obedit->data == tselem->id) {
1377                                 glColor4ub(255, 255, 255, alpha);
1378                                 active = 2;
1379                         }
1380                         else {
1381                                 if (tree_element_active(C, scene, soops, te, 0)) {
1382                                         glColor4ub(220, 220, 255, alpha);
1383                                         active = 2;
1384                                 }
1385                         }
1386                 }
1387                 else {
1388                         if (tree_element_type_active(NULL, scene, soops, te, tselem, 0) ) active = 2;
1389                         glColor4ub(220, 220, 255, alpha);
1390                 }
1391                 
1392                 /* active circle */
1393                 if (active) {
1394                         uiSetRoundBox(UI_CNR_ALL);
1395                         uiRoundBox((float)startx + UI_UNIT_X,
1396                                    (float)*starty + 1.0f * ufac,
1397                                    (float)startx + 2.0f * UI_UNIT_X - 2.0f * ufac,
1398                                    (float)*starty + UI_UNIT_Y - 1.0f * ufac,
1399                                    UI_UNIT_Y / 2.0f - 1.0f * ufac);
1400                         glEnable(GL_BLEND); /* roundbox disables it */
1401                         
1402                         te->flag |= TE_ACTIVE; // for lookup in display hierarchies
1403                 }
1404                 
1405                 /* open/close icon, only when sublevels, except for scene */
1406                 if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
1407                         int icon_x;
1408                         if (tselem->type == 0 && ELEM(te->idcode, ID_OB, ID_SCE))
1409                                 icon_x = startx;
1410                         else
1411                                 icon_x = startx + 5 * ufac;
1412                         
1413                         // icons a bit higher
1414                         if (TSELEM_OPEN(tselem, soops))
1415                                 UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_DOWN);
1416                         else
1417                                 UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_RIGHT);
1418                 }
1419                 offsx += UI_UNIT_X;
1420                 
1421                 /* datatype icon */
1422                 
1423                 if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
1424                         
1425                         tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, 1.0f);
1426                         
1427                         offsx += UI_UNIT_X;
1428                 }
1429                 else
1430                         offsx += 2 * ufac;
1431                 
1432                 if (tselem->type == 0 && tselem->id->lib) {
1433                         glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
1434                         if (tselem->id->flag & LIB_INDIRECT)
1435                                 UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT);
1436                         else
1437                                 UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT);
1438                         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
1439                         offsx += UI_UNIT_X;
1440                 }
1441                 glDisable(GL_BLEND);
1442                 
1443                 /* name */
1444                 if (active == 1) UI_ThemeColor(TH_TEXT_HI);
1445                 else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
1446                 else UI_ThemeColor(TH_TEXT);
1447                 
1448                 UI_DrawString(startx + offsx, *starty + 5 * ufac, te->name);
1449                 
1450                 offsx += (int)(UI_UNIT_X + UI_GetStringWidth(te->name));
1451                 
1452                 /* closed item, we draw the icons, not when it's a scene, or master-server list though */
1453                 if (!TSELEM_OPEN(tselem, soops)) {
1454                         if (te->subtree.first) {
1455                                 if (tselem->type == 0 && te->idcode == ID_SCE) {
1456                                         /* pass */
1457                                 }
1458                                 else if (tselem->type != TSE_R_LAYER) {
1459                                         /* this tree element always has same amount of branches, so don't draw */
1460
1461                                         int tempx = startx + offsx;
1462                                         
1463                                         /* divider */
1464                                         UI_ThemeColorShade(TH_BACK, -40);
1465                                         glRecti(tempx   - 10.0f * ufac,
1466                                                 *starty +  4.0f * ufac,
1467                                                 tempx   -  8.0f * ufac,
1468                                                 *starty + UI_UNIT_Y - 4.0f * ufac);
1469                                         
1470                                         glEnable(GL_BLEND);
1471                                         glPixelTransferf(GL_ALPHA_SCALE, 0.5);
1472                                         
1473                                         outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty);
1474                                         
1475                                         glPixelTransferf(GL_ALPHA_SCALE, 1.0);
1476                                         glDisable(GL_BLEND);
1477                                 }
1478                         }
1479                 }
1480         }
1481         /* store coord and continue, we need coordinates for elements outside view too */
1482         te->xs = (float)startx;
1483         te->ys = (float)*starty;
1484         te->xend = startx + offsx;
1485                 
1486         if (TSELEM_OPEN(tselem, soops)) {
1487                 *starty -= UI_UNIT_Y;
1488                 
1489                 for (ten = te->subtree.first; ten; ten = ten->next)
1490                         outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx + UI_UNIT_X, starty);
1491         }
1492         else {
1493                 for (ten = te->subtree.first; ten; ten = ten->next)
1494                         outliner_set_coord_tree_element(soops, te, startx, starty);
1495                 
1496                 *starty -= UI_UNIT_Y;
1497         }
1498 }
1499
1500 static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, int *starty)
1501 {
1502         TreeElement *te;
1503         TreeStoreElem *tselem;
1504         int y1, y2;
1505         
1506         if (lb->first == NULL) return;
1507         
1508         y1 = y2 = *starty; /* for vertical lines between objects */
1509         for (te = lb->first; te; te = te->next) {
1510                 y2 = *starty;
1511                 tselem = TREESTORE(te);
1512                 
1513                 /* horizontal line? */
1514                 if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE))
1515                         glRecti(startx, *starty, startx + UI_UNIT_X, *starty - 1);
1516                         
1517                 *starty -= UI_UNIT_Y;
1518                 
1519                 if (TSELEM_OPEN(tselem, soops))
1520                         outliner_draw_hierarchy(soops, &te->subtree, startx + UI_UNIT_X, starty);
1521         }
1522         
1523         /* vertical line */
1524         te = lb->last;
1525         if (te->parent || lb->first != lb->last) {
1526                 tselem = TREESTORE(te);
1527                 if (tselem->type == 0 && te->idcode == ID_OB) {
1528                         
1529                         glRecti(startx, y1 + UI_UNIT_Y, startx + 1, y2);
1530                 }
1531         }
1532 }
1533
1534 static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) 
1535 {
1536         TreeElement *te;
1537         TreeStoreElem *tselem;
1538         
1539         for (te = lb->first; te; te = te->next) {
1540                 tselem = TREESTORE(te);
1541                 
1542                 /* selection status */
1543                 if (TSELEM_OPEN(tselem, soops))
1544                         if (tselem->type == TSE_RNA_STRUCT)
1545                                 glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
1546
1547                 *starty -= UI_UNIT_Y;
1548                 if (TSELEM_OPEN(tselem, soops)) {
1549                         outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
1550                         if (tselem->type == TSE_RNA_STRUCT)
1551                                 fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
1552                 }
1553         }
1554 }
1555
1556 static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) 
1557 {
1558         TreeElement *te;
1559         TreeStoreElem *tselem;
1560         
1561         for (te = lb->first; te; te = te->next) {
1562                 tselem = TREESTORE(te);
1563                 
1564                 /* selection status */
1565                 if (tselem->flag & TSE_SELECTED) {
1566                         glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
1567                 }
1568                 *starty -= UI_UNIT_Y;
1569                 if (TSELEM_OPEN(tselem, soops)) outliner_draw_selection(ar, soops, &te->subtree, starty);
1570         }
1571 }
1572
1573
1574 static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops)
1575 {
1576         TreeElement *te;
1577         int starty, startx;
1578         float col[3];
1579                 
1580         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); // only once
1581         
1582         if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
1583                 /* struct marks */
1584                 UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
1585                 //UI_ThemeColorShade(TH_BACK, -20);
1586                 starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
1587                 outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
1588         }
1589         
1590         /* always draw selection fill before hierarchy */
1591         UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col);
1592         glColor3fv(col);
1593         starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
1594         outliner_draw_selection(ar, soops, &soops->tree, &starty);
1595         
1596         // gray hierarchy lines
1597         UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f);
1598         starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
1599         startx = 6;
1600         outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
1601         
1602         // items themselves
1603         starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
1604         startx = 0;
1605         for (te = soops->tree.first; te; te = te->next) {
1606                 outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty);
1607         }
1608 }
1609
1610
1611 static void outliner_back(ARegion *ar)
1612 {
1613         int ystart;
1614         
1615         UI_ThemeColorShade(TH_BACK, 6);
1616         ystart = (int)ar->v2d.tot.ymax;
1617         ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
1618         
1619         while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
1620                 glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
1621                 ystart -= 2 * UI_UNIT_Y;
1622         }
1623 }
1624
1625 static void outliner_draw_restrictcols(ARegion *ar)
1626 {
1627         int ystart;
1628         
1629         /* background underneath */
1630         UI_ThemeColor(TH_BACK);
1631         glRecti((int)(ar->v2d.cur.xmax - OL_TOGW),
1632                 (int)(ar->v2d.cur.ymin - 1), (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax);
1633         
1634         UI_ThemeColorShade(TH_BACK, 6);
1635         ystart = (int)ar->v2d.tot.ymax;
1636         ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
1637         
1638         while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
1639                 glRecti((int)ar->v2d.cur.xmax - OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
1640                 ystart -= 2 * UI_UNIT_Y;
1641         }
1642         
1643         UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
1644
1645         /* view */
1646         sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
1647                   (int)ar->v2d.cur.ymax,
1648                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
1649                   (int)ar->v2d.cur.ymin);
1650
1651         /* render */
1652         sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
1653                   (int)ar->v2d.cur.ymax,
1654                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
1655                   (int)ar->v2d.cur.ymin);
1656
1657         /* render */
1658         sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
1659                   (int)ar->v2d.cur.ymax,
1660                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
1661                   (int)ar->v2d.cur.ymin);
1662 }
1663
1664 /* ****************************************************** */
1665 /* Main Entrypoint - Draw contents of Outliner editor */
1666
1667 void draw_outliner(const bContext *C)
1668 {
1669         Main *mainvar = CTX_data_main(C); 
1670         Scene *scene = CTX_data_scene(C);
1671         ARegion *ar = CTX_wm_region(C);
1672         View2D *v2d = &ar->v2d;
1673         SpaceOops *soops = CTX_wm_space_outliner(C);
1674         uiBlock *block;
1675         int sizey = 0, sizex = 0, sizex_rna = 0;
1676
1677         outliner_build_tree(mainvar, scene, soops); // always
1678         
1679         /* get extents of data */
1680         outliner_height(soops, &soops->tree, &sizey);
1681
1682         if (ELEM3(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF, SO_KEYMAP)) {
1683                 /* RNA has two columns:
1684                  *  - column 1 is (max_width + OL_RNA_COL_SPACEX) or
1685                  *                               (OL_RNA_COL_X), whichever is wider...
1686                  *      - column 2 is fixed at OL_RNA_COL_SIZEX
1687                  *
1688                  *  (*) XXX max width for now is a fixed factor of (UI_UNIT_X * (max_indention + 100))
1689                  */
1690                  
1691                 /* get actual width of column 1 */
1692                 outliner_rna_width(soops, &soops->tree, &sizex_rna, 0);
1693                 sizex_rna = max_ii(OL_RNA_COLX, sizex_rna + OL_RNA_COL_SPACEX);
1694                 
1695                 /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
1696                 if (soops->outlinevis == SO_KEYMAP) 
1697                         sizex = sizex_rna + OL_RNA_COL_SIZEX * 3 + 50;  // XXX this is only really a quick hack to make this wide enough...
1698                 else
1699                         sizex = sizex_rna + OL_RNA_COL_SIZEX + 50;
1700         }
1701         else {
1702                 /* width must take into account restriction columns (if visible) so that entries will still be visible */
1703                 //outliner_width(soops, &soops->tree, &sizex);
1704                 outliner_rna_width(soops, &soops->tree, &sizex, 0); // XXX should use outliner_width instead when te->xend will be set correctly...
1705                 
1706                 /* constant offset for restriction columns */
1707                 // XXX this isn't that great yet...
1708                 if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
1709                         sizex += OL_TOGW * 3;
1710                 
1711         }
1712         
1713         /* adds vertical offset */
1714         sizey += OL_Y_OFFSET;
1715
1716         /* update size of tot-rect (extents of data/viewable area) */
1717         UI_view2d_totRect_set(v2d, sizex, sizey);
1718
1719         /* force display to pixel coords */
1720         v2d->flag |= (V2D_PIXELOFS_X | V2D_PIXELOFS_Y);
1721         /* set matrix for 2d-view controls */
1722         UI_view2d_view_ortho(v2d);
1723
1724         /* draw outliner stuff (background, hierachy lines and names) */
1725         outliner_back(ar);
1726         block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
1727         outliner_draw_tree((bContext *)C, block, scene, ar, soops);
1728         
1729         if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
1730                 /* draw rna buttons */
1731                 outliner_draw_rnacols(ar, sizex_rna);
1732                 outliner_draw_rnabuts(block, scene, ar, soops, sizex_rna, &soops->tree);
1733         }
1734         else if (soops->outlinevis == SO_KEYMAP) {
1735                 outliner_draw_keymapbuts(block, ar, soops, &soops->tree);
1736         }
1737         else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) {
1738                 /* draw restriction columns */
1739                 outliner_draw_restrictcols(ar);
1740                 outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree);
1741         }
1742
1743         /* draw edit buttons if nessecery */
1744         outliner_buttons(C, block, ar, soops, &soops->tree);
1745
1746         uiEndBlock(C, block);
1747         uiDrawBlock(C, block);
1748
1749         /* clear flag that allows quick redraws */
1750         soops->storeflag &= ~SO_TREESTORE_REDRAW;
1751