Nebula2探秘14-nGuiServer的创建与使用
happykevins文
关于nGui:
nGui是Nebula2本身集成的GUI系统。虽然Radon在mangalore中已经集成了对CEGUI的支持,但是nGui相比之下更加简单易用,而且紧密地与Nebula2结合,不存在CEGUI诸多的兼容性问题。另外其天生支持中文,所以在制作简单的游戏UI时可以考虑使用nGui系统。CEGUI是一个非常流行的开源的GUI系统,目前版本是0.5,虽然Bug很多而且不支持中文(网上已有很多的解决方案),但是其功能强大,并且CEGUI社区正在积极制作其相关工具,想要制作精美且复杂的UI系统的话可以考虑使用。在之后的教程中我会介绍在Nebula2中集成CEGUI的方法。
nGui的维护:
像一般的NebulaServers一样,nGui的创建过程大概分为3步:1.向Kernel添加ngui包;2.在kernel中创建nguiserver;3.调用nguiserver的初始化方法(Open)。另外在游戏循环中每帧都需要调用Trigger的方法以保证ngui正确处理用户输入,这需要有ninputserver的支持。最后在程序结束前要调用Close()方法以确保ngui正确释放资源。
nGui的初始化:
nGui的过程分为3步:1.设置nGui的skin。2.定制画刷列表。3.添加用户控件。其中前两个步骤Nebula2在startup.tcl中已经提供了默认的实现,用户也可以自由替换这些信息以实现自己期待的效果。添加用户控件可以通过两个途径来实现:1.通过kernelserver的new来创建。2.通过guiserver的newwindow来创建。其实他们本质上没有什么区别,guiserver也是通过kernelserver来创建的,只不过帮你维护了当前rootwindow的noh路径而已,nGui的所有控件都存放在noh的"/res/gui"下。
nGui的事件注册:
nGui的事件可以通过每个控件的SetXXCammond(cmd_name)来注册(XX为事件类型),传入参数cmd_name为脚本中对应的事件处理函数名,使用起来非常方便。
程序代码如下:
/*Nebula2-Tutorial14*/
/*UsingnGuiServer*/
/*author:happykevins*/
/****************************************************************************/
///----------------------------------------------------------------------------
///+必要头文件
//nebula2includes
#include"kernel/nkernelserver.h"
#include"kernel/nfileserver2.h"
#include"script/ntclserver.h"
#include"gfx2/nd3d9server.h"
#include"gfx2/ncamera2.h"
#include"gui/nguiserver.h"
#include"tools/nmayacamcontrol.h"
#include"scene/nsceneserver.h"
#include"gui/nguiwindow.h"
#include"gui/nguilabel.h"
#include"gui/nguitextlabel.h"
#include"gui/nguitextbutton.h"
#include"../NebulaUtils/nutildefs.h"
#include"../NebulaUtils/nkernelinfo.h"
///-必要头文件
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+链接库
#pragmacomment(lib,"wsock32.lib")
#pragmacomment(lib,"d_microtcl.lib")
#pragmacomment(lib,"d_nkernel.lib")
#pragmacomment(lib,"d_nnebula.lib")
#pragmacomment(lib,"d_ntoollib.lib")
#pragmacomment(lib,"d_ngui.lib")
#pragmacomment(lib,"dxguid.lib")
#pragmacomment(lib,"dxerr9.lib")
#pragmacomment(lib,"d3d9.lib")
#pragmacomment(lib,"d3dx9d.lib")
#pragmacomment(lib,"dinput8.lib")
#pragmacomment(lib,"d_ndinput8.lib")
#pragmacomment(lib,"d_ndirect3d9.lib")
///-链接库
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+声明使用的Nebula2Package&Module
nNebulaUseModule(ntclserver);
nNebulaUseModule(nresource);
nNebulaUseModule(nresourceserver);
nNebulaUseModule(ninputserver);
nNebulaUseModule(nfont2);
nNebulaUseModule(nmesh2);
nNebulaUseModule(nmesharray);
nNebulaUseModule(nshader2);
nNebulaUseModule(ntexture2);
nNebulaUseModule(ngfxserver2);
nNebulaUseModule(nsceneserver);
nNebulaUseModule(nshadowserver2);
nNebulaUseModule(nscenenode);
nNebulaUseModule(ntransformnode);
nNebulaUseModule(nabstractcameranode);
nNebulaUseModule(nclippingcameranode);
nNebulaUseModule(nreflectioncameranode);
nNebulaUseModule(nvariableserver);
nNebulaUseModule(nconserver);
nNebulaUsePackage(ngui);
nNebulaUsePackage(ndirect3d9);
nNebulaUsePackage(ndinput8);
///-声明使用的Nebula2Package&Module
///----------------------------------------------------------------------------
nCamera2cam;
nMayaCamControlccam;
nKernelInfoHelperks_info(NULL);
nTclServer*tcl=NULL;
nKernelServer*ks=NULL;
nD3D9Server*gfx2=NULL;
nInputServer*input=NULL;
nSceneServer*scene=NULL;
nGuiServer*gui=NULL;
///----------------------------------------------------------------------------
///+添加GUI控件
///
voidSetupGUI()
{
constfloatborderSize=0.02f;
//createadummyrootwindow
//gui->SetRootWindowPointer(0);
nGuiWindow*userRootWindow=gui->NewWindow("nguiwindow",true);
n_assert(userRootWindow);
rectanglenullRect(vector2(0.0f,0.0f),vector2(1.0f,1.0f));
userRootWindow->SetRect(nullRect);
//nGuiWindow*userRootWindow=gui->GetRootWindowPointer();
ks->PushCwd(userRootWindow);
//createlogolabel
nGuiLabel*rightLabel=(nGuiLabel*)ks->New("nguilabel","RightLogo");
n_assert(rightLabel);
vector2rightLabelSize=gui->ComputeScreenSpaceBrushSize("n2logo");
rectanglerightRect;
rightRect.v0.set(1.0f-rightLabelSize.x-borderSize,1.0f-rightLabelSize.y-borderSize);
rightRect.v1.set(1.0f-borderSize,1.0f-borderSize);
rightLabel->SetRect(rightRect);
rightLabel->SetDefaultBrush("n2logo");
rightLabel->SetPressedBrush("n2logo");
rightLabel->SetHighlightBrush("n2logo");
rightLabel->OnShow();
//createahelptextlabel
nGuiTextLabel*textLabel=(nGuiTextLabel*)ks->New("nguitextlabel","HelpLabel");
n_assert(textLabel);
textLabel->SetText("Esc:系统菜单请不要点击"Har/Scn/Dis/Cha" 由于没有连接以上服务,会导致程序崩溃!");
textLabel->SetFont("GuiSmall");
textLabel->SetAlignment(nGuiTextLabel::Left);
textLabel->SetColor(vector4(1.0f,1.0f,1.0f,1.0f));
textLabel->SetClipping(false);
vector2textExtent=textLabel->GetTextExtent();
rectangletextRect(vector2(0.0f,0.0f),textExtent);
textLabel->SetRect(textRect);
textLabel->OnShow();
//createacustombutton
nGuiTextButton*toggleBtn=(nGuiTextButton*)ks->New("nguitextbutton","ToggleBtn");
n_assert(toggleBtn);
toggleBtn->SetText("系统菜单");
toggleBtn->SetCommand("UIEvent_ToggleBtn");//脚本中的函数名
toggleBtn->SetFont("GuiSmall");
toggleBtn->SetAlignment(nGuiTextButton::Center);
toggleBtn->SetRect(rectangle(vector2(0.0f+borderSize,1-0.1f+borderSize),vector2(0.15f-borderSize,1.0f-borderSize)));
toggleBtn->SetDefaultBrush("button_n");
toggleBtn->SetPressedBrush("button_p");
toggleBtn->SetHighlightBrush("button_h");
toggleBtn->OnShow();
ks->PopCwd();
//setthenewuserrootwindow
gui->SetRootWindowPointer(userRootWindow);
}
///
///+添加GUI控件
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+初始化环境,创建需要的Server
///
boolInitApp()
{
///创建KernelServer
ks=n_new(nKernelServer);
///----------------------------------------------------------------------------
///+向KernelServer中添加Package&Module
nNebulaAddModule(ntclserver);
nNebulaAddModule(nresource);
nNebulaAddModule(nresourceserver);
nNebulaAddModule(ninputserver);
nNebulaAddModule(nfont2);
nNebulaAddModule(nmesh2);
nNebulaAddModule(nmesharray);
nNebulaAddModule(nshader2);
nNebulaAddModule(ntexture2);
nNebulaAddModule(ngfxserver2);
nNebulaAddModule(nsceneserver);
nNebulaAddModule(nshadowserver2);
nNebulaAddModule(nscenenode);
nNebulaAddModule(ntransformnode);
nNebulaAddModule(nabstractcameranode);
nNebulaAddModule(nclippingcameranode);
nNebulaAddModule(nreflectioncameranode);
nNebulaAddModule(nvariableserver);
nNebulaAddModule(nconserver);
ks->AddPackage(ndinput8);
ks->AddPackage(ngui);
ks->AddPackage(ndirect3d9);
///+向KernelServer中添加Package&Module
///----------------------------------------------------------------------------
///获得FileServer设置shaders的路径
nFileServer2*file=(nFileServer2*)ks->Lookup("sys/servers/file2");
///设置系统路径
file->SetAssign("home","bin:../../");
file->SetAssign("renderpath","home:datafiles/shaders");
file->SetAssign("shaders","renderpath:fixed");
file->SetAssign("scripts","home:datafiles/scripts");
///创建tclserver
tcl=(nTclServer*)ks->New("ntclserver","/sys/servers/script");
///创建ResourceServer
ks->New("nresourceserver","/sys/servers/resource");
///创建variableserver
ks->New("nvariableserver","/sys/servers/variable");
///创建guiserver(RenderPath依赖)
gui=(nGuiServer*)ks->New("nguiserver","/sys/servers/gui");
///创建ConsoleServer(RenderPath依赖)
ks->New("nconserver","/sys/servers/console");
///创建InputServer(GuiServer依赖)
input=(nInputServer*)ks->New("ndi8server","/sys/servers/input");
///创建D3D9Server
gfx2=(nD3D9Server*)ks->New("nd3d9server","/sys/servers/gfx");
///创建sceneserver
scene=(nSceneServer*)ks->New("nsceneserver","/sys/servers/scene");
///创建shadowserver
ks->New("nshadowserver2","/sys/servers/shadow");
///初始化显示模式
nDisplayMode2mode;
mode.SetXPos(150);
mode.SetYPos(100);
mode.SetWidth(640);
mode.SetHeight(480);
///将显示模式应用到d3d9server
gfx2->SetDisplayMode(mode);
gfx2->SetCamera(cam);
///启动sceneserver(启动d3d9server)
scene->SetRenderPathFilename("renderpath:dx7_renderpath.xml");
if(!scene->Open())
{
returnfalse;
}
///启动GUIServer
nStringret;
tcl->RunScript("scripts:T14_GuiServer.tcl",ret);
gui->Open();
///启动InputServer
input->Open();
ret.Clear();
tcl->RunFunction("OnT14MapInput",ret);
///设置GUI环境
SetupGUI();
returntrue;
}
///
///+初始化环境,创建需要的Server
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+初始化环境,创建需要的Server
///
boolCloseApp()
{
///关闭GUIServer
gui->Close();
///关闭sceneserver(关闭d3d9server)
scene->Close();
///销毁KernelServer
n_delete(ks);
returntrue;
}
///
///+初始化环境,创建需要的Server
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+Application
intmain(intargc,constchar**argv)
{
///初始化Application
if(!InitApp())
{
n_error("程序初始化失败! ");
return0;
}
ks_info.SetKernelServer(ks);
ks_info.LogNOH("/");
///这里相当于游戏循环,gfx2->Trigger()将触发win32的消息泵
while(gfx2->Trigger()&&tcl->Trigger())
{
///TriggerTimeServer
nTimeServer::Instance()->Trigger();
doubletime=nTimeServer::Instance()->GetTime();
///TriggerInputServer
input->Trigger(time);
///处理GUI事件,需要inputserver的支持
gui->Trigger();
///BeginScene(BeginFrame)
if(scene->BeginScene(ccam.GetViewMatrix()))
{
//RenderScene
scene->RenderScene();
//EndScene
scene->EndScene();
//PresentScene(EndFrame)
scene->PresentScene();
}
///FlushEvents
input->FlushEvents();
n_sleep(0.00f);
}
///释放资源
if(!CloseApp())
{
n_error("释放资源失败! ");
return0;
}
return0;
}
///-Application
///----------------------------------------------------------------------------
脚本代码如下:
#T14_GuiServer.tcl
#
#ThisisextractfromthethecentralNebularuntimestartupscript
#whichisusedforNebula2TutorialGuiServer
#
#ThescriptmainlysetsupthenGuiVariablesandMapInputs
#
#(C)2003RadonLabsGmbH
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#OnGuiServerOpen
#
#ThisfunctioniscalledwhentheNebula2GUIserverisopened.
#-------------------------------------------------------------------------------
procOnGuiServerOpen{}{
setcwd[psel]
#工具提示
#initializethedefaulttooltip
setguiRoot[/sys/servers/gui.getrootpath]
sel$guiRoot
newnguitooltipTooltip
selTooltip
.setdefaultbrush"tooltip"
.setfont"GuiSmall"
.setcolor0001
.setalignment"left"
.setborder0.0050.005
sel..
#设置Gui外观相关信息
#definethesystemskin
setskin[/sys/servers/gui.newskinsystem]
sel$skin
#settexturepathpre-andpostfix(NOTE:don'tchangepathtotextures:system!!!)
.settextureprefix"home:datafiles/textures/system/"
.settexturepostfix".dds"
#activeandinactivewindowmodulationcolor
.setactivewindowcolor1.01.01.01.0
.setinactivewindowcolor0.60.60.60.6
.setbuttontextcolor0.00.00.01.0
.settitletextcolor0.00.00.01.0
.setlabeltextcolor0.00.00.01.0
.setentrytextcolor0.00.00.01.0
.settextcolor0.00.00.01.0
.setmenutextcolor0.00.00.01.0
#####################################################################
#+添加画刷
#
#definebrushes
.beginbrushes
#windowtitlebar,windowbackground,tooltipbackground
.addbrushtitlebarskin6615210201.01.01.01.0
.addbrushwindowskin8154441.01.01.01.0
.addbrushtooltipskin8154441.01.00.8780.8
.addbrushpinkskin8154441.00.01.01.0
.addbrushdragboxskin8154441.00.80.80.5
#textentryfield
.addbrushtextentry_nskin446124880.70.70.71.0
.addbrushtextentry_pskin446124880.80.80.81.0
.addbrushtextentry_hskin446124880.90.90.91.0
.addbrushtextcursorskin446124880.40.40.41.0
#thewindowclosebutton
.addbrushclose_nskin3884016161.01.01.01.0
.addbrushclose_hskin4044016161.01.01.01.0
.addbrushclose_pskin4204016161.01.01.01.0
#thewindowsizebutton