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