Page 1 of 1

Custom menu backgrounds

Posted: Mon Mar 23, 2009 9:58 am
by Herr W
Hi everyone!

I'm trying to put in custom background images for each submenu... So far with medium success, i.e. it works in some submenues but doesn't in others.

If I got the tutorial on Code3Arena right, four steps are required:

1. Defining that there's gonna be a background shader...

Code: Select all

#define BACKGROUND_SHADER
2. Don't know what the first part does, but the second seems to be an alternative solid color if no shader is defined:

Code: Select all

qhandle_t	BackgroundShader;
vec4_t color_background	        = {0.00, 0.35, 0.69, 1.00};
3. In the C3A example the following belongs into the "_DRAW" part:

Code: Select all

#ifdef BACKGROUND_SHADER 
    UI_DrawHandlePic(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, BackgroundShader);
#else 
    UI_FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, color_background);
#endif
4. ... And this here right to the end of the code:

Code: Select all

#ifdef BACKGROUND_SHADER
	BackgroundShader = 
	  trap_R_RegisterShaderNoMip("*YOURSHADER_HERE*");
#endif
It seems as if I put "1","2" and "4" in the right places, but "3" is making trouble, cause some of the submenues lack that "_DRAW" part. Or I'm just to stupid to find it... :confused:

- Anyone who can help?!

Re: Custom menu backgrounds

Posted: Mon Mar 23, 2009 2:43 pm
by ^misantropia^
Wouldn't you rather handle this in UI_Refresh() in q3_ui/ui_atoms.c? You can preload the shaders in Menu_Cache() in q3_ui/ui_qmenu.c.

Re: Custom menu backgrounds

Posted: Tue Mar 24, 2009 9:49 am
by Herr W
Thanks! :)

I guess the part I've to concentrate on in ui_atoms.c is this:

Code: Select all

			if( uis.activemenu->showlogo ) {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackShader );
			}
			else {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackNoLogoShader );
			}
Seems as if this tells the game to draw the shader "menuback" in the main menu ("s_main.menu.showlogo = qtrue;") and the shader "menubacknologo" in all other submenues.

In ui_qmenu.c these lines look promising:

Code: Select all

	if ( uis.glconfig.hardwareType == GLHW_RAGEPRO ) {
		// the blend effect turns to shit with the normal 
		uis.menuBackShader	= trap_R_RegisterShaderNoMip( "menubackRagePro" );
	} else {
		uis.menuBackShader	= trap_R_RegisterShaderNoMip( "menuback" );
	}
	uis.menuBackNoLogoShader = trap_R_RegisterShaderNoMip( "menubacknologo" );
Okay, so if I want to draw the red Q3-logo to the back of each submenu I asume I just have to add that "s_main.menu.showlogo = qtrue;" line to each ones code.
Question is how to create more alternatives... Before I start messing up the code: Is this the right way...

1. Put in a new "if"-function for each background...

Code: Select all

			if( uis.activemenu->showlogo ) {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackShader );
			}
[color=#FF0000]if( uis.activemenu->showlogoA ) {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackShaderA );
			}
if( uis.activemenu->showlogoB ) {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackShaderB );[/color]
			else {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackNoLogoShader );
			}
2. then add new "else"-functions to ui_qmenu.c:

Code: Select all

	if ( uis.glconfig.hardwareType == GLHW_RAGEPRO ) {
		// the blend effect turns to shit with the normal 
		uis.menuBackShader	= trap_R_RegisterShaderNoMip( "menubackRagePro" );
	} else {
		uis.menuBackShader	= trap_R_RegisterShaderNoMip( "menuback" );
	}[color=#FF0000]else {
		uis.menuBackShaderA	= trap_R_RegisterShaderNoMip( "menubackA" );
	}else {
		uis.menuBackShaderB	= trap_R_RegisterShaderNoMip( "menubackB" );
	}[/color]
	uis.menuBackNoLogoShader = trap_R_RegisterShaderNoMip( "menubacknologo" );
3. Create shaders with the appropiate names ("menubackA", "menubackB"...)
4. Add a "s_main.menu.showlogoA = qtrue;", "s_main.menu.showlogoB = qtrue;" line to the submenues' code?

No, it is trickier than that, right?!

Re: Custom menu backgrounds

Posted: Tue Mar 24, 2009 1:42 pm
by ^misantropia^
I'd simplify the code in #2 to this:

Code: Select all

if ( uis.glconfig.hardwareType == GLHW_RAGEPRO ) {
    uis.menuBackShader        = trap_R_RegisterShaderNoMip( "menubackRagePro" );
    uis.menuSettingBackShader = trap_R_RegisterShaderNoMip( "menubackRagePro" );  
    // etc.
} else {
    uis.menuBackShader        = trap_R_RegisterShaderNoMip( "menuback" );
    uis.menuSettingBackShader = trap_R_RegisterShaderNoMip( "menubackSetting" );
    // etc.
}
Unconditionally load the shaders; the overhead is negligible and you'll always have a valid resource handle.

Re: Custom menu backgrounds

Posted: Tue Mar 24, 2009 1:46 pm
by ^misantropia^
Oh, and a slightly cleaner approach would be converting showlogo to an enum (and maybe renaming it), then do this:

Code: Select all

{
    qhandle_t shader;
    switch ( uis.activemenu->showlogo ) {
    case LOGO_DEFAULT:
        shader = uis.menuBackShader;
        break;
    case LOGO_SETTINGS:
        shader = uis.menuSettingsBackShader;
        break;
    }
    UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, shader );
}
Easier to read and maintain, and if you ever add a logo to the enum but forget to add it to the switch statement, the compiler will warn you about it.

Re: Custom menu backgrounds

Posted: Wed Mar 25, 2009 8:00 am
by Herr W
^misantropia^ wrote:Oh, and a slightly cleaner approach would be converting showlogo to an enum (and maybe renaming it), then do this:
That second part was too much at a time for me...

Google says an "enum" is
a user-defined type consisting of a set of enumerators( enumerator --- named integer constant)
- I have no idea what this means and how I could convert "showlogo" into one?!

The other thing I didn't get is where that second part of code you posted belongs to. :confused:

Can you help me again? (I think I'm pretty close to the desired result already.) :D

Re: Custom menu backgrounds

Posted: Wed Mar 25, 2009 9:17 pm
by corncobman
Basically enums are like whole numbers, starting at 0. The values never change and are associated with the name you give them.

so LOGO_DEFAULT has the value 0

and LOGO_SETTINGS has the value 1

Re: Custom menu backgrounds

Posted: Thu Mar 26, 2009 7:55 am
by Herr W
Still doesn't work.

I have this in ui_atoms.c ...

Code: Select all

UI_UpdateCvars();

	if ( uis.activemenu )
	{
		if (uis.activemenu->fullscreen)
		{
			// draw the background
			if( uis.activemenu->showlogo ) {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackShader );
			}
			if( uis.activemenu->showlogomenu ) {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menusplevelBackShader );
			}
			if( uis.activemenu->showlogostartserver ) {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menustartserverBackShader );
			}
// etc
			else {
				UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackNoLogoShader );
... this in ui_qmenu.c ...

Code: Select all

	uis.whiteShader = trap_R_RegisterShaderNoMip( "white" );
	if ( uis.glconfig.hardwareType == GLHW_RAGEPRO ) {
		// the blend effect turns to shit with the normal 
		uis.menuBackShader	= trap_R_RegisterShaderNoMip( "menubackRagePro" );
		uis.menusplevelBackShader = trap_R_RegisterShaderNoMip( "menubackRagePro" );
//etc
	} else {
		uis.menuBackShader	= trap_R_RegisterShaderNoMip( "menuback" );
		uis.menusplevelBackShader = trap_R_RegisterShaderNoMip( "menubacksplevel" );
	}
	uis.menuBackNoLogoShader = trap_R_RegisterShaderNoMip( "menubacknologo" );
... and something like ...

Code: Select all

	s_errorMessage.menu.showlogomenu = qtrue;

Code: Select all

	levelMenuInfo.menu.showlogosplevel = qtrue
etc. in the submenues' code.

But the compiler throws out a list of
#136: struct "_tag_menuframework" has no field "showlogomenu" ui_atoms.c q3rev_1/quake3-1.32b/code/q3_ui line 1234 C/C++ Problem
#136: struct "_tag_menuframework" has no field "showlogosplevel" ui_atoms.c q3rev_1/quake3-1.32b/code/q3_ui line 1237 C/C++ Problem
and
#136: struct "<unnamed>" has no field "menuBackShader" ui_atoms.c q3rev_1/quake3-1.32b/code/q3_ui line 1235 C/C++ Problem
#136: struct "<unnamed>" has no field "menusplevelBackShader" ui_atoms.c q3rev_1/quake3-1.32b/code/q3_ui line 1238 C/C++ Problem
errors. :cry:
Something seems to miss. But what?!

Re: Custom menu backgrounds

Posted: Thu Mar 26, 2009 9:11 am
by ^misantropia^
C 101: did you add those fields to their respective structs? They live in q3_ui/ui_local.h, if memory deceives me not.

Re: Custom menu backgrounds

Posted: Thu Mar 26, 2009 8:38 pm
by epicgoo
agreed.
you will be happier if you learn some basic C. just a little

Re: Custom menu backgrounds

Posted: Fri Mar 27, 2009 4:05 pm
by Herr W
Thanks again, ^misantropia^!

Seems as if I'm on a good way... The compiler doesn't throw out error messages anymore. :D Bad news is, that there are still no background images displayed. Even the one in the main menu is missing. Extremely weird, cause that part of the code is in it's original state. Couldn't have messed anything up there...
epicgoo wrote:agreed.
you will be happier if you learn some basic C. just a little
If only I had more spare time... But making a whole mod my oneself is already taking most of it. ;)
- So, no other chance than setting my hope on the helpfulness of you guys here when it comes to coding!

Re: Custom menu backgrounds

Posted: Fri Mar 27, 2009 6:25 pm
by ^misantropia^
Could you post a diff (unified format) of the files you've modified for this? If you use Windows, google for 'windows diff' and a few tools will pop up.

Re: Custom menu backgrounds

Posted: Sat Mar 28, 2009 2:14 pm
by ^misantropia^
Thanks for sending the code, my friend. I'm pretty sure I found your bug and it's a logic error. Behold!

Code: Select all

            // draw the background
            if( uis.activemenu->showlogo ) {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackShader );
            }
//WW start   
            if( uis.activemenu->showlogomenu ) {   
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menumenuBackShader );   
            }
            if( uis.activemenu->showlogosplevel ) {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menusplevelBackShader );
            }
            if( uis.activemenu->showlogostartserver ) {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menustartserverBackShader );
            }
            if( uis.activemenu->showlogoservers2 ) {   
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuservers2BackShader );   
            }
            if( uis.activemenu->showlogoplayermodel ) {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuplayermodelBackShader );
            }
            if( uis.activemenu->showlogocontrols2 ) {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menucontrols2BackShader );
            }
            if( uis.activemenu->showlogoplayersettings ) {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuplayersettingsBackShader );
            }
            if( uis.activemenu->showlogosound ) {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menusoundBackShader );
            }
            if( uis.activemenu->showlogocredits ) {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menucreditsBackShader );
            }
//WW end
            else {
                UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackNoLogoShader );
            }
You need to turn the 'if' statements into 'else if' statements (except for the first one, obviously). Why? Take a look at the last if: showlogocredits will almost always be false, which results in the else clause being executed and thus the menuBackNoLogoShader being drawn. QED. =)

Re: Custom menu backgrounds

Posted: Sun Mar 29, 2009 8:56 am
by Herr W
^misantropia^ wrote:You need to turn the 'if' statements into 'else if' statements (except for the first one, obviously). Why? Take a look at the last if: showlogocredits will almost always be false, which results in the else clause being executed and thus the menuBackNoLogoShader being drawn. QED. =)
Sounds absolutely logically. ;) But I would have never figured that out by myself!
Now everything works perfectly! Thanks a lot!