516 lines
17 KiB
Plaintext
516 lines
17 KiB
Plaintext
---------------------------------------------------
|
|
Blender interface.c API toolkit notes
|
|
(july 2003, Ton Roosendaal)
|
|
---------------------------------------------------
|
|
|
|
Contents
|
|
|
|
1 General notes
|
|
1.1 C and H files
|
|
|
|
2. Windows & Blocks
|
|
2.1 Memory allocation
|
|
2.2 And how it works internally
|
|
|
|
3. API for uiBlock
|
|
3.1 uiBlock Controlling functions
|
|
3.2 Internal function to know
|
|
|
|
4. API for uiButton
|
|
4.1 UiDefBut
|
|
1. BUT
|
|
2. TOG or TOGN or TOGR
|
|
TOG|BIT|<nr>
|
|
3. TOG3|BIT|<nr>
|
|
4. ROW
|
|
5. SLI or NUMSLI or HSVSLI
|
|
6. NUM
|
|
7. TEX
|
|
8. LABEL
|
|
9 SEPR
|
|
10. MENU
|
|
11. COL
|
|
4.2 Icon buttons
|
|
12. ICONROW
|
|
13. ICONTEXTROW
|
|
4.3 pulldown menus / block buttons
|
|
14. BLOCK
|
|
4.4 specials
|
|
15. KEYEVT
|
|
16. LINK and INLINK
|
|
17. IDPOIN
|
|
4.5 uiButton control fuctions
|
|
|
|
|
|
----------------1. General notes
|
|
|
|
- The API is built with Blender in mind, with some buttons acting on lists of Blender data.
|
|
It was not meant to be available as a separate SDK, nor to be used for other applications.
|
|
|
|
- It works with only OpenGL calls, for the full 100%. This means that it has some quirks
|
|
built-in to work with all OS's and OpenGL versions. Especially frontbuffer drawing is
|
|
a continuous point of attention. Buttons can be drawn with any window matrix. However,
|
|
errors can still occor when buttons are created in windows with non-standard glViewports.
|
|
|
|
- The code was written to replace the old 1.8 button system, but under high pressure. Quite
|
|
some button methods from the old system were copied for that reason.
|
|
|
|
- I tried to design a unified GUI system, which equally works for pulldown menus, pop up menus,
|
|
and normal button layouts. Although it gives nice features and freedom in design, the code
|
|
looks quite hard to understand for that reason. Not all 'normal' pulldown menu features
|
|
could be hacked in easily, they just differ too much from other UI elements. Could be
|
|
looked at once...
|
|
|
|
- During the past period of NaN (beginning of 2002) someone tried to make a more 'high' level
|
|
API for it, with less low level defines and structure info needed in calling code. I am not
|
|
really sure if this was done well... or even finished. In the bottom of interface.c you can
|
|
see the 'new' API which is now used in Blender code. It used to be so much more simple!
|
|
Nevertheless, I will use that convention in this doc.
|
|
|
|
- Unfinished stuff: the code was scheduled to be expanded with 'floating blocks' which can
|
|
serve as permanent little button-fields in Blender windows. Think for example of having
|
|
an (optional) extra field in the 3d window displaying object loc/rot/size.
|
|
After that, the existing button windows can be reorganized in such blocks as well, allowing
|
|
a user to configure the genereal buttons layout (make vertical for example).
|
|
|
|
|
|
--------------1.1 C and H files
|
|
|
|
blender/source/blender/src/interface.c /* almost all code */
|
|
blender/source/blender/include/interface.h /* internals for previous code */
|
|
blender/source/blender/include/BIF_interface.h /* externals for previous code */
|
|
|
|
(the previous 2 include files have not been separated fully yet)
|
|
|
|
Color and icons stuff has been put in: (unfinished code, under development)
|
|
blender/source/blender/src/resources.c
|
|
blender/source/blender/include/BIF_resources.h
|
|
|
|
Related code:
|
|
blender/source/blender/src/toolbox.c (extra GUI elements built on top of this API)
|
|
|
|
|
|
--------------2. Windows & Blocks
|
|
|
|
All GUI elements are collected in uiBlocks, which in turn are linked together in a list that's
|
|
part of a Blender Area-window.
|
|
|
|
uiBlock *block= uiNewBlock(&curarea->uiblocks, "stuff", UI_EMBOSSX, UI_HELV, curarea->win);
|
|
|
|
The next code example makes a new block, and puts it in the list of blocks of the current active
|
|
Area:
|
|
|
|
uiDoBlocks(&curarea->uiblocks, event);
|
|
|
|
This code is usually available in each area-window event queue handler. You give uiDoBlocks
|
|
an event code, and the uiDoBlocks handles whatever is to be handled. Blocks can be
|
|
standard buttons or pull down menus. Can return immediately, or jump to an internal handling
|
|
loop.
|
|
|
|
2.1 Memory allocation
|
|
|
|
Important to know is that for this toolkit there's no difference in "creating blocks" or
|
|
"drawing blocks". In fact, for each window redraw all blocks are created again. Constructing
|
|
button interfaces in Blender always happens in the main drawing function itself.
|
|
|
|
Memory allocation is handled as follows:
|
|
- if in this window a uiBlock with the same name existed, it is freed
|
|
- when you close a window (or blender) the uiBlocks get freed.
|
|
- when you duplicate (split) a window, the uiBlocks get copied
|
|
|
|
2.2 And how it works internally
|
|
|
|
With a call to uiDoblocks, all blocks in the current active window are evaluated.
|
|
It walks through the lists in a rather complex manner:
|
|
|
|
- while(looping)
|
|
|
|
/* the normal buttons handling */
|
|
- for each block
|
|
- call uiDoBlock (handles buttons for single block)
|
|
- (end for)
|
|
|
|
/* at this moment, a new block can be created, for a menu */
|
|
/* so we create a 2nd loop for it */
|
|
- while first block is a menu
|
|
- if block is a menu and not initialized:
|
|
- initalize 'saveunder'
|
|
- draw it
|
|
- get event from queue
|
|
- call uiDoBlock (handles buttons for single block)
|
|
/* here, a new block again can be created, for a sub menu */
|
|
- if return "end" from uiDoBlock
|
|
restore 'saveunder's
|
|
free all menu blocks
|
|
exit from loop
|
|
- do tooltip if nothing has happened
|
|
- (end while)
|
|
|
|
- if there was menu, it does this loop once more
|
|
(when you click outside a menu, at another button)
|
|
|
|
- (end while)
|
|
|
|
- do tooltip if nothing has happened
|
|
|
|
|
|
|
|
-------------3. API for uiBlock
|
|
|
|
Create a new buttons block, and link it to the window:
|
|
|
|
uiBlock *uiNewBlock(ListBase *lb, char *name, short dt, short font, short win)
|
|
ListBase *lb pointer to list basis, where the block will be appended to (blenlib)
|
|
char *name unique name to identify the block. When the name exists in the list,
|
|
the old uiBlock gets freed.
|
|
short dt drawtype. See below
|
|
short font font id number
|
|
short win blender area-window id
|
|
|
|
drawtype:
|
|
UI_EMBOSSX 0 /* Rounded embossed button (standard in Blender) */
|
|
UI_EMBOSSW 1 /* Simpler embossed button */
|
|
UI_EMBOSSN 2 /* Button with no border */
|
|
UI_EMBOSSF 3 /* Square embossed button (file select) */
|
|
UI_EMBOSSM 4 /* Colored, for pulldown menus */
|
|
UI_EMBOSSP 5 /* Simple borderless coloured button (like blender sensors) */
|
|
|
|
font:
|
|
UI_HELV 0 /* normal font */
|
|
UI_HELVB 1 /* bold font */
|
|
With the new truetype option in Blender, this is used for all font families
|
|
|
|
When a uiBlock is created, each uiButton that is defined gets the uiBlock properties.
|
|
Changing Block properties inbetween will affact uiButtons defined thereafter.
|
|
|
|
|
|
|
|
----------3.1 uiBlock Controlling functions:
|
|
|
|
void uiDrawBlock(block)
|
|
draws the block
|
|
|
|
void uiBlockSetCol(uiBlock *block, int col)
|
|
|
|
col:
|
|
BUTGREY,
|
|
BUTGREEN,
|
|
BUTBLUE,
|
|
BUTSALMON,
|
|
MIDGREY,
|
|
BUTPURPLE,
|
|
|
|
void uiBlockSetEmboss(uiBlock *block, int emboss)
|
|
changes drawtype
|
|
|
|
void uiBlockSetDirection(uiBlock *block, int direction)
|
|
for pop-up and pulldown menus:
|
|
|
|
direction:
|
|
UI_TOP
|
|
UI_DOWN
|
|
UI_LEFT
|
|
UI_RIGHT
|
|
|
|
void uiBlockSetXOfs(uiBlock *block, int xofs)
|
|
for menus, offset from parent
|
|
|
|
void uiBlockSetButmFunc(uiBlock *block, void (*menufunc)(void *arg, int event), void *arg)
|
|
sets function to be handled when a menu-block is marked "OK"
|
|
|
|
void uiAutoBlock(uiBlock *block, float minx, float miny, float sizex, float sizey, UI_BLOCK_ROWS)
|
|
|
|
Sets the buttons in this block to automatically align, and fit within boundaries.
|
|
Internally it allows multiple collums or rows as well. Only 'row order' has been implemented.
|
|
The uiDefBut definitions don't need coordinates as input here, but instead:
|
|
- first value (x1) to indicate row number
|
|
- width and height values (if filled in) will be used to define a relative width/height.
|
|
A call to uiDrawBlock will invoke the calculus to fit in all buttons.
|
|
|
|
|
|
|
|
---------- 3.2 Internal function to know:
|
|
|
|
These flags used to be accessible from outside of interface.c. Currently it is only
|
|
used elsewhere by toolbox.c, so it can be considered 'internal' somewhat.
|
|
|
|
void uiBlockSetFlag(uiBlock *block, int flag) /* block types, can be 'OR'ed */
|
|
UI_BLOCK_LOOP 1 a sublooping block, drawn in frontbuffer, i.e. menus
|
|
UI_BLOCK_REDRAW 2 block needs a redraw
|
|
UI_BLOCK_RET_1 4 block is closed when an event happens with value '1' (press key, not for mouse)
|
|
UI_BLOCK_BUSY 8 internal
|
|
UI_BLOCK_NUMSELECT 16 keys 1-2-...-9-0 can be used to select items
|
|
UI_BLOCK_ENTER_OK 32 enter key closes block with "OK"
|
|
|
|
(these values are being set within the interface.c and toolbox.c code.)
|
|
|
|
|
|
-------------4. API for uiButton
|
|
|
|
In Blender a button can do four things:
|
|
|
|
- directly visualize data, and write to it.
|
|
- put event codes (shorts) back in the queue, to be handled
|
|
- call a user-defined function pointer (while being pressed, etc)
|
|
- create and call another block (i.e. menu)
|
|
|
|
Internally, each button or menu item is a 'uiButton', with a generic API and handling:
|
|
ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
|
|
|
|
Beacause a lot of obscure generic (re-use) happens here, translation calls have been made
|
|
for each most button types individually.
|
|
|
|
|
|
-----------4.1 UiDefBut
|
|
|
|
uiBut *UiDefBut[CSIF]( uiBlock *block, int type, int retval, char *str,
|
|
short x1, short y1, short x2, short y2, xxxx *poin,
|
|
float min, float max, float a1, float a2, char *tip)
|
|
|
|
UiDefButC operatates on char
|
|
UiDefButS operatates on short
|
|
UiDefButI operatates on int
|
|
UiDefButF operatates on float
|
|
|
|
*block: current uiBlock pointer
|
|
type: see below
|
|
retval: return value, which is put back in queue
|
|
*str: button name
|
|
x1, y1: coordinates of left-lower corner
|
|
x1, y2: width, height
|
|
*poin: pointer to char, short, int, float
|
|
min, max used for slider buttons
|
|
a1, a2 extra info for some buttons
|
|
*tip: tooltip string
|
|
|
|
type:
|
|
|
|
1. BUT
|
|
Activation button. (like "Render")
|
|
Passing on a pointer is not needed
|
|
|
|
2. TOG or TOGN or TOGR
|
|
Toggle button (like "Lock")
|
|
The pointer value is set either at 0 or 1
|
|
If pressed, it calls the optional function with arguments provided.
|
|
Type TOGN: works negative, when pressed it sets at 0
|
|
Type TOGR: is part of a row, redraws automatically all buttons with same *poin
|
|
|
|
"|BIT|<nr>"
|
|
When added to type, it works on a single bit <nr> (lowest order bit: nr = '0')
|
|
|
|
3. TOG3|BIT|<nr>
|
|
A toggle with 3 values!
|
|
Can be only used for short *poin.
|
|
In the third toggle setting, the bit <nr> of *( poin+1) is set.
|
|
|
|
4. ROW
|
|
Button that's part of a row.
|
|
in "min" you set a row-id number, in "max" the value you want *poin to be
|
|
assigned when you press the button. Always pass on these values as floats.
|
|
When this button is pressed, it sets the "max" value to *poin, and redraws
|
|
all buttons with the same row-id number.
|
|
|
|
5. SLI or NUMSLI or HSVSLI
|
|
Slider, number-slider or hsv-slider button.
|
|
"min" and "max" are to clamp the value to.
|
|
If you want a button type "Col" to be updated, make 'a1' equal to 'retval'
|
|
from the COL button.
|
|
|
|
6. NUM
|
|
Number button
|
|
Set the clamping values 'min' and 'max' always as float.
|
|
For UiDefButF, set a 'step' in 'a1', in 1/100's. The step value is the increment or
|
|
decrement when you click once on the right or left side of a button.
|
|
The optional button function is additionally called for each change of the *poin value.
|
|
|
|
7. TEX
|
|
Text string button.
|
|
Pointertype is standard a char. Value 'max' is length of string (pass as float).
|
|
When button is left with ESC, it doesn't put the 'retval' at the queue.
|
|
|
|
8. LABEL
|
|
Label button.
|
|
Only displays text.
|
|
If 'min' is set at 1.0, the text is printed in white.
|
|
|
|
9 SEPR
|
|
A separator line, typically used within pulldown menus.
|
|
|
|
10. MENU
|
|
Menu button.
|
|
The syntax of the string in *name defines the menu items:
|
|
- %t means the previous text becomes the title
|
|
- item separator is '|'
|
|
- return values are indicated with %x[nr] (i.e: %x12).
|
|
without returnvalues, the first item gets value 0 (incl. title!)
|
|
Example: "Do something %t| turn left %2| turn right %1| nothing %0"
|
|
|
|
11. COL
|
|
A special button that only visualizes a RGB value
|
|
In 'retval' you can put a code, which is used to identify for sliders if it needs
|
|
redraws while using the sliders. Check button '5'.
|
|
As *poin you input the pointer to the 'r' value, 'g' and 'b' are supposed to be
|
|
next to that.
|
|
|
|
|
|
------------4.2 Icon buttons
|
|
|
|
Instead of a 'name', all buttons as described for uiDefBut also can have an icon:
|
|
|
|
uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon,
|
|
short x1, short y1, short x2, short y2, void *poin,
|
|
float min, float max, float a1, float a2, char *tip)
|
|
|
|
Same syntax and types available as previous uiDefBut, but now with an icon code
|
|
instead of a name. THe icons are numbered in resources.c
|
|
|
|
uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, char *str,
|
|
short x1, short y1, short x2, short y2, float *poin,
|
|
float min, float max, float a1, float a2, char *tip)
|
|
|
|
Same again, but now with an icon and string as button name.
|
|
|
|
Two special icon buttons are available in Blender:
|
|
|
|
12. ICONROW
|
|
(uiDefIconBut)
|
|
This button pops up a vertical menu with a row of icons to choose from.
|
|
'max' = amount of icons. The icons are supposed to be ordered in a sequence
|
|
It writes in *poin which item in the menu was choosen (starting with 0).
|
|
|
|
13. ICONTEXTROW
|
|
(uiDefIconTextBut)
|
|
Same as previous, but with the texts next to it.
|
|
|
|
|
|
|
|
-----------4.3 pulldown menus / block buttons
|
|
|
|
14. BLOCK
|
|
void uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str,
|
|
short x1, short y1, short x2, short y2, char *tip)
|
|
|
|
This button creates a new block when pressed. The function argument 'func' is called
|
|
to take care of this. An example func:
|
|
|
|
static uiBlock *info_file_importmenu(void *arg_unused)
|
|
{
|
|
uiBlock *block;
|
|
short yco= 0, xco = 20;
|
|
|
|
block= uiNewBlock(&curarea->uiblocks, "importmenu", UI_EMBOSSW, UI_HELV, G.curscreen->mainwin);
|
|
uiBlockSetXOfs(block, -40); // offset to parent button
|
|
|
|
/* flags are defines */
|
|
uiDefBut(block, LABEL, 0, "VRML 2.0 options", xco, yco, 125, 19, NULL, 0.0, 0.0, 0, 0, "");
|
|
uiDefButS(block, TOG|BIT|0, 0, "SepLayers", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "");
|
|
uiDefButS(block, TOG|BIT|1, 0, "Scale 1/100", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "");
|
|
uiDefButS(block, TOG|BIT|2, 0, "Two Sided", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "");
|
|
|
|
uiBlockSetDirection(block, UI_RIGHT);
|
|
uiTextBoundsBlock(block, 50); // checks for fontsize
|
|
|
|
return block;
|
|
}
|
|
|
|
The uiDef coordinates here are only relative. When this function is called, the interface
|
|
code automatically makes sure the buttons fit in the menu nicely.
|
|
|
|
Inside a menu uiBlock, other uiBlocks can be invoked to make a hierarchical menu.
|
|
|
|
|
|
|
|
-----------4.4 specials
|
|
|
|
15. KEYEVT
|
|
|
|
void uiDefKeyevtButS(uiBlock *block, int retval, char *str,
|
|
short x1, short y1, short x2, short y2, short *spoin, char *tip)
|
|
|
|
A special button, which stores a keyvalue in *spoin. When the button is pressed,
|
|
it displays the text 'Press any Key'. A keypress then stores the value.
|
|
|
|
16. LINK and INLINK
|
|
|
|
These button present a method of linking data in Blender, by drawing a line from one
|
|
icon to another. It consists of two button types:
|
|
|
|
LINK, the 'linking from' part, can be:
|
|
- a single pointer to data (only one line allowed)
|
|
- an array of pointers to data. The LINK buttons system keeps track of allocating
|
|
space for the array, and set the correct pointers in it.
|
|
|
|
INLINK, the 'linking to' part activates creating a link, when a user releases the mouse
|
|
cursor over it, while dragging a line from the LINK button.
|
|
|
|
These buttons are defined as follows:
|
|
|
|
|
|
uiBut but= uiDefIconBut(block, LINK, 0, ICON_LINK, x1, y1, w, h, NULL, 0, 0, 0, 0, "");
|
|
/* create the LINK icon */
|
|
|
|
uiSetButLink(but, void **pt, void ***ppt, short *totlink, short fromcode, short tocode);
|
|
**pt: pointer to pointer (only one link allowed)
|
|
***ppt: pointer to pointerpointer (an array of pointers)
|
|
(Either one of these values should be NULL)
|
|
|
|
fromcode: (currently unused)
|
|
tocode: a short indicating which blocks it can link to.
|
|
|
|
|
|
uiDefIconBut(block, INLINK, 0, ICON_INLINK, x1, y1, w, h, void *poin, short fromcode, 0, 0, 0, "");
|
|
poin: the pointer of the datablock you want to create links to
|
|
fromcode: a short identifying which LINK buttons can connect to it
|
|
|
|
|
|
|
|
17. IDPOIN
|
|
void uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, int retval, char *str,
|
|
short x1, short y1, short x2, short y2, void *idpp, char *tip)
|
|
|
|
The ID struct is a generic part in structs like Object, Material, Mesh, etc.
|
|
Most linking options in Blender happens using ID's. (Mesh -> Material).
|
|
|
|
This special button in Blender visualizes an ID pointer with its name. Typing in
|
|
a new name, changes the pointer. For most ID types in Blender functions have been
|
|
written already, needed by this button, to check validity of names, and assign the pointer.
|
|
|
|
(BTW: the 'void *idpp' has to be a pointer to the ID pointer!)
|
|
|
|
Example function that can be put in 'func':
|
|
|
|
void test_scriptpoin_but(char *name, ID **idpp)
|
|
{
|
|
ID *id;
|
|
|
|
id= G.main->text.first;
|
|
while(id) {
|
|
if( strcmp(name, id->name+2)==0 ) {
|
|
*idpp= id;
|
|
return;
|
|
}
|
|
id= id->next;
|
|
}
|
|
*idpp= 0;
|
|
}
|
|
|
|
|
|
------------- 4.5 uiButton control fuctions
|
|
|
|
|
|
void uiButSetFunc(uiBut *but, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2)
|
|
When the button is pressed and released, it calls this function, with the 2 arguments.
|
|
|
|
void uiButSetFlag(uiBut *but, int flag)
|
|
set a flag for further control of button behaviour:
|
|
flag:
|
|
UI_TEXT_LEFT
|
|
|
|
int uiButGetRetVal(uiBut *but)
|
|
gives return value
|
|
|
|
|
|
</body>
|
|
<br><br><br>
|