mirror of
https://github.com/edubart/otclient.git
synced 2025-10-19 05:53:26 +02:00
Restore support for animated png files
* Rework resource manager * Add missing files * Improve some graphics classes
This commit is contained in:
@@ -24,53 +24,60 @@
|
||||
#include "graphics.h"
|
||||
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
/*
|
||||
AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay) :
|
||||
Texture(),
|
||||
m_numFrames(numFrames)
|
||||
|
||||
AnimatedTexture::AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps, bool compress)
|
||||
{
|
||||
m_size.resize(width, height);
|
||||
if(!setupSize(size, buildMipmaps))
|
||||
return;
|
||||
|
||||
m_framesTextureId.resize(numFrames);
|
||||
m_framesDelay.resize(numFrames);
|
||||
|
||||
for(int i=0;i<numFrames;++i) {
|
||||
uchar *framePixels = framesPixels + (i*height*width* channels);
|
||||
uint id = internalLoadGLTexture(framePixels, channels, width, height);
|
||||
|
||||
m_framesTextureId[i] = id;
|
||||
m_framesDelay[i] = framesDelay[i];
|
||||
for(uint i=0;i<frames.size();++i) {
|
||||
m_frames.push_back(new Texture(frames[i], buildMipmaps, compress));
|
||||
}
|
||||
m_currentFrame = -1;
|
||||
g_dispatcher.scheduleEvent(std::bind(&AnimatedTexture::processAnimation, this), 0);
|
||||
|
||||
m_framesDelay = framesDelay;
|
||||
m_hasMipmaps = buildMipmaps;
|
||||
m_id = m_frames[0]->getId();
|
||||
m_currentFrame = 0;
|
||||
m_animTimer.restart();
|
||||
}
|
||||
|
||||
AnimatedTexture::~AnimatedTexture()
|
||||
{
|
||||
glDeleteTextures(m_numFrames, &m_framesTextureId[0]);
|
||||
m_id = 0;
|
||||
|
||||
}
|
||||
|
||||
void AnimatedTexture::enableBilinearFilter()
|
||||
bool AnimatedTexture::buildHardwareMipmaps()
|
||||
{
|
||||
for(int i=0;i<m_numFrames;++i) {
|
||||
glBindTexture(GL_TEXTURE_2D, m_framesTextureId[i]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
if(!g_graphics.canUseHardwareMipmaps())
|
||||
return false;
|
||||
for(const TexturePtr& frame : m_frames)
|
||||
frame->buildHardwareMipmaps();
|
||||
m_hasMipmaps = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnimatedTexture::processAnimation()
|
||||
void AnimatedTexture::setSmooth(bool smooth)
|
||||
{
|
||||
for(const TexturePtr& frame : m_frames)
|
||||
frame->setSmooth(smooth);
|
||||
m_smooth = smooth;
|
||||
}
|
||||
|
||||
void AnimatedTexture::setRepeat(bool repeat)
|
||||
{
|
||||
for(const TexturePtr& frame : m_frames)
|
||||
frame->setRepeat(repeat);
|
||||
m_repeat = repeat;
|
||||
}
|
||||
|
||||
void AnimatedTexture::updateAnimation()
|
||||
{
|
||||
if(m_animTimer.ticksElapsed() < m_framesDelay[m_currentFrame])
|
||||
return;
|
||||
|
||||
m_animTimer.restart();
|
||||
m_currentFrame++;
|
||||
if(m_currentFrame >= m_numFrames)
|
||||
if(m_currentFrame >= m_frames.size())
|
||||
m_currentFrame = 0;
|
||||
m_id = m_framesTextureId[m_currentFrame];
|
||||
|
||||
AnimatedTexturePtr self = asAnimatedTexture();
|
||||
|
||||
// continue to animate only if something still referencing this texture
|
||||
if(self->ref_count() > 1)
|
||||
g_dispatcher.scheduleEvent(std::bind(&AnimatedTexture::processAnimation, self), m_framesDelay[m_currentFrame]);
|
||||
m_id = m_frames[m_currentFrame]->getId();
|
||||
}
|
||||
*/
|
@@ -24,24 +24,28 @@
|
||||
#define ANIMATEDTEXTURE_H
|
||||
|
||||
#include "texture.h"
|
||||
/*
|
||||
#include <framework/core/timer.h>
|
||||
|
||||
class AnimatedTexture : public Texture
|
||||
{
|
||||
public:
|
||||
AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay);
|
||||
AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps = false, bool compress = false);
|
||||
virtual ~AnimatedTexture();
|
||||
|
||||
void enableBilinearFilter();
|
||||
void processAnimation();
|
||||
virtual bool buildHardwareMipmaps();
|
||||
|
||||
AnimatedTexturePtr asAnimatedTexture() { return static_self_cast<AnimatedTexture>(); }
|
||||
virtual void setSmooth(bool smooth);
|
||||
virtual void setRepeat(bool repeat);
|
||||
|
||||
void updateAnimation();
|
||||
|
||||
virtual bool isAnimatedTexture() { return true; }
|
||||
|
||||
private:
|
||||
std::vector<uint> m_framesTextureId;
|
||||
std::vector<TexturePtr> m_frames;
|
||||
std::vector<int> m_framesDelay;
|
||||
int m_numFrames;
|
||||
int m_currentFrame;
|
||||
ticks_t m_lastAnimCheckTicks;
|
||||
uint m_currentFrame;
|
||||
Timer m_animTimer;
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
@@ -52,9 +52,6 @@ void BitmapFont::load(const OTMLNodePtr& fontNode)
|
||||
m_glyphsSize[32].setWidth(spaceWidth);
|
||||
m_glyphsSize[160].setWidth(spaceWidth);
|
||||
|
||||
// use 127 as spacer [Width: 1]
|
||||
m_glyphsSize[127].setWidth(1);
|
||||
|
||||
// new line actually has a size that will be useful in multiline algorithm
|
||||
m_glyphsSize[(uchar)'\n'] = Size(1, m_glyphHeight);
|
||||
|
||||
@@ -262,6 +259,9 @@ Size BitmapFont::calculateTextRectSize(const std::string& text)
|
||||
|
||||
void BitmapFont::calculateGlyphsWidthsAutomatically(const ImagePtr& image, const Size& glyphSize)
|
||||
{
|
||||
if(!image)
|
||||
return;
|
||||
|
||||
int numHorizontalGlyphs = image->getSize().width() / glyphSize.width();
|
||||
auto texturePixels = image->getPixels();
|
||||
|
||||
@@ -338,4 +338,4 @@ std::string BitmapFont::wrapText(const std::string& text, int maxWidth)
|
||||
outText = outText.substr(0, outText.length()-1);
|
||||
|
||||
return outText;
|
||||
}
|
||||
}
|
||||
|
@@ -39,8 +39,8 @@ public:
|
||||
void setAlign(Fw::AlignmentFlag align) { m_align = align; update(); }
|
||||
|
||||
Size getTextSize() { return m_textSize; }
|
||||
std::string getText() { return m_text; }
|
||||
BitmapFontPtr getFont() { return m_font; }
|
||||
std::string getText() const { return m_text; }
|
||||
BitmapFontPtr getFont() const { return m_font; }
|
||||
Fw::AlignmentFlag getAlign() { return m_align; }
|
||||
|
||||
private:
|
||||
|
@@ -59,6 +59,11 @@ public:
|
||||
m_textureCoordArray.addQuad(src);
|
||||
m_hardwareCached = false;
|
||||
}
|
||||
void addUpsideDownQuad(const Rect& dest, const Rect& src) {
|
||||
m_vertexArray.addUpsideDownQuad(dest);
|
||||
m_textureCoordArray.addQuad(src);
|
||||
m_hardwareCached = false;
|
||||
}
|
||||
|
||||
void addBoudingRect(const Rect& dest, int innerLineWidth);
|
||||
void addRepeatedRects(const Rect& dest, const Rect& src);
|
||||
|
@@ -45,13 +45,12 @@ void FontManager::clearFonts()
|
||||
m_defaultFont = BitmapFontPtr(new BitmapFont("emptyfont"));
|
||||
}
|
||||
|
||||
bool FontManager::importFont(std::string fontFile)
|
||||
bool FontManager::importFont(std::string file)
|
||||
{
|
||||
try {
|
||||
if(!stdext::ends_with(fontFile, ".otfont"))
|
||||
fontFile += ".otfont";
|
||||
file = g_resources.guessFileType(file, "otfont");
|
||||
|
||||
OTMLDocumentPtr doc = OTMLDocument::parse(fontFile);
|
||||
OTMLDocumentPtr doc = OTMLDocument::parse(file);
|
||||
OTMLNodePtr fontNode = doc->at("Font");
|
||||
|
||||
std::string name = fontNode->valueAt("name");
|
||||
@@ -69,12 +68,12 @@ bool FontManager::importFont(std::string fontFile)
|
||||
m_fonts.push_back(font);
|
||||
|
||||
// set as default if needed
|
||||
if(!m_defaultFont)
|
||||
if(!m_defaultFont || fontNode->valueAt<bool>("default", false))
|
||||
m_defaultFont = font;
|
||||
|
||||
return true;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("Unable to load font from file '%s': %s", fontFile, e.what()));
|
||||
g_logger.error(stdext::format("Unable to load font from file '%s': %s", file, e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -100,4 +99,3 @@ BitmapFontPtr FontManager::getFont(const std::string& fontName)
|
||||
g_logger.error(stdext::format("font '%s' not found", fontName));
|
||||
return getDefaultFont();
|
||||
}
|
||||
|
||||
|
@@ -34,7 +34,7 @@ public:
|
||||
void terminate();
|
||||
void clearFonts();
|
||||
|
||||
bool importFont(std::string fontFile);
|
||||
bool importFont(std::string file);
|
||||
|
||||
bool fontExists(const std::string& fontName);
|
||||
BitmapFontPtr getFont(const std::string& fontName);
|
||||
|
@@ -173,6 +173,8 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
||||
{
|
||||
Painter *painter = nullptr;
|
||||
Painter *fallbackPainter = nullptr;
|
||||
PainterEngine fallbackPainterEngine = Painter_Any;
|
||||
|
||||
#ifdef PAINTER_OGL2
|
||||
// always prefer OpenGL 2 over OpenGL 1
|
||||
if(g_painterOGL2) {
|
||||
@@ -181,6 +183,7 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
||||
painter = g_painterOGL2;
|
||||
}
|
||||
fallbackPainter = g_painterOGL2;
|
||||
fallbackPainterEngine = Painter_OpenGL2;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -192,11 +195,14 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
||||
painter = g_painterOGL1;
|
||||
}
|
||||
fallbackPainter = g_painterOGL1;
|
||||
fallbackPainterEngine = Painter_OpenGL1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!painter)
|
||||
if(!painter) {
|
||||
painter = fallbackPainter;
|
||||
m_selectedPainterEngine = fallbackPainterEngine;
|
||||
}
|
||||
|
||||
// switch painters GL state
|
||||
if(painter) {
|
||||
|
@@ -59,6 +59,8 @@ public:
|
||||
std::string getVersion() { return (const char*)glGetString(GL_VERSION); }
|
||||
std::string getExtensions() { return (const char*)glGetString(GL_EXTENSIONS); }
|
||||
|
||||
void setShouldUseShaders(bool enable) { m_shouldUseShaders = enable; }
|
||||
|
||||
bool ok() { return m_ok; }
|
||||
bool canUseDrawArrays();
|
||||
bool canUseShaders();
|
||||
@@ -71,6 +73,7 @@ public:
|
||||
bool canUseClampToEdge();
|
||||
bool canUseBlendFuncSeparate();
|
||||
bool canCacheBackbuffer();
|
||||
bool shouldUseShaders() { return m_shouldUseShaders; }
|
||||
bool hasScissorBug();
|
||||
|
||||
private:
|
||||
@@ -87,6 +90,7 @@ private:
|
||||
stdext::boolean<true> m_useMipmaps;
|
||||
stdext::boolean<true> m_useHardwareMipmaps;
|
||||
stdext::boolean<true> m_useClampToEdge;
|
||||
stdext::boolean<true> m_shouldUseShaders;
|
||||
stdext::boolean<true> m_cacheBackbuffer;
|
||||
PainterEngine m_prefferedPainterEngine;
|
||||
PainterEngine m_selectedPainterEngine;
|
||||
@@ -94,4 +98,4 @@ private:
|
||||
|
||||
extern Graphics g_graphics;
|
||||
|
||||
#endif
|
||||
#endif
|
@@ -35,13 +35,11 @@ Image::Image(const Size& size, int bpp, uint8 *pixels)
|
||||
memcpy(&m_pixels[0], pixels, m_pixels.size());
|
||||
}
|
||||
|
||||
ImagePtr Image::load(const std::string& file)
|
||||
ImagePtr Image::load(std::string file)
|
||||
{
|
||||
ImagePtr image;
|
||||
try {
|
||||
// currently only png images are supported
|
||||
if(!stdext::ends_with(file, ".png"))
|
||||
stdext::throw_exception("image file format no supported");
|
||||
file = g_resources.guessFileType(file, "png");
|
||||
|
||||
// load image file data
|
||||
image = loadPNG(file);
|
||||
@@ -54,7 +52,7 @@ ImagePtr Image::load(const std::string& file)
|
||||
ImagePtr Image::loadPNG(const std::string& file)
|
||||
{
|
||||
std::stringstream fin;
|
||||
g_resources.loadFile(file, fin);
|
||||
g_resources.readFileStream(file, fin);
|
||||
ImagePtr image;
|
||||
apng_data apng;
|
||||
if(load_apng(fin, &apng) == 0) {
|
||||
|
@@ -31,7 +31,7 @@ class Image : public stdext::shared_object
|
||||
public:
|
||||
Image(const Size& size, int bpp = 4, uint8 *pixels = nullptr);
|
||||
|
||||
static ImagePtr load(const std::string& file);
|
||||
static ImagePtr load(std::string file);
|
||||
static ImagePtr loadPNG(const std::string& file);
|
||||
|
||||
void overwriteMask(const Color& maskedColor, const Color& insideColor = Color::white, const Color& outsideColor = Color::alpha);
|
||||
|
@@ -75,6 +75,7 @@ public:
|
||||
virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0;
|
||||
virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0;
|
||||
virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
|
||||
virtual void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
|
||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); }
|
||||
virtual void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
|
||||
virtual void drawFilledRect(const Rect& dest) = 0;
|
||||
|
@@ -149,6 +149,18 @@ void PainterOGL1::drawTexturedRect(const Rect& dest, const TexturePtr& texture,
|
||||
drawCoords(m_coordsBuffer, TriangleStrip);
|
||||
}
|
||||
|
||||
void PainterOGL1::drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
|
||||
{
|
||||
if(dest.isEmpty() || src.isEmpty() || texture->isEmpty())
|
||||
return;
|
||||
|
||||
setTexture(texture.get());
|
||||
|
||||
m_coordsBuffer.clear();
|
||||
m_coordsBuffer.addUpsideDownQuad(dest, src);
|
||||
drawCoords(m_coordsBuffer, TriangleStrip);
|
||||
}
|
||||
|
||||
void PainterOGL1::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
|
||||
{
|
||||
if(dest.isEmpty() || src.isEmpty() || texture->isEmpty())
|
||||
|
@@ -51,6 +51,7 @@ public:
|
||||
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
||||
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
|
||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
void drawFilledRect(const Rect& dest);
|
||||
void drawFilledTriangle(const Point& a, const Point& b, const Point& c);
|
||||
|
@@ -141,6 +141,19 @@ void PainterOGL2::drawTexturedRect(const Rect& dest, const TexturePtr& texture,
|
||||
drawCoords(m_coordsBuffer, TriangleStrip);
|
||||
}
|
||||
|
||||
void PainterOGL2::drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
|
||||
{
|
||||
if(dest.isEmpty() || src.isEmpty() || texture->isEmpty())
|
||||
return;
|
||||
|
||||
setDrawProgram(m_shaderProgram ? m_shaderProgram : m_drawTexturedProgram.get());
|
||||
setTexture(texture);
|
||||
|
||||
m_coordsBuffer.clear();
|
||||
m_coordsBuffer.addUpsideDownQuad(dest, src);
|
||||
drawCoords(m_coordsBuffer, TriangleStrip);
|
||||
}
|
||||
|
||||
void PainterOGL2::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
|
||||
{
|
||||
if(dest.isEmpty() || src.isEmpty() || texture->isEmpty())
|
||||
|
@@ -43,6 +43,7 @@ public:
|
||||
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
||||
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
|
||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
void drawFilledRect(const Rect& dest);
|
||||
void drawFilledTriangle(const Point& a, const Point& b, const Point& c);
|
||||
|
@@ -45,6 +45,8 @@ void PainterShaderProgram::setupUniforms()
|
||||
bindUniformLocation(TIME_UNIFORM, "u_Time");
|
||||
bindUniformLocation(TEX0_UNIFORM, "u_Tex0");
|
||||
bindUniformLocation(TEX1_UNIFORM, "u_Tex1");
|
||||
bindUniformLocation(TEX2_UNIFORM, "u_Tex2");
|
||||
bindUniformLocation(TEX3_UNIFORM, "u_Tex3");
|
||||
bindUniformLocation(RESOLUTION_UNIFORM, "u_Resolution");
|
||||
|
||||
setUniformValue(PROJECTION_MATRIX_UNIFORM, m_projectionMatrix);
|
||||
@@ -54,6 +56,8 @@ void PainterShaderProgram::setupUniforms()
|
||||
setUniformValue(TIME_UNIFORM, m_time);
|
||||
setUniformValue(TEX0_UNIFORM, 0);
|
||||
setUniformValue(TEX1_UNIFORM, 1);
|
||||
setUniformValue(TEX2_UNIFORM, 2);
|
||||
setUniformValue(TEX3_UNIFORM, 3);
|
||||
setUniformValue(RESOLUTION_UNIFORM, (float)m_resolution.width(), (float)m_resolution.height());
|
||||
}
|
||||
|
||||
@@ -154,7 +158,7 @@ void PainterShaderProgram::bindMultiTextures()
|
||||
|
||||
int i=1;
|
||||
for(const TexturePtr& tex : m_multiTextures) {
|
||||
glActiveTexture(GL_TEXTURE0 + 1);
|
||||
glActiveTexture(GL_TEXTURE0 + i++);
|
||||
glBindTexture(GL_TEXTURE_2D, tex->getId());
|
||||
}
|
||||
|
||||
|
@@ -20,8 +20,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PAINTERSHADER_H
|
||||
#define PAINTERSHADER_H
|
||||
#ifndef PAINTERSHADERPROGRAM_H
|
||||
#define PAINTERSHADERPROGRAM_H
|
||||
|
||||
#include "shaderprogram.h"
|
||||
#include "coordsbuffer.h"
|
||||
@@ -40,7 +40,9 @@ protected:
|
||||
TIME_UNIFORM = 4,
|
||||
TEX0_UNIFORM = 5,
|
||||
TEX1_UNIFORM = 6,
|
||||
RESOLUTION_UNIFORM = 7,
|
||||
TEX2_UNIFORM = 7,
|
||||
TEX3_UNIFORM = 8,
|
||||
RESOLUTION_UNIFORM = 9,
|
||||
};
|
||||
|
||||
friend class PainterOGL2;
|
||||
|
@@ -26,9 +26,11 @@
|
||||
|
||||
ParticleManager g_particles;
|
||||
|
||||
bool ParticleManager::importParticle(const std::string& file)
|
||||
bool ParticleManager::importParticle(std::string file)
|
||||
{
|
||||
try {
|
||||
file = g_resources.guessFileType(file, "otps");
|
||||
|
||||
OTMLDocumentPtr doc = OTMLDocument::parse(file);
|
||||
for(const OTMLNodePtr& node : doc->children()) {
|
||||
if(node->tag() == "Effect") {
|
||||
|
@@ -29,7 +29,7 @@
|
||||
class ParticleManager
|
||||
{
|
||||
public:
|
||||
bool importParticle(const std::string& file);
|
||||
bool importParticle(std::string file);
|
||||
ParticleEffectPtr createEffect(const std::string& name);
|
||||
void terminate();
|
||||
|
||||
|
@@ -80,7 +80,7 @@ bool Shader::compileSourceCode(const std::string& sourceCode)
|
||||
bool Shader::compileSourceFile(const std::string& sourceFile)
|
||||
{
|
||||
try {
|
||||
std::string sourceCode = g_resources.loadFile(sourceFile);
|
||||
std::string sourceCode = g_resources.readFileContents(sourceFile);
|
||||
return compileSourceCode(sourceCode);
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("unable to load shader source form file: %s", sourceFile));
|
||||
|
@@ -35,10 +35,10 @@ public:
|
||||
|
||||
void bind();
|
||||
void copyFromScreen(const Rect& screenRect);
|
||||
bool buildHardwareMipmaps();
|
||||
virtual bool buildHardwareMipmaps();
|
||||
|
||||
void setSmooth(bool smooth);
|
||||
void setRepeat(bool repeat);
|
||||
virtual void setSmooth(bool smooth);
|
||||
virtual void setRepeat(bool repeat);
|
||||
void setUpsideDown(bool upsideDown);
|
||||
|
||||
uint getId() { return m_id; }
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
bool isEmpty() { return m_id == 0; }
|
||||
bool hasRepeat() { return m_repeat; }
|
||||
bool hasMipmaps() { return m_hasMipmaps; }
|
||||
virtual bool isAnimatedTexture() { return false; }
|
||||
|
||||
protected:
|
||||
void createTexture();
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "image.h"
|
||||
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/graphics/apngloader.h>
|
||||
|
||||
TextureManager g_textures;
|
||||
@@ -38,11 +39,26 @@ void TextureManager::init()
|
||||
void TextureManager::terminate()
|
||||
{
|
||||
m_textures.clear();
|
||||
m_animatedTextures.clear();
|
||||
m_emptyTexture = nullptr;
|
||||
}
|
||||
|
||||
void TextureManager::poll()
|
||||
{
|
||||
// update only every 16msec, this allows upto 60 fps for animated textures
|
||||
static ticks_t lastUpdate = 0;
|
||||
ticks_t now = g_clock.millis();
|
||||
if(now - lastUpdate < 16)
|
||||
return;
|
||||
lastUpdate = now;
|
||||
|
||||
for(const AnimatedTexturePtr& animatedTexture : m_animatedTextures)
|
||||
animatedTexture->updateAnimation();
|
||||
}
|
||||
|
||||
void TextureManager::clearTexturesCache()
|
||||
{
|
||||
m_animatedTextures.clear();
|
||||
m_textures.clear();
|
||||
}
|
||||
|
||||
@@ -62,13 +78,11 @@ TexturePtr TextureManager::getTexture(const std::string& fileName)
|
||||
// texture not found, load it
|
||||
if(!texture) {
|
||||
try {
|
||||
// currently only png textures are supported
|
||||
if(!stdext::ends_with(filePath, ".png"))
|
||||
stdext::throw_exception("texture file format not supported");
|
||||
std::string filePathEx = g_resources.guessFileType(filePath, "png");
|
||||
|
||||
// load texture file data
|
||||
std::stringstream fin;
|
||||
g_resources.loadFile(filePath, fin);
|
||||
g_resources.readFileStream(filePathEx, fin);
|
||||
texture = loadPNG(fin);
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("Unable to load texture '%s': %s", fileName, e.what()));
|
||||
@@ -88,12 +102,22 @@ TexturePtr TextureManager::loadPNG(std::stringstream& file)
|
||||
|
||||
apng_data apng;
|
||||
if(load_apng(file, &apng) == 0) {
|
||||
Size imageSize(apng.width, apng.height);
|
||||
if(apng.num_frames > 1) { // animated texture
|
||||
//uchar *framesdata = apng.pdata + (apng.first_frame * apng.width * apng.height * apng.bpp);
|
||||
//texture = TexturePtr(new AnimatedTexture(apng.width, apng.height, apng.bpp, apng.num_frames, framesdata, (int*)apng.frames_delay));
|
||||
g_logger.error("animated textures is disabled for a while");
|
||||
std::vector<ImagePtr> frames;
|
||||
std::vector<int> framesDelay;
|
||||
for(uint i=0;i<apng.num_frames;++i) {
|
||||
uchar *frameData = apng.pdata + ((apng.first_frame+i) * imageSize.area() * apng.bpp);
|
||||
int frameDelay = apng.frames_delay[i];
|
||||
|
||||
framesDelay.push_back(frameDelay);
|
||||
frames.push_back(ImagePtr(new Image(imageSize, apng.bpp, frameData)));
|
||||
}
|
||||
AnimatedTexturePtr animatedTexture = new AnimatedTexture(imageSize, frames, framesDelay);
|
||||
m_animatedTextures.push_back(animatedTexture);
|
||||
texture = animatedTexture;
|
||||
} else {
|
||||
ImagePtr image = ImagePtr(new Image(Size(apng.width, apng.height), apng.bpp, apng.pdata));
|
||||
ImagePtr image = ImagePtr(new Image(imageSize, apng.bpp, apng.pdata));
|
||||
texture = TexturePtr(new Texture(image));
|
||||
}
|
||||
free_apng(&apng);
|
||||
|
@@ -30,6 +30,7 @@ class TextureManager
|
||||
public:
|
||||
void init();
|
||||
void terminate();
|
||||
void poll();
|
||||
|
||||
void clearTexturesCache();
|
||||
TexturePtr getTexture(const std::string& fileName);
|
||||
@@ -39,6 +40,7 @@ private:
|
||||
TexturePtr loadPNG(std::stringstream& file);
|
||||
|
||||
std::unordered_map<std::string, TexturePtr> m_textures;
|
||||
std::vector<AnimatedTexturePtr> m_animatedTextures;
|
||||
TexturePtr m_emptyTexture;
|
||||
};
|
||||
|
||||
|
@@ -61,6 +61,18 @@ public:
|
||||
addVertex(right, bottom);
|
||||
}
|
||||
|
||||
inline void addUpsideDownQuad(const Rect& rect) {
|
||||
float top = rect.top();
|
||||
float right = rect.right()+1;
|
||||
float bottom = rect.bottom()+1;
|
||||
float left = rect.left();
|
||||
|
||||
addVertex(left, bottom);
|
||||
addVertex(right, bottom);
|
||||
addVertex(left, top);
|
||||
addVertex(right, top);
|
||||
}
|
||||
|
||||
void clear() { m_buffer.reset(); }
|
||||
float *vertices() const { return m_buffer.data(); }
|
||||
int vertexCount() const { return m_buffer.size() / 2; }
|
||||
|
Reference in New Issue
Block a user