2015-04-16 16:55:32 +00:00
|
|
|
|
|
|
|
#ifndef __GWEN_OPENGL3_CORE_RENDERER_H
|
|
|
|
#define __GWEN_OPENGL3_CORE_RENDERER_H
|
|
|
|
|
|
|
|
#include "Gwen/Gwen.h"
|
|
|
|
#include "Gwen/BaseRender.h"
|
|
|
|
#include "GLPrimitiveRenderer.h"
|
|
|
|
#include "../OpenGLWindow/OpenGLInclude.h"
|
|
|
|
|
|
|
|
struct sth_stash;
|
|
|
|
#include "fontstash.h"
|
|
|
|
#include "Gwen/Texture.h"
|
|
|
|
|
|
|
|
#include "TwFonts.h"
|
|
|
|
static float extraSpacing = 0.;//6f;
|
|
|
|
#include <assert.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline void MyClamp(T& a, const T& lb, const T& ub)
|
|
|
|
{
|
|
|
|
if (a < lb)
|
|
|
|
{
|
|
|
|
a = lb;
|
|
|
|
}
|
|
|
|
else if (ub < a)
|
|
|
|
{
|
|
|
|
a = ub;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static GLuint BindFont(const CTexFont *_Font)
|
|
|
|
{
|
|
|
|
GLuint TexID = 0;
|
|
|
|
glGenTextures(1, &TexID);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, TexID);
|
|
|
|
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
|
|
|
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
|
|
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
|
|
|
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
|
|
|
return TexID;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct MyTextureLoader
|
|
|
|
{
|
|
|
|
virtual ~MyTextureLoader()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
virtual void LoadTexture( Gwen::Texture* pTexture ) = 0;
|
|
|
|
virtual void FreeTexture( Gwen::Texture* pTexture )=0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class GwenOpenGL3CoreRenderer : public Gwen::Renderer::Base
|
|
|
|
{
|
|
|
|
GLPrimitiveRenderer* m_primitiveRenderer;
|
|
|
|
float m_currentColor[4];
|
|
|
|
float m_yOffset;
|
|
|
|
sth_stash* m_font;
|
|
|
|
float m_screenWidth;
|
|
|
|
float m_screenHeight;
|
|
|
|
float m_fontScaling;
|
|
|
|
float m_retinaScale;
|
|
|
|
bool m_useTrueTypeFont;
|
|
|
|
const CTexFont* m_currentFont;
|
|
|
|
|
|
|
|
GLuint m_fontTextureId;
|
|
|
|
MyTextureLoader* m_textureLoader;
|
|
|
|
public:
|
|
|
|
GwenOpenGL3CoreRenderer (GLPrimitiveRenderer* primRender, sth_stash* font,float screenWidth, float screenHeight, float retinaScale, MyTextureLoader* loader=0)
|
|
|
|
:m_primitiveRenderer(primRender),
|
|
|
|
m_font(font),
|
|
|
|
m_screenWidth(screenWidth),
|
|
|
|
m_screenHeight(screenHeight),
|
|
|
|
m_retinaScale(retinaScale),
|
|
|
|
m_useTrueTypeFont(false),
|
|
|
|
m_textureLoader(loader)
|
|
|
|
{
|
|
|
|
///only enable true type fonts on Macbook Retina, it looks gorgeous
|
|
|
|
if (retinaScale==2.0f)
|
|
|
|
{
|
|
|
|
m_useTrueTypeFont = true;
|
|
|
|
}
|
|
|
|
m_currentColor[0] = 1;
|
|
|
|
m_currentColor[1] = 1;
|
|
|
|
m_currentColor[2] = 1;
|
|
|
|
m_currentColor[3] = 1;
|
|
|
|
|
|
|
|
m_fontScaling = 16.f*m_retinaScale;
|
|
|
|
|
|
|
|
TwGenerateDefaultFonts();
|
|
|
|
|
|
|
|
m_currentFont = g_DefaultNormalFont;
|
|
|
|
//m_currentFont = g_DefaultNormalFontAA;
|
|
|
|
|
|
|
|
//m_currentFont = g_DefaultLargeFont;
|
|
|
|
m_fontTextureId = BindFont(m_currentFont);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~GwenOpenGL3CoreRenderer()
|
|
|
|
{
|
|
|
|
TwDeleteDefaultFonts();
|
|
|
|
}
|
|
|
|
virtual void Resize(int width, int height)
|
|
|
|
{
|
|
|
|
m_screenWidth = width;
|
|
|
|
m_screenHeight = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Begin()
|
|
|
|
{
|
|
|
|
m_yOffset=0;
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
|
|
|
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
//glColor4ub(255,0,0,255);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
// saveOpenGLState(width,height);//m_glutScreenWidth,m_glutScreenHeight);
|
|
|
|
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
|
|
|
|
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
|
|
|
|
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
}
|
|
|
|
virtual void End()
|
|
|
|
{
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void StartClip()
|
|
|
|
{
|
2016-12-29 05:51:54 +00:00
|
|
|
|
2015-04-16 16:55:32 +00:00
|
|
|
if (m_useTrueTypeFont)
|
|
|
|
sth_flush_draw(m_font);
|
|
|
|
Gwen::Rect rect = ClipRegion();
|
|
|
|
|
|
|
|
// OpenGL's coords are from the bottom left
|
|
|
|
// so we need to translate them here.
|
|
|
|
{
|
|
|
|
GLint view[4];
|
|
|
|
glGetIntegerv( GL_VIEWPORT, &view[0] );
|
|
|
|
rect.y = view[3]/m_retinaScale - (rect.y + rect.h);
|
|
|
|
}
|
|
|
|
|
|
|
|
glScissor( m_retinaScale * rect.x * Scale(), m_retinaScale * rect.y * Scale(), m_retinaScale * rect.w * Scale(), m_retinaScale * rect.h * Scale() );
|
|
|
|
glEnable( GL_SCISSOR_TEST );
|
|
|
|
//glDisable( GL_SCISSOR_TEST );
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual void EndClip()
|
|
|
|
{
|
2016-12-29 05:51:54 +00:00
|
|
|
|
2015-04-16 16:55:32 +00:00
|
|
|
if (m_useTrueTypeFont)
|
|
|
|
sth_flush_draw(m_font);
|
|
|
|
glDisable( GL_SCISSOR_TEST );
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual void SetDrawColor( Gwen::Color color )
|
|
|
|
{
|
|
|
|
m_currentColor[0] = color.r/256.f;
|
|
|
|
m_currentColor[1] = color.g/256.f;
|
|
|
|
m_currentColor[2] = color.b/256.f;
|
|
|
|
m_currentColor[3] = color.a/256.f;
|
|
|
|
|
|
|
|
}
|
|
|
|
virtual void DrawFilledRect( Gwen::Rect rect )
|
|
|
|
{
|
2016-12-29 05:51:54 +00:00
|
|
|
// BT_PROFILE("GWEN_DrawFilledRect");
|
2015-04-16 16:55:32 +00:00
|
|
|
Translate( rect );
|
|
|
|
|
2016-12-29 05:51:54 +00:00
|
|
|
m_primitiveRenderer->drawRect(rect.x, rect.y+m_yOffset,
|
|
|
|
rect.x+rect.w, rect.y+rect.h+m_yOffset, m_currentColor);
|
|
|
|
|
|
|
|
|
|
|
|
// m_primitiveRenderer->drawTexturedRect2a(rect.x, rect.y+m_yOffset,
|
|
|
|
// rect.x+rect.w, rect.y+rect.h+m_yOffset, m_currentColor,0,0,1,1);
|
2015-04-16 16:55:32 +00:00
|
|
|
// m_yOffset+=rect.h+10;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderText( Gwen::Font* pFont, Gwen::Point rasterPos, const Gwen::UnicodeString& text )
|
|
|
|
{
|
2016-12-29 05:51:54 +00:00
|
|
|
// BT_PROFILE("GWEN_RenderText");
|
|
|
|
|
2015-04-16 16:55:32 +00:00
|
|
|
Gwen::String str = Gwen::Utility::UnicodeToString(text);
|
|
|
|
const char* unicodeText = (const char*)str.c_str();
|
|
|
|
|
|
|
|
Gwen::Rect r;
|
|
|
|
r.x = rasterPos.x;
|
|
|
|
r.y = rasterPos.y;
|
|
|
|
r.w = 0;
|
|
|
|
r.h = 0;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//printf("str = %s\n",unicodeText);
|
|
|
|
//int xpos=0;
|
|
|
|
//int ypos=0;
|
|
|
|
float dx;
|
|
|
|
|
|
|
|
int measureOnly=0;
|
|
|
|
|
|
|
|
if (m_useTrueTypeFont)
|
|
|
|
{
|
|
|
|
|
|
|
|
float yoffset = 0.f;
|
|
|
|
if (m_retinaScale==2.0f)
|
|
|
|
{
|
|
|
|
yoffset = -12;
|
|
|
|
}
|
|
|
|
Translate(r);
|
|
|
|
sth_draw_text(m_font,
|
|
|
|
1,m_fontScaling,
|
|
|
|
r.x,r.y+yoffset,
|
|
|
|
unicodeText,&dx, m_screenWidth,m_screenHeight,measureOnly,m_retinaScale);
|
|
|
|
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
//float width = 0.f;
|
|
|
|
int pos=0;
|
|
|
|
//float color[]={0.2f,0.2,0.2f,1.f};
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D,m_fontTextureId);
|
|
|
|
float width = r.x;
|
2016-12-29 05:51:54 +00:00
|
|
|
|
2015-04-16 16:55:32 +00:00
|
|
|
while (unicodeText[pos])
|
|
|
|
{
|
2016-12-29 05:51:54 +00:00
|
|
|
|
2015-04-16 16:55:32 +00:00
|
|
|
int c = unicodeText[pos];
|
|
|
|
r.h = m_currentFont->m_CharHeight;
|
|
|
|
r.w = m_currentFont->m_CharWidth[c]+extraSpacing;
|
|
|
|
Gwen::Rect rect = r;
|
|
|
|
Translate( rect );
|
|
|
|
|
2016-12-29 05:51:54 +00:00
|
|
|
m_primitiveRenderer->drawTexturedRect2(rect.x, rect.y+m_yOffset, rect.x+rect.w, rect.y+rect.h+m_yOffset, m_currentColor,m_currentFont->m_CharU0[c],m_currentFont->m_CharV0[c],m_currentFont->m_CharU1[c],m_currentFont->m_CharV1[c]);
|
2015-04-16 16:55:32 +00:00
|
|
|
|
|
|
|
width += r.w;
|
|
|
|
r.x = width;
|
|
|
|
pos++;
|
|
|
|
|
|
|
|
}
|
2016-12-29 05:51:54 +00:00
|
|
|
{
|
|
|
|
m_primitiveRenderer->drawTexturedRect3D2Text(false);
|
|
|
|
}
|
2015-04-16 16:55:32 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
Gwen::Point MeasureText( Gwen::Font* pFont, const Gwen::UnicodeString& text )
|
|
|
|
{
|
2016-12-29 05:51:54 +00:00
|
|
|
// BT_PROFILE("GWEN_MeasureText");
|
2015-04-16 16:55:32 +00:00
|
|
|
Gwen::String str = Gwen::Utility::UnicodeToString(text);
|
|
|
|
const char* unicodeText = (const char*)str.c_str();
|
|
|
|
|
|
|
|
// printf("str = %s\n",unicodeText);
|
|
|
|
int xpos=0;
|
|
|
|
int ypos=0;
|
|
|
|
|
|
|
|
|
|
|
|
int measureOnly=1;
|
|
|
|
float dx=0;
|
|
|
|
if (m_useTrueTypeFont)
|
|
|
|
{
|
|
|
|
sth_draw_text(m_font,
|
|
|
|
1,m_fontScaling,
|
|
|
|
xpos,ypos,
|
|
|
|
unicodeText,&dx, m_screenWidth,m_screenHeight,measureOnly);
|
|
|
|
|
|
|
|
Gwen::Point pt;
|
|
|
|
|
|
|
|
if (m_retinaScale==2.0f)
|
|
|
|
{
|
|
|
|
pt.x = dx*Scale()/2.f;
|
|
|
|
pt.y = m_fontScaling/2*Scale()+1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pt.x = dx*Scale();
|
|
|
|
pt.y = m_fontScaling*Scale()+1;
|
|
|
|
}
|
|
|
|
return pt;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float width = 0.f;
|
|
|
|
int pos=0;
|
|
|
|
while (unicodeText[pos])
|
|
|
|
{
|
|
|
|
width += m_currentFont->m_CharWidth[(int)unicodeText[pos]]+extraSpacing;
|
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
Gwen::Point pt;
|
|
|
|
int fontHeight = m_currentFont->m_CharHeight;
|
|
|
|
|
|
|
|
|
|
|
|
pt.x = width*Scale();
|
|
|
|
pt.y = (fontHeight+2) * Scale();
|
|
|
|
|
|
|
|
return pt;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Gwen::Renderer::Base::MeasureText(pFont,text);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virtual void LoadTexture( Gwen::Texture* pTexture )
|
|
|
|
{
|
|
|
|
if (m_textureLoader)
|
|
|
|
m_textureLoader->LoadTexture(pTexture);
|
|
|
|
}
|
|
|
|
virtual void FreeTexture( Gwen::Texture* pTexture )
|
|
|
|
{
|
|
|
|
if (m_textureLoader)
|
|
|
|
m_textureLoader->FreeTexture(pTexture);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virtual void DrawTexturedRect( Gwen::Texture* pTexture, Gwen::Rect rect, float u1=0.0f, float v1=0.0f, float u2=1.0f, float v2=1.0f )
|
|
|
|
{
|
2016-12-29 05:51:54 +00:00
|
|
|
// BT_PROFILE("DrawTexturedRect");
|
2015-04-16 16:55:32 +00:00
|
|
|
Translate( rect );
|
|
|
|
|
|
|
|
//float eraseColor[4] = {0,0,0,0};
|
|
|
|
//m_primitiveRenderer->drawRect(rect.x, rect.y+m_yOffset, rect.x+rect.w, rect.y+rect.h+m_yOffset, eraseColor);
|
|
|
|
|
|
|
|
GLint texHandle = (GLint) pTexture->m_intData;
|
|
|
|
//if (!texHandle)
|
|
|
|
// return;
|
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glBindTexture(GL_TEXTURE_2D,texHandle);
|
|
|
|
// glDisable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
|
|
|
|
|
|
|
|
/* bool useFiltering = true;
|
|
|
|
if (useFiltering)
|
|
|
|
{
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
}
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
*/
|
|
|
|
|
|
|
|
//glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE );
|
|
|
|
static float add=0.0;
|
|
|
|
//add+=1./512.;//0.01;
|
|
|
|
float color[4]={1,1,1,1};
|
|
|
|
|
|
|
|
m_primitiveRenderer->drawTexturedRect(rect.x, rect.y+m_yOffset, rect.x+rect.w, rect.y+rect.h+m_yOffset, color,0+add,0,1+add,1,true);
|
|
|
|
|
|
|
|
|
|
|
|
assert(glGetError()==GL_NO_ERROR);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
#endif //__GWEN_OPENGL3_CORE_RENDERER_H
|