added image widget with atlas support and global texture manager

This commit is contained in:
2017-02-07 23:42:39 +00:00
parent 83e59573e0
commit 5e5ddf310c
10 changed files with 167 additions and 9 deletions

BIN
data/icons.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -34,12 +34,24 @@
</border>
<separator width="10"/>
<border width="50" margin="0 5 0 0" color=".1" thickness="2" border-color=".5" justify="center" align="center"><text text="red" font-face="arial" font-size="11" color="1 0 0 1"/></border>
<border width="50" margin="0 5 0 0" color=".2" thickness="2" border-color=".5" justify="center" align="center"><text text="blue" font-face="arial" font-size="11" color="0 0 1 1"/></border>
<border width="50" margin="0 5 0 0" color=".2" thickness="2" border-color=".5" justify="center" align="center"><text text="blue" font-face="arial" font-size="11" color=".4 .4 1 1"/></border>
<border width="50" margin="0 5 0 0" color=".3" thickness="2" border-color=".5" justify="center" align="center"><text text="green" font-face="arial" font-size="11" color="0 1 0 1"/></border>
<separator width="10"/>
<border width="50" margin="0 5 0 0" color=".1" thickness="2" border-color=".7"></border>
<border width="50" margin="0 5 0 0" color=".2" thickness="2" border-color=".7"></border>
<border width="50" margin="0 5 0 0" color=".3" thickness="2" border-color=".7"></border>
<border width="50" margin="0 5 0 0" color=".1" thickness="2" border-color=".7" pad="4">
<image path="data/uvs.jpg" region="0 0 50 50" width="100%" height="100%" align="center" justify="flex-end">
<text text="atlas" font-face="arial" font-size="11"/>
</image>
</border>
<border width="70" margin="0 5 0 0" color=".2" thickness="2" border-color=".7">
<image path="data/social.png" region="0 0 230 230" width="100%" height="100%" pad="5" align="center" justify="flex-end">
<text text="Facebook" font-face="arial" font-size="11"/>
</image>
</border>
<border width="50" margin="0 5 0 0" color=".3" thickness="2" border-color=".7">
<image path="data/social.png" region="250 0 480 230" width="100%" height="100%" pad="5" align="center" justify="flex-end">
<text text="Twitter" font-face="arial" font-size="11"/>
</image>
</border>
<separator width="10"/>
<border width="50" margin="0 5 0 0"></border>
<border width="50" margin="0 5 0 0"></border>
@@ -66,11 +78,13 @@
<node width="1" grow="1" height="100%" pad="10" wrap="1" dir="col" justify="center" align="center">
<text text="hello widget" font-face="arial" font-size="30" color="0 1 1 1"/>
<text text="this is a small description of the useless big text above" font-face="arial" font-size="11" color="0 1 1 1"/>
<image margin="10 0 0 0" path="data/uvs.jpg" width="100" height="100"/>
</node>
</node>
<!-- status bar -->
<border height="30" width="100%" color=".15" border-color=".3" dir="row" pad="0 0 0 10" align="center">
<text text="Status Bar: nothing to show here." font-face="arial" font-size="11"/>
<text text="#fuckunity #fromscratch" font-face="arial" font-size="11" margin="0 0 0 10" color=".2 .5 1 1"/>
</border>
</node>
</layout>

BIN
data/social.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

View File

@@ -38,6 +38,26 @@ void App::init()
"void main(){"
" frag = vec4(uv.xy,0,1);"
"}";
static const char* shader_atlas_v =
"#version 150\n"
"uniform mat4 mvp;"
"uniform vec2 tof;"
"uniform vec2 tsz;"
"in vec2 pos;"
"in vec2 uvs;"
"out vec2 uv;"
"void main(){"
" uv = tof + uvs * tsz;"
" gl_Position = mvp * vec4(pos, 0, 1);"
"}";
static const char* shader_atlas_f =
"#version 150\n"
"uniform sampler2D tex;"
"in vec2 uv;"
"out vec4 frag;"
"void main(){"
" frag = texture(tex, uv);"
"}";
static const char* shader_color_v =
"#version 150\n"
"uniform mat4 mvp;"
@@ -99,7 +119,7 @@ void App::init()
const char* ttf = "/Library/Fonts/Arial.ttf";
#endif
FontManager::init();
FontManager::load(kFont::Arial_11, ttf, 13);
FontManager::load(kFont::Arial_11, ttf, 15);
FontManager::load(kFont::Arial_30, ttf, 30);
layout.load("data/layout.xml");
@@ -110,7 +130,9 @@ void App::init()
ShaderManager::create(kShader::Color, shader_color_v, shader_color_f);
ShaderManager::create(kShader::UVs, shader_v, shader_uv_f);
ShaderManager::create(kShader::Font, shader_font_v, shader_font_f);
WidgetBorder::m_plane.create<1>(1, 1);
ShaderManager::create(kShader::Atlas, shader_atlas_v, shader_atlas_f);
WidgetBorder::init();
WidgetImage::init();
if (!tex.load("data/uvs.jpg"))
printf("error loading image\n");

View File

@@ -5,7 +5,7 @@
bool Image::load(std::string filename)
{
stbi_set_flip_vertically_on_load(true);
//stbi_set_flip_vertically_on_load(true);
uint8_t* buffer = stbi_load(filename.c_str(), &width, &height, nullptr, 4);
comp = 4;
m_data = std::unique_ptr<uint8_t[]>(buffer);

View File

@@ -3,6 +3,8 @@
#include "util.h"
Plane WidgetBorder::m_plane;
Plane WidgetImage::m_plane;
Sampler WidgetImage::m_sampler;
void Node::update(float width, float height)
{
@@ -221,6 +223,9 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
case kWidget::Text:
m_widget = std::make_unique<WidgetText>();
break;
case kWidget::Image:
m_widget = std::make_unique<WidgetImage>();
break;
}
while (attr)

View File

@@ -31,6 +31,8 @@ enum class kAttribute : uint16_t
FontSize = const_hash("font-size"),
Justify = const_hash("justify"),
Align = const_hash("align"),
Path = const_hash("path"),
Region = const_hash("region"),
};
enum class kWidget : uint16_t
@@ -38,6 +40,7 @@ enum class kWidget : uint16_t
Border = const_hash("border"),
Shape = const_hash("shape"),
Text = const_hash("text"),
Image = const_hash("image"),
Ref = const_hash("ref"),
};
@@ -80,6 +83,10 @@ public:
glm::vec4 m_color;
glm::vec4 m_border_color;
float m_thinkness{ 1 };
static void init()
{
m_plane.create<1>(1, 1);
}
virtual std::unique_ptr<Widget> clone() override
{
auto ret = std::make_unique<WidgetBorder>();
@@ -281,6 +288,82 @@ public:
}
};
class WidgetImage : public Widget
{
public:
static Plane m_plane;
static Sampler m_sampler;
bool m_use_atlas;
glm::vec4 m_region;
glm::vec2 m_off;
glm::vec2 m_sz;
std::string m_path;
uint16_t m_id;
static void init()
{
m_plane.create<1>(1, 1);
m_sampler.create();
}
virtual std::unique_ptr<Widget> clone() override
{
auto ret = std::make_unique<WidgetImage>();
*ret = *this;
return std::move(ret);
}
virtual void create() override
{
if (TextureManager::load(m_path.c_str()))
{
auto tex_sz = TextureManager::get(m_id).size();
m_off = m_region.xy / tex_sz;
m_sz = (m_region.zw - m_region.xy) / tex_sz;
}
}
virtual void draw() override
{
TextureManager::get(m_id).bind();
m_sampler.bind(0);
if (m_use_atlas)
{
ShaderManager::use(kShader::Atlas);
ShaderManager::u_vec2(kShaderUniform::Tof, m_off);
ShaderManager::u_vec2(kShaderUniform::Tsz, m_sz);
}
else
{
ShaderManager::use(kShader::Texture);
}
ShaderManager::u_int(kShaderUniform::Tex, 0);
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
m_plane.draw_fill();
m_sampler.unbind();
TextureManager::get(m_id).unbind();
}
virtual void parse_attributes(kAttribute id, const tinyxml2::XMLAttribute* attr) override
{
switch (id)
{
case kAttribute::Path:
m_path = attr->Value();
m_id = const_hash(attr->Value());
break;
case kAttribute::Region:
{
glm::vec4 v;
int n = sscanf(attr->Value(), "%f %f %f %f", &v.x, &v.y, &v.z, &v.w);
if (n == 4)
{
m_region = v;
m_use_atlas = true;
}
break;
}
default:
break;
}
}
};
class Node
{
friend class LayoutManager;

View File

@@ -6,8 +6,8 @@ enum class kShaderUniform : uint16_t
MVP = const_hash("mvp"),
Tex = const_hash("tex"),
Col = const_hash("col"),
Tof = const_hash("texoff"),
Tsz = const_hash("texsz"),
Tof = const_hash("tof"),
Tsz = const_hash("tsz"),
};
class Shader
@@ -29,6 +29,7 @@ enum class kShader : uint16_t
Texture = const_hash("texture"),
UVs = const_hash("uvs"),
Font = const_hash("font"),
Atlas = const_hash("atlas"),
};
class ShaderManager

View File

@@ -1,6 +1,24 @@
#include "pch.h"
#include "texture.h"
#include "image.h"
#include "util.h"
std::map<uint16_t, Texture2D> TextureManager::m_textures;
bool TextureManager::load(const char* path)
{
uint16_t id = const_hash(path);
if (m_textures.count(id) == 0 || !m_textures[id].ready())
{
return m_textures[id].load(path);
}
return true;
}
Texture2D& TextureManager::get(uint16_t id)
{
return m_textures[id];
}
bool Texture2D::create(int width, int height, GLint format, const uint8_t* data)
{
@@ -31,6 +49,11 @@ void Texture2D::update(const uint8_t* data)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_width, m_height, m_format, GL_UNSIGNED_BYTE, data);
}
glm::vec2 Texture2D::size() const
{
return { m_width, m_height };
}
bool Sampler::create(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_EDGE*/)
{
glGenSamplers(1, &id);
@@ -55,3 +78,4 @@ void Sampler::unbind()
{
glBindSampler(current_unit, 0);
}

View File

@@ -15,6 +15,7 @@ public:
void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
void update(const uint8_t* data);
bool ready() const { return m_tex != 0; }
glm::vec2 size() const;
};
class Sampler
@@ -28,3 +29,11 @@ public:
void unbind();
bool ready() const { return id != 0; }
};
class TextureManager
{
public:
static std::map<uint16_t, Texture2D> m_textures;
static bool load(const char* path);
static Texture2D& get(uint16_t id);
};