Hey ive got a couple of questions
im creating a menu for a uni project i currently use the demo7 as the base code
ive created about 8 full windows inside the layout xml document each window contains different buttons and text areas some contain pictures and other widget thingys
question 1
whats the most efficent way of swapping menu windows currently i set all except 1 menu as invisible on startup then switch the new menu to visible and the previous to invisible would it be better to have only one window and somehow dynamically create the buttons and text areas from a file with new content or load all at the start as it is currently and use setVisible
question 2
is there a way to set a global subscribe event to the root window so i dont have to create seperate event calls for every single button im currently using code from the forums for event calls or at the very least create an event call one level higher than the button so it handles all the buttons for that menu window
this is the forum posts i found the single function event handler code from
http://www.cegui.org.uk/phpBB2/viewtopi ... ght=button
and
http://www.cegui.org.uk/wiki/index.php/ ... e_Callback
but these only confine the event calls to one function they dont fix the problem of having to set the same event to every single button
this is a problem because i have about 25 buttons in total
any help is appreciated thankyou
[resolved] creating menu system for a game
Moderators: CEGUI MVP, CEGUI Team
[resolved] creating menu system for a game
Last edited by duindain on Mon Jun 11, 2007 18:02, edited 2 times in total.
>> whats the most efficent way of swapping menu windows
It depends on the number of menu windows you have. If there's 100-500 then loading each one, even if invisible, would take up too many resources (memory) unnecessarily. Instead you'd be better off loading a single menu window at a time, destroying it (it's widgets and subscribed events) and loading a new menu window. But with this approach you now have to deal with disk access, which may cause unwanted pauses.
If you're reading from a hard disk then access is pretty fast, but if your resources are on a DVD or accessed through a network, then this slowdown may be unacceptable. An alternative would be to load a current menu and in background (another thread) load every menu that could be started from this current one).
>> is there a way to set a global subscribe event
Have a look at Cool_window_effects for an example of global events. With this approach you subscribe to the pushbutton click event and within the function handler you query the name of the button that triggered the event:
What I dislike with this approach is that every single pushbutton will pass through this function. If you have another pushbutton to be used for a different purpose then you'll have to write special code. Here's what I like better:
You'd call subscribeMenuButton() with every menu button and then code the appropriate response within onMenuButton(). It's still sloppy but seems safer.
You could also create 25 classes, 1 class per behavior:
If you have a lot of code handling each button then this approach may be cleaner. Another approach would be to use 25 different functions within a single class:
Note: none of this code has been tested.
It depends on the number of menu windows you have. If there's 100-500 then loading each one, even if invisible, would take up too many resources (memory) unnecessarily. Instead you'd be better off loading a single menu window at a time, destroying it (it's widgets and subscribed events) and loading a new menu window. But with this approach you now have to deal with disk access, which may cause unwanted pauses.
If you're reading from a hard disk then access is pretty fast, but if your resources are on a DVD or accessed through a network, then this slowdown may be unacceptable. An alternative would be to load a current menu and in background (another thread) load every menu that could be started from this current one).
>> is there a way to set a global subscribe event
Have a look at Cool_window_effects for an example of global events. With this approach you subscribe to the pushbutton click event and within the function handler you query the name of the button that triggered the event:
Code: Select all
bool onButtonClicked(const EventArgs& e)
{
const WindowEventArgs& we = static_cast<WindowEventArgs&>(e);
we.window->getName()
}
What I dislike with this approach is that every single pushbutton will pass through this function. If you have another pushbutton to be used for a different purpose then you'll have to write special code. Here's what I like better:
Code: Select all
class MyClass
{
void subscribeMenuButton(const String& pName)
{
Window* menuButton = WindowManager::getSingleton().getWindow(pName);
menuButton->subscribeEvent(PushButton::Event::Clicked, Event::Subscriber(&MyClass::onMenuButton, this));
}
bool onMenuButton(const EventArgs& e)
{
const WindowEventArgs& we = static_cast<WindowEventArgs&>(e);
we.window->getName()
// Process the action of this menu button
}
}
You'd call subscribeMenuButton() with every menu button and then code the appropriate response within onMenuButton(). It's still sloppy but seems safer.
You could also create 25 classes, 1 class per behavior:
Code: Select all
class MenuButton
{
public:
void subscribe(const String& pName)
{
Window* menuButton = WindowManager::getSingleton().getWindow(pName);
menuButton->subscribeEvent(PushButton::Event::Clicked, Event::Subscriber(&MenuButton::onMenuButton, this));
}
bool onMenuButton(const EventArgs& e)
{
onMenu();
}
virtual void onMenu() = 0;
};
class MenuButtonA : public MenuButton
{
public:
void onMenu()
{
// Perform the action
}
};
class MenuButtonB : public MenuButton
{
public:
void onMenu()
{
// Perform the action
}
};
If you have a lot of code handling each button then this approach may be cleaner. Another approach would be to use 25 different functions within a single class:
Code: Select all
class MyClass
{
void subscribeMenuButtons
{
Window* menuButton = WindowManager::getSingleton().getWindow("MenuButton1");
menuButton->subscribeEvent(PushButton::Event::Clicked, Event::Subscriber(&MyClass::onMenuButton1, this));
Window* menuButton = WindowManager::getSingleton().getWindow("MenuButton2");
menuButton->subscribeEvent(PushButton::Event::Clicked, Event::Subscriber(&MyClass::onMenuButton2, this));
}
bool onMenuButton1(const EventArgs& e)
{
// Process the action of this menu button
}
bool onMenuButton2(const EventArgs& e)
{
// Process the action of this menu button
}
}
Note: none of this code has been tested.
thankyou for the advice
ive ended up implementing the buttons as a vector of strings that i implement in a for loop to set the callbacks then just using if statements in the single callback system as follows
ive removed the majority of the buttons and if statements to make this post less lengthy i didnt make all this for 3 buttons heh
im using 8 windows at the moment im using the setvisible to swap between them it seems to work great
thankyou for your help
Code: Select all
void Demo7Sample::initDemoEventWiring(void)
{
using namespace CEGUI;
vector<string> buttons;
buttons.push_back("multiplayer"),
buttons.push_back("newgameback"),
buttons.push_back("newgamedifficultyback");
for(unsigned int index = 0; index<buttons.size();index++)
{
WindowManager::getSingleton().getWindow(buttons[index])->
subscribeEvent(PushButton::EventClicked, Event::Subscriber(&Demo7Sample::handleButtonClick, this));
}
}
Code: Select all
bool Demo7Sample::handleButtonClick(const CEGUI::EventArgs& e)
{
using namespace CEGUI;
const CEGUI::WindowEventArgs& we =
(const CEGUI::WindowEventArgs&) e;
string senderID = we.window->getName().c_str();
if(senderID == "quit")
handleQuit(e);
if(senderID == "newgame")
swapWindows("newgamewindow","defaultwindow");
if(senderID == "loadgame")
swapWindows("loadgamewindow","defaultwindow");
return true;
}
ive removed the majority of the buttons and if statements to make this post less lengthy i didnt make all this for 3 buttons heh
im using 8 windows at the moment im using the setvisible to swap between them it seems to work great
thankyou for your help
I forgot to mention another way. After you have loaded a .layout you can recursively go through every child and test whether it is a pushbutton. You can then subscribe that pushbutton. This way you automatically detect new buttons in the layout. And in the handleButtonClick() function you can code a default action of displaying a "This button has not been configured yet" message.
Who is online
Users browsing this forum: Baidu [Spider] and 9 guests
