184 lines
4.9 KiB
C++
184 lines
4.9 KiB
C++
#include "pch.h"
|
|
#include "log.h"
|
|
#include "node_image.h"
|
|
#include "renderer_gl/opengl_capabilities.h"
|
|
#include "shader.h"
|
|
#include "app.h"
|
|
|
|
Plane NodeImage::m_plane;
|
|
Sampler NodeImage::m_sampler;
|
|
Sampler NodeImage::m_sampler_mips;
|
|
|
|
void NodeImage::static_init()
|
|
{
|
|
m_plane.create<1>(1, 1);
|
|
m_sampler.create();
|
|
m_sampler_mips.create();
|
|
m_sampler_mips.set_filter(
|
|
pp::renderer::gl::linear_mipmap_linear_texture_filter(),
|
|
pp::renderer::gl::linear_texture_filter());
|
|
}
|
|
|
|
Node* NodeImage::clone_instantiate() const
|
|
{
|
|
return new NodeImage();
|
|
}
|
|
|
|
void NodeImage::clone_copy(Node* dest) const
|
|
{
|
|
Node::clone_copy(dest);
|
|
NodeImage* n = static_cast<NodeImage*>(dest);
|
|
n->m_use_atlas = m_use_atlas;
|
|
n->m_region = m_region;
|
|
n->m_off = m_off;
|
|
n->m_sz = m_sz;
|
|
n->m_path = m_path;
|
|
n->m_tex_id = m_tex_id;
|
|
n->m_url = m_url;
|
|
n->m_remote_texture = m_remote_texture;
|
|
n->m_autosize = m_autosize;
|
|
}
|
|
|
|
void NodeImage::create()
|
|
{
|
|
Node::create();
|
|
if (!m_path.empty() && TextureManager::load(m_path.c_str(), m_use_mipmaps))
|
|
{
|
|
//LOG("load image node %s", m_path.c_str());
|
|
auto tex_sz = TextureManager::get(m_tex_id).size();
|
|
m_off = xy(m_region) / tex_sz;
|
|
m_sz = (zw(m_region) - xy(m_region)) / tex_sz;
|
|
if (m_autosize)
|
|
SetAspectRatio(tex_sz.x / tex_sz.y);
|
|
}
|
|
}
|
|
|
|
void NodeImage::restore_context()
|
|
{
|
|
Node::restore_context();
|
|
create();
|
|
}
|
|
|
|
void NodeImage::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
|
{
|
|
Node::parse_attributes(ka, attr);
|
|
switch (ka)
|
|
{
|
|
case kAttribute::Mips:
|
|
m_use_mipmaps = attr->BoolValue();
|
|
break;
|
|
case kAttribute::Path:
|
|
m_path = attr->Value();
|
|
m_tex_id = const_hash(attr->Value());
|
|
break;
|
|
case kAttribute::Url:
|
|
m_url = 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;
|
|
}
|
|
case kAttribute::AutoSize:
|
|
m_autosize = attr->BoolValue();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void NodeImage::draw()
|
|
{
|
|
m_remote_texture ?
|
|
m_remote_texture->bind() :
|
|
TextureManager::get(m_tex_id).bind();
|
|
|
|
auto& sampler = m_use_mipmaps ? m_sampler_mips : m_sampler;
|
|
sampler.bind(0);
|
|
|
|
glEnable(pp::renderer::gl::blend_state());
|
|
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, m_mvp * glm::scale(glm::vec3(m_scale, 1.f)));
|
|
m_plane.draw_fill();
|
|
sampler.unbind();
|
|
glDisable(pp::renderer::gl::blend_state());
|
|
}
|
|
|
|
bool NodeImage::set_image(const std::string& path)
|
|
{
|
|
m_path = path;
|
|
m_tex_id = const_hash(path.c_str());
|
|
if (!m_path.empty() && TextureManager::load(m_path.c_str(), m_use_mipmaps))
|
|
{
|
|
auto tex_sz = TextureManager::get(m_tex_id).size();
|
|
m_off = xy(m_region) / tex_sz;
|
|
m_sz = (zw(m_region) - xy(m_region)) / tex_sz;
|
|
if (m_autosize)
|
|
SetAspectRatio(tex_sz.x / tex_sz.y);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void NodeImage::load_url(const std::string& url)
|
|
{
|
|
m_remote_header_decoded = false;
|
|
m_remote_asset = std::make_shared<Asset>();
|
|
m_remote_asset->open_url_async(url,
|
|
[this] (float progress) -> bool {
|
|
int w, h, c;
|
|
if (!m_remote_header_decoded &&
|
|
stbi_info_from_memory(m_remote_asset->tmp_data.data(), m_remote_asset->tmp_data.size(), &w, &h, &c))
|
|
{
|
|
if (m_autosize)
|
|
SetAspectRatio((float)w / (float)h);
|
|
m_remote_header_decoded = true;
|
|
}
|
|
return true;
|
|
},
|
|
[this] (bool success) {
|
|
if (success)
|
|
{
|
|
int w, h, c;
|
|
uint8_t* rgba = stbi_load_from_memory(m_remote_asset->m_data, m_remote_asset->m_len, &w, &h, &c, 4);
|
|
m_remote_texture = std::make_shared<Texture2D>();
|
|
m_remote_texture->create(
|
|
w,
|
|
h,
|
|
pp::renderer::gl::rgba8_internal_format(),
|
|
pp::renderer::gl::rgba_pixel_format(),
|
|
rgba);
|
|
if (m_use_mipmaps)
|
|
m_remote_texture->create_mipmaps();
|
|
delete rgba;
|
|
if (m_autosize)
|
|
SetAspectRatio((float)w / (float)h);
|
|
}
|
|
m_remote_asset.reset();
|
|
}
|
|
);
|
|
}
|
|
|
|
void NodeImage::added(Node* parent)
|
|
{
|
|
Node::added(parent);
|
|
if (!m_url.empty() && added_to_root())
|
|
load_url(m_url);
|
|
}
|