4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2008 Blender Foundation.
21 * All rights reserved.
24 * Contributor(s): Blender Foundation
26 * ***** END GPL LICENSE BLOCK *****
32 #include "DNA_color_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_space_types.h"
35 #include "DNA_scene_types.h"
36 #include "DNA_screen_types.h"
37 #include "DNA_space_types.h"
38 #include "DNA_texture_types.h"
39 #include "DNA_vec_types.h"
40 #include "DNA_windowmanager_types.h"
42 #include "MEM_guardedalloc.h"
44 #include "BLI_blenlib.h"
45 #include "BLI_arithb.h"
48 #include "BKE_colortools.h"
49 #include "BKE_global.h"
50 #include "BKE_screen.h"
51 #include "BKE_texture.h"
52 #include "BKE_utildefines.h"
60 #include "BIF_glutil.h"
62 #include "UI_interface.h"
64 #include "UI_resources.h"
65 #include "UI_view2d.h"
67 #include "RNA_access.h"
68 #include "RNA_types.h"
70 #include "outliner_intern.h"
72 #define SET_INT_IN_POINTER(i) ((void*)(intptr_t)(i))
73 #define GET_INT_FROM_POINTER(i) ((int)(intptr_t)(i))
76 #define COLUMN_WIDTH 150
78 typedef void (*uiTableCellFunc)(void *userdata, int row, int col, struct rcti *rct, struct uiBlock *block);
80 typedef struct uiTable {
84 uiTableCellFunc cellfunc;
88 uiTable *UI_table_create(int rows, int cols, rcti *rct, uiTableCellFunc cellfunc, void *userdata)
92 table= MEM_callocN(sizeof(uiTable), "uiTable");
94 table->cellfunc= cellfunc;
97 table->userdata= userdata;
102 void UI_table_free(uiTable *table)
107 void UI_table_draw(wmWindow *window, ARegion *region, uiTable *table)
117 block= uiBeginBlock(window, region, "table outliner", UI_EMBOSST, UI_HELV);
119 for(y=rct->ymax, row=0; y>rct->ymin; y-=ROW_HEIGHT, row++) {
121 UI_ThemeColorShade(TH_BACK, 6);
122 glRecti(v2d->cur.xmin, y-ROW_HEIGHT, v2d->cur.xmax, y);
125 if(row >= table->rows)
128 for(col=0; col<table->cols; col++) {
129 cellrct.xmin= rct->xmin+COLUMN_WIDTH*col + 1;
130 cellrct.xmax= rct->xmin+COLUMN_WIDTH*(col+1);
131 cellrct.ymin= y-ROW_HEIGHT;
134 table->cellfunc(table->userdata, row, col, &cellrct, block);
138 UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
140 for(col=0; col<table->cols; col++)
141 fdrawline(rct->xmin+COLUMN_WIDTH*(col+1), rct->ymin, rct->xmin+COLUMN_WIDTH*(col+1), rct->ymax);
148 /* ************************ main outliner area region *********************** */
150 typedef struct CellRNA {
157 CollectionPropertyIterator iter;
160 static void rna_back_cb(void *arg_buts, void *arg_unused)
162 SpaceOops *soutliner= arg_buts;
165 newpath= RNA_path_back(soutliner->rnapath);
166 if(soutliner->rnapath)
167 MEM_freeN(soutliner->rnapath);
168 soutliner->rnapath= newpath;
171 static void rna_pointer_cb(void *arg_buts, void *arg_prop, void *arg_index)
173 SpaceOops *soutliner= arg_buts;
174 PropertyRNA *prop= arg_prop;
176 int index= GET_INT_FROM_POINTER(arg_index);;
178 newpath= RNA_path_append(soutliner->rnapath, NULL, prop, index, NULL);
179 if(soutliner->rnapath)
180 MEM_freeN(soutliner->rnapath);
181 soutliner->rnapath= newpath;
184 static void rna_label(CellRNA *cell, rcti *rct, uiBlock *block)
186 PropertySubType subtype;
189 char *vectoritem[4]= {"x", "y", "z", "w"};
190 char *quatitem[4]= {"w", "x", "y", "z"};
191 char *coloritem[4]= {"r", "g", "b", "a"};
196 type= RNA_property_type(&cell->ptr, prop);
197 subtype= RNA_property_subtype(&cell->ptr, prop);
198 arraylength= RNA_property_array_length(&cell->ptr, prop);
200 if(cell->index == -1) {
201 uiDefBut(block, LABEL, 0, (char*)RNA_property_ui_name(&cell->ptr, prop), rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin, 0, 0, 0, 0, 0, (char*)RNA_property_ui_description(&cell->ptr, prop));
203 else if (type != PROP_COLLECTION) {
204 if(arraylength == 4 && subtype == PROP_ROTATION)
205 sprintf(item, " %s", quatitem[cell->index]);
206 else if(arraylength <= 4 && (subtype == PROP_VECTOR || subtype == PROP_ROTATION))
207 sprintf(item, " %s", vectoritem[cell->index]);
208 else if(arraylength <= 4 && subtype == PROP_COLOR)
209 sprintf(item, " %s", coloritem[cell->index]);
211 sprintf(item, " %d", cell->index+1);
213 uiDefBut(block, LABEL, 0, item, rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin, 0, 0, 0, 0, 0, "");
217 static void rna_collection_but(CellRNA *cell, rcti *rct, uiBlock *block)
221 PropertyRNA *nameprop;
222 char name[256]= "", *nameptr= name;
224 RNA_property_collection_lookup_int(&cell->ptr, cell->prop, cell->index, &lookup);
227 nameprop= RNA_struct_name_property(&lookup);
230 nameptr= RNA_property_string_get_alloc(&lookup, nameprop, name, sizeof(name));
232 sprintf(nameptr, "%d", cell->index+1);
235 but= uiDefBut(block, BUT, 0, nameptr, rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin, 0, 0, 0, 0, 0, "");
236 uiButSetFlag(but, UI_TEXT_LEFT);
241 uiButSetFunc3(but, rna_pointer_cb, cell->space, cell->prop, SET_INT_IN_POINTER(cell->index));
244 static void rna_but(CellRNA *cell, rcti *rct, uiBlock *block)
249 int arraylength, index;
252 type= RNA_property_type(&cell->ptr, prop);
253 arraylength= RNA_property_array_length(&cell->ptr, prop);
255 if(type == PROP_COLLECTION) {
256 /* item in a collection */
258 rna_collection_but(cell, rct, block);
262 index= (arraylength)? cell->index: 0;
265 but= uiDefRNABut(block, 0, &cell->ptr, prop, index, rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin);
267 if(type == PROP_POINTER)
268 uiButSetFunc3(but, rna_pointer_cb, cell->space, prop, SET_INT_IN_POINTER(0));
273 static void rna_path_but(CellRNA *cell, rcti *rct, uiBlock *block)
277 but= uiDefBut(block, BUT, 0, (cell->space->rnapath)? "..": ".", rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin, 0, 0, 0, 0, 0, "");
278 uiButSetFlag(but, UI_TEXT_LEFT);
279 uiButSetFunc(but, rna_back_cb, cell->space, NULL);
282 static void rna_table_cell_func(void *userdata, int row, int col, rcti *rct, uiBlock *block)
284 CellRNA *cell= userdata;
291 rna_path_but(cell, rct, block);
296 /* set next property for new row */
297 if(row != cell->lastrow) {
301 type= RNA_property_type(&cell->ptr, cell->prop);
302 if(type == PROP_COLLECTION)
303 length= RNA_property_collection_length(&cell->ptr, cell->prop);
305 length= RNA_property_array_length(&cell->ptr, cell->prop);
307 /* verify if we need to go to the next property */
308 if(type == PROP_COLLECTION && cell->index < length);
309 else if(length && cell->index < length);
311 RNA_property_collection_next(&cell->iter);
312 cell->prop= cell->iter.ptr.data;
318 cell->prop= cell->iter.ptr.data;
327 rna_label(cell, rct, block);
329 rna_but(cell, rct, block);
332 static void outliner_main_area_draw(const bContext *C, ARegion *ar)
337 PropertyRNA *prop, *iterprop;
340 int rows, cols, awidth, aheight, width, height;
341 SpaceOops *soutliner= C->area->spacedata.first;
342 View2D *v2d= &ar->v2d;
345 UI_GetThemeColor3fv(TH_BACK, col);
346 glClearColor(col[0], col[1], col[2], 0.0);
347 glClear(GL_COLOR_BUFFER_BIT);
349 // XXX width should be depend on max length of items (like height)...
350 awidth= width= ar->winrct.xmax - ar->winrct.xmin;
351 aheight= height= ar->winrct.ymax - ar->winrct.ymin;
354 cell.space= soutliner;
356 RNA_main_pointer_create(G.main, &cell.ptr);
359 /* solve RNA path or reset if fails */
360 if(soutliner->rnapath) {
361 if(!RNA_path_resolve(&cell.ptr, soutliner->rnapath, &newptr, &prop)) {
363 printf("RNA outliner: failed resolving path. (%s)\n", soutliner->rnapath);
366 if(newptr.data && newptr.type) {
370 MEM_freeN(soutliner->rnapath);
371 soutliner->rnapath= NULL;
375 /* compute number of rows and columns */
379 iterprop= RNA_struct_iterator_property(&cell.ptr);
380 RNA_property_collection_begin(&cell.ptr, iterprop, &cell.iter);
382 for(; cell.iter.valid; RNA_property_collection_next(&cell.iter)) {
383 prop= cell.iter.ptr.data;
385 rows += 1 + RNA_property_array_length(&cell.ptr, prop);
386 if(RNA_property_type(&cell.ptr, prop) == PROP_COLLECTION)
387 rows += RNA_property_collection_length(&cell.ptr, prop);
390 RNA_property_collection_end(&cell.iter);
392 if ((rows*ROW_HEIGHT) > height)
393 height= rows * ROW_HEIGHT;
395 /* need to validate view2d after updating size of tot */
397 v2d->tot.xmax= width;
399 v2d->tot.ymin= -height;
400 UI_view2d_enforce_status(v2d, awidth, aheight);
407 /* set matrix for 2d-view controls */
408 UI_view2d_ortho(C, v2d);
410 /* create and draw table */
411 table= UI_table_create(rows, 2, &rct, rna_table_cell_func, &cell);
413 RNA_property_collection_begin(&cell.ptr, iterprop, &cell.iter);
414 UI_table_draw(C->window, ar, table);
415 RNA_property_collection_end(&cell.iter);
417 UI_table_free(table);
420 static void outliner_main_area_free(ARegion *ar)
422 uiFreeBlocks(&ar->uiblocks);
425 /* ************************ header outliner area region *********************** */
427 static void outliner_header_area_draw(const bContext *C, ARegion *ar)
429 SpaceOops *soutliner= C->area->spacedata.first;
435 path= (soutliner->rnapath)? soutliner->rnapath: "Main";
438 UI_GetThemeColor3fv(TH_BACK, col);
439 glClearColor(MAX2(col[0]-0.3f, 0.0f), MAX2(col[1]-0.3f, 0.0f), MAX2(col[2]-0.3f, 0.0f), 0.0);
440 glClear(GL_COLOR_BUFFER_BIT);
442 width= ar->winrct.xmax - ar->winrct.xmin;
443 height= ar->winrct.ymax - ar->winrct.ymin;
446 UI_GetBoundingBox(UI_HELV, path, 0, &bbox);
448 glColor3f(1.0f, 1.0f, 1.0f);
450 UI_RasterPos(0.5f*(width - (bbox.xmax - bbox.xmin)), 0.5f*(height - (bbox.ymax - bbox.ymin)));
451 UI_DrawString(UI_HELV, path, 0);
454 static void outliner_header_area_free(ARegion *ar)
456 uiFreeBlocks(&ar->uiblocks);
459 /* ******************** default callbacks for outliner space ***************** */
461 static SpaceLink *outliner_new(void)
463 SpaceOops *soutliner;
465 soutliner= MEM_callocN(sizeof(SpaceOops), "initoutliner");
467 return (SpaceLink*)soutliner;
470 /* not spacelink itself */
471 static void outliner_free(SpaceLink *sl)
473 SpaceOops *soutliner= (SpaceOops*)sl;
475 if(soutliner->rnapath) {
476 MEM_freeN(soutliner->rnapath);
477 soutliner->rnapath= NULL;
481 /* spacetype; init callback */
482 static void outliner_init(wmWindowManager *wm, ScrArea *sa)
486 /* link area to SpaceXXX struct */
488 /* add handlers to area */
489 /* define how many regions, the order and types */
491 /* add types to regions */
492 for(ar= sa->regionbase.first; ar; ar= ar->next) {
493 if(ar->regiontype == RGN_TYPE_WINDOW) {
494 static ARegionType mainart={NULL, NULL, NULL, NULL, NULL};
496 mainart.draw= outliner_main_area_draw;
497 mainart.free= outliner_main_area_free;
501 WM_event_add_keymap_handler(&ar->handlers, &wm->uikeymap);
502 WM_event_add_keymap_handler(&ar->handlers, &wm->view2dkeymap);
504 else if(ar->regiontype == RGN_TYPE_HEADER) {
505 static ARegionType headerart={NULL, NULL, NULL, NULL, NULL};
507 headerart.draw= outliner_header_area_draw;
508 headerart.free= outliner_header_area_free;
510 ar->type= &headerart;
512 WM_event_add_keymap_handler(&ar->handlers, &wm->uikeymap);
513 WM_event_add_keymap_handler(&ar->handlers, &wm->view2dkeymap);
516 static ARegionType headerart={NULL, NULL, NULL, NULL, NULL};
517 ar->type= &headerart;
522 /* spacetype; context changed */
523 static void outliner_refresh(bContext *C, ScrArea *sa)
528 static SpaceLink *outliner_duplicate(SpaceLink *sl)
530 SpaceOops *soutliner= (SpaceOops *)sl;
531 SpaceOops *soutlinern= MEM_dupallocN(soutliner);
533 if(soutlinern->rnapath)
534 soutlinern->rnapath= MEM_dupallocN(soutlinern->rnapath);
536 return (SpaceLink *)soutlinern;
539 /* only called once, from screen/spacetypes.c */
540 void ED_spacetype_outliner(void)
544 st.spaceid= SPACE_OOPS;
546 st.new= outliner_new;
547 st.free= outliner_free;
548 st.init= outliner_init;
549 st.refresh= outliner_refresh;
550 st.duplicate= outliner_duplicate;
551 st.operatortypes= outliner_operatortypes;
552 st.keymap= outliner_keymap;
554 BKE_spacetype_register(&st);