Startup Splash Screen
by Robert Blanchet Jr. · 06/24/2002 (12:08 pm) · 17 comments
Download Code File
Unfortunately this resource is going to be a bit bare bones.
I had originally spent an hour typing up this resource only
for it to be lost to the internet gods and I lack the motivation
to try and reproduce all of the work that I lost.
Below I'll provide the code and script necessary for you to add
a splash screen fade in/fade out effect to your games startup
sequence. The primary motivation behind this resource was
Phil Carlisle's RWTA startup splash screens and the new Garage
Games startup sequence to the new Tribes 2 patch.
I used Phil's script code as a base for altering the startup gui
sequence and then added in my own source code to produce the
graphics effects.
To begin I want you to load up your trusty Compiler and add two
files to the gui folder of the Torque Workspace, a header file,
and a C++ source file. Open up the header file and add the
following:
to discuss. You'll notice, however, that I'm going to be using
some of the same code from guiChunkedBitmapCtrl. Unfortunately
that control doesn't have an associate header file so I'm forced to
either, make one for it, or re-invent the wheel, since I'm lazy
we are going to re-invent the wheel ;)
Go ahead and save the header file and open up the C++ source file.
There is a lot of code here but I've provided comments just in case
you get confused. If you still can't figure out how something works,
please feel free to ask here in the forums. Now that you have
the C++ source file open, go ahead and add all of the following
code:
Now that we are done with the source code portion, we can go ahead and compile the engine
while we move on to the next section.
The first thing we need to add to the scripts is a GUI script that creates an instance
of our new control and defines its properties. So open up your favorite text editor
and type out the following:
the gui control that my bitmap is "gg_logo" and that my fadeFactor is 50. Which
is then multiplied by 10,000 in the hardcode. You should recognize these two
properties from our C++ code earlier. The other important thing to notice
is that I define another control within the first control. This control will be
responsible for recognizing input from either the mouse or the keyboard.
Save this script as StartupGui.gui and place it in the torque folder fps/client/ui
It's very important that you make sure it's in that location and that the extension
is *.gui and not *.gui.txt.
Next we need to open up init.cs from the location fps/client/
There are several changes and additions we need to make to this file
so that we can add our new control to the startup sequence of Torque.
Scroll through this file until you find the following line of code:
Now search further down and find:
on the screen, we need to make sure that the MainMenuGui is loaded after
the fade in/fade out sequence is done, or if there is user input.
Just a bit further down you'll find the following:
GUI Canvas. This can happen through a number of ways. In our case it
happens when our fade in/fade out effect has finished. onInputEvent is
called whenever the user clicks the mouse or hits a key on the keyboard.
Go ahead and save the changes to init.cs
In the zip file I've provided a sample logo splash screen. You may wish to use
this or make your own, but make sure that it is located in fps/client/ui and
that the bitmap field of our StartupGui.gui script is changed to reflect the
new image.
Again, if you have any questions, feel free to ask. I hope you enjoy this resource.
Unfortunately this resource is going to be a bit bare bones.
I had originally spent an hour typing up this resource only
for it to be lost to the internet gods and I lack the motivation
to try and reproduce all of the work that I lost.
Below I'll provide the code and script necessary for you to add
a splash screen fade in/fade out effect to your games startup
sequence. The primary motivation behind this resource was
Phil Carlisle's RWTA startup splash screens and the new Garage
Games startup sequence to the new Tribes 2 patch.
I used Phil's script code as a base for altering the startup gui
sequence and then added in my own source code to produce the
graphics effects.
To begin I want you to load up your trusty Compiler and add two
files to the gui folder of the Torque Workspace, a header file,
and a C++ source file. Open up the header file and add the
following:
#ifndef _GUISPLASHSCREEN_H_
#define _GUISPLASHSCREEN_H_
#ifndef _CONSOLE_H_
#include "console/console.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _GUICANVAS_H_
#include "gui/guiCanvas.h"
#endif
#ifndef _GUICONTROL_H_
#include "gui/guiControl.h"
#endif
#ifndef _DGL_H_
#include "dgl/dgl.h"
#endif
#ifndef _GBITMAP_H_
#include "dgl/gBitmap.h"
#endif
#ifndef _GTEXMANAGER_H_
#include "dgl/gTexManager.h"
#endif
#ifndef _GCHUNKEDTEXMANAGER_H_
#include "dgl/gChunkedTexManager.h"
#endif
class GuiSplashScreen : public GuiControl
{
private:
typedef GuiControl Parent;
void renderRegion(const Point2I &offset, const Point2I &extent);
protected:
// Splash Screen Bitmap Name
StringTableEntry mLogoName;
// Currently selected bitmap
ChunkedTextureHandle mTexHandle;
// Keep track of time
F32 mFadeFactor;
F32 mTime;
// Keep track of fade state
bool mFadeIn;
public:
// Creation methods
DECLARE_CONOBJECT(GuiSplashScreen);
GuiSplashScreen();
static void initPersistFields();
static void consoleInit();
// Parental methods
bool onWake();
void onSleep();
void onRender(Point2I offset, const RectI &updateRect);
};
#endif // _GUISPLASHSCREEN_H_There is nothing really special about the header file that we needto discuss. You'll notice, however, that I'm going to be using
some of the same code from guiChunkedBitmapCtrl. Unfortunately
that control doesn't have an associate header file so I'm forced to
either, make one for it, or re-invent the wheel, since I'm lazy
we are going to re-invent the wheel ;)
Go ahead and save the header file and open up the C++ source file.
There is a lot of code here but I've provided comments just in case
you get confused. If you still can't figure out how something works,
please feel free to ask here in the forums. Now that you have
the C++ source file open, go ahead and add all of the following
code:
#include "gui/guiSplashScreen.h"
IMPLEMENT_CONOBJECT(GuiSplashScreen);
void GuiSplashScreen::initPersistFields()
{
Parent::initPersistFields();
addField( "bitmap", TypeFilename, Offset( mLogoName, GuiSplashScreen ) );
addField( "fadeFactor", TypeF32, Offset( mFadeFactor, GuiSplashScreen) );
}
void GuiSplashScreen::consoleInit()
{
// do nothing
}
GuiSplashScreen::GuiSplashScreen()
{
// Clear bitmap names
mLogoName = StringTable->insert("");
// Clear times
mTime = 0.0f;
// Set Fade State
mFadeIn = true;
}
bool GuiSplashScreen::onWake()
{
if(!Parent::onWake())
{
return false;
}
mTexHandle = ChunkedTextureHandle( mLogoName );
// Fades
mFadeFactor *= 10000.0f; // Multiply by 10,000 so the fade is produced over a long period of time
mTime = 0.0f;
mFadeIn = true;
return true;
}
void GuiSplashScreen::onSleep()
{
// Clear everything
mTexHandle = NULL;
mFadeFactor = 0.0f;
mTime = 0.0f;
mFadeIn = true;
Parent::onSleep();
}
// Function taken from guiChunkedBitmapCtrl
void GuiSplashScreen::renderRegion(const Point2I &offset, const Point2I &extent)
{
U32 widthCount = mTexHandle.getTextureCountWidth();
U32 heightCount = mTexHandle.getTextureCountHeight();
if(!widthCount || !heightCount)
{
return;
}
F32 widthScale = F32(extent.x) / F32(mTexHandle.getWidth());
F32 heightScale = F32(extent.y) / F32(mTexHandle.getHeight());
dglSetBitmapModulation(ColorF(1,1,1));
for(U32 i = 0; i < widthCount; i++)
{
for(U32 j = 0; j < heightCount; j++)
{
TextureHandle t = mTexHandle.getSubTexture(i, j);
RectI stretchRegion;
stretchRegion.point.x = (S32)(i * 256 * widthScale + offset.x);
stretchRegion.point.y = (S32)(j * 256 * heightScale + offset.y);
if(i == widthCount - 1)
{
stretchRegion.extent.x = extent.x + offset.x - stretchRegion.point.x;
}
else
{
stretchRegion.extent.x = (S32)((i * 256 + t.getWidth() ) * widthScale + offset.x - stretchRegion.point.x);
}
if(j == heightCount - 1)
{
stretchRegion.extent.y = extent.y + offset.y - stretchRegion.point.y;
}
else
{
stretchRegion.extent.y = (S32)((j * 256 + t.getHeight()) * heightScale + offset.y - stretchRegion.point.y);
}
dglDrawBitmapStretch(t, stretchRegion);
}
}
}
void GuiSplashScreen::onRender(Point2I offset, const RectI &updateRect)
{
// Make sure we have a texture handle
if(mTexHandle)
{
if(mFadeIn == true)
{
// Fade In Effect
if(mTime < mFadeFactor)
{
// Calculate alpha for the overlayed rectangle over the logo
F32 fade = 1 - (mTime / mFadeFactor);
// Render the logo
renderRegion(offset, mBounds.extent);
// Render a rectangle the size of the screen over the top of our logo
dglDrawRectFill(mBounds, ColorF(0, 0, 0, fade));
// Make sure to update the scene
setUpdate();
// Update time
mTime += F32(Platform::getVirtualMilliseconds());
}
else
{
// We are done fading in, so lets fade back out
mFadeIn = false;
mTime = 0.0f;
}
}
else
{
// Fade Out Effect
if(mTime < mFadeFactor)
{
// Render the logo
renderRegion(offset, mBounds.extent);
// Render a rectangle the size of the screen over the top of our logo
dglDrawRectFill(mBounds, ColorF(0, 0, 0, (mTime / mFadeFactor)));
// Update the scene
setUpdate();
// Update time
mTime += F32(Platform::getVirtualMilliseconds());
}
else
{
// We are done with both the fade in and fade out effect,
// so pop the control off the canvas
getRoot()->popDialogControl(this);
}
}
}
else
{
// We didn't have a texture handle, so might as well pop the control off the canvas right away
getRoot()->popDialogControl(this);
}
}Again if you need help, just ask :)Now that we are done with the source code portion, we can go ahead and compile the engine
while we move on to the next section.
The first thing we need to add to the scripts is a GUI script that creates an instance
of our new control and defines its properties. So open up your favorite text editor
and type out the following:
//--- OBJECT WRITE BEGIN ---
new GuiSplashScreen(StartupGui) {
profile = "GuiDefaultProfile";
horizSizing = "width";
vertSizing = "height";
position = "0 0";
extent = "640 480";
minExtent = "8 8";
visible = "1";
helpTag = "0";
bitmap = "./gg_logo";
fadeFactor = "50"; // value is multiplied by 10,000 internally
noCursor=1;
new GuiInputCtrl(StartupInputCtrl) {
profile = "GuiInputCtrlProfile";
position = "0 0";
extent = "10 10";
};
};
//--- OBJECT WRITE END ---There are only two things to really discuss here. One, you'll notice that I tellthe gui control that my bitmap is "gg_logo" and that my fadeFactor is 50. Which
is then multiplied by 10,000 in the hardcode. You should recognize these two
properties from our C++ code earlier. The other important thing to notice
is that I define another control within the first control. This control will be
responsible for recognizing input from either the mouse or the keyboard.
Save this script as StartupGui.gui and place it in the torque folder fps/client/ui
It's very important that you make sure it's in that location and that the extension
is *.gui and not *.gui.txt.
Next we need to open up init.cs from the location fps/client/
There are several changes and additions we need to make to this file
so that we can add our new control to the startup sequence of Torque.
Scroll through this file until you find the following line of code:
// Load up the shell GUIs
exec("./ui/mainMenuGui.gui");And change it to this:// Load up the shell GUIs
exec("./ui/StartupGui.gui"); // Startup Splash
exec("./ui/mainMenuGui.gui");Now search further down and find:
// Start up the main menu... this is separated out into a // method for easier mod override. loadMainMenu();And change it to the following:
// Display our startup splash screen Canvas.setContent( StartupGui );Now that we've made sure our splash screen is the first thing to display
on the screen, we need to make sure that the MainMenuGui is loaded after
the fade in/fade out sequence is done, or if there is user input.
Just a bit further down you'll find the following:
function loadMainMenu()
{
// Startup the client with the Main menu...
Canvas.setContent( MainMenuGui );
Canvas.setCursor("DefaultCursor");
}Add 2 functions before that which read:function StartupGui::onSleep(%this)
{
loadMainMenu();
}
function StartupInputCtrl::onInputEvent(%this, %dev, %evt, %make)
{
if(%make)
{
loadMainMenu();
}
}onSleep is called whenever the control associated with it is popped off the GUI Canvas. This can happen through a number of ways. In our case it
happens when our fade in/fade out effect has finished. onInputEvent is
called whenever the user clicks the mouse or hits a key on the keyboard.
Go ahead and save the changes to init.cs
In the zip file I've provided a sample logo splash screen. You may wish to use
this or make your own, but make sure that it is located in fps/client/ui and
that the bitmap field of our StartupGui.gui script is changed to reflect the
new image.
Again, if you have any questions, feel free to ask. I hope you enjoy this resource.
About the author
#2
06/24/2002 (1:59 pm)
This can also be done by simply using a gui control made by Melvyn May which masks the screen to a color, what i did was simplify melv's code a bit so it wont use masks, etc and added it to the canvas as a new set of functions. Same thing, same effect, nice work
#3
You're right Xavier, I could use Melv's mask code to do this but chose not to for a variety of reasons.
06/24/2002 (2:17 pm)
Thanks for the comments. Next time I'll be sure to explain more of what is going on and why it happens that way for tutorials.You're right Xavier, I could use Melv's mask code to do this but chose not to for a variety of reasons.
#4
Can't imagine what the ressource would have been before you lost it : cool by itself, but in context, very, very nice for someone who had just lost at least an hour of work down the cyber-drain... ;)
Bravo, and thank you
06/24/2002 (2:32 pm)
Nice one, and kinda primordial, since every team are eventually going to want their own splashup screen, whether accompanied by the GG/Torque one or not (don't remember if the license is specific about this or not).Can't imagine what the ressource would have been before you lost it : cool by itself, but in context, very, very nice for someone who had just lost at least an hour of work down the cyber-drain... ;)
Bravo, and thank you
#5
06/25/2002 (2:59 pm)
what are some of those reasons robert?
#6
1. To learn something from the experience
2. Personal achievement ;p
3. Showing others yet another way to do something
06/25/2002 (5:08 pm)
To name a few:1. To learn something from the experience
2. Personal achievement ;p
3. Showing others yet another way to do something
#8
Currently when the fading is done, it does a popDialogControl; which immediatly removes the faded screen and causes the maingui to be pushed to the top.
Why not have the fade out actualy fade to the next gui (maingui)?
-Ron
06/29/2002 (8:47 am)
Another usefull addition would be to modify the code so you can fade between gui elements.Currently when the fading is done, it does a popDialogControl; which immediatly removes the faded screen and causes the maingui to be pushed to the top.
Why not have the fade out actualy fade to the next gui (maingui)?
-Ron
#9
I don't really understand what you are trying to say in your last question. Currently this control does fade to the MainGUI, it's just not hardcoded.
Unless you mean fading to the MainGUI directly without going to black then I don't really understand your question.
06/29/2002 (12:13 pm)
Ron, the reason behind popping the control off immediately is because this was designed as a specialized class in which its sole lot in life was to show a splash screen and then remove itself.I don't really understand what you are trying to say in your last question. Currently this control does fade to the MainGUI, it's just not hardcoded.
Unless you mean fading to the MainGUI directly without going to black then I don't really understand your question.
#10
07/10/2002 (5:24 pm)
Robert, I found this resource very useful. I think there might be a prob however: adding this appears to "kill" the show tool. I created two identical apps, one with the splash screen, one without. One with would not open show tool. hmmm. Don't have a clue what might cause this but thought you could get to it quicker than I.
#11
08/15/2003 (4:45 pm)
Does this support multiple splash screen's? for example, a garagegames logo, then my own logo, then start of game. thanks chris
#12
@Desmond the reason for the nonfunctional show tool is because of these functions in the resource
as soon as the Fade effect is done it pops the MainMenu which in turn breaks the show tool. I have fixed this by chaning the loadMainMenu() function as such
also note that the StartupGui::onSleep() function causes a crash when you use this resource with the latest HEAD. You get an "Control is already sleeping" assert and crash.
-Ron
12/09/2003 (6:23 am)
WoW this is a dated resource :) but I have new info to add :)@Desmond the reason for the nonfunctional show tool is because of these functions in the resource
function loadMainMenu()
{ // Startup the client with the Main menu... Canvas.setContent( MainMenuGui );
Canvas.setCursor("DefaultCursor");
}
function StartupGui::onSleep(%this)
{
loadMainMenu();
}
function StartupInputCtrl::onInputEvent(%this, %dev, %evt, %make)
{
if(%make)
{ loadMainMenu();
}
}as soon as the Fade effect is done it pops the MainMenu which in turn breaks the show tool. I have fixed this by chaning the loadMainMenu() function as such
function loadMainMenu()
{
echo("loadMainMenu()");
// Startup the client with the Main menu..
if( $currentMod $= "show" )
{
Canvas.setContent( TSShowGui );
Canvas.setCursor("DefaultCursor");
} else {
Canvas.setContent( MainMenuGui );
Canvas.setCursor("DefaultCursor");
}
}also note that the StartupGui::onSleep() function causes a crash when you use this resource with the latest HEAD. You get an "Control is already sleeping" assert and crash.
-Ron
#13
Just commenting out the parent::onSleep(); seems to make it crash for me...
of course that could be a different crash caused by something totally unrelated.
03/25/2004 (4:03 pm)
I've just updated to the latest release 1.2.0 and I'm getting this Already sleeping error. I don't know enough about the way the gui control system works at the moment to fix it, but if you have a quick solution I'd appreciate it. Just commenting out the parent::onSleep(); seems to make it crash for me...
of course that could be a different crash caused by something totally unrelated.
#14
Our programmer is in the process of taking both the GuiControl and GuiSplashScreen code apart to see if I can find out what is happening but so far nothing stands out. Does anyone have a clue as to what is happening here?
07/30/2004 (7:21 am)
We started using Blachet's splash screen resource with Version 1.2.2 of the engine and it worked like a dream. This week we desided that we needed to start using the Torque HEAd and now we get a chrash because the "GuiControl::sleep:Child control is already asleep". Our programmer is in the process of taking both the GuiControl and GuiSplashScreen code apart to see if I can find out what is happening but so far nothing stands out. Does anyone have a clue as to what is happening here?
#15
07/30/2004 (12:16 pm)
There was a forum discussion re: the sleep function causing issues related to dedicated servers I think (can't remember exactly)....and it was changed in the HEAD.
#16
03/15/2005 (2:56 am)
We are also getting the same error "GuiControl::sleep:Child control is already asleep". Anyone has a solution?
#17
12/05/2005 (11:38 am)
why not use the GuiFadeinBitmapCtrl instead?
Torque Owner Philip Plante