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)