From 95cf7eb788e3a6d74bbcd1be19fce4f1152be4a7 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Fri, 8 Jun 2012 21:40:22 -0300 Subject: [PATCH] graphics optimizations/fixes/features * cache text vertex for StaticText, AnimatedText and Creature names * improved outfit rendering * fully compatible with OpenGL 1.1 * enable mipmaping for game sprites again * Ctrl+W hotkey clean game texts --- modules/game/gameinterface.lua | 1 + src/framework/CMakeLists.txt | 1 + src/framework/application.cpp | 16 ++--- src/framework/graphics/declarations.h | 2 + src/framework/graphics/image.cpp | 52 +++++++++++++-- src/framework/graphics/painter.cpp | 21 +++++++ src/framework/graphics/painter.h | 6 ++ src/framework/graphics/texture.cpp | 2 - src/framework/platform/x11window.cpp | 8 +-- src/otclient/core/animatedtext.cpp | 13 ++-- src/otclient/core/animatedtext.h | 5 +- src/otclient/core/creature.cpp | 91 ++++++++------------------- src/otclient/core/creature.h | 5 +- src/otclient/core/map.cpp | 6 ++ src/otclient/core/map.h | 1 + src/otclient/core/statictext.cpp | 13 ++-- src/otclient/core/statictext.h | 6 +- src/otclient/core/thingstype.cpp | 1 + src/otclient/core/thingtype.cpp | 80 ++++++++++------------- src/otclient/core/thingtype.h | 6 +- src/otclient/luafunctions.cpp | 1 + 21 files changed, 181 insertions(+), 156 deletions(-) diff --git a/modules/game/gameinterface.lua b/modules/game/gameinterface.lua index d9a65773..663ba597 100644 --- a/modules/game/gameinterface.lua +++ b/modules/game/gameinterface.lua @@ -53,6 +53,7 @@ function GameInterface.init() Keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel, 250) Keyboard.bindKeyDown('Ctrl+Q', GameInterface.tryLogout, gameRootPanel) Keyboard.bindKeyDown('Ctrl+L', GameInterface.tryLogout, gameRootPanel) + Keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() TextMessage.clearMessages() end, gameRootPanel) if g_game.isOnline() then GameInterface.show() diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 43fcb1ce..a6d8238d 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -197,6 +197,7 @@ SET(framework_SOURCES ${framework_SOURCES} # framework graphics ${CMAKE_CURRENT_LIST_DIR}/graphics/font.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/cachedtext.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/painter.cpp diff --git a/src/framework/application.cpp b/src/framework/application.cpp index 0e84b170..b748197f 100644 --- a/src/framework/application.cpp +++ b/src/framework/application.cpp @@ -167,7 +167,6 @@ void Application::run() if(!m_initialized) return; - bool cacheForeground = true; m_stopping = false; m_running = true; @@ -190,14 +189,7 @@ void Application::run() bool redraw = false; bool updateForeground = false; - bool canCacheForeground = g_graphics.canCacheBackbuffer() && m_foregroundFrameCounter.getMaxFps() != 0; - if(cacheForeground != canCacheForeground) { - cacheForeground = canCacheForeground; - if(cacheForeground) - glColorMask(1,1,1,1); - else - glColorMask(1,1,1,0); - } + bool cacheForeground = g_graphics.canCacheBackbuffer() && m_foregroundFrameCounter.getMaxFps() != 0; if(m_backgroundFrameCounter.shouldProcessNextFrame()) { redraw = true; @@ -219,11 +211,15 @@ void Application::run() m_foregroundFrameCounter.processNextFrame(); // draw foreground - g_painter->clear(Color::black); + g_painter->setAlphaWriting(true); + g_painter->clear(Color::alpha); g_ui.render(Fw::ForegroundPane); // copy the foreground to a texture m_foreground->copyFromScreen(viewportRect); + + g_painter->clear(Color::black); + g_painter->setAlphaWriting(false); } // draw background (animated stuff) diff --git a/src/framework/graphics/declarations.h b/src/framework/graphics/declarations.h index 8434ed15..518299e7 100644 --- a/src/framework/graphics/declarations.h +++ b/src/framework/graphics/declarations.h @@ -30,6 +30,7 @@ class Texture; class Image; class AnimatedTexture; class Font; +class CachedText; class FrameBuffer; class Shader; class ShaderProgram; @@ -46,6 +47,7 @@ typedef std::shared_ptr ImagePtr; typedef std::shared_ptr TexturePtr; typedef std::shared_ptr AnimatedTexturePtr; typedef std::shared_ptr FontPtr; +typedef std::shared_ptr CachedTextPtr; typedef std::shared_ptr FrameBufferPtr; typedef std::shared_ptr ShaderPtr; typedef std::shared_ptr ShaderProgramPtr; diff --git a/src/framework/graphics/image.cpp b/src/framework/graphics/image.cpp index 580478f1..5a95781c 100644 --- a/src/framework/graphics/image.cpp +++ b/src/framework/graphics/image.cpp @@ -131,13 +131,57 @@ bool Image::nextMipmap() assert(m_bpp == 4); assert(stdext::is_power_of_two(m_size.width()) && stdext::is_power_of_two(m_size.height())); - if(m_size.width() == 1 || m_size.height() == 1) + int iw = m_size.width(); + int ih = m_size.height(); + if(iw == 1 && ih == 1) return false; - Size size = m_size / 2; - std::vector pixels(size.area()*4, 0xFF); + int ow = iw > 1 ? iw/2 : 1; + int oh = ih > 1 ? ih/2 : 1; + + std::vector pixels(ow*oh*4, 0xFF); + + //FIXME: calculate mipmaps for 8x1, 4x1, 2x1 ... + if(iw != 1 && ih != 1) { + for(int x=0;x 0) + outPixel[i] = pixelsSum[i] / usedPixels; + else + outPixel[i] = 0; + } + outPixel[3] = pixelsSum[3]/4; + } + } + } + m_pixels = pixels; - m_size = size; + m_size = Size(ow, oh); return true; } diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index 88e5fe8b..64371a34 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -34,6 +34,7 @@ Painter::Painter() m_compositionMode = CompositionMode_Normal; m_shaderProgram = nullptr; m_texture = nullptr; + m_alphaWriting = false; } void Painter::resetState() @@ -44,6 +45,7 @@ void Painter::resetState() resetClipRect(); resetShaderProgram(); resetTexture(); + resetAlphaWriting(); } void Painter::refreshState() @@ -51,6 +53,7 @@ void Painter::refreshState() updateGlCompositionMode(); updateGlClipRect(); updateGlTexture(); + updateGlAlphaWriting(); } void Painter::saveState() @@ -64,6 +67,7 @@ void Painter::saveState() m_olderStates[m_oldStateIndex].clipRect = m_clipRect; m_olderStates[m_oldStateIndex].shaderProgram = m_shaderProgram; m_olderStates[m_oldStateIndex].texture = m_texture; + m_olderStates[m_oldStateIndex].alphaWriting = m_alphaWriting; m_oldStateIndex++; } @@ -137,6 +141,15 @@ void Painter::setTexture(Texture* texture) } } +void Painter::setAlphaWriting(bool enable) +{ + if(m_alphaWriting == enable) + return; + + m_alphaWriting = enable; + updateGlAlphaWriting(); +} + void Painter::updateGlTexture() { if(m_glTextureId != 0) @@ -177,3 +190,11 @@ void Painter::updateGlClipRect() glDisable(GL_SCISSOR_TEST); } } + +void Painter::updateGlAlphaWriting() +{ + if(m_alphaWriting) + glColorMask(1,1,1,1); + else + glColorMask(1,1,1,0); +} diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index 5e327cd5..716163f7 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -52,6 +52,7 @@ public: Rect clipRect; Texture *texture; PainterShaderProgram *shaderProgram; + bool alphaWriting; }; Painter(); @@ -85,6 +86,7 @@ public: virtual void setClipRect(const Rect& clipRect); virtual void setShaderProgram(PainterShaderProgram *shaderProgram) { m_shaderProgram = shaderProgram; } virtual void setTexture(Texture *texture); + void setAlphaWriting(bool enable); void setShaderProgram(const PainterShaderProgramPtr& shaderProgram) { setShaderProgram(shaderProgram.get()); } void setTexture(const TexturePtr& texture) { setTexture(texture.get()); } @@ -96,6 +98,7 @@ public: CompositionMode getCompositionMode() { return m_compositionMode; } Rect getClipRect() { return m_clipRect; } PainterShaderProgram *getShaderProgram() { return m_shaderProgram; } + bool getAlphaWriting() { return m_alphaWriting; } void resetColor() { setColor(Color::white); } void resetOpacity() { setOpacity(1.0f); } @@ -103,11 +106,13 @@ public: void resetCompositionMode() { setCompositionMode(CompositionMode_Normal); } void resetShaderProgram() { setShaderProgram(nullptr); } void resetTexture() { setTexture(nullptr); } + void resetAlphaWriting() { setAlphaWriting(false); } protected: void updateGlTexture(); void updateGlCompositionMode(); void updateGlClipRect(); + void updateGlAlphaWriting(); CoordsBuffer m_coordsBuffer; @@ -119,6 +124,7 @@ protected: Rect m_clipRect; Texture *m_texture; PainterShaderProgram *m_shaderProgram; + bool m_alphaWriting; PainterState m_olderStates[10]; int m_oldStateIndex; diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index 932280cf..1bc43945 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -62,7 +62,6 @@ Texture::Texture(const ImagePtr& image, bool buildMipmaps) bind(); - /* if(buildMipmaps) { int level = 0; do { @@ -70,7 +69,6 @@ Texture::Texture(const ImagePtr& image, bool buildMipmaps) } while(glImage->nextMipmap()); m_hasMipmaps = true; } else - */ setupPixels(0, glImage->getSize(), glImage->getPixelData(), glImage->getBpp()); setupWrap(); diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index ca13f06f..c986c487 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -370,10 +370,10 @@ void X11Window::internalChooseGLVisual() #else EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, #endif - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, - EGL_ALPHA_SIZE, 0, + EGL_RED_SIZE, 4, + EGL_GREEN_SIZE, 4, + EGL_BLUE_SIZE, 4, + EGL_ALPHA_SIZE, 4, EGL_NONE }; diff --git a/src/otclient/core/animatedtext.cpp b/src/otclient/core/animatedtext.cpp index 81ba6ccf..910e3679 100644 --- a/src/otclient/core/animatedtext.cpp +++ b/src/otclient/core/animatedtext.cpp @@ -28,20 +28,22 @@ AnimatedText::AnimatedText() { - m_font = g_fonts.getFont("verdana-11px-rounded"); + m_cachedText.setFont(g_fonts.getFont("verdana-11px-rounded")); + m_cachedText.setAlign(Fw::AlignLeft); } void AnimatedText::draw(const Point& dest, const Rect& visibleRect) { Point p = dest; - p.x += 20 - m_textSize.width() / 2; + Size textSize = m_cachedText.getTextSize(); + p.x += 20 - textSize.width() / 2; p.y += (-20 * m_animationTimer.ticksElapsed()) / Otc::ANIMATED_TEXT_DURATION; - Rect rect(p, m_textSize); + Rect rect(p, textSize); if(visibleRect.contains(rect)) { //TODO: cache into a framebuffer g_painter->setColor(m_color); - m_font->drawText(m_text, rect, Fw::AlignLeft); + m_cachedText.draw(rect); } } @@ -61,6 +63,5 @@ void AnimatedText::setColor(int color) void AnimatedText::setText(const std::string& text) { - m_textSize = m_font->calculateTextRectSize(text); - m_text = text; + m_cachedText.setText(text); } diff --git a/src/otclient/core/animatedtext.h b/src/otclient/core/animatedtext.h index 66cf42a2..cba58891 100644 --- a/src/otclient/core/animatedtext.h +++ b/src/otclient/core/animatedtext.h @@ -26,6 +26,7 @@ #include "thing.h" #include #include +#include class AnimatedText : public Thing { @@ -42,11 +43,9 @@ public: bool isAnimatedText() { return true; } private: - FontPtr m_font; - Size m_textSize; - std::string m_text; Color m_color; Timer m_animationTimer; + CachedText m_cachedText; }; #endif diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index c45a853b..691d7ca2 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -52,7 +52,8 @@ Creature::Creature() : Thing() m_skull = Otc::SkullNone; m_shield = Otc::ShieldNone; m_emblem = Otc::EmblemNone; - m_informationFont = g_fonts.getFont("verdana-11px-rounded"); + m_nameCache.setFont(g_fonts.getFont("verdana-11px-rounded")); + m_nameCache.setAlign(Fw::AlignTopCenter); } /* @@ -85,21 +86,6 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate) void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction) { - /* - if(!outfitProgram) { - outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram); - outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); - outfitProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/outfit.frag"); - outfitProgram->link(); - outfitProgram->bindUniformLocation(HEAD_COLOR_UNIFORM, "headColor"); - outfitProgram->bindUniformLocation(BODY_COLOR_UNIFORM, "bodyColor"); - outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor"); - outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor"); - } - */ - - int xPattern = 0, yPattern = 0, zPattern = 0; - // outfit is a real creature if(m_outfit.getCategory() == ThingsType::Creature) { int animationPhase = animateWalk ? m_walkAnimationPhase : 0; @@ -110,6 +96,7 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani } // xPattern => creature direction + int xPattern; if(direction == Otc::NorthEast || direction == Otc::SouthEast) xPattern = Otc::East; else if(direction == Otc::NorthWest || direction == Otc::SouthWest) @@ -118,55 +105,29 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani xPattern = direction; // yPattern => creature addon - for(yPattern = 0; yPattern < getNumPatternsY(); yPattern++) { + for(int yPattern = 0; yPattern < getNumPatternsY(); yPattern++) { - // continue if we dont have this addon. + // continue if we dont have this addon if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1)))) continue; - /* - g_painter->setShaderProgram(outfitProgram); - - outfitProgram->bind(); - outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); - outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); - outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); - outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); - */ - - m_type->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase); - for(int h = 0; h < getDimensionHeight(); h++) { - for(int w = 0; w < getDimensionWidth(); w++) { - // setup texture outfit mask - /* - TexturePtr maskTex; - if(getLayers() > 1) - maskTex = m_type->getSprite(w, h, 1, xPattern, yPattern, zPattern, animationPhase); - - outfitProgram->setTexture(maskTex, 1); - */ - - Point p = dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor; - - if(getLayers() > 1) { - g_painter->saveState(); - g_painter->setCompositionMode(Painter::CompositionMode_Multiply); - - g_painter->setColor(m_outfit.getHeadColor()); - m_type->drawMask(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 1, animationPhase, ThingType::YellowMask); - g_painter->setColor(m_outfit.getBodyColor()); - m_type->drawMask(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 1, animationPhase, ThingType::RedMask); - g_painter->setColor(m_outfit.getLegsColor()); - m_type->drawMask(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 1, animationPhase, ThingType::GreenMask); - g_painter->setColor(m_outfit.getFeetColor()); - m_type->drawMask(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 1, animationPhase, ThingType::BlueMask); - - g_painter->restoreSavedState(); - } - } + m_type->draw(dest, scaleFactor, 0, xPattern, yPattern, 0, animationPhase); + + if(getLayers() > 1) { + Color oldColor = g_painter->getColor(); + Painter::CompositionMode oldComposition = g_painter->getCompositionMode(); + g_painter->setCompositionMode(Painter::CompositionMode_Multiply); + g_painter->setColor(m_outfit.getHeadColor()); + m_type->draw(dest, scaleFactor, ThingType::YellowMask, xPattern, yPattern, 0, animationPhase); + g_painter->setColor(m_outfit.getBodyColor()); + m_type->draw(dest, scaleFactor, ThingType::RedMask, xPattern, yPattern, 0, animationPhase); + g_painter->setColor(m_outfit.getLegsColor()); + m_type->draw(dest, scaleFactor, ThingType::GreenMask, xPattern, yPattern, 0, animationPhase); + g_painter->setColor(m_outfit.getFeetColor()); + m_type->draw(dest, scaleFactor, ThingType::BlueMask, xPattern, yPattern, 0, animationPhase); + g_painter->setColor(oldColor); + g_painter->setCompositionMode(oldComposition); } - - //g_painter->resetShaderProgram(); } // outfit is a creature imitating an item or the invisible effect } else { @@ -203,6 +164,7 @@ void Creature::drawOutfit(const Rect& destRect, bool resize) outfitBuffer = FrameBufferPtr(new FrameBuffer(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS))); outfitBuffer->bind(); + g_painter->setAlphaWriting(true); g_painter->clear(Color::alpha); internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South); outfitBuffer->release(); @@ -236,7 +198,8 @@ void Creature::drawInformation(const Point& point, bool useGray, const Rect& par Rect backgroundRect = Rect(point.x-(13.5), point.y, 27, 4); backgroundRect.bind(parentRect); - Rect textRect = Rect(point.x - m_nameSize.width() / 2.0, point.y-12, m_nameSize); + Size nameSize = m_nameCache.getTextSize(); + Rect textRect = Rect(point.x - nameSize.width() / 2.0, point.y-12, nameSize); textRect.bind(parentRect); // distance them @@ -256,8 +219,7 @@ void Creature::drawInformation(const Point& point, bool useGray, const Rect& par g_painter->setColor(fillColor); g_painter->drawFilledRect(healthRect); - if(m_informationFont) - m_informationFont->drawText(m_name, textRect, Fw::AlignTopCenter); + m_nameCache.draw(textRect); if(m_skull != Otc::SkullNone && m_skullTexture) { g_painter->setColor(Color::white); @@ -447,8 +409,7 @@ void Creature::terminateWalk() void Creature::setName(const std::string& name) { - if(m_informationFont) - m_nameSize = m_informationFont->calculateTextRectSize(name); + m_nameCache.setText(name); m_name = name; } diff --git a/src/otclient/core/creature.h b/src/otclient/core/creature.h index 8a3a0b35..d7269a5e 100644 --- a/src/otclient/core/creature.h +++ b/src/otclient/core/creature.h @@ -28,6 +28,7 @@ #include #include #include +#include class Creature : public Thing { @@ -104,7 +105,6 @@ protected: uint32 m_id; std::string m_name; - Size m_nameSize; uint8 m_healthPercent; Otc::Direction m_direction; Outfit m_outfit; @@ -124,8 +124,7 @@ protected: Boolean m_showTimedSquare; Boolean m_showStaticSquare; Boolean m_removed; - - FontPtr m_informationFont; + CachedText m_nameCache; Color m_informationColor; // walk related diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 5bf67f12..d8cda4bc 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -124,6 +124,12 @@ void Map::cleanDynamicThings() for(int i=0;i<=Otc::MAX_Z;++i) m_floorMissiles[i].clear(); + + cleanTexts(); +} + +void Map::cleanTexts() +{ m_animatedTexts.clear(); m_staticTexts.clear(); } diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index 0ab798f9..e0680b2d 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -38,6 +38,7 @@ public: void save(); void clean(); void cleanDynamicThings(); + void cleanTexts(); // thing related void addThing(const ThingPtr& thing, const Position& pos, int stackPos = -1); diff --git a/src/otclient/core/statictext.cpp b/src/otclient/core/statictext.cpp index 38fed19d..a97f19a2 100644 --- a/src/otclient/core/statictext.cpp +++ b/src/otclient/core/statictext.cpp @@ -28,20 +28,21 @@ StaticText::StaticText() { - m_font = g_fonts.getFont("verdana-11px-rounded"); + m_cachedText.setFont(g_fonts.getFont("verdana-11px-rounded")); + m_cachedText.setAlign(Fw::AlignCenter); } void StaticText::draw(const Point& dest, const Rect& parentRect) { - Rect rect = Rect(dest - Point(m_textSize.width() / 2, m_textSize.height()) + Point(20, 5), m_textSize); + Size textSize = m_cachedText.getTextSize(); + Rect rect = Rect(dest - Point(textSize.width() / 2, textSize.height()) + Point(20, 5), textSize); Rect boundRect = rect; boundRect.bind(parentRect); // draw only if the real center is not too far from the parent center, or its a yell if((boundRect.center() - rect.center()).length() < parentRect.width() / 15 || isYell()) { - //TODO: cache into a framebuffer g_painter->setColor(m_color); - m_font->drawText(m_text, boundRect, Fw::AlignCenter); + m_cachedText.draw(boundRect); } } @@ -116,6 +117,6 @@ void StaticText::compose() text += "\n"; } - m_text = m_font->wrapText(text, Otc::MAX_STATIC_TEXT_WIDTH); - m_textSize = m_font->calculateTextRectSize(m_text); + m_cachedText.setText(text); + m_cachedText.wrapText(Otc::MAX_STATIC_TEXT_WIDTH); } diff --git a/src/otclient/core/statictext.h b/src/otclient/core/statictext.h index bfccfda1..4cf51100 100644 --- a/src/otclient/core/statictext.h +++ b/src/otclient/core/statictext.h @@ -24,6 +24,7 @@ #define STATICTEXT_H #include "thing.h" +#include #include class StaticText : public Thing @@ -48,13 +49,12 @@ public: private: void compose(); - FontPtr m_font; - Size m_textSize; Boolean m_yell; std::vector m_messages; - std::string m_name, m_text; + std::string m_name; Otc::SpeakType m_messageType; Color m_color; + CachedText m_cachedText; }; #endif diff --git a/src/otclient/core/thingstype.cpp b/src/otclient/core/thingstype.cpp index 1cf8b3e8..86b71ff6 100644 --- a/src/otclient/core/thingstype.cpp +++ b/src/otclient/core/thingstype.cpp @@ -146,6 +146,7 @@ bool ThingsType::parseThingType(const FileStreamPtr& fin, ThingType& thingType) thingType.m_textures.resize(thingType.m_dimensions[ThingType::AnimationPhases]); thingType.m_texturesFramesRects.resize(thingType.m_dimensions[ThingType::AnimationPhases]); + thingType.m_texturesFramesOriginRects.resize(thingType.m_dimensions[ThingType::AnimationPhases]); thingType.m_texturesFramesOffsets.resize(thingType.m_dimensions[ThingType::AnimationPhases]); return true; diff --git a/src/otclient/core/thingtype.cpp b/src/otclient/core/thingtype.cpp index 83046ade..397652c8 100644 --- a/src/otclient/core/thingtype.cpp +++ b/src/otclient/core/thingtype.cpp @@ -41,8 +41,15 @@ void ThingType::draw(const Point& dest, float scaleFactor, int layer, int xPatte const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects. int frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern); - Point textureOffset = m_texturesFramesOffsets[animationPhase][frameIndex]; - Rect textureRect = m_texturesFramesRects[animationPhase][frameIndex]; + Point textureOffset; + Rect textureRect; + + if(scaleFactor != 1.0f) { + textureRect = m_texturesFramesOriginRects[animationPhase][frameIndex]; + } else { + textureOffset = m_texturesFramesOffsets[animationPhase][frameIndex]; + textureRect = m_texturesFramesRects[animationPhase][frameIndex]; + } Point displacement(m_parameters[DisplacementX], m_parameters[DisplacementY]); Rect screenRect(dest + (-displacement + textureOffset - Point(m_dimensions[Width] - 1, m_dimensions[Height] - 1) * Otc::TILE_PIXELS) * scaleFactor, @@ -51,68 +58,45 @@ void ThingType::draw(const Point& dest, float scaleFactor, int layer, int xPatte g_painter->drawTexturedRect(screenRect, texture, textureRect); } -void ThingType::drawMask(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase, ThingType::SpriteMask mask) -{ - int scaledSize = Otc::TILE_PIXELS * scaleFactor; - - Point displacement(m_parameters[DisplacementX], m_parameters[DisplacementY]); - - Rect drawRect(dest - displacement*scaleFactor, Size(scaledSize, scaledSize)); - g_painter->drawTexturedRect(drawRect, getSpriteMask(w, h, layer, xPattern, yPattern, zPattern, animationPhase, mask)); -} - -TexturePtr& ThingType::getSpriteMask(int w, int h, int l, int x, int y, int z, int a, ThingType::SpriteMask mask) -{ - if(m_spritesMask.size() == 0) - m_spritesMask.resize(m_spritesIndex.size()); - - uint index = getSpriteIndex(w,h,l,x,y,z,a); - TexturePtr& maskTexture = m_spritesMask[index][mask]; - if(!maskTexture) { - ImagePtr maskImage = g_sprites.getSpriteImage(m_spritesIndex[index]); - if(!maskImage) - maskTexture = g_graphics.getEmptyTexture(); - else { - static Color maskColors[LastMask] = { Color::yellow, Color::red, Color::green, Color::blue }; - maskImage->overwriteMask(maskColors[mask]); - - maskTexture = TexturePtr(new Texture(maskImage, true)); - } - } - - return maskTexture; -} - TexturePtr& ThingType::getTexture(int animationPhase) { TexturePtr& animationPhaseTexture = m_textures[animationPhase]; if(!animationPhaseTexture) { - - int textureLayers = m_dimensions[Layers]; - if(m_category != ThingsType::Creature) // we dont need layers in texture. they can be 'rendered' now. - textureLayers = 1; + // we don't need layers in common items, they will be pre-drawn + int textureLayers = 1; + int numLayers = m_dimensions[Layers]; + if(m_category == ThingsType::Creature && m_dimensions[Layers] >= 2) { + // 5 layers: outfit base, red mask, green mask, blue mask, yellow mask + textureLayers = 5; + numLayers = 5; + } int indexSize = textureLayers * m_dimensions[PatternX] * m_dimensions[PatternY] * m_dimensions[PatternZ]; Size textureSize = getBestDimension(m_dimensions[Width], m_dimensions[Height], indexSize); ImagePtr fullImage = ImagePtr(new Image(textureSize * Otc::TILE_PIXELS)); m_texturesFramesRects[animationPhase].resize(indexSize); + m_texturesFramesOriginRects[animationPhase].resize(indexSize); m_texturesFramesOffsets[animationPhase].resize(indexSize); for(int z = 0; z < m_dimensions[PatternZ]; ++z) { for(int y = 0; y < m_dimensions[PatternY]; ++y) { for(int x = 0; x < m_dimensions[PatternX]; ++x) { - for(int l = 0; l < m_dimensions[Layers]; ++l) { - + for(int l = 0; l < numLayers; ++l) { + bool spriteMask = (m_category == ThingsType::Creature && l > 0); int frameIndex = getTextureIndex(l % textureLayers, x, y, z); Point framePos = Point(frameIndex % (textureSize.width() / m_dimensions[Width]) * m_dimensions[Width], frameIndex / (textureSize.width() / m_dimensions[Width]) * m_dimensions[Height]) * Otc::TILE_PIXELS; for(int h = 0; h < m_dimensions[Height]; ++h) { for(int w = 0; w < m_dimensions[Width]; ++w) { - uint spriteIndex = getSpriteIndex(w, h, l, x, y, z, animationPhase); + uint spriteIndex = getSpriteIndex(w, h, spriteMask ? 1 : l, x, y, z, animationPhase); ImagePtr spriteImage = g_sprites.getSpriteImage(m_spritesIndex[spriteIndex]); if(spriteImage) { + if(spriteMask) { + static Color maskColors[] = { Color::red, Color::green, Color::blue, Color::yellow }; + spriteImage->overwriteMask(maskColors[l - 1]); + } Point spritePos = Point(m_dimensions[Width] - w - 1, m_dimensions[Height] - h - 1) * Otc::TILE_PIXELS; @@ -121,33 +105,35 @@ TexturePtr& ThingType::getTexture(int animationPhase) } } - Rect drawRect(framePos + Point(m_dimensions[Width], m_dimensions[Height]) * Otc::TILE_PIXELS, framePos); + Rect drawRect(framePos + Point(m_dimensions[Width], m_dimensions[Height]) * Otc::TILE_PIXELS - Point(1,1), framePos); for(int x = framePos.x; x < framePos.x + m_dimensions[Width] * Otc::TILE_PIXELS; ++x) { for(int y = framePos.y; y < framePos.y + m_dimensions[Height] * Otc::TILE_PIXELS; ++y) { uint8 *p = fullImage->getPixel(x,y); if(p[3] != 0x00) { - drawRect.setTop(std::min(y, (int)drawRect.top())); - drawRect.setLeft(std::min(x, (int)drawRect.left())); + drawRect.setTop (std::min(y, (int)drawRect.top())); + drawRect.setLeft (std::min(x, (int)drawRect.left())); drawRect.setBottom(std::max(y, (int)drawRect.bottom())); - drawRect.setRight(std::max(x, (int)drawRect.right())); + drawRect.setRight (std::max(x, (int)drawRect.right())); } } } m_texturesFramesRects[animationPhase][frameIndex] = drawRect; - m_texturesFramesOffsets[animationPhase][frameIndex] = drawRect.topLeft() - framePos + Point(1,1); + m_texturesFramesOriginRects[animationPhase][frameIndex] = Rect(framePos, Size(m_dimensions[Width], m_dimensions[Height]) * Otc::TILE_PIXELS); + m_texturesFramesOffsets[animationPhase][frameIndex] = drawRect.topLeft() - framePos; } } } } animationPhaseTexture = TexturePtr(new Texture(fullImage, true)); + animationPhaseTexture->setSmooth(true); } return animationPhaseTexture; } Size ThingType::getBestDimension(int w, int h, int count) { - const int MAX = 16; + const int MAX = 32; int k = 1; while(k < w) diff --git a/src/otclient/core/thingtype.h b/src/otclient/core/thingtype.h index df3aa9ae..e396271a 100644 --- a/src/otclient/core/thingtype.h +++ b/src/otclient/core/thingtype.h @@ -99,10 +99,10 @@ struct ThingType }; enum SpriteMask { - YellowMask = 0, - RedMask, + RedMask = 1, GreenMask, BlueMask, + YellowMask, LastMask }; @@ -146,10 +146,10 @@ private: std::array m_parameters; std::array m_properties; std::vector m_spritesIndex; - std::vector> m_spritesMask; std::vector m_textures; std::vector > m_texturesFramesRects; + std::vector > m_texturesFramesOriginRects; std::vector > m_texturesFramesOffsets; friend class ThingsType; diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 5ba735ac..8eb09635 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -68,6 +68,7 @@ void OTClient::registerLuaFunctions() g_lua.bindClassStaticFunction("g_map", "removeThingByPos", std::bind(&Map::removeThingByPos, &g_map, std::placeholders::_1, std::placeholders::_2)); g_lua.bindClassStaticFunction("g_map", "removeThing", std::bind(&Map::removeThing, &g_map, std::placeholders::_1)); g_lua.bindClassStaticFunction("g_map", "cleanTile", std::bind(&Map::cleanTile, &g_map, std::placeholders::_1)); + g_lua.bindClassStaticFunction("g_map", "cleanTexts", std::bind(&Map::cleanTexts, &g_map)); g_lua.bindClassStaticFunction("g_map", "getTile", std::bind(&Map::getTile, &g_map, std::placeholders::_1)); g_lua.bindClassStaticFunction("g_map", "setCentralPosition", std::bind(&Map::setCentralPosition, &g_map, std::placeholders::_1)); g_lua.bindClassStaticFunction("g_map", "getCentralPosition", std::bind(&Map::getCentralPosition, &g_map));