osg3.0 集成 CEGUI 0.8.7

集成的关键是从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加载资源,设置相对路径总是失败,所以先使用绝对路径,以后再查原因。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值