From BlenderWiki

Jump to: navigation, search

Adding a Theme Color

Adding a new color to Blender's GUI theme system is quite easy, but involves a few steps. I've cataloged them here as a quick walk-through. In this example I'm adding theme colors for the various types of sequence editor strips.


1. Define names for the theme colors

Here we need to give the theme colors defined names so we can refer to them in our code.

source/blender/include/BIF_resources.h

Add to the end of enum { TH_AUTO, TH_BUT_OUTLINE, ... } your new theme colors, following the same naming scheme. Colors that are used in the GUI (i.e. consistent across window space types) should be added before the TH_THEMEUI define. Other window space specific colors should be added at the end.

	TH_NODE_GROUP,
 
	TH_SEQ_MOVIE,
	TH_SEQ_IMAGE,
	TH_SEQ_SCENE,
	...


2. Create variables to store the colors in

source/makesdna/DNA_userdef_types.h

This file contains the structs that get saved in SDNA, to the .B.blend user settings file. You need to add variables here to store the theme colors in when they are saved in the file. If the the colour you're adding is a cross-space UI theme color, add the necessary variables to struct ThemeUI, otherwise add them to struct ThemeSpace.

You will need to follow the DNA struct padding rules here.

	char movie[4], image[4], scene[4], audio[4];		// for sequence editor
	...


3. Set up theme API and define color values for the default theme

source/src/resources.c

BIF_ThemeGetColorPtr() is the function that finds the right color values in the User Preferences struct based on the theme color name. Find BIF_ThemeGetColorPtr() and add in the appropriate code, referencing the variables you just made in DNA_userdef_types.h . Again, refer to the existing code, and add your theme colors in the same places, depending on whether they are UI theme colors or window space theme colors.

		case TH_SEQ_MOVIE:
			cp= ts->movie; break;
		case TH_SEQ_IMAGE:
			cp= ts->image; break;
		...

BIF_InitTheme() defines the values of the new theme colors in the Default theme. Find the correct place there to add your new colors:

		/* space seq */
		btheme->tseq= btheme->tv3d;
		SETCOL(btheme->tseq.back, 	116, 116, 116, 255);
		SETCOL(btheme->tseq.movie, 	94, 165, 92, 255);
		SETCOL(btheme->tseq.image, 	39, 127, 137, 255);
		...

BIF_ThemeColorsPup() generates the theme color menu in the user preferences window. You also need to add your theme color names here so users can select and edit the theme colors themselves. Find the appropriate place and add in your new names.

		case SPACE_SEQ:
			str += sprintf(str, "Grid %%x%d|", TH_GRID);
			str += sprintf(str, "Window Sliders %%x%d|", TH_SHADE1);
			str += sprintf(str, "%%l|");
			str += sprintf(str, "Movie Strip %%x%d|", TH_SEQ_MOVIE);
			str += sprintf(str, "Image Strip %%x%d|", TH_SEQ_IMAGE);
			...

You can use

		str += sprintf(str, "%%l|");

to insert a separator in the menu.

4. Set default values for the theme colors, for when opening an old .blend file

Old .blend files (mainly the .B.blend) saved from before the theme color was added won't have any data for the new theme colors in its DNA.

source/src/usiblender.c

init_userdef_file() initializes the UserDef struct, which is where the theme colors are stored. You will need to initialize old files with default data if they're older than the current release. So if the next release (that will contain your new theme colors) is version 2.42, then search for the section that says:

		if (G.main->versionfile <= 241) {

If your theme color does not store alpha, then a good way to check that the the color doesn't exist in the file is to check to see if alpha = 0 (if it doesn't use alpha, alpha should be set to 255 by default). These snippet of code will go through the themes stored in the .blend file and initialize the new values:

		bTheme *btheme;
		for (btheme= U.themes.first; btheme; btheme= btheme->next) {
			/* Sequence editor theme, check for alpha==0 is safe, then color was never set */
			if(btheme->tseq.movie[3]==0) {
				SETCOL(btheme->tseq.movie, 	94, 165, 92, 255);
				SETCOL(btheme->tseq.image, 	39, 127, 137, 255);
 
				...
			}
		}

Of course you can integrate this into any existing code that is there to handle the same thing.


5. Make exceptions for special theme values

If your theme color uses values that aren't the usual RGB triplet you'll need to make an exception for them in the theme UI display code, to show users the correct controls needed to manipulate the values. This is necessary if, for example, the theme color involves a user-defined alpha value, or if it's controlling an number value, such as the vertex point size, or if it's a choice between multiple options, such as the UI theme's draw type.

source/src/space.c

Make the relevant modifications in info_user_themebuts(). You can see examples of other exceptions underneath the line marked with

		/* first handle exceptions, special single values, row selection, etc */

If you just want to enable access to the alpha value, add your theme color name to the list in

		if ELEM7(th_curcol, TH_PANEL, TH_LAMP, ...

And use the relevant ELEM() macro for the amount of names.


6. Update the Python API

Python has access to the theme colors, in order to load and save themes via scripts. These should be updated too. If you're adding new UI theme colors you will need to edit ThemeUI_getAttr() and ThemeUI_setAttr(). In this example, we're adding theme colors for the sequence editor, so we need to add it in ThemeSpace_getAttr() and ThemeSpace_setAttr() instead. The procedure is just about identical for either.

python/api2_2x/windowTheme.c

In ThemeSpace_getAttr(), add entries for the new theme colors, using the same names as the variables created in DNA_userdef_types.h. If they're just simple RGB colors, they should be added before any of the "else if" lines that deal with single number values.

		...
		ELSEIF_TSP_RGBA( movie )
		ELSEIF_TSP_RGBA( image )
		...

You also seem to need to add an extra amount of 's' in the line

		attrib = Py_BuildValue("[sssssssssssssssssssssssssssssssssss]", "theme", ...

for how many new items you are adding, and also add your variables to that function in the same positions as you added them above.

		... "movie", "image", ... );

Then edit ThemeSpace_setAttr() as well. You can just copy and paste the ELSEIF_TSP_RGBA lines from above into the same position here.

python/api2_2x/doc/Theme.py

Also update the documentation file with the new variables in the same locations in either class ThemeUI or class ThemeSpace


7. Use the theme color in your code!

To set the current OpenGL color to your theme color use the function:

	void 	BIF_ThemeColor(int colorid);

as

	BIF_ThemeColor(TH_SEQ_MOVIE);

With whatever theme color name you like. In BIF_resources.h, you can also see other functions such as:

void 	BIF_ThemeColorShade(int colorid, int offset);

Sets the current OpenGL color to the theme color, but darkened or lightened by the specified amount (offset)


void	BIF_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);

Sets the current OpenGL color to the theme color, darkened or lightened by the specified amount (offset) and with less or more alpha (alphaoffset)


void 	BIF_ThemeColorBlend(int colorid1, int colorid2, float fac);

Sets the current OpenGL color to a blend between two theme colors (colorid1, colorid2), blended with a specified proportion of the first to the second (fac)


void    BIF_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset);

Sets the current OpenGL color to a blend between two theme colors (colorid1, colorid2), blended with a specified proportion of the first to the second (fac), and darkened or lightened by a specified amount (offset)


There are more theme color functions, to return the color's actual numeric values rather than setting it as the current OpenGL drawing color, and to get a theme color from a specified window space type. See source/include/BIF_resources.h for all of the available functions you can use.