diff --git a/src/color.h b/src/color.h new file mode 100644 index 00000000..4d9a7bea --- /dev/null +++ b/src/color.h @@ -0,0 +1,62 @@ +/* The MIT License + * + * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#ifndef COLOR_H +#define COLOR_H + +#include "prerequisites.h" + +typedef uint32 RGBA; + +class Color +{ +public: + Color() : color(0) { } + Color(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) : color(((r & 0xff)<<24) | ((g & 0xff)<<16) | ((b & 0xff)<<8) | (a & 0xff)) { } + Color(const Color& other) : color(other.color) { } + Color(RGBA rgba) : color(rgba) { } + + uint8 red() const { return (color >> 24) & 0xFF; } + uint8 green() const { return (color >> 16) & 0xFF; } + uint8 blue() const { return (color >> 8) & 0xFF; } + uint8 alpha() const { return color & 0xFF; } + RGBA rgba() const { return color; } + const uint8* rgbaPtr() const { return (const uint8*)&color; } + + void setRed(uint8 r) { color = ((r & 0xff)<<24) | (color & 0x00ffffff); } + void setGreen(uint8 g) { color = ((g & 0xff)<<16) | (color & 0xff00ffff); } + void setBlue(uint8 b) { color = ((b & 0xff)<<8) | (color & 0xffff00ff); } + void setAlpha(uint8 a) { color = (a & 0xff) | (color & 0xffffff00); } + void setRGBA(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) { color = ((r & 0xff)<<24) | ((g & 0xff)<<16) | ((b & 0xff)<<8) | (a & 0xff); } + void setRGBA(uint32 rgba) { color = rgba; } + + Color& operator=(const Color& other) { color = other.color; return *this; } + bool operator==(const Color& other) const { return other.color == color; } + bool operator!=(const Color& other) const { return other.color != color; } + +private: + RGBA color; +}; + +#endif // COLOR_H diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 061b205a..f0f77e02 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -23,12 +23,9 @@ #include "configmanager.h" -#include "logger.h" -#include "util.h" +#include "resourcemanager.h" -#include #include -#include "resourcemanager.h" ConfigManager g_config; @@ -77,9 +74,11 @@ bool ConfigManager::load(const std::string& fileName) void ConfigManager::save() { - YAML::Emitter out; - out << m_confsMap; - g_resources.saveFile(m_fileName, (const unsigned char*)out.c_str(), out.size()); + if(!m_fileName.empty()) { + YAML::Emitter out; + out << m_confsMap; + g_resources.saveFile(m_fileName, (const unsigned char*)out.c_str(), out.size()); + } } void ConfigManager::setValue(const std::string &key, const std::string &value) diff --git a/src/configmanager.h b/src/configmanager.h index d9dccd5c..d948cb8f 100644 --- a/src/configmanager.h +++ b/src/configmanager.h @@ -25,8 +25,7 @@ #ifndef CONFIGMANAGER_H #define CONFIGMANAGER_H -#include -#include +#include "prerequisites.h" class ConfigManager { diff --git a/src/engine.cpp b/src/engine.cpp index cb91aaac..90468bfd 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -25,10 +25,8 @@ #include "engine.h" #include "platform.h" #include "graphics.h" -#include "const.h" #include "input.h" #include "configmanager.h" -#include "logger.h" #include "gamestate.h" Engine g_engine; @@ -36,7 +34,6 @@ Engine g_engine; Engine::Engine() : m_stopping(false), m_running(false), - m_lastFrameTicks(0), m_currentState(NULL) { } @@ -82,18 +79,19 @@ void Engine::terminate() void Engine::run() { unsigned long ticks; + static unsigned long lastFrameTicks; m_running = true; - m_lastFrameTicks = Platform::getTicks(); + lastFrameTicks = Platform::getTicks(); while(!m_stopping) { // fire platform events Platform::poll(); // update ticks = Platform::getTicks(); - update(ticks - m_lastFrameTicks); - m_lastFrameTicks = ticks; + update(ticks - lastFrameTicks); + lastFrameTicks = ticks; // render render(); @@ -102,7 +100,7 @@ void Engine::run() Platform::swapBuffers(); } - m_lastFrameTicks = 0; + lastFrameTicks = 0; m_stopping = false; m_running = false; } @@ -117,7 +115,8 @@ void Engine::changeState(GameState* newState) if(m_currentState) m_currentState->onLeave(); m_currentState = newState; - m_currentState->onEnter(); + if(m_currentState) + m_currentState->onEnter(); } void Engine::render() diff --git a/src/engine.h b/src/engine.h index 44522059..6fe37f43 100644 --- a/src/engine.h +++ b/src/engine.h @@ -25,6 +25,8 @@ #ifndef ENGINE_H #define ENGINE_H +#include "prerequisites.h" + struct InputEvent; class GameState; @@ -66,8 +68,6 @@ private: bool m_stopping; bool m_running; - unsigned long m_lastFrameTicks; - GameState *m_currentState; }; diff --git a/src/framebuffer.cpp b/src/framebuffer.cpp index 5e3f1e53..74490f1c 100644 --- a/src/framebuffer.cpp +++ b/src/framebuffer.cpp @@ -21,15 +21,9 @@ * THE SOFTWARE. */ -#define GL_GLEXT_PROTOTYPES - #include "framebuffer.h" #include "platform.h" #include "graphics.h" -#include "logger.h" - -#include -#include FrameBuffer::FrameBuffer(int width, int height) { diff --git a/src/framebuffer.h b/src/framebuffer.h index ed4fe509..d63347db 100644 --- a/src/framebuffer.h +++ b/src/framebuffer.h @@ -25,7 +25,7 @@ #ifndef FRAMEBUFFER_H #define FRAMEBUFFER_H -#include +#include "prerequisites.h" class FrameBuffer { diff --git a/src/graphics.cpp b/src/graphics.cpp index 34a47a58..47dc63e1 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -24,9 +24,6 @@ #include "graphics.h" #include "logger.h" - -#include -#include #include "texture.h" Graphics g_graphics; @@ -60,15 +57,18 @@ void Graphics::terminate() void Graphics::resize(int width, int height) { - m_width = width; - m_height = height; + m_screenSize.setWidth(width); + m_screenSize.setHeight(height); restoreViewport(); } void Graphics::restoreViewport() { + const int& width = m_screenSize.width(); + const int& height = m_screenSize.height(); + // resize gl viewport - glViewport(0, 0, m_width, m_height); + glViewport(0, 0, width, height); /* 0,0---------0,w @@ -80,7 +80,7 @@ void Graphics::restoreViewport() // setup view region like above glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluOrtho2D(0.0f, m_width, m_height, 0.0f); + gluOrtho2D(0.0f, width, height, 0.0f); // back to model view glMatrixMode(GL_MODELVIEW); @@ -98,3 +98,107 @@ void Graphics::endRender() { } + +void Graphics::drawTexturedRect(const Rect& screenCoords, const Texture *texture, const Rect& texCoords) +{ + // rect correction for opengl + int right = screenCoords.right()+1; + int bottom = screenCoords.bottom()+1; + int top = screenCoords.top(); + int left = screenCoords.left(); + + float tright; + float tbottom; + float ttop; + float tleft; + + if(!texCoords.isEmpty()) { + const Size& textureSize = texture->getSize(); + tright = (float)(texCoords.right()+1)/textureSize.width(); + tbottom = (float)(texCoords.bottom()+1)/textureSize.height(); + ttop = (float)texCoords.top()/textureSize.height(); + tleft = (float)texCoords.left()/textureSize.width(); + } else { + tright = 0.0f; + tbottom = 1.0f; + ttop = 0.0f; + tleft = 1.0f; + } + + glBindTexture(GL_TEXTURE_2D, texture->getTextureId()); + glBegin(GL_QUADS); + glTexCoord2f(tleft, ttop); glVertex2i(left, top); + glTexCoord2f(tleft, tbottom); glVertex2i(left, bottom); + glTexCoord2f(tright, tbottom); glVertex2i(right, bottom); + glTexCoord2f(tright, ttop); glVertex2i(right, top); + glEnd(); +} + +void Graphics::drawColoredRect(const Rect& screenCoords, const Color& color) +{ + glDisable(GL_TEXTURE_2D); + + glColor4ubv(color.rgbaPtr()); + + // rect correction for opengl + int right = screenCoords.right()+1; + int bottom = screenCoords.bottom()+1; + int top = screenCoords.top(); + int left = screenCoords.left(); + + glBegin(GL_QUADS); + glVertex2i(left, top); + glVertex2i(left, bottom); + glVertex2i(right, bottom); + glVertex2i(right, top); + glEnd(); + + glEnable(GL_TEXTURE_2D); +} + + +void Graphics::drawBoundingRect(const Rect& screenCoords, const Color& color, int lineWidth) +{ + if(2*lineWidth > screenCoords.height()) + return; + + glDisable(GL_TEXTURE_2D); + + glColor4ubv(color.rgbaPtr()); + + // rect correction for opengl + int right = screenCoords.right()+1; + int bottom = screenCoords.bottom()+1; + int top = screenCoords.top(); + int left = screenCoords.left(); + + glBegin(GL_QUADS); + + // top line + glVertex2i(left, top); + glVertex2i(left, top+lineWidth); + glVertex2i(right, top+lineWidth); + glVertex2i(right, top); + + // left + glVertex2i(left, screenCoords.top()+lineWidth); + glVertex2i(left, bottom-lineWidth); + glVertex2i(left+lineWidth, bottom-lineWidth); + glVertex2i(left+lineWidth, screenCoords.top()+lineWidth); + + // bottom line + glVertex2i(left, bottom); + glVertex2i(left, bottom-lineWidth); + glVertex2i(right, bottom-lineWidth); + glVertex2i(right, bottom); + + // right line + glVertex2i(right, top+lineWidth); + glVertex2i(right, bottom-lineWidth); + glVertex2i(right-lineWidth, bottom-lineWidth); + glVertex2i(right-lineWidth, top+lineWidth); + + glEnd(); + + glEnable(GL_TEXTURE_2D); +} diff --git a/src/graphics.h b/src/graphics.h index 1f885490..d3f1b4ff 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -25,6 +25,11 @@ #ifndef GRAPHICS_H #define GRAPHICS_H +#include "prerequisites.h" +#include "rect.h" +#include "size.h" +#include "color.h" + class Texture; class Graphics @@ -48,12 +53,13 @@ public: /// Called after every render void endRender(); - int getWidth() { return m_width; } - int getHeight() { return m_height; } + const Size& getScreenSize() const { return m_screenSize; } + void drawTexturedRect(const Rect& screenCoords, const Texture *texture, const Rect& texCoords = Rect()); + void drawColoredRect(const Rect& screenCoords, const Color& color); + void drawBoundingRect(const Rect& screenCoords, const Color& color, int lineWidth); private: - int m_width; - int m_height; + Size m_screenSize; }; extern Graphics g_graphics; diff --git a/src/logger.cpp b/src/logger.cpp index 02179f1d..1e622547 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -23,10 +23,6 @@ #include "logger.h" -#include "util.h" - -#include -#include #include void Logger::log(int level, const char *trace, const char *format, ...) diff --git a/src/logger.h b/src/logger.h index 59b1c45b..e5f2bd2c 100644 --- a/src/logger.h +++ b/src/logger.h @@ -25,9 +25,7 @@ #ifndef LOGGER_H #define LOGGER_H -#include -#include -#include +#include "prerequisites.h" namespace Logger { diff --git a/src/main.cpp b/src/main.cpp index b4b19708..60c347b1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,8 +23,6 @@ #include "engine.h" -#include "const.h" -#include "logger.h" #include "configmanager.h" #include "resourcemanager.h" #include "platform.h" diff --git a/src/menustate.cpp b/src/menustate.cpp index d7edbbb1..4de6c19c 100644 --- a/src/menustate.cpp +++ b/src/menustate.cpp @@ -28,8 +28,8 @@ #include "texturemanager.h" #include "logger.h" #include "engine.h" +#include "rect.h" -FrameBuffer *fbo; TexturePtr background; MenuState::MenuState() @@ -44,8 +44,8 @@ MenuState::~MenuState() void MenuState::onEnter() { - background = g_textures.get("background.png"); - background->enableBilinearFilter(); + m_background = g_textures.get("background.png"); + m_background->enableBilinearFilter(); } void MenuState::onLeave() @@ -64,43 +64,19 @@ void MenuState::onInputEvent(InputEvent* event) void MenuState::render() { - // draw background - background->bind(); - - int x = 0; - int y = 0; - int screenWidth = g_graphics.getWidth(); - int screenHeight = g_graphics.getHeight(); - int textureWidth = background->getWidth(); - int textureHeight = background->getHeight(); - - int texCoordX; - int texCoordY; - int texCoordWidth; - int texCoordHeight; - - int wantedWidth = 1240; - int wantedHeight = 880; - - float originalRatio = (float)wantedWidth/wantedHeight; - float screenRatio = (float)screenWidth/screenHeight; - if(screenRatio >= originalRatio) { - texCoordHeight = wantedHeight; - texCoordWidth = std::min((int)(wantedHeight*screenRatio), textureWidth); - } else { - texCoordWidth = wantedWidth; - texCoordHeight = std::min((int)(wantedWidth/screenRatio), textureHeight); - } - texCoordX = textureWidth - texCoordWidth; - texCoordY = textureHeight - texCoordHeight; - - - glBegin(GL_QUADS); - glTexCoord2f((float)texCoordX/textureWidth, (float)texCoordY/textureHeight); glVertex2i(x, y); - glTexCoord2f((float)texCoordX/textureWidth, (float)(texCoordY+texCoordHeight)/textureHeight); glVertex2i(x, y+screenHeight); - glTexCoord2f((float)(texCoordX+texCoordWidth)/textureWidth, (float)(texCoordY+texCoordHeight)/textureHeight); glVertex2i(x+screenWidth, y+screenHeight); - glTexCoord2f((float)(texCoordX+texCoordWidth)/textureWidth, (float)texCoordY/textureHeight); glVertex2i(x+screenWidth, y); - glEnd(); + static Size minTexCoordsSize(1240, 880); + const Size& screenSize = g_graphics.getScreenSize(); + Size texSize = m_background->getSize(); + + Size texCoordsSize = screenSize; + if(texCoordsSize < minTexCoordsSize) + texCoordsSize.scale(minTexCoordsSize, KEEP_ASPECT_RATIO_BY_EXPANDING); + texCoordsSize = texCoordsSize.boundedTo(texSize); + + Rect texCoords(0, 0, texCoordsSize); + texCoords.moveBottomRight(texSize.toPoint()); + + g_graphics.drawTexturedRect(Rect(0, 0, screenSize), m_background.get(), texCoords); } void MenuState::update(int elapsedTicks) diff --git a/src/menustate.h b/src/menustate.h index 47575ecb..5722f171 100644 --- a/src/menustate.h +++ b/src/menustate.h @@ -25,7 +25,9 @@ #ifndef MENUSTATE_H #define MENUSTATE_H +#include "prerequisites.h" #include "gamestate.h" +#include "texture.h" class MenuState : public GameState { @@ -42,6 +44,9 @@ public: void render(); void update(int elapsedTicks); + +private: + TexturePtr m_background; }; #endif // MENUSTATE_H diff --git a/src/platform.h b/src/platform.h index 991421b9..74c20c4d 100644 --- a/src/platform.h +++ b/src/platform.h @@ -25,7 +25,8 @@ #ifndef PLATFORM_H #define PLATFORM_H -// namespace with platform specific stuff +#include "prerequisites.h" + namespace Platform { void init(); diff --git a/src/point.h b/src/point.h new file mode 100644 index 00000000..ae85e719 --- /dev/null +++ b/src/point.h @@ -0,0 +1,79 @@ +/* The MIT License + * + * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#ifndef POINT_H +#define POINT_H + +#include "prerequisites.h" + +template +class TSize; + +template +class TPoint +{ +public: + inline TPoint() : x(0), y(0) {}; + inline TPoint(T x, T y) : x(x), y(y) { }; + inline TPoint(const TPoint& other) : x(other.x), y(other.y) { }; + + inline bool isNull() const { return x==0 && y==0; } + inline TSize toSize() const { return TSize(x, y); } + + inline TPoint operator-() const { return TPoint(-x, -y); } + inline TPoint operator+(const TPoint& other) const { return TPoint(x + other.x, y + other.y); } + inline TPoint& operator+=(const TPoint& other) { x+=other.x; y+=other.y; return *this; } + inline TPoint operator-(const TPoint& other) const { return TPoint(x - other.x, y - other.y); } + inline TPoint& operator-=(const TPoint& other) { x-=other.x; y-=other.y; return *this; } + inline TPoint operator*(const TPoint& other) const { return TPoint(x * other.x, y * other.y); } + inline TPoint& operator*=(const TPoint& other) { x*=other.x; y*=other.y; return *this; } + inline TPoint operator*(const T v) const { return TPoint(x * v, y * v); } + inline TPoint& operator*=(const T v) { x*=v; y*=v; return *this; } + inline TPoint operator/(const TPoint& other) const { return TPoint(x/other.x, y/other.y); } + inline TPoint& operator/=(const TPoint& other) { x/=other.x; y/=other.y; return *this; } + inline TPoint operator/(const T v) const { return TPoint(x/v, y/v); } + inline TPoint& operator/=(const T v) { x/=v; y/=v; return *this; } + + inline bool operator<=(const TPoint&other) const { return x<=other.x && y<=other.y; } + inline bool operator>=(const TPoint&other) const { return x>=other.x && y>=other.y; } + inline bool operator<(const TPoint&other) const { return x(const TPoint&other) const { return x>other.x && y>other.y; } + + inline TPoint& operator=(const TPoint& other) { x = other.x; y = other.y; return *this; } + inline bool operator==(const TPoint& other) const { return other.x==x && other.y==y; } + inline bool operator!=(const TPoint& other) const { return other.x!=x || other.y!=y; } + + inline float length() const { return sqrtf((float)(x*x + y*y)); } + + inline float distanceFrom(const TPoint& other) const { + return TPoint(x - other.x, y - other.y).getLength(); + } + + T x, y; +}; + +typedef TPoint Point; +typedef TPoint PointF; + +#endif diff --git a/src/const.h b/src/prerequisites.h similarity index 59% rename from src/const.h rename to src/prerequisites.h index 7a30e759..bff39a95 100644 --- a/src/const.h +++ b/src/prerequisites.h @@ -22,13 +22,60 @@ */ -#ifndef VERSION_H -#define VERSION_H +#ifndef PREREQUISITES_H +#define PREREQUISITES_H -#define APP_VERSION "0.1.0" +// app name #define APP_NAME "OTClient" #define APP_LONGNAME APP_NAME " " APP_VERSION -#define APP_ICON "data/otclient.bmp" -#endif +// app version +#define APP_VERSION "0.1.0" + +// int types +#include + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; +typedef int32_t int32; +typedef int16_t int16; +typedef int8_t int8; + +// c headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// stl headers +#include +#include +#include +#include +#include + +// GL stuff +#define GL_GLEXT_PROTOTYPES + +#include +#include +#include + +// utilities +#include "logger.h" +#include "util.h" +#endif // PREREQUISITES_H \ No newline at end of file diff --git a/src/rect.h b/src/rect.h new file mode 100644 index 00000000..025e8dcb --- /dev/null +++ b/src/rect.h @@ -0,0 +1,284 @@ +/* The MIT License + * + * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#ifndef RECT_H +#define RECT_H + +#include "prerequisites.h" +#include "point.h" +#include "size.h" + +template +class TPoint; + +template +class TSize; + +template +class TRect +{ +public: + inline TRect() : x1(0), y1(0), x2(-1), y2(-1) { } + inline TRect(T x, T y, T width, T height) : x1(x), y1(y), x2(x+width-1), y2(y+height-1) { } + inline TRect(const TPoint& topLeft, const TPoint& bottomRight) : x1(topLeft.x), y1(topLeft.y), x2(bottomRight.x), y2(bottomRight.y) { } + inline TRect(const TRect& other) : x1(other.x1), y1(other.y1), x2(other.x2), y2(other.y2) { } + inline TRect(T x, T y, const TSize& size) : x1(x), y1(y), x2(x+size.width()-1), y2(y+size.height()-1) { } + inline TRect(const TPoint& topLeft, const TSize& size) : x1(topLeft.x), y1(topLeft.y), x2(x+size.width()-1), y2(y+size.height()-1) { } + + inline bool isNull() const { return x2 == x1 - 1 && y2 == y1 - 1; } + inline bool isEmpty() const { return x1 > x2 || y1 > y2; } + inline bool isValid() const { return x1 <= x2 && y1 <= y2; } + + inline T left() const { return x1; } + inline T top() const { return y1; } + inline T right() const { return x2; } + inline T bottom() const { return y2; } + inline T x() const { return x1; } + inline T y() const { return y1; } + inline TPoint topLeft() const { return TPoint(x1, y1); } + inline TPoint bottomRight() const { return TPoint(x2, y2); } + inline TPoint topRight() const { return TPoint(x2, y1); } + inline TPoint bottomLeft() const { return TPoint(x1, y2); } + inline TPoint center() const { return TPoint((x1+x2)/2, (y1+y2)/2); } + inline T width() const { return x2 - x1 + 1; } + inline T height() const { return y2 - y1 + 1; } + inline TSize size() const { return TSize(width(), height()); } + + inline void setLeft(T pos) { x1 = pos; } + inline void setTop(T pos) { y1 = pos; } + inline void setRight(T pos) { x2 = pos; } + inline void setBottom(T pos) { y2 = pos; } + inline void setX(T x) { x1 = x; } + inline void setY(T y) { y1 = y; } + inline void setTopLeft(const TPoint &p) { x1 = p.x; y1 = p.y; } + inline void setBottomRight(const TPoint &p) { x2 = p.x; y2 = p.y; } + inline void setTopRight(const TPoint &p) { x2 = p.x; y1 = p.y; } + inline void setBottomLeft(const TPoint &p) { x1 = p.x; y2 = p.y; } + inline void setWidth(T width) { x2 = x1 + width - 1; } + inline void setHeight(T height) { y2 = y1 + height- 1; } + inline void setSize(T width, T height) { x2 = x1 + width; y2 = y1 + height; } + inline void setSize(const TSize& size) { x2 = x1 + size.width(); y2 = y1 + size.height(); } + inline void setRect(T x, T y, T width, T height) { x1 = x; y1 = y; x2 = (x + width - 1); y2 = (y + height - 1); } + inline void setCoords(int left, int top, int right, int bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; } + + inline void translate(T x, T y) { x1 += x; y1 += y; x2 += x; y2 += y; } + inline void translate(const TPoint &p) { x1 += p.x; y1 += p.y; x2 += p.x; y2 += p.y; } + inline void moveTo(T x, T y) { x2 += x - x1; y2 += y - y1; x1 = x; y1 = y; } + inline void moveTo(const TPoint &p) { x2 += p.x - x1; y2 += p.y - y1; x1 = p.x; y1 = p.y; } + inline void moveLeft(T pos) { x2 += (pos - x1); x1 = pos; } + inline void moveTop(T pos) { y2 += (pos - y1); y1 = pos; } + inline void moveRight(T pos) { x1 += (pos - x2); x2 = pos; } + inline void moveBottom(T pos) { y1 += (pos - y2); y2 = pos; } + inline void moveTopLeft(const TPoint &p) { moveLeft(p.x); moveTop(p.y); } + inline void moveBottomRight(const TPoint &p) { moveRight(p.x); moveBottom(p.y); } + inline void moveTopRight(const TPoint &p) { moveRight(p.x); moveTop(p.y); } + inline void moveBottomLeft(const TPoint &p) { moveLeft(p.x); moveBottom(p.y); } + + inline TRect translated(int x, int y) const { return TRect(TPoint(x1 + x, y1 + y), TPoint(x2 + x, y2 + y)); } + inline TRect translated(const TPoint &p) const { return TRect(TPoint(x1 + p.x(), y1 + p.y()), TPoint(x2 + p.x(), y2 + p.y())); } + + void moveCenter(const TPoint &p) { + T w = x2 - x1; + T h = y2 - y1; + x1 = p.x() - w/2; + y1 = p.y() - h/2; + x2 = x1 + w; + y2 = y1 + h; + } + + bool contains(const TPoint &p, bool insideOnly = false) const { + T l, r; + if(x2 < x1 - 1) { + l = x2; + r = x1; + } else { + l = x1; + r = x2; + } + if(insideOnly) { + if(p.x() <= l || p.x() >= r) + return false; + } else { + if(p.x() < l || p.x() > r) + return false; + } + int t, b; + if(y2 < y1 - 1) { + t = y2; + b = y1; + } else { + t = y1; + b = y2; + } + if(insideOnly) { + if(p.y() <= t || p.y() >= b) + return false; + } else { + if(p.y() < t || p.y() > b) + return false; + } + return true; + } + + bool intersects(const TRect &r) const { + if(isNull() || r.isNull()) + return false; + + int l1 = x1; + int r1 = x1; + if(x2 - x1 + 1 < 0) + l1 = x2; + else + r1 = x2; + + int l2 = r.x1; + int r2 = r.x1; + if(r.x2 - r.x1 + 1 < 0) + l2 = r.x2; + else + r2 = r.x2; + + if (l1 > r2 || l2 > r1) + return false; + + int t1 = y1; + int b1 = y1; + if(y2 - y1 + 1 < 0) + t1 = y2; + else + b1 = y2; + + int t2 = r.y1; + int b2 = r.y1; + if (r.y2 - r.y1 + 1 < 0) + t2 = r.y2; + else + b2 = r.y2; + + if(t1 > b2 || t2 > b1) + return false; + + return true; + } + + TRect united(const TRect &r) const { + if(isNull() || r.isNull()) + return TRect(); + + int l1 = x1; + int r1 = x1; + if (x2 - x1 + 1 < 0) + l1 = x2; + else + r1 = x2; + + int l2 = r.x1; + int r2 = r.x1; + if(r.x2 - r.x1 + 1 < 0) + l2 = r.x2; + else + r2 = r.x2; + + if(l1 > r2 || l2 > r1) + return TRect(); + + int t1 = y1; + int b1 = y1; + if(y2 - y1 + 1 < 0) + t1 = y2; + else + b1 = y2; + + int t2 = r.y1; + int b2 = r.y1; + if(r.y2 - r.y1 + 1 < 0) + t2 = r.y2; + else + b2 = r.y2; + + if(t1 > b2 || t2 > b1) + return TRect(); + + TRect tmp; + tmp.x1 = std::max(l1, l2); + tmp.x2 = std::min(r1, r2); + tmp.y1 = std::max(t1, t2); + tmp.y2 = std::min(b1, b2); + return tmp; + } + + TRect intersection(const TRect &r) const { + if(isNull()) + return r; + if(r.isNull()) + return *this; + + int l1 = x1; + int r1 = x1; + if(x2 - x1 + 1 < 0) + l1 = x2; + else + r1 = x2; + + int l2 = r.x1; + int r2 = r.x1; + if(r.x2 - r.x1 + 1 < 0) + l2 = r.x2; + else + r2 = r.x2; + + int t1 = y1; + int b1 = y1; + if(y2 - y1 + 1 < 0) + t1 = y2; + else + b1 = y2; + + int t2 = r.y1; + int b2 = r.y1; + if(r.y2 - r.y1 + 1 < 0) + t2 = r.y2; + else + b2 = r.y2; + + TRect tmp; + tmp.x1 = std::min(l1, l2); + tmp.x2 = std::max(r1, r2); + tmp.y1 = std::min(t1, t2); + tmp.y2 = std::max(b1, b2); + return tmp; + } + + inline TRect& operator=(const TRect& other) { x1 = other.x1; y1 = other.y1; x2 = other.x2; y2 = other.y2; return *this; } + inline bool operator==(const TRect& other) const { return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2); } + inline bool operator!=(const TRect& other) const { return (x1 != other.x1 || y1 != other.y1 || x2 != other.x2 || y2 != other.y2); } + +private: + T x1, y1, x2, y2; +}; + +typedef TRect Rect; +typedef TRect RectF; + +#endif // RECT_H diff --git a/src/resourcemanager.cpp b/src/resourcemanager.cpp index 6de06568..356fc93f 100644 --- a/src/resourcemanager.cpp +++ b/src/resourcemanager.cpp @@ -23,7 +23,6 @@ #include "resourcemanager.h" -#include "logger.h" #include diff --git a/src/resourcemanager.h b/src/resourcemanager.h index 34f90c74..9333653c 100644 --- a/src/resourcemanager.h +++ b/src/resourcemanager.h @@ -25,7 +25,7 @@ #ifndef RESOURCEMANAGER_H #define RESOURCEMANAGER_H -#include +#include "prerequisites.h" class ResourceManager { diff --git a/src/size.h b/src/size.h new file mode 100644 index 00000000..d088f0b4 --- /dev/null +++ b/src/size.h @@ -0,0 +1,113 @@ +/* The MIT License + * + * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#ifndef SIZE_H +#define SIZE_H + +#include "prerequisites.h" +#include "point.h" + +enum ESizeScaleMode { + IGNORE_ASPECT_RATIO, + KEEP_ASPECT_RATIO, + KEEP_ASPECT_RATIO_BY_EXPANDING +}; + +template +class TSize +{ +public: + TSize() : wd(-1), ht(-1) {}; + TSize(T width, T height) : wd(width), ht(height) { }; + TSize(const TSize& other) : wd(other.wd), ht(other.ht) { }; + + inline TPoint toPoint() const { return TPoint(wd, ht); } + + inline bool isNull() const { return wd==0 && ht==0; } + inline bool isEmpty() const { return wd<1 || ht<1; } + inline bool isValid() const { return wd>=0 && ht>=0; } + + inline int width() const { return wd; } + inline int height() const { return ht; } + + inline void setWidth(T w) { wd = w; } + inline void setHeight(T h) { ht = h; } + + inline TSize operator-() const { return TSize(-wd, -ht); } + inline TSize operator+(const TSize& other) const { return TSize(wd + other.wd, ht + other.ht); } + inline TSize& operator+=(const TSize& other) { wd+=other.wd; ht+=other.ht; return *this; } + inline TSize operator-(const TSize& other) const { return TSize(wd - other.wd, ht - other.ht); } + inline TSize& operator-=(const TSize& other) { wd-=other.wd; ht-=other.ht; return *this; } + inline TSize operator*(const float v) const { return TSize((T)v*wd, (T)ht*v); } + inline TSize& operator*=(const float v) { wd=(T)v*wd; ht=(T)ht*v; return *this; } + inline TSize operator/(const float v) const { return TSize((T)wd/v, (T)ht/v); } + inline TSize& operator/=(const float v) { (T)wd/=v; (T)ht/=v; return *this; } + + inline bool operator<=(const TSize&other) const { return wd<=other.wd || ht<=other.ht; } + inline bool operator>=(const TSize&other) const { return wd>=other.wd || ht>=other.ht; } + inline bool operator<(const TSize&other) const { return wd(const TSize&other) const { return wd>other.wd || ht>other.ht; } + + inline TSize& operator=(const TSize& other) { wd = other.wd; ht = other.ht; return *this; } + inline bool operator==(const TSize& other) const { return other.wd==wd && other.ht==ht; } + inline bool operator!=(const TSize& other) const { return other.wd!=wd || other.ht!=ht; } + + inline TSize expandedTo(const TSize& other) const { return TSize(std::max(wd,other.wd), std::max(ht,other.ht)); } + inline TSize boundedTo(const TSize& other) const { return TSize(std::min(wd,other.wd), std::min(ht,other.ht)); } + + void scale(const TSize& s, ESizeScaleMode mode) { + if(mode == IGNORE_ASPECT_RATIO || wd == 0 || ht == 0) { + wd = s.wd; + ht = s.ht; + } else { + bool useHeight; + T rw = (s.ht * wd) / ht; + + if(mode == KEEP_ASPECT_RATIO) + useHeight = (rw <= s.wd); + else // mode == KEEP_ASPECT_RATIO_BY_EXPANDING + useHeight = (rw >= s.wd); + + if(useHeight) { + wd = rw; + ht = s.ht; + } else { + ht = (s.wd * ht)/wd; + wd = s.wd; + } + } + } + void scale(int w, int h, ESizeScaleMode mode) { scale(TSize(w, h)); } + + inline float ratio() const { return (float)wd/ht; } + inline T area() const { return wd*ht; } + +private: + T wd, ht; +}; + +typedef TSize Size; +typedef TSize SizeF; + +#endif diff --git a/src/texture.cpp b/src/texture.cpp index a47f3aee..bea89d43 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -24,13 +24,10 @@ #include "texture.h" -#include -#include - Texture::Texture(int width, int height, int components, unsigned char *pixels) { - m_width = width; - m_height = height; + m_size.setWidth(width); + m_size.setHeight(height); glGenTextures(1, &m_textureId); glBindTexture(GL_TEXTURE_2D, m_textureId); @@ -66,30 +63,9 @@ Texture::~Texture() glDeleteTextures(1, &m_textureId); } -void Texture::bind() -{ - glBindTexture(GL_TEXTURE_2D, m_textureId); -} - void Texture::enableBilinearFilter() { glBindTexture(GL_TEXTURE_2D, m_textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } - -void Texture::draw(int x, int y) -{ - draw(x, y, m_width, m_height); -} - -void Texture::draw(int x, int y, int width, int height) -{ - glBindTexture(GL_TEXTURE_2D, m_textureId); - glBegin(GL_QUADS); - glTexCoord2i(0, 0); glVertex2i(x, y); - glTexCoord2i(0, 1); glVertex2i(x, y+height); - glTexCoord2i(1, 1); glVertex2i(x+width, y+height); - glTexCoord2i(1, 0); glVertex2i(x+width, y); - glEnd(); -} diff --git a/src/texture.h b/src/texture.h index 096a7658..3742ece7 100644 --- a/src/texture.h +++ b/src/texture.h @@ -25,7 +25,8 @@ #ifndef TEXTURE_H #define TEXTURE_H -#include +#include "prerequisites.h" +#include "size.h" #include class TextureManager; @@ -37,22 +38,15 @@ public: Texture(int width, int height, int components, unsigned char *pixels = NULL); virtual ~Texture(); - /// Bind texture for drawing - void bind(); - /// Enable texture bilinear filter (smooth scaled textures) void enableBilinearFilter(); - void draw(int x, int y); - void draw(int x, int y, int width, int height); - - int getWidth() const { return m_width; } - int getHeight() const { return m_height; } + const Size& getSize() const { return m_size; } + GLuint getTextureId() const { return m_textureId; } private: GLuint m_textureId; - int m_width; - int m_height; + Size m_size; }; typedef boost::shared_ptr TexturePtr; diff --git a/src/textureloader.cpp b/src/textureloader.cpp index 7dad2f72..ef99a1a0 100644 --- a/src/textureloader.cpp +++ b/src/textureloader.cpp @@ -23,38 +23,37 @@ #include "textureloader.h" +#include "texture.h" -#include #include -TexturePtr TextureLoader::loadPNG(const unsigned char *fileData, unsigned int fileSize) +Texture *TextureLoader::loadPNG(const unsigned char *fileData, unsigned int fileSize) { - TexturePtr texture; FILE *pngFile = fmemopen((void*)fileData, fileSize, "rb"); if(!pngFile) - return texture; + return NULL; png_byte sig[8]; if(!fread(&sig, 8, 1, pngFile)) - return texture; + return NULL; if(png_sig_cmp(sig, 0, 8)) - return texture; + return NULL; png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) - return texture; + return NULL; png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); - return texture; + return NULL; } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return texture; + return NULL; } png_init_io(png_ptr, pngFile); @@ -101,7 +100,7 @@ TexturePtr TextureLoader::loadPNG(const unsigned char *fileData, unsigned int fi default: if(png_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return texture; + return NULL; }; unsigned char *pixels = new unsigned char[width * height * components]; @@ -117,7 +116,7 @@ TexturePtr TextureLoader::loadPNG(const unsigned char *fileData, unsigned int fi fclose(pngFile); delete[] row_pointers; - texture = TexturePtr(new Texture(width, height, components, pixels)); + Texture *texture = new Texture(width, height, components, pixels); delete[] pixels; diff --git a/src/textureloader.h b/src/textureloader.h index 140f816e..fdcc78e0 100644 --- a/src/textureloader.h +++ b/src/textureloader.h @@ -25,12 +25,14 @@ #ifndef TEXTURELOADER_H #define TEXTURELOADER_H -#include "texture.h" +#include "prerequisites.h" + +class Texture; namespace TextureLoader { /// Load a png textures using libpng - TexturePtr loadPNG(const unsigned char *fileData, unsigned int fileSize); + Texture *loadPNG(const unsigned char *fileData, unsigned int fileSize); } #endif // TEXTURELOADER_H diff --git a/src/texturemanager.cpp b/src/texturemanager.cpp index 4320ef63..b8718c84 100644 --- a/src/texturemanager.cpp +++ b/src/texturemanager.cpp @@ -25,7 +25,6 @@ #include "texturemanager.h" #include "resourcemanager.h" #include "textureloader.h" -#include "logger.h" #include @@ -61,7 +60,7 @@ TexturePtr TextureManager::get(const std::string& textureFile) if(!textureFileData) return texture; - texture = TextureLoader::loadPNG(textureFileData, fileSize); + texture = TexturePtr(TextureLoader::loadPNG(textureFileData, fileSize)); if(!texture) error("Unable to load texture %s, loading error.", textureFile.c_str()); delete[] textureFileData; diff --git a/src/texturemanager.h b/src/texturemanager.h index a95264ce..457e3658 100644 --- a/src/texturemanager.h +++ b/src/texturemanager.h @@ -25,11 +25,9 @@ #ifndef TEXTUREMANAGER_H #define TEXTUREMANAGER_H +#include "prerequisites.h" #include "texture.h" -#include -#include - class TextureManager { public: diff --git a/src/util.cpp b/src/util.cpp index 6a597041..f0efadd2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -24,8 +24,6 @@ #include "util.h" -#include - std::string vformat(const char *format, va_list args) { if(!format) diff --git a/src/util.h b/src/util.h index 27256151..eea8ba33 100644 --- a/src/util.h +++ b/src/util.h @@ -25,9 +25,7 @@ #ifndef UTIL_H #define UTIL_H -#include -#include -#include +#include "prerequisites.h" /// Formatting like printf for std::string, va_list input version std::string vformat(const char *format, va_list args); diff --git a/src/x11platform.cpp b/src/x11platform.cpp index 2262f6a7..69fb0ce9 100644 --- a/src/x11platform.cpp +++ b/src/x11platform.cpp @@ -26,19 +26,11 @@ #include "engine.h" #include "input.h" #include "logger.h" -#include "const.h" -#include #include #include #include -#include -#include -#include -#include -#include - #include #include #include