Compiling, libraries, modules, coding guidelines and porting

Moderators: jesterKing, stiv

Post Reply
Posts: 0
Joined: Mon Feb 19, 2007 4:21 am
Location: Miami,Florida


Post by ace1 »

Can anybody out there help me use the uiBut() interface functions.
I'm reading the code and it seems that event handling code is spread everywhere across the codebase.Also,the UI functions are full of nested code.
Can anyone explain the basic theory behind using these interfaces in a
simple way?
I could write my own event handlers but because I'm developing for Blender,I want to use the native ones but I just can't grasp the idea behind it's design.

More specifically I need help in detecting when a button is pressed and depressed.Perhaps a sample code snipet could be provided.

It seems simple enough,but the UI code is so deeply nested and event handling code so transparent I can't figure it out.

I can modify and write code all day long but the development of my second new feature project has all but come to a halt because of my lack of understanding of Blender's UI code usage.

Please help me make some sense out of the whys and hows of Blender's UI interface code.
I would be eternally grateful ! :D :D :D :D :D :D :D

Posts: 0
Joined: Sun Dec 05, 2004 3:40 am
Location: Chch, NZ

Post by aligorith »


Here we go.... it may take me some time to get all of it up ;)

Hope it helps


Buttons in Blender are really multi-functional. They are also rebuild + redrawn everytime the interface is redrawn.

Helpful Hint: Find a button that seems to do what you want, copy + paste its code, then figure out what its really doing...

Firstly, most buttons in Blender directly correspond to some setting. Therefore, you must pass a pointer to the variable (in a particular struct) that the value of that setting is stored if that is the case. Hence the 9th/10th argument (such as '&ob->loc[0]') to uiDefBut*() functions.

Blender will read the current value of that setting from that variable, and display it in the UI. When the user modifies that setting in the UI, the new value is written onto that variable. Depending on the type of setting you're thinking about, you may want to add a few new variables to the relevant structs in SDNA (I won't go into detail about that here).

Settings in Blender are stored in four basic ways:
1. Bitmapped Values
- This method is used whenever you have some simple boolean (True/False) type of setting.
- A bunch of related settings (flags) are stored in the same variable.
- These variables are usually only shorts or ints, shorts where there are likely to be fewer related settings, and ints where there are more.
- Each setting should be #define-d, with capital letters for the name (be descriptive but don't make it too long). Check out DNA_action_types.h for some examples of these defines.
- Add settings-flags o a variable by doing someVar |= (<flags here separated by '|' character>);
- Remove settings-flags from a variable by doing someVar &= ~(<flags here separated by '|' character>);
- Detect if a variable has a flag by doing (someVar & SOMEFLAG). If it has that flag, it should evaluate to leave that flag.

For example...

Code: Select all

typedef struct SomeStruct {
   short fewSettings;
   int manySettings;
   short pad;
} SomeStruct;

#define FEW_APPLE 0x01
#define FEW_PEAR 0x02
#define FEW_BANANA 0x04
#define FEW_GRAPE 0x08
#define FEW_MANGO 0x10

#define MANY_A 0x001
#define MANY_B 0x002
#define MANY_C 0x004
#define MANY_D 0x008
#define MANY_E 0x010
#define MANY_F 0x020
#define MANY_G 0x040

void someFunc ()
   SomeStruct *ss;
   ss = MEM_callocN(sizeof(ss), "tempStruct");
   /* set settings to start with */
   ss->fewSettings = FEW_APPLE|FEW_PEAR;
   ss->manySettings = MANY_A|MANY_C|MANY_F;

   /* add some extra flags */
   ss->fewSettings |= (FEW_GRAPE|FEW_BANANA);
   ss->manySettings |= (MANY_D|MANY_G);
  /* add some extra flags */
   ss->fewSettings &= ~(FEW_GRAPE|FEW_BANANA);
   ss->manySettings &= ~(MANY_D|MANY_F);

  /* see whether vars have certain flags */
  printf("few has FEW_GRAPE? %d \n", (ss->fewSettings & FEW_GRAPE));
  printf("many has MANY_G? %d \n", (ss->manySettings & MANY_G));


2. Numerical Values
- These are stored as floats, ints, shorts, chars
- Use an int/short/char when you need some discrete 'mode' settings - usually combo-boxes (MENU - more on this later) or a strip of toggle buttons (ROW - more on this too), when the mode can only be one thing at once. i.e. the Renderer type menu

3. Strings
- Used for naming stuff that isn't Blender datablock data (i.e. structs that start with an 'ID *id;' entry are ID-data. Those are usually found in the include files in makesdna folder)
- char name[32];

4. ID-Pointers
... coming soon...

Secondly, buttons that do not directly correspond to some setting (or do not have any pointer to any data), are used to make stuff happen (i.e. 'Render').

There are two ways to handle events:
1. Callback function
- This option is less commonly used, and should ONLY be used when the action that is taken after the button is pressed is dependent on access to certain data that would be impossible or very hard to get hold of when doing event handling.
- Firstly, you need to get the button once you've made it

Code: Select all

but = uiDefBut*(...)
- Then, you set it to use a special function that should be executed when it is pressed. func_name is simply the name of the function to use, and var 1 and var2 are pointers to data that the function should get to use, that will be available after the current function that you wrote this code in has finished running.

Code: Select all

uiButSetFunc(but, func_name, var1, var2);
- Finally, you write the code for the function. It must be like the following example (you can declare it as 'static void' if you wish)

Code: Select all

void something_special_cb (void *var1, void *var2)
   ... do something useful ...
- This callback function will get executed when the button gets pressed, but before it's event code is handled.

2. Event code
- The second or third argument to a uiDefBut*() function, usually in capital letters, is the event that gets added to the event queue once the button has set it's values/run it's callback function.
- There are various places where events are handled, but I won't mention them here for now.

Thirdly, button types:
The way a button appears/behaves in the interface depends on the second argument. This will have one of the following values (and a few more):

Code: Select all


- BUT -> just a standard button that just lets you click on it
- MENU -> a combo-box thing. it pops up a list of choices when you click on it
- NUM -> a numeric slider [< NAME:Value >] for relatively un-limited values
- NUMSLI -> a numeric slider [ Name Value ---|-------- ] for relative limited values
- TOG -> mainly for bitmapped settings
- TOGN -> like toggle but acts the opposite way. i.e. when value & SOMEFLAG, then it will be off instead of on.
- ROW -> for mode settings where only variable can only have one value at a time

Fourthly, name of function to use:
- If there is no variable to write to, use
otherwise, use uiDefBut as the start of the name
- If the variable to write to is a float, the last character of the name must be a F
- If the variable to write to is an int, the last character of the name must be an I
- If the variable to write to is a short, the last character of the name must be a S
- If the variable to write to is a char, the last character of the name must be a C
- If the setting the button affects is accessed via bitmapping, the start of the name is uiDefButBit instead of uiDefBut
- For other special cases involving icons/text/menus, search around the source code a bit.
Last edited by aligorith on Sun Sep 02, 2007 11:47 am, edited 2 times in total.

Posts: 0
Joined: Mon Feb 19, 2007 4:21 am
Location: Miami,Florida

Post by ace1 »

Thanks for the info so far!
When you finish the "explanation"(PLEASE FINISH :D ) I'm going to see if I (or you) can wiki it.
It will will help a lot of new developers.
Please finish explaining.You don't know how grateful I am for you to take the time to help me with your Blender coding expertise!

I can code but the UI code is a black box to me.But what you have provided so far has helped as well.

Posts: 0
Joined: Mon Feb 19, 2007 4:21 am
Location: Miami,Florida

Post by ace1 »

I'm going to aquire wiki editing rights today.I think that this needs to be posted in the developers section(Hacker's Guide).This documentation was a long time in coming.The more persons that understand the code's architecture,the faster the development because more coders will be less intimidated by Blender's codebase.You will be given credit for the info.
If there's more to be explained, please do so.

P.S. You write VERY GOOD documentation.Simple and easy to follow.

Thanks a million sofar! :D

Posts: 0
Joined: Mon Feb 19, 2007 4:21 am
Location: Miami,Florida


Post by ace1 »

Can anyone explain the allqueue() functions in the blender code to me?
It's everywhere.I'm in the process of coding another new feature and learning UI code while in the process which isn't as easy as I thought.But, I know this fuction is key to screen display.

Thanks ! :D

Posts: 0
Joined: Sun Feb 19, 2006 4:14 pm

Post by BeBraw »

allqueue is used to redraw wanted areas of the main window. Check it out at space.c. That should clear things up a bit.

Missing proper allqueue results in values not being updated appropriately. There are several use cases to consider (for instance there could be multiple buttons windows open with same context -> redraw of all buttons windows is needed or else values update only after the user does something to trigger the redraw).

The system could be neater (automatic redraws provided by proper messaging system) but allqueue is what we have now.

Site Admin
Posts: 207
Joined: Fri Oct 18, 2002 12:48 pm
Location: Finland

Post by jesterKing »

Just FYI, there's also an interface API document in doc/ ...


Post Reply