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)
115 block= uiBeginBlock(window, region, "table outliner", UI_EMBOSST, UI_HELV);
117 for(y=rct->ymax, row=0; y>rct->ymin; y-=ROW_HEIGHT, row++) {
119 UI_ThemeColorShade(TH_BACK, 6);
120 glRecti(rct->xmin, y-ROW_HEIGHT, rct->xmax, y);
123 if(row >= table->rows)
126 for(col=0; col<table->cols; col++) {
127 cellrct.xmin= rct->xmin+COLUMN_WIDTH*col + 1;
128 cellrct.xmax= rct->xmin+COLUMN_WIDTH*(col+1);
129 cellrct.ymin= y-ROW_HEIGHT;
132 table->cellfunc(table->userdata, row, col, &cellrct, block);
136 UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
138 for(col=0; col<table->cols; col++)
139 fdrawline(rct->xmin+COLUMN_WIDTH*(col+1), rct->ymin, rct->xmin+COLUMN_WIDTH*(col+1), rct->ymax);
146 /* ************************ main outliner area region *********************** */
148 typedef struct CellRNA {
155 CollectionPropertyIterator iter;
156 PropertyRNA *iterprop;
159 static void rna_back_cb(void *arg_buts, void *arg_unused)
161 SpaceOops *soutliner= arg_buts;
164 newpath= RNA_path_back(soutliner->rnapath);
165 if(soutliner->rnapath)
166 MEM_freeN(soutliner->rnapath);
167 soutliner->rnapath= newpath;
170 static void rna_pointer_cb(void *arg_buts, void *arg_prop, void *arg_index)
172 SpaceOops *soutliner= arg_buts;
173 PropertyRNA *prop= arg_prop;
175 int index= GET_INT_FROM_POINTER(arg_index);;
177 newpath= RNA_path_append(soutliner->rnapath, NULL, prop, index, NULL);
178 if(soutliner->rnapath)
179 MEM_freeN(soutliner->rnapath);
180 soutliner->rnapath= newpath;
183 static void rna_label(CellRNA *cell, rcti *rct, uiBlock *block)
185 PropertySubType subtype;
188 char *vectoritem[4]= {"x", "y", "z", "w"};
189 char *quatitem[4]= {"w", "x", "y", "z"};
190 char *coloritem[4]= {"r", "g", "b", "a"};
195 type= RNA_property_type(prop, &cell->ptr);
196 subtype= RNA_property_subtype(prop, &cell->ptr);
197 arraylength= RNA_property_array_length(prop, &cell->ptr);
199 if(cell->index == -1) {
200 uiDefBut(block, LABEL, 0, (char*)RNA_property_ui_name(prop, &cell->ptr), rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin, 0, 0, 0, 0, 0, (char*)RNA_property_ui_description(prop, &cell->ptr));
202 else if (type != PROP_COLLECTION) {
203 if(arraylength == 4 && subtype == PROP_ROTATION)
204 sprintf(item, " %s", quatitem[cell->index]);
205 else if(arraylength <= 4 && (subtype == PROP_VECTOR || subtype == PROP_ROTATION))
206 sprintf(item, " %s", vectoritem[cell->index]);
207 else if(arraylength <= 4 && subtype == PROP_COLOR)
208 sprintf(item, " %s", coloritem[cell->index]);
210 sprintf(item, " %d", cell->index+1);
212 uiDefBut(block, LABEL, 0, item, rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin, 0, 0, 0, 0, 0, "");
216 static void rna_collection_but(CellRNA *cell, rcti *rct, uiBlock *block)
220 PropertyRNA *nameprop;
221 char name[256]= "", *nameptr= name;
223 RNA_property_collection_lookup_int(cell->prop, &cell->ptr, cell->index, &lookup);
226 nameprop= RNA_struct_name_property(&lookup);
229 nameptr= RNA_property_string_get_alloc(nameprop, &lookup, name, sizeof(name));
231 sprintf(nameptr, "%d", cell->index+1);
234 but= uiDefBut(block, BUT, 0, nameptr, rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin, 0, 0, 0, 0, 0, "");
235 uiButSetFlag(but, UI_TEXT_LEFT);
240 uiButSetFunc3(but, rna_pointer_cb, cell->space, cell->prop, SET_INT_IN_POINTER(cell->index));
243 static void rna_but(CellRNA *cell, rcti *rct, uiBlock *block)
248 int arraylength, index;
251 type= RNA_property_type(prop, &cell->ptr);
252 arraylength= RNA_property_array_length(prop, &cell->ptr);
254 if(type == PROP_COLLECTION) {
255 /* item in a collection */
257 rna_collection_but(cell, rct, block);
261 index= (arraylength)? cell->index: 0;
264 but= uiDefRNABut(block, 0, &cell->ptr, prop, index, rct->xmin, rct->ymin, rct->xmax-rct->xmin, rct->ymax-rct->ymin);
266 if(type == PROP_POINTER)
267 uiButSetFunc3(but, rna_pointer_cb, cell->space, prop, SET_INT_IN_POINTER(0));
272 static void rna_path_but(CellRNA *cell, rcti *rct, uiBlock *block)
276 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, "");
277 uiButSetFlag(but, UI_TEXT_LEFT);
278 uiButSetFunc(but, rna_back_cb, cell->space, NULL);
281 static void rna_table_cell_func(void *userdata, int row, int col, rcti *rct, uiBlock *block)
283 CellRNA *cell= userdata;
290 rna_path_but(cell, rct, block);
295 /* set next property for new row */
296 if(row != cell->lastrow) {
300 type= RNA_property_type(cell->prop, &cell->ptr);
301 if(type == PROP_COLLECTION)
302 length= RNA_property_collection_length(cell->prop, &cell->ptr);
304 length= RNA_property_array_length(cell->prop, &cell->ptr);
306 /* verify if we need to go to the next property */
307 if(type == PROP_COLLECTION && cell->index < length);
308 else if(length && cell->index < length);
310 RNA_property_collection_next(cell->iterprop, &cell->iter);
311 cell->prop= cell->iter.ptr.data;
317 cell->prop= cell->iter.ptr.data;
326 rna_label(cell, rct, block);
328 rna_but(cell, rct, block);
331 static void outliner_main_area_draw(const bContext *C, ARegion *ar)
339 int rows, cols, width, height;
340 SpaceOops *soutliner= C->area->spacedata.first;
343 UI_GetThemeColor3fv(TH_BACK, col);
344 glClearColor(col[0], col[1], col[2], 0.0);
345 glClear(GL_COLOR_BUFFER_BIT);
347 width= ar->winrct.xmax - ar->winrct.xmin;
348 height= ar->winrct.ymax - ar->winrct.ymin;
356 cell.space= soutliner;
358 RNA_pointer_main_get(G.main, &cell.ptr);
361 /* solve RNA path or reset if fails */
362 if(soutliner->rnapath) {
363 if(!RNA_path_resolve(&cell.ptr, soutliner->rnapath, &newptr, &prop)) {
365 printf("RNA outliner: failed resolving path. (%s)\n", soutliner->rnapath);
368 if(newptr.data && newptr.type) {
372 MEM_freeN(soutliner->rnapath);
373 soutliner->rnapath= NULL;
377 /* compute number of rows and columns */
381 cell.iterprop= RNA_struct_iterator_property(&cell.ptr);
382 RNA_property_collection_begin(cell.iterprop, &cell.iter, &cell.ptr);
384 for(; cell.iter.valid; RNA_property_collection_next(cell.iterprop, &cell.iter)) {
385 prop= cell.iter.ptr.data;
387 rows += 1 + RNA_property_array_length(prop, &cell.ptr);
388 if(RNA_property_type(prop, &cell.ptr) == PROP_COLLECTION)
389 rows += RNA_property_collection_length(prop, &cell.ptr);
392 RNA_property_collection_end(cell.iterprop, &cell.iter);
394 /* create and draw table */
395 table= UI_table_create(rows, 2, &rct, rna_table_cell_func, &cell);
397 RNA_property_collection_begin(cell.iterprop, &cell.iter, &cell.ptr);
398 UI_table_draw(C->window, ar, table);
399 RNA_property_collection_end(cell.iterprop, &cell.iter);
401 UI_table_free(table);
404 static void outliner_main_area_free(ARegion *ar)
406 uiFreeBlocks(&ar->uiblocks);
409 /* ************************ header outliner area region *********************** */
411 static void outliner_header_area_draw(const bContext *C, ARegion *ar)
413 SpaceOops *soutliner= C->area->spacedata.first;
419 path= (soutliner->rnapath)? soutliner->rnapath: "Main";
422 UI_GetThemeColor3fv(TH_BACK, col);
423 glClearColor(MAX2(col[0]-0.3f, 0.0f), MAX2(col[1]-0.3f, 0.0f), MAX2(col[2]-0.3f, 0.0f), 0.0);
424 glClear(GL_COLOR_BUFFER_BIT);
426 width= ar->winrct.xmax - ar->winrct.xmin;
427 height= ar->winrct.ymax - ar->winrct.ymin;
430 UI_GetBoundingBox(UI_HELV, path, 0, &bbox);
432 glColor3f(1.0f, 1.0f, 1.0f);
434 UI_RasterPos(0.5f*(width - (bbox.xmax - bbox.xmin)), 0.5f*(height - (bbox.ymax - bbox.ymin)));
435 UI_DrawString(UI_HELV, path, 0);
438 static void outliner_header_area_free(ARegion *ar)
440 uiFreeBlocks(&ar->uiblocks);
443 /* ******************** default callbacks for outliner space ***************** */
445 static SpaceLink *outliner_new(void)
447 SpaceOops *soutliner;
449 soutliner= MEM_callocN(sizeof(SpaceOops), "initoutliner");
451 return (SpaceLink*)soutliner;
454 /* not spacelink itself */
455 static void outliner_free(SpaceLink *sl)
457 SpaceOops *soutliner= (SpaceOops*)sl;
459 if(soutliner->rnapath) {
460 MEM_freeN(soutliner->rnapath);
461 soutliner->rnapath= NULL;
465 /* spacetype; init callback */
466 static void outliner_init(wmWindowManager *wm, ScrArea *sa)
470 /* link area to SpaceXXX struct */
472 /* add handlers to area */
473 /* define how many regions, the order and types */
475 /* add types to regions */
476 for(ar= sa->regionbase.first; ar; ar= ar->next) {
477 if(ar->regiontype == RGN_TYPE_WINDOW) {
478 static ARegionType mainart={NULL, NULL, NULL, NULL, NULL};
480 mainart.draw= outliner_main_area_draw;
481 mainart.free= outliner_main_area_free;
485 WM_event_add_keymap_handler(&ar->handlers, &wm->uikeymap);
487 else if(ar->regiontype == RGN_TYPE_HEADER) {
488 static ARegionType headerart={NULL, NULL, NULL, NULL, NULL};
490 headerart.draw= outliner_header_area_draw;
491 headerart.free= outliner_header_area_free;
493 ar->type= &headerart;
495 WM_event_add_keymap_handler(&ar->handlers, &wm->uikeymap);
498 static ARegionType headerart={NULL, NULL, NULL, NULL, NULL};
499 ar->type= &headerart;
504 /* spacetype; context changed */
505 static void outliner_refresh(bContext *C, ScrArea *sa)
510 static SpaceLink *outliner_duplicate(SpaceLink *sl)
512 SpaceOops *soutliner= (SpaceOops *)sl;
513 SpaceOops *soutlinern= MEM_dupallocN(soutliner);
515 if(soutlinern->rnapath)
516 soutlinern->rnapath= MEM_dupallocN(soutlinern->rnapath);
518 return (SpaceLink *)soutlinern;
521 /* only called once, from screen/spacetypes.c */
522 void ED_spacetype_outliner(void)
526 st.spaceid= SPACE_OOPS;
528 st.new= outliner_new;
529 st.free= outliner_free;
530 st.init= outliner_init;
531 st.refresh= outliner_refresh;
532 st.duplicate= outliner_duplicate;
533 st.operatortypes= outliner_operatortypes;
534 st.keymap= outliner_keymap;
536 BKE_spacetype_register(&st);