~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/editors/space_outliner/outliner.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2012-07-23 08:54:18 UTC
  • mfrom: (14.2.16 sid)
  • mto: (14.2.19 sid)
  • mto: This revision was merged to the branch mainline in revision 42.
  • Revision ID: package-import@ubuntu.com-20120723085418-9foz30v6afaf5ffs
Tags: 2.63a-2
* debian/: Cycles support added (Closes: #658075)
  For now, this top feature has been enabled only
  on [any-amd64 any-i386] architectures because
  of OpenImageIO failing on all others
* debian/: scripts installation path changed
  from /usr/lib to /usr/share:
  + debian/patches/: patchset re-worked for path changing
  + debian/control: "Breaks" field added on yafaray-exporter

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * $Id: outliner.c 30384 2010-07-15 16:56:04Z campbellbarton $
3
 
 *
4
 
 * ***** BEGIN GPL LICENSE BLOCK *****
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU General Public License
8
 
 * as published by the Free Software Foundation; either version 2
9
 
 * of the License, or (at your option) any later version. 
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software Foundation,
18
 
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 
 *
20
 
 * The Original Code is Copyright (C) 2004 Blender Foundation.
21
 
 * All rights reserved.
22
 
 *
23
 
 * The Original Code is: all of this file.
24
 
 *
25
 
 * Contributor(s): none yet.
26
 
 *
27
 
 * ***** END GPL LICENSE BLOCK *****
28
 
 */
29
 
 
30
 
#include <math.h>
31
 
#include <string.h>
32
 
#include <stdlib.h>
33
 
#include <stddef.h>
34
 
 
35
 
#include "MEM_guardedalloc.h"
36
 
 
37
 
#include "DNA_anim_types.h"
38
 
#include "DNA_armature_types.h"
39
 
#include "DNA_constraint_types.h"
40
 
#include "DNA_camera_types.h"
41
 
#include "DNA_group_types.h"
42
 
#include "DNA_key_types.h"
43
 
#include "DNA_lamp_types.h"
44
 
#include "DNA_material_types.h"
45
 
#include "DNA_mesh_types.h"
46
 
#include "DNA_meta_types.h"
47
 
#include "DNA_particle_types.h"
48
 
#include "DNA_scene_types.h"
49
 
#include "DNA_world_types.h"
50
 
#include "DNA_sequence_types.h"
51
 
 
52
 
#include "BLI_blenlib.h"
53
 
 
54
 
#if defined WIN32 && !defined _LIBC
55
 
# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
56
 
#else
57
 
# define _GNU_SOURCE
58
 
# include <fnmatch.h>
59
 
#endif
60
 
 
61
 
#include "IMB_imbuf_types.h"
62
 
 
63
 
#include "BKE_animsys.h"
64
 
#include "BKE_constraint.h"
65
 
#include "BKE_context.h"
66
 
#include "BKE_deform.h"
67
 
#include "BKE_depsgraph.h"
68
 
#include "BKE_fcurve.h"
69
 
#include "BKE_global.h"
70
 
#include "BKE_group.h"
71
 
#include "BKE_library.h"
72
 
#include "BKE_main.h"
73
 
#include "BKE_material.h"
74
 
#include "BKE_modifier.h"
75
 
#include "BKE_object.h"
76
 
#include "BKE_report.h"
77
 
#include "BKE_screen.h"
78
 
#include "BKE_scene.h"
79
 
#include "BKE_sequencer.h"
80
 
#include "BKE_utildefines.h"
81
 
 
82
 
#include "ED_armature.h"
83
 
#include "ED_object.h"
84
 
#include "ED_screen.h"
85
 
#include "ED_util.h"
86
 
 
87
 
#include "WM_api.h"
88
 
#include "WM_types.h"
89
 
 
90
 
#include "BIF_gl.h"
91
 
#include "BIF_glutil.h"
92
 
 
93
 
#include "UI_interface.h"
94
 
#include "UI_interface_icons.h"
95
 
#include "UI_resources.h"
96
 
#include "UI_view2d.h"
97
 
 
98
 
#include "RNA_access.h"
99
 
#include "RNA_define.h"
100
 
 
101
 
#include "ED_keyframing.h"
102
 
 
103
 
#include "outliner_intern.h"
104
 
 
105
 
 
106
 
 
107
 
#define OL_H    19
108
 
#define OL_X    18
109
 
 
110
 
#define OL_TOG_RESTRICT_VIEWX   54
111
 
#define OL_TOG_RESTRICT_SELECTX 36
112
 
#define OL_TOG_RESTRICT_RENDERX 18
113
 
 
114
 
#define OL_TOGW OL_TOG_RESTRICT_VIEWX
115
 
 
116
 
#define OL_RNA_COLX                     300
117
 
#define OL_RNA_COL_SIZEX        150
118
 
#define OL_RNA_COL_SPACEX       50
119
 
 
120
 
#define TS_CHUNK        128
121
 
 
122
 
#define TREESTORE(a) ((a)?soops->treestore->data+(a)->store_index:NULL)
123
 
 
124
 
/* ************* XXX **************** */
125
 
 
126
 
static void error(const char *dummy, ...) {}
127
 
 
128
 
/* ********************************** */
129
 
 
130
 
 
131
 
/* ******************** PROTOTYPES ***************** */
132
 
static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty);
133
 
static void outliner_do_object_operation(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, 
134
 
                                                                                 void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *));
135
 
 
136
 
static int group_select_flag(Group *gr);
137
 
 
138
 
/* ******************** PERSISTANT DATA ***************** */
139
 
 
140
 
static void outliner_storage_cleanup(SpaceOops *soops)
141
 
{
142
 
        TreeStore *ts= soops->treestore;
143
 
        
144
 
        if(ts) {
145
 
                TreeStoreElem *tselem;
146
 
                int a, unused= 0;
147
 
                
148
 
                /* each element used once, for ID blocks with more users to have each a treestore */
149
 
                for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) tselem->used= 0;
150
 
 
151
 
                /* cleanup only after reading file or undo step, and always for
152
 
                 * RNA datablocks view in order to save memory */
153
 
                if(soops->storeflag & SO_TREESTORE_CLEANUP) {
154
 
                        
155
 
                        for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) {
156
 
                                if(tselem->id==NULL) unused++;
157
 
                        }
158
 
 
159
 
                        if(unused) {
160
 
                                if(ts->usedelem == unused) {
161
 
                                        MEM_freeN(ts->data);
162
 
                                        ts->data= NULL;
163
 
                                        ts->usedelem= ts->totelem= 0;
164
 
                                }
165
 
                                else {
166
 
                                        TreeStoreElem *tsnewar, *tsnew;
167
 
                                        
168
 
                                        tsnew=tsnewar= MEM_mallocN((ts->usedelem-unused)*sizeof(TreeStoreElem), "new tselem");
169
 
                                        for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) {
170
 
                                                if(tselem->id) {
171
 
                                                        *tsnew= *tselem;
172
 
                                                        tsnew++;
173
 
                                                }
174
 
                                        }
175
 
                                        MEM_freeN(ts->data);
176
 
                                        ts->data= tsnewar;
177
 
                                        ts->usedelem-= unused;
178
 
                                        ts->totelem= ts->usedelem;
179
 
                                }
180
 
                        }
181
 
                }
182
 
        }
183
 
}
184
 
 
185
 
static void check_persistant(SpaceOops *soops, TreeElement *te, ID *id, short type, short nr)
186
 
{
187
 
        TreeStore *ts;
188
 
        TreeStoreElem *tselem;
189
 
        int a;
190
 
        
191
 
        /* case 1; no TreeStore */
192
 
        if(soops->treestore==NULL) {
193
 
                ts= soops->treestore= MEM_callocN(sizeof(TreeStore), "treestore");
194
 
        }
195
 
        ts= soops->treestore;
196
 
        
197
 
        /* check if 'te' is in treestore */
198
 
        tselem= ts->data;
199
 
        for(a=0; a<ts->usedelem; a++, tselem++) {
200
 
                if(tselem->id==id && tselem->used==0) {
201
 
                        if((type==0 && tselem->type==0) ||(tselem->type==type && tselem->nr==nr)) {
202
 
                                te->store_index= a;
203
 
                                tselem->used= 1;
204
 
                                return;
205
 
                        }
206
 
                }
207
 
        }
208
 
        
209
 
        /* add 1 element to treestore */
210
 
        if(ts->usedelem==ts->totelem) {
211
 
                TreeStoreElem *tsnew;
212
 
                
213
 
                tsnew= MEM_mallocN((ts->totelem+TS_CHUNK)*sizeof(TreeStoreElem), "treestore data");
214
 
                if(ts->data) {
215
 
                        memcpy(tsnew, ts->data, ts->totelem*sizeof(TreeStoreElem));
216
 
                        MEM_freeN(ts->data);
217
 
                }
218
 
                ts->data= tsnew;
219
 
                ts->totelem+= TS_CHUNK;
220
 
        }
221
 
        
222
 
        tselem= ts->data+ts->usedelem;
223
 
        
224
 
        tselem->type= type;
225
 
        if(type) tselem->nr= nr; // we're picky! :)
226
 
        else tselem->nr= 0;
227
 
        tselem->id= id;
228
 
        tselem->used = 0;
229
 
        tselem->flag= TSE_CLOSED;
230
 
        te->store_index= ts->usedelem;
231
 
        
232
 
        ts->usedelem++;
233
 
}
234
 
 
235
 
/* ******************** TREE MANAGEMENT ****************** */
236
 
 
237
 
void outliner_free_tree(ListBase *lb)
238
 
{
239
 
        
240
 
        while(lb->first) {
241
 
                TreeElement *te= lb->first;
242
 
                
243
 
                outliner_free_tree(&te->subtree);
244
 
                BLI_remlink(lb, te);
245
 
 
246
 
                if(te->flag & TE_FREE_NAME) MEM_freeN(te->name);
247
 
                MEM_freeN(te);
248
 
        }
249
 
}
250
 
 
251
 
static void outliner_height(SpaceOops *soops, ListBase *lb, int *h)
252
 
{
253
 
        TreeElement *te= lb->first;
254
 
        while(te) {
255
 
                TreeStoreElem *tselem= TREESTORE(te);
256
 
                if((tselem->flag & TSE_CLOSED)==0) 
257
 
                        outliner_height(soops, &te->subtree, h);
258
 
                (*h) += OL_H;
259
 
                te= te->next;
260
 
        }
261
 
}
262
 
 
263
 
#if 0  // XXX this is currently disabled until te->xend is set correctly
264
 
static void outliner_width(SpaceOops *soops, ListBase *lb, int *w)
265
 
{
266
 
        TreeElement *te= lb->first;
267
 
        while(te) {
268
 
//              TreeStoreElem *tselem= TREESTORE(te);
269
 
                
270
 
                // XXX fixme... te->xend is not set yet
271
 
                if(tselem->flag & TSE_CLOSED) {
272
 
                        if (te->xend > *w)
273
 
                                *w = te->xend;
274
 
                }
275
 
                outliner_width(soops, &te->subtree, w);
276
 
                te= te->next;
277
 
        }
278
 
}
279
 
#endif
280
 
 
281
 
static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int startx)
282
 
{
283
 
        TreeElement *te= lb->first;
284
 
        while(te) {
285
 
                TreeStoreElem *tselem= TREESTORE(te);
286
 
                        // XXX fixme... (currently, we're using a fixed length of 100)!
287
 
                /*if(te->xend) {
288
 
                        if(te->xend > *w)
289
 
                                *w = te->xend;
290
 
                }*/
291
 
                if(startx+100 > *w)
292
 
                        *w = startx+100;
293
 
 
294
 
                if((tselem->flag & TSE_CLOSED)==0)
295
 
                        outliner_rna_width(soops, &te->subtree, w, startx+OL_X);
296
 
                te= te->next;
297
 
        }
298
 
}
299
 
 
300
 
static TreeElement *outliner_find_tree_element(ListBase *lb, int store_index)
301
 
{
302
 
        TreeElement *te= lb->first, *tes;
303
 
        while(te) {
304
 
                if(te->store_index==store_index) return te;
305
 
                tes= outliner_find_tree_element(&te->subtree, store_index);
306
 
                if(tes) return tes;
307
 
                te= te->next;
308
 
        }
309
 
        return NULL;
310
 
}
311
 
 
312
 
 
313
 
 
314
 
static ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode)
315
 
{
316
 
        TreeStoreElem *tselem;
317
 
        te= te->parent;
318
 
        
319
 
        while(te) {
320
 
                tselem= TREESTORE(te);
321
 
                if(tselem->type==0 && te->idcode==idcode) return tselem->id;
322
 
                te= te->parent;
323
 
        }
324
 
        return NULL;
325
 
}
326
 
 
327
 
struct treesort {
328
 
        TreeElement *te;
329
 
        ID *id;
330
 
        char *name;
331
 
        short idcode;
332
 
};
333
 
 
334
 
static int treesort_alpha(const void *v1, const void *v2)
335
 
{
336
 
        const struct treesort *x1= v1, *x2= v2;
337
 
        int comp;
338
 
        
339
 
        /* first put objects last (hierarchy) */
340
 
        comp= (x1->idcode==ID_OB);
341
 
        if(x2->idcode==ID_OB) comp+=2;
342
 
        
343
 
        if(comp==1) return 1;
344
 
        else if(comp==2) return -1;
345
 
        else if(comp==3) {
346
 
                int comp= strcmp(x1->name, x2->name);
347
 
                
348
 
                if( comp>0 ) return 1;
349
 
                else if( comp<0) return -1;
350
 
                return 0;
351
 
        }
352
 
        return 0;
353
 
}
354
 
 
355
 
/* this is nice option for later? doesnt look too useful... */
356
 
#if 0
357
 
static int treesort_obtype_alpha(const void *v1, const void *v2)
358
 
{
359
 
        const struct treesort *x1= v1, *x2= v2;
360
 
        
361
 
        /* first put objects last (hierarchy) */
362
 
        if(x1->idcode==ID_OB && x2->idcode!=ID_OB) return 1;
363
 
        else if(x2->idcode==ID_OB && x1->idcode!=ID_OB) return -1;
364
 
        else {
365
 
                /* 2nd we check ob type */
366
 
                if(x1->idcode==ID_OB && x2->idcode==ID_OB) {
367
 
                        if( ((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1;
368
 
                        else if( ((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1;
369
 
                        else return 0;
370
 
                }
371
 
                else {
372
 
                        int comp= strcmp(x1->name, x2->name);
373
 
                        
374
 
                        if( comp>0 ) return 1;
375
 
                        else if( comp<0) return -1;
376
 
                        return 0;
377
 
                }
378
 
        }
379
 
}
380
 
#endif
381
 
 
382
 
/* sort happens on each subtree individual */
383
 
static void outliner_sort(SpaceOops *soops, ListBase *lb)
384
 
{
385
 
        TreeElement *te;
386
 
        TreeStoreElem *tselem;
387
 
        int totelem=0;
388
 
        
389
 
        te= lb->last;
390
 
        if(te==NULL) return;
391
 
        tselem= TREESTORE(te);
392
 
        
393
 
        /* sorting rules; only object lists or deformgroups */
394
 
        if( (tselem->type==TSE_DEFGROUP) || (tselem->type==0 && te->idcode==ID_OB)) {
395
 
                
396
 
                /* count first */
397
 
                for(te= lb->first; te; te= te->next) totelem++;
398
 
                
399
 
                if(totelem>1) {
400
 
                        struct treesort *tear= MEM_mallocN(totelem*sizeof(struct treesort), "tree sort array");
401
 
                        struct treesort *tp=tear;
402
 
                        int skip= 0;
403
 
                        
404
 
                        for(te= lb->first; te; te= te->next, tp++) {
405
 
                                tselem= TREESTORE(te);
406
 
                                tp->te= te;
407
 
                                tp->name= te->name;
408
 
                                tp->idcode= te->idcode;
409
 
                                if(tselem->type && tselem->type!=TSE_DEFGROUP) tp->idcode= 0;   // dont sort this
410
 
                                tp->id= tselem->id;
411
 
                        }
412
 
                        /* keep beginning of list */
413
 
                        for(tp= tear, skip=0; skip<totelem; skip++, tp++)
414
 
                                if(tp->idcode) break;
415
 
                        
416
 
                        if(skip<totelem)
417
 
                                qsort(tear+skip, totelem-skip, sizeof(struct treesort), treesort_alpha);
418
 
                        
419
 
                        lb->first=lb->last= NULL;
420
 
                        tp= tear;
421
 
                        while(totelem--) {
422
 
                                BLI_addtail(lb, tp->te);
423
 
                                tp++;
424
 
                        }
425
 
                        MEM_freeN(tear);
426
 
                }
427
 
        }
428
 
        
429
 
        for(te= lb->first; te; te= te->next) {
430
 
                outliner_sort(soops, &te->subtree);
431
 
        }
432
 
}
433
 
 
434
 
/* Prototype, see functions below */
435
 
static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv, 
436
 
                                                                                 TreeElement *parent, short type, short index);
437
 
 
438
 
#define LOG2I(x) (int)(log(x)/log(2.0))
439
 
 
440
 
static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, SceneRenderLayer *srl)
441
 
{
442
 
        TreeStoreElem *tselem = NULL;
443
 
        TreeElement *te = NULL;
444
 
 
445
 
        /* log stuff is to convert bitflags (powers of 2) to small integers,
446
 
         * in order to not overflow short tselem->nr */
447
 
        
448
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_COMBINED));
449
 
        te->name= "Combined";
450
 
        te->directdata= &srl->passflag;
451
 
        
452
 
        /* save cpu cycles, but we add the first to invoke an open/close triangle */
453
 
        tselem = TREESTORE(tenla);
454
 
        if(tselem->flag & TSE_CLOSED)
455
 
                return;
456
 
        
457
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_Z));
458
 
        te->name= "Z";
459
 
        te->directdata= &srl->passflag;
460
 
        
461
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_VECTOR));
462
 
        te->name= "Vector";
463
 
        te->directdata= &srl->passflag;
464
 
        
465
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_NORMAL));
466
 
        te->name= "Normal";
467
 
        te->directdata= &srl->passflag;
468
 
        
469
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_UV));
470
 
        te->name= "UV";
471
 
        te->directdata= &srl->passflag;
472
 
        
473
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_MIST));
474
 
        te->name= "Mist";
475
 
        te->directdata= &srl->passflag;
476
 
        
477
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXOB));
478
 
        te->name= "Index Object";
479
 
        te->directdata= &srl->passflag;
480
 
        
481
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_RGBA));
482
 
        te->name= "Color";
483
 
        te->directdata= &srl->passflag;
484
 
        
485
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_DIFFUSE));
486
 
        te->name= "Diffuse";
487
 
        te->directdata= &srl->passflag;
488
 
        
489
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SPEC));
490
 
        te->name= "Specular";
491
 
        te->directdata= &srl->passflag;
492
 
        
493
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SHADOW));
494
 
        te->name= "Shadow";
495
 
        te->directdata= &srl->passflag;
496
 
        
497
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_AO));
498
 
        te->name= "AO";
499
 
        te->directdata= &srl->passflag;
500
 
        
501
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFLECT));
502
 
        te->name= "Reflection";
503
 
        te->directdata= &srl->passflag;
504
 
        
505
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFRACT));
506
 
        te->name= "Refraction";
507
 
        te->directdata= &srl->passflag;
508
 
        
509
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDIRECT));
510
 
        te->name= "Indirect";
511
 
        te->directdata= &srl->passflag;
512
 
 
513
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_ENVIRONMENT));
514
 
        te->name= "Environment";
515
 
        te->directdata= &srl->passflag;
516
 
 
517
 
        te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_EMIT));
518
 
        te->name= "Emit";
519
 
        te->directdata= &srl->passflag;
520
 
}
521
 
 
522
 
#undef LOG2I
523
 
 
524
 
/* special handling of hierarchical non-lib data */
525
 
static void outliner_add_bone(SpaceOops *soops, ListBase *lb, ID *id, Bone *curBone, 
526
 
                                                          TreeElement *parent, int *a)
527
 
{
528
 
        TreeElement *te= outliner_add_element(soops, lb, id, parent, TSE_BONE, *a);
529
 
        
530
 
        (*a)++;
531
 
        te->name= curBone->name;
532
 
        te->directdata= curBone;
533
 
        
534
 
        for(curBone= curBone->childbase.first; curBone; curBone=curBone->next) {
535
 
                outliner_add_bone(soops, &te->subtree, id, curBone, te, a);
536
 
        }
537
 
}
538
 
 
539
 
static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
540
 
{
541
 
        SceneRenderLayer *srl;
542
 
        TreeElement *tenla= outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
543
 
        int a;
544
 
        
545
 
        tenla->name= "RenderLayers";
546
 
        for(a=0, srl= sce->r.layers.first; srl; srl= srl->next, a++) {
547
 
                TreeElement *tenlay= outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, a);
548
 
                tenlay->name= srl->name;
549
 
                tenlay->directdata= &srl->passflag;
550
 
                
551
 
                if(srl->light_override)
552
 
                        outliner_add_element(soops, &tenlay->subtree, srl->light_override, tenlay, TSE_LINKED_LAMP, 0);
553
 
                if(srl->mat_override)
554
 
                        outliner_add_element(soops, &tenlay->subtree, srl->mat_override, tenlay, TSE_LINKED_MAT, 0);
555
 
                
556
 
                outliner_add_passes(soops, tenlay, &sce->id, srl);
557
 
        }
558
 
        
559
 
        outliner_add_element(soops,  lb, sce->world, te, 0, 0);
560
 
}
561
 
 
562
 
static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv, 
563
 
                                                                                 TreeElement *parent, short type, short index)
564
 
{
565
 
        TreeElement *te;
566
 
        TreeStoreElem *tselem;
567
 
        ID *id= idv;
568
 
        int a = 0;
569
 
        
570
 
        if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
571
 
                id= ((PointerRNA*)idv)->id.data;
572
 
                if(!id) id= ((PointerRNA*)idv)->data;
573
 
        }
574
 
 
575
 
        if(id==NULL) return NULL;
576
 
 
577
 
        te= MEM_callocN(sizeof(TreeElement), "tree elem");
578
 
        /* add to the visual tree */
579
 
        BLI_addtail(lb, te);
580
 
        /* add to the storage */
581
 
        check_persistant(soops, te, id, type, index);
582
 
        tselem= TREESTORE(te);  
583
 
        
584
 
        te->parent= parent;
585
 
        te->index= index;       // for data arays
586
 
        if(ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP));
587
 
        else if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM));
588
 
        else if(type==TSE_ANIM_DATA);
589
 
        else {
590
 
                te->name= id->name+2; // default, can be overridden by Library or non-ID data
591
 
                te->idcode= GS(id->name);
592
 
        }
593
 
        
594
 
        if(type==0) {
595
 
 
596
 
                /* tuck pointer back in object, to construct hierarchy */
597
 
                if(GS(id->name)==ID_OB) id->newid= (ID *)te;
598
 
                
599
 
                /* expand specific data always */
600
 
                switch(GS(id->name)) {
601
 
                case ID_LI:
602
 
                        te->name= ((Library *)id)->name;
603
 
                        break;
604
 
                case ID_SCE:
605
 
                        outliner_add_scene_contents(soops, &te->subtree, (Scene *)id, te);
606
 
                        break;
607
 
                case ID_OB:
608
 
                        {
609
 
                                Object *ob= (Object *)id;
610
 
                                
611
 
                                outliner_add_element(soops, &te->subtree, ob->adt, te, TSE_ANIM_DATA, 0);
612
 
                                outliner_add_element(soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this
613
 
                                
614
 
                                if(ob->proxy && ob->id.lib==NULL)
615
 
                                        outliner_add_element(soops, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
616
 
                                
617
 
                                outliner_add_element(soops, &te->subtree, ob->data, te, 0, 0);
618
 
                                
619
 
                                if(ob->pose) {
620
 
                                        bArmature *arm= ob->data;
621
 
                                        bPoseChannel *pchan;
622
 
                                        TreeElement *ten;
623
 
                                        TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_POSE_BASE, 0);
624
 
                                        
625
 
                                        tenla->name= "Pose";
626
 
                                        
627
 
                                        if(arm->edbo==NULL && (ob->mode & OB_MODE_POSE)) {      // channels undefined in editmode, but we want the 'tenla' pose icon itself
628
 
                                                int a= 0, const_index= 1000;    /* ensure unique id for bone constraints */
629
 
                                                
630
 
                                                for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, a++) {
631
 
                                                        ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a);
632
 
                                                        ten->name= pchan->name;
633
 
                                                        ten->directdata= pchan;
634
 
                                                        pchan->prev= (bPoseChannel *)ten;
635
 
                                                        
636
 
                                                        if(pchan->constraints.first) {
637
 
                                                                //Object *target;
638
 
                                                                bConstraint *con;
639
 
                                                                TreeElement *ten1;
640
 
                                                                TreeElement *tenla1= outliner_add_element(soops, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0);
641
 
                                                                //char *str;
642
 
                                                                
643
 
                                                                tenla1->name= "Constraints";
644
 
                                                                for(con= pchan->constraints.first; con; con= con->next, const_index++) {
645
 
                                                                        ten1= outliner_add_element(soops, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index);
646
 
#if 0 /* disabled as it needs to be reworked for recoded constraints system */
647
 
                                                                        target= get_constraint_target(con, &str);
648
 
                                                                        if(str && str[0]) ten1->name= str;
649
 
                                                                        else if(target) ten1->name= target->id.name+2;
650
 
                                                                        else ten1->name= con->name;
651
 
#endif
652
 
                                                                        ten1->name= con->name;
653
 
                                                                        ten1->directdata= con;
654
 
                                                                        /* possible add all other types links? */
655
 
                                                                }
656
 
                                                        }
657
 
                                                }
658
 
                                                /* make hierarchy */
659
 
                                                ten= tenla->subtree.first;
660
 
                                                while(ten) {
661
 
                                                        TreeElement *nten= ten->next, *par;
662
 
                                                        tselem= TREESTORE(ten);
663
 
                                                        if(tselem->type==TSE_POSE_CHANNEL) {
664
 
                                                                pchan= (bPoseChannel *)ten->directdata;
665
 
                                                                if(pchan->parent) {
666
 
                                                                        BLI_remlink(&tenla->subtree, ten);
667
 
                                                                        par= (TreeElement *)pchan->parent->prev;
668
 
                                                                        BLI_addtail(&par->subtree, ten);
669
 
                                                                        ten->parent= par;
670
 
                                                                }
671
 
                                                        }
672
 
                                                        ten= nten;
673
 
                                                }
674
 
                                                /* restore prev pointers */
675
 
                                                pchan= ob->pose->chanbase.first;
676
 
                                                if(pchan) pchan->prev= NULL;
677
 
                                                for(; pchan; pchan= pchan->next) {
678
 
                                                        if(pchan->next) pchan->next->prev= pchan;
679
 
                                                }
680
 
                                        }
681
 
                                        
682
 
                                        /* Pose Groups */
683
 
                                        if(ob->pose->agroups.first) {
684
 
                                                bActionGroup *agrp;
685
 
                                                TreeElement *ten;
686
 
                                                TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0);
687
 
                                                int a= 0;
688
 
                                                
689
 
                                                tenla->name= "Bone Groups";
690
 
                                                for (agrp=ob->pose->agroups.first; agrp; agrp=agrp->next, a++) {
691
 
                                                        ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSEGRP, a);
692
 
                                                        ten->name= agrp->name;
693
 
                                                        ten->directdata= agrp;
694
 
                                                }
695
 
                                        }
696
 
                                }
697
 
                                
698
 
                                for(a=0; a<ob->totcol; a++) 
699
 
                                        outliner_add_element(soops, &te->subtree, ob->mat[a], te, 0, a);
700
 
                                
701
 
                                if(ob->constraints.first) {
702
 
                                        //Object *target;
703
 
                                        bConstraint *con;
704
 
                                        TreeElement *ten;
705
 
                                        TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0);
706
 
                                        int a= 0;
707
 
                                        //char *str;
708
 
                                        
709
 
                                        tenla->name= "Constraints";
710
 
                                        for(con= ob->constraints.first; con; con= con->next, a++) {
711
 
                                                ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a);
712
 
#if 0 /* disabled due to constraints system targets recode... code here needs review */
713
 
                                                target= get_constraint_target(con, &str);
714
 
                                                if(str && str[0]) ten->name= str;
715
 
                                                else if(target) ten->name= target->id.name+2;
716
 
                                                else ten->name= con->name;
717
 
#endif
718
 
                                                ten->name= con->name;
719
 
                                                ten->directdata= con;
720
 
                                                /* possible add all other types links? */
721
 
                                        }
722
 
                                }
723
 
                                
724
 
                                if(ob->modifiers.first) {
725
 
                                        ModifierData *md;
726
 
                                        TreeElement *temod = outliner_add_element(soops, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0);
727
 
                                        int index;
728
 
 
729
 
                                        temod->name = "Modifiers";
730
 
                                        for (index=0,md=ob->modifiers.first; md; index++,md=md->next) {
731
 
                                                TreeElement *te = outliner_add_element(soops, &temod->subtree, ob, temod, TSE_MODIFIER, index);
732
 
                                                te->name= md->name;
733
 
                                                te->directdata = md;
734
 
 
735
 
                                                if (md->type==eModifierType_Lattice) {
736
 
                                                        outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_LINKED_OB, 0);
737
 
                                                } else if (md->type==eModifierType_Curve) {
738
 
                                                        outliner_add_element(soops, &te->subtree, ((CurveModifierData*) md)->object, te, TSE_LINKED_OB, 0);
739
 
                                                } else if (md->type==eModifierType_Armature) {
740
 
                                                        outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_LINKED_OB, 0);
741
 
                                                } else if (md->type==eModifierType_Hook) {
742
 
                                                        outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_LINKED_OB, 0);
743
 
                                                } else if (md->type==eModifierType_ParticleSystem) {
744
 
                                                        TreeElement *ten;
745
 
                                                        ParticleSystem *psys= ((ParticleSystemModifierData*) md)->psys;
746
 
                                                        
747
 
                                                        ten = outliner_add_element(soops, &te->subtree, ob, te, TSE_LINKED_PSYS, 0);
748
 
                                                        ten->directdata = psys;
749
 
                                                        ten->name = psys->part->id.name+2;
750
 
                                                }
751
 
                                        }
752
 
                                }
753
 
                                if(ob->defbase.first) {
754
 
                                        bDeformGroup *defgroup;
755
 
                                        TreeElement *ten;
756
 
                                        TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
757
 
                                        int a= 0;
758
 
                                        
759
 
                                        tenla->name= "Vertex Groups";
760
 
                                        for (defgroup=ob->defbase.first; defgroup; defgroup=defgroup->next, a++) {
761
 
                                                ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a);
762
 
                                                ten->name= defgroup->name;
763
 
                                                ten->directdata= defgroup;
764
 
                                        }
765
 
                                }
766
 
                                
767
 
                                if(ob->dup_group)
768
 
                                        outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);     
769
 
                                
770
 
                        }
771
 
                        break;
772
 
                case ID_ME:
773
 
                        {
774
 
                                Mesh *me= (Mesh *)id;
775
 
                                
776
 
                                //outliner_add_element(soops, &te->subtree, me->adt, te, TSE_ANIM_DATA, 0);
777
 
                                
778
 
                                outliner_add_element(soops, &te->subtree, me->key, te, 0, 0);
779
 
                                for(a=0; a<me->totcol; a++) 
780
 
                                        outliner_add_element(soops, &te->subtree, me->mat[a], te, 0, a);
781
 
                                /* could do tfaces with image links, but the images are not grouped nicely.
782
 
                                   would require going over all tfaces, sort images in use. etc... */
783
 
                        }
784
 
                        break;
785
 
                case ID_CU:
786
 
                        {
787
 
                                Curve *cu= (Curve *)id;
788
 
                                
789
 
                                outliner_add_element(soops, &te->subtree, cu->adt, te, TSE_ANIM_DATA, 0);
790
 
                                
791
 
                                for(a=0; a<cu->totcol; a++) 
792
 
                                        outliner_add_element(soops, &te->subtree, cu->mat[a], te, 0, a);
793
 
                        }
794
 
                        break;
795
 
                case ID_MB:
796
 
                        {
797
 
                                MetaBall *mb= (MetaBall *)id;
798
 
                                for(a=0; a<mb->totcol; a++) 
799
 
                                        outliner_add_element(soops, &te->subtree, mb->mat[a], te, 0, a);
800
 
                        }
801
 
                        break;
802
 
                case ID_MA:
803
 
                {
804
 
                        Material *ma= (Material *)id;
805
 
                        
806
 
                        outliner_add_element(soops, &te->subtree, ma->adt, te, TSE_ANIM_DATA, 0);
807
 
                        
808
 
                        for(a=0; a<MAX_MTEX; a++) {
809
 
                                if(ma->mtex[a]) outliner_add_element(soops, &te->subtree, ma->mtex[a]->tex, te, 0, a);
810
 
                        }
811
 
                }
812
 
                        break;
813
 
                case ID_TE:
814
 
                        {
815
 
                                Tex *tex= (Tex *)id;
816
 
                                
817
 
                                outliner_add_element(soops, &te->subtree, tex->adt, te, TSE_ANIM_DATA, 0);
818
 
                                outliner_add_element(soops, &te->subtree, tex->ima, te, 0, 0);
819
 
                        }
820
 
                        break;
821
 
                case ID_CA:
822
 
                        {
823
 
                                Camera *ca= (Camera *)id;
824
 
                                outliner_add_element(soops, &te->subtree, ca->adt, te, TSE_ANIM_DATA, 0);
825
 
                        }
826
 
                        break;
827
 
                case ID_LA:
828
 
                        {
829
 
                                Lamp *la= (Lamp *)id;
830
 
                                
831
 
                                outliner_add_element(soops, &te->subtree, la->adt, te, TSE_ANIM_DATA, 0);
832
 
                                
833
 
                                for(a=0; a<MAX_MTEX; a++) {
834
 
                                        if(la->mtex[a]) outliner_add_element(soops, &te->subtree, la->mtex[a]->tex, te, 0, a);
835
 
                                }
836
 
                        }
837
 
                        break;
838
 
                case ID_WO:
839
 
                        {
840
 
                                World *wrld= (World *)id;
841
 
                                
842
 
                                outliner_add_element(soops, &te->subtree, wrld->adt, te, TSE_ANIM_DATA, 0);
843
 
                                
844
 
                                for(a=0; a<MAX_MTEX; a++) {
845
 
                                        if(wrld->mtex[a]) outliner_add_element(soops, &te->subtree, wrld->mtex[a]->tex, te, 0, a);
846
 
                                }
847
 
                        }
848
 
                        break;
849
 
                case ID_KE:
850
 
                        {
851
 
                                Key *key= (Key *)id;
852
 
                                
853
 
                                outliner_add_element(soops, &te->subtree, key->adt, te, TSE_ANIM_DATA, 0);
854
 
                        }
855
 
                        break;
856
 
                case ID_AC:
857
 
                        {
858
 
                                // XXX do we want to be exposing the F-Curves here?
859
 
                                //bAction *act= (bAction *)id;
860
 
                        }
861
 
                        break;
862
 
                case ID_AR:
863
 
                        {
864
 
                                bArmature *arm= (bArmature *)id;
865
 
                                int a= 0;
866
 
                                
867
 
                                if(arm->edbo) {
868
 
                                        EditBone *ebone;
869
 
                                        TreeElement *ten;
870
 
                                        
871
 
                                        for (ebone = arm->edbo->first; ebone; ebone=ebone->next, a++) {
872
 
                                                ten= outliner_add_element(soops, &te->subtree, id, te, TSE_EBONE, a);
873
 
                                                ten->directdata= ebone;
874
 
                                                ten->name= ebone->name;
875
 
                                                ebone->temp= ten;
876
 
                                        }
877
 
                                        /* make hierarchy */
878
 
                                        ten= te->subtree.first;
879
 
                                        while(ten) {
880
 
                                                TreeElement *nten= ten->next, *par;
881
 
                                                ebone= (EditBone *)ten->directdata;
882
 
                                                if(ebone->parent) {
883
 
                                                        BLI_remlink(&te->subtree, ten);
884
 
                                                        par= ebone->parent->temp;
885
 
                                                        BLI_addtail(&par->subtree, ten);
886
 
                                                        ten->parent= par;
887
 
                                                }
888
 
                                                ten= nten;
889
 
                                        }
890
 
                                }
891
 
                                else {
892
 
                                        /* do not extend Armature when we have posemode */
893
 
                                        tselem= TREESTORE(te->parent);
894
 
                                        if( GS(tselem->id->name)==ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE);
895
 
                                        else {
896
 
                                                Bone *curBone;
897
 
                                                for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
898
 
                                                        outliner_add_bone(soops, &te->subtree, id, curBone, te, &a);
899
 
                                                }
900
 
                                        }
901
 
                                }
902
 
                        }
903
 
                        break;
904
 
                }
905
 
        }
906
 
        else if(type==TSE_ANIM_DATA) {
907
 
                AnimData *adt= (AnimData *)idv;
908
 
                
909
 
                /* this element's info */
910
 
                te->name= "Animation";
911
 
                
912
 
                /* Action */
913
 
                outliner_add_element(soops, &te->subtree, adt->action, te, 0, 0);
914
 
                
915
 
                /* Drivers */
916
 
                if (adt->drivers.first) {
917
 
                        TreeElement *ted= outliner_add_element(soops, &te->subtree, adt, te, TSE_DRIVER_BASE, 0);
918
 
                        ID *lastadded= NULL;
919
 
                        FCurve *fcu;
920
 
                        
921
 
                        ted->name= "Drivers";
922
 
                
923
 
                        for (fcu= adt->drivers.first; fcu; fcu= fcu->next) {
924
 
                                if (fcu->driver && fcu->driver->variables.first)  {
925
 
                                        ChannelDriver *driver= fcu->driver;
926
 
                                        DriverVar *dvar;
927
 
                                        
928
 
                                        for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
929
 
                                                /* loop over all targets used here */
930
 
                                                DRIVER_TARGETS_USED_LOOPER(dvar) 
931
 
                                                {
932
 
                                                        if (lastadded != dtar->id) {
933
 
                                                                // XXX this lastadded check is rather lame, and also fails quite badly...
934
 
                                                                outliner_add_element(soops, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0);
935
 
                                                                lastadded= dtar->id;
936
 
                                                        }
937
 
                                                }
938
 
                                                DRIVER_TARGETS_LOOPER_END
939
 
                                        }
940
 
                                }
941
 
                        }
942
 
                }
943
 
                
944
 
                /* NLA Data */
945
 
                if (adt->nla_tracks.first) {
946
 
                        TreeElement *tenla= outliner_add_element(soops, &te->subtree, adt, te, TSE_NLA, 0);
947
 
                        NlaTrack *nlt;
948
 
                        int a= 0;
949
 
                        
950
 
                        tenla->name= "NLA Tracks";
951
 
                        
952
 
                        for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
953
 
                                TreeElement *tenlt= outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a);
954
 
                                NlaStrip *strip;
955
 
                                TreeElement *ten;
956
 
                                int b= 0;
957
 
                                
958
 
                                tenlt->name= nlt->name;
959
 
                                
960
 
                                for (strip=nlt->strips.first; strip; strip=strip->next, b++) {
961
 
                                        ten= outliner_add_element(soops, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b);
962
 
                                        if(ten) ten->directdata= strip;
963
 
                                }
964
 
                        }
965
 
                }
966
 
        }
967
 
        else if(type==TSE_SEQUENCE) {
968
 
                Sequence *seq= (Sequence*) idv;
969
 
                Sequence *p;
970
 
 
971
 
                /*
972
 
                 * The idcode is a little hack, but the outliner
973
 
                 * only check te->idcode if te->type is equal to zero,
974
 
                 * so this is "safe".
975
 
                 */
976
 
                te->idcode= seq->type;
977
 
                te->directdata= seq;
978
 
 
979
 
                if(seq->type<7) {
980
 
                        /*
981
 
                         * This work like the sequence.
982
 
                         * If the sequence have a name (not default name)
983
 
                         * show it, in other case put the filename.
984
 
                         */
985
 
                        if(strcmp(seq->name, "SQ"))
986
 
                                te->name= seq->name;
987
 
                        else {
988
 
                                if((seq->strip) && (seq->strip->stripdata))
989
 
                                        te->name= seq->strip->stripdata->name;
990
 
                                else if((seq->strip) && (seq->strip->tstripdata) && (seq->strip->tstripdata->ibuf))
991
 
                                        te->name= seq->strip->tstripdata->ibuf->name;
992
 
                                else
993
 
                                        te->name= "SQ None";
994
 
                        }
995
 
 
996
 
                        if(seq->type==SEQ_META) {
997
 
                                te->name= "Meta Strip";
998
 
                                p= seq->seqbase.first;
999
 
                                while(p) {
1000
 
                                        outliner_add_element(soops, &te->subtree, (void*)p, te, TSE_SEQUENCE, index);
1001
 
                                        p= p->next;
1002
 
                                }
1003
 
                        }
1004
 
                        else
1005
 
                                outliner_add_element(soops, &te->subtree, (void*)seq->strip, te, TSE_SEQ_STRIP, index);
1006
 
                }
1007
 
                else
1008
 
                        te->name= "Effect";
1009
 
        }
1010
 
        else if(type==TSE_SEQ_STRIP) {
1011
 
                Strip *strip= (Strip *)idv;
1012
 
 
1013
 
                if(strip->dir)
1014
 
                        te->name= strip->dir;
1015
 
                else
1016
 
                        te->name= "Strip None";
1017
 
                te->directdata= strip;
1018
 
        }
1019
 
        else if(type==TSE_SEQUENCE_DUP) {
1020
 
                Sequence *seq= (Sequence*)idv;
1021
 
 
1022
 
                te->idcode= seq->type;
1023
 
                te->directdata= seq;
1024
 
                te->name= seq->strip->stripdata->name;
1025
 
        }
1026
 
        else if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
1027
 
                PointerRNA pptr, propptr, *ptr= (PointerRNA*)idv;
1028
 
                PropertyRNA *prop, *iterprop;
1029
 
                PropertyType proptype;
1030
 
                int a, tot;
1031
 
 
1032
 
                /* we do lazy build, for speed and to avoid infinite recusion */
1033
 
 
1034
 
                if(ptr->data == NULL) {
1035
 
                        te->name= "(empty)";
1036
 
                }
1037
 
                else if(type == TSE_RNA_STRUCT) {
1038
 
                        /* struct */
1039
 
                        te->name= RNA_struct_name_get_alloc(ptr, NULL, 0);
1040
 
 
1041
 
                        if(te->name)
1042
 
                                te->flag |= TE_FREE_NAME;
1043
 
                        else
1044
 
                                te->name= (char*)RNA_struct_ui_name(ptr->type);
1045
 
 
1046
 
                        iterprop= RNA_struct_iterator_property(ptr->type);
1047
 
                        tot= RNA_property_collection_length(ptr, iterprop);
1048
 
 
1049
 
                        /* auto open these cases */
1050
 
                        if(!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER)
1051
 
                                if(!tselem->used)
1052
 
                                        tselem->flag &= ~TSE_CLOSED;
1053
 
 
1054
 
                        if(!(tselem->flag & TSE_CLOSED)) {
1055
 
                                for(a=0; a<tot; a++)
1056
 
                                        outliner_add_element(soops, &te->subtree, (void*)ptr, te, TSE_RNA_PROPERTY, a);
1057
 
                        }
1058
 
                        else if(tot)
1059
 
                                te->flag |= TE_LAZY_CLOSED;
1060
 
 
1061
 
                        te->rnaptr= *ptr;
1062
 
                }
1063
 
                else if(type == TSE_RNA_PROPERTY) {
1064
 
                        /* property */
1065
 
                        iterprop= RNA_struct_iterator_property(ptr->type);
1066
 
                        RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr);
1067
 
 
1068
 
                        prop= propptr.data;
1069
 
                        proptype= RNA_property_type(prop);
1070
 
 
1071
 
                        te->name= (char*)RNA_property_ui_name(prop);
1072
 
                        te->directdata= prop;
1073
 
                        te->rnaptr= *ptr;
1074
 
 
1075
 
                        if(proptype == PROP_POINTER) {
1076
 
                                pptr= RNA_property_pointer_get(ptr, prop);
1077
 
 
1078
 
                                if(pptr.data) {
1079
 
                                        if(!(tselem->flag & TSE_CLOSED))
1080
 
                                                outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, -1);
1081
 
                                        else
1082
 
                                                te->flag |= TE_LAZY_CLOSED;
1083
 
                                }
1084
 
                        }
1085
 
                        else if(proptype == PROP_COLLECTION) {
1086
 
                                tot= RNA_property_collection_length(ptr, prop);
1087
 
 
1088
 
                                if(!(tselem->flag & TSE_CLOSED)) {
1089
 
                                        for(a=0; a<tot; a++) {
1090
 
                                                RNA_property_collection_lookup_int(ptr, prop, a, &pptr);
1091
 
                                                outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, -1);
1092
 
                                        }
1093
 
                                }
1094
 
                                else if(tot)
1095
 
                                        te->flag |= TE_LAZY_CLOSED;
1096
 
                        }
1097
 
                        else if(ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
1098
 
                                tot= RNA_property_array_length(ptr, prop);
1099
 
 
1100
 
                                if(!(tselem->flag & TSE_CLOSED)) {
1101
 
                                        for(a=0; a<tot; a++)
1102
 
                                                outliner_add_element(soops, &te->subtree, (void*)ptr, te, TSE_RNA_ARRAY_ELEM, a);
1103
 
                                }
1104
 
                                else if(tot)
1105
 
                                        te->flag |= TE_LAZY_CLOSED;
1106
 
                        }
1107
 
                }
1108
 
                else if(type == TSE_RNA_ARRAY_ELEM) {
1109
 
                        char c;
1110
 
 
1111
 
                        prop= parent->directdata;
1112
 
 
1113
 
                        te->directdata= prop;
1114
 
                        te->rnaptr= *ptr;
1115
 
                        te->index= index;
1116
 
 
1117
 
                        c= RNA_property_array_item_char(prop, index);
1118
 
 
1119
 
                        te->name= MEM_callocN(sizeof(char)*20, "OutlinerRNAArrayName");
1120
 
                        if(c) sprintf(te->name, "  %c", c);
1121
 
                        else sprintf(te->name, "  %d", index+1);
1122
 
                        te->flag |= TE_FREE_NAME;
1123
 
                }
1124
 
        }
1125
 
        else if(type == TSE_KEYMAP) {
1126
 
                wmKeyMap *km= (wmKeyMap *)idv;
1127
 
                wmKeyMapItem *kmi;
1128
 
                char opname[OP_MAX_TYPENAME];
1129
 
                
1130
 
                te->directdata= idv;
1131
 
                te->name= km->idname;
1132
 
                
1133
 
                if(!(tselem->flag & TSE_CLOSED)) {
1134
 
                        a= 0;
1135
 
                        
1136
 
                        for (kmi= km->items.first; kmi; kmi= kmi->next, a++) {
1137
 
                                const char *key= WM_key_event_string(kmi->type);
1138
 
                                
1139
 
                                if(key[0]) {
1140
 
                                        wmOperatorType *ot= NULL;
1141
 
                                        
1142
 
                                        if(kmi->propvalue);
1143
 
                                        else ot= WM_operatortype_find(kmi->idname, 0);
1144
 
                                        
1145
 
                                        if(ot || kmi->propvalue) {
1146
 
                                                TreeElement *ten= outliner_add_element(soops, &te->subtree, kmi, te, TSE_KEYMAP_ITEM, a);
1147
 
                                                
1148
 
                                                ten->directdata= kmi;
1149
 
                                                
1150
 
                                                if(kmi->propvalue) {
1151
 
                                                        ten->name= "Modal map, not yet";
1152
 
                                                }
1153
 
                                                else {
1154
 
                                                        WM_operator_py_idname(opname, ot->idname);
1155
 
                                                        ten->name= BLI_strdup(opname);
1156
 
                                                        ten->flag |= TE_FREE_NAME;
1157
 
                                                }
1158
 
                                        }
1159
 
                                }
1160
 
                        }
1161
 
                }
1162
 
                else 
1163
 
                        te->flag |= TE_LAZY_CLOSED;
1164
 
        }
1165
 
 
1166
 
        return te;
1167
 
}
1168
 
 
1169
 
static void outliner_make_hierarchy(SpaceOops *soops, ListBase *lb)
1170
 
{
1171
 
        TreeElement *te, *ten, *tep;
1172
 
        TreeStoreElem *tselem;
1173
 
 
1174
 
        /* build hierarchy */
1175
 
        // XXX also, set extents here...
1176
 
        te= lb->first;
1177
 
        while(te) {
1178
 
                ten= te->next;
1179
 
                tselem= TREESTORE(te);
1180
 
                
1181
 
                if(tselem->type==0 && te->idcode==ID_OB) {
1182
 
                        Object *ob= (Object *)tselem->id;
1183
 
                        if(ob->parent && ob->parent->id.newid) {
1184
 
                                BLI_remlink(lb, te);
1185
 
                                tep= (TreeElement *)ob->parent->id.newid;
1186
 
                                BLI_addtail(&tep->subtree, te);
1187
 
                                // set correct parent pointers
1188
 
                                for(te=tep->subtree.first; te; te= te->next) te->parent= tep;
1189
 
                        }
1190
 
                }
1191
 
                te= ten;
1192
 
        }
1193
 
}
1194
 
 
1195
 
/* Helped function to put duplicate sequence in the same tree. */
1196
 
int need_add_seq_dup(Sequence *seq)
1197
 
{
1198
 
        Sequence *p;
1199
 
 
1200
 
        if((!seq->strip) || (!seq->strip->stripdata) || (!seq->strip->stripdata->name))
1201
 
                return(1);
1202
 
 
1203
 
        /*
1204
 
         * First check backward, if we found a duplicate
1205
 
         * sequence before this, don't need it, just return.
1206
 
         */
1207
 
        p= seq->prev;
1208
 
        while(p) {
1209
 
                if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
1210
 
                        p= p->prev;
1211
 
                        continue;
1212
 
                }
1213
 
 
1214
 
                if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
1215
 
                        return(2);
1216
 
                p= p->prev;
1217
 
        }
1218
 
 
1219
 
        p= seq->next;
1220
 
        while(p) {
1221
 
                if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
1222
 
                        p= p->next;
1223
 
                        continue;
1224
 
                }
1225
 
 
1226
 
                if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
1227
 
                        return(0);
1228
 
                p= p->next;
1229
 
        }
1230
 
        return(1);
1231
 
}
1232
 
 
1233
 
void add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *te, short index)
1234
 
{
1235
 
        TreeElement *ch;
1236
 
        Sequence *p;
1237
 
 
1238
 
        p= seq;
1239
 
        while(p) {
1240
 
                if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
1241
 
                        p= p->next;
1242
 
                        continue;
1243
 
                }
1244
 
 
1245
 
                if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
1246
 
                        ch= outliner_add_element(soops, &te->subtree, (void*)p, te, TSE_SEQUENCE, index);
1247
 
                p= p->next;
1248
 
        }
1249
 
}
1250
 
 
1251
 
static int outliner_filter_has_name(TreeElement *te, char *name, int flags)
1252
 
{
1253
 
#if 0
1254
 
        int found= 0;
1255
 
        
1256
 
        /* determine if match */
1257
 
        if (flags & SO_FIND_CASE_SENSITIVE) {
1258
 
                if (flags & SO_FIND_COMPLETE)
1259
 
                        found= strcmp(te->name, name) == 0;
1260
 
                else
1261
 
                        found= strstr(te->name, name) != NULL;
1262
 
        }
1263
 
        else {
1264
 
                if (flags & SO_FIND_COMPLETE)
1265
 
                        found= BLI_strcasecmp(te->name, name) == 0;
1266
 
                else
1267
 
                        found= BLI_strcasestr(te->name, name) != NULL;
1268
 
        }
1269
 
#else
1270
 
        
1271
 
        int fn_flag= 0;
1272
 
        int found= 0;
1273
 
        
1274
 
        if ((flags & SO_FIND_CASE_SENSITIVE) == 0)
1275
 
                fn_flag |= FNM_CASEFOLD;
1276
 
 
1277
 
        if (flags & SO_FIND_COMPLETE) {
1278
 
                found= fnmatch(name, te->name, fn_flag)==0;
1279
 
        }
1280
 
        else {
1281
 
                char fn_name[sizeof(((struct SpaceOops *)NULL)->search_string) + 2];
1282
 
                sprintf(fn_name, "*%s*", name);
1283
 
                found= fnmatch(fn_name, te->name, fn_flag)==0;
1284
 
        }
1285
 
        return found;
1286
 
#endif
1287
 
}
1288
 
 
1289
 
static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
1290
 
{
1291
 
        TreeElement *te, *ten;
1292
 
        TreeStoreElem *tselem;
1293
 
        
1294
 
        /* although we don't have any search string, we return TRUE 
1295
 
         * since the entire tree is ok then...
1296
 
         */
1297
 
        if (soops->search_string[0]==0) 
1298
 
                return 1;
1299
 
 
1300
 
        for (te= lb->first; te; te= ten) {
1301
 
                ten= te->next;
1302
 
                
1303
 
                if (0==outliner_filter_has_name(te, soops->search_string, soops->search_flags)) {
1304
 
                        /* item isn't something we're looking for, but...
1305
 
                         *      - if the subtree is expanded, check if there are any matches that can be easily found
1306
 
                         *              so that searching for "cu" in the default scene will still match the Cube
1307
 
                         *      - otherwise, we can't see within the subtree and the item doesn't match,
1308
 
                         *              so these can be safely ignored (i.e. the subtree can get freed)
1309
 
                         */
1310
 
                        tselem= TREESTORE(te);
1311
 
                        
1312
 
                        if ((tselem->flag & TSE_CLOSED) || outliner_filter_tree(soops, &te->subtree)==0) { 
1313
 
                                outliner_free_tree(&te->subtree);
1314
 
                                BLI_remlink(lb, te);
1315
 
                                
1316
 
                                if(te->flag & TE_FREE_NAME) MEM_freeN(te->name);
1317
 
                                MEM_freeN(te);
1318
 
                        }
1319
 
                }
1320
 
                else {
1321
 
                        /* filter subtree too */
1322
 
                        outliner_filter_tree(soops, &te->subtree);
1323
 
                }
1324
 
        }
1325
 
        
1326
 
        /* if there are still items in the list, that means that there were still some matches */
1327
 
        return (lb->first != NULL);
1328
 
}
1329
 
 
1330
 
 
1331
 
static void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
1332
 
{
1333
 
        Base *base;
1334
 
        Object *ob;
1335
 
        TreeElement *te=NULL, *ten;
1336
 
        TreeStoreElem *tselem;
1337
 
        int show_opened= (soops->treestore==NULL); /* on first view, we open scenes */
1338
 
 
1339
 
        if(soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW))
1340
 
           return;
1341
 
           
1342
 
        outliner_free_tree(&soops->tree);
1343
 
        outliner_storage_cleanup(soops);
1344
 
        
1345
 
        /* clear ob id.new flags */
1346
 
        for(ob= mainvar->object.first; ob; ob= ob->id.next) ob->id.newid= NULL;
1347
 
        
1348
 
        /* options */
1349
 
        if(soops->outlinevis == SO_LIBRARIES) {
1350
 
                Library *lib;
1351
 
                
1352
 
                for(lib= mainvar->library.first; lib; lib= lib->id.next) {
1353
 
                        ten= outliner_add_element(soops, &soops->tree, lib, NULL, 0, 0);
1354
 
                        lib->id.newid= (ID *)ten;
1355
 
                }
1356
 
                /* make hierarchy */
1357
 
                ten= soops->tree.first;
1358
 
                while(ten) {
1359
 
                        TreeElement *nten= ten->next, *par;
1360
 
                        tselem= TREESTORE(ten);
1361
 
                        lib= (Library *)tselem->id;
1362
 
                        if(lib->parent) {
1363
 
                                BLI_remlink(&soops->tree, ten);
1364
 
                                par= (TreeElement *)lib->parent->id.newid;
1365
 
                                BLI_addtail(&par->subtree, ten);
1366
 
                                ten->parent= par;
1367
 
                        }
1368
 
                        ten= nten;
1369
 
                }
1370
 
                /* restore newid pointers */
1371
 
                for(lib= mainvar->library.first; lib; lib= lib->id.next)
1372
 
                        lib->id.newid= NULL;
1373
 
                
1374
 
        }
1375
 
        else if(soops->outlinevis == SO_ALL_SCENES) {
1376
 
                Scene *sce;
1377
 
                for(sce= mainvar->scene.first; sce; sce= sce->id.next) {
1378
 
                        te= outliner_add_element(soops, &soops->tree, sce, NULL, 0, 0);
1379
 
                        tselem= TREESTORE(te);
1380
 
                        if(sce==scene && show_opened) 
1381
 
                                tselem->flag &= ~TSE_CLOSED;
1382
 
                        
1383
 
                        for(base= sce->base.first; base; base= base->next) {
1384
 
                                ten= outliner_add_element(soops, &te->subtree, base->object, te, 0, 0);
1385
 
                                ten->directdata= base;
1386
 
                        }
1387
 
                        outliner_make_hierarchy(soops, &te->subtree);
1388
 
                        /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
1389
 
                        for(base= sce->base.first; base; base= base->next) base->object->id.newid= NULL;
1390
 
                }
1391
 
        }
1392
 
        else if(soops->outlinevis == SO_CUR_SCENE) {
1393
 
                
1394
 
                outliner_add_scene_contents(soops, &soops->tree, scene, NULL);
1395
 
                
1396
 
                for(base= scene->base.first; base; base= base->next) {
1397
 
                        ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
1398
 
                        ten->directdata= base;
1399
 
                }
1400
 
                outliner_make_hierarchy(soops, &soops->tree);
1401
 
        }
1402
 
        else if(soops->outlinevis == SO_VISIBLE) {
1403
 
                for(base= scene->base.first; base; base= base->next) {
1404
 
                        if(base->lay & scene->lay)
1405
 
                                outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
1406
 
                }
1407
 
                outliner_make_hierarchy(soops, &soops->tree);
1408
 
        }
1409
 
        else if(soops->outlinevis == SO_GROUPS) {
1410
 
                Group *group;
1411
 
                GroupObject *go;
1412
 
                
1413
 
                for(group= mainvar->group.first; group; group= group->id.next) {
1414
 
                        if(group->gobject.first) {
1415
 
                                te= outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
1416
 
                                tselem= TREESTORE(te);
1417
 
                                
1418
 
                                for(go= group->gobject.first; go; go= go->next) {
1419
 
                                        ten= outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
1420
 
                                        ten->directdata= NULL; /* eh, why? */
1421
 
                                }
1422
 
                                outliner_make_hierarchy(soops, &te->subtree);
1423
 
                                /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
1424
 
                                for(go= group->gobject.first; go; go= go->next) go->ob->id.newid= NULL;
1425
 
                        }
1426
 
                }
1427
 
        }
1428
 
        else if(soops->outlinevis == SO_SAME_TYPE) {
1429
 
                Object *ob= OBACT;
1430
 
                if(ob) {
1431
 
                        for(base= scene->base.first; base; base= base->next) {
1432
 
                                if(base->object->type==ob->type) {
1433
 
                                        ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
1434
 
                                        ten->directdata= base;
1435
 
                                }
1436
 
                        }
1437
 
                        outliner_make_hierarchy(soops, &soops->tree);
1438
 
                }
1439
 
        }
1440
 
        else if(soops->outlinevis == SO_SELECTED) {
1441
 
                for(base= scene->base.first; base; base= base->next) {
1442
 
                        if(base->lay & scene->lay) {
1443
 
                                if(base==BASACT || (base->flag & SELECT)) {
1444
 
                                        ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
1445
 
                                        ten->directdata= base;
1446
 
                                }
1447
 
                        }
1448
 
                }
1449
 
                outliner_make_hierarchy(soops, &soops->tree);
1450
 
        }
1451
 
        else if(soops->outlinevis==SO_SEQUENCE) {
1452
 
                Sequence *seq;
1453
 
                Editing *ed= seq_give_editing(scene, FALSE);
1454
 
                int op;
1455
 
 
1456
 
                if(ed==NULL)
1457
 
                        return;
1458
 
 
1459
 
                seq= ed->seqbasep->first;
1460
 
                if(!seq)
1461
 
                        return;
1462
 
 
1463
 
                while(seq) {
1464
 
                        op= need_add_seq_dup(seq);
1465
 
                        if(op==1)
1466
 
                                ten= outliner_add_element(soops, &soops->tree, (void*)seq, NULL, TSE_SEQUENCE, 0);
1467
 
                        else if(op==0) {
1468
 
                                ten= outliner_add_element(soops, &soops->tree, (void*)seq, NULL, TSE_SEQUENCE_DUP, 0);
1469
 
                                add_seq_dup(soops, seq, ten, 0);
1470
 
                        }
1471
 
                        seq= seq->next;
1472
 
                }
1473
 
        }
1474
 
        else if(soops->outlinevis==SO_DATABLOCKS) {
1475
 
                PointerRNA mainptr;
1476
 
 
1477
 
                RNA_main_pointer_create(mainvar, &mainptr);
1478
 
 
1479
 
                ten= outliner_add_element(soops, &soops->tree, (void*)&mainptr, NULL, TSE_RNA_STRUCT, -1);
1480
 
 
1481
 
                if(show_opened)  {
1482
 
                        tselem= TREESTORE(ten);
1483
 
                        tselem->flag &= ~TSE_CLOSED;
1484
 
                }
1485
 
        }
1486
 
        else if(soops->outlinevis==SO_USERDEF) {
1487
 
                PointerRNA userdefptr;
1488
 
 
1489
 
                RNA_pointer_create(NULL, &RNA_UserPreferences, &U, &userdefptr);
1490
 
 
1491
 
                ten= outliner_add_element(soops, &soops->tree, (void*)&userdefptr, NULL, TSE_RNA_STRUCT, -1);
1492
 
 
1493
 
                if(show_opened)  {
1494
 
                        tselem= TREESTORE(ten);
1495
 
                        tselem->flag &= ~TSE_CLOSED;
1496
 
                }
1497
 
        }
1498
 
        else if(soops->outlinevis==SO_KEYMAP) {
1499
 
                wmWindowManager *wm= mainvar->wm.first;
1500
 
                wmKeyMap *km;
1501
 
                
1502
 
                for(km= wm->defaultconf->keymaps.first; km; km= km->next) {
1503
 
                        ten= outliner_add_element(soops, &soops->tree, (void*)km, NULL, TSE_KEYMAP, 0);
1504
 
                }
1505
 
        }
1506
 
        else {
1507
 
                ten= outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
1508
 
                if(ten) ten->directdata= BASACT;
1509
 
        }
1510
 
 
1511
 
        outliner_sort(soops, &soops->tree);
1512
 
        outliner_filter_tree(soops, &soops->tree);
1513
 
}
1514
 
 
1515
 
/* **************** INTERACTIVE ************* */
1516
 
 
1517
 
static int outliner_count_levels(SpaceOops *soops, ListBase *lb, int curlevel)
1518
 
{
1519
 
        TreeElement *te;
1520
 
        int level=curlevel, lev;
1521
 
        
1522
 
        for(te= lb->first; te; te= te->next) {
1523
 
                
1524
 
                lev= outliner_count_levels(soops, &te->subtree, curlevel+1);
1525
 
                if(lev>level) level= lev;
1526
 
        }
1527
 
        return level;
1528
 
}
1529
 
 
1530
 
static int outliner_has_one_flag(SpaceOops *soops, ListBase *lb, short flag, short curlevel)
1531
 
{
1532
 
        TreeElement *te;
1533
 
        TreeStoreElem *tselem;
1534
 
        int level;
1535
 
        
1536
 
        for(te= lb->first; te; te= te->next) {
1537
 
                tselem= TREESTORE(te);
1538
 
                if(tselem->flag & flag) return curlevel;
1539
 
                
1540
 
                level= outliner_has_one_flag(soops, &te->subtree, flag, curlevel+1);
1541
 
                if(level) return level;
1542
 
        }
1543
 
        return 0;
1544
 
}
1545
 
 
1546
 
static void outliner_set_flag(SpaceOops *soops, ListBase *lb, short flag, short set)
1547
 
{
1548
 
        TreeElement *te;
1549
 
        TreeStoreElem *tselem;
1550
 
        
1551
 
        for(te= lb->first; te; te= te->next) {
1552
 
                tselem= TREESTORE(te);
1553
 
                if(set==0) tselem->flag &= ~flag;
1554
 
                else tselem->flag |= flag;
1555
 
                outliner_set_flag(soops, &te->subtree, flag, set);
1556
 
        }
1557
 
}
1558
 
 
1559
 
/* --- */
1560
 
 
1561
 
void object_toggle_visibility_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
1562
 
{
1563
 
        Base *base= (Base *)te->directdata;
1564
 
        
1565
 
        if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
1566
 
        if(base) {
1567
 
                base->object->restrictflag^=OB_RESTRICT_VIEW;
1568
 
        }
1569
 
}
1570
 
 
1571
 
static int outliner_toggle_visibility_exec(bContext *C, wmOperator *op)
1572
 
{
1573
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
1574
 
        Scene *scene= CTX_data_scene(C);
1575
 
        ARegion *ar= CTX_wm_region(C);
1576
 
        
1577
 
        outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb);
1578
 
        
1579
 
        ED_region_tag_redraw(ar);
1580
 
        
1581
 
        return OPERATOR_FINISHED;
1582
 
}
1583
 
 
1584
 
void OUTLINER_OT_visibility_toggle(wmOperatorType *ot)
1585
 
{
1586
 
        /* identifiers */
1587
 
        ot->name= "Toggle Visability";
1588
 
        ot->idname= "OUTLINER_OT_visibility_toggle";
1589
 
        ot->description= "Toggle the visibility of selected items";
1590
 
        
1591
 
        /* callbacks */
1592
 
        ot->exec= outliner_toggle_visibility_exec;
1593
 
        ot->poll= ED_operator_outliner_active;
1594
 
        
1595
 
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1596
 
}
1597
 
 
1598
 
/* --- */
1599
 
 
1600
 
static void object_toggle_selectability_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
1601
 
{
1602
 
        Base *base= (Base *)te->directdata;
1603
 
        
1604
 
        if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
1605
 
        if(base) {
1606
 
                base->object->restrictflag^=OB_RESTRICT_SELECT;
1607
 
        }
1608
 
}
1609
 
 
1610
 
static int outliner_toggle_selectability_exec(bContext *C, wmOperator *op)
1611
 
{
1612
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
1613
 
        Scene *scene= CTX_data_scene(C);
1614
 
        ARegion *ar= CTX_wm_region(C);
1615
 
        
1616
 
        outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_selectability_cb);
1617
 
        
1618
 
        ED_region_tag_redraw(ar);
1619
 
        
1620
 
        return OPERATOR_FINISHED;
1621
 
}
1622
 
 
1623
 
void OUTLINER_OT_selectability_toggle(wmOperatorType *ot)
1624
 
{
1625
 
        /* identifiers */
1626
 
        ot->name= "Toggle Selectability";
1627
 
        ot->idname= "OUTLINER_OT_selectability_toggle";
1628
 
        ot->description= "Toggle the selectability";
1629
 
        
1630
 
        /* callbacks */
1631
 
        ot->exec= outliner_toggle_selectability_exec;
1632
 
        ot->poll= ED_operator_outliner_active;
1633
 
        
1634
 
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1635
 
}
1636
 
 
1637
 
void object_toggle_renderability_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
1638
 
{
1639
 
        Base *base= (Base *)te->directdata;
1640
 
        
1641
 
        if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
1642
 
        if(base) {
1643
 
                base->object->restrictflag^=OB_RESTRICT_RENDER;
1644
 
        }
1645
 
}
1646
 
 
1647
 
static int outliner_toggle_renderability_exec(bContext *C, wmOperator *op)
1648
 
{
1649
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
1650
 
        Scene *scene= CTX_data_scene(C);
1651
 
        ARegion *ar= CTX_wm_region(C);
1652
 
        
1653
 
        outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb);
1654
 
        
1655
 
        ED_region_tag_redraw(ar);
1656
 
        
1657
 
        return OPERATOR_FINISHED;
1658
 
}
1659
 
 
1660
 
void OUTLINER_OT_renderability_toggle(wmOperatorType *ot)
1661
 
{
1662
 
        /* identifiers */
1663
 
        ot->name= "Toggle Renderability";
1664
 
        ot->idname= "OUTLINER_OT_renderability_toggle";
1665
 
        ot->description= "Toggle the renderbility of selected items";
1666
 
        
1667
 
        /* callbacks */
1668
 
        ot->exec= outliner_toggle_renderability_exec;
1669
 
        ot->poll= ED_operator_outliner_active;
1670
 
        
1671
 
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1672
 
}
1673
 
 
1674
 
/* --- */
1675
 
 
1676
 
static int outliner_toggle_expanded_exec(bContext *C, wmOperator *op)
1677
 
{
1678
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
1679
 
        ARegion *ar= CTX_wm_region(C);
1680
 
        
1681
 
        if (outliner_has_one_flag(soops, &soops->tree, TSE_CLOSED, 1))
1682
 
                outliner_set_flag(soops, &soops->tree, TSE_CLOSED, 0);
1683
 
        else 
1684
 
                outliner_set_flag(soops, &soops->tree, TSE_CLOSED, 1);
1685
 
        
1686
 
        ED_region_tag_redraw(ar);
1687
 
        
1688
 
        return OPERATOR_FINISHED;
1689
 
}
1690
 
 
1691
 
void OUTLINER_OT_expanded_toggle(wmOperatorType *ot)
1692
 
{
1693
 
        /* identifiers */
1694
 
        ot->name= "Expand/Collapse All";
1695
 
        ot->idname= "OUTLINER_OT_expanded_toggle";
1696
 
        ot->description= "Expand/Collapse all items";
1697
 
        
1698
 
        /* callbacks */
1699
 
        ot->exec= outliner_toggle_expanded_exec;
1700
 
        ot->poll= ED_operator_outliner_active;
1701
 
        
1702
 
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1703
 
}
1704
 
 
1705
 
/* --- */
1706
 
 
1707
 
static int outliner_toggle_selected_exec(bContext *C, wmOperator *op)
1708
 
{
1709
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
1710
 
        ARegion *ar= CTX_wm_region(C);
1711
 
        
1712
 
        if (outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1))
1713
 
                outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0);
1714
 
        else 
1715
 
                outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 1);
1716
 
        
1717
 
        soops->storeflag |= SO_TREESTORE_REDRAW;
1718
 
        
1719
 
        ED_region_tag_redraw(ar);
1720
 
        
1721
 
        return OPERATOR_FINISHED;
1722
 
}
1723
 
 
1724
 
void OUTLINER_OT_selected_toggle(wmOperatorType *ot)
1725
 
{
1726
 
        /* identifiers */
1727
 
        ot->name= "Toggle Selected";
1728
 
        ot->idname= "OUTLINER_OT_selected_toggle";
1729
 
        ot->description= "Toggle the Outliner selection of items";
1730
 
        
1731
 
        /* callbacks */
1732
 
        ot->exec= outliner_toggle_selected_exec;
1733
 
        ot->poll= ED_operator_outliner_active;
1734
 
        
1735
 
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1736
 
}
1737
 
 
1738
 
/* --- */
1739
 
 
1740
 
/* helper function for Show/Hide one level operator */
1741
 
static void outliner_openclose_level(SpaceOops *soops, ListBase *lb, int curlevel, int level, int open)
1742
 
{
1743
 
        TreeElement *te;
1744
 
        TreeStoreElem *tselem;
1745
 
        
1746
 
        for(te= lb->first; te; te= te->next) {
1747
 
                tselem= TREESTORE(te);
1748
 
                
1749
 
                if(open) {
1750
 
                        if(curlevel<=level) tselem->flag &= ~TSE_CLOSED;
1751
 
                }
1752
 
                else {
1753
 
                        if(curlevel>=level) tselem->flag |= TSE_CLOSED;
1754
 
                }
1755
 
                
1756
 
                outliner_openclose_level(soops, &te->subtree, curlevel+1, level, open);
1757
 
        }
1758
 
}
1759
 
 
1760
 
static int outliner_one_level_exec(bContext *C, wmOperator *op)
1761
 
{
1762
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
1763
 
        ARegion *ar= CTX_wm_region(C);
1764
 
        int add= RNA_boolean_get(op->ptr, "open");
1765
 
        int level;
1766
 
        
1767
 
        level= outliner_has_one_flag(soops, &soops->tree, TSE_CLOSED, 1);
1768
 
        if(add==1) {
1769
 
                if(level) outliner_openclose_level(soops, &soops->tree, 1, level, 1);
1770
 
        }
1771
 
        else {
1772
 
                if(level==0) level= outliner_count_levels(soops, &soops->tree, 0);
1773
 
                if(level) outliner_openclose_level(soops, &soops->tree, 1, level-1, 0);
1774
 
        }
1775
 
        
1776
 
        ED_region_tag_redraw(ar);
1777
 
        
1778
 
        return OPERATOR_FINISHED;
1779
 
}
1780
 
 
1781
 
void OUTLINER_OT_show_one_level(wmOperatorType *ot)
1782
 
{
1783
 
        /* identifiers */
1784
 
        ot->name= "Show/Hide One Level";
1785
 
        ot->idname= "OUTLINER_OT_show_one_level";
1786
 
        
1787
 
        /* callbacks */
1788
 
        ot->exec= outliner_one_level_exec;
1789
 
        ot->poll= ED_operator_outliner_active;
1790
 
        
1791
 
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1792
 
        
1793
 
        /* properties */
1794
 
        RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep.");
1795
 
}
1796
 
 
1797
 
/* return 1 when levels were opened */
1798
 
static int outliner_open_back(SpaceOops *soops, TreeElement *te)
1799
 
{
1800
 
        TreeStoreElem *tselem;
1801
 
        int retval= 0;
1802
 
        
1803
 
        for (te= te->parent; te; te= te->parent) {
1804
 
                tselem= TREESTORE(te);
1805
 
                if (tselem->flag & TSE_CLOSED) { 
1806
 
                        tselem->flag &= ~TSE_CLOSED;
1807
 
                        retval= 1;
1808
 
                }
1809
 
        }
1810
 
        return retval;
1811
 
}
1812
 
 
1813
 
/* This is not used anywhere at the moment */
1814
 
#if 0
1815
 
static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *teFind, int *found)
1816
 
{
1817
 
        TreeElement *te;
1818
 
        TreeStoreElem *tselem;
1819
 
        
1820
 
        for (te= lb->first; te; te= te->next) {
1821
 
                /* check if this tree-element was the one we're seeking */
1822
 
                if (te == teFind) {
1823
 
                        *found= 1;
1824
 
                        return;
1825
 
                }
1826
 
                
1827
 
                /* try to see if sub-tree contains it then */
1828
 
                outliner_open_reveal(soops, &te->subtree, teFind, found);
1829
 
                if (*found) {
1830
 
                        tselem= TREESTORE(te);
1831
 
                        if (tselem->flag & TSE_CLOSED) 
1832
 
                                tselem->flag &= ~TSE_CLOSED;
1833
 
                        return;
1834
 
                }
1835
 
        }
1836
 
}
1837
 
#endif
1838
 
 
1839
 
// XXX just use View2D ops for this?
1840
 
void outliner_page_up_down(Scene *scene, ARegion *ar, SpaceOops *soops, int up)
1841
 
{
1842
 
        int dy= ar->v2d.mask.ymax-ar->v2d.mask.ymin;
1843
 
        
1844
 
        if(up == -1) dy= -dy;
1845
 
        ar->v2d.cur.ymin+= dy;
1846
 
        ar->v2d.cur.ymax+= dy;
1847
 
        
1848
 
        soops->storeflag |= SO_TREESTORE_REDRAW;
1849
 
}
1850
 
 
1851
 
/* **** do clicks on items ******* */
1852
 
 
1853
 
static int tree_element_active_renderlayer(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set)
1854
 
{
1855
 
        Scene *sce;
1856
 
        
1857
 
        /* paranoia check */
1858
 
        if(te->idcode!=ID_SCE)
1859
 
                return 0;
1860
 
        sce= (Scene *)tselem->id;
1861
 
        
1862
 
        if(set) {
1863
 
                sce->r.actlay= tselem->nr;
1864
 
                WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, sce);
1865
 
        }
1866
 
        else {
1867
 
                return sce->r.actlay==tselem->nr;
1868
 
        }
1869
 
        return 0;
1870
 
}
1871
 
 
1872
 
static void tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
1873
 
{
1874
 
        TreeStoreElem *tselem= TREESTORE(te);
1875
 
        Scene *sce;
1876
 
        Base *base;
1877
 
        Object *ob= NULL;
1878
 
        
1879
 
        /* if id is not object, we search back */
1880
 
        if(te->idcode==ID_OB) ob= (Object *)tselem->id;
1881
 
        else {
1882
 
                ob= (Object *)outliner_search_back(soops, te, ID_OB);
1883
 
                if(ob==OBACT) return;
1884
 
        }
1885
 
        if(ob==NULL) return;
1886
 
        
1887
 
        sce= (Scene *)outliner_search_back(soops, te, ID_SCE);
1888
 
        if(sce && scene != sce) {
1889
 
                ED_screen_set_scene(C, sce);
1890
 
        }
1891
 
        
1892
 
        /* find associated base in current scene */
1893
 
        for(base= FIRSTBASE; base; base= base->next) 
1894
 
                if(base->object==ob) break;
1895
 
        if(base) {
1896
 
                if(set==2) {
1897
 
                        /* swap select */
1898
 
                        if(base->flag & SELECT)
1899
 
                                ED_base_object_select(base, BA_DESELECT);
1900
 
                        else 
1901
 
                                ED_base_object_select(base, BA_SELECT);
1902
 
                }
1903
 
                else {
1904
 
                        Base *b;
1905
 
                        /* deleselect all */
1906
 
                        for(b= FIRSTBASE; b; b= b->next) {
1907
 
                                b->flag &= ~SELECT;
1908
 
                                b->object->flag= b->flag;
1909
 
                        }
1910
 
                        ED_base_object_select(base, BA_SELECT);
1911
 
                }
1912
 
                if(C)
1913
 
                        ED_base_object_activate(C, base); /* adds notifier */
1914
 
        }
1915
 
        
1916
 
        if(ob!=scene->obedit) 
1917
 
                ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO);
1918
 
        
1919
 
        WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
1920
 
 
1921
 
}
1922
 
 
1923
 
static int tree_element_active_material(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
1924
 
{
1925
 
        TreeElement *tes;
1926
 
        Object *ob;
1927
 
        
1928
 
        /* we search for the object parent */
1929
 
        ob= (Object *)outliner_search_back(soops, te, ID_OB);
1930
 
        // note: ob->matbits can be NULL when a local object points to a library mesh.
1931
 
        if(ob==NULL || ob!=OBACT || ob->matbits==NULL) return 0;        // just paranoia
1932
 
        
1933
 
        /* searching in ob mat array? */
1934
 
        tes= te->parent;
1935
 
        if(tes->idcode==ID_OB) {
1936
 
                if(set) {
1937
 
                        ob->actcol= te->index+1;
1938
 
                        ob->matbits[te->index]= 1;      // make ob material active too
1939
 
                        ob->colbits |= (1<<te->index);
1940
 
                }
1941
 
                else {
1942
 
                        if(ob->actcol == te->index+1) 
1943
 
                                if(ob->matbits[te->index]) return 1;
1944
 
                }
1945
 
        }
1946
 
        /* or we search for obdata material */
1947
 
        else {
1948
 
                if(set) {
1949
 
                        ob->actcol= te->index+1;
1950
 
                        ob->matbits[te->index]= 0;      // make obdata material active too
1951
 
                        ob->colbits &= ~(1<<te->index);
1952
 
                }
1953
 
                else {
1954
 
                        if(ob->actcol == te->index+1)
1955
 
                                if(ob->matbits[te->index]==0) return 1;
1956
 
                }
1957
 
        }
1958
 
        if(set) {
1959
 
                WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, NULL);
1960
 
        }
1961
 
        return 0;
1962
 
}
1963
 
 
1964
 
static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
1965
 
{
1966
 
        TreeElement *tep;
1967
 
        TreeStoreElem *tselem, *tselemp;
1968
 
        Object *ob=OBACT;
1969
 
        SpaceButs *sbuts=NULL;
1970
 
        
1971
 
        if(ob==NULL) return 0; // no active object
1972
 
        
1973
 
        tselem= TREESTORE(te);
1974
 
        
1975
 
        /* find buttons area (note, this is undefined really still, needs recode in blender) */
1976
 
        /* XXX removed finding sbuts */
1977
 
        
1978
 
        /* where is texture linked to? */
1979
 
        tep= te->parent;
1980
 
        tselemp= TREESTORE(tep);
1981
 
        
1982
 
        if(tep->idcode==ID_WO) {
1983
 
                World *wrld= (World *)tselemp->id;
1984
 
 
1985
 
                if(set) {
1986
 
                        if(sbuts) {
1987
 
                                // XXX sbuts->tabo= TAB_SHADING_TEX;    // hack from header_buttonswin.c
1988
 
                                // XXX sbuts->texfrom= 1;
1989
 
                        }
1990
 
// XXX                  extern_set_butspace(F6KEY, 0);  // force shading buttons texture
1991
 
                        wrld->texact= te->index;
1992
 
                }
1993
 
                else if(tselemp->id == (ID *)(scene->world)) {
1994
 
                        if(wrld->texact==te->index) return 1;
1995
 
                }
1996
 
        }
1997
 
        else if(tep->idcode==ID_LA) {
1998
 
                Lamp *la= (Lamp *)tselemp->id;
1999
 
                if(set) {
2000
 
                        if(sbuts) {
2001
 
                                // XXX sbuts->tabo= TAB_SHADING_TEX;    // hack from header_buttonswin.c
2002
 
                                // XXX sbuts->texfrom= 2;
2003
 
                        }
2004
 
// XXX                  extern_set_butspace(F6KEY, 0);  // force shading buttons texture
2005
 
                        la->texact= te->index;
2006
 
                }
2007
 
                else {
2008
 
                        if(tselemp->id == ob->data) {
2009
 
                                if(la->texact==te->index) return 1;
2010
 
                        }
2011
 
                }
2012
 
        }
2013
 
        else if(tep->idcode==ID_MA) {
2014
 
                Material *ma= (Material *)tselemp->id;
2015
 
                if(set) {
2016
 
                        if(sbuts) {
2017
 
                                //sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c
2018
 
                                // XXX sbuts->texfrom= 0;
2019
 
                        }
2020
 
// XXX                  extern_set_butspace(F6KEY, 0);  // force shading buttons texture
2021
 
                        ma->texact= (char)te->index;
2022
 
                        
2023
 
                        /* also set active material */
2024
 
                        ob->actcol= tep->index+1;
2025
 
                }
2026
 
                else if(tep->flag & TE_ACTIVE) {        // this is active material
2027
 
                        if(ma->texact==te->index) return 1;
2028
 
                }
2029
 
        }
2030
 
        
2031
 
        return 0;
2032
 
}
2033
 
 
2034
 
 
2035
 
static int tree_element_active_lamp(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
2036
 
{
2037
 
        Object *ob;
2038
 
        
2039
 
        /* we search for the object parent */
2040
 
        ob= (Object *)outliner_search_back(soops, te, ID_OB);
2041
 
        if(ob==NULL || ob!=OBACT) return 0;     // just paranoia
2042
 
        
2043
 
        if(set) {
2044
 
// XXX          extern_set_butspace(F5KEY, 0);
2045
 
        }
2046
 
        else return 1;
2047
 
        
2048
 
        return 0;
2049
 
}
2050
 
 
2051
 
static int tree_element_active_world(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
2052
 
{
2053
 
        TreeElement *tep;
2054
 
        TreeStoreElem *tselem=NULL;
2055
 
        Scene *sce=NULL;
2056
 
        
2057
 
        tep= te->parent;
2058
 
        if(tep) {
2059
 
                tselem= TREESTORE(tep);
2060
 
                sce= (Scene *)tselem->id;
2061
 
        }
2062
 
        
2063
 
        if(set) {       // make new scene active
2064
 
                if(sce && scene != sce) {
2065
 
                        ED_screen_set_scene(C, sce);
2066
 
                }
2067
 
        }
2068
 
        
2069
 
        if(tep==NULL || tselem->id == (ID *)scene) {
2070
 
                if(set) {
2071
 
// XXX                  extern_set_butspace(F8KEY, 0);
2072
 
                }
2073
 
                else {
2074
 
                        return 1;
2075
 
                }
2076
 
        }
2077
 
        return 0;
2078
 
}
2079
 
 
2080
 
static int tree_element_active_defgroup(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
2081
 
{
2082
 
        Object *ob;
2083
 
        
2084
 
        /* id in tselem is object */
2085
 
        ob= (Object *)tselem->id;
2086
 
        if(set) {
2087
 
                ob->actdef= te->index+1;
2088
 
                DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
2089
 
                WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
2090
 
        }
2091
 
        else {
2092
 
                if(ob==OBACT)
2093
 
                        if(ob->actdef== te->index+1) return 1;
2094
 
        }
2095
 
        return 0;
2096
 
}
2097
 
 
2098
 
static int tree_element_active_posegroup(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
2099
 
{
2100
 
        Object *ob= (Object *)tselem->id;
2101
 
        
2102
 
        if(set) {
2103
 
                if (ob->pose) {
2104
 
                        ob->pose->active_group= te->index+1;
2105
 
                        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2106
 
                }
2107
 
        }
2108
 
        else {
2109
 
                if(ob==OBACT && ob->pose) {
2110
 
                        if (ob->pose->active_group== te->index+1) return 1;
2111
 
                }
2112
 
        }
2113
 
        return 0;
2114
 
}
2115
 
 
2116
 
static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
2117
 
{
2118
 
        Object *ob= (Object *)tselem->id;
2119
 
        bArmature *arm= ob->data;
2120
 
        bPoseChannel *pchan= te->directdata;
2121
 
        
2122
 
        if(set) {
2123
 
                if(!(pchan->bone->flag & BONE_HIDDEN_P)) {
2124
 
                        
2125
 
                        if(set==2) ED_pose_deselectall(ob, 2, 0);       // 2 = clear active tag
2126
 
                        else ED_pose_deselectall(ob, 0, 0);     // 0 = deselect 
2127
 
                        
2128
 
                        if(set==2 && (pchan->bone->flag & BONE_SELECTED)) {
2129
 
                                pchan->bone->flag &= ~BONE_SELECTED;
2130
 
                                if(arm->act_bone==pchan->bone)
2131
 
                                        arm->act_bone= NULL;
2132
 
                        } else {
2133
 
                                pchan->bone->flag |= BONE_SELECTED;
2134
 
                                arm->act_bone= pchan->bone;
2135
 
                        }
2136
 
                        
2137
 
                        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, ob);
2138
 
 
2139
 
                }
2140
 
        }
2141
 
        else {
2142
 
                if(ob==OBACT && ob->pose) {
2143
 
                        if (pchan->bone->flag & BONE_SELECTED) return 1;
2144
 
                }
2145
 
        }
2146
 
        return 0;
2147
 
}
2148
 
 
2149
 
static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
2150
 
{
2151
 
        bArmature *arm= (bArmature *)tselem->id;
2152
 
        Bone *bone= te->directdata;
2153
 
        
2154
 
        if(set) {
2155
 
                if(!(bone->flag & BONE_HIDDEN_P)) {
2156
 
                        if(set==2) ED_pose_deselectall(OBACT, 2, 0);    // 2 is clear active tag
2157
 
                        else ED_pose_deselectall(OBACT, 0, 0);
2158
 
                        
2159
 
                        if(set==2 && (bone->flag & BONE_SELECTED)) {
2160
 
                                bone->flag &= ~BONE_SELECTED;
2161
 
                                if(arm->act_bone==bone)
2162
 
                                        arm->act_bone= NULL;
2163
 
                        } else {
2164
 
                                bone->flag |= BONE_SELECTED;
2165
 
                                arm->act_bone= bone;
2166
 
                        }
2167
 
                        
2168
 
                        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, OBACT);
2169
 
                }
2170
 
        }
2171
 
        else {
2172
 
                Object *ob= OBACT;
2173
 
                
2174
 
                if(ob && ob->data==arm) {
2175
 
                        if (bone->flag & BONE_SELECTED) return 1;
2176
 
                }
2177
 
        }
2178
 
        return 0;
2179
 
}
2180
 
 
2181
 
 
2182
 
/* ebones only draw in editmode armature */
2183
 
static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
2184
 
{
2185
 
        EditBone *ebone= te->directdata;
2186
 
        
2187
 
        if(set) {
2188
 
                if(!(ebone->flag & BONE_HIDDEN_A)) {
2189
 
                        bArmature *arm= scene->obedit->data;
2190
 
                        if(set==2) ED_armature_deselectall(scene->obedit, 2, 0);        // only clear active tag
2191
 
                        else ED_armature_deselectall(scene->obedit, 0, 0);      // deselect
2192
 
 
2193
 
                        ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL;
2194
 
                        arm->act_edbone= ebone;
2195
 
 
2196
 
                        // flush to parent?
2197
 
                        if(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag |= BONE_TIPSEL;
2198
 
                        
2199
 
                        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, scene->obedit);
2200
 
                }
2201
 
        }
2202
 
        else {
2203
 
                if (ebone->flag & BONE_SELECTED) return 1;
2204
 
        }
2205
 
        return 0;
2206
 
}
2207
 
 
2208
 
static int tree_element_active_modifier(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set)
2209
 
{
2210
 
        if(set) {
2211
 
                Object *ob= (Object *)tselem->id;
2212
 
                
2213
 
                WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
2214
 
 
2215
 
// XXX          extern_set_butspace(F9KEY, 0);
2216
 
        }
2217
 
        
2218
 
        return 0;
2219
 
}
2220
 
 
2221
 
static int tree_element_active_psys(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
2222
 
{
2223
 
        if(set) {
2224
 
                Object *ob= (Object *)tselem->id;
2225
 
                
2226
 
                WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
2227
 
                
2228
 
// XXX          extern_set_butspace(F7KEY, 0);
2229
 
        }
2230
 
        
2231
 
        return 0;
2232
 
}
2233
 
 
2234
 
static int tree_element_active_constraint(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set)
2235
 
{
2236
 
        if(set) {
2237
 
                Object *ob= (Object *)tselem->id;
2238
 
                
2239
 
                WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
2240
 
// XXX          extern_set_butspace(F7KEY, 0);
2241
 
        }
2242
 
        
2243
 
        return 0;
2244
 
}
2245
 
 
2246
 
static int tree_element_active_text(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
2247
 
{
2248
 
        // XXX removed
2249
 
        return 0;
2250
 
}
2251
 
 
2252
 
/* generic call for ID data check or make/check active in UI */
2253
 
static int tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
2254
 
{
2255
 
 
2256
 
        switch(te->idcode) {
2257
 
                case ID_MA:
2258
 
                        return tree_element_active_material(C, scene, soops, te, set);
2259
 
                case ID_WO:
2260
 
                        return tree_element_active_world(C, scene, soops, te, set);
2261
 
                case ID_LA:
2262
 
                        return tree_element_active_lamp(C, scene, soops, te, set);
2263
 
                case ID_TE:
2264
 
                        return tree_element_active_texture(C, scene, soops, te, set);
2265
 
                case ID_TXT:
2266
 
                        return tree_element_active_text(C, scene, soops, te, set);
2267
 
        }
2268
 
        return 0;
2269
 
}
2270
 
 
2271
 
static int tree_element_active_pose(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
2272
 
{
2273
 
        Object *ob= (Object *)tselem->id;
2274
 
        Base *base= object_in_scene(ob, scene);
2275
 
        
2276
 
        if(set) {
2277
 
                if(scene->obedit) 
2278
 
                        ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO);
2279
 
                
2280
 
                if(ob->mode & OB_MODE_POSE) 
2281
 
                        ED_armature_exit_posemode(C, base);
2282
 
                else 
2283
 
                        ED_armature_enter_posemode(C, base);
2284
 
        }
2285
 
        else {
2286
 
                if(ob->mode & OB_MODE_POSE) return 1;
2287
 
        }
2288
 
        return 0;
2289
 
}
2290
 
 
2291
 
static int tree_element_active_sequence(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set)
2292
 
{
2293
 
        Sequence *seq= (Sequence*) te->directdata;
2294
 
 
2295
 
        if(set) {
2296
 
// XXX          select_single_seq(seq, 1);
2297
 
        }
2298
 
        else {
2299
 
                if(seq->flag & SELECT)
2300
 
                        return(1);
2301
 
        }
2302
 
        return(0);
2303
 
}
2304
 
 
2305
 
static int tree_element_active_sequence_dup(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
2306
 
{
2307
 
        Sequence *seq, *p;
2308
 
        Editing *ed= seq_give_editing(scene, FALSE);
2309
 
 
2310
 
        seq= (Sequence*)te->directdata;
2311
 
        if(set==0) {
2312
 
                if(seq->flag & SELECT)
2313
 
                        return(1);
2314
 
                return(0);
2315
 
        }
2316
 
 
2317
 
// XXX  select_single_seq(seq, 1);
2318
 
        p= ed->seqbasep->first;
2319
 
        while(p) {
2320
 
                if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
2321
 
                        p= p->next;
2322
 
                        continue;
2323
 
                }
2324
 
 
2325
 
//              if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
2326
 
// XXX                  select_single_seq(p, 0);
2327
 
                p= p->next;
2328
 
        }
2329
 
        return(0);
2330
 
}
2331
 
 
2332
 
static int tree_element_active_keymap_item(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set)
2333
 
{
2334
 
        wmKeyMapItem *kmi= te->directdata;
2335
 
        
2336
 
        if(set==0) {
2337
 
                if(kmi->flag & KMI_INACTIVE) return 0;
2338
 
                return 1;
2339
 
        }
2340
 
        else {
2341
 
                kmi->flag ^= KMI_INACTIVE;
2342
 
        }
2343
 
        return 0;
2344
 
}
2345
 
 
2346
 
 
2347
 
/* generic call for non-id data to make/check active in UI */
2348
 
/* Context can be NULL when set==0 */
2349
 
static int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, int set)
2350
 
{
2351
 
        switch(tselem->type) {
2352
 
                case TSE_DEFGROUP:
2353
 
                        return tree_element_active_defgroup(C, scene, te, tselem, set);
2354
 
                case TSE_BONE:
2355
 
                        return tree_element_active_bone(C, scene, te, tselem, set);
2356
 
                case TSE_EBONE:
2357
 
                        return tree_element_active_ebone(C, scene, te, tselem, set);
2358
 
                case TSE_MODIFIER:
2359
 
                        return tree_element_active_modifier(C, te, tselem, set);
2360
 
                case TSE_LINKED_OB:
2361
 
                        if(set) tree_element_set_active_object(C, scene, soops, te, set);
2362
 
                        else if(tselem->id==(ID *)OBACT) return 1;
2363
 
                        break;
2364
 
                case TSE_LINKED_PSYS:
2365
 
                        return tree_element_active_psys(C, scene, te, tselem, set);
2366
 
                case TSE_POSE_BASE:
2367
 
                        return tree_element_active_pose(C, scene, te, tselem, set);
2368
 
                case TSE_POSE_CHANNEL:
2369
 
                        return tree_element_active_posechannel(C, scene, te, tselem, set);
2370
 
                case TSE_CONSTRAINT:
2371
 
                        return tree_element_active_constraint(C, te, tselem, set);
2372
 
                case TSE_R_LAYER:
2373
 
                        return tree_element_active_renderlayer(C, te, tselem, set);
2374
 
                case TSE_POSEGRP:
2375
 
                        return tree_element_active_posegroup(C, scene, te, tselem, set);
2376
 
                case TSE_SEQUENCE:
2377
 
                        return tree_element_active_sequence(C, te, tselem, set);
2378
 
                case TSE_SEQUENCE_DUP:
2379
 
                        return tree_element_active_sequence_dup(C, scene, te, tselem, set);
2380
 
                case TSE_KEYMAP_ITEM:
2381
 
                        return tree_element_active_keymap_item(C, te, tselem, set);
2382
 
                        
2383
 
        }
2384
 
        return 0;
2385
 
}
2386
 
 
2387
 
static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int extend, float *mval)
2388
 
{
2389
 
        
2390
 
        if(mval[1]>te->ys && mval[1]<te->ys+OL_H) {
2391
 
                TreeStoreElem *tselem= TREESTORE(te);
2392
 
                int openclose= 0;
2393
 
 
2394
 
                /* open close icon */
2395
 
                if((te->flag & TE_ICONROW)==0) {                                // hidden icon, no open/close
2396
 
                        if( mval[0]>te->xs && mval[0]<te->xs+OL_X) 
2397
 
                                openclose= 1;
2398
 
                }
2399
 
 
2400
 
                if(openclose) {
2401
 
                        /* all below close/open? */
2402
 
                        if(extend) {
2403
 
                                tselem->flag &= ~TSE_CLOSED;
2404
 
                                outliner_set_flag(soops, &te->subtree, TSE_CLOSED, !outliner_has_one_flag(soops, &te->subtree, TSE_CLOSED, 1));
2405
 
                        }
2406
 
                        else {
2407
 
                                if(tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
2408
 
                                else tselem->flag |= TSE_CLOSED;
2409
 
                                
2410
 
                        }
2411
 
 
2412
 
                        return 1;
2413
 
                }
2414
 
                /* name and first icon */
2415
 
                else if(mval[0]>te->xs && mval[0]<te->xend) {
2416
 
                        
2417
 
                        /* always makes active object */
2418
 
                        if(tselem->type!=TSE_SEQUENCE && tselem->type!=TSE_SEQ_STRIP && tselem->type!=TSE_SEQUENCE_DUP)
2419
 
                                tree_element_set_active_object(C, scene, soops, te, 1 + (extend!=0 && tselem->type==0));
2420
 
                        
2421
 
                        if(tselem->type==0) { // the lib blocks
2422
 
                                /* editmode? */
2423
 
                                if(te->idcode==ID_SCE) {
2424
 
                                        if(scene!=(Scene *)tselem->id) {
2425
 
                                                ED_screen_set_scene(C, (Scene *)tselem->id);
2426
 
                                        }
2427
 
                                }
2428
 
                                else if(te->idcode==ID_GR) {
2429
 
                                        Group *gr= (Group *)tselem->id;
2430
 
                                        GroupObject *gob;
2431
 
 
2432
 
                                        if(extend) {
2433
 
                                                int sel= BA_SELECT;
2434
 
                                                for(gob= gr->gobject.first; gob; gob= gob->next) {
2435
 
                                                        if(gob->ob->flag & SELECT) {
2436
 
                                                                sel= BA_DESELECT;
2437
 
                                                                break;
2438
 
                                                        }
2439
 
                                                }
2440
 
 
2441
 
                                                for(gob= gr->gobject.first; gob; gob= gob->next) {
2442
 
                                                        ED_base_object_select(object_in_scene(gob->ob, scene), sel);
2443
 
                                                }
2444
 
                                        }
2445
 
                                        else {
2446
 
                                                scene_deselect_all(scene);
2447
 
 
2448
 
                                                for(gob= gr->gobject.first; gob; gob= gob->next) {
2449
 
                                                        if((gob->ob->flag & SELECT) == 0)
2450
 
                                                                ED_base_object_select(object_in_scene(gob->ob, scene), BA_SELECT);
2451
 
                                                }
2452
 
                                        }
2453
 
 
2454
 
                                        WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
2455
 
                                }
2456
 
                                else if(ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
2457
 
                                        Object *obedit= CTX_data_edit_object(C);
2458
 
                                        if(obedit) 
2459
 
                                                ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO);
2460
 
                                        else {
2461
 
                                                Object *ob= CTX_data_active_object(C);
2462
 
 
2463
 
                                                /* Don't allow edit mode if the object is hide!
2464
 
                                                 * check the bug #22153 and #21609
2465
 
                                                 */
2466
 
                                                if (ob && (!(ob->restrictflag & OB_RESTRICT_VIEW)))
2467
 
                                                        ED_object_enter_editmode(C, EM_WAITCURSOR);
2468
 
                                                // XXX extern_set_butspace(F9KEY, 0);
2469
 
                                        }
2470
 
                                } else {        // rest of types
2471
 
                                        tree_element_active(C, scene, soops, te, 1);
2472
 
                                }
2473
 
                                
2474
 
                        }
2475
 
                        else tree_element_type_active(C, scene, soops, te, tselem, 1+(extend!=0));
2476
 
 
2477
 
                        return 1;
2478
 
                }
2479
 
        }
2480
 
        
2481
 
        for(te= te->subtree.first; te; te= te->next) {
2482
 
                if(do_outliner_item_activate(C, scene, ar, soops, te, extend, mval)) return 1;
2483
 
        }
2484
 
        return 0;
2485
 
}
2486
 
 
2487
 
/* event can enterkey, then it opens/closes */
2488
 
static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event)
2489
 
{
2490
 
        Scene *scene= CTX_data_scene(C);
2491
 
        ARegion *ar= CTX_wm_region(C);
2492
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
2493
 
        TreeElement *te;
2494
 
        float fmval[2];
2495
 
        int extend= RNA_boolean_get(op->ptr, "extend");
2496
 
        
2497
 
        UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1);
2498
 
        
2499
 
        for(te= soops->tree.first; te; te= te->next) {
2500
 
                if(do_outliner_item_activate(C, scene, ar, soops, te, extend, fmval)) break;
2501
 
        }
2502
 
        
2503
 
        if(te) {
2504
 
                ED_undo_push(C, "Outliner click event");
2505
 
        }
2506
 
        else {
2507
 
                short selecting= -1;
2508
 
                int row;
2509
 
                
2510
 
                /* get row number - 100 here is just a dummy value since we don't need the column */
2511
 
                UI_view2d_listview_view_to_cell(&ar->v2d, 1000, OL_H, 0.0f, 0.0f, 
2512
 
                                                fmval[0], fmval[1], NULL, &row);
2513
 
                
2514
 
                /* select relevant row */
2515
 
                outliner_select(soops, &soops->tree, &row, &selecting);
2516
 
                
2517
 
                soops->storeflag |= SO_TREESTORE_REDRAW;
2518
 
                
2519
 
                ED_undo_push(C, "Outliner selection event");
2520
 
        }
2521
 
        
2522
 
        ED_region_tag_redraw(ar);
2523
 
 
2524
 
        return OPERATOR_FINISHED;
2525
 
}
2526
 
 
2527
 
void OUTLINER_OT_item_activate(wmOperatorType *ot)
2528
 
{
2529
 
        ot->name= "Activate Item";
2530
 
        ot->idname= "OUTLINER_OT_item_activate";
2531
 
        
2532
 
        ot->invoke= outliner_item_activate;
2533
 
        
2534
 
        ot->poll= ED_operator_outliner_active;
2535
 
        
2536
 
        RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection for activation.");
2537
 
}
2538
 
 
2539
 
/* *********** */
2540
 
 
2541
 
static int do_outliner_item_openclose(bContext *C, SpaceOops *soops, TreeElement *te, int all, float *mval)
2542
 
{
2543
 
        
2544
 
        if(mval[1]>te->ys && mval[1]<te->ys+OL_H) {
2545
 
                TreeStoreElem *tselem= TREESTORE(te);
2546
 
 
2547
 
                /* all below close/open? */
2548
 
                if(all) {
2549
 
                        tselem->flag &= ~TSE_CLOSED;
2550
 
                        outliner_set_flag(soops, &te->subtree, TSE_CLOSED, !outliner_has_one_flag(soops, &te->subtree, TSE_CLOSED, 1));
2551
 
                }
2552
 
                else {
2553
 
                        if(tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
2554
 
                        else tselem->flag |= TSE_CLOSED;
2555
 
                }
2556
 
 
2557
 
                return 1;
2558
 
        }
2559
 
        
2560
 
        for(te= te->subtree.first; te; te= te->next) {
2561
 
                if(do_outliner_item_openclose(C, soops, te, all, mval)) 
2562
 
                        return 1;
2563
 
        }
2564
 
        return 0;
2565
 
        
2566
 
}
2567
 
 
2568
 
/* event can enterkey, then it opens/closes */
2569
 
static int outliner_item_openclose(bContext *C, wmOperator *op, wmEvent *event)
2570
 
{
2571
 
        ARegion *ar= CTX_wm_region(C);
2572
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
2573
 
        TreeElement *te;
2574
 
        float fmval[2];
2575
 
        int all= RNA_boolean_get(op->ptr, "all");
2576
 
        
2577
 
        UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1);
2578
 
        
2579
 
        for(te= soops->tree.first; te; te= te->next) {
2580
 
                if(do_outliner_item_openclose(C, soops, te, all, fmval)) 
2581
 
                        break;
2582
 
        }
2583
 
 
2584
 
        ED_region_tag_redraw(ar);
2585
 
        
2586
 
        return OPERATOR_FINISHED;
2587
 
}
2588
 
 
2589
 
void OUTLINER_OT_item_openclose(wmOperatorType *ot)
2590
 
{
2591
 
        ot->name= "Open/Close Item";
2592
 
        ot->idname= "OUTLINER_OT_item_openclose";
2593
 
        
2594
 
        ot->invoke= outliner_item_openclose;
2595
 
        
2596
 
        ot->poll= ED_operator_outliner_active;
2597
 
        
2598
 
        RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items.");
2599
 
 
2600
 
}
2601
 
 
2602
 
 
2603
 
/* ********************************************** */
2604
 
 
2605
 
static int do_outliner_item_rename(bContext *C, ARegion *ar, SpaceOops *soops, TreeElement *te, float *mval)
2606
 
{
2607
 
        
2608
 
        if(mval[1]>te->ys && mval[1]<te->ys+OL_H) {
2609
 
                TreeStoreElem *tselem= TREESTORE(te);
2610
 
                
2611
 
                /* name and first icon */
2612
 
                if(mval[0]>te->xs && mval[0]<te->xend) {
2613
 
                        
2614
 
                        /* can't rename rna datablocks entries */
2615
 
                        if(ELEM3(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))
2616
 
                           ;
2617
 
                        else if(ELEM10(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE, TSE_SCRIPT_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS)) 
2618
 
                                        error("Cannot edit builtin name");
2619
 
                        else if(ELEM3(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP))
2620
 
                                error("Cannot edit sequence name");
2621
 
                        else if(tselem->id->lib) {
2622
 
                                // XXX                                          error_libdata();
2623
 
                        } else if(te->idcode == ID_LI && te->parent) {
2624
 
                                error("Cannot edit the path of an indirectly linked library");
2625
 
                        } else {
2626
 
                                tselem->flag |= TSE_TEXTBUT;
2627
 
                                ED_region_tag_redraw(ar);
2628
 
                        }
2629
 
                }
2630
 
                return 1;
2631
 
        }
2632
 
        
2633
 
        for(te= te->subtree.first; te; te= te->next) {
2634
 
                if(do_outliner_item_rename(C, ar, soops, te, mval)) return 1;
2635
 
        }
2636
 
        return 0;
2637
 
}
2638
 
 
2639
 
static int outliner_item_rename(bContext *C, wmOperator *op, wmEvent *event)
2640
 
{
2641
 
        ARegion *ar= CTX_wm_region(C);
2642
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
2643
 
        TreeElement *te;
2644
 
        float fmval[2];
2645
 
        
2646
 
        UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1);
2647
 
        
2648
 
        for(te= soops->tree.first; te; te= te->next) {
2649
 
                if(do_outliner_item_rename(C, ar, soops, te, fmval)) break;
2650
 
        }
2651
 
        
2652
 
        return OPERATOR_FINISHED;
2653
 
}
2654
 
 
2655
 
 
2656
 
void OUTLINER_OT_item_rename(wmOperatorType *ot)
2657
 
{
2658
 
        ot->name= "Rename Item";
2659
 
        ot->idname= "OUTLINER_OT_item_rename";
2660
 
        
2661
 
        ot->invoke= outliner_item_rename;
2662
 
        
2663
 
        ot->poll= ED_operator_outliner_active;
2664
 
}
2665
 
 
2666
 
 
2667
 
 
2668
 
/* recursive helper for function below */
2669
 
static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te, int startx, int *starty)
2670
 
{
2671
 
        TreeStoreElem *tselem= TREESTORE(te);
2672
 
        
2673
 
        /* store coord and continue, we need coordinates for elements outside view too */
2674
 
        te->xs= (float)startx;
2675
 
        te->ys= (float)(*starty);
2676
 
        *starty-= OL_H;
2677
 
        
2678
 
        if((tselem->flag & TSE_CLOSED)==0) {
2679
 
                TreeElement *ten;
2680
 
                for(ten= te->subtree.first; ten; ten= ten->next) {
2681
 
                        outliner_set_coordinates_element(soops, ten, startx+OL_X, starty);
2682
 
                }
2683
 
        }
2684
 
        
2685
 
}
2686
 
 
2687
 
/* to retrieve coordinates with redrawing the entire tree */
2688
 
static void outliner_set_coordinates(ARegion *ar, SpaceOops *soops)
2689
 
{
2690
 
        TreeElement *te;
2691
 
        int starty= (int)(ar->v2d.tot.ymax)-OL_H;
2692
 
        int startx= 0;
2693
 
        
2694
 
        for(te= soops->tree.first; te; te= te->next) {
2695
 
                outliner_set_coordinates_element(soops, te, startx, &starty);
2696
 
        }
2697
 
}
2698
 
 
2699
 
static TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, ID *id)
2700
 
{
2701
 
        TreeElement *te, *tes;
2702
 
        TreeStoreElem *tselem;
2703
 
        
2704
 
        for(te= lb->first; te; te= te->next) {
2705
 
                tselem= TREESTORE(te);
2706
 
                if(tselem->type==0) {
2707
 
                        if(tselem->id==id) return te;
2708
 
                        /* only deeper on scene or object */
2709
 
                        if( te->idcode==ID_OB || te->idcode==ID_SCE) { 
2710
 
                                tes= outliner_find_id(soops, &te->subtree, id);
2711
 
                                if(tes) return tes;
2712
 
                        }
2713
 
                }
2714
 
        }
2715
 
        return NULL;
2716
 
}
2717
 
 
2718
 
static int outliner_show_active_exec(bContext *C, wmOperator *op)
2719
 
{
2720
 
        SpaceOops *so= CTX_wm_space_outliner(C);
2721
 
        Scene *scene= CTX_data_scene(C);
2722
 
        ARegion *ar= CTX_wm_region(C);
2723
 
        View2D *v2d= &ar->v2d;
2724
 
        
2725
 
        TreeElement *te;
2726
 
        int xdelta, ytop;
2727
 
        
2728
 
        // TODO: make this get this info from context instead...
2729
 
        if (OBACT == NULL) 
2730
 
                return OPERATOR_CANCELLED;
2731
 
        
2732
 
        te= outliner_find_id(so, &so->tree, (ID *)OBACT);
2733
 
        if (te) {
2734
 
                /* make te->ys center of view */
2735
 
                ytop= (int)(te->ys + (v2d->mask.ymax - v2d->mask.ymin)/2);
2736
 
                if (ytop>0) ytop= 0;
2737
 
                
2738
 
                v2d->cur.ymax= (float)ytop;
2739
 
                v2d->cur.ymin= (float)(ytop-(v2d->mask.ymax - v2d->mask.ymin));
2740
 
                
2741
 
                /* make te->xs ==> te->xend center of view */
2742
 
                xdelta = (int)(te->xs - v2d->cur.xmin);
2743
 
                v2d->cur.xmin += xdelta;
2744
 
                v2d->cur.xmax += xdelta;
2745
 
                
2746
 
                so->storeflag |= SO_TREESTORE_REDRAW;
2747
 
        }
2748
 
        
2749
 
        ED_region_tag_redraw(ar);
2750
 
        
2751
 
        return OPERATOR_FINISHED;
2752
 
}
2753
 
 
2754
 
void OUTLINER_OT_show_active(wmOperatorType *ot)
2755
 
{
2756
 
        /* identifiers */
2757
 
        ot->name= "Show Active";
2758
 
        ot->idname= "OUTLINER_OT_show_active";
2759
 
        ot->description= "Adjust the view so that the active Object is shown centered";
2760
 
        
2761
 
        /* callbacks */
2762
 
        ot->exec= outliner_show_active_exec;
2763
 
        ot->poll= ED_operator_outliner_active;
2764
 
        
2765
 
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2766
 
}
2767
 
 
2768
 
/* find next element that has this name */
2769
 
static TreeElement *outliner_find_named(SpaceOops *soops, ListBase *lb, char *name, int flags, TreeElement *prev, int *prevFound)
2770
 
{
2771
 
        TreeElement *te, *tes;
2772
 
        
2773
 
        for (te= lb->first; te; te= te->next) {
2774
 
                int found = outliner_filter_has_name(te, name, flags);
2775
 
                
2776
 
                if(found) {
2777
 
                        /* name is right, but is element the previous one? */
2778
 
                        if (prev) {
2779
 
                                if ((te != prev) && (*prevFound)) 
2780
 
                                        return te;
2781
 
                                if (te == prev) {
2782
 
                                        *prevFound = 1;
2783
 
                                }
2784
 
                        }
2785
 
                        else
2786
 
                                return te;
2787
 
                }
2788
 
                
2789
 
                tes= outliner_find_named(soops, &te->subtree, name, flags, prev, prevFound);
2790
 
                if(tes) return tes;
2791
 
        }
2792
 
 
2793
 
        /* nothing valid found */
2794
 
        return NULL;
2795
 
}
2796
 
 
2797
 
/* tse is not in the treestore, we use its contents to find a match */
2798
 
static TreeElement *outliner_find_tse(SpaceOops *soops, TreeStoreElem *tse)
2799
 
{
2800
 
        TreeStore *ts= soops->treestore;
2801
 
        TreeStoreElem *tselem;
2802
 
        int a;
2803
 
        
2804
 
        if(tse->id==NULL) return NULL;
2805
 
        
2806
 
        /* check if 'tse' is in treestore */
2807
 
        tselem= ts->data;
2808
 
        for(a=0; a<ts->usedelem; a++, tselem++) {
2809
 
                if((tse->type==0 && tselem->type==0) || (tselem->type==tse->type && tselem->nr==tse->nr)) {
2810
 
                        if(tselem->id==tse->id) {
2811
 
                                break;
2812
 
                        }
2813
 
                }
2814
 
        }
2815
 
        if(tselem) 
2816
 
                return outliner_find_tree_element(&soops->tree, a);
2817
 
        
2818
 
        return NULL;
2819
 
}
2820
 
 
2821
 
 
2822
 
/* Called to find an item based on name.
2823
 
 */
2824
 
void outliner_find_panel(Scene *scene, ARegion *ar, SpaceOops *soops, int again, int flags) 
2825
 
{
2826
 
        TreeElement *te= NULL;
2827
 
        TreeElement *last_find;
2828
 
        TreeStoreElem *tselem;
2829
 
        int ytop, xdelta, prevFound=0;
2830
 
        char name[32];
2831
 
        
2832
 
        /* get last found tree-element based on stored search_tse */
2833
 
        last_find= outliner_find_tse(soops, &soops->search_tse);
2834
 
        
2835
 
        /* determine which type of search to do */
2836
 
        if (again && last_find) {
2837
 
                /* no popup panel - previous + user wanted to search for next after previous */         
2838
 
                BLI_strncpy(name, soops->search_string, sizeof(name));
2839
 
                flags= soops->search_flags;
2840
 
                
2841
 
                /* try to find matching element */
2842
 
                te= outliner_find_named(soops, &soops->tree, name, flags, last_find, &prevFound);
2843
 
                if (te==NULL) {
2844
 
                        /* no more matches after previous, start from beginning again */
2845
 
                        prevFound= 1;
2846
 
                        te= outliner_find_named(soops, &soops->tree, name, flags, last_find, &prevFound);
2847
 
                }
2848
 
        }
2849
 
        else {
2850
 
                /* pop up panel - no previous, or user didn't want search after previous */
2851
 
                strcpy(name, "");
2852
 
// XXX          if (sbutton(name, 0, sizeof(name)-1, "Find: ") && name[0]) {
2853
 
//                      te= outliner_find_named(soops, &soops->tree, name, flags, NULL, &prevFound);
2854
 
//              }
2855
 
//              else return; /* XXX RETURN! XXX */
2856
 
        }
2857
 
 
2858
 
        /* do selection and reveal */
2859
 
        if (te) {
2860
 
                tselem= TREESTORE(te);
2861
 
                if (tselem) {
2862
 
                        /* expand branches so that it will be visible, we need to get correct coordinates */
2863
 
                        if( outliner_open_back(soops, te))
2864
 
                                outliner_set_coordinates(ar, soops);
2865
 
                        
2866
 
                        /* deselect all visible, and select found element */
2867
 
                        outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0);
2868
 
                        tselem->flag |= TSE_SELECTED;
2869
 
                        
2870
 
                        /* make te->ys center of view */
2871
 
                        ytop= (int)(te->ys + (ar->v2d.mask.ymax-ar->v2d.mask.ymin)/2);
2872
 
                        if(ytop>0) ytop= 0;
2873
 
                        ar->v2d.cur.ymax= (float)ytop;
2874
 
                        ar->v2d.cur.ymin= (float)(ytop-(ar->v2d.mask.ymax-ar->v2d.mask.ymin));
2875
 
                        
2876
 
                        /* make te->xs ==> te->xend center of view */
2877
 
                        xdelta = (int)(te->xs - ar->v2d.cur.xmin);
2878
 
                        ar->v2d.cur.xmin += xdelta;
2879
 
                        ar->v2d.cur.xmax += xdelta;
2880
 
                        
2881
 
                        /* store selection */
2882
 
                        soops->search_tse= *tselem;
2883
 
                        
2884
 
                        BLI_strncpy(soops->search_string, name, 33);
2885
 
                        soops->search_flags= flags;
2886
 
                        
2887
 
                        /* redraw */
2888
 
                        soops->storeflag |= SO_TREESTORE_REDRAW;
2889
 
                }
2890
 
        }
2891
 
        else {
2892
 
                /* no tree-element found */
2893
 
                error("Not found: %s", name);
2894
 
        }
2895
 
}
2896
 
 
2897
 
/* helper function for tree_element_shwo_hierarchy() - recursively checks whether subtrees have any objects*/
2898
 
static int subtree_has_objects(SpaceOops *soops, ListBase *lb)
2899
 
{
2900
 
        TreeElement *te;
2901
 
        TreeStoreElem *tselem;
2902
 
        
2903
 
        for(te= lb->first; te; te= te->next) {
2904
 
                tselem= TREESTORE(te);
2905
 
                if(tselem->type==0 && te->idcode==ID_OB) return 1;
2906
 
                if( subtree_has_objects(soops, &te->subtree)) return 1;
2907
 
        }
2908
 
        return 0;
2909
 
}
2910
 
 
2911
 
/* recursive helper function for Show Hierarchy operator */
2912
 
static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase *lb)
2913
 
{
2914
 
        TreeElement *te;
2915
 
        TreeStoreElem *tselem;
2916
 
 
2917
 
        /* open all object elems, close others */
2918
 
        for(te= lb->first; te; te= te->next) {
2919
 
                tselem= TREESTORE(te);
2920
 
                
2921
 
                if(tselem->type==0) {
2922
 
                        if(te->idcode==ID_SCE) {
2923
 
                                if(tselem->id!=(ID *)scene) tselem->flag |= TSE_CLOSED;
2924
 
                                        else tselem->flag &= ~TSE_CLOSED;
2925
 
                        }
2926
 
                        else if(te->idcode==ID_OB) {
2927
 
                                if(subtree_has_objects(soops, &te->subtree)) tselem->flag &= ~TSE_CLOSED;
2928
 
                                else tselem->flag |= TSE_CLOSED;
2929
 
                        }
2930
 
                }
2931
 
                else tselem->flag |= TSE_CLOSED;
2932
 
                
2933
 
                if(tselem->flag & TSE_CLOSED); else tree_element_show_hierarchy(scene, soops, &te->subtree);
2934
 
        }
2935
 
}
2936
 
 
2937
 
/* show entire object level hierarchy */
2938
 
static int outliner_show_hierarchy_exec(bContext *C, wmOperator *op)
2939
 
{
2940
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
2941
 
        ARegion *ar= CTX_wm_region(C);
2942
 
        Scene *scene= CTX_data_scene(C);
2943
 
        
2944
 
        /* recursively open/close levels */
2945
 
        tree_element_show_hierarchy(scene, soops, &soops->tree);
2946
 
        
2947
 
        ED_region_tag_redraw(ar);
2948
 
        
2949
 
        return OPERATOR_FINISHED;
2950
 
}
2951
 
 
2952
 
void OUTLINER_OT_show_hierarchy(wmOperatorType *ot)
2953
 
{
2954
 
        /* identifiers */
2955
 
        ot->name= "Show Hierarchy";
2956
 
        ot->idname= "OUTLINER_OT_show_hierarchy";
2957
 
        ot->description= "Open all object entries and close all others";
2958
 
        
2959
 
        /* callbacks */
2960
 
        ot->exec= outliner_show_hierarchy_exec;
2961
 
        ot->poll= ED_operator_outliner_active; //  TODO: shouldn't be allowed in RNA views...
2962
 
        
2963
 
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2964
 
}
2965
 
 
2966
 
void outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting)
2967
 
{
2968
 
        TreeElement *te;
2969
 
        TreeStoreElem *tselem;
2970
 
        
2971
 
        for (te= lb->first; te && *index >= 0; te=te->next, (*index)--) {
2972
 
                tselem= TREESTORE(te);
2973
 
                
2974
 
                /* if we've encountered the right item, set its 'Outliner' selection status */
2975
 
                if (*index == 0) {
2976
 
                        /* this should be the last one, so no need to do anything with index */
2977
 
                        if ((te->flag & TE_ICONROW)==0) {
2978
 
                                /* -1 value means toggle testing for now... */
2979
 
                                if (*selecting == -1) {
2980
 
                                        if (tselem->flag & TSE_SELECTED) 
2981
 
                                                *selecting= 0;
2982
 
                                        else 
2983
 
                                                *selecting= 1;
2984
 
                                }
2985
 
                                
2986
 
                                /* set selection */
2987
 
                                if (*selecting) 
2988
 
                                        tselem->flag |= TSE_SELECTED;
2989
 
                                else 
2990
 
                                        tselem->flag &= ~TSE_SELECTED;
2991
 
                        }
2992
 
                }
2993
 
                else if ((tselem->flag & TSE_CLOSED)==0) {
2994
 
                        /* Only try selecting sub-elements if we haven't hit the right element yet
2995
 
                         *
2996
 
                         * Hack warning:
2997
 
                         *      Index must be reduced before supplying it to the sub-tree to try to do
2998
 
                         *      selection, however, we need to increment it again for the next loop to 
2999
 
                         *      function correctly
3000
 
                         */
3001
 
                        (*index)--;
3002
 
                        outliner_select(soops, &te->subtree, index, selecting);
3003
 
                        (*index)++;
3004
 
                }
3005
 
        }
3006
 
}
3007
 
 
3008
 
/* ************ SELECTION OPERATIONS ********* */
3009
 
 
3010
 
static void set_operation_types(SpaceOops *soops, ListBase *lb,
3011
 
                                int *scenelevel,
3012
 
                                int *objectlevel,
3013
 
                                int *idlevel,
3014
 
                                int *datalevel)
3015
 
{
3016
 
        TreeElement *te;
3017
 
        TreeStoreElem *tselem;
3018
 
        
3019
 
        for(te= lb->first; te; te= te->next) {
3020
 
                tselem= TREESTORE(te);
3021
 
                if(tselem->flag & TSE_SELECTED) {
3022
 
                        if(tselem->type) {
3023
 
                                if(*datalevel==0) 
3024
 
                                        *datalevel= tselem->type;
3025
 
                                else if(*datalevel!=tselem->type) 
3026
 
                                        *datalevel= -1;
3027
 
                        }
3028
 
                        else {
3029
 
                                int idcode= GS(tselem->id->name);
3030
 
                                switch(idcode) {
3031
 
                                        case ID_SCE:
3032
 
                                                *scenelevel= 1;
3033
 
                                                break;
3034
 
                                        case ID_OB:
3035
 
                                                *objectlevel= 1;
3036
 
                                                break;
3037
 
                                                
3038
 
                                        case ID_ME: case ID_CU: case ID_MB: case ID_LT:
3039
 
                                        case ID_LA: case ID_AR: case ID_CA:
3040
 
                                        case ID_MA: case ID_TE: case ID_IP: case ID_IM:
3041
 
                                        case ID_SO: case ID_KE: case ID_WO: case ID_AC:
3042
 
                                        case ID_NLA: case ID_TXT: case ID_GR:
3043
 
                                                if(*idlevel==0) *idlevel= idcode;
3044
 
                                                else if(*idlevel!=idcode) *idlevel= -1;
3045
 
                                                        break;
3046
 
                                }
3047
 
                        }
3048
 
                }
3049
 
                if((tselem->flag & TSE_CLOSED)==0) {
3050
 
                        set_operation_types(soops, &te->subtree,
3051
 
                                                                scenelevel, objectlevel, idlevel, datalevel);
3052
 
                }
3053
 
        }
3054
 
}
3055
 
 
3056
 
static void unlink_material_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
3057
 
{
3058
 
        Material **matar=NULL;
3059
 
        int a, totcol=0;
3060
 
        
3061
 
        if( GS(tsep->id->name)==ID_OB) {
3062
 
                Object *ob= (Object *)tsep->id;
3063
 
                totcol= ob->totcol;
3064
 
                matar= ob->mat;
3065
 
        }
3066
 
        else if( GS(tsep->id->name)==ID_ME) {
3067
 
                Mesh *me= (Mesh *)tsep->id;
3068
 
                totcol= me->totcol;
3069
 
                matar= me->mat;
3070
 
        }
3071
 
        else if( GS(tsep->id->name)==ID_CU) {
3072
 
                Curve *cu= (Curve *)tsep->id;
3073
 
                totcol= cu->totcol;
3074
 
                matar= cu->mat;
3075
 
        }
3076
 
        else if( GS(tsep->id->name)==ID_MB) {
3077
 
                MetaBall *mb= (MetaBall *)tsep->id;
3078
 
                totcol= mb->totcol;
3079
 
                matar= mb->mat;
3080
 
        }
3081
 
 
3082
 
        for(a=0; a<totcol; a++) {
3083
 
                if(a==te->index && matar[a]) {
3084
 
                        matar[a]->id.us--;
3085
 
                        matar[a]= NULL;
3086
 
                }
3087
 
        }
3088
 
}
3089
 
 
3090
 
static void unlink_texture_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
3091
 
{
3092
 
        MTex **mtex= NULL;
3093
 
        int a;
3094
 
        
3095
 
        if( GS(tsep->id->name)==ID_MA) {
3096
 
                Material *ma= (Material *)tsep->id;
3097
 
                mtex= ma->mtex;
3098
 
        }
3099
 
        else if( GS(tsep->id->name)==ID_LA) {
3100
 
                Lamp *la= (Lamp *)tsep->id;
3101
 
                mtex= la->mtex;
3102
 
        }
3103
 
        else if( GS(tsep->id->name)==ID_WO) {
3104
 
                World *wrld= (World *)tsep->id;
3105
 
                mtex= wrld->mtex;
3106
 
        }
3107
 
        else return;
3108
 
        
3109
 
        for(a=0; a<MAX_MTEX; a++) {
3110
 
                if(a==te->index && mtex[a]) {
3111
 
                        if(mtex[a]->tex) {
3112
 
                                mtex[a]->tex->id.us--;
3113
 
                                mtex[a]->tex= NULL;
3114
 
                        }
3115
 
                }
3116
 
        }
3117
 
}
3118
 
 
3119
 
static void unlink_group_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
3120
 
{
3121
 
        Group *group= (Group *)tselem->id;
3122
 
        
3123
 
        if(tsep) {
3124
 
                if( GS(tsep->id->name)==ID_OB) {
3125
 
                        Object *ob= (Object *)tsep->id;
3126
 
                        ob->dup_group= NULL;
3127
 
                }
3128
 
        }
3129
 
        else {
3130
 
                unlink_group(group);
3131
 
        }
3132
 
}
3133
 
 
3134
 
static void outliner_do_libdata_operation(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, 
3135
 
                                                                                 void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *))
3136
 
{
3137
 
        TreeElement *te;
3138
 
        TreeStoreElem *tselem;
3139
 
        
3140
 
        for(te=lb->first; te; te= te->next) {
3141
 
                tselem= TREESTORE(te);
3142
 
                if(tselem->flag & TSE_SELECTED) {
3143
 
                        if(tselem->type==0) {
3144
 
                                TreeStoreElem *tsep= TREESTORE(te->parent);
3145
 
                                operation_cb(C, scene, te, tsep, tselem);
3146
 
                        }
3147
 
                }
3148
 
                if((tselem->flag & TSE_CLOSED)==0) {
3149
 
                        outliner_do_libdata_operation(C, scene, soops, &te->subtree, operation_cb);
3150
 
                }
3151
 
        }
3152
 
}
3153
 
 
3154
 
/* */
3155
 
 
3156
 
static void object_select_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
3157
 
{
3158
 
        Base *base= (Base *)te->directdata;
3159
 
        
3160
 
        if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
3161
 
        if(base && ((base->object->restrictflag & OB_RESTRICT_VIEW)==0)) {
3162
 
                base->flag |= SELECT;
3163
 
                base->object->flag |= SELECT;
3164
 
        }
3165
 
}
3166
 
 
3167
 
static void object_deselect_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
3168
 
{
3169
 
        Base *base= (Base *)te->directdata;
3170
 
        
3171
 
        if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
3172
 
        if(base) {
3173
 
                base->flag &= ~SELECT;
3174
 
                base->object->flag &= ~SELECT;
3175
 
        }
3176
 
}
3177
 
 
3178
 
static void object_delete_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
3179
 
{
3180
 
        Base *base= (Base *)te->directdata;
3181
 
        
3182
 
        if(base==NULL) 
3183
 
                base= object_in_scene((Object *)tselem->id, scene);
3184
 
        if(base) {
3185
 
                // check also library later
3186
 
                if(scene->obedit==base->object) 
3187
 
                        ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO);
3188
 
                
3189
 
                ED_base_object_free_and_unlink(scene, base);
3190
 
                te->directdata= NULL;
3191
 
                tselem->id= NULL;
3192
 
        }
3193
 
        
3194
 
        WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
3195
 
 
3196
 
}
3197
 
 
3198
 
static void id_local_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
3199
 
{
3200
 
        if(tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) {
3201
 
                tselem->id->lib= NULL;
3202
 
                tselem->id->flag= LIB_LOCAL;
3203
 
                new_id(0, tselem->id, 0);
3204
 
        }
3205
 
}
3206
 
 
3207
 
static void group_linkobs2scene_cb(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
3208
 
{
3209
 
        Group *group= (Group *)tselem->id;
3210
 
        GroupObject *gob;
3211
 
        Base *base;
3212
 
        
3213
 
        for(gob=group->gobject.first; gob; gob=gob->next) {
3214
 
                base= object_in_scene(gob->ob, scene);
3215
 
                if (base) {
3216
 
                        base->object->flag |= SELECT;
3217
 
                        base->flag |= SELECT;
3218
 
                } else {
3219
 
                        /* link to scene */
3220
 
                        base= MEM_callocN( sizeof(Base), "add_base");
3221
 
                        BLI_addhead(&scene->base, base);
3222
 
                        base->lay= (1<<20)-1; /*v3d->lay;*/ /* would be nice to use the 3d layer but the include's not here */
3223
 
                        gob->ob->flag |= SELECT;
3224
 
                        base->flag = gob->ob->flag;
3225
 
                        base->object= gob->ob;
3226
 
                        id_lib_extern((ID *)gob->ob); /* incase these are from a linked group */
3227
 
                }
3228
 
        }
3229
 
}
3230
 
 
3231
 
static void outliner_do_object_operation(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, 
3232
 
                                                                                 void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *))
3233
 
{
3234
 
        TreeElement *te;
3235
 
        TreeStoreElem *tselem;
3236
 
        
3237
 
        for(te=lb->first; te; te= te->next) {
3238
 
                tselem= TREESTORE(te);
3239
 
                if(tselem->flag & TSE_SELECTED) {
3240
 
                        if(tselem->type==0 && te->idcode==ID_OB) {
3241
 
                                // when objects selected in other scenes... dunno if that should be allowed
3242
 
                                Scene *sce= (Scene *)outliner_search_back(soops, te, ID_SCE);
3243
 
                                if(sce && scene != sce) {
3244
 
                                        ED_screen_set_scene(C, sce);
3245
 
                                }
3246
 
                                
3247
 
                                operation_cb(C, scene, te, NULL, tselem);
3248
 
                        }
3249
 
                }
3250
 
                if((tselem->flag & TSE_CLOSED)==0) {
3251
 
                        outliner_do_object_operation(C, scene, soops, &te->subtree, operation_cb);
3252
 
                }
3253
 
        }
3254
 
}
3255
 
 
3256
 
/* ******************************************** */
3257
 
 
3258
 
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *tselem)
3259
 
{
3260
 
        bPoseChannel *pchan= (bPoseChannel *)te->directdata;
3261
 
        
3262
 
        if(event==1)
3263
 
                pchan->bone->flag |= BONE_SELECTED;
3264
 
        else if(event==2)
3265
 
                pchan->bone->flag &= ~BONE_SELECTED;
3266
 
        else if(event==3) {
3267
 
                pchan->bone->flag |= BONE_HIDDEN_P;
3268
 
                pchan->bone->flag &= ~BONE_SELECTED;
3269
 
        }
3270
 
        else if(event==4)
3271
 
                pchan->bone->flag &= ~BONE_HIDDEN_P;
3272
 
}
3273
 
 
3274
 
static void bone_cb(int event, TreeElement *te, TreeStoreElem *tselem)
3275
 
{
3276
 
        Bone *bone= (Bone *)te->directdata;
3277
 
        
3278
 
        if(event==1)
3279
 
                bone->flag |= BONE_SELECTED;
3280
 
        else if(event==2)
3281
 
                bone->flag &= ~BONE_SELECTED;
3282
 
        else if(event==3) {
3283
 
                bone->flag |= BONE_HIDDEN_P;
3284
 
                bone->flag &= ~BONE_SELECTED;
3285
 
        }
3286
 
        else if(event==4)
3287
 
                bone->flag &= ~BONE_HIDDEN_P;
3288
 
}
3289
 
 
3290
 
static void ebone_cb(int event, TreeElement *te, TreeStoreElem *tselem)
3291
 
{
3292
 
        EditBone *ebone= (EditBone *)te->directdata;
3293
 
        
3294
 
        if(event==1)
3295
 
                ebone->flag |= BONE_SELECTED;
3296
 
        else if(event==2)
3297
 
                ebone->flag &= ~BONE_SELECTED;
3298
 
        else if(event==3) {
3299
 
                ebone->flag |= BONE_HIDDEN_A;
3300
 
                ebone->flag &= ~BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
3301
 
        }
3302
 
        else if(event==4)
3303
 
                ebone->flag &= ~BONE_HIDDEN_A;
3304
 
}
3305
 
 
3306
 
static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem)
3307
 
{
3308
 
//      Sequence *seq= (Sequence*) te->directdata;
3309
 
        if(event==1) {
3310
 
// XXX          select_single_seq(seq, 1);
3311
 
        }
3312
 
}
3313
 
 
3314
 
static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb, 
3315
 
                                                                                 void (*operation_cb)(int, TreeElement *, TreeStoreElem *))
3316
 
{
3317
 
        TreeElement *te;
3318
 
        TreeStoreElem *tselem;
3319
 
        
3320
 
        for(te=lb->first; te; te= te->next) {
3321
 
                tselem= TREESTORE(te);
3322
 
                if(tselem->flag & TSE_SELECTED) {
3323
 
                        if(tselem->type==type) {
3324
 
                                operation_cb(event, te, tselem);
3325
 
                        }
3326
 
                }
3327
 
                if((tselem->flag & TSE_CLOSED)==0) {
3328
 
                        outliner_do_data_operation(soops, type, event, &te->subtree, operation_cb);
3329
 
                }
3330
 
        }
3331
 
}
3332
 
 
3333
 
void outliner_del(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops)
3334
 
{
3335
 
        
3336
 
        if(soops->outlinevis==SO_SEQUENCE)
3337
 
                ;//             del_seq();
3338
 
        else {
3339
 
                outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_cb);
3340
 
                DAG_scene_sort(scene);
3341
 
                ED_undo_push(C, "Delete Objects");
3342
 
        }
3343
 
}
3344
 
 
3345
 
/* **************************************** */
3346
 
 
3347
 
static EnumPropertyItem prop_object_op_types[] = {
3348
 
        {1, "SELECT", 0, "Select", ""},
3349
 
        {2, "DESELECT", 0, "Deselect", ""},
3350
 
        {4, "DELETE", 0, "Delete", ""},
3351
 
        {6, "TOGVIS", 0, "Toggle Visible", ""},
3352
 
        {7, "TOGSEL", 0, "Toggle Selectable", ""},
3353
 
        {8, "TOGREN", 0, "Toggle Renderable", ""},
3354
 
        {0, NULL, 0, NULL, NULL}
3355
 
};
3356
 
 
3357
 
static int outliner_object_operation_exec(bContext *C, wmOperator *op)
3358
 
{
3359
 
        Scene *scene= CTX_data_scene(C);
3360
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
3361
 
        int event;
3362
 
        char *str= NULL;
3363
 
        
3364
 
        /* check for invalid states */
3365
 
        if (soops == NULL)
3366
 
                return OPERATOR_CANCELLED;
3367
 
        
3368
 
        event= RNA_enum_get(op->ptr, "type");
3369
 
 
3370
 
        if(event==1) {
3371
 
                Scene *sce= scene;      // to be able to delete, scenes are set...
3372
 
                outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_cb);
3373
 
                if(scene != sce) {
3374
 
                        ED_screen_set_scene(C, sce);
3375
 
                }
3376
 
                
3377
 
                str= "Select Objects";
3378
 
        }
3379
 
        else if(event==2) {
3380
 
                outliner_do_object_operation(C, scene, soops, &soops->tree, object_deselect_cb);
3381
 
                str= "Deselect Objects";
3382
 
        }
3383
 
        else if(event==4) {
3384
 
                outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_cb);
3385
 
                DAG_scene_sort(scene);
3386
 
                str= "Delete Objects";
3387
 
        }
3388
 
        else if(event==5) {     /* disabled, see above (ton) */
3389
 
                outliner_do_object_operation(C, scene, soops, &soops->tree, id_local_cb);
3390
 
                str= "Localized Objects";
3391
 
        }
3392
 
        else if(event==6) {
3393
 
                outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb);
3394
 
                str= "Toggle Visibility";
3395
 
        }
3396
 
        else if(event==7) {
3397
 
                outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_selectability_cb);
3398
 
                str= "Toggle Selectability";
3399
 
        }
3400
 
        else if(event==8) {
3401
 
                outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb);
3402
 
                str= "Toggle Renderability";
3403
 
        }
3404
 
        
3405
 
        WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
3406
 
 
3407
 
        ED_undo_push(C, str);
3408
 
        
3409
 
        return OPERATOR_FINISHED;
3410
 
}
3411
 
 
3412
 
 
3413
 
void OUTLINER_OT_object_operation(wmOperatorType *ot)
3414
 
{
3415
 
        /* identifiers */
3416
 
        ot->name= "Outliner Object Operation";
3417
 
        ot->idname= "OUTLINER_OT_object_operation";
3418
 
        ot->description= "";
3419
 
        
3420
 
        /* callbacks */
3421
 
        ot->invoke= WM_menu_invoke;
3422
 
        ot->exec= outliner_object_operation_exec;
3423
 
        ot->poll= ED_operator_outliner_active;
3424
 
        
3425
 
        ot->flag= 0;
3426
 
 
3427
 
        ot->prop= RNA_def_enum(ot->srna, "type", prop_object_op_types, 0, "Object Operation", "");
3428
 
}
3429
 
 
3430
 
/* **************************************** */
3431
 
 
3432
 
static EnumPropertyItem prop_group_op_types[] = {
3433
 
        {1, "UNLINK", 0, "Unlink", ""},
3434
 
        {2, "LOCAL", 0, "Make Local", ""},
3435
 
        {3, "LINK", 0, "Link Group Objects to Scene", ""},
3436
 
        {4, "TOGVIS", 0, "Toggle Visible", ""},
3437
 
        {5, "TOGSEL", 0, "Toggle Selectable", ""},
3438
 
        {6, "TOGREN", 0, "Toggle Renderable", ""},
3439
 
        {0, NULL, 0, NULL, NULL}
3440
 
};
3441
 
 
3442
 
static int outliner_group_operation_exec(bContext *C, wmOperator *op)
3443
 
{
3444
 
        Scene *scene= CTX_data_scene(C);
3445
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
3446
 
        int event;
3447
 
        
3448
 
        /* check for invalid states */
3449
 
        if (soops == NULL)
3450
 
                return OPERATOR_CANCELLED;
3451
 
        
3452
 
        event= RNA_enum_get(op->ptr, "type");
3453
 
        
3454
 
        if(event==1) {
3455
 
                outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_group_cb);
3456
 
                ED_undo_push(C, "Unlink group");
3457
 
        }
3458
 
        else if(event==2) {
3459
 
                outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb);
3460
 
                ED_undo_push(C, "Localized Data");
3461
 
        }
3462
 
        else if(event==3) {
3463
 
                outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_linkobs2scene_cb);
3464
 
                ED_undo_push(C, "Link Group Objects to Scene");
3465
 
        }   
3466
 
        
3467
 
        
3468
 
        WM_event_add_notifier(C, NC_GROUP, NULL);
3469
 
        
3470
 
        return OPERATOR_FINISHED;
3471
 
}
3472
 
 
3473
 
 
3474
 
void OUTLINER_OT_group_operation(wmOperatorType *ot)
3475
 
{
3476
 
        /* identifiers */
3477
 
        ot->name= "Outliner Group Operation";
3478
 
        ot->idname= "OUTLINER_OT_group_operation";
3479
 
        ot->description= "";
3480
 
        
3481
 
        /* callbacks */
3482
 
        ot->invoke= WM_menu_invoke;
3483
 
        ot->exec= outliner_group_operation_exec;
3484
 
        ot->poll= ED_operator_outliner_active;
3485
 
        
3486
 
        ot->flag= 0;
3487
 
        
3488
 
        ot->prop= RNA_def_enum(ot->srna, "type", prop_group_op_types, 0, "Group Operation", "");
3489
 
}
3490
 
 
3491
 
/* **************************************** */
3492
 
 
3493
 
static EnumPropertyItem prop_id_op_types[] = {
3494
 
        {1, "UNLINK", 0, "Unlink", ""},
3495
 
        {2, "LOCAL", 0, "Make Local", ""},
3496
 
        {0, NULL, 0, NULL, NULL}
3497
 
};
3498
 
 
3499
 
static int outliner_id_operation_exec(bContext *C, wmOperator *op)
3500
 
{
3501
 
        Scene *scene= CTX_data_scene(C);
3502
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
3503
 
        int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0;
3504
 
        int event;
3505
 
        
3506
 
        /* check for invalid states */
3507
 
        if (soops == NULL)
3508
 
                return OPERATOR_CANCELLED;
3509
 
        
3510
 
        set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
3511
 
        
3512
 
        event= RNA_enum_get(op->ptr, "type");
3513
 
        
3514
 
        if(event==1) {
3515
 
                switch(idlevel) {
3516
 
                        case ID_MA:
3517
 
                                outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_material_cb);
3518
 
                                ED_undo_push(C, "Unlink material");
3519
 
                                break;
3520
 
                        case ID_TE:
3521
 
                                outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_texture_cb);
3522
 
                                ED_undo_push(C, "Unlink texture");
3523
 
                                break;
3524
 
                        default:
3525
 
                                BKE_report(op->reports, RPT_WARNING, "Not Yet");
3526
 
                }
3527
 
        }
3528
 
        else if(event==2) {
3529
 
                outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb);
3530
 
                ED_undo_push(C, "Localized Data");
3531
 
        }
3532
 
        
3533
 
        /* wrong notifier still... */
3534
 
        WM_event_add_notifier(C, NC_OBJECT, NULL);
3535
 
        
3536
 
        return OPERATOR_FINISHED;
3537
 
}
3538
 
 
3539
 
 
3540
 
void OUTLINER_OT_id_operation(wmOperatorType *ot)
3541
 
{
3542
 
        /* identifiers */
3543
 
        ot->name= "Outliner ID data Operation";
3544
 
        ot->idname= "OUTLINER_OT_id_operation";
3545
 
        ot->description= "";
3546
 
        
3547
 
        /* callbacks */
3548
 
        ot->invoke= WM_menu_invoke;
3549
 
        ot->exec= outliner_id_operation_exec;
3550
 
        ot->poll= ED_operator_outliner_active;
3551
 
        
3552
 
        ot->flag= 0;
3553
 
        
3554
 
        ot->prop= RNA_def_enum(ot->srna, "type", prop_id_op_types, 0, "ID data Operation", "");
3555
 
}
3556
 
 
3557
 
/* **************************************** */
3558
 
 
3559
 
static EnumPropertyItem prop_data_op_types[] = {
3560
 
        {1, "SELECT", 0, "Select", ""},
3561
 
        {2, "DESELECT", 0, "Deselect", ""},
3562
 
        {3, "HIDE", 0, "Hide", ""},
3563
 
        {4, "UNHIDE", 0, "Unhide", ""},
3564
 
        {0, NULL, 0, NULL, NULL}
3565
 
};
3566
 
 
3567
 
static int outliner_data_operation_exec(bContext *C, wmOperator *op)
3568
 
{
3569
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
3570
 
        int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0;
3571
 
        int event;
3572
 
        
3573
 
        /* check for invalid states */
3574
 
        if (soops == NULL)
3575
 
                return OPERATOR_CANCELLED;
3576
 
        
3577
 
        event= RNA_enum_get(op->ptr, "type");
3578
 
        set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
3579
 
        
3580
 
        if(datalevel==TSE_POSE_CHANNEL) {
3581
 
                if(event>0) {
3582
 
                        outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb);
3583
 
                        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
3584
 
                        ED_undo_push(C, "PoseChannel operation");
3585
 
                }
3586
 
        }
3587
 
        else if(datalevel==TSE_BONE) {
3588
 
                if(event>0) {
3589
 
                        outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb);
3590
 
                        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
3591
 
                        ED_undo_push(C, "Bone operation");
3592
 
                }
3593
 
        }
3594
 
        else if(datalevel==TSE_EBONE) {
3595
 
                if(event>0) {
3596
 
                        outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb);
3597
 
                        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
3598
 
                        ED_undo_push(C, "EditBone operation");
3599
 
                }
3600
 
        }
3601
 
        else if(datalevel==TSE_SEQUENCE) {
3602
 
                if(event>0) {
3603
 
                        outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb);
3604
 
                }
3605
 
        }
3606
 
        
3607
 
        return OPERATOR_FINISHED;
3608
 
}
3609
 
 
3610
 
 
3611
 
void OUTLINER_OT_data_operation(wmOperatorType *ot)
3612
 
{
3613
 
        /* identifiers */
3614
 
        ot->name= "Outliner Data Operation";
3615
 
        ot->idname= "OUTLINER_OT_data_operation";
3616
 
        ot->description= "";
3617
 
        
3618
 
        /* callbacks */
3619
 
        ot->invoke= WM_menu_invoke;
3620
 
        ot->exec= outliner_data_operation_exec;
3621
 
        ot->poll= ED_operator_outliner_active;
3622
 
        
3623
 
        ot->flag= 0;
3624
 
        
3625
 
        ot->prop= RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", "");
3626
 
}
3627
 
 
3628
 
 
3629
 
/* ******************** */
3630
 
 
3631
 
 
3632
 
static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, wmEvent *event, float *mval)
3633
 
{
3634
 
        
3635
 
        if(mval[1]>te->ys && mval[1]<te->ys+OL_H) {
3636
 
                int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0;
3637
 
                TreeStoreElem *tselem= TREESTORE(te);
3638
 
                
3639
 
                /* select object that's clicked on and popup context menu */
3640
 
                if (!(tselem->flag & TSE_SELECTED)) {
3641
 
                        
3642
 
                        if ( outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1) )
3643
 
                                outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0);
3644
 
                        
3645
 
                        tselem->flag |= TSE_SELECTED;
3646
 
                        /* redraw, same as outliner_select function */
3647
 
                        soops->storeflag |= SO_TREESTORE_REDRAW;
3648
 
                        ED_region_tag_redraw(ar);
3649
 
                }
3650
 
                
3651
 
                set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
3652
 
                
3653
 
                if(scenelevel) {
3654
 
                        //if(objectlevel || datalevel || idlevel) error("Mixed selection");
3655
 
                        //else pupmenu("Scene Operations%t|Delete");
3656
 
                }
3657
 
                else if(objectlevel) {
3658
 
                        WM_operator_name_call(C, "OUTLINER_OT_object_operation", WM_OP_INVOKE_REGION_WIN, NULL);
3659
 
                }
3660
 
                else if(idlevel) {
3661
 
                        if(idlevel==-1 || datalevel) error("Mixed selection");
3662
 
                        else {
3663
 
                                if (idlevel==ID_GR)
3664
 
                                        WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
3665
 
                                else
3666
 
                                        WM_operator_name_call(C, "OUTLINER_OT_id_operation", WM_OP_INVOKE_REGION_WIN, NULL);
3667
 
                        }
3668
 
                }
3669
 
                else if(datalevel) {
3670
 
                        if(datalevel==-1) error("Mixed selection");
3671
 
                        else {
3672
 
                                WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL);
3673
 
                        }
3674
 
                }
3675
 
                
3676
 
                return 1;
3677
 
        }
3678
 
        
3679
 
        for(te= te->subtree.first; te; te= te->next) {
3680
 
                if(do_outliner_operation_event(C, scene, ar, soops, te, event, mval)) 
3681
 
                        return 1;
3682
 
        }
3683
 
        return 0;
3684
 
}
3685
 
 
3686
 
 
3687
 
static int outliner_operation(bContext *C, wmOperator *op, wmEvent *event)
3688
 
{
3689
 
        Scene *scene= CTX_data_scene(C);
3690
 
        ARegion *ar= CTX_wm_region(C);
3691
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
3692
 
        TreeElement *te;
3693
 
        float fmval[2];
3694
 
        
3695
 
        UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1);
3696
 
        
3697
 
        for(te= soops->tree.first; te; te= te->next) {
3698
 
                if(do_outliner_operation_event(C, scene, ar, soops, te, event, fmval)) break;
3699
 
        }
3700
 
        
3701
 
        return OPERATOR_FINISHED;
3702
 
}
3703
 
 
3704
 
/* Menu only! Calls other operators */
3705
 
void OUTLINER_OT_operation(wmOperatorType *ot)
3706
 
{
3707
 
        ot->name= "Execute Operation";
3708
 
        ot->idname= "OUTLINER_OT_operation";
3709
 
        
3710
 
        ot->invoke= outliner_operation;
3711
 
        
3712
 
        ot->poll= ED_operator_outliner_active;
3713
 
}
3714
 
 
3715
 
 
3716
 
 
3717
 
/* ***************** ANIMATO OPERATIONS ********************************** */
3718
 
/* KeyingSet and Driver Creation - Helper functions */
3719
 
 
3720
 
/* specialised poll callback for these operators to work in Datablocks view only */
3721
 
static int ed_operator_outliner_datablocks_active(bContext *C)
3722
 
{
3723
 
        ScrArea *sa= CTX_wm_area(C);
3724
 
        if ((sa) && (sa->spacetype==SPACE_OUTLINER)) {
3725
 
                SpaceOops *so= CTX_wm_space_outliner(C);
3726
 
                return (so->outlinevis == SO_DATABLOCKS);
3727
 
        }
3728
 
        return 0;
3729
 
}
3730
 
 
3731
 
 
3732
 
/* Helper func to extract an RNA path from selected tree element 
3733
 
 * NOTE: the caller must zero-out all values of the pointers that it passes here first, as
3734
 
 * this function does not do that yet 
3735
 
 */
3736
 
static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, 
3737
 
                                                        ID **id, char **path, int *array_index, short *flag, short *groupmode)
3738
 
{
3739
 
        ListBase hierarchy = {NULL, NULL};
3740
 
        LinkData *ld;
3741
 
        TreeElement *tem, *temnext, *temsub;
3742
 
        TreeStoreElem *tse, *tsenext;
3743
 
        PointerRNA *ptr, *nextptr;
3744
 
        PropertyRNA *prop;
3745
 
        char *newpath=NULL;
3746
 
        
3747
 
        /* optimise tricks:
3748
 
         *      - Don't do anything if the selected item is a 'struct', but arrays are allowed
3749
 
         */
3750
 
        if (tselem->type == TSE_RNA_STRUCT)
3751
 
                return;
3752
 
        
3753
 
        /* Overview of Algorithm:
3754
 
         *      1. Go up the chain of parents until we find the 'root', taking note of the 
3755
 
         *         levels encountered in reverse-order (i.e. items are added to the start of the list
3756
 
         *      for more convenient looping later)
3757
 
         *      2. Walk down the chain, adding from the first ID encountered 
3758
 
         *         (which will become the 'ID' for the KeyingSet Path), and build a  
3759
 
         *              path as we step through the chain
3760
 
         */
3761
 
         
3762
 
        /* step 1: flatten out hierarchy of parents into a flat chain */
3763
 
        for (tem= te->parent; tem; tem= tem->parent) {
3764
 
                ld= MEM_callocN(sizeof(LinkData), "LinkData for tree_element_to_path()");
3765
 
                ld->data= tem;
3766
 
                BLI_addhead(&hierarchy, ld);
3767
 
        }
3768
 
        
3769
 
        /* step 2: step down hierarchy building the path (NOTE: addhead in previous loop was needed so that we can loop like this) */
3770
 
        for (ld= hierarchy.first; ld; ld= ld->next) {
3771
 
                /* get data */
3772
 
                tem= (TreeElement *)ld->data;
3773
 
                tse= TREESTORE(tem);
3774
 
                ptr= &tem->rnaptr;
3775
 
                prop= tem->directdata;
3776
 
                
3777
 
                /* check if we're looking for first ID, or appending to path */
3778
 
                if (*id) {
3779
 
                        /* just 'append' property to path 
3780
 
                         *      - to prevent memory leaks, we must write to newpath not path, then free old path + swap them
3781
 
                         */
3782
 
                        if(tse->type == TSE_RNA_PROPERTY) {
3783
 
                                if(RNA_property_type(prop) == PROP_POINTER) {
3784
 
                                        /* for pointer we just append property name */
3785
 
                                        newpath= RNA_path_append(*path, ptr, prop, 0, NULL);
3786
 
                                }
3787
 
                                else if(RNA_property_type(prop) == PROP_COLLECTION) {
3788
 
                                        char buf[128], *name;
3789
 
                                        
3790
 
                                        temnext= (TreeElement*)(ld->next->data);
3791
 
                                        tsenext= TREESTORE(temnext);
3792
 
                                        
3793
 
                                        nextptr= &temnext->rnaptr;
3794
 
                                        name= RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf));
3795
 
                                        
3796
 
                                        if(name) {
3797
 
                                                /* if possible, use name as a key in the path */
3798
 
                                                newpath= RNA_path_append(*path, NULL, prop, 0, name);
3799
 
                                                
3800
 
                                                if(name != buf)
3801
 
                                                        MEM_freeN(name);
3802
 
                                        }
3803
 
                                        else {
3804
 
                                                /* otherwise use index */
3805
 
                                                int index= 0;
3806
 
                                                
3807
 
                                                for(temsub=tem->subtree.first; temsub; temsub=temsub->next, index++)
3808
 
                                                        if(temsub == temnext)
3809
 
                                                                break;
3810
 
                                                
3811
 
                                                newpath= RNA_path_append(*path, NULL, prop, index, NULL);
3812
 
                                        }
3813
 
                                        
3814
 
                                        ld= ld->next;
3815
 
                                }
3816
 
                        }
3817
 
                        
3818
 
                        if(newpath) {
3819
 
                                if (*path) MEM_freeN(*path);
3820
 
                                *path= newpath;
3821
 
                                newpath= NULL;
3822
 
                        }
3823
 
                }
3824
 
                else {
3825
 
                        /* no ID, so check if entry is RNA-struct, and if that RNA-struct is an ID datablock to extract info from */
3826
 
                        if (tse->type == TSE_RNA_STRUCT) {
3827
 
                                /* ptr->data not ptr->id.data seems to be the one we want, since ptr->data is sometimes the owner of this ID? */
3828
 
                                if(RNA_struct_is_ID(ptr->type)) {
3829
 
                                        *id= (ID *)ptr->data;
3830
 
                                        
3831
 
                                        /* clear path */
3832
 
                                        if(*path) {
3833
 
                                                MEM_freeN(*path);
3834
 
                                                path= NULL;
3835
 
                                        }
3836
 
                                }
3837
 
                        }
3838
 
                }
3839
 
        }
3840
 
 
3841
 
        /* step 3: if we've got an ID, add the current item to the path */
3842
 
        if (*id) {
3843
 
                /* add the active property to the path */
3844
 
                ptr= &te->rnaptr;
3845
 
                prop= te->directdata;
3846
 
                
3847
 
                /* array checks */
3848
 
                if (tselem->type == TSE_RNA_ARRAY_ELEM) {
3849
 
                        /* item is part of an array, so must set the array_index */
3850
 
                        *array_index= te->index;
3851
 
                }
3852
 
                else if (RNA_property_array_length(ptr, prop)) {
3853
 
                        /* entire array was selected, so keyframe all */
3854
 
                        *flag |= KSP_FLAG_WHOLE_ARRAY;
3855
 
                }
3856
 
                
3857
 
                /* path */
3858
 
                newpath= RNA_path_append(*path, NULL, prop, 0, NULL);
3859
 
                if (*path) MEM_freeN(*path);
3860
 
                *path= newpath;
3861
 
        }
3862
 
 
3863
 
        /* free temp data */
3864
 
        BLI_freelistN(&hierarchy);
3865
 
}
3866
 
 
3867
 
/* ***************** KEYINGSET OPERATIONS *************** */
3868
 
 
3869
 
/* These operators are only available in databrowser mode for now, as
3870
 
 * they depend on having RNA paths and/or hierarchies available.
3871
 
 */
3872
 
enum {
3873
 
        DRIVERS_EDITMODE_ADD    = 0,
3874
 
        DRIVERS_EDITMODE_REMOVE,
3875
 
} eDrivers_EditModes;
3876
 
 
3877
 
/* Utilities ---------------------------------- */ 
3878
 
 
3879
 
/* Recursively iterate over tree, finding and working on selected items */
3880
 
static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, short mode)
3881
 
{
3882
 
        TreeElement *te;
3883
 
        TreeStoreElem *tselem;
3884
 
        
3885
 
        for (te= tree->first; te; te=te->next) {
3886
 
                tselem= TREESTORE(te);
3887
 
                
3888
 
                /* if item is selected, perform operation */
3889
 
                if (tselem->flag & TSE_SELECTED) {
3890
 
                        ID *id= NULL;
3891
 
                        char *path= NULL;
3892
 
                        int array_index= 0;
3893
 
                        short flag= 0;
3894
 
                        short groupmode= KSP_GROUP_KSNAME;
3895
 
                        
3896
 
                        /* check if RNA-property described by this selected element is an animateable prop */
3897
 
                        if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) && RNA_property_animateable(&te->rnaptr, te->directdata)) {
3898
 
                                /* get id + path + index info from the selected element */
3899
 
                                tree_element_to_path(soops, te, tselem, 
3900
 
                                                &id, &path, &array_index, &flag, &groupmode);
3901
 
                        }
3902
 
                        
3903
 
                        /* only if ID and path were set, should we perform any actions */
3904
 
                        if (id && path) {
3905
 
                                int arraylen = 1;
3906
 
                                
3907
 
                                /* array checks */
3908
 
                                if (flag & KSP_FLAG_WHOLE_ARRAY) {
3909
 
                                        /* entire array was selected, so add drivers for all */
3910
 
                                        arraylen= RNA_property_array_length(&te->rnaptr, te->directdata);
3911
 
                                }
3912
 
                                else
3913
 
                                        arraylen= array_index;
3914
 
                                
3915
 
                                /* we should do at least one step */
3916
 
                                if (arraylen == array_index)
3917
 
                                        arraylen++;
3918
 
                                
3919
 
                                /* for each array element we should affect, add driver */
3920
 
                                for (; array_index < arraylen; array_index++) {
3921
 
                                        /* action depends on mode */
3922
 
                                        switch (mode) {
3923
 
                                                case DRIVERS_EDITMODE_ADD:
3924
 
                                                {
3925
 
                                                        /* add a new driver with the information obtained (only if valid) */
3926
 
                                                        ANIM_add_driver(id, path, array_index, flag, DRIVER_TYPE_PYTHON);
3927
 
                                                }
3928
 
                                                        break;
3929
 
                                                case DRIVERS_EDITMODE_REMOVE:
3930
 
                                                {
3931
 
                                                        /* remove driver matching the information obtained (only if valid) */
3932
 
                                                        ANIM_remove_driver(id, path, array_index, flag);
3933
 
                                                }
3934
 
                                                        break;
3935
 
                                        }
3936
 
                                }
3937
 
                                
3938
 
                                /* free path, since it had to be generated */
3939
 
                                MEM_freeN(path);
3940
 
                        }
3941
 
                        
3942
 
                        
3943
 
                }
3944
 
                
3945
 
                /* go over sub-tree */
3946
 
                if ((tselem->flag & TSE_CLOSED)==0)
3947
 
                        do_outliner_drivers_editop(soops, &te->subtree, mode);
3948
 
        }
3949
 
}
3950
 
 
3951
 
/* Add Operator ---------------------------------- */
3952
 
 
3953
 
static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op)
3954
 
{
3955
 
        SpaceOops *soutliner= CTX_wm_space_outliner(C);
3956
 
        
3957
 
        /* check for invalid states */
3958
 
        if (soutliner == NULL)
3959
 
                return OPERATOR_CANCELLED;
3960
 
        
3961
 
        /* recursively go into tree, adding selected items */
3962
 
        do_outliner_drivers_editop(soutliner, &soutliner->tree, DRIVERS_EDITMODE_ADD);
3963
 
        
3964
 
        /* send notifiers */
3965
 
        WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
3966
 
        
3967
 
        return OPERATOR_FINISHED;
3968
 
}
3969
 
 
3970
 
void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot)
3971
 
{
3972
 
        /* api callbacks */
3973
 
        ot->idname= "OUTLINER_OT_drivers_add_selected";
3974
 
        ot->name= "Add Drivers for Selected";
3975
 
        ot->description= "Add drivers to selected items";
3976
 
        
3977
 
        /* api callbacks */
3978
 
        ot->exec= outliner_drivers_addsel_exec;
3979
 
        ot->poll= ed_operator_outliner_datablocks_active;
3980
 
        
3981
 
        /* flags */
3982
 
        ot->flag = OPTYPE_UNDO;
3983
 
}
3984
 
 
3985
 
 
3986
 
/* Remove Operator ---------------------------------- */
3987
 
 
3988
 
static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op)
3989
 
{
3990
 
        SpaceOops *soutliner= CTX_wm_space_outliner(C);
3991
 
        
3992
 
        /* check for invalid states */
3993
 
        if (soutliner == NULL)
3994
 
                return OPERATOR_CANCELLED;
3995
 
        
3996
 
        /* recursively go into tree, adding selected items */
3997
 
        do_outliner_drivers_editop(soutliner, &soutliner->tree, DRIVERS_EDITMODE_REMOVE);
3998
 
        
3999
 
        /* send notifiers */
4000
 
        WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
4001
 
        
4002
 
        return OPERATOR_FINISHED;
4003
 
}
4004
 
 
4005
 
void OUTLINER_OT_drivers_delete_selected(wmOperatorType *ot)
4006
 
{
4007
 
        /* identifiers */
4008
 
        ot->idname= "OUTLINER_OT_drivers_delete_selected";
4009
 
        ot->name= "Delete Drivers for Selected";
4010
 
        ot->description= "Delete drivers assigned to selected items";
4011
 
        
4012
 
        /* api callbacks */
4013
 
        ot->exec= outliner_drivers_deletesel_exec;
4014
 
        ot->poll= ed_operator_outliner_datablocks_active;
4015
 
        
4016
 
        /* flags */
4017
 
        ot->flag = OPTYPE_UNDO;
4018
 
}
4019
 
 
4020
 
/* ***************** KEYINGSET OPERATIONS *************** */
4021
 
 
4022
 
/* These operators are only available in databrowser mode for now, as
4023
 
 * they depend on having RNA paths and/or hierarchies available.
4024
 
 */
4025
 
enum {
4026
 
        KEYINGSET_EDITMODE_ADD  = 0,
4027
 
        KEYINGSET_EDITMODE_REMOVE,
4028
 
} eKeyingSet_EditModes;
4029
 
 
4030
 
/* Utilities ---------------------------------- */ 
4031
 
 
4032
 
/* find the 'active' KeyingSet, and add if not found (if adding is allowed) */
4033
 
// TODO: should this be an API func?
4034
 
static KeyingSet *verify_active_keyingset(Scene *scene, short add)
4035
 
{
4036
 
        KeyingSet *ks= NULL;
4037
 
        
4038
 
        /* sanity check */
4039
 
        if (scene == NULL)
4040
 
                return NULL;
4041
 
        
4042
 
        /* try to find one from scene */
4043
 
        if (scene->active_keyingset > 0)
4044
 
                ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
4045
 
                
4046
 
        /* add if none found */
4047
 
        // XXX the default settings have yet to evolve
4048
 
        if ((add) && (ks==NULL)) {
4049
 
                ks= BKE_keyingset_add(&scene->keyingsets, NULL, KEYINGSET_ABSOLUTE, 0);
4050
 
                scene->active_keyingset= BLI_countlist(&scene->keyingsets);
4051
 
        }
4052
 
        
4053
 
        return ks;
4054
 
}
4055
 
 
4056
 
/* Recursively iterate over tree, finding and working on selected items */
4057
 
static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBase *tree, short mode)
4058
 
{
4059
 
        TreeElement *te;
4060
 
        TreeStoreElem *tselem;
4061
 
        
4062
 
        for (te= tree->first; te; te=te->next) {
4063
 
                tselem= TREESTORE(te);
4064
 
                
4065
 
                /* if item is selected, perform operation */
4066
 
                if (tselem->flag & TSE_SELECTED) {
4067
 
                        ID *id= NULL;
4068
 
                        char *path= NULL;
4069
 
                        int array_index= 0;
4070
 
                        short flag= 0;
4071
 
                        short groupmode= KSP_GROUP_KSNAME;
4072
 
                        
4073
 
                        /* check if RNA-property described by this selected element is an animateable prop */
4074
 
                        if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) && RNA_property_animateable(&te->rnaptr, te->directdata)) {
4075
 
                                /* get id + path + index info from the selected element */
4076
 
                                tree_element_to_path(soops, te, tselem, 
4077
 
                                                &id, &path, &array_index, &flag, &groupmode);
4078
 
                        }
4079
 
                        
4080
 
                        /* only if ID and path were set, should we perform any actions */
4081
 
                        if (id && path) {
4082
 
                                /* action depends on mode */
4083
 
                                switch (mode) {
4084
 
                                        case KEYINGSET_EDITMODE_ADD:
4085
 
                                        {
4086
 
                                                /* add a new path with the information obtained (only if valid) */
4087
 
                                                // TODO: what do we do with group name? for now, we don't supply one, and just let this use the KeyingSet name
4088
 
                                                BKE_keyingset_add_path(ks, id, NULL, path, array_index, flag, groupmode);
4089
 
                                                ks->active_path= BLI_countlist(&ks->paths);
4090
 
                                        }
4091
 
                                                break;
4092
 
                                        case KEYINGSET_EDITMODE_REMOVE:
4093
 
                                        {
4094
 
                                                /* find the relevant path, then remove it from the KeyingSet */
4095
 
                                                KS_Path *ksp= BKE_keyingset_find_path(ks, id, NULL, path, array_index, groupmode);
4096
 
                                                
4097
 
                                                if (ksp) {
4098
 
                                                        /* free path's data */
4099
 
                                                        // TODO: we probably need an API method for this 
4100
 
                                                        if (ksp->rna_path) MEM_freeN(ksp->rna_path);
4101
 
                                                        ks->active_path= 0;
4102
 
                                                        
4103
 
                                                        /* remove path from set */
4104
 
                                                        BLI_freelinkN(&ks->paths, ksp);
4105
 
                                                }
4106
 
                                        }
4107
 
                                                break;
4108
 
                                }
4109
 
                                
4110
 
                                /* free path, since it had to be generated */
4111
 
                                MEM_freeN(path);
4112
 
                        }
4113
 
                }
4114
 
                
4115
 
                /* go over sub-tree */
4116
 
                if ((tselem->flag & TSE_CLOSED)==0)
4117
 
                        do_outliner_keyingset_editop(soops, ks, &te->subtree, mode);
4118
 
        }
4119
 
}
4120
 
 
4121
 
/* Add Operator ---------------------------------- */
4122
 
 
4123
 
static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
4124
 
{
4125
 
        SpaceOops *soutliner= CTX_wm_space_outliner(C);
4126
 
        Scene *scene= CTX_data_scene(C);
4127
 
        KeyingSet *ks= verify_active_keyingset(scene, 1);
4128
 
        
4129
 
        /* check for invalid states */
4130
 
        if (ks == NULL) {
4131
 
                BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Keying Set");
4132
 
                return OPERATOR_CANCELLED;
4133
 
        }
4134
 
        if (soutliner == NULL)
4135
 
                return OPERATOR_CANCELLED;
4136
 
        
4137
 
        /* recursively go into tree, adding selected items */
4138
 
        do_outliner_keyingset_editop(soutliner, ks, &soutliner->tree, KEYINGSET_EDITMODE_ADD);
4139
 
        
4140
 
        /* send notifiers */
4141
 
        WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
4142
 
        
4143
 
        return OPERATOR_FINISHED;
4144
 
}
4145
 
 
4146
 
void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot)
4147
 
{
4148
 
        /* identifiers */
4149
 
        ot->idname= "OUTLINER_OT_keyingset_add_selected";
4150
 
        ot->name= "Keyingset Add Selected";
4151
 
        
4152
 
        /* api callbacks */
4153
 
        ot->exec= outliner_keyingset_additems_exec;
4154
 
        ot->poll= ed_operator_outliner_datablocks_active;
4155
 
        
4156
 
        /* flags */
4157
 
        ot->flag = OPTYPE_UNDO;
4158
 
}
4159
 
 
4160
 
 
4161
 
/* Remove Operator ---------------------------------- */
4162
 
 
4163
 
static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *op)
4164
 
{
4165
 
        SpaceOops *soutliner= CTX_wm_space_outliner(C);
4166
 
        Scene *scene= CTX_data_scene(C);
4167
 
        KeyingSet *ks= verify_active_keyingset(scene, 1);
4168
 
        
4169
 
        /* check for invalid states */
4170
 
        if (soutliner == NULL)
4171
 
                return OPERATOR_CANCELLED;
4172
 
        
4173
 
        /* recursively go into tree, adding selected items */
4174
 
        do_outliner_keyingset_editop(soutliner, ks, &soutliner->tree, KEYINGSET_EDITMODE_REMOVE);
4175
 
        
4176
 
        /* send notifiers */
4177
 
        WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
4178
 
        
4179
 
        return OPERATOR_FINISHED;
4180
 
}
4181
 
 
4182
 
void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot)
4183
 
{
4184
 
        /* identifiers */
4185
 
        ot->idname= "OUTLINER_OT_keyingset_remove_selected";
4186
 
        ot->name= "Keyingset Remove Selected";
4187
 
        
4188
 
        /* api callbacks */
4189
 
        ot->exec= outliner_keyingset_removeitems_exec;
4190
 
        ot->poll= ed_operator_outliner_datablocks_active;
4191
 
        
4192
 
        /* flags */
4193
 
        ot->flag = OPTYPE_UNDO;
4194
 
}
4195
 
 
4196
 
/* ***************** DRAW *************** */
4197
 
 
4198
 
/* make function calls a bit compacter */
4199
 
struct DrawIconArg {
4200
 
        uiBlock *block;
4201
 
        ID *id;
4202
 
        int xmax, x, y;
4203
 
        float alpha;
4204
 
};
4205
 
 
4206
 
static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
4207
 
{
4208
 
        /* restrict collumn clip... it has been coded by simply overdrawing, doesnt work for buttons */
4209
 
        if(arg->x >= arg->xmax) 
4210
 
                UI_icon_draw(arg->x, arg->y, icon);
4211
 
        else {
4212
 
                uiBut *but= uiDefIconBut(arg->block, LABEL, 0, icon, arg->x-4, arg->y, ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH, NULL, 0.0, 0.0, 1.0, arg->alpha, (arg->id && arg->id->lib) ? arg->id->lib->name : "");
4213
 
                if(arg->id)
4214
 
                        uiButSetDragID(but, arg->id);
4215
 
        }
4216
 
 
4217
 
}
4218
 
 
4219
 
static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, float alpha)
4220
 
{
4221
 
        struct DrawIconArg arg;
4222
 
        
4223
 
        /* make function calls a bit compacter */
4224
 
        arg.block= block;
4225
 
        arg.id= tselem->id;
4226
 
        arg.xmax= xmax;
4227
 
        arg.x= x;
4228
 
        arg.y= y;
4229
 
        arg.alpha= alpha;
4230
 
        
4231
 
        if(tselem->type) {
4232
 
                switch( tselem->type) {
4233
 
                        case TSE_ANIM_DATA:
4234
 
                                UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx
4235
 
                        case TSE_NLA:
4236
 
                                UI_icon_draw(x, y, ICON_NLA); break;
4237
 
                        case TSE_NLA_TRACK:
4238
 
                                UI_icon_draw(x, y, ICON_NLA); break; // XXX
4239
 
                        case TSE_NLA_ACTION:
4240
 
                                UI_icon_draw(x, y, ICON_ACTION); break;
4241
 
                        case TSE_DEFGROUP_BASE:
4242
 
                                UI_icon_draw(x, y, ICON_GROUP_VERTEX); break;
4243
 
                        case TSE_BONE:
4244
 
                        case TSE_EBONE:
4245
 
                                UI_icon_draw(x, y, ICON_BONE_DATA); break;
4246
 
                        case TSE_CONSTRAINT_BASE:
4247
 
                                UI_icon_draw(x, y, ICON_CONSTRAINT); break;
4248
 
                        case TSE_MODIFIER_BASE:
4249
 
                                UI_icon_draw(x, y, ICON_MODIFIER); break;
4250
 
                        case TSE_LINKED_OB:
4251
 
                                UI_icon_draw(x, y, ICON_OBJECT_DATA); break;
4252
 
                        case TSE_LINKED_PSYS:
4253
 
                                UI_icon_draw(x, y, ICON_PARTICLES); break;
4254
 
                        case TSE_MODIFIER:
4255
 
                        {
4256
 
                                Object *ob= (Object *)tselem->id;
4257
 
                                ModifierData *md= BLI_findlink(&ob->modifiers, tselem->nr);
4258
 
                                switch(md->type) {
4259
 
                                        case eModifierType_Subsurf: 
4260
 
                                                UI_icon_draw(x, y, ICON_MOD_SUBSURF); break;
4261
 
                                        case eModifierType_Armature: 
4262
 
                                                UI_icon_draw(x, y, ICON_MOD_ARMATURE); break;
4263
 
                                        case eModifierType_Lattice: 
4264
 
                                                UI_icon_draw(x, y, ICON_MOD_LATTICE); break;
4265
 
                                        case eModifierType_Curve: 
4266
 
                                                UI_icon_draw(x, y, ICON_MOD_CURVE); break;
4267
 
                                        case eModifierType_Build: 
4268
 
                                                UI_icon_draw(x, y, ICON_MOD_BUILD); break;
4269
 
                                        case eModifierType_Mirror: 
4270
 
                                                UI_icon_draw(x, y, ICON_MOD_MIRROR); break;
4271
 
                                        case eModifierType_Decimate: 
4272
 
                                                UI_icon_draw(x, y, ICON_MOD_DECIM); break;
4273
 
                                        case eModifierType_Wave: 
4274
 
                                                UI_icon_draw(x, y, ICON_MOD_WAVE); break;
4275
 
                                        case eModifierType_Hook: 
4276
 
                                                UI_icon_draw(x, y, ICON_HOOK); break;
4277
 
                                        case eModifierType_Softbody: 
4278
 
                                                UI_icon_draw(x, y, ICON_MOD_SOFT); break;
4279
 
                                        case eModifierType_Boolean: 
4280
 
                                                UI_icon_draw(x, y, ICON_MOD_BOOLEAN); break;
4281
 
                                        case eModifierType_ParticleSystem: 
4282
 
                                                UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
4283
 
                                        case eModifierType_ParticleInstance:
4284
 
                                                UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
4285
 
                                        case eModifierType_EdgeSplit:
4286
 
                                                UI_icon_draw(x, y, ICON_MOD_EDGESPLIT); break;
4287
 
                                        case eModifierType_Array:
4288
 
                                                UI_icon_draw(x, y, ICON_MOD_ARRAY); break;
4289
 
                                        case eModifierType_UVProject:
4290
 
                                                UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break;
4291
 
                                        case eModifierType_Displace:
4292
 
                                                UI_icon_draw(x, y, ICON_MOD_DISPLACE); break;
4293
 
                                        case eModifierType_Shrinkwrap:
4294
 
                                                UI_icon_draw(x, y, ICON_MOD_SHRINKWRAP); break;
4295
 
                                        case eModifierType_Cast:
4296
 
                                                UI_icon_draw(x, y, ICON_MOD_CAST); break;
4297
 
                                        case eModifierType_MeshDeform:
4298
 
                                                UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break;
4299
 
                                        case eModifierType_Bevel:
4300
 
                                                UI_icon_draw(x, y, ICON_MOD_BEVEL); break;
4301
 
                                        case eModifierType_Smooth:
4302
 
                                                UI_icon_draw(x, y, ICON_MOD_SMOOTH); break;
4303
 
                                        case eModifierType_SimpleDeform:
4304
 
                                                UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break;
4305
 
                                        case eModifierType_Mask:
4306
 
                                                UI_icon_draw(x, y, ICON_MOD_MASK); break;
4307
 
                                        case eModifierType_Cloth:
4308
 
                                                UI_icon_draw(x, y, ICON_MOD_CLOTH); break;
4309
 
                                        case eModifierType_Explode:
4310
 
                                                UI_icon_draw(x, y, ICON_MOD_EXPLODE); break;
4311
 
                                        case eModifierType_Collision:
4312
 
                                                UI_icon_draw(x, y, ICON_MOD_PHYSICS); break;
4313
 
                                        case eModifierType_Fluidsim:
4314
 
                                                UI_icon_draw(x, y, ICON_MOD_FLUIDSIM); break;
4315
 
                                        case eModifierType_Multires:
4316
 
                                                UI_icon_draw(x, y, ICON_MOD_MULTIRES); break;
4317
 
                                        case eModifierType_Smoke:
4318
 
                                                UI_icon_draw(x, y, ICON_MOD_SMOKE); break;
4319
 
                                        case eModifierType_Solidify:
4320
 
                                                UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break;
4321
 
                                        case eModifierType_Screw:
4322
 
                                                UI_icon_draw(x, y, ICON_MOD_SCREW); break;
4323
 
                                        default:
4324
 
                                                UI_icon_draw(x, y, ICON_DOT); break;
4325
 
                                }
4326
 
                                break;
4327
 
                        }
4328
 
                        case TSE_SCRIPT_BASE:
4329
 
                                UI_icon_draw(x, y, ICON_TEXT); break;
4330
 
                        case TSE_POSE_BASE:
4331
 
                                UI_icon_draw(x, y, ICON_ARMATURE_DATA); break;
4332
 
                        case TSE_POSE_CHANNEL:
4333
 
                                UI_icon_draw(x, y, ICON_BONE_DATA); break;
4334
 
                        case TSE_PROXY:
4335
 
                                UI_icon_draw(x, y, ICON_GHOST); break;
4336
 
                        case TSE_R_LAYER_BASE:
4337
 
                                UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
4338
 
                        case TSE_R_LAYER:
4339
 
                                UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
4340
 
                        case TSE_LINKED_LAMP:
4341
 
                                UI_icon_draw(x, y, ICON_LAMP_DATA); break;
4342
 
                        case TSE_LINKED_MAT:
4343
 
                                UI_icon_draw(x, y, ICON_MATERIAL_DATA); break;
4344
 
                        case TSE_POSEGRP_BASE:
4345
 
                                UI_icon_draw(x, y, ICON_VERTEXSEL); break;
4346
 
                        case TSE_SEQUENCE:
4347
 
                                if(te->idcode==SEQ_MOVIE)
4348
 
                                        UI_icon_draw(x, y, ICON_SEQUENCE);
4349
 
                                else if(te->idcode==SEQ_META)
4350
 
                                        UI_icon_draw(x, y, ICON_DOT);
4351
 
                                else if(te->idcode==SEQ_SCENE)
4352
 
                                        UI_icon_draw(x, y, ICON_SCENE);
4353
 
                                else if(te->idcode==SEQ_SOUND)
4354
 
                                        UI_icon_draw(x, y, ICON_SOUND);
4355
 
                                else if(te->idcode==SEQ_IMAGE)
4356
 
                                        UI_icon_draw(x, y, ICON_IMAGE_COL);
4357
 
                                else
4358
 
                                        UI_icon_draw(x, y, ICON_PARTICLES);
4359
 
                                break;
4360
 
                        case TSE_SEQ_STRIP:
4361
 
                                UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT);
4362
 
                                break;
4363
 
                        case TSE_SEQUENCE_DUP:
4364
 
                                UI_icon_draw(x, y, ICON_OBJECT_DATA);
4365
 
                                break;
4366
 
                        case TSE_RNA_STRUCT:
4367
 
                                if(RNA_struct_is_ID(te->rnaptr.type)) {
4368
 
                                        arg.id= (ID *)te->rnaptr.data;
4369
 
                                        tselem_draw_icon_uibut(&arg, RNA_struct_ui_icon(te->rnaptr.type));
4370
 
                                }
4371
 
                                else
4372
 
                                        UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type));
4373
 
                                break;
4374
 
                        default:
4375
 
                                UI_icon_draw(x, y, ICON_DOT); break;
4376
 
                }
4377
 
        }
4378
 
        else if (GS(tselem->id->name) == ID_OB) {
4379
 
                Object *ob= (Object *)tselem->id;
4380
 
                switch (ob->type) {
4381
 
                        case OB_LAMP:
4382
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
4383
 
                        case OB_MESH: 
4384
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
4385
 
                        case OB_CAMERA: 
4386
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
4387
 
                        case OB_CURVE: 
4388
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
4389
 
                        case OB_MBALL: 
4390
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
4391
 
                        case OB_LATTICE: 
4392
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
4393
 
                        case OB_ARMATURE: 
4394
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
4395
 
                        case OB_FONT: 
4396
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
4397
 
                        case OB_SURF: 
4398
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
4399
 
                        case OB_EMPTY: 
4400
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
4401
 
                
4402
 
                }
4403
 
        }
4404
 
        else {
4405
 
                switch( GS(tselem->id->name)) {
4406
 
                        case ID_SCE:
4407
 
                                tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
4408
 
                        case ID_ME:
4409
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break;
4410
 
                        case ID_CU:
4411
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break;
4412
 
                        case ID_MB:
4413
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break;
4414
 
                        case ID_LT:
4415
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break;
4416
 
                        case ID_LA:
4417
 
                        {
4418
 
                                Lamp *la= (Lamp *)tselem->id;
4419
 
                                
4420
 
                                switch(la->type) {
4421
 
                                        case LA_LOCAL:
4422
 
                                                tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break;
4423
 
                                        case LA_SUN:
4424
 
                                                tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break;
4425
 
                                        case LA_SPOT:
4426
 
                                                tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break;
4427
 
                                        case LA_HEMI:
4428
 
                                                tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break;
4429
 
                                        case LA_AREA:
4430
 
                                                tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break;
4431
 
                                        default:
4432
 
                                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break;
4433
 
                                }
4434
 
                                break;
4435
 
                        }
4436
 
                        case ID_MA:
4437
 
                                tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break;
4438
 
                        case ID_TE:
4439
 
                                tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break;
4440
 
                        case ID_IM:
4441
 
                                tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break;
4442
 
                        case ID_SO:
4443
 
                                tselem_draw_icon_uibut(&arg, ICON_SPEAKER); break;
4444
 
                        case ID_AR:
4445
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break;
4446
 
                        case ID_CA:
4447
 
                                tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break;
4448
 
                        case ID_KE:
4449
 
                                tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break;
4450
 
                        case ID_WO:
4451
 
                                tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break;
4452
 
                        case ID_AC:
4453
 
                                tselem_draw_icon_uibut(&arg, ICON_ACTION); break;
4454
 
                        case ID_NLA:
4455
 
                                tselem_draw_icon_uibut(&arg, ICON_NLA); break;
4456
 
                        case ID_TXT:
4457
 
                                tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break;
4458
 
                        case ID_GR:
4459
 
                                tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
4460
 
                        case ID_LI:
4461
 
                                tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
4462
 
                }
4463
 
        }
4464
 
}
4465
 
 
4466
 
static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys)
4467
 
{
4468
 
        TreeElement *te;
4469
 
        TreeStoreElem *tselem;
4470
 
        int active;
4471
 
 
4472
 
        for(te= lb->first; te; te= te->next) {
4473
 
                
4474
 
                /* exit drawing early */
4475
 
                if((*offsx) - OL_X > xmax)
4476
 
                        break;
4477
 
 
4478
 
                tselem= TREESTORE(te);
4479
 
                
4480
 
                /* object hierarchy always, further constrained on level */
4481
 
                if(level<1 || (tselem->type==0 && te->idcode==ID_OB)) {
4482
 
 
4483
 
                        /* active blocks get white circle */
4484
 
                        active= 0;
4485
 
                        if(tselem->type==0) {
4486
 
                                if(te->idcode==ID_OB) active= (OBACT==(Object *)tselem->id);
4487
 
                                else if(scene->obedit && scene->obedit->data==tselem->id) active= 1;    // XXX use context?
4488
 
                                else active= tree_element_active(C, scene, soops, te, 0);
4489
 
                        }
4490
 
                        else active= tree_element_type_active(NULL, scene, soops, te, tselem, 0);
4491
 
                        
4492
 
                        if(active) {
4493
 
                                uiSetRoundBox(15);
4494
 
                                glColor4ub(255, 255, 255, 100);
4495
 
                                uiRoundBox( (float)*offsx-0.5f, (float)ys-1.0f, (float)*offsx+OL_H-3.0f, (float)ys+OL_H-3.0f, OL_H/2.0f-2.0f);
4496
 
                                glEnable(GL_BLEND); /* roundbox disables */
4497
 
                        }
4498
 
                        
4499
 
                        tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f);
4500
 
                        te->xs= (float)*offsx;
4501
 
                        te->ys= (float)ys;
4502
 
                        te->xend= (short)*offsx+OL_X;
4503
 
                        te->flag |= TE_ICONROW; // for click
4504
 
                        
4505
 
                        (*offsx) += OL_X;
4506
 
                }
4507
 
                
4508
 
                /* this tree element always has same amount of branches, so dont draw */
4509
 
                if(tselem->type!=TSE_R_LAYER)
4510
 
                        outliner_draw_iconrow(C, block, scene, soops, &te->subtree, level+1, xmax, offsx, ys);
4511
 
        }
4512
 
        
4513
 
}
4514
 
 
4515
 
static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty)
4516
 
{
4517
 
        TreeElement *ten;
4518
 
        TreeStoreElem *tselem;
4519
 
        int offsx= 0, active=0; // active=1 active obj, else active data
4520
 
        
4521
 
        tselem= TREESTORE(te);
4522
 
 
4523
 
        if(*starty+2*OL_H >= ar->v2d.cur.ymin && *starty<= ar->v2d.cur.ymax) {
4524
 
                int xmax= ar->v2d.cur.xmax;
4525
 
                
4526
 
                /* icons can be ui buts, we dont want it to overlap with restrict */
4527
 
                if((soops->flag & SO_HIDE_RESTRICTCOLS)==0)
4528
 
                        xmax-= OL_TOGW+ICON_DEFAULT_WIDTH;
4529
 
                
4530
 
                glEnable(GL_BLEND);
4531
 
 
4532
 
                /* colors for active/selected data */
4533
 
                if(tselem->type==0) {
4534
 
                        if(te->idcode==ID_SCE) {
4535
 
                                if(tselem->id == (ID *)scene) {
4536
 
                                        glColor4ub(255, 255, 255, 100);
4537
 
                                        active= 2;
4538
 
                                }
4539
 
                        }
4540
 
                        else if(te->idcode==ID_GR) {
4541
 
                                Group *gr = (Group *)tselem->id;
4542
 
 
4543
 
                                if(group_select_flag(gr)) {
4544
 
                                        char col[4];
4545
 
                                        UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
4546
 
                                        col[3]= 100;
4547
 
                                        glColor4ubv((GLubyte *)col);
4548
 
 
4549
 
                                        active= 2;
4550
 
                                }
4551
 
                        }
4552
 
                        else if(te->idcode==ID_OB) {
4553
 
                                Object *ob= (Object *)tselem->id;
4554
 
                                
4555
 
                                if(ob==OBACT || (ob->flag & SELECT)) {
4556
 
                                        char col[4];
4557
 
                                        
4558
 
                                        active= 2;
4559
 
                                        if(ob==OBACT) {
4560
 
                                                UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
4561
 
                                                /* so black text is drawn when active and not selected */
4562
 
                                                if (ob->flag & SELECT) active= 1;
4563
 
                                        }
4564
 
                                        else UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
4565
 
                                        col[3]= 100;
4566
 
                                        glColor4ubv((GLubyte *)col);
4567
 
                                }
4568
 
 
4569
 
                        }
4570
 
                        else if(scene->obedit && scene->obedit->data==tselem->id) {
4571
 
                                glColor4ub(255, 255, 255, 100);
4572
 
                                active= 2;
4573
 
                        }
4574
 
                        else {
4575
 
                                if(tree_element_active(C, scene, soops, te, 0)) {
4576
 
                                        glColor4ub(220, 220, 255, 100);
4577
 
                                        active= 2;
4578
 
                                }
4579
 
                        }
4580
 
                }
4581
 
                else {
4582
 
                        if( tree_element_type_active(NULL, scene, soops, te, tselem, 0) ) active= 2;
4583
 
                        glColor4ub(220, 220, 255, 100);
4584
 
                }
4585
 
                
4586
 
                /* active circle */
4587
 
                if(active) {
4588
 
                        uiSetRoundBox(15);
4589
 
                        uiRoundBox( (float)startx+OL_H-1.5f, (float)*starty+2.0f, (float)startx+2.0f*OL_H-4.0f, (float)*starty+OL_H-1.0f, OL_H/2.0f-2.0f);
4590
 
                        glEnable(GL_BLEND);     /* roundbox disables it */
4591
 
                        
4592
 
                        te->flag |= TE_ACTIVE; // for lookup in display hierarchies
4593
 
                }
4594
 
                
4595
 
                /* open/close icon, only when sublevels, except for scene */
4596
 
                if(te->subtree.first || (tselem->type==0 && te->idcode==ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
4597
 
                        int icon_x;
4598
 
                        if(tselem->type==0 && ELEM(te->idcode, ID_OB, ID_SCE))
4599
 
                                icon_x = startx;
4600
 
                        else
4601
 
                                icon_x = startx+5;
4602
 
 
4603
 
                                // icons a bit higher
4604
 
                        if(tselem->flag & TSE_CLOSED) 
4605
 
                                UI_icon_draw((float)icon_x, (float)*starty+2, ICON_DISCLOSURE_TRI_RIGHT);
4606
 
                        else
4607
 
                                UI_icon_draw((float)icon_x, (float)*starty+2, ICON_DISCLOSURE_TRI_DOWN);
4608
 
                }
4609
 
                offsx+= OL_X;
4610
 
                
4611
 
                /* datatype icon */
4612
 
                
4613
 
                if(!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
4614
 
                        // icons a bit higher
4615
 
                        tselem_draw_icon(block, xmax, (float)startx+offsx, (float)*starty+2, tselem, te, 1.0f);
4616
 
                        
4617
 
                        offsx+= OL_X;
4618
 
                }
4619
 
                else
4620
 
                        offsx+= 2;
4621
 
                
4622
 
                if(tselem->type==0 && tselem->id->lib) {
4623
 
                        glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
4624
 
                        if(tselem->id->flag & LIB_INDIRECT)
4625
 
                                UI_icon_draw((float)startx+offsx, (float)*starty+2, ICON_LIBRARY_DATA_INDIRECT);
4626
 
                        else
4627
 
                                UI_icon_draw((float)startx+offsx, (float)*starty+2, ICON_LIBRARY_DATA_DIRECT);
4628
 
                        glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
4629
 
                        offsx+= OL_X;
4630
 
                }               
4631
 
                glDisable(GL_BLEND);
4632
 
 
4633
 
                /* name */
4634
 
                if(active==1) UI_ThemeColor(TH_TEXT_HI);
4635
 
                else if(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
4636
 
                else UI_ThemeColor(TH_TEXT);
4637
 
                
4638
 
                UI_DrawString(startx+offsx, *starty+5, te->name);
4639
 
                
4640
 
                offsx+= (int)(OL_X + UI_GetStringWidth(te->name));
4641
 
                
4642
 
                /* closed item, we draw the icons, not when it's a scene, or master-server list though */
4643
 
                if(tselem->flag & TSE_CLOSED) {
4644
 
                        if(te->subtree.first) {
4645
 
                                if(tselem->type==0 && te->idcode==ID_SCE);
4646
 
                                else if(tselem->type!=TSE_R_LAYER) { /* this tree element always has same amount of branches, so dont draw */
4647
 
                                        int tempx= startx+offsx;
4648
 
                                        
4649
 
                                        // divider
4650
 
                                        UI_ThemeColorShade(TH_BACK, -40);
4651
 
                                        glRecti(tempx -10, *starty+4, tempx -8, *starty+OL_H-4);
4652
 
 
4653
 
                                        glEnable(GL_BLEND);
4654
 
                                        glPixelTransferf(GL_ALPHA_SCALE, 0.5);
4655
 
 
4656
 
                                        outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty+2);
4657
 
 
4658
 
                                        glPixelTransferf(GL_ALPHA_SCALE, 1.0);
4659
 
                                        glDisable(GL_BLEND);
4660
 
                                }
4661
 
                        }
4662
 
                }
4663
 
        }       
4664
 
        /* store coord and continue, we need coordinates for elements outside view too */
4665
 
        te->xs= (float)startx;
4666
 
        te->ys= (float)*starty;
4667
 
        te->xend= startx+offsx;
4668
 
                
4669
 
        *starty-= OL_H;
4670
 
 
4671
 
        if((tselem->flag & TSE_CLOSED)==0) {
4672
 
                for(ten= te->subtree.first; ten; ten= ten->next) {
4673
 
                        outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx+OL_X, starty);
4674
 
                }
4675
 
        }       
4676
 
}
4677
 
 
4678
 
static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, int *starty)
4679
 
{
4680
 
        TreeElement *te;
4681
 
        TreeStoreElem *tselem;
4682
 
        int y1, y2;
4683
 
        
4684
 
        if(lb->first==NULL) return;
4685
 
        
4686
 
        y1=y2= *starty; /* for vertical lines between objects */
4687
 
        for(te=lb->first; te; te= te->next) {
4688
 
                y2= *starty;
4689
 
                tselem= TREESTORE(te);
4690
 
                
4691
 
                /* horizontal line? */
4692
 
                if(tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE))
4693
 
                        glRecti(startx, *starty, startx+OL_X, *starty-1);
4694
 
                        
4695
 
                *starty-= OL_H;
4696
 
                
4697
 
                if((tselem->flag & TSE_CLOSED)==0)
4698
 
                        outliner_draw_hierarchy(soops, &te->subtree, startx+OL_X, starty);
4699
 
        }
4700
 
        
4701
 
        /* vertical line */
4702
 
        te= lb->last;
4703
 
        if(te->parent || lb->first!=lb->last) {
4704
 
                tselem= TREESTORE(te);
4705
 
                if(tselem->type==0 && te->idcode==ID_OB) {
4706
 
                        
4707
 
                        glRecti(startx, y1+OL_H, startx+1, y2);
4708
 
                }
4709
 
        }
4710
 
}
4711
 
 
4712
 
static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) 
4713
 
{
4714
 
        TreeElement *te;
4715
 
        TreeStoreElem *tselem;
4716
 
        
4717
 
        for(te= lb->first; te; te= te->next) {
4718
 
                tselem= TREESTORE(te);
4719
 
                
4720
 
                /* selection status */
4721
 
                if((tselem->flag & TSE_CLOSED)==0)
4722
 
                        if(tselem->type == TSE_RNA_STRUCT)
4723
 
                                glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+OL_H-1);
4724
 
 
4725
 
                *starty-= OL_H;
4726
 
                if((tselem->flag & TSE_CLOSED)==0) {
4727
 
                        outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
4728
 
                        if(tselem->type == TSE_RNA_STRUCT)
4729
 
                                fdrawline(0, (float)*starty+OL_H-1, ar->v2d.cur.xmax, (float)*starty+OL_H-1);
4730
 
                }
4731
 
        }
4732
 
}
4733
 
 
4734
 
static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) 
4735
 
{
4736
 
        TreeElement *te;
4737
 
        TreeStoreElem *tselem;
4738
 
        
4739
 
        for(te= lb->first; te; te= te->next) {
4740
 
                tselem= TREESTORE(te);
4741
 
                
4742
 
                /* selection status */
4743
 
                if(tselem->flag & TSE_SELECTED) {
4744
 
                        glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+OL_H-1);
4745
 
                }
4746
 
                *starty-= OL_H;
4747
 
                if((tselem->flag & TSE_CLOSED)==0) outliner_draw_selection(ar, soops, &te->subtree, starty);
4748
 
        }
4749
 
}
4750
 
 
4751
 
 
4752
 
static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops)
4753
 
{
4754
 
        TreeElement *te;
4755
 
        int starty, startx;
4756
 
        float col[4];
4757
 
                
4758
 
        glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); // only once
4759
 
        
4760
 
        if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
4761
 
                /* struct marks */
4762
 
                UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
4763
 
                //UI_ThemeColorShade(TH_BACK, -20);
4764
 
                starty= (int)ar->v2d.tot.ymax-OL_H;
4765
 
                outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
4766
 
        }
4767
 
        
4768
 
        /* always draw selection fill before hierarchy */
4769
 
        UI_GetThemeColor3fv(TH_BACK, col);
4770
 
        glColor3f(col[0]+0.06f, col[1]+0.08f, col[2]+0.10f);
4771
 
        starty= (int)ar->v2d.tot.ymax-OL_H;
4772
 
        outliner_draw_selection(ar, soops, &soops->tree, &starty);
4773
 
        
4774
 
        // grey hierarchy lines
4775
 
        UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.2f);
4776
 
        starty= (int)ar->v2d.tot.ymax-OL_H/2;
4777
 
        startx= 6;
4778
 
        outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
4779
 
        
4780
 
        // items themselves
4781
 
        starty= (int)ar->v2d.tot.ymax-OL_H;
4782
 
        startx= 0;
4783
 
        for(te= soops->tree.first; te; te= te->next) {
4784
 
                outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty);
4785
 
        }
4786
 
}
4787
 
 
4788
 
 
4789
 
static void outliner_back(ARegion *ar, SpaceOops *soops)
4790
 
{
4791
 
        int ystart;
4792
 
        
4793
 
        UI_ThemeColorShade(TH_BACK, 6);
4794
 
        ystart= (int)ar->v2d.tot.ymax;
4795
 
        ystart= OL_H*(ystart/(OL_H));
4796
 
        
4797
 
        while(ystart+2*OL_H > ar->v2d.cur.ymin) {
4798
 
                glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart+OL_H);
4799
 
                ystart-= 2*OL_H;
4800
 
        }
4801
 
}
4802
 
 
4803
 
static void outliner_draw_restrictcols(ARegion *ar, SpaceOops *soops)
4804
 
{
4805
 
        int ystart;
4806
 
        
4807
 
        /* background underneath */
4808
 
        UI_ThemeColor(TH_BACK);
4809
 
        glRecti((int)ar->v2d.cur.xmax-OL_TOGW, (int)ar->v2d.cur.ymin, (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax);
4810
 
        
4811
 
        UI_ThemeColorShade(TH_BACK, 6);
4812
 
        ystart= (int)ar->v2d.tot.ymax;
4813
 
        ystart= OL_H*(ystart/(OL_H));
4814
 
        
4815
 
        while(ystart+2*OL_H > ar->v2d.cur.ymin) {
4816
 
                glRecti((int)ar->v2d.cur.xmax-OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart+OL_H);
4817
 
                ystart-= 2*OL_H;
4818
 
        }
4819
 
        
4820
 
        UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
4821
 
 
4822
 
        /* view */
4823
 
        fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX,
4824
 
                ar->v2d.cur.ymax,
4825
 
                ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX,
4826
 
                ar->v2d.cur.ymin);
4827
 
 
4828
 
        /* render */
4829
 
        fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX,
4830
 
                ar->v2d.cur.ymax,
4831
 
                ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX,
4832
 
                ar->v2d.cur.ymin);
4833
 
 
4834
 
        /* render */
4835
 
        fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX,
4836
 
                ar->v2d.cur.ymax,
4837
 
                ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX,
4838
 
                ar->v2d.cur.ymin);
4839
 
}
4840
 
 
4841
 
static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
4842
 
{
4843
 
        Base *base;
4844
 
        Scene *scene = (Scene *)poin;
4845
 
        Object *ob = (Object *)poin2;
4846
 
        Object *obedit= CTX_data_edit_object(C);
4847
 
 
4848
 
        /* Don't allow hide an objet in edit mode,
4849
 
         * check the bug #22153 and #21609
4850
 
         */
4851
 
        if (obedit && obedit == ob) {
4852
 
                if (ob->restrictflag & OB_RESTRICT_VIEW)
4853
 
                        ob->restrictflag &= ~OB_RESTRICT_VIEW;
4854
 
                return;
4855
 
        }
4856
 
        
4857
 
        /* deselect objects that are invisible */
4858
 
        if (ob->restrictflag & OB_RESTRICT_VIEW) {
4859
 
        
4860
 
                /* Ouch! There is no backwards pointer from Object to Base, 
4861
 
                 * so have to do loop to find it. */
4862
 
                for(base= FIRSTBASE; base; base= base->next) {
4863
 
                        if(base->object==ob) {
4864
 
                                base->flag &= ~SELECT;
4865
 
                                base->object->flag= base->flag;
4866
 
                        }
4867
 
                }
4868
 
        }
4869
 
        WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
4870
 
 
4871
 
}
4872
 
 
4873
 
static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2)
4874
 
{
4875
 
        Base *base;
4876
 
        Scene *scene = (Scene *)poin;
4877
 
        Object *ob = (Object *)poin2;
4878
 
        
4879
 
        /* if select restriction has just been turned on */
4880
 
        if (ob->restrictflag & OB_RESTRICT_SELECT) {
4881
 
        
4882
 
                /* Ouch! There is no backwards pointer from Object to Base, 
4883
 
                 * so have to do loop to find it. */
4884
 
                for(base= FIRSTBASE; base; base= base->next) {
4885
 
                        if(base->object==ob) {
4886
 
                                base->flag &= ~SELECT;
4887
 
                                base->object->flag= base->flag;
4888
 
                        }
4889
 
                }
4890
 
        }
4891
 
        WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
4892
 
 
4893
 
}
4894
 
 
4895
 
static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2)
4896
 
{
4897
 
        WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, poin);
4898
 
}
4899
 
 
4900
 
static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *poin2)
4901
 
{
4902
 
        WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, poin);
4903
 
}
4904
 
 
4905
 
static void restrictbutton_modifier_cb(bContext *C, void *poin, void *poin2)
4906
 
{
4907
 
        Object *ob = (Object *)poin2;
4908
 
        
4909
 
        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
4910
 
 
4911
 
        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
4912
 
}
4913
 
 
4914
 
static void restrictbutton_bone_cb(bContext *C, void *poin, void *poin2)
4915
 
{
4916
 
        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
4917
 
}
4918
 
 
4919
 
 
4920
 
static int group_restrict_flag(Group *gr, int flag)
4921
 
{
4922
 
        GroupObject *gob;
4923
 
 
4924
 
        for(gob= gr->gobject.first; gob; gob= gob->next) {
4925
 
                if((gob->ob->restrictflag & flag) == 0)
4926
 
                        return 0;
4927
 
        }
4928
 
 
4929
 
        return 1;
4930
 
}
4931
 
 
4932
 
static int group_select_flag(Group *gr)
4933
 
{
4934
 
        GroupObject *gob;
4935
 
 
4936
 
        for(gob= gr->gobject.first; gob; gob= gob->next)
4937
 
                if((gob->ob->flag & SELECT))
4938
 
                        return 1;
4939
 
 
4940
 
        return 0;
4941
 
}
4942
 
 
4943
 
static void restrictbutton_gr_restrict_flag(bContext *C, void *poin, void *poin2, int flag)
4944
 
{       
4945
 
        Scene *scene = (Scene *)poin;           
4946
 
        GroupObject *gob;
4947
 
        Group *gr = (Group *)poin2;     
4948
 
 
4949
 
        if(group_restrict_flag(gr, flag)) {
4950
 
                for(gob= gr->gobject.first; gob; gob= gob->next) {
4951
 
                        gob->ob->restrictflag &= ~flag;
4952
 
 
4953
 
                        if(flag==OB_RESTRICT_VIEW)
4954
 
                                if(gob->ob->flag & SELECT)
4955
 
                                        ED_base_object_select(object_in_scene(gob->ob, scene), BA_DESELECT);
4956
 
                }
4957
 
        }
4958
 
        else {
4959
 
                for(gob= gr->gobject.first; gob; gob= gob->next) {
4960
 
                        gob->ob->restrictflag |= flag;
4961
 
 
4962
 
                        if(flag==OB_RESTRICT_VIEW)
4963
 
                                if((gob->ob->flag & SELECT) == 0)
4964
 
                                        ED_base_object_select(object_in_scene(gob->ob, scene), BA_SELECT);
4965
 
                }
4966
 
        }
4967
 
4968
 
 
4969
 
static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2)
4970
 
{
4971
 
        restrictbutton_gr_restrict_flag(C, poin, poin2, OB_RESTRICT_VIEW);
4972
 
        WM_event_add_notifier(C, NC_GROUP, NULL);
4973
 
}
4974
 
static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2)
4975
 
{
4976
 
        restrictbutton_gr_restrict_flag(C, poin, poin2, OB_RESTRICT_SELECT);
4977
 
        WM_event_add_notifier(C, NC_GROUP, NULL);
4978
 
}
4979
 
static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poin2)
4980
 
{
4981
 
        restrictbutton_gr_restrict_flag(C, poin, poin2, OB_RESTRICT_RENDER);
4982
 
        WM_event_add_notifier(C, NC_GROUP, NULL);
4983
 
}
4984
 
 
4985
 
 
4986
 
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
4987
 
{
4988
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
4989
 
        Scene *scene= CTX_data_scene(C);
4990
 
        Object *obedit= CTX_data_edit_object(C);
4991
 
        TreeStore *ts= soops->treestore;
4992
 
        TreeStoreElem *tselem= tsep;
4993
 
        
4994
 
        if(ts && tselem) {
4995
 
                TreeElement *te= outliner_find_tse(soops, tselem);
4996
 
                
4997
 
                if(tselem->type==0) {
4998
 
                        test_idbutton(tselem->id->name+2);      // library.c, unique name and alpha sort
4999
 
                        
5000
 
                        switch(GS(tselem->id->name)) {
5001
 
                                case ID_MA:
5002
 
                                        WM_event_add_notifier(C, NC_MATERIAL, NULL); break;
5003
 
                                case ID_TE:
5004
 
                                        WM_event_add_notifier(C, NC_TEXTURE, NULL); break;
5005
 
                                case ID_IM:
5006
 
                                        WM_event_add_notifier(C, NC_IMAGE, NULL); break;
5007
 
                                case ID_SCE:
5008
 
                                        WM_event_add_notifier(C, NC_SCENE, NULL); break;
5009
 
                                default:
5010
 
                                        WM_event_add_notifier(C, NC_ID|NA_RENAME, NULL); break;
5011
 
                        }                                       
5012
 
                        /* Check the library target exists */
5013
 
                        if (te->idcode == ID_LI) {
5014
 
                                char expanded[FILE_MAXDIR + FILE_MAXFILE];
5015
 
                                BLI_strncpy(expanded, ((Library *)tselem->id)->name, FILE_MAXDIR + FILE_MAXFILE);
5016
 
                                BLI_path_abs(expanded, G.sce);
5017
 
                                if (!BLI_exists(expanded)) {
5018
 
                                        error("This path does not exist, correct this before saving");
5019
 
                                }
5020
 
                        }
5021
 
                }
5022
 
                else {
5023
 
                        switch(tselem->type) {
5024
 
                        case TSE_DEFGROUP:
5025
 
                                defgroup_unique_name(te->directdata, (Object *)tselem->id); //  id = object
5026
 
                                break;
5027
 
                        case TSE_NLA_ACTION:
5028
 
                                test_idbutton(tselem->id->name+2);
5029
 
                                break;
5030
 
                        case TSE_EBONE:
5031
 
                        {
5032
 
                                bArmature *arm= (bArmature *)tselem->id;
5033
 
                                if(arm->edbo) {
5034
 
                                        EditBone *ebone= te->directdata;
5035
 
                                        char newname[32];
5036
 
                                        
5037
 
                                        /* restore bone name */
5038
 
                                        BLI_strncpy(newname, ebone->name, 32);
5039
 
                                        BLI_strncpy(ebone->name, oldname, 32);
5040
 
                                        ED_armature_bone_rename(obedit->data, oldname, newname);
5041
 
                                        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, OBACT);
5042
 
                                }
5043
 
                        }
5044
 
                                break;
5045
 
 
5046
 
                        case TSE_BONE:
5047
 
                                {
5048
 
                                        Bone *bone= te->directdata;
5049
 
                                        Object *ob;
5050
 
                                        char newname[32];
5051
 
                                        
5052
 
                                        // always make current object active
5053
 
                                        tree_element_set_active_object(C, scene, soops, te, 1);
5054
 
                                        ob= OBACT;
5055
 
                                        
5056
 
                                        /* restore bone name */
5057
 
                                        BLI_strncpy(newname, bone->name, 32);
5058
 
                                        BLI_strncpy(bone->name, oldname, 32);
5059
 
                                        ED_armature_bone_rename(ob->data, oldname, newname);
5060
 
                                        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
5061
 
                                }
5062
 
                                break;
5063
 
                        case TSE_POSE_CHANNEL:
5064
 
                                {
5065
 
                                        bPoseChannel *pchan= te->directdata;
5066
 
                                        Object *ob;
5067
 
                                        char newname[32];
5068
 
                                        
5069
 
                                        // always make current object active
5070
 
                                        tree_element_set_active_object(C, scene, soops, te, 1);
5071
 
                                        ob= OBACT;
5072
 
                                        
5073
 
                                        /* restore bone name */
5074
 
                                        BLI_strncpy(newname, pchan->name, 32);
5075
 
                                        BLI_strncpy(pchan->name, oldname, 32);
5076
 
                                        ED_armature_bone_rename(ob->data, oldname, newname);
5077
 
                                        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
5078
 
                                }
5079
 
                                break;
5080
 
                        case TSE_POSEGRP:
5081
 
                                {
5082
 
                                        Object *ob= (Object *)tselem->id; // id = object
5083
 
                                        bActionGroup *grp= te->directdata;
5084
 
                                        
5085
 
                                        BLI_uniquename(&ob->pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name));
5086
 
                                        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
5087
 
                                }
5088
 
                                break;
5089
 
                        case TSE_R_LAYER:
5090
 
                                break;
5091
 
                        }
5092
 
                }
5093
 
                tselem->flag &= ~TSE_TEXTBUT;
5094
 
        }
5095
 
}
5096
 
 
5097
 
static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, ListBase *lb)
5098
 
{       
5099
 
        uiBut *bt;
5100
 
        TreeElement *te;
5101
 
        TreeStoreElem *tselem;
5102
 
        Object *ob = NULL;
5103
 
        Group  *gr = NULL;
5104
 
 
5105
 
        for(te= lb->first; te; te= te->next) {
5106
 
                tselem= TREESTORE(te);
5107
 
                if(te->ys+2*OL_H >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {   
5108
 
                        /* objects have toggle-able restriction flags */
5109
 
                        if(tselem->type==0 && te->idcode==ID_OB) {
5110
 
                                PointerRNA ptr;
5111
 
 
5112
 
                                ob = (Object *)tselem->id;
5113
 
                                RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr);
5114
 
                                
5115
 
                                uiBlockSetEmboss(block, UI_EMBOSSN);
5116
 
                                bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_VIEW_OFF,
5117
 
                                                          (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1,
5118
 
                                                          &ptr, "hide", -1, 0, 0, -1, -1, NULL);
5119
 
                                uiButSetFunc(bt, restrictbutton_view_cb, scene, ob);
5120
 
                                
5121
 
                                bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_SELECT_OFF,
5122
 
                                                                  (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1,
5123
 
                                                                  &ptr, "hide_select", -1, 0, 0, -1, -1, NULL);
5124
 
                                uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob);
5125
 
                                
5126
 
                                bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_RENDER_OFF,
5127
 
                                                                  (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (short)te->ys, 17, OL_H-1,
5128
 
                                                                  &ptr, "hide_render", -1, 0, 0, -1, -1, NULL);
5129
 
                                uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob);
5130
 
                                
5131
 
                                uiBlockSetEmboss(block, UI_EMBOSS);
5132
 
                                
5133
 
                        }
5134
 
                        if(tselem->type==0 && te->idcode==ID_GR){ 
5135
 
                                int restrict_bool;
5136
 
                                gr = (Group *)tselem->id;
5137
 
                                
5138
 
                                uiBlockSetEmboss(block, UI_EMBOSSN);
5139
 
 
5140
 
                                restrict_bool= group_restrict_flag(gr, OB_RESTRICT_VIEW);
5141
 
                                bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, 0, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
5142
 
                                uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr);
5143
 
 
5144
 
                                restrict_bool= group_restrict_flag(gr, OB_RESTRICT_SELECT);
5145
 
                                bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, 0, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
5146
 
                                uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr);
5147
 
 
5148
 
                                restrict_bool= group_restrict_flag(gr, OB_RESTRICT_RENDER);
5149
 
                                bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (short)te->ys, 17, OL_H-1, 0, 0, 0, 0, 0, "Restrict/Allow renderability");
5150
 
                                uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr);
5151
 
 
5152
 
                                uiBlockSetEmboss(block, UI_EMBOSS);
5153
 
                        }
5154
 
                        /* scene render layers and passes have toggle-able flags too! */
5155
 
                        else if(tselem->type==TSE_R_LAYER) {
5156
 
                                uiBlockSetEmboss(block, UI_EMBOSSN);
5157
 
                                
5158
 
                                bt= uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT-1, 
5159
 
                                                                         (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
5160
 
                                uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
5161
 
                                
5162
 
                                uiBlockSetEmboss(block, UI_EMBOSS);
5163
 
                        }
5164
 
                        else if(tselem->type==TSE_R_PASS) {
5165
 
                                int *layflag= te->directdata;
5166
 
                                int passflag= 1<<tselem->nr;
5167
 
                                
5168
 
                                uiBlockSetEmboss(block, UI_EMBOSSN);
5169
 
                                
5170
 
                                
5171
 
                                bt= uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT-1, 
5172
 
                                                                         (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, layflag, 0, 0, 0, 0, "Render this Pass");
5173
 
                                uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
5174
 
                                
5175
 
                                layflag++;      /* is lay_xor */
5176
 
                                if(ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT, SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
5177
 
                                        bt= uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag)?ICON_DOT:ICON_BLANK1, 
5178
 
                                                                         (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
5179
 
                                uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
5180
 
                                
5181
 
                                uiBlockSetEmboss(block, UI_EMBOSS);
5182
 
                        }
5183
 
                        else if(tselem->type==TSE_MODIFIER)  {
5184
 
                                ModifierData *md= (ModifierData *)te->directdata;
5185
 
                                ob = (Object *)tselem->id;
5186
 
                                
5187
 
                                uiBlockSetEmboss(block, UI_EMBOSSN);
5188
 
                                bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF, 
5189
 
                                                (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
5190
 
                                uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
5191
 
                                
5192
 
                                bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF, 
5193
 
                                                (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (short)te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
5194
 
                                uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
5195
 
                        }
5196
 
                        else if(tselem->type==TSE_POSE_CHANNEL)  {
5197
 
                                bPoseChannel *pchan= (bPoseChannel *)te->directdata;
5198
 
                                Bone *bone = pchan->bone;
5199
 
                                
5200
 
                                uiBlockSetEmboss(block, UI_EMBOSSN);
5201
 
                                bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF, 
5202
 
                                                (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
5203
 
                                uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
5204
 
                                
5205
 
                                bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, 
5206
 
                                                (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
5207
 
                                uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
5208
 
                        }
5209
 
                        else if(tselem->type==TSE_EBONE)  {
5210
 
                                EditBone *ebone= (EditBone *)te->directdata;
5211
 
                                
5212
 
                                uiBlockSetEmboss(block, UI_EMBOSSN);
5213
 
                                bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF, 
5214
 
                                                (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
5215
 
                                uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
5216
 
                                
5217
 
                                bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, 
5218
 
                                                (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
5219
 
                                uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
5220
 
                        }
5221
 
                }
5222
 
                
5223
 
                if((tselem->flag & TSE_CLOSED)==0) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
5224
 
        }
5225
 
}
5226
 
 
5227
 
static void outliner_draw_rnacols(ARegion *ar, SpaceOops *soops, int sizex)
5228
 
{
5229
 
        View2D *v2d= &ar->v2d;
5230
 
        
5231
 
        UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
5232
 
 
5233
 
        /* draw column separator lines */
5234
 
        fdrawline((float)sizex,
5235
 
                v2d->cur.ymax,
5236
 
                (float)sizex,
5237
 
                v2d->cur.ymin);
5238
 
 
5239
 
        fdrawline((float)sizex+OL_RNA_COL_SIZEX,
5240
 
                v2d->cur.ymax,
5241
 
                (float)sizex+OL_RNA_COL_SIZEX,
5242
 
                v2d->cur.ymin);
5243
 
}
5244
 
 
5245
 
static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
5246
 
{       
5247
 
        TreeElement *te;
5248
 
        TreeStoreElem *tselem;
5249
 
        PointerRNA *ptr;
5250
 
        PropertyRNA *prop;
5251
 
        
5252
 
        uiBlockSetEmboss(block, UI_EMBOSST);
5253
 
 
5254
 
        for(te= lb->first; te; te= te->next) {
5255
 
                tselem= TREESTORE(te);
5256
 
                if(te->ys+2*OL_H >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {   
5257
 
                        if(tselem->type == TSE_RNA_PROPERTY) {
5258
 
                                ptr= &te->rnaptr;
5259
 
                                prop= te->directdata;
5260
 
                                
5261
 
                                if(!(RNA_property_type(prop) == PROP_POINTER && (tselem->flag & TSE_CLOSED)==0))
5262
 
                                        uiDefAutoButR(block, ptr, prop, -1, "", 0, sizex, (int)te->ys, OL_RNA_COL_SIZEX, OL_H-1);
5263
 
                        }
5264
 
                        else if(tselem->type == TSE_RNA_ARRAY_ELEM) {
5265
 
                                ptr= &te->rnaptr;
5266
 
                                prop= te->directdata;
5267
 
                                
5268
 
                                uiDefAutoButR(block, ptr, prop, te->index, "", 0, sizex, (int)te->ys, OL_RNA_COL_SIZEX, OL_H-1);
5269
 
                        }
5270
 
                }
5271
 
                
5272
 
                if((tselem->flag & TSE_CLOSED)==0) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
5273
 
        }
5274
 
}
5275
 
 
5276
 
static void operator_call_cb(struct bContext *C, void *arg_kmi, void *arg2)
5277
 
{
5278
 
        wmOperatorType *ot= arg2;
5279
 
        wmKeyMapItem *kmi= arg_kmi;
5280
 
        
5281
 
        if(ot)
5282
 
                BLI_strncpy(kmi->idname, ot->idname, OP_MAX_TYPENAME);
5283
 
}
5284
 
 
5285
 
static void operator_search_cb(const struct bContext *C, void *arg_kmi, char *str, uiSearchItems *items)
5286
 
{
5287
 
        wmOperatorType *ot = WM_operatortype_first();
5288
 
        
5289
 
        for(; ot; ot= ot->next) {
5290
 
                
5291
 
                if(BLI_strcasestr(ot->idname, str)) {
5292
 
                        char name[OP_MAX_TYPENAME];
5293
 
                        
5294
 
                        /* display name for menu */
5295
 
                        WM_operator_py_idname(name, ot->idname);
5296
 
                        
5297
 
                        if(0==uiSearchItemAdd(items, name, ot, 0))
5298
 
                                break;
5299
 
                }
5300
 
        }
5301
 
}
5302
 
 
5303
 
/* operator Search browse menu, open */
5304
 
static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi)
5305
 
{
5306
 
        static char search[OP_MAX_TYPENAME];
5307
 
        wmEvent event;
5308
 
        wmWindow *win= CTX_wm_window(C);
5309
 
        wmKeyMapItem *kmi= arg_kmi;
5310
 
        wmOperatorType *ot= WM_operatortype_find(kmi->idname, 0);
5311
 
        uiBlock *block;
5312
 
        uiBut *but;
5313
 
        
5314
 
        /* clear initial search string, then all items show */
5315
 
        search[0]= 0;
5316
 
        
5317
 
        block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
5318
 
        uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
5319
 
        
5320
 
        /* fake button, it holds space for search items */
5321
 
        uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
5322
 
        
5323
 
        but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, "");
5324
 
        uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot);
5325
 
        
5326
 
        uiBoundsBlock(block, 6);
5327
 
        uiBlockSetDirection(block, UI_DOWN);    
5328
 
        uiEndBlock(C, block);
5329
 
        
5330
 
        event= *(win->eventstate);      /* XXX huh huh? make api call */
5331
 
        event.type= EVT_BUT_OPEN;
5332
 
        event.val= KM_PRESS;
5333
 
        event.customdata= but;
5334
 
        event.customdatafree= FALSE;
5335
 
        wm_event_add(win, &event);
5336
 
        
5337
 
        return block;
5338
 
}
5339
 
 
5340
 
#define OL_KM_KEYBOARD          0
5341
 
#define OL_KM_MOUSE                     1
5342
 
#define OL_KM_TWEAK                     2
5343
 
#define OL_KM_SPECIALS          3
5344
 
 
5345
 
static short keymap_menu_type(short type)
5346
 
{
5347
 
        if(ISKEYBOARD(type)) return OL_KM_KEYBOARD;
5348
 
        if(ISTWEAK(type)) return OL_KM_TWEAK;
5349
 
        if(ISMOUSE(type)) return OL_KM_MOUSE;
5350
 
//      return OL_KM_SPECIALS;
5351
 
        return 0;
5352
 
}
5353
 
 
5354
 
static char *keymap_type_menu(void)
5355
 
{
5356
 
        static char string[500];
5357
 
        static char formatstr[] = "|%s %%x%d";
5358
 
        char *str= string;
5359
 
        
5360
 
        str += sprintf(str, "Event Type %%t");
5361
 
        
5362
 
        str += sprintf(str, formatstr, "Keyboard", OL_KM_KEYBOARD);
5363
 
        str += sprintf(str, formatstr, "Mouse", OL_KM_MOUSE);
5364
 
        str += sprintf(str, formatstr, "Tweak", OL_KM_TWEAK);
5365
 
//      str += sprintf(str, formatstr, "Specials", OL_KM_SPECIALS);
5366
 
        
5367
 
        return string;
5368
 
}       
5369
 
 
5370
 
static char *keymap_mouse_menu(void)
5371
 
{
5372
 
        static char string[500];
5373
 
        static char formatstr[] = "|%s %%x%d";
5374
 
        char *str= string;
5375
 
        
5376
 
        str += sprintf(str, "Mouse Event %%t");
5377
 
        
5378
 
        str += sprintf(str, formatstr, "Left Mouse", LEFTMOUSE);
5379
 
        str += sprintf(str, formatstr, "Middle Mouse", MIDDLEMOUSE);
5380
 
        str += sprintf(str, formatstr, "Right Mouse", RIGHTMOUSE);
5381
 
        str += sprintf(str, formatstr, "Button4 Mouse ", BUTTON4MOUSE);
5382
 
        str += sprintf(str, formatstr, "Button5 Mouse ", BUTTON5MOUSE);
5383
 
        str += sprintf(str, formatstr, "Action Mouse", ACTIONMOUSE);
5384
 
        str += sprintf(str, formatstr, "Select Mouse", SELECTMOUSE);
5385
 
        str += sprintf(str, formatstr, "Mouse Move", MOUSEMOVE);
5386
 
        str += sprintf(str, formatstr, "Wheel Up", WHEELUPMOUSE);
5387
 
        str += sprintf(str, formatstr, "Wheel Down", WHEELDOWNMOUSE);
5388
 
        str += sprintf(str, formatstr, "Wheel In", WHEELINMOUSE);
5389
 
        str += sprintf(str, formatstr, "Wheel Out", WHEELOUTMOUSE);
5390
 
        str += sprintf(str, formatstr, "Mouse/Trackpad Pan", MOUSEPAN);
5391
 
        str += sprintf(str, formatstr, "Mouse/Trackpad Zoom", MOUSEZOOM);
5392
 
        str += sprintf(str, formatstr, "Mouse/Trackpad Rotate", MOUSEROTATE);
5393
 
        
5394
 
        return string;
5395
 
}
5396
 
 
5397
 
static char *keymap_tweak_menu(void)
5398
 
{
5399
 
        static char string[500];
5400
 
        static char formatstr[] = "|%s %%x%d";
5401
 
        char *str= string;
5402
 
        
5403
 
        str += sprintf(str, "Tweak Event %%t");
5404
 
        
5405
 
        str += sprintf(str, formatstr, "Left Mouse", EVT_TWEAK_L);
5406
 
        str += sprintf(str, formatstr, "Middle Mouse", EVT_TWEAK_M);
5407
 
        str += sprintf(str, formatstr, "Right Mouse", EVT_TWEAK_R);
5408
 
        str += sprintf(str, formatstr, "Action Mouse", EVT_TWEAK_A);
5409
 
        str += sprintf(str, formatstr, "Select Mouse", EVT_TWEAK_S);
5410
 
        
5411
 
        return string;
5412
 
}
5413
 
 
5414
 
static char *keymap_tweak_dir_menu(void)
5415
 
{
5416
 
        static char string[500];
5417
 
        static char formatstr[] = "|%s %%x%d";
5418
 
        char *str= string;
5419
 
        
5420
 
        str += sprintf(str, "Tweak Direction %%t");
5421
 
        
5422
 
        str += sprintf(str, formatstr, "Any", KM_ANY);
5423
 
        str += sprintf(str, formatstr, "North", EVT_GESTURE_N);
5424
 
        str += sprintf(str, formatstr, "North-East", EVT_GESTURE_NE);
5425
 
        str += sprintf(str, formatstr, "East", EVT_GESTURE_E);
5426
 
        str += sprintf(str, formatstr, "Sout-East", EVT_GESTURE_SE);
5427
 
        str += sprintf(str, formatstr, "South", EVT_GESTURE_S);
5428
 
        str += sprintf(str, formatstr, "South-West", EVT_GESTURE_SW);
5429
 
        str += sprintf(str, formatstr, "West", EVT_GESTURE_W);
5430
 
        str += sprintf(str, formatstr, "North-West", EVT_GESTURE_NW);
5431
 
        
5432
 
        return string;
5433
 
}
5434
 
 
5435
 
 
5436
 
static void keymap_type_cb(bContext *C, void *kmi_v, void *unused_v)
5437
 
{
5438
 
        wmKeyMapItem *kmi= kmi_v;
5439
 
        short maptype= keymap_menu_type(kmi->type);
5440
 
        
5441
 
        if(maptype!=kmi->maptype) {
5442
 
                switch(kmi->maptype) {
5443
 
                        case OL_KM_KEYBOARD:
5444
 
                                kmi->type= AKEY;
5445
 
                                kmi->val= KM_PRESS;
5446
 
                                break;
5447
 
                        case OL_KM_MOUSE:
5448
 
                                kmi->type= LEFTMOUSE;
5449
 
                                kmi->val= KM_PRESS;
5450
 
                                break;
5451
 
                        case OL_KM_TWEAK:
5452
 
                                kmi->type= EVT_TWEAK_L;
5453
 
                                kmi->val= KM_ANY;
5454
 
                                break;
5455
 
                        case OL_KM_SPECIALS:
5456
 
                                kmi->type= AKEY;
5457
 
                                kmi->val= KM_PRESS;
5458
 
                }
5459
 
                ED_region_tag_redraw(CTX_wm_region(C));
5460
 
        }
5461
 
}
5462
 
 
5463
 
static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
5464
 
{
5465
 
        TreeElement *te;
5466
 
        TreeStoreElem *tselem;
5467
 
        
5468
 
        uiBlockSetEmboss(block, UI_EMBOSST);
5469
 
        
5470
 
        for(te= lb->first; te; te= te->next) {
5471
 
                tselem= TREESTORE(te);
5472
 
                if(te->ys+2*OL_H >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
5473
 
                        uiBut *but;
5474
 
                        char *str;
5475
 
                        int xstart= 240;
5476
 
                        int butw1= 20; /* operator */
5477
 
                        int butw2= 90; /* event type, menus */
5478
 
                        int butw3= 43; /* modifiers */
5479
 
 
5480
 
                        if(tselem->type == TSE_KEYMAP_ITEM) {
5481
 
                                wmKeyMapItem *kmi= te->directdata;
5482
 
                                
5483
 
                                /* modal map? */
5484
 
                                if(kmi->propvalue);
5485
 
                                else {
5486
 
                                        uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys+1, butw1, OL_H-1, "Assign new Operator");
5487
 
                                }
5488
 
                                xstart+= butw1+10;
5489
 
                                
5490
 
                                /* map type button */
5491
 
                                kmi->maptype= keymap_menu_type(kmi->type);
5492
 
                                
5493
 
                                str= keymap_type_menu();
5494
 
                                but= uiDefButS(block, MENU, 0, str,     xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->maptype, 0, 0, 0, 0, "Event type");
5495
 
                                uiButSetFunc(but, keymap_type_cb, kmi, NULL);
5496
 
                                xstart+= butw2+5;
5497
 
                                
5498
 
                                /* edit actual event */
5499
 
                                switch(kmi->maptype) {
5500
 
                                        case OL_KM_KEYBOARD:
5501
 
                                                uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->type, "Key code");
5502
 
                                                xstart+= butw2+5;
5503
 
                                                break;
5504
 
                                        case OL_KM_MOUSE:
5505
 
                                                str= keymap_mouse_menu();
5506
 
                                                uiDefButS(block, MENU, 0, str, xstart,(int)te->ys+1, butw2, OL_H-1, &kmi->type, 0, 0, 0, 0,  "Mouse button");   
5507
 
                                                xstart+= butw2+5;
5508
 
                                                break;
5509
 
                                        case OL_KM_TWEAK:
5510
 
                                                str= keymap_tweak_menu();
5511
 
                                                uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->type, 0, 0, 0, 0,  "Tweak gesture"); 
5512
 
                                                xstart+= butw2+5;
5513
 
                                                str= keymap_tweak_dir_menu();
5514
 
                                                uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->val, 0, 0, 0, 0,  "Tweak gesture direction");        
5515
 
                                                xstart+= butw2+5;
5516
 
                                                break;
5517
 
                                }
5518
 
                                
5519
 
                                /* modifiers */
5520
 
                                uiDefButS(block, OPTION, 0, "Shift",    xstart, (int)te->ys+1, butw3+5, OL_H-1, &kmi->shift, 0, 0, 0, 0, "Modifier"); xstart+= butw3+5;
5521
 
                                uiDefButS(block, OPTION, 0, "Ctrl",     xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->ctrl, 0, 0, 0, 0, "Modifier"); xstart+= butw3;
5522
 
                                uiDefButS(block, OPTION, 0, "Alt",      xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->alt, 0, 0, 0, 0, "Modifier"); xstart+= butw3;
5523
 
                                uiDefButS(block, OPTION, 0, "Cmd",      xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->oskey, 0, 0, 0, 0, "Modifier"); xstart+= butw3;
5524
 
                                xstart+= 5;
5525
 
                                uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->keymodifier, "Key Modifier code");
5526
 
                                xstart+= butw3+5;
5527
 
                                
5528
 
                                /* rna property */
5529
 
                                if(kmi->ptr && kmi->ptr->data)
5530
 
                                        uiDefBut(block, LABEL, 0, "(RNA property)",     xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->oskey, 0, 0, 0, 0, ""); xstart+= butw2;
5531
 
                                        
5532
 
                                
5533
 
                        }
5534
 
                }
5535
 
                
5536
 
                if((tselem->flag & TSE_CLOSED)==0) outliner_draw_keymapbuts(block, ar, soops, &te->subtree);
5537
 
        }
5538
 
}
5539
 
 
5540
 
 
5541
 
static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
5542
 
{
5543
 
        uiBut *bt;
5544
 
        TreeElement *te;
5545
 
        TreeStoreElem *tselem;
5546
 
        int dx, len;
5547
 
        
5548
 
        for(te= lb->first; te; te= te->next) {
5549
 
                tselem= TREESTORE(te);
5550
 
                if(te->ys+2*OL_H >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
5551
 
                        
5552
 
                        if(tselem->flag & TSE_TEXTBUT) {
5553
 
                                
5554
 
                                /* If we add support to rename Sequence.
5555
 
                                 * need change this.
5556
 
                                 */
5557
 
                                if(tselem->type == TSE_POSE_BASE) continue; // prevent crash when trying to rename 'pose' entry of armature
5558
 
                                
5559
 
                                if(tselem->type==TSE_EBONE) len = sizeof(((EditBone*) 0)->name);
5560
 
                                else if (tselem->type==TSE_MODIFIER) len = sizeof(((ModifierData*) 0)->name);
5561
 
                                else if(tselem->id && GS(tselem->id->name)==ID_LI) len = sizeof(((Library*) 0)->name);
5562
 
                                else len= sizeof(((ID*) 0)->name)-2;
5563
 
                                
5564
 
 
5565
 
                                dx= (int)UI_GetStringWidth(te->name);
5566
 
                                if(dx<100) dx= 100;
5567
 
                                
5568
 
                                bt= uiDefBut(block, TEX, OL_NAMEBUTTON, "",  (short)te->xs+2*OL_X-4, (short)te->ys, dx+10, OL_H-1, te->name, 1.0, (float)len-1, 0, 0, "");
5569
 
                                uiButSetRenameFunc(bt, namebutton_cb, tselem);
5570
 
                                
5571
 
                                /* returns false if button got removed */
5572
 
                                if( 0 == uiButActiveOnly(C, block, bt) )
5573
 
                                        tselem->flag &= ~TSE_TEXTBUT;
5574
 
                        }
5575
 
                }
5576
 
                
5577
 
                if((tselem->flag & TSE_CLOSED)==0) outliner_buttons(C, block, ar, soops, &te->subtree);
5578
 
        }
5579
 
}
5580
 
 
5581
 
void draw_outliner(const bContext *C)
5582
 
{
5583
 
        Main *mainvar= CTX_data_main(C);
5584
 
        Scene *scene= CTX_data_scene(C);
5585
 
        ARegion *ar= CTX_wm_region(C);
5586
 
        View2D *v2d= &ar->v2d;
5587
 
        SpaceOops *soops= CTX_wm_space_outliner(C);
5588
 
        uiBlock *block;
5589
 
        int sizey= 0, sizex= 0, sizex_rna= 0;
5590
 
        
5591
 
        outliner_build_tree(mainvar, scene, soops); // always 
5592
 
        
5593
 
        /* get extents of data */
5594
 
        outliner_height(soops, &soops->tree, &sizey);
5595
 
 
5596
 
        if (ELEM3(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF, SO_KEYMAP)) {
5597
 
                /* RNA has two columns:
5598
 
                 *      - column 1 is (max_width + OL_RNA_COL_SPACEX) or
5599
 
                 *                               (OL_RNA_COL_X), whichever is wider...
5600
 
                 *      - column 2 is fixed at OL_RNA_COL_SIZEX
5601
 
                 *
5602
 
                 *  (*) XXX max width for now is a fixed factor of OL_X*(max_indention+100)
5603
 
                 */
5604
 
                 
5605
 
                /* get actual width of column 1 */
5606
 
                outliner_rna_width(soops, &soops->tree, &sizex_rna, 0);
5607
 
                sizex_rna= MAX2(OL_RNA_COLX, sizex_rna+OL_RNA_COL_SPACEX);
5608
 
                
5609
 
                /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
5610
 
                if (soops->outlinevis == SO_KEYMAP) 
5611
 
                        sizex= sizex_rna + OL_RNA_COL_SIZEX*3 + 50; // XXX this is only really a quick hack to make this wide enough...
5612
 
                else
5613
 
                        sizex= sizex_rna + OL_RNA_COL_SIZEX + 50;
5614
 
        }
5615
 
        else {
5616
 
                /* width must take into account restriction columns (if visible) so that entries will still be visible */
5617
 
                //outliner_width(soops, &soops->tree, &sizex);
5618
 
                outliner_rna_width(soops, &soops->tree, &sizex, 0); // XXX should use outliner_width instead when te->xend will be set correctly...
5619
 
                
5620
 
                /* constant offset for restriction columns */
5621
 
                // XXX this isn't that great yet...
5622
 
                if ((soops->flag & SO_HIDE_RESTRICTCOLS)==0)
5623
 
                        sizex += OL_TOGW*3;
5624
 
        }
5625
 
        
5626
 
        /* tweak to display last line (when list bigger than window) */
5627
 
        sizey += V2D_SCROLL_HEIGHT;
5628
 
        
5629
 
        /* update size of tot-rect (extents of data/viewable area) */
5630
 
        UI_view2d_totRect_set(v2d, sizex, sizey);
5631
 
 
5632
 
        /* set matrix for 2d-view controls */
5633
 
        UI_view2d_view_ortho(C, v2d);
5634
 
 
5635
 
        /* draw outliner stuff (background and hierachy lines) */
5636
 
        outliner_back(ar, soops);
5637
 
        block= uiBeginBlock(C, ar, "outliner buttons", UI_EMBOSS);
5638
 
        outliner_draw_tree((bContext *)C, block, scene, ar, soops);
5639
 
 
5640
 
        /* draw icons and names */
5641
 
        outliner_buttons(C, block, ar, soops, &soops->tree);
5642
 
        
5643
 
        if(ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
5644
 
                /* draw rna buttons */
5645
 
                outliner_draw_rnacols(ar, soops, sizex_rna);
5646
 
                outliner_draw_rnabuts(block, scene, ar, soops, sizex_rna, &soops->tree);
5647
 
        }
5648
 
        else if(soops->outlinevis == SO_KEYMAP) {
5649
 
                outliner_draw_keymapbuts(block, ar, soops, &soops->tree);
5650
 
        }
5651
 
        else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) {
5652
 
                /* draw restriction columns */
5653
 
                outliner_draw_restrictcols(ar, soops);
5654
 
                outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree);
5655
 
        }
5656
 
        
5657
 
        uiEndBlock(C, block);
5658
 
        uiDrawBlock(C, block);
5659
 
        
5660
 
        /* clear flag that allows quick redraws */
5661
 
        soops->storeflag &= ~SO_TREESTORE_REDRAW;
5662
 
}
5663