Creating an IGUIEnvironment

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Morgawr
Posts: 95
Joined: Wed Sep 26, 2007 7:04 pm

Creating an IGUIEnvironment

Post by Morgawr »

Hello everybody, how do I create and use an IGUIEnvironment without having to get it from the IrrlichtDriver? I want to make different environments for my different scenes which, at certain points, will change the environments loading a different one depending on the scene I'm at.. I can't find a function that sets the environment for the IrrlichtDriver... is there a way to do this?
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

I dont have an answer to your exact question, but I do have a system that I use that performs the same type of function.

the 'level' class keeps track of any gui elements that are created and it hides/restores them as the level is loaded and unloaded. This allows me to use a 'level' for anything that I want, for example, the main menu is just a level itself, which allows me to have an animated 3d background going on whiel the user is in the main menu. It also allows game objects to add gui elements to the screen (example, an 'eye' is displayed when the 'true vision' spell is active. It opens when the owner object is near a 'secret'

the CSApp has a list of 'levels' and can swap between them.

Each level has it's own SMGR which is used for rendering everything. This is particularly cool, as I can load multiple 'levels' and hot swap between them, gui included and i dont have to do any fancy footwork.

When a level becomes the active level, the app calls the Load() function of the level. When the level loses 'focus' the app calls the UnLoad() function.

Code: Select all

oid CSLevel::Load()
{
}

void CSLevel::UnLoad()
{
	// ok, a little strange behavior here. 
	// in the event that a parent exists, we have to account for that
	// so...... run backwards through the list (parent always created before child)
	// and if parent exists, dont delete the child because the parent will do that
	// when it is destroyed
	for (int x=MAX_GUI_ELEMENTS-1; x>-1; x--) 
	{
		if (m_GUIElements[x]) 
		{
			if (m_GUIElements[x]->getParent()!=0) m_GUIElements[x]->remove();
			m_GUIElements[x]=NULL;
		}
	}
}
Here is an example level to show what I mean.

Code: Select all

#pragma once

// include the needed header files
#include "CSApp.h"
#include "CSlevel.h"
#include "GlobalData.h"

#include <windows.h>
#include <stdio.h>

// a simple test level to use it is derived from CSLevel and can be added to the CSApp
// list of levels easily in the CobbleStones.h file
class CSLevel_SlideShow : public CSLevel
{
public:

	// declare the persistent variables
	ADD_PUBLIC(int,m_Timer,Timer);
	ADD_PUBLIC(int,m_MaxTimer,MaxTimer);
	ADD_PUBLIC(bool,m_Valid,Valid);
	char m_Path[1000];

	WIN32_FIND_DATA FindFileData;
	HANDLE hFind;
	DWORD dwError;
	INT retval;

	// class contructor / destructor
	CSLevel_SlideShow(void)				{	Initialize();	}
	virtual ~CSLevel_SlideShow(void)	{	Cleanup();		}

	// set all variables to a known value this prevents us from accessing memory 
	// that has not been allocated properly
	virtual void Initialize()		{
										SetTimer(0);
										SetMaxTimer(1000);
										CS_INIT(m_Valid);
									}

	// using the create() method allows us to capture errors and handle
	// them properly. 
	virtual bool Create(CSApp* App)	{	
										// create the base class
										if (!CSLevel::Create(App)) return false;	

										// create an Irrlicht FPS camera
										// if we cannot create it, then bail, otherwise
										// set the position to something nice
										m_Camera = m_Smgr->addCameraSceneNodeFPS(0,100,100);
										if (!m_Camera) return false;
										m_Camera->setPosition(core::vector3df(50,50,-150));
										
										strcpy(m_Path,"media");
										int index = 0;

										// Find the first file in the directory.
										char dirpath[1000];
										sprintf(dirpath,"%s\\*.jpg",m_Path);
										hFind = FindFirstFile(ConvertToWChar(dirpath), &FindFileData);

										if (hFind == INVALID_HANDLE_VALUE) SetValid(false);
										else SetValid(true);

										// it looks like everything went fine
										return true;	
									}

	// cleanup whatever memory mess we made
	virtual bool Cleanup()			{	
										if (m_Valid) FindClose(hFind);
										Initialize();		
										return false;			
									}

	// do whatever this calss does each frame
	virtual void Frame()			{	
										// let the base class do whatver it does each frame
										CSLevel::Frame();	

										m_Timer++;
										// show the next picture
										if (m_Timer > m_MaxTimer) 
										{
											m_Timer = 0;
											if (GetValid())
											{
												if (FindNextFile(hFind, &FindFileData) != 0) 
												{
													// remember the filename		 
													char filename[255];
													char text[255];
													wcstombs(text,FindFileData.cFileName,wcslen(FindFileData.cFileName));
													if (m_GUIElements[1])m_GUIElements[1]->remove();
													m_GUIElements[1] = 0;
													sprintf(filename,"%s\\%s",m_Path,text);

													int x = 0;
													int y = 0;
													ITexture* image = m_App->m_Engine->m_Driver->getTexture(filename);
													if (image)
													{
														x = m_App->m_Engine->m_Device->getVideoDriver()->getScreenSize().Width/2 - (image->getSize().Width / 2);
														y = m_App->m_Engine->m_Device->getVideoDriver()->getScreenSize().Height/2 - (image->getSize().Height / 2);
														m_GUIElements[1] = m_App->m_Engine->m_Gui->addImage(image,position2d<int>(x,y));
													}
												}
												else
												{
													FindClose(hFind);
													
													// Find the first file in the directory.
													char dirpath[1000];
													sprintf(dirpath,"%s\\*.jpg",m_Path);
													hFind = FindFirstFile(ConvertToWChar(dirpath), &FindFileData);

													if (hFind == INVALID_HANDLE_VALUE) SetValid(false);
													else SetValid(true);
												}
											}
										}

										// render everything using this smgr
										m_Smgr->drawAll();		
									}

	virtual bool OnEvent(SEvent event)
									{
										// let the camera have the message if it wants it
										if (m_Camera->OnEvent(event)) return true;

										// do application level message handling here
										// based upon the event type
										switch(event.EventType)
										{
										case EET_GUI_EVENT :
												{
													if (event.GUIEvent.EventType == EGET_EDITBOX_ENTER)
													{
														if (GetValid())	FindClose(hFind);
														
														strcpy(m_Path,ConvertToMultiByte((wchar_t*)event.GUIEvent.Caller->getText()));

														// Find the first file in the directory.
														char dirpath[1000];
														sprintf(dirpath,"%s\\*.jpg",m_Path);
														hFind = FindFirstFile(ConvertToWChar(dirpath), &FindFileData);

														if (hFind == INVALID_HANDLE_VALUE) SetValid(false);
														else SetValid(true);
													} 
													else
													if (event.GUIEvent.EventType == EGET_SCROLL_BAR_CHANGED)
													{
														IGUIScrollBar* sb = (IGUIScrollBar*)event.GUIEvent.Caller;
														m_MaxTimer = sb->getPos() * 100;
													}

												} break;

											case EET_KEY_INPUT_EVENT :
												{
													if (event.KeyInput.Shift) { /*nothing*/ };
												} break;
	
											// if it is a mouse event
											case EET_MOUSE_INPUT_EVENT :
												{
													// based upon the mouse event type
													switch (event.MouseInput.Event)
													{
														// if it is a mouse right button down event
														case EMIE_RMOUSE_PRESSED_DOWN : 
															{
															};	break;
														case EMIE_LMOUSE_PRESSED_DOWN :
														 { 
														 } break;

														case EMIE_LMOUSE_LEFT_UP :
														 { 
														 } break;

														case EMIE_MOUSE_MOVED :
															{
															} break;
													}
												} break;
										}

										// we did not want this message
										return false;
									}

	// this is called whenever the level is set as the application current level
	// reload whatever persistent GUI elements that there are and reset the mouse,
	// fog etc...
	virtual void Load()				{	
										// toggle whether the mouse will move the camera
										// or just mvoe around the screen for the GUI
										m_Camera->setInputReceiverEnabled(false);
										m_App->m_Engine->m_Device->getCursorControl()->setVisible(true);
										m_GUIElements[0] = m_App->m_Engine->m_Gui->addEditBox(ConvertToWChar(m_Path),core::rect<s32>(10,10,200,30),true,0,ID_PATH);
										m_GUIElements[2] = m_App->m_Engine->m_Gui->addScrollBar(true,core::rect<s32>(10,50,200,80),0,ID_SPEED);
									}
};
notice the Load() function, it is called by the App class when the level is selected as the active level.

Code: Select all

void CSApp::SetCurrentLevel(int i)
{
	if (m_Levels[i])
	{
		if (m_Levels[m_CurrentLevel]) m_Levels[m_CurrentLevel]->UnLoad();
		m_CurrentLevel = i;
		m_Levels[m_CurrentLevel]->Load();
		m_Engine->m_Device->setInputReceivingSceneManager(m_Levels[m_CurrentLevel]->m_Smgr);
	}
}
notice also that the m_Smgr of the selected level becomes the input smgr for the device. Pretty cool stuff they left us in there I think :)

last btut not least, the app calls the frame of the level each frame

Code: Select all

void CSApp::Frame()
{
	if (GetEngine())
	{
		GetEngine()->BeginFrame();
		if (m_Levels[m_CurrentLevel]) m_Levels[m_CurrentLevel]->Frame();
		GetEngine()->Frame();
		GetEngine()->EndFrame();
	}
}


so............ again, I dont have an answer to your exact question, but maybe this will give you can idea of how to simulate what you are wanting.
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

another solution would be to create the GUI with another lib like FLTK or wxWidgets and use Irrlicht for render to a widget as view port... ;)
there is a tutorial that shows how to render to a win32 window/widget and I think there are some threads in the forums, too... :lol:
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
RenoRosco
Posts: 11
Joined: Sat Sep 15, 2007 7:26 am

Post by RenoRosco »

I solved it in a similar way(Edit: like Seven). You should look after GameStates and GameStateManager tutorials i think on http://www.GameDev.net is a nice one.
Morgawr
Posts: 95
Joined: Wed Sep 26, 2007 7:04 pm

Post by Morgawr »

After posting this topic, and before reading your replies, I solved this problem myself.. Also I read that Gamestate on gameDev and I realized I did something which is similar to what is explained there.. only it's called GameScene instead of Gamestate... anyways my solution is that every GameScene has a initGUIEnv(); function which is called in the readyScene(); function which is the function called when a scene changes and another one is loaded. Inside the initGUIEnv(); I save the GUIEnvironment pointer taken from IrrlichtDevice inside an IGUIEnvironment object... Then I clear it (clearing whatever was inside it from other scenes) and I load all the GUI elements I need for that scene...
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

glad to hear you got it working.

If you are loading multiple scenes and switching between them, you might want to look into having each 'level' create it's own scenemanager also. I find it very handy to be able to load multiple worlds and then just switch between them.
Post Reply