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>
|
</border>
|
||||||
<separator width="10"/>
|
<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=".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>
|
<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"/>
|
<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=".1" thickness="2" border-color=".7" pad="4">
|
||||||
<border width="50" margin="0 5 0 0" color=".2" thickness="2" border-color=".7"></border>
|
<image path="data/uvs.jpg" region="0 0 50 50" width="100%" height="100%" align="center" justify="flex-end">
|
||||||
<border width="50" margin="0 5 0 0" color=".3" thickness="2" border-color=".7"></border>
|
<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"/>
|
<separator width="10"/>
|
||||||
<border width="50" margin="0 5 0 0"></border>
|
<border width="50" margin="0 5 0 0"></border>
|
||||||
<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">
|
<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="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"/>
|
<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>
|
||||||
</node>
|
</node>
|
||||||
<!-- status bar -->
|
<!-- status bar -->
|
||||||
<border height="30" width="100%" color=".15" border-color=".3" dir="row" pad="0 0 0 10" align="center">
|
<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="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>
|
</border>
|
||||||
</node>
|
</node>
|
||||||
</layout>
|
</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(){"
|
"void main(){"
|
||||||
" frag = vec4(uv.xy,0,1);"
|
" 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 =
|
static const char* shader_color_v =
|
||||||
"#version 150\n"
|
"#version 150\n"
|
||||||
"uniform mat4 mvp;"
|
"uniform mat4 mvp;"
|
||||||
@@ -99,7 +119,7 @@ void App::init()
|
|||||||
const char* ttf = "/Library/Fonts/Arial.ttf";
|
const char* ttf = "/Library/Fonts/Arial.ttf";
|
||||||
#endif
|
#endif
|
||||||
FontManager::init();
|
FontManager::init();
|
||||||
FontManager::load(kFont::Arial_11, ttf, 13);
|
FontManager::load(kFont::Arial_11, ttf, 15);
|
||||||
FontManager::load(kFont::Arial_30, ttf, 30);
|
FontManager::load(kFont::Arial_30, ttf, 30);
|
||||||
|
|
||||||
layout.load("data/layout.xml");
|
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::Color, shader_color_v, shader_color_f);
|
||||||
ShaderManager::create(kShader::UVs, shader_v, shader_uv_f);
|
ShaderManager::create(kShader::UVs, shader_v, shader_uv_f);
|
||||||
ShaderManager::create(kShader::Font, shader_font_v, shader_font_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"))
|
if (!tex.load("data/uvs.jpg"))
|
||||||
printf("error loading image\n");
|
printf("error loading image\n");
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
bool Image::load(std::string filename)
|
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);
|
uint8_t* buffer = stbi_load(filename.c_str(), &width, &height, nullptr, 4);
|
||||||
comp = 4;
|
comp = 4;
|
||||||
m_data = std::unique_ptr<uint8_t[]>(buffer);
|
m_data = std::unique_ptr<uint8_t[]>(buffer);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
Plane WidgetBorder::m_plane;
|
Plane WidgetBorder::m_plane;
|
||||||
|
Plane WidgetImage::m_plane;
|
||||||
|
Sampler WidgetImage::m_sampler;
|
||||||
|
|
||||||
void Node::update(float width, float height)
|
void Node::update(float width, float height)
|
||||||
{
|
{
|
||||||
@@ -221,6 +223,9 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
|
|||||||
case kWidget::Text:
|
case kWidget::Text:
|
||||||
m_widget = std::make_unique<WidgetText>();
|
m_widget = std::make_unique<WidgetText>();
|
||||||
break;
|
break;
|
||||||
|
case kWidget::Image:
|
||||||
|
m_widget = std::make_unique<WidgetImage>();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (attr)
|
while (attr)
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ enum class kAttribute : uint16_t
|
|||||||
FontSize = const_hash("font-size"),
|
FontSize = const_hash("font-size"),
|
||||||
Justify = const_hash("justify"),
|
Justify = const_hash("justify"),
|
||||||
Align = const_hash("align"),
|
Align = const_hash("align"),
|
||||||
|
Path = const_hash("path"),
|
||||||
|
Region = const_hash("region"),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class kWidget : uint16_t
|
enum class kWidget : uint16_t
|
||||||
@@ -38,6 +40,7 @@ enum class kWidget : uint16_t
|
|||||||
Border = const_hash("border"),
|
Border = const_hash("border"),
|
||||||
Shape = const_hash("shape"),
|
Shape = const_hash("shape"),
|
||||||
Text = const_hash("text"),
|
Text = const_hash("text"),
|
||||||
|
Image = const_hash("image"),
|
||||||
Ref = const_hash("ref"),
|
Ref = const_hash("ref"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,6 +83,10 @@ public:
|
|||||||
glm::vec4 m_color;
|
glm::vec4 m_color;
|
||||||
glm::vec4 m_border_color;
|
glm::vec4 m_border_color;
|
||||||
float m_thinkness{ 1 };
|
float m_thinkness{ 1 };
|
||||||
|
static void init()
|
||||||
|
{
|
||||||
|
m_plane.create<1>(1, 1);
|
||||||
|
}
|
||||||
virtual std::unique_ptr<Widget> clone() override
|
virtual std::unique_ptr<Widget> clone() override
|
||||||
{
|
{
|
||||||
auto ret = std::make_unique<WidgetBorder>();
|
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
|
class Node
|
||||||
{
|
{
|
||||||
friend class LayoutManager;
|
friend class LayoutManager;
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ enum class kShaderUniform : uint16_t
|
|||||||
MVP = const_hash("mvp"),
|
MVP = const_hash("mvp"),
|
||||||
Tex = const_hash("tex"),
|
Tex = const_hash("tex"),
|
||||||
Col = const_hash("col"),
|
Col = const_hash("col"),
|
||||||
Tof = const_hash("texoff"),
|
Tof = const_hash("tof"),
|
||||||
Tsz = const_hash("texsz"),
|
Tsz = const_hash("tsz"),
|
||||||
};
|
};
|
||||||
|
|
||||||
class Shader
|
class Shader
|
||||||
@@ -29,6 +29,7 @@ enum class kShader : uint16_t
|
|||||||
Texture = const_hash("texture"),
|
Texture = const_hash("texture"),
|
||||||
UVs = const_hash("uvs"),
|
UVs = const_hash("uvs"),
|
||||||
Font = const_hash("font"),
|
Font = const_hash("font"),
|
||||||
|
Atlas = const_hash("atlas"),
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShaderManager
|
class ShaderManager
|
||||||
|
|||||||
@@ -1,6 +1,24 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "image.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)
|
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);
|
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*/)
|
bool Sampler::create(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_EDGE*/)
|
||||||
{
|
{
|
||||||
glGenSamplers(1, &id);
|
glGenSamplers(1, &id);
|
||||||
@@ -55,3 +78,4 @@ void Sampler::unbind()
|
|||||||
{
|
{
|
||||||
glBindSampler(current_unit, 0);
|
glBindSampler(current_unit, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public:
|
|||||||
void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
|
void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
|
||||||
void update(const uint8_t* data);
|
void update(const uint8_t* data);
|
||||||
bool ready() const { return m_tex != 0; }
|
bool ready() const { return m_tex != 0; }
|
||||||
|
glm::vec2 size() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Sampler
|
class Sampler
|
||||||
@@ -28,3 +29,11 @@ public:
|
|||||||
void unbind();
|
void unbind();
|
||||||
bool ready() const { return id != 0; }
|
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