1 ---------------------------------------------------
2 Blender interface.c API toolkit notes
3 (july 2003, Ton Roosendaal)
4 ---------------------------------------------------
13 2.2 And how it works internally
16 3.1 uiBlock Controlling functions
17 3.2 Internal function to know
22 2. TOG or TOGN or TOGR
26 5. SLI or NUMSLI or HSVSLI
36 4.3 pulldown menus / block buttons
42 4.5 uiButton control fuctions
45 ----------------1. General notes
47 - The API is built with Blender in mind, with some buttons acting on lists of Blender data.
48 It was not meant to be available as a separate SDK, nor to be used for other applications.
50 - It works with only OpenGL calls, for the full 100%. This means that it has some quirks
51 built-in to work with all OS's and OpenGL versions. Especially frontbuffer drawing is
52 a continuous point of attention. Buttons can be drawn with any window matrix. However,
53 errors can still occor when buttons are created in windows with non-standard glViewports.
55 - The code was written to replace the old 1.8 button system, but under high pressure. Quite
56 some button methods from the old system were copied for that reason.
58 - I tried to design a unified GUI system, which equally works for pulldown menus, pop up menus,
59 and normal button layouts. Although it gives nice features and freedom in design, the code
60 looks quite hard to understand for that reason. Not all 'normal' pulldown menu features
61 could be hacked in easily, they just differ too much from other UI elements. Could be
64 - During the past period of NaN (beginning of 2002) someone tried to make a more 'high' level
65 API for it, with less low level defines and structure info needed in calling code. I am not
66 really sure if this was done well... or even finished. In the bottom of interface.c you can
67 see the 'new' API which is now used in Blender code. It used to be so much more simple!
68 Nevertheless, I will use that convention in this doc.
70 - Unfinished stuff: the code was scheduled to be expanded with 'floating blocks' which can
71 serve as permanent little button-fields in Blender windows. Think for example of having
72 an (optional) extra field in the 3d window displaying object loc/rot/size.
73 After that, the existing button windows can be reorganized in such blocks as well, allowing
74 a user to configure the genereal buttons layout (make vertical for example).
77 --------------1.1 C and H files
79 blender/source/blender/src/interface.c /* almost all code */
80 blender/source/blender/include/interface.h /* internals for previous code */
81 blender/source/blender/include/BIF_interface.h /* externals for previous code */
83 (the previous 2 include files have not been separated fully yet)
85 Color and icons stuff has been put in: (unfinished code, under development)
86 blender/source/blender/src/resources.c
87 blender/source/blender/include/BIF_resources.h
90 blender/source/blender/src/toolbox.c (extra GUI elements built on top of this API)
93 --------------2. Windows & Blocks
95 All GUI elements are collected in uiBlocks, which in turn are linked together in a list that's
96 part of a Blender Area-window.
98 uiBlock *block= uiNewBlock(&curarea->uiblocks, "stuff", UI_EMBOSSX, UI_HELV, curarea->win);
100 The next code example makes a new block, and puts it in the list of blocks of the current active
103 uiDoBlocks(&curarea->uiblocks, event);
105 This code is usually available in each area-window event queue handler. You give uiDoBlocks
106 an event code, and the uiDoBlocks handles whatever is to be handled. Blocks can be
107 standard buttons or pull down menus. Can return immediately, or jump to an internal handling
110 2.1 Memory allocation
112 Important to know is that for this toolkit there's no difference in "creating blocks" or
113 "drawing blocks". In fact, for each window redraw all blocks are created again. Constructing
114 button interfaces in Blender always happens in the main drawing function itself.
116 Memory allocation is handled as follows:
117 - if in this window a uiBlock with the same name existed, it is freed
118 - when you close a window (or blender) the uiBlocks get freed.
119 - when you duplicate (split) a window, the uiBlocks get copied
121 2.2 And how it works internally
123 With a call to uiDoblocks, all blocks in the current active window are evaluated.
124 It walks through the lists in a rather complex manner:
128 /* the normal buttons handling */
130 - call uiDoBlock (handles buttons for single block)
133 /* at this moment, a new block can be created, for a menu */
134 /* so we create a 2nd loop for it */
135 - while first block is a menu
136 - if block is a menu and not initialized:
137 - initalize 'saveunder'
139 - get event from queue
140 - call uiDoBlock (handles buttons for single block)
141 /* here, a new block again can be created, for a sub menu */
142 - if return "end" from uiDoBlock
146 - do tooltip if nothing has happened
149 - if there was menu, it does this loop once more
150 (when you click outside a menu, at another button)
154 - do tooltip if nothing has happened
158 -------------3. API for uiBlock
160 Create a new buttons block, and link it to the window:
162 uiBlock *uiNewBlock(ListBase *lb, char *name, short dt, short font, short win)
163 ListBase *lb pointer to list basis, where the block will be appended to (blenlib)
164 char *name unique name to identify the block. When the name exists in the list,
165 the old uiBlock gets freed.
166 short dt drawtype. See below
167 short font font id number
168 short win blender area-window id
171 UI_EMBOSSX 0 /* Rounded embossed button (standard in Blender) */
172 UI_EMBOSSW 1 /* Simpler embossed button */
173 UI_EMBOSSN 2 /* Button with no border */
174 UI_EMBOSSF 3 /* Square embossed button (file select) */
175 UI_EMBOSSM 4 /* Colored, for pulldown menus */
176 UI_EMBOSSP 5 /* Simple borderless coloured button (like blender sensors) */
179 UI_HELV 0 /* normal font */
180 UI_HELVB 1 /* bold font */
181 With the new truetype option in Blender, this is used for all font families
183 When a uiBlock is created, each uiButton that is defined gets the uiBlock properties.
184 Changing Block properties inbetween will affact uiButtons defined thereafter.
188 ----------3.1 uiBlock Controlling functions:
190 void uiDrawBlock(block)
193 void uiBlockSetCol(uiBlock *block, int col)
203 void uiBlockSetEmboss(uiBlock *block, int emboss)
206 void uiBlockSetDirection(uiBlock *block, int direction)
207 for pop-up and pulldown menus:
215 void uiBlockSetXOfs(uiBlock *block, int xofs)
216 for menus, offset from parent
218 void uiBlockSetButmFunc(uiBlock *block, void (*menufunc)(void *arg, int event), void *arg)
219 sets function to be handled when a menu-block is marked "OK"
221 void uiAutoBlock(uiBlock *block, float minx, float miny, float sizex, float sizey, UI_BLOCK_ROWS)
223 Sets the buttons in this block to automatically align, and fit within boundaries.
224 Internally it allows multiple collums or rows as well. Only 'row order' has been implemented.
225 The uiDefBut definitions don't need coordinates as input here, but instead:
226 - first value (x1) to indicate row number
227 - width and height values (if filled in) will be used to define a relative width/height.
228 A call to uiDrawBlock will invoke the calculus to fit in all buttons.
232 ---------- 3.2 Internal function to know:
234 These flags used to be accessible from outside of interface.c. Currently it is only
235 used elsewhere by toolbox.c, so it can be considered 'internal' somewhat.
237 void uiBlockSetFlag(uiBlock *block, int flag) /* block types, can be 'OR'ed */
238 UI_BLOCK_LOOP 1 a sublooping block, drawn in frontbuffer, i.e. menus
239 UI_BLOCK_REDRAW 2 block needs a redraw
240 UI_BLOCK_RET_1 4 block is closed when an event happens with value '1' (press key, not for mouse)
241 UI_BLOCK_BUSY 8 internal
242 UI_BLOCK_NUMSELECT 16 keys 1-2-...-9-0 can be used to select items
243 UI_BLOCK_ENTER_OK 32 enter key closes block with "OK"
245 (these values are being set within the interface.c and toolbox.c code.)
248 -------------4. API for uiButton
250 In Blender a button can do four things:
252 - directly visualize data, and write to it.
253 - put event codes (shorts) back in the queue, to be handled
254 - call a user-defined function pointer (while being pressed, etc)
255 - create and call another block (i.e. menu)
257 Internally, each button or menu item is a 'uiButton', with a generic API and handling:
258 ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
260 Beacause a lot of obscure generic (re-use) happens here, translation calls have been made
261 for each most button types individually.
264 -----------4.1 UiDefBut
266 uiBut *UiDefBut[CSIF]( uiBlock *block, int type, int retval, char *str,
267 short x1, short y1, short x2, short y2, xxxx *poin,
268 float min, float max, float a1, float a2, char *tip)
270 UiDefButC operatates on char
271 UiDefButS operatates on short
272 UiDefButI operatates on int
273 UiDefButF operatates on float
275 *block: current uiBlock pointer
277 retval: return value, which is put back in queue
279 x1, y1: coordinates of left-lower corner
280 x2, y2: width, height
281 *poin: pointer to char, short, int, float
282 min, max used for slider buttons
283 a1, a2 extra info for some buttons
289 Activation button. (like "Render")
290 Passing on a pointer is not needed
292 2. TOG or TOGN or TOGR
293 Toggle button (like "Lock")
294 The pointer value is set either at 0 or 1
295 If pressed, it calls the optional function with arguments provided.
296 Type TOGN: works negative, when pressed it sets at 0
297 Type TOGR: is part of a row, redraws automatically all buttons with same *poin
300 When added to type, it works on a single bit <nr> (lowest order bit: nr = '0')
303 A toggle with 3 values!
304 Can be only used for short *poin.
305 In the third toggle setting, the bit <nr> of *( poin+1) is set.
308 Button that's part of a row.
309 in "min" you set a row-id number, in "max" the value you want *poin to be
310 assigned when you press the button. Always pass on these values as floats.
311 When this button is pressed, it sets the "max" value to *poin, and redraws
312 all buttons with the same row-id number.
314 5. SLI or NUMSLI or HSVSLI
315 Slider, number-slider or hsv-slider button.
316 "min" and "max" are to clamp the value to.
317 If you want a button type "Col" to be updated, make 'a1' equal to 'retval'
322 Set the clamping values 'min' and 'max' always as float.
323 For UiDefButF, set a 'step' in 'a1', in 1/100's. The step value is the increment or
324 decrement when you click once on the right or left side of a button.
325 The optional button function is additionally called for each change of the *poin value.
329 Pointertype is standard a char. Value 'max' is length of string (pass as float).
330 When button is left with ESC, it doesn't put the 'retval' at the queue.
335 If 'min' is set at 1.0, the text is printed in white.
338 A separator line, typically used within pulldown menus.
342 The syntax of the string in *name defines the menu items:
343 - %t means the previous text becomes the title
344 - item separator is '|'
345 - return values are indicated with %x[nr] (i.e: %x12).
346 without returnvalues, the first item gets value 0 (incl. title!)
347 Example: "Do something %t| turn left %2| turn right %1| nothing %0"
350 A special button that only visualizes a RGB value
351 In 'retval' you can put a code, which is used to identify for sliders if it needs
352 redraws while using the sliders. Check button '5'.
353 As *poin you input the pointer to the 'r' value, 'g' and 'b' are supposed to be
357 ------------4.2 Icon buttons
359 Instead of a 'name', all buttons as described for uiDefBut also can have an icon:
361 uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon,
362 short x1, short y1, short x2, short y2, void *poin,
363 float min, float max, float a1, float a2, char *tip)
365 Same syntax and types available as previous uiDefBut, but now with an icon code
366 instead of a name. THe icons are numbered in resources.c
368 uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, char *str,
369 short x1, short y1, short x2, short y2, float *poin,
370 float min, float max, float a1, float a2, char *tip)
372 Same again, but now with an icon and string as button name.
374 Two special icon buttons are available in Blender:
378 This button pops up a vertical menu with a row of icons to choose from.
379 'max' = amount of icons. The icons are supposed to be ordered in a sequence
380 It writes in *poin which item in the menu was choosen (starting with 0).
384 Same as previous, but with the texts next to it.
388 -----------4.3 pulldown menus / block buttons
391 void uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str,
392 short x1, short y1, short x2, short y2, char *tip)
394 This button creates a new block when pressed. The function argument 'func' is called
395 to take care of this. An example func:
397 static uiBlock *info_file_importmenu(void *arg_unused)
400 short yco= 0, xco = 20;
402 block= uiNewBlock(&curarea->uiblocks, "importmenu", UI_EMBOSSW, UI_HELV, G.curscreen->mainwin);
403 uiBlockSetXOfs(block, -40); // offset to parent button
405 /* flags are defines */
406 uiDefBut(block, LABEL, 0, "VRML 2.0 options", xco, yco, 125, 19, NULL, 0.0, 0.0, 0, 0, "");
407 uiDefButS(block, TOG|BIT|0, 0, "SepLayers", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "");
408 uiDefButS(block, TOG|BIT|1, 0, "Scale 1/100", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "");
409 uiDefButS(block, TOG|BIT|2, 0, "Two Sided", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "");
411 uiBlockSetDirection(block, UI_RIGHT);
412 uiTextBoundsBlock(block, 50); // checks for fontsize
417 The uiDef coordinates here are only relative. When this function is called, the interface
418 code automatically makes sure the buttons fit in the menu nicely.
420 Inside a menu uiBlock, other uiBlocks can be invoked to make a hierarchical menu.
424 -----------4.4 specials
428 void uiDefKeyevtButS(uiBlock *block, int retval, char *str,
429 short x1, short y1, short x2, short y2, short *spoin, char *tip)
431 A special button, which stores a keyvalue in *spoin. When the button is pressed,
432 it displays the text 'Press any Key'. A keypress then stores the value.
436 These button present a method of linking data in Blender, by drawing a line from one
437 icon to another. It consists of two button types:
439 LINK, the 'linking from' part, can be:
440 - a single pointer to data (only one line allowed)
441 - an array of pointers to data. The LINK buttons system keeps track of allocating
442 space for the array, and set the correct pointers in it.
444 INLINK, the 'linking to' part activates creating a link, when a user releases the mouse
445 cursor over it, while dragging a line from the LINK button.
447 These buttons are defined as follows:
450 uiBut but= uiDefIconBut(block, LINK, 0, ICON_LINK, x1, y1, w, h, NULL, 0, 0, 0, 0, "");
451 /* create the LINK icon */
453 uiSetButLink(but, void **pt, void ***ppt, short *totlink, short fromcode, short tocode);
454 **pt: pointer to pointer (only one link allowed)
455 ***ppt: pointer to pointerpointer (an array of pointers)
456 (Either one of these values should be NULL)
458 fromcode: (currently unused)
459 tocode: a short indicating which blocks it can link to.
462 uiDefIconBut(block, INLINK, 0, ICON_INLINK, x1, y1, w, h, void *poin, short fromcode, 0, 0, 0, "");
463 poin: the pointer of the datablock you want to create links to
464 fromcode: a short identifying which LINK buttons can connect to it
469 void uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, int retval, char *str,
470 short x1, short y1, short x2, short y2, void *idpp, char *tip)
472 The ID struct is a generic part in structs like Object, Material, Mesh, etc.
473 Most linking options in Blender happens using ID's. (Mesh -> Material).
475 This special button in Blender visualizes an ID pointer with its name. Typing in
476 a new name, changes the pointer. For most ID types in Blender functions have been
477 written already, needed by this button, to check validity of names, and assign the pointer.
479 (BTW: the 'void *idpp' has to be a pointer to the ID pointer!)
481 Example function that can be put in 'func':
483 void test_scriptpoin_but(char *name, ID **idpp)
487 id= G.main->text.first;
489 if( strcmp(name, id->name+2)==0 ) {
499 ------------- 4.5 uiButton control fuctions
502 void uiButSetFunc(uiBut *but, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2)
503 When the button is pressed and released, it calls this function, with the 2 arguments.
505 void uiButSetFlag(uiBut *but, int flag)
506 set a flag for further control of button behaviour:
510 int uiButGetRetVal(uiBut *but)