We are running CEGUI 7.2. (We don't have time to test and integrate our app with 7.5 before our deadline is up next month. 9_9)
We are using openscenegraph for our renderer. We have one 'main' layout that contains things like our sidebar panel with the main buttons and widgets; all spawned windows are in separate layout files. While testing out how to make custom widgets we turned 2 of these windows--our 'toolbox window' and our 'maplayers window' into widgets. We really only needed framewindow-derived classes to handle events and such, but it was a learning experience. So both of these classes have their own looknfeels defined that has all of their buttons and listboxes and such defined as children under the looknfeel instead of using the framewindow looknfeel and defining/positioning their children in the layout file. The layout files basically just define the size and starting position of our spawned windows.
We have another custom class representing a specific popup menu we wanted. I defined this in the scheme file same as our other windows, but unlike with the windows I didn't define a separate looknfeel for it and instead used the base popupmenu looknfeel like so:
Code: Select all
<FalagardMapping WindowType="Immersive_Border/ToolsPopupMenu" TargetType="CEGUI/PopupMenu" Renderer="Falagard/PopupMenu" LookNFeel="Immersive_Border/PopupMenu" />
The ToolsPopupMenu is programmatically created, so there is no layout file associated with it.
The current problem:
I am creating a new spawned window, but I want to do it differently than the first two: I want all of the different child buttons and other widgets to be placed in the layout file, not in the looknfeel, so it's easier for us to position and manipulate these later. I approached this task much like I did the ToolsPopupMenu: I am making a class to handle the events associated with this particular window, but don't want to define the layout in the looknfeel. I don't think our spawned windows should be custom widgets since they're not meant to be reused.
I made my class for the window--the LocatorWindow--and like our other spawned windows it derives from CEGUI::FrameWindow (actually, from our own FrameWindow which is really just (inherits from) a CEGUI::FrameWindow with the close button behavior defined so that we didn't have to do this for all of our framewindows).
.h file:
Code: Select all
namespace is_ui
{
class LocatorWindow : public FrameWindow
{
public:
LocatorWindow(const CEGUI::String &type, const CEGUI::String &name);
~LocatorWindow(void);
static const CEGUI::String WidgetTypeName;
CEGUI::Editbox* getLat();
CEGUI::Editbox* getLong();
CEGUI::Editbox* getAlt();
virtual void initialiseComponents();
bool OnEventSearch(const CEGUI::EventArgs& e);
private:
osgEarthUtil::EarthManipulator* _cameraManipulator;
CEGUI::Editbox* _lat;
CEGUI::Editbox* _long;
CEGUI::Editbox* _alt;
CEGUI::PushButton* _search;
};
}
.cpp file:
Code: Select all
namespace is_ui
{
const CEGUI::String LocatorWindow::WidgetTypeName("Immersive_Border/LocatorWindow");
LocatorWindow::LocatorWindow(const CEGUI::String &type, const CEGUI::String &name) : FrameWindow(type, name)
{
_cameraManipulator = 0;
_lat = 0;
_long = 0;
_alt = 0;
_search = 0;
}
LocatorWindow::~LocatorWindow()
{
}
CEGUI::Editbox* LocatorWindow::getLat()
{
return _lat;
}
CEGUI::Editbox* LocatorWindow::getLong()
{
return _long;
}
CEGUI::Editbox* LocatorWindow::getAlt()
{
return _alt;
}
void LocatorWindow::initialiseComponents()
{
FrameWindow::initialiseComponents();
CEGUI::WindowManager& winMgr = CEGUI::WindowManager::getSingleton();
_lat = static_cast<CEGUI::Editbox*>(winMgr.getWindow(this->getName() + "/lat"));
_long = static_cast<CEGUI::Editbox*>(winMgr.getWindow(this->getName() + "/long"));
_alt = static_cast<CEGUI::Editbox*>(winMgr.getWindow(this->getName() + "/alt"));
_search = static_cast<CEGUI::PushButton*>(winMgr.getWindow(this->getName() + "/SearchButton"));
_search->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&LocatorWindow::OnEventSearch, this));
}
bool LocatorWindow::OnEventSearch(const CEGUI::EventArgs &e)
{
_cameraManipulator = is_graphics::GraphicsManager::getInstance()->getRenderer()->getEarthCameraManipulator();
double usrLat = atof( _lat->getText().c_str() );
double usrLong = atof( _long->getText().c_str() );
double usrAlt = 4e6;
if( usrLat < 180 && usrLat > -180 )
{
if( usrLong < 180 && usrLong > -180 )
{
_cameraManipulator->setViewpoint( osgEarthUtil::Viewpoint( osg::Vec3d( usrLat, usrLong, 0.0 ), 0.0, -90.0, usrAlt), 4.0 );
}
}
return true;
}
} // namespace is_ui
As you can see I named this window type Immersive_Border/LocatorWindow . I gave it a window factory as I did with all of our custom classes/widgets:
Code: Select all
void UiManager::bindCeguiWidgets()
{
CEGUI::WindowFactoryManager& wfMgr = CEGUI::WindowFactoryManager::getSingleton();
CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<FrameWindow> >();
CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<LocatorWindow> >();
CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<MapLayerItemEntry> >();
CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<MapLayersWindow> >();
CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<ToolboxWindow> >();
CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<ToolsPopupMenu> >();
}
Finally, I added it to the scheme file:
Code: Select all
<FalagardMapping WindowType="Immersive_Border/LocatorWindow" TargetType="CEGUI/FrameWindow" Renderer="Falagard/FrameWindow" LookNFeel="Immersive_Border/FrameWindow" />
In the .layout file for the window, where it used to be an Immersive_Border/FrameWindow, I changed it to an Immersive_Border/LocatorWindow:
Code: Select all
<Window Type="Immersive_Border/LocatorWindow" Name="LocatorWindow" >
Essentially I've treated this window the same as our other windows, except that in the .layout file under our LocatorWindow it has children textboxes and such, and the LocatorWindow is supposed to follow the looknfeel of the Immersive_Border/FrameWindow instead of a custom Immersive_Border/LocatorWindow looknfeel. However, whereas the other windows spawn fine when I click the gui buttons to open them, attempting to spawn the LocatorWindow causes the application to freeze up and throw an exception in the console window.
CEGUI::UnknownObjectException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiproperty
set.cpp(124) : There is no Property named 'Clickable' available in the set.
CEGUI::UnknownObjectException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiwindowma
nager.cpp(256) : WindowManager::getWindow - A Window object with the name 'Locat
orWindow/lat' does not exist within the system
CEGUI::InvalidRequestException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiguilayo
ut_xmlhandler.cpp(233) : GUILayout_xmlHandler::startElement - layout loading has
been aborted since no WindowFactory is available for 'Immersive_Border/LocatorW
indow' objects.
A similar error is recorded in the CEGUI log:
24/11/2010 11:51:00 (Error) CEGUI::UnknownObjectException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiwindowmanager.cpp(256) : WindowManager::getWindow - A Window object with the name 'LocatorWindow/lat' does not exist within the system
24/11/2010 11:51:00 (Error) CEGUI::InvalidRequestException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiguilayout_xmlhandler.cpp(233) : GUILayout_xmlHandler::startElement - layout loading has been aborted since no WindowFactory is available for 'Immersive_Border/LocatorWindow' objects.
24/11/2010 11:51:00 (Error) WindowManager::loadWindowLayout - loading of layout from file 'Immersive_LocatorWindow.layout' failed.
I should mention that before I converted the layout file to use Immersive_Border/LocatorWindow as a window type, the window would render just fine, but since it was an Immersive_Border/FrameWindow instead of our LocatorWindow class, it didn't respond to input as we had programmed into our class. As soon as I switched the window type in the layout it started telling me the above errors--that it doesn't have a windowfactory. I thought that by adding it to our scheme file and creating a windowfactory in our application we shouldn't have these issues. Really, I don't see why this doesn't work and yet our other windows do; the differences are mostly stylistic and dealing with children windows, but should have no bearing on this. But then I would also expect it to throw the error about not having a window factory BEFORE it says it can't find LocatorWindow/lat (one of the child windows--no duh it can't be found before the parent is created!)...
Can you shed any light on this? I want to be able to model all of our windows after this approach instead of the old one, but I can't do that until I figure out why it's not working with this first window!
Also, I can post the complete CEGUI log if need be but thought I would save you the trouble by just posting the relevant error and telling you what version we're running. If you need other info from it, though, let me know.