diff --git a/CMakeLists.txt b/CMakeLists.txt index e78aeeed..b156d73c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,8 @@ ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug") # find sources SET(SOURCES + src/menustate.cpp + src/framebuffer.cpp src/textureloader.cpp src/texture.cpp src/texturemanager.cpp diff --git a/src/engine.cpp b/src/engine.cpp index acd8bbfa..cb7a838a 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -29,13 +29,15 @@ #include "input.h" #include "configmanager.h" #include "logger.h" +#include "gamestate.h" Engine g_engine; Engine::Engine() : m_stopping(false), m_running(false), - m_lastFrameTicks(0) + m_lastFrameTicks(0), + m_currentState(NULL) { } @@ -108,20 +110,32 @@ void Engine::stop() m_stopping = true; } +void Engine::changeState(GameState* newState) +{ + if(m_currentState) + m_currentState->onLeave(); + m_currentState = newState; + m_currentState->onEnter(); +} + void Engine::render() { g_graphics.beginRender(); + if(m_currentState) + m_currentState->render(); g_graphics.endRender(); } void Engine::update(int elapsedTicks) { - + if(m_currentState) + m_currentState->update(elapsedTicks); } void Engine::onClose() { - stop(); + if(m_currentState) + m_currentState->onClose(); } void Engine::onResize(int width, int height) @@ -131,5 +145,6 @@ void Engine::onResize(int width, int height) void Engine::onInputEvent(InputEvent *event) { - + if(m_currentState) + m_currentState->onInputEvent(event); } diff --git a/src/engine.h b/src/engine.h index 8374b33d..44522059 100644 --- a/src/engine.h +++ b/src/engine.h @@ -27,6 +27,8 @@ struct InputEvent; +class GameState; + class Engine { public: @@ -38,8 +40,13 @@ public: /// Main loop void run(); + + /// Stops main loop void stop(); + /// Change current game state + void changeState(GameState *newState); + bool isRunning() const { return m_running; } bool isStopping() const { return m_stopping; } @@ -60,6 +67,8 @@ private: bool m_running; unsigned long m_lastFrameTicks; + + GameState *m_currentState; }; extern Engine g_engine; diff --git a/src/framebuffer.cpp b/src/framebuffer.cpp new file mode 100644 index 00000000..9e4762f9 --- /dev/null +++ b/src/framebuffer.cpp @@ -0,0 +1,120 @@ +/* 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. + */ + +#define GL_GLEXT_PROTOTYPES + +#include "framebuffer.h" + +#include +#include +#include "platform.h" +#include "graphics.h" + +FrameBuffer::FrameBuffer(int width, int height) : + m_fbo(0) +{ + m_width = width; + m_height = height; + + // texture where the framebuffer will be store + m_frameTexture = TexturePtr(new Texture(width, height, 4)); + + // we want a smooth framebuffer + m_frameTexture->enableBilinearFilter(); + + // use FBO only if supported + if(Platform::isExtensionSupported("EXT_framebuffer_object")) { + m_fallbackOldImp = false; + + // generate FBO + glGenFramebuffersEXT(1, &m_fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + + // attach 2D texture to this FBO + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_frameTexture->getTextureId(), 0); + + // must be called before checking + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch(status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: + //ok + break; + default: + m_fallbackOldImp = true; + break; + } + } else { + // otherwise fallback to copy texture from screen implementation + m_fallbackOldImp = true; + } +} + +FrameBuffer::~FrameBuffer() +{ + if(m_fbo) + glDeleteFramebuffersEXT(1, &m_fbo); +} + +void FrameBuffer::bind() +{ + if(!m_fallbackOldImp) { + // bind framebuffer + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + + // must be called before rendering to framebuffer + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } + + // clear framebuffer + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + // setup framebuffer viewport + g_graphics.setViewport(m_width, m_height); +} + +void FrameBuffer::unbind() +{ + if(!m_fallbackOldImp) { + // bind back buffer again + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + // must be called to render to back buffer again + glDrawBuffer(GL_BACK); + glReadBuffer(GL_BACK); + } else { + // copy screen to texture + m_frameTexture->copyFromScreen(0, 0, 0, 0, m_width, m_height); + + // clear screen + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + } + + // restore graphics viewport + g_graphics.restoreViewport(); +} diff --git a/src/framebuffer.h b/src/framebuffer.h new file mode 100644 index 00000000..32ebfca3 --- /dev/null +++ b/src/framebuffer.h @@ -0,0 +1,52 @@ +/* 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 FRAMEBUFFER_H +#define FRAMEBUFFER_H + +#include "texture.h" + +class FrameBuffer +{ + FrameBuffer(int width, int height); + virtual ~FrameBuffer(); + + /// Return the texture where everything was drawn + TexturePtr getFramebufferTexture(); + + /// Bind the framebuffer, everything rendered will be draw on it + void bind(); + + /// Unbind the framebuffer, render on back buffer again + void unbind(); + +private: + TexturePtr m_frameTexture; + GLuint m_fbo; + bool m_fallbackOldImp; + int m_width; + int m_height; +}; + +#endif // FRAMEBUFFER_H diff --git a/src/gamestate.h b/src/gamestate.h new file mode 100644 index 00000000..c3c63c0b --- /dev/null +++ b/src/gamestate.h @@ -0,0 +1,46 @@ +/* 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 GAMESTATE_H +#define GAMESTATE_H + +struct InputEvent; + +class GameState +{ +public: + GameState() { } + virtual ~GameState() { } + + virtual void onEnter() = 0; + virtual void onLeave() = 0; + + virtual void onClose() = 0; + virtual void onInputEvent(InputEvent *event) = 0; + + virtual void render() = 0; + virtual void update(int elapsedTicks) = 0; +}; + +#endif // GAMESTATE_H diff --git a/src/graphics.cpp b/src/graphics.cpp index 571334ca..ee967661 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -24,11 +24,9 @@ #include "graphics.h" #include "logger.h" -#include "texturemanager.h" #include #include -#include "platform.h" Graphics g_graphics; @@ -60,17 +58,24 @@ void Graphics::terminate() } void Graphics::resize(int width, int height) +{ + m_width = width; + m_height = height; + restoreViewport(); +} + +void Graphics::setViewport(int width, int height) { // resize gl viewport glViewport(0, 0, width, height); /* - 0,0---------0,w - | | - | | - | | - h,0---------h,w - */ + 0 ,0---------0,w** + | | + | | + | | + h,0---------h,w + */ // setup view region like above glMatrixMode(GL_PROJECTION); glLoadIdentity(); diff --git a/src/graphics.h b/src/graphics.h index aad36e5a..57f772e2 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -34,14 +34,27 @@ public: void init(); void terminate(); - ///Called after every window resize + /// Called after every window resize void resize(int width, int height); - ///Called before every render + /// Called before every render void beginRender(); - ///Called after every render + /// Called after every render void endRender(); + + /// Restore original viewport + void restoreViewport() { setViewport(m_width, m_height); } + + /// Set viewport, used by FrameBuffer + void setViewport(int width, int height); + + int getWidth() { return m_width; } + int getHeight() { return m_height; } + +private: + int m_width; + int m_height; }; extern Graphics g_graphics; diff --git a/src/main.cpp b/src/main.cpp index e0be7bac..5ec5b984 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,9 +28,12 @@ #include "configmanager.h" #include "resourcemanager.h" #include "platform.h" +#include "menustate.h" #include +#include + /// Catches signals so we can exit nicely void signal_handler(int sig) { @@ -77,9 +80,17 @@ int main(int argc, const char *argv[]) notice(APP_LONGNAME); - // setup the engine and run + // setup the engine g_engine.init(); + + // create initial state + boost::scoped_ptr menuState(new MenuState); + g_engine.changeState(menuState.get()); + + // run g_engine.run(); + + // terminate stuff g_engine.terminate(); // save configurations before exiting diff --git a/src/menustate.cpp b/src/menustate.cpp new file mode 100644 index 00000000..8b8d258c --- /dev/null +++ b/src/menustate.cpp @@ -0,0 +1,67 @@ +/* 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. + */ + + +#include "menustate.h" +#include "framebuffer.h" +#include "graphics.h" +#include "texturemanager.h" + +MenuState::MenuState() +{ +} + +MenuState::~MenuState() +{ + +} + +void MenuState::onEnter() +{ + +} + +void MenuState::onLeave() +{ + +} + +void MenuState::onClose() +{ + +} + +void MenuState::onInputEvent(InputEvent* event) +{ + +} + +void MenuState::render() +{ + +} + +void MenuState::update(int elapsedTicks) +{ + +} diff --git a/src/menustate.h b/src/menustate.h new file mode 100644 index 00000000..47575ecb --- /dev/null +++ b/src/menustate.h @@ -0,0 +1,47 @@ +/* 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 MENUSTATE_H +#define MENUSTATE_H + +#include "gamestate.h" + +class MenuState : public GameState +{ + +public: + MenuState(); + virtual ~MenuState(); + + void onEnter(); + void onLeave(); + + void onClose(); + void onInputEvent(InputEvent *event); + + void render(); + void update(int elapsedTicks); +}; + +#endif // MENUSTATE_H diff --git a/src/texture.cpp b/src/texture.cpp index d56ac410..baac399a 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -27,14 +27,13 @@ #include #include -Texture::Texture(int width, int height, unsigned char *pixels, int components) +Texture::Texture(int width, int height, int components, unsigned char *pixels) { m_width = width; m_height = height; glGenTextures(1, &m_textureId); glBindTexture(GL_TEXTURE_2D, m_textureId); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); GLenum format = 0; switch(components) { @@ -54,9 +53,6 @@ Texture::Texture(int width, int height, unsigned char *pixels, int components) glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, format, GL_UNSIGNED_BYTE, pixels); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -70,14 +66,21 @@ Texture::~Texture() glDeleteTextures(1, &m_textureId); } -void Texture::enableBilinearFilter() +void Texture::bind() { glBindTexture(GL_TEXTURE_2D, m_textureId); +} + +void Texture::enableBilinearFilter() +{ + bind(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } -void Texture::bind() +void Texture::copyFromScreen(int xoffset, int yoffset, int x, int y, int width, int height) { - glBindTexture(GL_TEXTURE_2D, m_textureId); + bind(); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height); } + diff --git a/src/texture.h b/src/texture.h index 6245d5b3..5c105782 100644 --- a/src/texture.h +++ b/src/texture.h @@ -33,7 +33,8 @@ class TextureManager; class Texture { public: - Texture(int width, int height, unsigned char *pixels, int components); + /// Create a texture, width and height must be a multiple of 2 + Texture(int width, int height, int components, unsigned char *pixels = NULL); virtual ~Texture(); /// Bind texture for drawing @@ -42,8 +43,12 @@ public: /// Enable texture bilinear filter (smooth scaled textures) void enableBilinearFilter(); + /// Copy screen pixels to texture + void copyFromScreen(int xoffset, int yoffset, int x, int y, int width, int height); + int getWidth() const { return m_width; } int getHeight() const { return m_height; } + GLuint getTextureId() const { return m_textureId; } private: GLuint m_textureId; diff --git a/src/textureloader.cpp b/src/textureloader.cpp index 7f73a34e..7dad2f72 100644 --- a/src/textureloader.cpp +++ b/src/textureloader.cpp @@ -117,7 +117,7 @@ TexturePtr TextureLoader::loadPNG(const unsigned char *fileData, unsigned int fi fclose(pngFile); delete[] row_pointers; - texture = TexturePtr(new Texture(width, height, pixels, components)); + texture = TexturePtr(new Texture(width, height, components, pixels)); delete[] pixels;