UI_Image、UI_Label、Button、UI_Manage、是继承了我们之前写的CUI类,因为写的比较简单,所以就放在同一章去讲了
CUI的具体实现可以看第四篇文章
老样子先贴代码
Label.h
#pragma once typedef char * va_list; #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define va_end(ap) ( ap = (va_list)0 ) namespace U2D { class CUI_Label :public CUI { private: GLuint _base; UINT m_fontSize; string m_string; public: CUI_Label(const char *string, const char *fontName, float fontSize); void setString(char* string, ...); void drawCNString(const char *str); void draw(); CUI_Label(); ~CUI_Label(); }; }
Label.cpp
#include "Engine.h" namespace U2D { CUI_Label::CUI_Label() { } CUI_Label::CUI_Label(const char *string, const char *fontName, float fontSize) { HDC hdc = CPlateForm::getInstance()->getHdc(); HFONT font; font = CreateFont(-fontSize, 0, 0, 0, FW_BOLD, false, false, false, ANSI_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE | DEFAULT_PITCH, CUser::getInstance()->CharToWchar(fontName)); _base = glGenLists(96); HFONT oldfont = (HFONT)SelectObject(hdc, font); wglUseFontBitmaps(hdc, 32, 96, _base); SelectObject(hdc, oldfont); DeleteObject(font); m_fontSize = fontSize; m_string = string; } void CUI_Label::draw() { int len, i; wchar_t* wstring; HDC hDC = CPlateForm::getInstance()->getHdc();; //获取显示设备 if (visible == false) return; //计算从局部到全局的转换矩阵 Matrix3 scaleMatrix; Matrix3 rotateMatrix; Matrix3 transMatrix; scaleMatrix.Scale(scale.x, scale.y);//放缩 if (flip == true) //水平翻转 scaleMatrix._11 *= -1; rotateMatrix.Rotate(angle); //旋转 transMatrix.Translate(pos.x, pos.y);//平移 local_matrix = scaleMatrix*rotateMatrix*transMatrix; if (parent == NULL) { world_color = local_color; world_matrix = local_matrix; } else { sColor col = parent->getWorldColor(); world_color.r = local_color.r*col.r; world_color.g = local_color.g*col.g; world_color.b = local_color.b*col.b; world_color.a = local_color.a*col.a; world_matrix = local_matrix*parent->getWorldMatrix(); } glPushMatrix(); glPushAttrib(GL_LIST_BIT); glRasterPos2f(pos.x, pos.y + m_fontSize); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4fv(world_color.color); len = 0; for (i = 0; m_string[i] != '\0'; ++i) //计算字符的个数 { if (IsDBCSLeadByte(m_string[i])) //如果是双字节字符的(比如中文字符),两个字节才算一个字符 ++i; //否则一个字节算一个字符 ++len; } wstring = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));//将混合字符转化为宽字符 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, m_string.c_str(), -1, wstring, len); wstring[len] = L' ';// 只是转义符,它本身的类型是wchar_t for (i = 0; i < len; ++i) // 逐个输出字符 { wglUseFontBitmapsW(hDC, wstring[i], 1, _base); glCallList(_base); } //glListBase(_base - 32); //glCallLists(m_string.length(), GL_UNSIGNED_BYTE, m_string.c_str()); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glPopAttrib(); glPopMatrix(); free(wstring);// 回收所有临时资源 glDeleteLists(_base, 1); } void CUI_Label::setString(char* string, ...) { char temp[255]; m_string = ""; va_list ap; va_start(ap, string); while (0 != *string) { if ('%' != *string) { m_string += *string; } else { switch (*++string) { case 'd': { int val = va_arg(ap, int); _itoa(val, temp, 10); m_string += temp; } break; case 'c': { char val = va_arg(ap, char); m_string += val; } break; case 's': { char *str = va_arg(ap, char*); m_string += str; } break; case 'f': case '.': { double val = va_arg(ap, double); char fmt[10]; char *lp = fmt; *lp++ = '%'; while (*string != 'f') { *lp++ = *string++; } *lp++ = 'f'; *lp = 0; sprintf(temp, fmt, val); m_string += temp; } break; case 'x': { int val = va_arg(ap, int); _itoa(val, temp, 16); m_string += temp; } break; default: break; } } string++; } va_end(ap); } void CUI_Label::drawCNString(const char* str) { int len, i; wchar_t* wstring; HDC hDC = CPlateForm::getInstance()->getHdc();; //获取显示设备 GLuint list = glGenLists(1); //申请1个显示列表 //计算字符的个数 //如果是双字节字符的(比如中文字符),两个字节才算一个字符 //否则一个字节算一个字符 len = 0; for (i = 0; str[i] != '\0'; ++i) { if (IsDBCSLeadByte(str[i])) ++i; ++len; } wstring = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));// 将混合字符转化为宽字符 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len); wstring[len] = L' ';// 只是转义符,它本身的类型是wchar_t for (i = 0; i < len; ++i) // 逐个输出字符 { wglUseFontBitmapsW(hDC, wstring[i], 1, list); glCallList(list); } free(wstring);// 回收所有临时资源 glDeleteLists(list, 1); } CUI_Label::~CUI_Label() { glDeleteLists(_base, 96); } }
Image.h
#pragma once namespace U2D { class CUI_Image :public CUI { protected: CCTexture *texture; public: CUI_Image(char *imageName); void draw(); void drawDebug() {}; CUI_Image(); ~CUI_Image(); }; }
Image.cpp
#include "Engine.h" namespace U2D { CUI_Image::CUI_Image() { } CUI_Image::CUI_Image(char *imageName) { texture = CTextureManager::getInstance()->addTexture(imageName); int wid = texture->getWidth(); int hei = texture->getHeight(); cornerPoint[0] = Vector2(-wid*anchor.x, -hei*anchor.y); cornerPoint[1] = Vector2(-wid*anchor.x, hei*(1 - anchor.y)); cornerPoint[2] = Vector2(wid*(1 - anchor.x), hei*(1 - anchor.y)); cornerPoint[3] = Vector2(wid*(1 - anchor.x), -hei*anchor.y); } void CUI_Image::draw() { if (visible == false) return; //计算从局部到全局的转换矩阵 Matrix3 scaleMatrix; Matrix3 rotateMatrix; Matrix3 transMatrix; //放缩 scaleMatrix.Scale(scale.x, scale.y); //水平翻转 if (flip == true) scaleMatrix._11 *= -1; //旋转 rotateMatrix.Rotate(angle); //平移 transMatrix.Translate(pos.x, pos.y); local_matrix = scaleMatrix*rotateMatrix*transMatrix; if (parent == NULL) { world_color = local_color; world_matrix = local_matrix; } else { sColor col = parent->getWorldColor(); world_color.r = local_color.r*col.r; world_color.g = local_color.g*col.g; world_color.b = local_color.b*col.b; world_color.a = local_color.a*col.a; world_matrix = local_matrix*parent->getWorldMatrix(); } glPushMatrix(); glLoadMatrixf(world_matrix.mat); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, texture->getTextureID()); glColor4fv(world_color.color); glBegin(GL_TRIANGLE_STRIP); int wid = texture->getWidth(); int hei = texture->getHeight(); glTexCoord2f(0, 1); glVertex2f(-wid*anchor.x, -hei*anchor.y); glTexCoord2f(0, 0); glVertex2f(-wid*anchor.x, hei*(1 - anchor.y)); glTexCoord2f(1, 1); glVertex2f(wid*(1 - anchor.x), -hei*anchor.y); glTexCoord2f(1, 0); glVertex2f(wid*(1 - anchor.x), hei*(1 - anchor.y)); glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glPopMatrix(); } CUI_Image::~CUI_Image() { } }
Button.h
#pragma once namespace U2D { class Button :public CUI { bool m_bPressed;//鼠标按着 bool m_bMouseIn;//鼠标在范围里 GLPolygon goly;//按钮的形状 CCTexture *normalTexture;//一般(没有按)状态下的图片 CCTexture *mouseInTexture;//进入按钮的范围 CCTexture *pressTexture;//按着按钮 CCTexture *currentTexture;//当前状态 public: Button(); Button(Vector2 point[4]); Button(char *normalImage); Button(char *normalImage, char *pressImage); Button(char *normalImage, char *mouseInImage, char *pressImage); void draw(); bool MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); ~Button(); }; }
Button.cpp
#include "Engine.h" namespace U2D { Button::Button() { } Button::Button(Vector2 point[4]) { m_bPressed = false; m_bMouseIn = false; normalTexture = NULL; mouseInTexture = NULL; pressTexture = NULL; for (int i = 0; i < 4; i++) { cornerPoint[i] = point[i]; } } Button::Button(char *normalImage) { m_bPressed = false; m_bMouseIn = false; normalTexture = CTextureManager::getInstance()->addTexture(normalImage); int wid = normalTexture->getWidth(); int hei = normalTexture->getHeight(); cornerPoint[0] = Vector2(-wid*anchor.x, -hei*anchor.y); cornerPoint[1] = Vector2(-wid*anchor.x, hei*(1 - anchor.y)); cornerPoint[2] = Vector2(wid*(1 - anchor.x), hei*(1 - anchor.y)); cornerPoint[3] = Vector2(wid*(1 - anchor.x), -hei*anchor.y); mouseInTexture = normalTexture; pressTexture = mouseInTexture; } Button::Button(char *normalImage, char *pressImage) { m_bPressed = false; m_bMouseIn = false; normalTexture = CTextureManager::getInstance()->addTexture(normalImage); int wid = normalTexture->getWidth(); int hei = normalTexture->getHeight(); cornerPoint[0] = Vector2(-wid*anchor.x, -hei*anchor.y); cornerPoint[1] = Vector2(-wid*anchor.x, hei*(1 - anchor.y)); cornerPoint[2] = Vector2(wid*(1 - anchor.x), hei*(1 - anchor.y)); cornerPoint[3] = Vector2(wid*(1 - anchor.x), -hei*anchor.y); mouseInTexture = normalTexture; pressTexture = CTextureManager::getInstance()->addTexture(pressImage); } Button::Button(char *normalImage, char *mouseInImage, char *pressImage) { m_bPressed = false; m_bMouseIn = false; normalTexture = CTextureManager::getInstance()->addTexture(normalImage); int wid = normalTexture->getWidth(); int hei = normalTexture->getHeight(); cornerPoint[0] = Vector2(-wid*anchor.x, -hei*anchor.y); cornerPoint[1] = Vector2(-wid*anchor.x, hei*(1 - anchor.y)); cornerPoint[2] = Vector2(wid*(1 - anchor.x), hei*(1 - anchor.y)); cornerPoint[3] = Vector2(wid*(1 - anchor.x), -hei*anchor.y); mouseInTexture = CTextureManager::getInstance()->addTexture(mouseInImage); pressTexture = CTextureManager::getInstance()->addTexture(pressImage); } void Button::draw() { Gizmo::drawGLPolygon(goly, sColor(1, 0, 0, 1)); if (visible == false) return; //计算从局部到全局的转换矩阵 Matrix3 scaleMatrix; Matrix3 rotateMatrix; Matrix3 transMatrix; //放缩 scaleMatrix.Scale(scale.x, scale.y); //水平翻转 if (flip == true) scaleMatrix._11 *= -1; //旋转 rotateMatrix.Rotate(angle); //平移 transMatrix.Translate(pos.x, pos.y); local_matrix = scaleMatrix*rotateMatrix*transMatrix; if (parent == NULL) { world_color = local_color; world_matrix = local_matrix; } else { sColor col = parent->getWorldColor(); world_color.r = local_color.r*col.r; world_color.g = local_color.g*col.g; world_color.b = local_color.b*col.b; world_color.a = local_color.a*col.a; world_matrix = local_matrix*parent->getWorldMatrix(); } if (m_bPressed) { currentTexture = pressTexture; } else if (m_bMouseIn) { currentTexture = mouseInTexture; } else { currentTexture = normalTexture; } glPushMatrix(); glLoadMatrixf(world_matrix.mat); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, currentTexture->getTextureID()); glColor4fv(world_color.color); glBegin(GL_TRIANGLE_STRIP); int wid = currentTexture->getWidth(); int hei = currentTexture->getHeight(); cornerPoint[0] = Vector2(-wid*anchor.x, -hei*anchor.y); cornerPoint[1] = Vector2(-wid*anchor.x, hei*(1 - anchor.y)); cornerPoint[2] = Vector2(wid*(1 - anchor.x), hei*(1 - anchor.y)); cornerPoint[3] = Vector2(wid*(1 - anchor.x), -hei*anchor.y); Vector2 ver[4]; for (int i = 0; i < 4; i++) { Vec2TransformCoord(ver[i], cornerPoint[i], world_matrix); } goly.Set(ver, 4); glTexCoord2f(0, 1); glVertex2f(-wid*anchor.x, -hei*anchor.y); glTexCoord2f(0, 0); glVertex2f(-wid*anchor.x, hei*(1 - anchor.y)); glTexCoord2f(1, 1); glVertex2f(wid*(1 - anchor.x), -hei*anchor.y); glTexCoord2f(1, 0); glVertex2f(wid*(1 - anchor.x), hei*(1 - anchor.y)); glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glPopMatrix(); } bool Button::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (visible == false) return false; switch (uMsg) { case WM_LBUTTONDOWN: { Vector2 mousePos = Vector2(LOWORD(lParam), HIWORD(lParam)); if (Collider::Intersects(mousePos, goly)) { m_bPressed = true; //鼠标移动出客户区,你也可以接受到鼠标消息 SetCapture(hWnd); return true; } } break; case WM_MOUSEMOVE: { Vector2 mousePos = Vector2(LOWORD(lParam), HIWORD(lParam)); if (Collider::Intersects(mousePos, goly)) { if (m_bPressed == false) m_bMouseIn = true; return true; } else { m_bPressed = false; m_bMouseIn = false; //必须与SetCapture配对 ReleaseCapture(); } } break; case WM_LBUTTONUP: { Vector2 mousePos = Vector2(LOWORD(lParam), HIWORD(lParam)); if (m_bPressed == true) { m_bPressed = false; //必须与SetCapture配对 ReleaseCapture(); if (Collider::Intersects(mousePos, goly)) { // 鼠标弹起时发送消息 sendEvent(Event::MOUSE_UP); return true; } } } break; } return false; } Button::~Button() { } }
UI_Manager.h
#pragma once namespace U2D { class CUI_Manage { class ZOrder_Op { public: bool operator()(CUI*a, CUI*b); }; protected: //friend class CPlateForm; list<CUI*> uiList;//UI的链表 static CUI_Manage*instance; public: static CUI_Manage*getInstance(); void _draw(); void MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void addUI(CUI* ui, int z = 0); void addUI(char *name, CUI*ui, int z = 0); CUI *findUI(char *name); CUI_Manage(); virtual ~CUI_Manage(); }; }
UI_Manage.cpp
#include "Engine.h" namespace U2D { CUI_Manage*CUI_Manage::instance = NULL; bool CUI_Manage::ZOrder_Op::operator()(CUI*a, CUI*b) { if (a->zOrder < b->zOrder) return true; return false; } CUI_Manage*CUI_Manage::getInstance() { if (instance == NULL) { instance = new CUI_Manage; } return instance; } CUI_Manage::CUI_Manage() { } void CUI_Manage::_draw() { uiList.sort(ZOrder_Op()); for (auto iter = uiList.begin(); iter != uiList.end(); iter++) { (*iter)->draw(); } } void CUI_Manage::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { //用逆迭代器的目的:后面的最后画。所以最后画出来是在最上面,如果点击了最上面的按钮就跳出,这样就不会消息穿透到下面的按钮! list<CUI*>::reverse_iterator rev_iter;//iterator for (rev_iter = uiList.rbegin(); rev_iter != uiList.rend(); rev_iter++) { if ((*rev_iter)->MsgProc(hWnd, uMsg, wParam, lParam)) break; } } void CUI_Manage::addUI(CUI* ui, int z) { //CUI*temp = findUI(ui->name); //if (temp != NULL) // return; ui->setZorder(z); ui->setParent((CNode*)(CScene*)this); uiList.push_back(ui); } void CUI_Manage::addUI(char *name, CUI*ui, int z) { ui->setName(name); addUI(ui, z); } CUI* CUI_Manage::findUI(char *name) { for (auto iter = uiList.begin(); iter != uiList.end(); iter++) { if (strcmp((*iter)->name, name) == 0) { return (*iter); } } return NULL; } CUI_Manage::~CUI_Manage() { } }
先把代码贴出来,等有时间再回过头来重点讲解。