【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2723|回复: 1

OpenGL GUI教程

[复制链接]
发表于 2006-11-9 17:03:07 | 显示全部楼层 |阅读模式

作者:Ionware

译者:akinggw

欢迎来到我的GUI系列文章的第一篇。我从一个非常高的角度更新了他们,这样是为了便于你喜欢上她并且能很快明白。

她是一个OPENGL GUI,只需要OPENGL去渲染她的组件和建立纹理/材质,但从某种意义上说她并不依赖与OPENGL

目录

l 简介

l 类定义和结构

l 画一个东东

l 处理输入

l 下载

简介

什么是GUI?图形用户界面。正确,还有什么?好的,让我们看一下标准的WINDOWS。她像什么?就像一个带边框,颜色和纹理的简单的多边形。因此,假设我们的GUI也将是一个2D多边形(四边形)。那我们需要怎样做呢?让我们看一下。

类定义和结构

我们的第一个类,是的,CGUIElement,是其它控制的基础。我们将以后为它添加更多的功能。让我们看一下这个类:

class CGUIElement: public CXMLResource,public CdoubleList<CGUIElement *>

{

CREATOR(CGUI);

CREATOR(CGUIBorder);

Public:

CGUIElement();

Virtual ~CGUIElement();

Virtual void Initialize();

Virtual int Create(CGUIElement *pParent,tRect WidgetRect,Ctexture *pTexture = NULL,Cmaterial *pMaterial = NULL,bool bBorder = false);

Virtual int LoadXML(TiXmlNode *pDateNode,Cstring strFilename);

Virtual int SaveXML(TIXmlNode *pDateNode,Cstring strFilename);

Virtual void Draw();

Virtual void Destroy();

Virtual void ProcessMessages();

Virtual void ProcessMessage(tGUIMessage& Message);

Virtual int Resize(tRect& NewRect);

Virtual int OnKeyDown(UINT uiKeyCode);

Virtual int OnKeyUp(UINT uiKeyCode);

Virtual int OnMove(UINT x,UINT y);

Virtual int OnMouseMove(UINT x,UINT y);

Virtual int OnLMouseDown(UINT x, UINT y);

Virtual int OnLMouseUp(UINT x, UINT y);

Virtual int OnRMouseDown(UINT x,UINT y);

Virtual int OnRMouseUp(UINT x,UINT y);

UINT GetWidth();

Void SetWidth(UINT uiWidth);

UINT GetHeight();

Void Setheight(UINT uiHeight);

CGUIElement *GetChild(UINT uiIndex);

CGUIElement *GetChild(eGUIControlType eWidgetType);

CGUIElement *GetChild(TiXmlElement *pXMLElement);

UINT GetChildCount();

Void RemoveChild(CGUIElement *pChild);

Void HideSiblings(int iDeep = -1);

Void ShowSiblings(int iDeep = -1);

Void SetZOrder(UINT uiZOrder);

UINT GetZOrder();

Bool Visible();

void Hide();

void Show();

CGUIElement *GetParent();

Void Setparent(CGUIElement *pParent);

Void SetTexture(Ctexture *pTexture);

Ctexture *GetTexture();

Void SetMaterial(Cmaterial *pMaterial);

Cmaterial *GetMaterial();

Void SetTexCoord(UINT uiIndex,float U,float V);

Tvertex2f& GetTexCoord(UINT index);

CGUI *GetGUI();

Void SetRect(tRect& NewRect);

TRect& GetRect();

Void SetGUI(CGUI *pGUI);

EGUIControlType& GetType();

Void SetType(eGUIControlType eWidgetType);

Void SetFlag(eGUIFlag eFlag,bool bSet);

Bool IsFlagSet(eGUIFlag eFlag);

Bool IsChild(CGUIElement *pElement);

Bool IsAutoCalc();

Void SetAutoCalc(bool bAutoCalc);

Virtual bool IsOfType(eEntityType eType);

Cstring GetElementType();

      #ifdef GUI_USE_ACTIVE_INACTIVE
  bool IsActive() { return m_bActive; };
  void Activate() { m_bActive = true;};
  void Deactivate() {m_bActive = false;};
#endif
 
protected:
 #ifndef GUI_USE_ACTIVE_INACTIVE
  Cmaterial *m_pMaterial;                  //组件的材质指针
 #elif
  COLORREF m_ActiveColor;                  //材质活动的颜色
  COLORREF m_InactiveColor;                //材质静止的颜色
  Bool m_bActive;                          //材质是活动或静止
 #endif
  //组件的关键参数
  eGUIControlType m_eControlType;          //组件的类型
  bool m_bAutoCalc;                        //自动计算标志:用于很多方面
  CGUIElement *m_pParent;                  //父亲组件
  CGUI *m_pGUI;                            //根GUI
  DWORD m_dwFlags;                        //组件标志
  Ctexture *m_pTexture;                   //组件的纹理指针
  Tvertex2fm_texCoord[4];                 //组件的纹理坐标
  Bool m_bVisible;                        //组件的可视标志

};

这段代码显示的结构如下:

http://openglgui.sourceforge.net/images/gui_tut1_img1.jpg

是的,这是一个非常大的类,她是我们一切的基础,因此,现在我们看一下她的功能函数。

首先,我们需要初始化一个组件,这个完全可以在构造函数中完成,但是我选择在Initialize()函数中完成她。

正如你所看到的,我们有自己的消息处理类,因此每个类都有自己的消息处理函数ProcessMessages()在每次画的时候处理它,并且寻找与她相关的消息。例如,按下一个按钮后会出现一个下拉菜单,你是否会选择她其中的一个选项。

每个组件也有一个导入/保存函数,但是并不需要每次都重写她。相反,我们使用一个通用的类去保存她的组件参数,然后在根结点时保存整棵树的参数。同样,我们也有自己的键盘/鼠标处理函数。

整个GUI的结构如下:

http://openglgui.sourceforge.net/images/gui_tut1_img2.jpg

 楼主| 发表于 2006-11-9 17:03:26 | 显示全部楼层

画一个东东

下面,我们来看一下她是如何作画的:

void CGUIElement:raw()

{

if(!Visible())

return;

int left = m_Rect.left;

int right = m_Rect.right;

int top = m_Rect.top;

int botton = m_Rect.bottom;

if(m_pTexture == NULL)

{

gldisable(GL_TEXTURE_2D);

if(m_pMaterial != NULL)

{

glDisable(GL_LIGHTING);

glColor4fv(m_pMaterial->GetAmient().RGBA);

}

else

{

glDisable(GL_LIGHTING);

glColor3d(255,255,255);

}

glBegin(GL_QUADS);

glVertex3d(left,bottom,0);

glVertex3d(right,botton,0);

glVertex3d(right,top,0);

glVertex3d(left,top,0);

glEnd();

}

else

{

m_pTexture->Bind();

if(m_pMaterial != NULL)

{

glDisable(GL_LIGHTING);

glColor3f(m_pMattrial->GetAmbient().R/255.0f,m_pMattrial->GetAmbient().G/255.0f,m_pMattrial->GetAmbient().B/255.0f);

}

else

glColor3d(1,1,1);

if(m_pTexture->IsMasked())

{

glAlphaFunc(GL_GREATER,0.0f);

glEnable(GL_ALPHA_TEST);

}

glBegin(GL_QUADS);

glTexCoord2f(m_TexCoord[0].x,m_TexCoord[0].y);glVertex3d(left,bottom.0);

glTexCoord2f(m_TexCoord[1].x,m_TexCoord[1].y);glVertex3d(right,bottom.0);

glTexCoord2f(m_TexCoord[2].x,m_TexCoord[2].y);glVertex3d(right,top.0);

glTexCoord2f(m_TexCoord[3].x,m_TexCoord[3].y);glVertex3d(left,top.0);

glEnd();

if(m_pTexture->IsMasked())

glDisable(GL_ALPHA_TEST);

}

CGUIElement *Iter = begin();

Set_ptr(Iter);

While(Iter != NULL)

{

Iter->Draw();

Iter = next();

}

}

正如你所看到的,她非常容易明白,所以我就不讲了,(:

处理输入

一个基本的组件只需要处理鼠标事件。

Int CGUIElement::OnLMouseUp(UINT x,UINT y)

{

CGUIElement *IterElement = end();

Set_ptr(IterElement);

While(IterElement != NULL)

{

if(IterElement->OnLMouseUp(x,y)){

return 1;

IterElement = prev();

}

if(GetType() != GUI)

{

if(PointInRect(GetRect(),x,y))

{

GetGUI()->ostMessage(this,NULL,GUI_Message_AquireFocus);

Return 1;

}

return 0;

}

}

正如你所看到的,首先组件将这个输入送给他的孩子,看他们是否能处理它。如果他们能,将返回1,那么根结点就不用处理这个鼠标输出。相反就由她自己处理。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 06:43

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表