UI_Image、UI_Label、Button、UI_Manage、是继承了我们之前写的CUI类,因为写的比较简单,所以就放在同一章去讲了
CUI的具体实现可以看第四篇文章
4.引擎2D基类CUI类实现_天才小熊猫oo的博客-CSDN博客实现了引擎基础组件中的基类CUI类https://blog.csdn.net/qq_33531923/article/details/126716404
老样子先贴代码
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 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::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()
{
}
}
先把代码贴出来,等有时间再回过头来重点讲解。