gui renderer: fopen -> FileSystem::OpenAsync - closes #51

This commit is contained in:
Mikulas Florek 2014-01-02 11:56:23 +01:00
parent a03827a06c
commit 887f96534c
5 changed files with 126 additions and 87 deletions

View file

@ -17,6 +17,8 @@ namespace Lux
struct AtlasImpl
{
void imageLoaded(TextureBase& img);
map<uint32_t, Atlas::Part*> m_parts;
TextureBase* m_texture;
string m_path;
@ -62,11 +64,23 @@ namespace Lux
m_impl = 0;
}
void AtlasImpl::imageLoaded(TextureBase& img)
{
for(map<uint32_t, Atlas::Part*>::iterator iter = m_parts.begin(), end = m_parts.end(); iter != end; ++iter)
{
iter.second()->m_left /= img.getWidth();
iter.second()->m_right /= img.getWidth();
iter.second()->m_top /= img.getHeight();
iter.second()->m_bottom /= img.getHeight();
}
}
void atlasLoaded(Lux::FS::IFile* file, bool success, void* user_data)
{
if(!success)
{
file->close();
return;
}
AtlasImpl* atlas = static_cast<AtlasImpl*>(user_data);
@ -74,8 +88,9 @@ namespace Lux
JsonSerializer serializer(*file, JsonSerializer::READ);
char tmp[260];
serializer.deserialize("image", tmp, 260);
atlas->m_texture = atlas->m_renderer->loadImage(tmp);
atlas->m_texture = atlas->m_renderer->loadImage(tmp, *atlas->m_filesystem);
ASSERT(atlas->m_texture);
atlas->m_texture->onLoaded().bind<AtlasImpl, &AtlasImpl::imageLoaded>(atlas);
int count;
serializer.deserialize("part_count", count);
serializer.deserializeArrayBegin("parts");
@ -89,10 +104,6 @@ namespace Lux
serializer.deserializeArrayItem(part->m_bottom);
part->m_pixel_width = part->m_right - part->m_left;
part->m_pixel_height = part->m_bottom - part->m_top;
part->m_right /= atlas->m_texture->getWidth();
part->m_left /= atlas->m_texture->getWidth();
part->m_top /= atlas->m_texture->getHeight();
part->m_bottom /= atlas->m_texture->getHeight();
part->name = tmp;
atlas->m_parts.insert(crc32(tmp), part);
}

View file

@ -23,7 +23,7 @@ namespace UI
{
public:
virtual void loadFont(const char* path, FS::FileSystem& file_system) = 0;
virtual TextureBase* loadImage(const char* name) = 0;
virtual TextureBase* loadImage(const char* name, FS::FileSystem& file_system) = 0;
virtual void beginRender(float w, float h) = 0;
virtual void renderImage(TextureBase* image, float* vertices, float* tex_coords, int vertex_count) = 0;
virtual void measureText(const char* text, float* w, float* h) = 0;

View file

@ -3,6 +3,7 @@
#include <Windows.h>
#include <gl/GL.h>
#include "core/array.h"
#include "core/delegate_list.h"
#include "core/file_system.h"
#include "core/ifile.h"
#include "core/map.h"
@ -28,6 +29,8 @@ namespace UI
GLuint getId() const { return m_gl_id; }
void setId(GLuint id) { m_gl_id = id; }
static void imageLoaded(FS::IFile* file, bool success, void* user_data);
private:
GLuint m_gl_id;
};
@ -49,12 +52,14 @@ namespace UI
TextureBase* getImage(const char* name);
static void fontLoaded(FS::IFile* file, bool success, void* user_data);
void fontImageLoaded(TextureBase& img);
map<char, Character> m_characters;
PODArray<TextureBase*> m_images;
OpenGLTexture* m_font_image;
int m_window_height;
PODArray<Block::Area> m_scissors_areas;
FS::FileSystem* m_file_system;
};
#pragma pack(1)
@ -102,89 +107,101 @@ namespace UI
}
TextureBase* OpenGLRenderer::loadImage(const char* name)
TextureBase* OpenGLRenderer::loadImage(const char* name, FS::FileSystem& file_system)
{
TextureBase* img = m_impl->getImage(name);
if(img)
{
return img;
}
FILE* fp;
fopen_s(&fp, name, "rb");
fseek(fp, 0, SEEK_END);
long buffer_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* buffer = new char[buffer_size];
fread(buffer, buffer_size, 1, fp);
fclose(fp);
TGAHeader header;
memcpy(&header, buffer, sizeof(TGAHeader));
int color_mode = header.bitsPerPixel / 8;
int image_size = header.width * header.height * 4;
if (header.dataType != 2)
{
return NULL;
}
if (color_mode < 3)
{
return NULL;
}
const char* image_src = buffer + sizeof(TGAHeader);
unsigned char* image_dest = new unsigned char[image_size];
img = new OpenGLTexture(name, (float)header.width, (float)header.height);
// Targa is BGR, swap to RGB and flip Y axis
for (long y = 0; y < header.height; y++)
{
long read_index = y * header.width * color_mode;
long write_index = ((header.imageDescriptor & 32) != 0) ? read_index : (header.height - y - 1) * header.width * color_mode;
for (long x = 0; x < header.width; x++)
{
image_dest[write_index] = image_src[read_index+2];
image_dest[write_index+1] = image_src[read_index+1];
image_dest[write_index+2] = image_src[read_index];
if (color_mode == 4)
image_dest[write_index+3] = image_src[read_index+3];
else
image_dest[write_index+3] = 255;
write_index += 4;
read_index += color_mode;
}
}
GLuint texture_id = 0;
glGenTextures(1, &texture_id);
if (texture_id == 0)
{
return NULL;
}
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, header.width, header.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_dest);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/
delete [] image_dest;
delete [] buffer;
static_cast<OpenGLTexture*>(img)->setId(texture_id);
img = new OpenGLTexture(name, (float)0, (float)0);
static_cast<OpenGLTexture*>(img)->setId(0);
file_system.openAsync(file_system.getDefaultDevice(), name, FS::Mode::OPEN | FS::Mode::READ, &OpenGLTexture::imageLoaded, img);
return img;
}
void OpenGLTexture::imageLoaded(FS::IFile* file, bool success, void* user_data)
{
if(success)
{
size_t buffer_size = file->size();
char* buffer = new char[buffer_size];
file->read(buffer, buffer_size);
file->close();
TGAHeader header;
memcpy(&header, buffer, sizeof(TGAHeader));
int color_mode = header.bitsPerPixel / 8;
int image_size = header.width * header.height * 4;
if (header.dataType != 2)
{
delete[] buffer;
return;
}
if (color_mode < 3)
{
delete[] buffer;
return;
}
const char* image_src = buffer + sizeof(TGAHeader);
unsigned char* image_dest = new unsigned char[image_size];
// Targa is BGR, swap to RGB and flip Y axis
for (long y = 0; y < header.height; y++)
{
long read_index = y * header.width * color_mode;
long write_index = ((header.imageDescriptor & 32) != 0) ? read_index : (header.height - y - 1) * header.width * color_mode;
for (long x = 0; x < header.width; x++)
{
image_dest[write_index] = image_src[read_index+2];
image_dest[write_index+1] = image_src[read_index+1];
image_dest[write_index+2] = image_src[read_index];
if (color_mode == 4)
image_dest[write_index+3] = image_src[read_index+3];
else
image_dest[write_index+3] = 255;
write_index += 4;
read_index += color_mode;
}
}
GLuint texture_id = 0;
glGenTextures(1, &texture_id);
if (texture_id == 0)
{
delete[] buffer;
return;
}
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, header.width, header.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_dest);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/
delete [] image_dest;
delete [] buffer;
OpenGLTexture* img = static_cast<OpenGLTexture*>(user_data);
img->setId(texture_id);
img->setSize((float)header.width, (float)header.height);
img->onLoaded().invoke(*img);
}
else
{
file->close();
}
}
void OpenGLRenderer::setWindowHeight(int height)
{
@ -355,6 +372,16 @@ namespace UI
}
void OpenGLRendererImpl::fontImageLoaded(TextureBase& texture)
{
char tmp[255];
strcpy_s(tmp, texture.getName().c_str());
int len = strlen(tmp);
strcpy_s(tmp + len - 4, 255 - len + 4, ".fnt");
m_file_system->openAsync(m_file_system->getDefaultDevice(), tmp, FS::Mode::OPEN | FS::Mode::READ, &OpenGLRendererImpl::fontLoaded, this);
}
void OpenGLRendererImpl::fontLoaded(FS::IFile* file, bool success, void* user_data)
{
if(success)
@ -407,12 +434,9 @@ namespace UI
void OpenGLRenderer::loadFont(const char* path, FS::FileSystem& file_system)
{
m_impl->m_font_image = static_cast<OpenGLTexture*>(loadImage(path));
char tmp[255];
strcpy_s(tmp, path);
int len = strlen(tmp);
strcpy_s(tmp + len - 4, 255 - len + 4, ".fnt");
file_system.openAsync(file_system.getDefaultDevice(), tmp, FS::Mode::OPEN | FS::Mode::READ, &OpenGLRendererImpl::fontLoaded, m_impl);
m_impl->m_file_system = &file_system;
m_impl->m_font_image = static_cast<OpenGLTexture*>(loadImage(path, file_system));
m_impl->m_font_image->onLoaded().bind<OpenGLRendererImpl, &OpenGLRendererImpl::fontImageLoaded>(m_impl);
}

View file

@ -20,7 +20,7 @@ namespace UI
bool create();
void destroy();
virtual TextureBase* loadImage(const char* name) LUX_OVERRIDE;
virtual TextureBase* loadImage(const char* name, FS::FileSystem& file_system) LUX_OVERRIDE;
virtual void loadFont(const char* path, FS::FileSystem& file_system) LUX_OVERRIDE;
virtual void beginRender(float w, float h) LUX_OVERRIDE;
virtual void renderImage(TextureBase* image, float* vertices, float* tex_coords, int vertex_count) LUX_OVERRIDE;

View file

@ -1,6 +1,7 @@
#pragma once
#include "core/delegate_list.h"
#include "core/string.h"
@ -24,11 +25,14 @@ namespace Lux
const string& getName() const { return m_name; }
float getWidth() const { return m_width; }
float getHeight() const { return m_height; }
void setSize(float width, float height) { m_width = width; m_height = height; }
DelegateList<void (TextureBase&)>& onLoaded() { return m_on_loaded; }
protected:
string m_name;
float m_width;
float m_height;
DelegateList<void (TextureBase&)> m_on_loaded;
};
} // ~namespace Lux