diff options
Diffstat (limited to 'src')
61 files changed, 778 insertions, 1258 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b40eab7b..695fef36 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,10 @@ -FIND_PACKAGE(SDL REQUIRED) -FIND_PACKAGE(SDL_image REQUIRED) -FIND_PACKAGE(SDL_mixer REQUIRED) -FIND_PACKAGE(SDL_net REQUIRED) -FIND_PACKAGE(SDL_ttf REQUIRED) -FIND_PACKAGE(SDL_gfx REQUIRED) +include(FindPkgConfig) +pkg_check_modules(SDL2 REQUIRED sdl2>=2.0.1) +pkg_check_modules(SDL2IMAGE REQUIRED SDL2_image) +pkg_check_modules(SDL2MIXER REQUIRED SDL2_mixer) +pkg_check_modules(SDL2NET REQUIRED SDL2_net) +pkg_check_modules(SDL2TTF REQUIRED SDL2_ttf) +pkg_check_modules(SDL2GFX REQUIRED SDL2_gfx) FIND_PACKAGE(CURL REQUIRED) FIND_PACKAGE(LibXml2 REQUIRED) FIND_PACKAGE(PhysFS REQUIRED) @@ -34,11 +35,6 @@ ENDIF() SET(FLAGS "-DPACKAGE_VERSION=\\\"${VERSION}\\\"") SET(FLAGS "${FLAGS} -DPKG_DATADIR=\\\"${PKG_DATADIR}/\\\"") SET(FLAGS "${FLAGS} -DLOCALEDIR=\\\"${LOCALEDIR}/\\\"") -IF (ENABLE_CPP0X) - SET(FLAGS "${FLAGS} -std=c++0x -DENABLE_CPP0X=1") -ELSE() - INCLUDE_DIRECTORIES("cpp0x_compat") -ENDIF() IF (ENABLE_NLS) SET(FLAGS "${FLAGS} -DENABLE_NLS=1") @@ -69,8 +65,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL SunOS) SET(EXTRA_LIBRARIES intl) ENDIF() -SET(GUICHAN_COMPONENTS "SDL") -FIND_PACKAGE(Guichan REQUIRED ${GUICHAN_COMPONENTS}) +FIND_PACKAGE(Guichan REQUIRED) IF (WITH_OPENGL) FIND_PACKAGE(OpenGL REQUIRED) @@ -79,20 +74,14 @@ IF (WITH_OPENGL) MESSAGE(STATUS "OpenGL support enabled") ENDIF (WITH_OPENGL) -IF (USE_X11) - FIND_PACKAGE(X11 REQUIRED) - INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR}) - SET(FLAGS "${FLAGS} -DUSE_X11") -ENDIF (USE_X11) - INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} - ${SDL_INCLUDE_DIR} - ${SDLIMAGE_INCLUDE_DIR} - ${SDLMIXER_INCLUDE_DIR} - ${SDLNET_INCLUDE_DIR} - ${SDLTTF_INCLUDE_DIR} - ${SDLGFX_INCLUDE_DIR} + ${SDL2_INCLUDE_DIRS} + ${SDL2IMAGE_INCLUDE_DIRS} + ${SDL2MIXER_INCLUDE_DIRS} + ${SDL2NET_INCLUDE_DIRS} + ${SDL2TTF_INCLUDE_DIRS} + ${SDL2GFX_INCLUDE_DIRS} ${PNG_INCLUDE_DIR} ${PHYSFS_INCLUDE_DIR} ${CURL_INCLUDE_DIR} @@ -116,19 +105,6 @@ IF (MINGW) "<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -O coff -o <OBJECT> <SOURCE>") ENDIF() -# Fix some stuff that gets not hidden by mainline modules -MARK_AS_ADVANCED(PHYSFS_INCLUDE_DIR) -MARK_AS_ADVANCED(PHYSFS_LIBRARY) -MARK_AS_ADVANCED(SDLIMAGE_INCLUDE_DIR) -MARK_AS_ADVANCED(SDLIMAGE_LIBRARY) -MARK_AS_ADVANCED(SDLMAIN_LIBRARY) -MARK_AS_ADVANCED(SDLMIXER_INCLUDE_DIR) -MARK_AS_ADVANCED(SDLMIXER_LIBRARY) -MARK_AS_ADVANCED(SDLNET_INCLUDE_DIR) -MARK_AS_ADVANCED(SDLNET_LIBRARY) -MARK_AS_ADVANCED(SDL_INCLUDE_DIR) -MARK_AS_ADVANCED(SDL_LIBRARY) - SET(SRCS gui/widgets/avatarlistbox.cpp gui/widgets/avatarlistbox.h @@ -679,12 +655,12 @@ ENDIF(ENABLE_MANASERV) TARGET_LINK_LIBRARIES(mana ${INTERNAL_LIBRARIES} - ${SDLGFX_LIBRARIES} - ${SDL_LIBRARY} - ${SDLIMAGE_LIBRARY} - ${SDLMIXER_LIBRARY} - ${SDLNET_LIBRARY} - ${SDLTTF_LIBRARY} + ${SDL2_LIBRARIES} + ${SDL2GFX_LIBRARIES} + ${SDL2IMAGE_LIBRARIES} + ${SDL2MIXER_LIBRARIES} + ${SDL2NET_LIBRARIES} + ${SDL2TTF_LIBRARIES} ${PNG_LIBRARIES} ${PHYSFS_LIBRARY} ${CURL_LIBRARIES} diff --git a/src/client.cpp b/src/client.cpp index 1489a0dc..0db7efa6 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -34,7 +34,6 @@ #endif #include "playerrelations.h" #include "sound.h" -#include "statuseffect.h" #include "units.h" #include "gui/changeemaildialog.h" @@ -66,12 +65,8 @@ #include "resources/chardb.h" #include "resources/hairdb.h" -#include "resources/emotedb.h" #include "resources/image.h" #include "resources/itemdb.h" -#include "resources/monsterdb.h" -#include "resources/specialdb.h" -#include "resources/npcdb.h" #include "resources/resourcemanager.h" #include "resources/theme.h" #include "resources/userpalette.h" @@ -241,11 +236,6 @@ Client::Client(const Options &options): } atexit(SDL_Quit); - SDL_EnableUNICODE(1); - SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); - - SDL_WM_SetCaption(branding.getValue("appName", "Mana").c_str(), NULL); - ResourceManager *resman = ResourceManager::getInstance(); if (!resman->setWriteDir(mLocalDataDir)) @@ -254,8 +244,6 @@ Client::Client(const Options &options): "Exiting.", mLocalDataDir.c_str())); } - Image::SDLsetEnableAlphaCache(config.getValue("alphaCache", true)); - #if defined __APPLE__ CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); @@ -300,6 +288,39 @@ Client::Client(const Options &options): // Add the local data directory to PhysicsFS search path resman->addToSearchPath(mLocalDataDir, false); + bool useOpenGL = !mOptions.noOpenGL && (config.getValue("opengl", 1) == 1); + + // Set up the transparency option for low CPU when not using OpenGL. + if (!useOpenGL && (config.getValue("disableTransparency", 0) == 1)) + Image::SDLdisableTransparency(); + +#ifdef USE_OPENGL + // Setup image loading for the right image format + Image::setLoadAsOpenGL(useOpenGL); + + // Create the graphics context + graphics = useOpenGL ? new OpenGLGraphics : new Graphics; +#else + // Create the graphics context + graphics = new Graphics; +#endif + + const int width = config.getIntValue("screenwidth"); + const int height = config.getIntValue("screenheight"); + const bool fullscreen = config.getBoolValue("screen"); + + // Try to set the desired video mode + if (!graphics->setVideoMode(width, height, fullscreen)) + { + logger->error(strprintf("Couldn't set %dx%d video mode: %s", + width, height, SDL_GetError())); + } + + SDL_SetWindowTitle(graphics->getTarget(), + branding.getValue("appName", "Mana").c_str()); + + Image::setRenderer(graphics->getRenderer()); + std::string iconFile = branding.getValue("appIcon", "icons/mana"); #ifdef _WIN32 iconFile += ".ico"; @@ -325,42 +346,10 @@ Client::Client(const Options &options): mIcon = IMG_Load(iconFile.c_str()); if (mIcon) { - SDL_SetAlpha(mIcon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); - SDL_WM_SetIcon(mIcon, NULL); + SDL_SetWindowIcon(graphics->getTarget(), mIcon); } #endif - bool useOpenGL = !mOptions.noOpenGL && (config.getValue("opengl", 1) == 1); - - // Set up the transparency option for low CPU when not using OpenGL. - if (!useOpenGL && (config.getValue("disableTransparency", 0) == 1)) - Image::SDLdisableTransparency(); - -#ifdef USE_OPENGL - - // Setup image loading for the right image format - Image::setLoadAsOpenGL(useOpenGL); - - // Create the graphics context - graphics = useOpenGL ? new OpenGLGraphics : new Graphics; -#else - // Create the graphics context - graphics = new Graphics; -#endif - - const int width = config.getIntValue("screenwidth"); - const int height = config.getIntValue("screenheight"); - const int bpp = 0; - const bool fullscreen = config.getBoolValue("screen"); - const bool hwaccel = config.getBoolValue("hwaccel"); - - // Try to set the desired video mode - if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel)) - { - logger->error(strprintf("Couldn't set %dx%dx%d video mode: %s", - width, height, bpp, SDL_GetError())); - } - // Initialize for drawing graphics->_beginDraw(); @@ -511,8 +500,12 @@ int Client::exec() case SDL_KEYDOWN: break; - case SDL_VIDEORESIZE: - handleVideoResize(event.resize.w, event.resize.h); + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + handleVideoResize(event.window.data1, event.window.data2); + break; + } break; } @@ -761,8 +754,7 @@ int Client::exec() // Load XML databases CharDB::load(); - if (itemDb) - delete itemDb; + delete itemDb; switch (Net::getNetworkType()) { @@ -1375,25 +1367,15 @@ void Client::accountLogin(LoginData *loginData) void Client::handleVideoResize(int width, int height) { - // Keep a minimum size. This isn't adhered to by the actual window, but - // it keeps some window positions from getting messed up. - width = std::max(640, width); - height = std::max(360, height); - - if (graphics->changeVideoMode(width, - height, - graphics->getBpp(), - false, - graphics->getHWAccel())) - { - videoResized(graphics->getWidth(), - graphics->getHeight()); + graphics->videoResized(width, height); - // Since everything appears to have worked out, remember to store the - // new size in the configuration. - config.setValue("screenwidth", width); - config.setValue("screenheight", height); - } + // The graphics width/height may be different due to scale + videoResized(graphics->getWidth(), graphics->getHeight()); + + // Since everything appears to have worked out, remember to store the + // new size in the configuration. + config.setValue("screenwidth", width); + config.setValue("screenheight", height); } void Client::videoResized(int width, int height) @@ -1409,3 +1391,18 @@ void Client::videoResized(int width, int height) if (mGame) mGame->videoResized(width, height); } + +bool Client::isActive() +{ + return !(SDL_GetWindowFlags(graphics->getTarget()) & SDL_WINDOW_MINIMIZED); +} + +bool Client::hasInputFocus() +{ + return SDL_GetWindowFlags(graphics->getTarget()) & SDL_WINDOW_INPUT_FOCUS; +} + +bool Client::hasMouseFocus() +{ + return SDL_GetWindowFlags(graphics->getTarget()) & SDL_WINDOW_MOUSE_FOCUS; +} diff --git a/src/client.h b/src/client.h index 4ad5562d..28fd4445 100644 --- a/src/client.h +++ b/src/client.h @@ -29,7 +29,7 @@ #include <guichan/actionlistener.hpp> #include <SDL.h> -#include <SDL_framerate.h> +#include <SDL2_framerate.h> #include <string> @@ -214,14 +214,9 @@ public: */ void videoResized(int width, int height); - static bool isActive() - { return SDL_GetAppState() & SDL_APPACTIVE; } - - static bool hasInputFocus() - { return SDL_GetAppState() & SDL_APPINPUTFOCUS; } - - static bool hasMouseFocus() - { return SDL_GetAppState() & SDL_APPMOUSEFOCUS; } + static bool isActive(); + static bool hasInputFocus(); + static bool hasMouseFocus(); private: void initRootDir(); diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp index cd07ca51..0f231535 100644 --- a/src/compoundsprite.cpp +++ b/src/compoundsprite.cpp @@ -20,7 +20,6 @@ #include "compoundsprite.h" -#include "game.h" #include "graphics.h" #include "map.h" @@ -223,6 +222,7 @@ int CompoundSprite::getDuration() const return duration; } +#if 0 static void updateValues(int &dimension, int &pos, int imgDimUL, int imgDimRD, int imgOffset) { // Handle going beyond the left/up @@ -238,11 +238,18 @@ static void updateValues(int &dimension, int &pos, int imgDimUL, int imgDimRD, i if (temp > dimension) dimension = temp; } - -#include "localplayer.h" +#endif void CompoundSprite::redraw() const { +#if 1 // TODO_SDL2: Does it make sense to implement CompoundSprite? + mWidth = mSprites.at(0)->getWidth(); + mHeight = mSprites.at(0)->getHeight(); + mOffsetX = 0; + mOffsetY = 0; + mNeedsRedraw = false; +#else + #ifdef USE_OPENGL // TODO OpenGL support if (Image::getLoadAsOpenGL()) @@ -295,7 +302,7 @@ void CompoundSprite::redraw() const int amask = 0xff000000; #endif - SDL_Surface *surface = SDL_CreateRGBSurface(SDL_HWSURFACE, mWidth, mHeight, + SDL_Surface *surface = SDL_CreateRGBSurface(0, mWidth, mHeight, 32, rmask, gmask, bmask, amask); if (!surface) @@ -322,7 +329,7 @@ void CompoundSprite::redraw() const delete graphics; - SDL_Surface *surfaceA = SDL_CreateRGBSurface(SDL_HWSURFACE, mWidth, mHeight, + SDL_Surface *surfaceA = SDL_CreateRGBSurface(0, mWidth, mHeight, 32, rmask, gmask, bmask, amask); SDL_SetAlpha(surface, 0, SDL_ALPHA_OPAQUE); @@ -338,4 +345,5 @@ void CompoundSprite::redraw() const SDL_FreeSurface(surfaceA); mNeedsRedraw = false; +#endif } diff --git a/src/cpp0x_compat/cstdint b/src/cpp0x_compat/cstdint deleted file mode 100644 index 05d56c6e..00000000 --- a/src/cpp0x_compat/cstdint +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Compatibility header used when the compiler doesn't support C++0x. - * - * While GCC 4.2.1 understands types like uint16_t by default, later versions - * are more strict so here are some typedefs for types used in our code. - */ - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; diff --git a/src/event.cpp b/src/event.cpp index 45e65fff..73099cc3 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -37,7 +37,7 @@ Event::~Event() // Integers -void Event::setInt(const std::string &key, int value) throw (BadEvent) +void Event::setInt(const std::string &key, int value) { if (mData.find(key) != mData.end()) throw KEY_ALREADY_EXISTS; @@ -45,7 +45,7 @@ void Event::setInt(const std::string &key, int value) throw (BadEvent) mData[key] = new IntData(value); } -int Event::getInt(const std::string &key) const throw (BadEvent) +int Event::getInt(const std::string &key) const { VariableMap::const_iterator it = mData.find(key); if (it == mData.end()) @@ -66,7 +66,7 @@ bool Event::hasInt(const std::string &key) const // Strings -void Event::setString(const std::string &key, const std::string &value) throw (BadEvent) +void Event::setString(const std::string &key, const std::string &value) { if (mData.find(key) != mData.end()) throw KEY_ALREADY_EXISTS; @@ -74,7 +74,7 @@ void Event::setString(const std::string &key, const std::string &value) throw (B mData[key] = new StringData(value); } -const std::string &Event::getString(const std::string &key) const throw (BadEvent) +const std::string &Event::getString(const std::string &key) const { VariableMap::const_iterator it = mData.find(key); if (it == mData.end()) @@ -96,7 +96,7 @@ bool Event::hasString(const std::string &key) const // Floats -void Event::setFloat(const std::string &key, double value) throw (BadEvent) +void Event::setFloat(const std::string &key, double value) { if (mData.find(key) != mData.end()) throw KEY_ALREADY_EXISTS; @@ -104,7 +104,7 @@ void Event::setFloat(const std::string &key, double value) throw (BadEvent) mData[key] = new FloatData(value); } -double Event::getFloat(const std::string &key) const throw (BadEvent) +double Event::getFloat(const std::string &key) const { VariableMap::const_iterator it = mData.find(key); if (it == mData.end()) @@ -125,7 +125,7 @@ bool Event::hasFloat(const std::string &key) const // Booleans -void Event::setBool(const std::string &key, bool value) throw (BadEvent) +void Event::setBool(const std::string &key, bool value) { if (mData.find(key) != mData.end()) throw KEY_ALREADY_EXISTS; @@ -133,7 +133,7 @@ void Event::setBool(const std::string &key, bool value) throw (BadEvent) mData[key] = new BoolData(value); } -bool Event::getBool(const std::string &key) const throw (BadEvent) +bool Event::getBool(const std::string &key) const { VariableMap::const_iterator it = mData.find(key); if (it == mData.end()) @@ -154,7 +154,7 @@ bool Event::hasBool(const std::string &key) const // Items -void Event::setItem(const std::string &key, Item *value) throw (BadEvent) +void Event::setItem(const std::string &key, Item *value) { if (mData.find(key) != mData.end()) throw KEY_ALREADY_EXISTS; @@ -162,7 +162,7 @@ void Event::setItem(const std::string &key, Item *value) throw (BadEvent) mData[key] = new ItemData(value); } -Item *Event::getItem(const std::string &key) const throw (BadEvent) +Item *Event::getItem(const std::string &key) const { VariableMap::const_iterator it = mData.find(key); if (it == mData.end()) @@ -183,7 +183,7 @@ bool Event::hasItem(const std::string &key) const // Actors -void Event::setActor(const std::string &key, ActorSprite *value) throw (BadEvent) +void Event::setActor(const std::string &key, ActorSprite *value) { if (mData.find(key) != mData.end()) throw KEY_ALREADY_EXISTS; @@ -191,7 +191,7 @@ void Event::setActor(const std::string &key, ActorSprite *value) throw (BadEvent mData[key] = new ActorData(value); } -ActorSprite *Event::getActor(const std::string &key) const throw (BadEvent) +ActorSprite *Event::getActor(const std::string &key) const { VariableMap::const_iterator it = mData.find(key); if (it == mData.end()) diff --git a/src/event.h b/src/event.h index f33e4c70..b785b16f 100644 --- a/src/event.h +++ b/src/event.h @@ -132,12 +132,12 @@ public: /** * Sets the given variable to the given integer, if it isn't already set. */ - void setInt(const std::string &key, int value) throw (BadEvent); + void setInt(const std::string &key, int value); /** * Returns the given variable if it is set and an integer. */ - int getInt(const std::string &key) const throw (BadEvent); + int getInt(const std::string &key) const; /** * Returns the given variable if it is set and an integer, returning the @@ -156,12 +156,12 @@ public: /** * Sets the given variable to the given string, if it isn't already set. */ - void setString(const std::string &key, const std::string &value) throw (BadEvent); + void setString(const std::string &key, const std::string &value); /** * Returns the given variable if it is set and a string. */ - const std::string &getString(const std::string &key) const throw (BadEvent); + const std::string &getString(const std::string &key) const; /** * Returns the given variable if it is set and a string, returning the @@ -182,12 +182,12 @@ public: * Sets the given variable to the given floating-point, if it isn't already * set. */ - void setFloat(const std::string &key, double value) throw (BadEvent); + void setFloat(const std::string &key, double value); /** * Returns the given variable if it is set and a floating-point. */ - double getFloat(const std::string &key) const throw (BadEvent); + double getFloat(const std::string &key) const; /** * Returns the given variable if it is set and a floating-point, returning @@ -206,12 +206,12 @@ public: /** * Sets the given variable to the given boolean, if it isn't already set. */ - void setBool(const std::string &key, bool value) throw (BadEvent); + void setBool(const std::string &key, bool value); /** * Returns the given variable if it is set and a boolean. */ - bool getBool(const std::string &key) const throw (BadEvent); + bool getBool(const std::string &key) const; /** * Returns the given variable if it is set and a boolean, returning the @@ -230,12 +230,12 @@ public: /** * Sets the given variable to the given Item, if it isn't already set. */ - void setItem(const std::string &key, Item *value) throw (BadEvent); + void setItem(const std::string &key, Item *value); /** * Returns the given variable if it is set and an Item. */ - Item *getItem(const std::string &key) const throw (BadEvent); + Item *getItem(const std::string &key) const; /** * Returns the given variable if it is set and an Item, returning the @@ -254,12 +254,12 @@ public: /** * Sets the given variable to the given actor, if it isn't already set. */ - void setActor(const std::string &key, ActorSprite *value) throw (BadEvent); + void setActor(const std::string &key, ActorSprite *value); /** * Returns the given variable if it is set and an actor. */ - ActorSprite *getActor(const std::string &key) const throw (BadEvent); + ActorSprite *getActor(const std::string &key) const; /** * Returns the given variable if it is set and an actor, returning the diff --git a/src/game.cpp b/src/game.cpp index 824eb7d1..5b78bdb5 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -42,7 +42,6 @@ #include "sound.h" #include "gui/chatwindow.h" -#include "gui/confirmdialog.h" #include "gui/debugwindow.h" #include "gui/equipmentwindow.h" #include "gui/gui.h" @@ -72,7 +71,6 @@ #include "gui/widgets/layout.h" #include "net/gamehandler.h" -#include "net/generalhandler.h" #include "net/net.h" #include "net/playerhandler.h" @@ -403,10 +401,10 @@ void Game::handleInput() { bool used = false; - if (event.type == SDL_VIDEORESIZE) + if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { // Let the client deal with this one (it'll pass down from there) - Client::instance()->handleVideoResize(event.resize.w, event.resize.h); + Client::instance()->handleVideoResize(event.window.data1, event.window.data2); } // Keyboard events (for discontinuous keys) else if (event.type == SDL_KEYDOWN) diff --git a/src/graphics.cpp b/src/graphics.cpp index 08b1b298..d5c1e1a0 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -19,8 +19,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <cassert> - #include "graphics.h" #include "log.h" @@ -28,122 +26,96 @@ #include "utils/gettext.h" -#include <SDL_gfxBlitFunc.h> -#include <SDL/SDL_rotozoom.h> - -Graphics::Graphics(): - mWidth(0), - mHeight(0), - mScale(1), - mBpp(0), - mFullscreen(false), - mHWAccel(false), - mBlitMode(BLIT_NORMAL), - mScreenSurface(0) +#include <guichan/exception.hpp> + +Graphics::~Graphics() { - mTarget = 0; + _endDraw(); } -Graphics::~Graphics() +void Graphics::setTarget(SDL_Window *target) { _endDraw(); + + mTarget = target; + + if (mTarget) + _beginDraw(); } -bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) +bool Graphics::setVideoMode(int w, int h, bool fs) { logger->log("Setting video mode %dx%d %s", w, h, fs ? "fullscreen" : "windowed"); - logger->log("Bits per pixel: %d", bpp); - - int displayFlags = SDL_ANYFORMAT; + int windowFlags = SDL_WINDOW_ALLOW_HIGHDPI; if (fs) - displayFlags |= SDL_FULLSCREEN; + windowFlags |= SDL_WINDOW_FULLSCREEN; else - displayFlags |= SDL_RESIZABLE; + windowFlags |= SDL_WINDOW_RESIZABLE; - if (hwaccel) - displayFlags |= SDL_HWSURFACE | SDL_DOUBLEBUF; - else - displayFlags |= SDL_SWSURFACE; + // TODO_SDL2: Support SDL_WINDOW_FULLSCREEN_DESKTOP - SDL_FreeSurface(mTarget); - mTarget = 0; + SDL_Window *window = nullptr; + SDL_Renderer *renderer = nullptr; + SDL_CreateWindowAndRenderer(w, h, windowFlags, &window, &renderer); - // Calculate scaling factor - mScale = std::max(w / 640, h / 360); + if (!window) + return false; - mScreenSurface = SDL_SetVideoMode(w, h, bpp, displayFlags); - const SDL_PixelFormat& fmt = *(mScreenSurface->format); - setTarget(SDL_CreateRGBSurface(SDL_SWSURFACE, - w / mScale, h / mScale, - fmt.BitsPerPixel, - fmt.Rmask, fmt.Gmask, fmt.Bmask, 0)); + SDL_SetWindowMinimumSize(window, 640, 360); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); - if (!mTarget) - return false; + setTarget(window); - mWidth = mTarget->w; - mHeight = mTarget->h; - mBpp = bpp; + mRenderer = renderer; + videoResized(w, h); mFullscreen = fs; - mHWAccel = hwaccel; - - char videoDriverName[64]; - if (SDL_VideoDriverName(videoDriverName, 64)) - logger->log("Using video driver: %s", videoDriverName); + if (const char *driver = SDL_GetCurrentVideoDriver()) + logger->log("Using video driver: %s", driver); else - logger->log("Using video driver: unknown"); - - const SDL_VideoInfo *vi = SDL_GetVideoInfo(); - - logger->log("Possible to create hardware surfaces: %s", - vi->hw_available ? "yes" : "no"); - logger->log("Window manager available: %s", - vi->wm_available ? "yes" : "no"); - logger->log("Accelerated hardware to hardware blits: %s", - vi->blit_hw ? "yes" : "no"); - logger->log("Accelerated hardware to hardware colorkey blits: %s", - vi->blit_hw_CC ? "yes" : "no"); - logger->log("Accelerated hardware to hardware alpha blits: %s", - vi->blit_hw_A ? "yes" : "no"); - logger->log("Accelerated software to hardware blits: %s", - vi->blit_sw ? "yes" : "no"); - logger->log("Accelerated software to hardware colorkey blits: %s", - vi->blit_sw_CC ? "yes" : "no"); - logger->log("Accelerated software to hardware alpha blits: %s", - vi->blit_sw_A ? "yes" : "no"); - logger->log("Accelerated color fills: %s", - vi->blit_fill ? "yes" : "no"); - logger->log("Available video memory: %d", vi->video_mem); + logger->log("Using video driver: not initialized"); + + SDL_RendererInfo info; + + if (SDL_GetRendererInfo(mRenderer, &info) == 0) { + logger->log("Using renderer: %s", info.name); + + logger->log("The renderer is a software fallback: %s", + (info.flags & SDL_RENDERER_SOFTWARE) ? "yes" : "no"); + logger->log("The renderer is hardware accelerated: %s", + (info.flags & SDL_RENDERER_ACCELERATED) ? "yes" : "no"); + logger->log("Vsync: %s", + (info.flags & SDL_RENDERER_PRESENTVSYNC) ? "on" : "off"); + logger->log("Renderer supports rendering to texture: %s", + (info.flags & SDL_RENDERER_TARGETTEXTURE) ? "yes" : "no"); + logger->log("Max texture size: %dx%d", + info.max_texture_width, info.max_texture_height); + } return true; } -bool Graphics::changeVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) +bool Graphics::changeVideoMode(int w, int h, bool fs) { // Just return success if we're already in this mode - if (mScreenSurface && mScreenSurface->w == w && - mScreenSurface->h == h && - mBpp == bpp && - mFullscreen == fs && - mHWAccel == hwaccel) + if (mWidth == w && + mHeight == h && + mFullscreen == fs) return true; _endDraw(); - bool success = setVideoMode(w, h, bpp, fs, hwaccel); + bool success = setVideoMode(w, h, fs); - // If it didn't work, try to restore fallback resolution. If that doesn't + // If it didn't work, try to restore the previous mode. If that doesn't // work either, we're in big trouble and bail out. - if (!success) - { - if (!setVideoMode(640, 360, mBpp, mFullscreen, mHWAccel)) - { + if (!success) { + if (!setVideoMode(mWidth, mHeight, mFullscreen)) { logger->error(_("Failed to change video mode and couldn't " - "switch back to the fallback mode!")); + "switch back to the previous mode!")); } } @@ -152,12 +124,36 @@ bool Graphics::changeVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) return success; } +void Graphics::videoResized(int w, int h) +{ + const int prevWidth = mWidth; + const int prevHeight = mHeight; + + mScale = getScale(w, h); + mWidth = w / mScale; + mHeight = h / mScale; + + if (mWidth != prevWidth || mHeight != prevHeight) { + if (mScreenTexture) { + SDL_DestroyTexture(mScreenTexture); + mScreenTexture = nullptr; + } + + if (mScale > 1) { + auto pixelFormat = SDL_GetWindowPixelFormat(mTarget); + mScreenTexture = SDL_CreateTexture(mRenderer, pixelFormat, SDL_TEXTUREACCESS_TARGET, mWidth, mHeight); + } + + SDL_SetRenderTarget(mRenderer, mScreenTexture); + } +} + bool Graphics::drawImage(Image *image, int x, int y) { - if (image) - return drawImage(image, 0, 0, x, y, image->mBounds.w, image->mBounds.h); - else + if (!image) return false; + + return drawImage(image, 0, 0, x, y, image->mBounds.w, image->mBounds.h); } bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY, @@ -167,15 +163,7 @@ bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY, bool useColor) { // Check that preconditions for blitting are met. - if (!mTarget || !image) - return false; - if (!image->mSDLSurface) - return false; - - Image *tmpImage = image->SDLgetScaledImage(desiredWidth, desiredHeight); - bool returnValue = false; - - if (!tmpImage) + if (!mTarget || !image || !image->mTexture) return false; dstX += mClipStack.top().xOffset; @@ -188,78 +176,37 @@ bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY, SDL_Rect srcRect; dstRect.x = dstX; dstRect.y = dstY; srcRect.x = srcX; srcRect.y = srcY; - srcRect.w = tmpImage->getWidth(); - srcRect.h = tmpImage->getHeight(); - - returnValue = !(SDL_BlitSurface(tmpImage->mSDLSurface, &srcRect, - mTarget, &dstRect) < 0); - - tmpImage->decRef(Resource::DeleteImmediately); + srcRect.w = width; + srcRect.h = height; + dstRect.w = desiredWidth; + dstRect.h = desiredHeight; - return returnValue; + return !(SDL_RenderCopy(mRenderer, image->mTexture, &srcRect, &dstRect) < 0); } bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY, - int width, int height, bool) + int width, int height, bool useColor) { - // Check that preconditions for blitting are met. - if (!mTarget || !image || !image->mSDLSurface) + if (!image) return false; - dstX += mClipStack.top().xOffset; - dstY += mClipStack.top().yOffset; - - srcX += image->mBounds.x; - srcY += image->mBounds.y; - - SDL_Rect dstRect; - SDL_Rect srcRect; - dstRect.x = dstX; dstRect.y = dstY; - srcRect.x = srcX; srcRect.y = srcY; - srcRect.w = width; - srcRect.h = height; - - if (mBlitMode == BLIT_NORMAL) - return !(SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0); - else - return !(SDL_gfxBlitRGBA(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0); + return drawRescaledImage(image, + srcX, srcY, + dstX, dstY, + width, height, + width, height, useColor); } void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h) { // Check that preconditions for blitting are met. - if (!mTarget || !image) - return; - if (!image->mSDLSurface) + if (!image) return; const int iw = image->getWidth(); const int ih = image->getHeight(); - if (iw == 0 || ih == 0) - return; - - for (int py = 0; py < h; py += ih) // Y position on pattern plane - { - int dh = (py + ih >= h) ? h - py : ih; - int srcY = image->mBounds.y; - int dstY = y + py + mClipStack.top().yOffset; - - for (int px = 0; px < w; px += iw) // X position on pattern plane - { - int dw = (px + iw >= w) ? w - px : iw; - int srcX = image->mBounds.x; - int dstX = x + px + mClipStack.top().xOffset; - - SDL_Rect dstRect; - SDL_Rect srcRect; - dstRect.x = dstX; dstRect.y = dstY; - srcRect.x = srcX; srcRect.y = srcY; - srcRect.w = dw; srcRect.h = dh; - - SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect); - } - } + drawRescaledImagePattern(image, x, y, w, h, iw, ih); } void Graphics::drawRescaledImagePattern(Image *image, @@ -268,50 +215,34 @@ void Graphics::drawRescaledImagePattern(Image *image, int scaledWidth, int scaledHeight) { // Check that preconditions for blitting are met. - if (!mTarget || !image) - return; - if (!image->mSDLSurface) + if (!mTarget || !image || !image->mTexture) return; if (scaledHeight == 0 || scaledWidth == 0) return; - Image *tmpImage = image->SDLgetScaledImage(scaledWidth, scaledHeight); - if (!tmpImage) - return; - - const int iw = tmpImage->getWidth(); - const int ih = tmpImage->getHeight(); - - if (iw == 0 || ih == 0) - { - tmpImage->decRef(Resource::DeleteImmediately); - return; - } - - for (int py = 0; py < h; py += ih) // Y position on pattern plane + for (int py = 0; py < h; py += scaledHeight) // Y position on pattern plane { - int dh = (py + ih >= h) ? h - py : ih; - int srcY = tmpImage->mBounds.y; + int dh = (py + scaledHeight >= h) ? h - py : scaledHeight; + int srcY = image->mBounds.y; int dstY = y + py + mClipStack.top().yOffset; - for (int px = 0; px < w; px += iw) // X position on pattern plane + for (int px = 0; px < w; px += scaledWidth) // X position on pattern plane { - int dw = (px + iw >= w) ? w - px : iw; - int srcX = tmpImage->mBounds.x; + int dw = (px + scaledWidth >= w) ? w - px : scaledWidth; + int srcX = image->mBounds.x; int dstX = x + px + mClipStack.top().xOffset; SDL_Rect dstRect; SDL_Rect srcRect; dstRect.x = dstX; dstRect.y = dstY; + dstRect.w = dw; dstRect.h = dh; srcRect.x = srcX; srcRect.y = srcY; srcRect.w = dw; srcRect.h = dh; - SDL_BlitSurface(tmpImage->mSDLSurface, &srcRect, mTarget, &dstRect); + SDL_RenderCopy(mRenderer, image->mTexture, &srcRect, &dstRect); } } - - tmpImage->decRef(Resource::DeleteImmediately); } void Graphics::drawImageRect(int x, int y, int w, int h, @@ -368,27 +299,16 @@ void Graphics::drawImageRect(int x, int y, int w, int h, void Graphics::updateScreen() { - // Center viewport - SDL_Rect dstRect; - dstRect.x = (mScreenSurface->w-getWidth() * mScale) / 2; - dstRect.y = (mScreenSurface->h-getHeight() * mScale) / 2; - - // Zoom in if necessary - if (mScale > 1) - { - SDL_Surface *tmp = zoomSurface(mTarget, mScale, mScale, 0); - - // Copy temporary surface to screen - SDL_BlitSurface(tmp, NULL, mScreenSurface, &dstRect); - SDL_FreeSurface(tmp); + if (!mScreenTexture) { + // Simple case when we're rendering directly to the window + SDL_RenderPresent(mRenderer); + } else { + // Otherwise, we now render the screen surface to the window + SDL_SetRenderTarget(mRenderer, NULL); + SDL_RenderCopy(mRenderer, mScreenTexture, NULL, NULL); + SDL_RenderPresent(mRenderer); + SDL_SetRenderTarget(mRenderer, mScreenTexture); } - else - { - // Copy mTarget directly to screen - SDL_BlitSurface(mTarget, NULL, mScreenSurface, &dstRect); - } - - SDL_Flip(mScreenSurface); } SDL_Surface *Graphics::getScreenshot() @@ -404,10 +324,145 @@ SDL_Surface *Graphics::getScreenshot() #endif int amask = 0x00000000; - SDL_Surface *screenshot = SDL_CreateRGBSurface(SDL_SWSURFACE, mTarget->w, - mTarget->h, 24, rmask, gmask, bmask, amask); - - SDL_BlitSurface(mTarget, NULL, screenshot, NULL); + SDL_Surface *screenshot = SDL_CreateRGBSurface(0, mWidth, + mHeight, 24, rmask, gmask, bmask, amask); + SDL_RenderReadPixels(mRenderer, NULL, SDL_PIXELFORMAT_RGB888, screenshot->pixels, screenshot->pitch); return screenshot; } + +bool Graphics::pushClipArea(gcn::Rectangle area) +{ + bool result = gcn::Graphics::pushClipArea(area); + updateSDLClipRect(); + return result; +} + +void Graphics::popClipArea() +{ + gcn::Graphics::popClipArea(); + updateSDLClipRect(); +} + +void Graphics::updateSDLClipRect() +{ + if (mClipStack.empty()) + { + SDL_RenderSetClipRect(mRenderer, NULL); + return; + } + + const gcn::ClipRectangle &carea = mClipStack.top(); + SDL_Rect rect; + rect.x = carea.x; + rect.y = carea.y; + rect.w = carea.width; + rect.h = carea.height; + + SDL_RenderSetClipRect(mRenderer, &rect); +} + +int Graphics::getScale(int w, int h) +{ + return std::max(w / 640, h / 360); +} + +void Graphics::drawPoint(int x, int y) +{ + if (mClipStack.empty()) + { + throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?"); + } + + const gcn::ClipRectangle &top = mClipStack.top(); + + x += top.xOffset; + y += top.yOffset; + + if (!top.isPointInRect(x, y)) + return; + + SDL_SetRenderDrawColor(mRenderer, + (Uint8)(mColor.r), + (Uint8)(mColor.g), + (Uint8)(mColor.b), + (Uint8)(mColor.a)); + SDL_RenderDrawPoint(mRenderer, x, y); +} + +void Graphics::drawLine(int x1, int y1, int x2, int y2) +{ + if (mClipStack.empty()) + { + throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?"); + } + + const gcn::ClipRectangle &top = mClipStack.top(); + + x1 += top.xOffset; + y1 += top.yOffset; + x2 += top.xOffset; + y2 += top.yOffset; + + SDL_SetRenderDrawColor(mRenderer, + (Uint8)(mColor.r), + (Uint8)(mColor.g), + (Uint8)(mColor.b), + (Uint8)(mColor.a)); + SDL_RenderDrawLine(mRenderer, x1, y1, x2, y2); +} + +void Graphics::drawRectangle(const gcn::Rectangle &rectangle) +{ + if (mClipStack.empty()) + { + throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?"); + } + + const gcn::ClipRectangle &top = mClipStack.top(); + + SDL_Rect rect; + rect.x = rectangle.x + top.xOffset; + rect.y = rectangle.y + top.yOffset; + rect.w = rectangle.width; + rect.h = rectangle.height; + + SDL_SetRenderDrawColor(mRenderer, + (Uint8)(mColor.r), + (Uint8)(mColor.g), + (Uint8)(mColor.b), + (Uint8)(mColor.a)); + SDL_RenderDrawRect(mRenderer, &rect); +} + +void Graphics::fillRectangle(const gcn::Rectangle &rectangle) +{ + if (mClipStack.empty()) + { + throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?"); + } + + const gcn::ClipRectangle &top = mClipStack.top(); + + gcn::Rectangle area = rectangle; + area.x += top.xOffset; + area.y += top.yOffset; + + if(!area.isIntersecting(top)) + { + return; + } + + SDL_Rect rect; + rect.x = area.x; + rect.y = area.y; + rect.w = area.width; + rect.h = area.height; + + SDL_SetRenderDrawColor(mRenderer, + (Uint8)(mColor.r), + (Uint8)(mColor.g), + (Uint8)(mColor.b), + (Uint8)(mColor.a)); + SDL_RenderFillRect(mRenderer, &rect); +} diff --git a/src/graphics.h b/src/graphics.h index 36a9adb9..f92374ec 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -22,13 +22,14 @@ #ifndef GRAPHICS_H #define GRAPHICS_H -#include <guichan/sdl/sdlgraphics.hpp> +#include <SDL.h> + +#include <guichan/color.hpp> +#include <guichan/graphics.hpp> class Image; class ImageRect; -struct SDL_Surface; - static const int defaultScreenWidth = 800; static const int defaultScreenHeight = 600; @@ -49,8 +50,9 @@ static const int defaultScreenHeight = 600; * Sections 0, 2, 6 and 8 will remain as is. 1, 3, 4, 5 and 7 will be * repeated to fit the size of the widget. */ -struct ImageRect +class ImageRect { +public: enum ImagePosition { UPPER_LEFT = 0, @@ -70,28 +72,36 @@ struct ImageRect /** * A central point of control for graphics. */ -class Graphics : public gcn::SDLGraphics +class Graphics : public gcn::Graphics { public: - enum BlitMode { - BLIT_NORMAL = 0, - BLIT_GFX - }; - - Graphics(); + Graphics() = default; virtual ~Graphics(); /** + * Sets the target SDL_Window to draw to. This funtion also pushes a + * clip areas corresponding to the dimension of the target. + * + * @param target the target to draw to. + */ + virtual void setTarget(SDL_Window *target); + + SDL_Window *getTarget() const { return mTarget; } + SDL_Renderer *getRenderer() const { return mRenderer; } + + /** * Try to create a window with the given settings. */ - virtual bool setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel); + virtual bool setVideoMode(int w, int h, bool fs); /** * Change the video mode. Can be used for switching to full screen, * changing resolution or adapting after window resize. */ - bool changeVideoMode(int w, int h, int bpp, bool fs, bool hwaccel); + bool changeVideoMode(int w, int h, bool fs); + + virtual void videoResized(int w, int h); /** * Blits an image onto the screen. @@ -176,12 +186,6 @@ class Graphics : public gcn::SDLGraphics drawImageRect(area.x, area.y, area.width, area.height, imgRect); } - void setBlitMode(BlitMode mode) - { mBlitMode = mode; } - - BlitMode getBlitMode() - { return mBlitMode; } - /** * Updates the screen. This is done by either copying the buffer to the * screen or swapping pages. @@ -189,12 +193,12 @@ class Graphics : public gcn::SDLGraphics virtual void updateScreen(); /** - * Returns the width of the drawable surface. + * Returns the width of the screen. */ int getWidth() const { return mWidth; } /** - * Returns the height of the drawable surface. + * Returns the height of the screen. */ int getHeight() const { return mHeight; } @@ -204,38 +208,60 @@ class Graphics : public gcn::SDLGraphics int getScale() const { return mScale; } /** - * Returns the amount of bits per pixel that was requested (not the - * actual amount that's currently active). - */ - int getBpp() const { return mBpp; } - - /** * Returns whether we're in a full screen mode. */ bool getFullscreen() const { return mFullscreen; } /** - * Returns whether old-fashioned SDL-based hardware acceleration was - * requested (not whether it's currently active). - */ - bool getHWAccel() const { return mHWAccel; } - - /** * Takes a screenshot and returns it as SDL surface. */ virtual SDL_Surface *getScreenshot(); gcn::Font *getFont() const { return mFont; } + virtual bool pushClipArea(gcn::Rectangle area); + + virtual void popClipArea(); + + virtual void drawImage(const gcn::Image *image, + int srcX, + int srcY, + int dstX, + int dstY, + int width, + int height) {} // not used + + virtual void drawPoint(int x, int y); + + virtual void drawLine(int x1, int y1, int x2, int y2); + + virtual void drawRectangle(const gcn::Rectangle &rectangle); + + virtual void fillRectangle(const gcn::Rectangle &rectangle); + + virtual void setColor(const gcn::Color &color) + { + mColor = color; + } + + virtual const gcn::Color &getColor() const + { + return mColor; + } + protected: - int mWidth; - int mHeight; - int mScale; - int mBpp; - bool mFullscreen; - bool mHWAccel; - BlitMode mBlitMode; - SDL_Surface *mScreenSurface; + void updateSDLClipRect(); + int getScale(int w, int h); + + int mWidth = 0; + int mHeight = 0; + int mScale = 1; + bool mFullscreen = false; + gcn::Color mColor; + + SDL_Window *mTarget = nullptr; + SDL_Renderer *mRenderer = nullptr; + SDL_Texture *mScreenTexture = nullptr; }; extern Graphics *graphics; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 2e1d006e..cb6682bd 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -26,6 +26,7 @@ #include "gui/sdlinput.h" #include "gui/truetypefont.h" +#include "gui/widgets/textfield.h" #include "gui/widgets/window.h" #include "gui/widgets/windowcontainer.h" @@ -190,6 +191,12 @@ void Gui::logic() Palette::advanceGradients(); gcn::Gui::logic(); + + while (!guiInput->isTextQueueEmpty()) + { + TextInput textInput = guiInput->dequeueTextInput(); + handleTextInput(textInput); + } } void Gui::draw() @@ -267,3 +274,14 @@ void Gui::handleMouseMoved(const gcn::MouseInput &mouseInput) gcn::Gui::handleMouseMoved(mouseInput); mMouseInactivityTimer = 0; } + +void Gui::handleTextInput(const TextInput &textInput) +{ + if (auto focused = mFocusHandler->getFocused()) + { + if (auto textField = dynamic_cast<TextField*>(focused)) + { + textField->textInput(textInput); + } + } +} diff --git a/src/gui/gui.h b/src/gui/gui.h index 006987da..998b6ec8 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -26,6 +26,7 @@ #include <guichan/gui.hpp> +class TextInput; class Graphics; class GuiConfigListener; class ImageSet; @@ -114,6 +115,7 @@ class Gui : public gcn::Gui protected: void handleMouseMoved(const gcn::MouseInput &mouseInput); + void handleTextInput(const TextInput &textInput); private: GuiConfigListener *mConfigListener; diff --git a/src/gui/sdlinput.cpp b/src/gui/sdlinput.cpp index 46636d52..c0f24a7a 100644 --- a/src/gui/sdlinput.cpp +++ b/src/gui/sdlinput.cpp @@ -109,6 +109,23 @@ gcn::MouseInput SDLInput::dequeueMouseInput() return mouseInput; } +bool SDLInput::isTextQueueEmpty() const +{ + return mTextInputQueue.empty(); +} + +TextInput SDLInput::dequeueTextInput() +{ + if (mTextInputQueue.empty()) + { + throw GCN_EXCEPTION("The queue is empty."); + } + + TextInput textInput(mTextInputQueue.front()); + mTextInputQueue.pop(); + return textInput; +} + void SDLInput::pushInput(SDL_Event event) { gcn::KeyInput keyInput; @@ -122,8 +139,8 @@ void SDLInput::pushInput(SDL_Event event) keyInput.setShiftPressed(event.key.keysym.mod & KMOD_SHIFT); keyInput.setControlPressed(event.key.keysym.mod & KMOD_CTRL); keyInput.setAltPressed(event.key.keysym.mod & KMOD_ALT); - keyInput.setMetaPressed(event.key.keysym.mod & KMOD_META); - keyInput.setNumericPad(event.key.keysym.sym >= SDLK_KP0 + keyInput.setMetaPressed(event.key.keysym.mod & KMOD_GUI); + keyInput.setNumericPad(event.key.keysym.sym >= SDLK_KP_0 && event.key.keysym.sym <= SDLK_KP_EQUALS); mKeyInputQueue.push(keyInput); @@ -135,8 +152,8 @@ void SDLInput::pushInput(SDL_Event event) keyInput.setShiftPressed(event.key.keysym.mod & KMOD_SHIFT); keyInput.setControlPressed(event.key.keysym.mod & KMOD_CTRL); keyInput.setAltPressed(event.key.keysym.mod & KMOD_ALT); - keyInput.setMetaPressed(event.key.keysym.mod & KMOD_META); - keyInput.setNumericPad(event.key.keysym.sym >= SDLK_KP0 + keyInput.setMetaPressed(event.key.keysym.mod & KMOD_GUI); + keyInput.setNumericPad(event.key.keysym.sym >= SDLK_KP_0 && event.key.keysym.sym <= SDLK_KP_EQUALS); mKeyInputQueue.push(keyInput); @@ -147,19 +164,7 @@ void SDLInput::pushInput(SDL_Event event) mouseInput.setX(event.button.x); mouseInput.setY(event.button.y); mouseInput.setButton(convertMouseButton(event.button.button)); - - if (event.button.button == SDL_BUTTON_WHEELDOWN) - { - mouseInput.setType(gcn::MouseInput::WHEEL_MOVED_DOWN); - } - else if (event.button.button == SDL_BUTTON_WHEELUP) - { - mouseInput.setType(gcn::MouseInput::WHEEL_MOVED_UP); - } - else - { - mouseInput.setType(gcn::MouseInput::PRESSED); - } + mouseInput.setType(gcn::MouseInput::PRESSED); mouseInput.setTimeStamp(SDL_GetTicks()); mMouseInputQueue.push(mouseInput); break; @@ -183,6 +188,35 @@ void SDLInput::pushInput(SDL_Event event) mMouseInputQueue.push(mouseInput); break; + case SDL_MOUSEWHEEL: + if (event.wheel.y) { +#if SDL_VERSION_ATLEAST(2, 26, 0) + mouseInput.setX(event.wheel.mouseX); + mouseInput.setY(event.wheel.mouseY); +#else + int x, y; + SDL_GetMouseState(&x, &y); + mouseInput.setX(x); + mouseInput.setY(y); +#endif + mouseInput.setButton(gcn::MouseInput::EMPTY); + mouseInput.setType(event.wheel.y > 0 ? gcn::MouseInput::WHEEL_MOVED_UP + : gcn::MouseInput::WHEEL_MOVED_DOWN); + mouseInput.setTimeStamp(SDL_GetTicks()); + mMouseInputQueue.push(mouseInput); + } + break; + + case SDL_TEXTINPUT: + mTextInputQueue.emplace(event.text.text); + break; + + // TODO_SDL2: This is now a window event + // case SDL_WINDOWEVENT: + // switch (event.window.event) { + // } + // break; +#if 0 case SDL_ACTIVEEVENT: /* * This occurs when the mouse leaves the window and the Gui-chan @@ -209,7 +243,7 @@ void SDLInput::pushInput(SDL_Event event) mMouseInWindow = true; } break; - +#endif } // end switch } @@ -231,9 +265,9 @@ int SDLInput::convertMouseButton(int button) int SDLInput::convertKeyCharacter(SDL_Event event) { - SDL_keysym keysym = event.key.keysym; + SDL_Keysym keysym = event.key.keysym; - int value = keysym.unicode; + int value = keysym.sym; switch (keysym.sym) { @@ -265,16 +299,10 @@ int SDLInput::convertKeyCharacter(SDL_Event event) value = Key::PAUSE; break; case SDLK_SPACE: - // Special characters like ~ (tilde) ends up - // with the keysym.sym SDLK_SPACE which - // without this check would be lost. The check - // is only valid on key down events in SDL. - if (event.type == SDL_KEYUP || keysym.unicode == ' ') - { - value = Key::SPACE; - } + value = Key::SPACE; break; case SDLK_ESCAPE: + case SDLK_AC_BACK: value = Key::ESCAPE; break; case SDLK_DELETE: @@ -292,7 +320,7 @@ int SDLInput::convertKeyCharacter(SDL_Event event) case SDLK_PAGEUP: value = Key::PAGE_UP; break; - case SDLK_PRINT: + case SDLK_PRINTSCREEN: value = Key::PRINT_SCREEN; break; case SDLK_PAGEDOWN: @@ -343,27 +371,21 @@ int SDLInput::convertKeyCharacter(SDL_Event event) case SDLK_F15: value = Key::F15; break; - case SDLK_NUMLOCK: + case SDLK_NUMLOCKCLEAR: value = Key::NUM_LOCK; break; case SDLK_CAPSLOCK: value = Key::CAPS_LOCK; break; - case SDLK_SCROLLOCK: + case SDLK_SCROLLLOCK: value = Key::SCROLL_LOCK; break; - case SDLK_RMETA: + case SDLK_RGUI: value = Key::RIGHT_META; break; - case SDLK_LMETA: + case SDLK_LGUI: value = Key::LEFT_META; break; - case SDLK_LSUPER: - value = Key::LEFT_SUPER; - break; - case SDLK_RSUPER: - value = Key::RIGHT_SUPER; - break; case SDLK_MODE: value = Key::ALT_GR; break; @@ -394,34 +416,34 @@ int SDLInput::convertKeyCharacter(SDL_Event event) { switch (keysym.sym) { - case SDLK_KP0: + case SDLK_KP_0: value = Key::INSERT; break; - case SDLK_KP1: + case SDLK_KP_1: value = Key::END; break; - case SDLK_KP2: + case SDLK_KP_2: value = Key::DOWN; break; - case SDLK_KP3: + case SDLK_KP_3: value = Key::PAGE_DOWN; break; - case SDLK_KP4: + case SDLK_KP_4: value = Key::LEFT; break; - case SDLK_KP5: + case SDLK_KP_5: value = 0; break; - case SDLK_KP6: + case SDLK_KP_6: value = Key::RIGHT; break; - case SDLK_KP7: + case SDLK_KP_7: value = Key::HOME; break; - case SDLK_KP8: + case SDLK_KP_8: value = Key::UP; break; - case SDLK_KP9: + case SDLK_KP_9: value = Key::PAGE_UP; break; default: diff --git a/src/gui/sdlinput.h b/src/gui/sdlinput.h index 90f70df3..09bb788e 100644 --- a/src/gui/sdlinput.h +++ b/src/gui/sdlinput.h @@ -61,13 +61,15 @@ #include <queue> -#include <SDL/SDL.h> +#include <SDL.h> #include <guichan/input.hpp> #include <guichan/keyinput.hpp> #include <guichan/mouseinput.hpp> #include <guichan/platform.hpp> +#include <string> + namespace Key { enum @@ -122,6 +124,19 @@ namespace Key }; } +class TextInput +{ +public: + TextInput(const char *text) + : mText(text) + {} + + const std::string &getText() const { return mText; } + +private: + std::string mText; +}; + /** * SDL implementation of Input. */ @@ -160,6 +175,10 @@ public: virtual gcn::MouseInput dequeueMouseInput(); + bool isTextQueueEmpty() const; + + TextInput dequeueTextInput(); + protected: /** * Converts a mouse button from SDL to a Guichan mouse button @@ -181,6 +200,7 @@ protected: std::queue<gcn::KeyInput> mKeyInputQueue; std::queue<gcn::MouseInput> mMouseInputQueue; + std::queue<TextInput> mTextInputQueue; bool mMouseDown; bool mMouseInWindow; diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index c468490c..eb59c4ea 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -38,6 +38,8 @@ #include "utils/dtor.h" #include "utils/gettext.h" +#include <functional> + extern Window *statusWindow; Setup::Setup(): @@ -103,12 +105,12 @@ void Setup::action(const gcn::ActionEvent &event) if (event.getId() == "Apply") { setVisible(false); - for_each(mTabs.begin(), mTabs.end(), std::mem_fun(&SetupTab::apply)); + for_each(mTabs.begin(), mTabs.end(), std::mem_fn(&SetupTab::apply)); } else if (event.getId() == "Cancel") { setVisible(false); - for_each(mTabs.begin(), mTabs.end(), std::mem_fun(&SetupTab::cancel)); + for_each(mTabs.begin(), mTabs.end(), std::mem_fn(&SetupTab::cancel)); } else if (event.getId() == "Reset Windows") { diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp index 5e29519b..b66ba3aa 100644 --- a/src/gui/setup_keyboard.cpp +++ b/src/gui/setup_keyboard.cpp @@ -178,8 +178,8 @@ void Setup_Keyboard::refreshAssignedKey(int index) caption = keyboard.getKeyCaption(index) + ": "; else { - char *temp = SDL_GetKeyName( - (SDLKey) keyboard.getKeyValue(index)); + const char *temp = SDL_GetKeyName( + (SDL_Scancode) keyboard.getKeyValue(index)); caption = strprintf("%-25s", (keyboard.getKeyCaption(index) + ": ").c_str()) + toString(temp); diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 5a697160..ac419de5 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -26,8 +26,6 @@ #include "game.h" #include "graphics.h" #include "localplayer.h" -#include "log.h" -#include "main.h" #include "gui/okdialog.h" @@ -38,8 +36,6 @@ #include "gui/widgets/scrollarea.h" #include "gui/widgets/slider.h" #include "gui/widgets/spacer.h" -#include "gui/widgets/textfield.h" -#include "gui/widgets/dropdown.h" #include "utils/gettext.h" #include "utils/stringutils.h" @@ -90,26 +86,21 @@ class ModeListModel : public gcn::ListModel ModeListModel::ModeListModel() { /* Get available fullscreen/hardware modes */ - SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); - - /* Check which modes are available */ - if (modes == (SDL_Rect **)0) - logger->log("No modes available"); - else if (modes == (SDL_Rect **)-1) - logger->log("All resolutions available"); - else + const int numModes = SDL_GetNumDisplayModes(0); + for (int i = 0; i < numModes; i++) { - for (int i = 0; modes[i]; ++i) - { - const int width = modes[i]->w; - const int height = modes[i]->h; + SDL_DisplayMode mode; + if (SDL_GetDisplayMode(0, i, &mode) != 0) + continue; - // Skip the unreasonably small modes - if (width < 640 || height < 360) - continue; + // Skip the unreasonably small modes + if (mode.w < 640 || mode.h < 360) + continue; - mVideoModes.push_back(toString(width) + "x" + toString(height)); - } + // TODO_SDL2: Modes now dinstinguish between pixel format and refresh rate as well + // TODO_SDL2: Fullscreen mode needs display selection + + mVideoModes.push_back(toString(mode.w) + "x" + toString(mode.h)); } } @@ -255,9 +246,7 @@ void Setup_Video::apply() { if (!graphics->changeVideoMode(screenWidth, screenHeight, - graphics->getBpp(), - fullscreen, - graphics->getHWAccel())) + fullscreen)) { std::stringstream errorMessage; if (fullscreen) diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp index 1b960d64..437f9d01 100644 --- a/src/gui/socialwindow.cpp +++ b/src/gui/socialwindow.cpp @@ -33,8 +33,6 @@ #include "gui/widgets/avatarlistbox.h" #include "gui/widgets/browserbox.h" #include "gui/widgets/button.h" -#include "gui/widgets/container.h" -#include "gui/widgets/label.h" #include "gui/widgets/linkhandler.h" #include "gui/widgets/popup.h" #include "gui/widgets/scrollarea.h" @@ -47,7 +45,6 @@ #include "resources/theme.h" -#include "utils/dtor.h" #include "utils/gettext.h" #include "utils/stringutils.h" @@ -618,7 +615,7 @@ void SocialWindow::showPartyCreate() { new OkDialog(_("Create Party"), _("Cannot create party. You are already in a party"), - this); + true, this); return; } diff --git a/src/gui/tradewindow.h b/src/gui/tradewindow.h index 59ddcbdc..20da4574 100644 --- a/src/gui/tradewindow.h +++ b/src/gui/tradewindow.h @@ -117,7 +117,7 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener */ void setStatus(Status s); - typedef const std::auto_ptr<Inventory> InventoryPtr; + typedef const std::unique_ptr<Inventory> InventoryPtr; InventoryPtr mMyInventory; InventoryPtr mPartnerInventory; diff --git a/src/gui/truetypefont.cpp b/src/gui/truetypefont.cpp index 620ba191..443adaa5 100644 --- a/src/gui/truetypefont.cpp +++ b/src/gui/truetypefont.cpp @@ -28,6 +28,7 @@ #include "utils/stringutils.h" +#include <guichan/color.hpp> #include <guichan/exception.hpp> const unsigned int CACHE_SIZE = 256; @@ -53,9 +54,10 @@ class TextChunk void generate(TTF_Font *font) { SDL_Color sdlCol; - sdlCol.b = color.b; sdlCol.r = color.r; sdlCol.g = color.g; + sdlCol.b = color.b; + sdlCol.a = color.a; const char *str = getSafeUtf8String(text); SDL_Surface *surface = TTF_RenderUTF8_Blended( diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 0f737fb0..b2945617 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -311,7 +311,7 @@ void Viewport::_followMouse() if (mPlayerFollowMouse && button & SDL_BUTTON(1)) { // We create a mouse event and send it to mouseDragged. - Uint8 *keys = SDL_GetKeyState(NULL); + const Uint8 *keys = SDL_GetKeyboardState(NULL); gcn::MouseEvent mouseEvent(NULL, (keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]), false, diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 4a31fa63..9247f67a 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -182,7 +182,7 @@ Button::~Button() { for (int mode = 0; mode < BUTTON_COUNT; ++mode) { - for_each(mButton[mode].grid, mButton[mode].grid + 9, + std::for_each(mButton[mode].grid, mButton[mode].grid + 9, dtor<Image*>()); } delete[] mButton; diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp index ec76f861..c9974fec 100644 --- a/src/gui/widgets/desktop.cpp +++ b/src/gui/widgets/desktop.cpp @@ -94,14 +94,9 @@ void Desktop::draw(gcn::Graphics *graphics) if (mWallpaper) { - if (!Image::useOpenGL()) - g->drawImage(mWallpaper, - (getWidth() - mWallpaper->getWidth()) / 2, - (getHeight() - mWallpaper->getHeight()) / 2); - else - g->drawRescaledImage(mWallpaper, 0, 0, 0, 0, - mWallpaper->getWidth(), mWallpaper->getHeight(), - getWidth(), getHeight(), false); + g->drawRescaledImage(mWallpaper, 0, 0, 0, 0, + mWallpaper->getWidth(), mWallpaper->getHeight(), + getWidth(), getHeight(), false); } mBgSkin->setAlpha(1.0f); @@ -168,19 +163,6 @@ void Desktop::setBestFittingWallpaper() mWallpaper->decRef(Resource::DeleteImmediately); mWallpaper = wallpaper; - - // In software mode we try to prescale the image for performance - if (!wallpaper->useOpenGL() && - (wallpaper->getWidth() != width || - wallpaper->getHeight() != height)) - { - if (Image *prescaled = wallpaper->SDLgetScaledImage(width, height)) - { - // Make sure the original can be freed - wallpaper->decRef(); - mWallpaper = prescaled; - } - } } else { diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp index e90f6073..101afaef 100644 --- a/src/gui/widgets/dropdown.cpp +++ b/src/gui/widgets/dropdown.cpp @@ -102,7 +102,7 @@ DropDown::~DropDown() buttons[1][0]->decRef(); buttons[1][1]->decRef(); - for_each(skin.grid, skin.grid + 9, dtor<Image*>()); + std::for_each(skin.grid, skin.grid + 9, dtor<Image*>()); } delete mScrollArea; diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp index 3105a762..cdb2d3c4 100644 --- a/src/gui/widgets/emoteshortcutcontainer.cpp +++ b/src/gui/widgets/emoteshortcutcontainer.cpp @@ -92,7 +92,7 @@ void EmoteShortcutContainer::draw(gcn::Graphics *graphics) // Draw emote keyboard shortcut. const char *key = SDL_GetKeyName( - (SDLKey) keyboard.getKeyValue(keyboard.KEY_EMOTE_1 + i)); + (SDL_Scancode) keyboard.getKeyValue(keyboard.KEY_EMOTE_1 + i)); graphics->setColor(Theme::getThemeColor(Theme::TEXT)); g->drawText(key, emoteX + 2, emoteY + 2, gcn::Graphics::LEFT); diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp index f1690d43..396de3bd 100644 --- a/src/gui/widgets/itemshortcutcontainer.cpp +++ b/src/gui/widgets/itemshortcutcontainer.cpp @@ -86,7 +86,7 @@ void ItemShortcutContainer::draw(gcn::Graphics *graphics) // Draw item keyboard shortcut. const char *key = SDL_GetKeyName( - (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_1 + i)); + (SDL_Scancode) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_1 + i)); graphics->setColor(Theme::getThemeColor(Theme::TEXT)); g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT); diff --git a/src/gui/widgets/playerbox.cpp b/src/gui/widgets/playerbox.cpp index 5c5976c1..4f341af0 100644 --- a/src/gui/widgets/playerbox.cpp +++ b/src/gui/widgets/playerbox.cpp @@ -75,7 +75,7 @@ PlayerBox::~PlayerBox() if (instances == 0) { - for_each(background.grid, background.grid + 9, dtor<Image*>()); + std::for_each(background.grid, background.grid + 9, dtor<Image*>()); } } diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp index 27b194ff..4695f5ab 100644 --- a/src/gui/widgets/progressbar.cpp +++ b/src/gui/widgets/progressbar.cpp @@ -88,7 +88,7 @@ ProgressBar::~ProgressBar() if (mInstances == 0) { - for_each(mBorder.grid, mBorder.grid + 9, dtor<Image*>()); + std::for_each(mBorder.grid, mBorder.grid + 9, dtor<Image*>()); } } diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp index d5e824e1..c95adeaa 100644 --- a/src/gui/widgets/scrollarea.cpp +++ b/src/gui/widgets/scrollarea.cpp @@ -66,9 +66,9 @@ ScrollArea::~ScrollArea() if (instances == 0) { - for_each(background.grid, background.grid + 9, dtor<Image*>()); - for_each(vMarker.grid, vMarker.grid + 9, dtor<Image*>()); - for_each(vMarkerHi.grid, vMarkerHi.grid + 9, dtor<Image*>()); + std::for_each(background.grid, background.grid + 9, dtor<Image*>()); + std::for_each(vMarker.grid, vMarker.grid + 9, dtor<Image*>()); + std::for_each(vMarkerHi.grid, vMarkerHi.grid + 9, dtor<Image*>()); buttons[UP][0]->decRef(); buttons[UP][1]->decRef(); diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp index 17b7108f..c8ed2141 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tab.cpp @@ -76,7 +76,7 @@ Tab::~Tab() { for (int mode = 0; mode < TAB_COUNT; mode++) { - for_each(tabImg[mode].grid, tabImg[mode].grid + 9, dtor<Image*>()); + std::for_each(tabImg[mode].grid, tabImg[mode].grid + 9, dtor<Image*>()); } } } diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp index ec57f1c7..35ce09c5 100644 --- a/src/gui/widgets/textfield.cpp +++ b/src/gui/widgets/textfield.cpp @@ -24,7 +24,6 @@ #include "configuration.h" #include "graphics.h" -#include "gui/palette.h" #include "gui/sdlinput.h" #include "resources/image.h" @@ -36,6 +35,8 @@ #include <guichan/font.hpp> +#include <SDL.h> + #undef DELETE //Win32 compatibility hack int TextField::instances = 0; @@ -84,7 +85,7 @@ TextField::~TextField() instances--; if (instances == 0) - for_each(skin.grid, skin.grid + 9, dtor<Image*>()); + std::for_each(skin.grid, skin.grid + 9, dtor<Image*>()); } void TextField::updateAlpha() @@ -162,33 +163,7 @@ int TextField::getValue() const void TextField::keyPressed(gcn::KeyEvent &keyEvent) { - int val = keyEvent.getKey().getValue(); - - if (val >= 32) - { - int l; - if (val < 128) l = 1; // 0xxxxxxx - else if (val < 0x800) l = 2; // 110xxxxx 10xxxxxx - else if (val < 0x10000) l = 3; // 1110xxxx 10xxxxxx 10xxxxxx - else l = 4; // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - - char buf[4]; - for (int i = 0; i < l; ++i) - { - buf[i] = val >> (6 * (l - i - 1)); - if (i > 0) buf[i] = (buf[i] & 63) | 128; - } - - if (l > 1) buf[0] |= 255 << (8 - l); - - mText.insert(mCaretPosition, std::string(buf, buf + l)); - mCaretPosition += l; - } - - /* In UTF-8, 10xxxxxx is only used for inner parts of characters. So skip - them when processing key presses. */ - - switch (val) + switch (keyEvent.getKey().getValue()) { case Key::LEFT: { @@ -302,8 +277,9 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent) return; break; - case 22: // Control code 22, SYNCHRONOUS IDLE, sent on Ctrl+v - handlePaste(); + case SDLK_v: + if (keyEvent.isControlPressed()) + handlePaste(); break; } @@ -311,6 +287,12 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent) fixScroll(); } +void TextField::textInput(const TextInput &textInput) +{ + mText.insert(mCaretPosition, textInput.getText()); + mCaretPosition += textInput.getText().length(); +} + void TextField::autoComplete() { if (mAutoComplete && mText.size() > 0) @@ -383,7 +365,7 @@ void TextField::handlePaste() std::string text = getText(); std::string::size_type caretPos = getCaretPosition(); - if (RetrieveBuffer(text, caretPos)) { + if (insertFromClipboard(text, caretPos)) { setText(text); setCaretPosition(caretPos); } diff --git a/src/gui/widgets/textfield.h b/src/gui/widgets/textfield.h index 94cada41..bf60cbc3 100644 --- a/src/gui/widgets/textfield.h +++ b/src/gui/widgets/textfield.h @@ -26,6 +26,7 @@ #include <vector> +class TextInput; class ImageRect; class TextField; @@ -116,6 +117,11 @@ class TextField : public gcn::TextField void keyPressed(gcn::KeyEvent &keyEvent); /** + * Handle text input (should possibly be new event in Guichan). + */ + void textInput(const TextInput &textInput); + + /** * Set the minimum value for a range */ void setMinimum(int min) { mMinimum = min; } diff --git a/src/gui/windowmenu.cpp b/src/gui/windowmenu.cpp index a06415fb..ff75e5d1 100644 --- a/src/gui/windowmenu.cpp +++ b/src/gui/windowmenu.cpp @@ -167,7 +167,7 @@ static std::string createShortcutCaption(const std::string& text, if (key != KeyboardConfig::KEY_NO_VALUE) { caption += " ("; - caption += SDL_GetKeyName((SDLKey) keyboard.getKeyValue(key)); + caption += SDL_GetKeyName((SDL_Scancode) keyboard.getKeyValue(key)); caption += ")"; } return caption; diff --git a/src/guild.cpp b/src/guild.cpp index 2beee4f5..714ca010 100644 --- a/src/guild.cpp +++ b/src/guild.cpp @@ -169,7 +169,7 @@ void Guild::setRights(short rights) bool Guild::isMember(GuildMember *member) const { - if (member->mGuild > 0 && member->mGuild != this) + if (member->mGuild != nullptr && member->mGuild != this) return false; MemberList::const_iterator itr = mMembers.begin(), diff --git a/src/joystick.cpp b/src/joystick.cpp index cc6e532b..a1da181c 100644 --- a/src/joystick.cpp +++ b/src/joystick.cpp @@ -37,7 +37,7 @@ void Joystick::init() joystickCount = SDL_NumJoysticks(); logger->log("%i joysticks/gamepads found", joystickCount); for (int i = 0; i < joystickCount; i++) - logger->log("- %s", SDL_JoystickName(i)); + logger->log("- %s", SDL_JoystickNameForIndex(i)); } Joystick::Joystick(int no): diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp index 0f4a46bf..39c99bc3 100644 --- a/src/keyboardconfig.cpp +++ b/src/keyboardconfig.cpp @@ -99,8 +99,8 @@ static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = { {"keyChatNextTab", SDLK_RIGHTBRACKET, _("Next Chat Tab")}, {"keyOK", SDLK_SPACE, _("Select OK")}, {"keyQuit", SDLK_ESCAPE, _("Quit")}, - {"keyIgnoreInput1", SDLK_LSUPER, _("Ignore input 1")}, - {"keyIgnoreInput2", SDLK_RSUPER, _("Ignore input 2")} + {"keyIgnoreInput1", SDLK_LGUI, _("Ignore input 1")}, + {"keyIgnoreInput2", SDLK_RGUI, _("Ignore input 2")} }; void KeyboardConfig::init() @@ -231,5 +231,5 @@ bool KeyboardConfig::isKeyActive(int index) const void KeyboardConfig::refreshActiveKeys() { - mActiveKeys = SDL_GetKeyState(NULL); + mActiveKeys = SDL_GetKeyboardState(NULL); } diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h index 8c744123..cb58dd90 100644 --- a/src/keyboardconfig.h +++ b/src/keyboardconfig.h @@ -227,7 +227,7 @@ class KeyboardConfig KeyFunction mKey[KEY_TOTAL]; /**< Pointer to all the key data */ - uint8_t *mActiveKeys; /**< Stores a list of all the keys */ + const uint8_t *mActiveKeys; /**< Stores a list of all the keys */ std::string mBindError; }; diff --git a/src/net/download.cpp b/src/net/download.cpp index bccba7a3..61cdf114 100644 --- a/src/net/download.cpp +++ b/src/net/download.cpp @@ -124,7 +124,7 @@ bool Download::start() { logger->log("Starting download: %s", mUrl.c_str()); - mThread = SDL_CreateThread(downloadThread, this); + mThread = SDL_CreateThread(downloadThread, "Download", this); if (!mThread) { diff --git a/src/net/manaserv/messagehandler.h b/src/net/manaserv/messagehandler.h index 6e0221cb..8949d34e 100644 --- a/src/net/manaserv/messagehandler.h +++ b/src/net/manaserv/messagehandler.h @@ -41,7 +41,7 @@ class MessageHandler : public Net::MessageHandler virtual void handleMessage(MessageIn &msg) = 0; }; -typedef const std::auto_ptr<MessageHandler> MessageHandlerPtr; +typedef const std::unique_ptr<MessageHandler> MessageHandlerPtr; } // namespace ManaServ diff --git a/src/net/manaserv/messagein.h b/src/net/manaserv/messagein.h index 89ae5ed8..1edc4fe7 100644 --- a/src/net/manaserv/messagein.h +++ b/src/net/manaserv/messagein.h @@ -52,7 +52,10 @@ class MessageIn /** * Returns the length of unread data. */ - unsigned int getUnreadLength() const { return mLength - mPos; } + unsigned int getUnreadLength() const + { + return (mPos < mLength) ? mLength - mPos : 0; + } /** * Reads an unsigned 8-bit integer from the message. diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp index 51c757cc..77b545fd 100644 --- a/src/net/tmwa/loginhandler.cpp +++ b/src/net/tmwa/loginhandler.cpp @@ -298,7 +298,7 @@ void LoginHandler::sendLoginRegister(const std::string &username, const std::string &password) { MessageOut outMsg(0x0064); - outMsg.writeInt32(0); // client version + outMsg.writeInt32(20); // client version outMsg.writeString(username, 24); outMsg.writeString(password, 24); diff --git a/src/net/tmwa/messagehandler.h b/src/net/tmwa/messagehandler.h index 2b1f5b7e..b598f896 100644 --- a/src/net/tmwa/messagehandler.h +++ b/src/net/tmwa/messagehandler.h @@ -49,7 +49,7 @@ class MessageHandler : public Net::MessageHandler Network *mNetwork; }; -typedef const std::auto_ptr<MessageHandler> MessageHandlerPtr; +typedef const std::unique_ptr<MessageHandler> MessageHandlerPtr; } diff --git a/src/net/tmwa/messagein.h b/src/net/tmwa/messagein.h index 48121187..2f66ca28 100644 --- a/src/net/tmwa/messagein.h +++ b/src/net/tmwa/messagein.h @@ -50,7 +50,10 @@ class MessageIn /** * Returns the length of unread data. */ - unsigned int getUnreadLength() const { return mLength - mPos; } + unsigned int getUnreadLength() const + { + return (mPos < mLength) ? mLength - mPos : 0; + } /** * Reads an unsigned 8-bit integer from the message. diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp index 3a02deba..ed564b46 100644 --- a/src/net/tmwa/network.cpp +++ b/src/net/tmwa/network.cpp @@ -77,7 +77,7 @@ uint16_t packet_lengths[0x220] = { 11, 7,VAR, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3, // #0x01C0 2, 14, 10,VAR, 22, 22, 4, 2, 13, 97, 0, 9, 9, 29, 6, 28, - 8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2,VAR, 47, 33, 6, + 8, 14, 10, 35, 6,VAR, 4, 11, 54, 53, 60, 2,VAR, 47, 33, 6, 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2,VAR,VAR, VAR,VAR, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56,VAR, 4, 5, 10, // #0x0200 @@ -159,7 +159,7 @@ bool Network::connect(ServerInfo server) mToSkip = 0; mState = CONNECTING; - mWorkerThread = SDL_CreateThread(networkThread, this); + mWorkerThread = SDL_CreateThread(networkThread, "Network", this); if (!mWorkerThread) { setError("Unable to create network worker thread"); diff --git a/src/net/tmwa/tradehandler.cpp b/src/net/tmwa/tradehandler.cpp index 40e37594..a02056a4 100644 --- a/src/net/tmwa/tradehandler.cpp +++ b/src/net/tmwa/tradehandler.cpp @@ -207,6 +207,11 @@ void TradeHandler::handleMessage(MessageIn &msg) SERVER_NOTICE(_("Failed adding item. Trade " "partner has no free slot.")) break; + case 3: + // Add item failed - non tradable item + SERVER_NOTICE(_("Failed adding item. You " + "cant trade this item.")) + break; default: SERVER_NOTICE(_("Failed adding item for " "unknown reason.")) diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 28fd47f6..0b79e933 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -63,7 +63,13 @@ OpenGLGraphics::~OpenGLGraphics() void OpenGLGraphics::setSync(bool sync) { + if (mSync == sync) + return; + mSync = sync; + + if (mContext) + SDL_GL_SetSwapInterval(sync ? 1 : 0); } void OpenGLGraphics::setReduceInputLag(bool reduceInputLag) @@ -71,55 +77,59 @@ void OpenGLGraphics::setReduceInputLag(bool reduceInputLag) mReduceInputLag = reduceInputLag; } -bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) +bool OpenGLGraphics::setVideoMode(int w, int h, bool fs) { logger->log("Setting video mode %dx%d %s", w, h, fs ? "fullscreen" : "windowed"); - int displayFlags = SDL_ANYFORMAT | SDL_OPENGL; + // TODO_SDL2: Support SDL_WINDOW_ALLOW_HIGHDPI, but check handling of clip area - const double targetRatio = (double) 640 / 360; // 1.77778 - const double requestedRatio = (double) w / h; + int windowFlags = SDL_WINDOW_OPENGL; - if (requestedRatio < targetRatio) { - // Screen is higher / narrower than target aspect ratio: calculate - // scale based on height. - mScale = (int) std::floor((double) h / 360); - } else { - mScale = (int) std::floor((double) w / 640); - } - - mWidth = w / mScale; - mHeight = h / mScale; - mBpp = bpp; - mFullscreen = fs; - mHWAccel = hwaccel; + mScale = getScale(w, h); if (fs) { - displayFlags |= SDL_FULLSCREEN; + windowFlags |= SDL_WINDOW_FULLSCREEN; } else { // Resizing currently not supported on Windows, where it would require // reuploading all textures. #if !defined(_WIN32) - displayFlags |= SDL_RESIZABLE; + windowFlags |= SDL_WINDOW_RESIZABLE; #endif } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - if (!(mTarget = SDL_SetVideoMode(w, h, bpp, displayFlags))) + SDL_Window *window = SDL_CreateWindow("Mana", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + w, h, windowFlags); + if (!window) { + logger->log("Failed to create window: %s", SDL_GetError()); return false; + } + + SDL_SetWindowMinimumSize(window, 640, 360); + + SDL_GLContext glContext = SDL_GL_CreateContext(window); + if (!glContext) { + logger->log("Failed to create OpenGL context: %s", SDL_GetError()); + return false; + } + + mTarget = window; + mContext = glContext; + mWidth = w / mScale; + mHeight = h / mScale; + mFullscreen = fs; -#ifdef __APPLE__ if (mSync) { - const GLint VBL = 1; - CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL); + SDL_GL_SetSwapInterval(1); } -#endif // Setup OpenGL glViewport(0, 0, mWidth * mScale, mHeight * mScale); @@ -152,6 +162,19 @@ bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) return true; } +void OpenGLGraphics::videoResized(int w, int h) +{ + _endDraw(); + + mScale = getScale(w, h); + mWidth = w / mScale; + mHeight = h / mScale; + + glViewport(0, 0, w, h); + + _beginDraw(); +} + static inline void drawQuad(Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height) @@ -623,7 +646,7 @@ void OpenGLGraphics::drawRescaledImagePattern(Image *image, void OpenGLGraphics::updateScreen() { - SDL_GL_SwapBuffers(); + SDL_GL_SwapWindow(mTarget); /* * glFinish flushes all OpenGL commands and makes sure they have been @@ -647,7 +670,7 @@ void OpenGLGraphics::_beginDraw() glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0.0, (double) mWidth, (double) mHeight, 0.0, -1.0, 1.0); + glOrtho(0.0, (double)mWidth, (double)mHeight, 0.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -669,8 +692,8 @@ void OpenGLGraphics::_endDraw() SDL_Surface* OpenGLGraphics::getScreenshot() { - int h = mTarget->h; - int w = mTarget->w; + int w, h; + SDL_GL_GetDrawableSize(mTarget, &w, &h); GLint pack = 1; SDL_Surface *screenshot = SDL_CreateRGBSurface( @@ -721,13 +744,14 @@ bool OpenGLGraphics::pushClipArea(gcn::Rectangle area) transY = -mClipStack.top().yOffset; } + // Skip Graphics::popClipArea since we don't need to interact with SDL2 bool result = gcn::Graphics::pushClipArea(area); transX += mClipStack.top().xOffset; transY += mClipStack.top().yOffset; int x = (int) (mClipStack.top().x * mScale); - int y = mTarget->h - (int) ((mClipStack.top().y + + int y = (int) ((mHeight - mClipStack.top().y - mClipStack.top().height) * mScale); int width = (int) (mClipStack.top().width * mScale); int height = (int) (mClipStack.top().height * mScale); @@ -741,13 +765,14 @@ bool OpenGLGraphics::pushClipArea(gcn::Rectangle area) void OpenGLGraphics::popClipArea() { + // Skip Graphics::popClipArea since we don't need to interact with SDL2 gcn::Graphics::popClipArea(); if (mClipStack.empty()) return; int x = (int) (mClipStack.top().x * mScale); - int y = mTarget->h - (int) ((mClipStack.top().y + + int y = (int) ((mHeight - mClipStack.top().y - mClipStack.top().height) * mScale); int width = (int) (mClipStack.top().width * mScale); int height = (int) (mClipStack.top().height * mScale); diff --git a/src/openglgraphics.h b/src/openglgraphics.h index 63c32261..01bca360 100644 --- a/src/openglgraphics.h +++ b/src/openglgraphics.h @@ -37,8 +37,8 @@ class OpenGLGraphics : public Graphics ~OpenGLGraphics(); /** - * Sets whether vertical refresh syncing is enabled. Takes effect after - * the next call to setVideoMode(). Only implemented on MacOS for now. + * Sets whether vertical refresh syncing is enabled. Takes effect + * immediately. */ void setSync(bool sync); bool getSync() const { return mSync; } @@ -53,7 +53,9 @@ class OpenGLGraphics : public Graphics void setReduceInputLag(bool reduceInputLag); bool getReduceInputLag() const { return mReduceInputLag; } - bool setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel); + bool setVideoMode(int w, int h, bool fs); + + void videoResized(int w, int h); bool drawImage(Image *image, int srcX, int srcY, @@ -118,6 +120,7 @@ class OpenGLGraphics : public Graphics void drawQuadArrayii(int size); + SDL_GLContext mContext = nullptr; GLfloat *mFloatTexArray; GLint *mIntTexArray; GLint *mIntVertArray; diff --git a/src/party.cpp b/src/party.cpp index 344bbdad..126a63c1 100644 --- a/src/party.cpp +++ b/src/party.cpp @@ -168,7 +168,7 @@ void Party::setRights(short rights) bool Party::isMember(PartyMember *member) const { - if (member->mParty > 0 && member->mParty != this) + if (member->mParty != nullptr && member->mParty != this) return false; MemberList::const_iterator itr = mMembers.begin(), diff --git a/src/resources/ambientlayer.cpp b/src/resources/ambientlayer.cpp index c31afbac..301927f8 100644 --- a/src/resources/ambientlayer.cpp +++ b/src/resources/ambientlayer.cpp @@ -33,25 +33,6 @@ AmbientLayer::AmbientLayer(Image *img, float parallax, mKeepRatio(keepRatio) { mImage->incRef(); - - if (keepRatio && !mImage->useOpenGL() - && defaultScreenWidth != 0 - && defaultScreenHeight != 0 - && graphics->getWidth() != defaultScreenWidth - && graphics->getHeight() != defaultScreenHeight) - { - // Rescale the overlay to keep the ratio as if we were on - // the default resolution... - Image *rescaledOverlay = mImage->SDLgetScaledImage( - (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), - (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); - - if (rescaledOverlay) - { - mImage->decRef(); - mImage = rescaledOverlay; - } - } } AmbientLayer::~AmbientLayer() @@ -86,7 +67,7 @@ void AmbientLayer::update(int timePassed, float dx, float dy) void AmbientLayer::draw(Graphics *graphics, int x, int y) { - if (!mImage->useOpenGL() || !mKeepRatio) + if (!mKeepRatio) graphics->drawImagePattern(mImage, (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY); else @@ -94,5 +75,4 @@ void AmbientLayer::draw(Graphics *graphics, int x, int y) (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY, (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); - } diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 7e592198..6f2609b0 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -29,10 +29,8 @@ #endif #include "log.h" -#include "configuration.h" #include <SDL_image.h> -#include <SDL_rotozoom.h> #ifdef USE_OPENGL bool Image::mUseOpenGL = false; @@ -40,47 +38,38 @@ bool Image::mPowerOfTwoTextures = true; int Image::mTextureType = 0; int Image::mTextureSize = 0; #endif -bool Image::mEnableAlphaCache = false; // The low CPU mode is disabled per default bool Image::mDisableTransparency = false; -Image::Image(SDL_Surface *image, bool hasAlphaChannel, Uint8 *alphaChannel): +SDL_Renderer *Image::mRenderer; + +Image::Image(SDL_Texture *texture, int width, int height): mAlpha(1.0f), - mSDLSurface(image), - mAlphaChannel(alphaChannel), - mHasAlphaChannel(hasAlphaChannel) + mTexture(texture) { #ifdef USE_OPENGL mGLImage = 0; #endif - mUseAlphaCache = Image::mEnableAlphaCache; - mBounds.x = 0; mBounds.y = 0; + mBounds.w = width; + mBounds.h = height; - mLoaded = false; + mLoaded = mTexture != nullptr; - if (mSDLSurface) + if (!mLoaded) { - mBounds.w = mSDLSurface->w; - mBounds.h = mSDLSurface->h; - - mLoaded = true; - } - else logger->log( "Image::Image(SDL_Surface*): Couldn't load invalid Surface!"); + } } #ifdef USE_OPENGL Image::Image(GLuint glimage, int width, int height, int texWidth, int texHeight): mAlpha(1.0f), - mSDLSurface(0), - mAlphaChannel(0), - mHasAlphaChannel(true), - mUseAlphaCache(false), + mTexture(0), mGLImage(glimage), mTexWidth(texWidth), mTexHeight(texHeight) @@ -140,10 +129,8 @@ Resource *Image::load(SDL_RWops *rw, Dye const &dye) rgba.Gmask = 0x00FF0000; rgba.Gloss = 0; rgba.Gshift = 16; rgba.Bmask = 0x0000FF00; rgba.Bloss = 0; rgba.Bshift = 8; rgba.Amask = 0x000000FF; rgba.Aloss = 0; rgba.Ashift = 0; - rgba.colorkey = 0; - rgba.alpha = 255; - SDL_Surface *surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE); + SDL_Surface *surf = SDL_ConvertSurface(tmpImage, &rgba, 0); SDL_FreeSurface(tmpImage); Uint32 *pixels = static_cast< Uint32 * >(surf->pixels); @@ -173,34 +160,14 @@ Image *Image::load(SDL_Surface *tmpImage) return _SDLload(tmpImage); } -void Image::SDLcleanCache() -{ - ResourceManager *resman = ResourceManager::getInstance(); - - for (std::map<float, SDL_Surface*>::iterator - i = mAlphaCache.begin(), i_end = mAlphaCache.end(); - i != i_end; ++i) - { - if (mSDLSurface != i->second) - resman->scheduleDelete(i->second); - i->second = 0; - } - mAlphaCache.clear(); -} - void Image::unload() { mLoaded = false; - if (mSDLSurface) + if (mTexture) { - SDLcleanCache(); - // Free the image surface. - SDL_FreeSurface(mSDLSurface); - mSDLSurface = NULL; - - delete[] mAlphaChannel; - mAlphaChannel = NULL; + SDL_DestroyTexture(mTexture); + mTexture = NULL; } #ifdef USE_OPENGL @@ -221,27 +188,6 @@ bool Image::useOpenGL() #endif } -bool Image::hasAlphaChannel() -{ - if (!mLoaded) - return false; - -#ifdef USE_OPENGL - if (mUseOpenGL) - return true; -#endif - - return mHasAlphaChannel; -} - -SDL_Surface *Image::getByAlpha(float alpha) -{ - std::map<float, SDL_Surface*>::iterator it = mAlphaCache.find(alpha); - if (it != mAlphaCache.end()) - return (*it).second; - return 0; -} - void Image::setAlpha(float alpha) { if (!useOpenGL() && mDisableTransparency) @@ -253,188 +199,26 @@ void Image::setAlpha(float alpha) if (alpha < 0.0f || alpha > 1.0f) return; - if (mSDLSurface) - { - if (mUseAlphaCache) - { - SDL_Surface *surface = getByAlpha(mAlpha); - if (!surface) - { - if (mAlphaCache.size() > 100) - SDLcleanCache(); - - mAlphaCache[mAlpha] = mSDLSurface; - } - surface = getByAlpha(alpha); - if (surface) - { - mAlphaCache.erase(alpha); - mSDLSurface = surface; - mAlpha = alpha; - return; - } - else - { - mSDLSurface = Image::SDLduplicateSurface(mSDLSurface); - } - } - - mAlpha = alpha; - - if (!hasAlphaChannel()) - { - // Set the alpha value this image is drawn at - SDL_SetAlpha(mSDLSurface, SDL_SRCALPHA, (int) (255 * mAlpha)); - } - else - { - if (SDL_MUSTLOCK(mSDLSurface)) - SDL_LockSurface(mSDLSurface); - - // Precompute as much as possible - int maxHeight = std::min((mBounds.y + mBounds.h), mSDLSurface->h); - int maxWidth = std::min((mBounds.x + mBounds.w), mSDLSurface->w); - int i = 0; - - for (int y = mBounds.y; y < maxHeight; y++) - for (int x = mBounds.x; x < maxWidth; x++) - { - i = y * mSDLSurface->w + x; - // Only change the pixel if it was visible at load time... - Uint8 sourceAlpha = mAlphaChannel[i]; - if (sourceAlpha > 0) - { - Uint8 r, g, b, a; - SDL_GetRGBA(((Uint32*) mSDLSurface->pixels)[i], - mSDLSurface->format, - &r, &g, &b, &a); - - a = (Uint8) (sourceAlpha * mAlpha); - - // Here is the pixel we want to set - ((Uint32 *)(mSDLSurface->pixels))[i] = - SDL_MapRGBA(mSDLSurface->format, r, g, b, a); - } - } - - if (SDL_MUSTLOCK(mSDLSurface)) - SDL_UnlockSurface(mSDLSurface); - } - } - else - { - mAlpha = alpha; - } -} - -Image *Image::SDLgetScaledImage(int width, int height) -{ - if (width == 0 || height == 0) - return 0; + mAlpha = alpha; - // Increase our reference count and return ourselves in case of same size - if (width == getWidth() && height == getHeight()) + if (mTexture) { - incRef(); - return this; - } - - if (!mSDLSurface) - return 0; - - ResourceManager *resman = ResourceManager::getInstance(); - - // Generate a unique ID path for storing the scaled version in the - // resource manager. - std::string idPath = getIdPath(); - idPath += ":scaled:"; - idPath += toString(width); - idPath += "x"; - idPath += toString(height); - - // Try whether a scaled version is already available - Image *scaledImage = static_cast<Image*>(resman->get(idPath)); - - if (!scaledImage) - { - // No scaled version with this size exists already, so create one - SDL_Surface *scaledSurface = zoomSurface(mSDLSurface, - (double) width / getWidth(), - (double) height / getHeight(), - 1); - - if (scaledSurface) - { - scaledImage = load(scaledSurface); - SDL_FreeSurface(scaledSurface); - - // Place the scaled image in the resource manager - resman->addResource(idPath, scaledImage); - } + SDL_SetTextureAlphaMod(mTexture, (Uint8) (255 * mAlpha)); } - - return scaledImage; } -SDL_Surface* Image::SDLduplicateSurface(SDL_Surface* tmpImage) +Image *Image::_SDLload(SDL_Surface *image) { - if (!tmpImage || !tmpImage->format) + if (!image || !mRenderer) return NULL; - return SDL_ConvertSurface(tmpImage, tmpImage->format, SDL_SWSURFACE); + SDL_Texture *texture = SDL_CreateTextureFromSurface(mRenderer, image); + return new Image(texture, image->w, image->h); } -Image *Image::_SDLload(SDL_Surface *tmpImage) +void Image::setRenderer(SDL_Renderer *renderer) { - if (!tmpImage) - return NULL; - - bool hasAlpha = false; - - // The alpha channel to be filled with alpha values - Uint8 *alphaChannel = new Uint8[tmpImage->w * tmpImage->h]; - - if (tmpImage->format->BitsPerPixel == 32) - { - // Figure out whether the image uses its alpha layer - for (int i = 0; i < tmpImage->w * tmpImage->h; ++i) - { - Uint8 r, g, b, a; - SDL_GetRGBA( - ((Uint32*) tmpImage->pixels)[i], - tmpImage->format, - &r, &g, &b, &a); - - if (a != 255) - hasAlpha = true; - - alphaChannel[i] = a; - } - } - - SDL_Surface *image; - - // Convert the surface to the current display format - if (hasAlpha) - image = SDL_DisplayFormatAlpha(tmpImage); - else - { - image = SDL_DisplayFormat(tmpImage); - - // We also delete the alpha channel since - // it's not used. - delete[] alphaChannel; - alphaChannel = NULL; - } - - if (!image) - { - logger->log("Error: Image convert failed."); - delete[] alphaChannel; - return NULL; - } - - return new Image(image, hasAlpha, alphaChannel); + mRenderer = renderer; } #ifdef USE_OPENGL @@ -489,7 +273,7 @@ Image *Image::_GLload(SDL_Surface *image) } // Make sure the alpha channel is not used, but copied to destination - SDL_SetAlpha(oldImage, 0, SDL_ALPHA_OPAQUE); + SDL_SetSurfaceBlendMode(oldImage, SDL_BLENDMODE_NONE); SDL_BlitSurface(oldImage, NULL, image, NULL); } @@ -583,38 +367,24 @@ Image *Image::getSubImage(int x, int y, int width, int height) mTexWidth, mTexHeight); #endif - return new SubImage(this, mSDLSurface, + return new SubImage(this, mTexture, mBounds.x + x, mBounds.y + y, width, height); } -void Image::SDLterminateAlphaCache() -{ - SDLcleanCache(); - mUseAlphaCache = false; -} - //============================================================================ // SubImage Class //============================================================================ -SubImage::SubImage(Image *parent, SDL_Surface *image, +SubImage::SubImage(Image *parent, SDL_Texture *texture, int x, int y, int width, int height): - Image(image), + Image(texture, width, height), mParent(parent) { if (mParent) { mParent->incRef(); - mParent->SDLterminateAlphaCache(); - mHasAlphaChannel = mParent->hasAlphaChannel(); - mAlphaChannel = mParent->SDLgetAlphaChannel(); - } - else - { - mHasAlphaChannel = false; - mAlphaChannel = 0; } // Set up the rectangle. @@ -622,7 +392,6 @@ SubImage::SubImage(Image *parent, SDL_Surface *image, mBounds.y = y; mBounds.w = width; mBounds.h = height; - mUseAlphaCache = false; } #ifdef USE_OPENGL @@ -644,10 +413,8 @@ SubImage::SubImage(Image *parent, GLuint image, SubImage::~SubImage() { - // Avoid destruction of the image - mSDLSurface = 0; - // Avoid possible destruction of its alpha channel - mAlphaChannel = 0; + // Avoid destruction of the texture + mTexture = nullptr; #ifdef USE_OPENGL mGLImage = 0; #endif diff --git a/src/resources/image.h b/src/resources/image.h index b762bf2a..efe2262e 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -37,8 +37,6 @@ #include <SDL_opengl.h> #endif -#include <map> - class Dye; class Position; @@ -129,12 +127,6 @@ class Image : public Resource */ Image *getSubImage(int x, int y, int width, int height); - /** - * Tells if the image has got an alpha channel - * @return true if it's true, false otherwise. - */ - bool hasAlphaChannel(); - // SDL only public functions /** @@ -146,31 +138,7 @@ class Image : public Resource static bool SDLisTransparencyDisabled() { return mDisableTransparency; } - /** - * Gets an scaled instance of an image. The returned image is managed - * by the ResourceManager. - * - * @param width The desired width of the scaled image. - * @param height The desired height of the scaled image. - * - * @return An Image resource, or 0 on failure. - */ - Image *SDLgetScaledImage(int width, int height); - - /** - * Get the alpha Channel of a SDL surface. - */ - Uint8 *SDLgetAlphaChannel() const - { return mAlphaChannel; } - - SDL_Surface* SDLduplicateSurface(SDL_Surface* tmpImage); - - void SDLcleanCache(); - - void SDLterminateAlphaCache(); - - static void SDLsetEnableAlphaCache(bool n) - { mEnableAlphaCache = n; } + static void setRenderer(SDL_Renderer *renderer); #ifdef USE_OPENGL @@ -204,30 +172,18 @@ class Image : public Resource // ----------------------- /** SDL Constructor */ - Image(SDL_Surface *image, bool hasAlphaChannel = false, - Uint8 *alphaChannel = NULL); + Image(SDL_Texture *texture, int width, int height); - /** SDL_Surface to SDL_Surface Image loader */ + /** SDL_Surface to SDL_Texture Image loader */ static Image *_SDLload(SDL_Surface *tmpImage); - SDL_Surface *getByAlpha(float alpha); - - SDL_Surface *mSDLSurface; - - /** Alpha Channel pointer used for 32bit based SDL surfaces */ - Uint8 *mAlphaChannel; - bool mHasAlphaChannel; - - /** Alpha cache: The cache stores a copy of the image - for specific requested opacities, hence, increasing - the image disply speed */ - std::map<float, SDL_Surface*> mAlphaCache; - bool mUseAlphaCache; - static bool mEnableAlphaCache; + SDL_Texture *mTexture; /** Stores whether the transparency is disabled */ static bool mDisableTransparency; + static SDL_Renderer *mRenderer; + // ----------------------- // OpenGL protected members // ----------------------- @@ -261,7 +217,7 @@ class Image : public Resource class SubImage : public Image { public: - SubImage(Image *parent, SDL_Surface *image, + SubImage(Image *parent, SDL_Texture *texture, int x, int y, int width, int height); #ifdef USE_OPENGL SubImage(Image *parent, GLuint image, int x, int y, diff --git a/src/resources/settingsmanager.cpp b/src/resources/settingsmanager.cpp index 940ebb59..a26fae9d 100644 --- a/src/resources/settingsmanager.cpp +++ b/src/resources/settingsmanager.cpp @@ -85,7 +85,8 @@ namespace SettingsManager NPCDB::unload(); SpecialDB::unload(); MonsterDB::unload(); - itemDb->unload(); + if (itemDb) + itemDb->unload(); hairDB.unload(); Attributes::unload(); } @@ -209,4 +210,3 @@ namespace SettingsManager } } - diff --git a/src/resources/theme.cpp b/src/resources/theme.cpp index 8db05be9..84d6311b 100644 --- a/src/resources/theme.cpp +++ b/src/resources/theme.cpp @@ -88,8 +88,8 @@ void Skin::updateAlpha(float minimumOpacityAllowed) void Skin::setAlpha(float alpha) { - for_each(mBorder.grid, mBorder.grid + 9, - std::bind2nd(std::mem_fun(&Image::setAlpha), alpha)); + std::for_each(mBorder.grid, mBorder.grid + 9, + [=] (Image *img) { img->setAlpha(alpha); }); mCloseImage->setAlpha(alpha); mStickyImageUp->setAlpha(alpha); diff --git a/src/sound.cpp b/src/sound.cpp index 1af1f136..44f55cba 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -22,7 +22,6 @@ #include <SDL.h> #include "configuration.h" -#include "game.h" #include "localplayer.h" #include "log.h" #include "sound.h" @@ -112,7 +111,6 @@ void Sound::info() { SDL_version compiledVersion; const SDL_version *linkedVersion; - char driver[40] = "Unknown"; const char *format = "Unknown"; int rate = 0; Uint16 audioFormat = 0; @@ -121,7 +119,7 @@ void Sound::info() MIX_VERSION(&compiledVersion); linkedVersion = Mix_Linked_Version(); - SDL_AudioDriverName(driver, 40); + const char *driver = SDL_GetCurrentAudioDriver(); Mix_QuerySpec(&rate, &audioFormat, &channels); switch (audioFormat) diff --git a/src/utils/copynpaste.cpp b/src/utils/copynpaste.cpp index 2bb8fb49..ccb36d79 100644 --- a/src/utils/copynpaste.cpp +++ b/src/utils/copynpaste.cpp @@ -1,7 +1,6 @@ /* - * Retrieve string pasted depending on OS mechanisms. - * Copyright (C) 2001-2010 Wormux Team - * Copyright (C) 2010-2012 The Mana Developers + * Clipboard Interaction. + * Copyright (C) 2010-2024 The Mana Developers * * This file is part of The Mana Client. * @@ -19,301 +18,18 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* - * IMPORTANT! - * - * This code was taken from Wormux svn trunk at Feb 25 2010. Please don't - * make any unnecessary modifications, and try to sync up modifications - * when possible. - */ - -#ifdef _MSC_VER -# include "msvc/config.h" -#elif defined(HAVE_CONFIG_H) -# include "config.h" -#endif - -#include <SDL_syswm.h> -#include "copynpaste.h" - -#ifdef _WIN32 -bool RetrieveBuffer(std::string& text, std::string::size_type& pos) -{ - bool ret = false; - - if (!OpenClipboard(NULL)) - return false; - - HANDLE h = GetClipboardData(CF_UNICODETEXT); - if (h) - { - LPCWSTR data = (LPCWSTR)GlobalLock(h); +#include "utils/copynpaste.h" - if (data) - { - int len = WideCharToMultiByte(CP_UTF8, 0, data, -1, NULL, 0, NULL, NULL); - if (len > 0) - { - // Convert from UTF-16 to UTF-8 - void *temp = malloc(len); - if (WideCharToMultiByte(CP_UTF8, 0, data, -1, (LPSTR)temp, len, NULL, NULL)) - { - text.insert(pos, (char*)temp); - pos += len-1; - } - free(temp); - ret = true; - } - } - GlobalUnlock(h); - } - else - { - h = GetClipboardData(CF_TEXT); - - if (h) - { - const char *data = (char*)GlobalLock(h); - if (data) - { - text.insert(pos, data); - pos += strlen(data); - ret = true; - } - GlobalUnlock(h); - } - } - - CloseClipboard(); - return ret; -} -#elif defined(__APPLE__) +#include <SDL.h> -#ifdef Status -#undef Status -#endif - -#include <Carbon/Carbon.h> - -// Sorry for the very long code, all nicer OS X APIs are coded in Objective C and not C! -// Also it does very thorough error handling -bool GetDataFromPasteboard( PasteboardRef inPasteboard, char* flavorText /* out */, const int bufSize ) +bool insertFromClipboard(std::string &text, std::string::size_type &pos) { - OSStatus err = noErr; - PasteboardSyncFlags syncFlags; - ItemCount itemCount; - - syncFlags = PasteboardSynchronize( inPasteboard ); - - //require_action( syncFlags & kPasteboardModified, PasteboardOutOfSync, - // err = badPasteboardSyncErr ); - - err = PasteboardGetItemCount( inPasteboard, &itemCount ); - require_noerr( err, CantGetPasteboardItemCount ); - - for (UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++) - { - PasteboardItemID itemID; - CFArrayRef flavorTypeArray; - CFIndex flavorCount; - - err = PasteboardGetItemIdentifier( inPasteboard, itemIndex, &itemID ); - require_noerr( err, CantGetPasteboardItemIdentifier ); - - err = PasteboardCopyItemFlavors( inPasteboard, itemID, &flavorTypeArray ); - require_noerr( err, CantCopyPasteboardItemFlavors ); - - flavorCount = CFArrayGetCount( flavorTypeArray ); - - for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++) - { - CFStringRef flavorType; - CFDataRef flavorData; - CFIndex flavorDataSize; - flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex); - - // we're only interested by text... - if (UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text"))) - { - err = PasteboardCopyItemFlavorData( inPasteboard, itemID, - flavorType, &flavorData ); - require_noerr( err, CantCopyFlavorData ); - flavorDataSize = CFDataGetLength( flavorData ); - flavorDataSize = (flavorDataSize<254) ? flavorDataSize : 254; - - if (flavorDataSize+2 > bufSize) - { - fprintf(stderr, "Cannot copy clipboard, contents is too big!\n"); - return false; - } - - for (short dataIndex = 0; dataIndex <= flavorDataSize; dataIndex++) - { - char byte = *(CFDataGetBytePtr( flavorData ) + dataIndex); - flavorText[dataIndex] = byte; - } - - flavorText[flavorDataSize] = '\0'; - flavorText[flavorDataSize+1] = '\n'; - - CFRelease (flavorData); - return true; - } - - continue; - CantCopyFlavorData: fprintf(stderr, "Cannot copy clipboard, CantCopyFlavorData!\n"); - } - - CFRelease (flavorTypeArray); - continue; - - CantCopyPasteboardItemFlavors: fprintf(stderr, "Cannot copy clipboard, CantCopyPasteboardItemFlavors!\n"); continue; - CantGetPasteboardItemIdentifier: fprintf(stderr, "Cannot copy clipboard, CantGetPasteboardItemIdentifier!\n"); continue; - } - fprintf(stderr, "Cannot copy clipboard, found no acceptable flavour!\n"); - return false; - - CantGetPasteboardItemCount: fprintf(stderr, "Cannot copy clipboard, CantGetPasteboardItemCount!\n"); return false; - //PasteboardOutOfSync: fprintf(stderr, "Cannot copy clipboard, PasteboardOutOfSync!\n"); return false; -} - -bool getClipBoard(char* text /* out */, const int bufSize ) -{ - OSStatus err = noErr; - - PasteboardRef theClipboard; - err = PasteboardCreate( kPasteboardClipboard, &theClipboard ); - require_noerr( err, PasteboardCreateFailed ); - - if (!GetDataFromPasteboard(theClipboard, text, bufSize)) - { - fprintf(stderr, "Cannot copy clipboard, GetDataFromPasteboardFailed!\n"); - return false; - } - - CFRelease(theClipboard); - - return true; - - // ---- error handling - PasteboardCreateFailed: fprintf(stderr, "Cannot copy clipboard, PasteboardCreateFailed!\n"); - CFRelease(theClipboard); - return false; -} - -bool RetrieveBuffer(std::string& text, std::string::size_type& pos) -{ - const int bufSize = 512; - char buffer[bufSize]; - - if (getClipBoard(buffer, bufSize)) - { - text = buffer; - pos += strlen(buffer); - return true; - } - else - { - return false; - } -} - -#elif USE_X11 -static char* getSelection(Display *dpy, Window us, Atom selection) -{ - int max_events = 50; - Window owner = XGetSelectionOwner (dpy, selection); - int ret; - - //printf("XConvertSelection on %s\n", XGetAtomName(dpy, selection)); - if (owner == None) - { - //printf("No owner\n"); - return NULL; - } - XConvertSelection(dpy, selection, XA_STRING, XA_PRIMARY, us, CurrentTime); - XFlush(dpy); - - while (max_events--) - { - XEvent e; - - XNextEvent(dpy, &e); - if(e.type == SelectionNotify) - { - //printf("Received %s\n", XGetAtomName(dpy, e.xselection.selection)); - if(e.xselection.property == None) - { - //printf("Couldn't convert\n"); - return NULL; - } - - long unsigned len, left, dummy; - int format; - Atom type; - unsigned char *data = NULL; - - XGetWindowProperty(dpy, us, e.xselection.property, 0, 0, False, - AnyPropertyType, &type, &format, &len, &left, &data); - if (left < 1) - return NULL; - - ret = XGetWindowProperty(dpy, us, e.xselection.property, 0, left, False, - AnyPropertyType, &type, &format, &len, &dummy, &data); - if (ret != Success) - { - //printf("Failed to get property: %p on %lu\n", data, len); - return NULL; - } - - //printf(">>> Got %s: len=%lu left=%lu (event %i)\n", data, len, left, 50-max_events); - return (char*)data; - } - } - return NULL; -} - -bool RetrieveBuffer(std::string& text, std::string::size_type& pos) -{ - SDL_SysWMinfo info; - - //printf("Retrieving buffer...\n"); - SDL_VERSION(&info.version); - if ( SDL_GetWMInfo(&info) ) - { - Display *dpy = info.info.x11.display; - Window us = info.info.x11.window; - char *data = NULL; - - if (!data) - { - data = getSelection(dpy, us, XA_PRIMARY); - } - if (!data) - { - data = getSelection(dpy, us, XA_SECONDARY); - } - if (!data) - { - Atom XA_CLIPBOARD = XInternAtom(dpy, "CLIPBOARD", 0); - data = getSelection(dpy, us, XA_CLIPBOARD); - } - if (data) - { - // check cursor position - if (pos > text.size()) { - pos = text.size(); - } - - text.insert(pos, data); - pos += strlen(data); - XFree(data); - - return true; - } - } - return false; + char *buf = SDL_GetClipboardText(); + const size_t len = strlen(buf); + if (len > 0) { + text.insert(pos, buf); + pos += len; + } + SDL_free(buf); + return len > 0; } -#else -bool RetrieveBuffer(std::string&, std::string::size_type&) { return false; } -#endif diff --git a/src/utils/copynpaste.h b/src/utils/copynpaste.h index c2430e1c..b6aa0de0 100644 --- a/src/utils/copynpaste.h +++ b/src/utils/copynpaste.h @@ -1,7 +1,6 @@ /* - * Retrieve string pasted depending on OS mechanisms. - * Copyright (C) 2001-2010 Wormux Team - * Copyright (C) 2010-2012 The Mana Developers + * Clipboard Interaction. + * Copyright (C) 2010-2024 The Mana Developers * * This file is part of The Mana Client. * @@ -25,10 +24,7 @@ * Attempts to retrieve text from the clipboard buffer and inserts it in * \a text at position \pos. The characters are encoded in utf-8. * - * Implemented for Windows, X11 and Mac OS X. - * * @return <code>true</code> when successful or <code>false</code> when there * was a problem retrieving the clipboard buffer. */ -bool RetrieveBuffer(std::string& text, std::string::size_type& pos); - +bool insertFromClipboard(std::string &text, std::string::size_type &pos); diff --git a/src/utils/dtor.h b/src/utils/dtor.h index 223b73ed..76c68725 100644 --- a/src/utils/dtor.h +++ b/src/utils/dtor.h @@ -23,18 +23,16 @@ #define UTILS_DTOR_H #include <algorithm> -#include <functional> #include <utility> template<typename T> -struct dtor : public std::unary_function <T, void> +struct dtor { void operator()(T &ptr) { delete ptr; } }; template<typename T1, typename T2> -struct dtor<std::pair<T1, T2> > : -public std::unary_function <std::pair<T1, T2>, void> +struct dtor<std::pair<T1, T2>> { void operator()(std::pair<T1, T2> &pair) { delete pair.second; } }; diff --git a/src/utils/mutex.h b/src/utils/mutex.h index f7f26233..d0120cfa 100644 --- a/src/utils/mutex.h +++ b/src/utils/mutex.h @@ -53,9 +53,7 @@ class MutexLocker { public: MutexLocker(Mutex *mutex); -#ifdef ENABLE_CPP0X MutexLocker(MutexLocker&&); -#endif ~MutexLocker(); private: @@ -95,13 +93,11 @@ inline MutexLocker::MutexLocker(Mutex *mutex): mMutex->lock(); } -#ifdef ENABLE_CPP0X inline MutexLocker::MutexLocker(MutexLocker&& rhs): mMutex(rhs.mMutex) { rhs.mMutex = NULL; } -#endif inline MutexLocker::~MutexLocker() { diff --git a/src/utils/physfsrwops.h b/src/utils/physfsrwops.h index 406fba6f..8008b224 100644 --- a/src/utils/physfsrwops.h +++ b/src/utils/physfsrwops.h @@ -40,7 +40,7 @@ extern "C" { * @return A valid SDL_RWops structure on success, NULL on error. Specifics * of the error can be gleaned from PHYSFS_getLastError(). */ -__EXPORT__ SDL_RWops *PHYSFSRWOPS_openRead(const char *fname); +SDL_RWops *PHYSFSRWOPS_openRead(const char *fname); /** * Open a platform-independent filename for writing, and make it accessible @@ -52,7 +52,7 @@ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openRead(const char *fname); * @return A valid SDL_RWops structure on success, NULL on error. Specifics * of the error can be gleaned from PHYSFS_getLastError(). */ -__EXPORT__ SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname); +SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname); /** * Open a platform-independent filename for appending, and make it accessible @@ -64,7 +64,7 @@ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname); * @return A valid SDL_RWops structure on success, NULL on error. Specifics * of the error can be gleaned from PHYSFS_getLastError(). */ -__EXPORT__ SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname); +SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname); /** * Make a SDL_RWops from an existing PhysicsFS file handle. You should @@ -76,7 +76,7 @@ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname); * @return A valid SDL_RWops structure on success, NULL on error. Specifics * of the error can be gleaned from PHYSFS_getLastError(). */ -__EXPORT__ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle); +SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle); #ifdef __cplusplus } @@ -85,4 +85,3 @@ __EXPORT__ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle); #endif /* include-once blocker */ /* end of physfsrwops.h ... */ - diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp index 4f27d41b..05f1bf7b 100644 --- a/src/utils/stringutils.cpp +++ b/src/utils/stringutils.cpp @@ -136,7 +136,7 @@ int compareStrI(const std::string &a, const std::string &b) std::string::const_iterator itB = b.begin(); std::string::const_iterator endB = b.end(); - for (; itA < endA, itB < endB; ++itA, ++itB) + for (; itA < endA && itB < endB; ++itA, ++itB) { int comp = tolower(*itA) - tolower(*itB); if (comp) diff --git a/src/vector.h b/src/vector.h index d181f938..25f6c120 100644 --- a/src/vector.h +++ b/src/vector.h @@ -60,6 +60,14 @@ class Vector return x == 0.0f && y == 0.0f && z == 0.0f; } + Vector &operator=(const Vector &v) + { + x = v.x; + y = v.y; + z = v.z; + return *this; + } + /** * Scale vector operator. */ |