集成的关键是从Drawable派生子类,在子类内部执行cegui绘制,同时需要注意CEGUI的初始化,需要放到realize()函数之后,否则无法拿到OpenGL HRC。核心代码如下:
CEGUILayer.h
#ifndef CEGUI_LAYER_H
#define CEGUI_LAYER_H
#include <CEGUI/System.h>
#include <CEGUI/RendererModules/OpenGL/GLRenderer.h>
#include <CEGUI/ScriptModule.h>
#include <CEGUI/FontManager.h>
#include <CEGUI/SchemeManager.h>
#include <CEGUI/WindowManager.h>
#include <CEGUI/Exceptions.h>
#include <CEGUI/GUIContext.h>
#include <CEGUI/Window.h>
#include <CEGUI/widgets/FrameWindow.h>
#include <CEGUI/DefaultResourceProvider.h>
#include <CEGUI/ImageManager.h>
#include <CEGUI/falagard/WidgetLookManager.h>
#include <iostream>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/State>
#include <osgViewer/Viewer>
#include <osg/CoordinateSystemNode>
#include <osgGA/GUIEventAdapter>
class CEGUIDrawable : public osg::Drawable
{
public:
CEGUIDrawable();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
CEGUIDrawable(const CEGUIDrawable& drawable,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
Drawable(drawable,copyop) {}
META_Object(osg,CEGUIDrawable);
void initResource();
void config();
void drawImplementation(osg::RenderInfo& renderInfo) const;
protected:
virtual ~CEGUIDrawable();
unsigned int _activeContextID;
CEGUI::Window* d_root;
CEGUI::OpenGLRenderer* m_render;
};
struct CEGUIEventCallback : public osgGA::GUIEventHandler
{
CEGUIEventCallback() {}
/** do customized Event code. */
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor* nv)
{
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv);
CEGUIDrawable* cd = dynamic_cast<CEGUIDrawable*>(obj);
CEGUI::GUIContext& context = CEGUI::System::getSingleton().getDefaultGUIContext();
if (!ev || !cd) return false;
float fInvY = ea.getWindowHeight() - ea.getY();
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::DRAG):
case(osgGA::GUIEventAdapter::MOVE):
context.injectMousePosition(ea.getX(),fInvY);
return true;
case(osgGA::GUIEventAdapter::PUSH):
{
context.injectMousePosition(ea.getX(), fInvY);
if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) // left
context.injectMouseButtonDown(CEGUI::LeftButton);
else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) // middle
context.injectMouseButtonDown(CEGUI::MiddleButton);
else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // right
context.injectMouseButtonDown(CEGUI::RightButton);
return true;
}
case(osgGA::GUIEventAdapter::RELEASE):
{
context.injectMousePosition(ea.getX(), fInvY);
if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) // left
context.injectMouseButtonUp(CEGUI::LeftButton);
else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) // middle
context.injectMouseButtonUp(CEGUI::MiddleButton);
else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // right
context.injectMouseButtonUp(CEGUI::RightButton);
return true;
}
case(osgGA::GUIEventAdapter::DOUBLECLICK):
{
// do we need to do something special here to handle double click??? Will just assume button down for now.
context.injectMousePosition(ea.getX(), fInvY);
if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) // left
context.injectMouseButtonDown(CEGUI::LeftButton);
else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) // middle
context.injectMouseButtonDown(CEGUI::MiddleButton);
else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // right
context.injectMouseButtonDown(CEGUI::RightButton);
return true;
}
case(osgGA::GUIEventAdapter::KEYDOWN):
context.injectKeyDown( static_cast<CEGUI::Key::Scan>(ea.getKey()) );
context.injectChar( static_cast<CEGUI::Key::Scan>( ea.getKey() ) );
return true;
case(osgGA::GUIEventAdapter::KEYUP):
context.injectKeyUp( static_cast<CEGUI::Key::Scan>(ea.getKey()) );
return true;
default:
break;
}
return false;
}
};
#endif // CEGUI_LAYER_H
CEGUILayer.cpp
#include "ceGuiLayer.h"
CEGUIDrawable::CEGUIDrawable()
{
setSupportsDisplayList(false);
setEventCallback(new CEGUIEventCallback());
/* new CEGUI::System( new CEGUI::OpenGLRenderer(0) ); */
// Create an OpenGLRenderer object that uses the current GL viewport as
// the default output surface.
CEGUI::OpenGLRenderer& myRenderer =
CEGUI::OpenGLRenderer::create();
_activeContextID = 0;
m_render = &myRenderer;
CEGUI::System::create(myRenderer);
}
CEGUIDrawable::~CEGUIDrawable()
{
// delete CEGUI??
CEGUI::System::destroy();
CEGUI::OpenGLRenderer::destroy(*m_render);
}
void CEGUIDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
{
osg::State* state = renderInfo.getState();
if (state->getContextID()!=_activeContextID) return;
glPushAttrib(GL_ALL_ATTRIB_BITS);
state->disableAllVertexArrays();
/* CEGUI::System::getSingleton().renderGUI(); */
{
// user function to draw 3D scene
// draw3DScene();
// make sure that before calling renderAllGUIContexts, that any bound textures
// and shaders used to render the scene above are disabled using
// glBindTexture(0) and glUseProgram(0) respectively also set
// glActiveTexture(GL_TEXTURE_0)
// draw GUI
// NB: When using the old desktop OpenGL 1.2 renderer, this call should not
// occur between glBegin/glEnd calls.
CEGUI::System::getSingleton().renderAllGUIContexts();
}
glPopAttrib();
state->checkGLErrors("CEGUIDrawable::drawImplementation");
}
void CEGUIDrawable::initResource()
{
using namespace CEGUI;
// CEGUI relies on various systems being set-up, so this is what we do
// here first.
//
// The first thing to do is load a CEGUI 'scheme' this is basically a file
// that groups all the required resources and definitions for a particular
// skin so they can be loaded / initialised easily
//
// So, we use the SchemeManager singleton to load in a scheme that loads the
// imagery and registers widgets for the TaharezLook skin. This scheme also
// loads in a font that gets used as the system default.
SchemeManager::getSingleton().createFromFile("TaharezLook.scheme");
// The next thing we do is to set a default mouse cursor image. This is
// not strictly essential, although it is nice to always have a visible
// cursor if a window or widget does not explicitly set one of its own.
//
// The TaharezLook Imageset contains an Image named "MouseArrow" which is
// the ideal thing to have as a defult mouse cursor image.
CEGUI::GUIContext& guiContext = CEGUI::System::getSingleton().getDefaultGUIContext();
guiContext.getMouseCursor().setDefaultImage("TaharezLook/MouseArrow");
// Now the system is initialised, we can actually create some UI elements, for
// this first example, a full-screen 'root' window is set as the active GUI
// sheet, and then a simple frame window will be created and attached to it.
// All windows and widgets are created via the WindowManager singleton.
WindowManager& winMgr = WindowManager::getSingleton();
// Here we create a "DefaultWindow". This is a native type, that is, it does
// not have to be loaded via a scheme, it is always available. One common use
// for the DefaultWindow is as a generic container for other windows. Its
// size defaults to 1.0f x 1.0f using the Relative metrics mode, which means
// when it is set as the root GUI sheet window, it will cover the entire display.
// The DefaultWindow does not perform any rendering of its own, so is invisible.
//
// Create a DefaultWindow called 'Root'.
d_root = winMgr.createWindow( "DefaultWindow", "root" );
System::getSingleton().getDefaultGUIContext().setRootWindow( d_root );
// load font and setup default if not loaded via scheme
Font& defaultFont = FontManager::getSingleton().createFromFile("DejaVuSans-12.font");
// Set default font for the gui context
guiContext.setDefaultFont(&defaultFont);
// Set the root window as root of our GUI Context
guiContext.setRootWindow((CEGUI::Window*)d_root);
// A FrameWindow is a window with a frame and a titlebar which may be moved around
// and resized.
//
// Create a FrameWindow in the TaharezLook style, and name it 'Demo Window'
CEGUI::FrameWindow* wnd = (FrameWindow*)winMgr.createWindow("TaharezLook/FrameWindow", "Demo Window");
// Here we attach the newly created FrameWindow to the previously created
// DefaultWindow which we will be using as the root of the displayed gui.
d_root->addChild((CEGUI::Element*)wnd);
// Windows are in Relative metrics mode by default. This means that we can
// specify sizes and positions without having to know the exact pixel size
// of the elements in advance. The relative metrics mode co-ordinates are
// relative to the parent of the window where the co-ordinates are being set.
// This means that if 0.5f is specified as the width for a window, that window
// will be half as its parent window.
//
// Here we set the FrameWindow so that it is half the size of the display,
// and centered within the display.
wnd->setPosition(UVector2(cegui_reldim(0.25f), cegui_reldim( 0.25f)));
wnd->setSize(USize(cegui_reldim(0.5f), cegui_reldim( 0.5f)));
// now we set the maximum and minum sizes for the new window. These are
// specified using relative co-ordinates, but the important thing to note
// is that these settings are aways relative to the display rather than the
// parent window.
//
// here we set a maximum size for the FrameWindow which is equal to the size
// of the display, and a minimum size of one tenth of the display.
wnd->setMaxSize(USize(cegui_reldim(1.0f), cegui_reldim( 1.0f)));
wnd->setMinSize(USize(cegui_reldim(0.1f), cegui_reldim( 0.1f)));
// As a final step in the initialisation of our sample window, we set the window's
// text to "Hello World!", so that this text will appear as the caption in the
// FrameWindow's titlebar.
wnd->setText("Hello World!");
//wnd->subscribeEvent(CEGUI::Window::EventMouseClick, Event::Subscriber(&HelloWorldDemo::handleHelloWorldClicked, this));
// return true so that the samples framework knows that initialisation was a
}
void CEGUIDrawable::config()
{
#if 1
CEGUI::DefaultResourceProvider* rp = static_cast<CEGUI::DefaultResourceProvider*>
(CEGUI::System::getSingleton().getResourceProvider());
rp->setResourceGroupDirectory("schemes", "D:/cegui/cegui-0.8.7/datafiles/schemes/");
rp->setResourceGroupDirectory("imagesets", "D:/cegui/cegui-0.8.7/datafiles/imagesets/");
rp->setResourceGroupDirectory("fonts", "D:/cegui/cegui-0.8.7/datafiles/fonts/");
rp->setResourceGroupDirectory("layouts", "D:/cegui/cegui-0.8.7/datafiles/layouts/");
rp->setResourceGroupDirectory("looknfeels", "D:/cegui/cegui-0.8.7/datafiles/looknfeel/");
rp->setResourceGroupDirectory("lua_scripts", "D:/cegui/cegui-0.8.7/datafiles/lua_scripts/");
#else
CEGUI::DefaultResourceProvider* rp = static_cast<CEGUI::DefaultResourceProvider*>
(CEGUI::System::getSingleton().getResourceProvider());
rp->setResourceGroupDirectory("schemes", "./../datafiles/schemes/");
rp->setResourceGroupDirectory("imagesets", "./../datafiles/imagesets/");
rp->setResourceGroupDirectory("fonts", "./../datafiles/fonts/");
rp->setResourceGroupDirectory("layouts", "./../datafiles/layouts/");
rp->setResourceGroupDirectory("looknfeels", "./../datafiles/looknfeel/");
rp->setResourceGroupDirectory("lua_scripts", "./../datafiles/lua_scripts/");
#endif
CEGUI::ImageManager::setImagesetDefaultResourceGroup("imagesets");
CEGUI::Font::setDefaultResourceGroup("fonts");
CEGUI::Scheme::setDefaultResourceGroup("schemes");
CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels");
CEGUI::WindowManager::setDefaultResourceGroup("layouts");
CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts");
}
Main.cpp
#include "ceGuiLayer.h"
int main( int argc, char **argv )
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
// construct the viewer.
osgViewer::Viewer viewer;
// creat rc
//创建渲染窗口
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x = 0;
traits->y = 0;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
if (gc.valid())
{
viewer.getCamera()->setGraphicsContext(gc.get());
viewer.getCamera()->setViewport(10,10,800,600);
gc->setClearColor(osg::Vec4f(0.2f,0.2f,0.6f,1.0f));
gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
else
{
osg::notify(osg::NOTICE)<<" GraphicsWindow has not been created successfully."<<std::endl;
}
// read the scene from the list of file specified command line args.
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
// if no model has been successfully loaded report failure.
if (!loadedModel)
{
std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
}
else
{
loadedModel = osgDB::readNodeFile("cow.osg");
}
osg::ref_ptr<osg::Group> group = new osg::Group;
group->addChild(loadedModel.get());
// pass the loaded scene graph to the viewer.
viewer.setSceneData(group.get());
viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);//设置单线程模式
viewer.realize();
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
viewer.getCamera()->getGraphicsContext()->makeCurrent();
osg::ref_ptr<CEGUIDrawable> cd = new CEGUIDrawable();
geode->addDrawable(cd.get());
group->addChild(geode.get());
cd->config();
cd->initResource();
// run the viewer
return viewer.run();
}
参考:https://blog.csdn.net/greyfreedom/article/details/8574865
遗留问题
CEGUI加载资源,设置相对路径总是失败,所以先使用绝对路径,以后再查原因。