added image widget with atlas support and global texture manager
This commit is contained in:
BIN
data/icons.png
Normal file
BIN
data/icons.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
@@ -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
BIN
data/social.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 309 KiB |
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user