diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..0a2159be3
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,62 @@
+language: cpp
+
+before_install:
+ #new boost
+ - sudo add-apt-repository --yes ppa:boost-latest/ppa
+ #new GCC
+ - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
+ #new Clang
+ - sudo add-apt-repository --yes ppa:h-rayflood/llvm
+ #new SDL2
+ - sudo add-apt-repository --yes ppa:zoogie/sdl2-snapshots
+ #new Qt
+ - sudo add-apt-repository --yes ppa:beineri/opt-qt531
+ #new FFmpeg
+ - sudo add-apt-repository --yes ppa:djcj/vlc-stable
+
+ - sudo apt-get update -qq
+
+ - sudo apt-get install -qq $SUPPORT
+ - sudo apt-get install -qq $PACKAGE
+ - sudo apt-get install -qq cmake yasm libboost1.55-all-dev zlib1g-dev
+ - sudo apt-get install -qq libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev
+ - sudo apt-get install -qq libavformat-dev libswscale-dev
+ - sudo apt-get install -qq qt53declarative
+
+ #setup compiler
+ - source /opt/qt53/bin/qt53-env.sh
+ - export CC=${REAL_CC} CXX=${REAL_CXX}
+
+before_script:
+ - mkdir build
+ - cd build
+ - cmake ..
+
+script:
+ - make
+
+env:
+ - ignore=this
+
+matrix:
+ exclude:
+ - env: ignore=this
+ include:
+ - compiler: clang
+ env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8
+ - compiler: clang
+ env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8
+ - compiler: clang
+ env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8
+ - compiler: gcc
+ env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT=
+ - compiler: gcc
+ env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT=
+
+notifications:
+ email:
+ recipients:
+ - vcmi.fail@mixaill.tk
+ - saven.ivan@gmail.com
+ on_success: change
+ on_failure: always
diff --git a/AI/BattleAI/BattleAI.cbp b/AI/BattleAI/BattleAI.cbp
index 4e89e3f01..990a0d760 100644
--- a/AI/BattleAI/BattleAI.cbp
+++ b/AI/BattleAI/BattleAI.cbp
@@ -6,7 +6,8 @@
-
+
+
@@ -15,7 +16,31 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AI/BattleAI/CMakeLists.txt b/AI/BattleAI/CMakeLists.txt
index 63ddc505c..c380e15d6 100644
--- a/AI/BattleAI/CMakeLists.txt
+++ b/AI/BattleAI/CMakeLists.txt
@@ -16,6 +16,6 @@ set_target_properties(BattleAI PROPERTIES ${PCH_PROPERTIES})
cotire(BattleAI)
if (NOT APPLE) # Already inside vcmiclient bundle
- install(TARGETS BattleAI DESTINATION ${AI_LIB_DIR})
+ install(TARGETS BattleAI RUNTIME DESTINATION ${AI_LIB_DIR} LIBRARY DESTINATION ${AI_LIB_DIR})
endif()
diff --git a/AI/EmptyAI/CMakeLists.txt b/AI/EmptyAI/CMakeLists.txt
index c7a40ec70..e7f7df371 100644
--- a/AI/EmptyAI/CMakeLists.txt
+++ b/AI/EmptyAI/CMakeLists.txt
@@ -12,5 +12,5 @@ add_library(EmptyAI SHARED ${emptyAI_SRCS})
target_link_libraries(EmptyAI vcmi)
if (NOT APPLE) # Already inside vcmiclient bundle
- install(TARGETS EmptyAI DESTINATION ${AI_LIB_DIR})
+ install(TARGETS EmptyAI RUNTIME DESTINATION ${AI_LIB_DIR} LIBRARY DESTINATION ${AI_LIB_DIR})
endif()
diff --git a/AI/EmptyAI/EmptyAI.cbp b/AI/EmptyAI/EmptyAI.cbp
index 26df768d8..17c6e0b38 100644
--- a/AI/EmptyAI/EmptyAI.cbp
+++ b/AI/EmptyAI/EmptyAI.cbp
@@ -6,7 +6,8 @@
-
+
+
@@ -15,7 +16,32 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AI/FuzzyLite/CMakeLists.txt b/AI/FuzzyLite/CMakeLists.txt
index b0164a945..7eca472db 100644
--- a/AI/FuzzyLite/CMakeLists.txt
+++ b/AI/FuzzyLite/CMakeLists.txt
@@ -50,4 +50,6 @@ add_library(FuzzyLite_lib STATIC ${FuzzyLite_lib_SRCS})
# all symobls from FuzzyLite exposed to public. This triggers errors
# when library is checked by analizers for issues
# Correct solution is either make FuzzyLite symbols hidden or turn lib into dynamic
-SET_TARGET_PROPERTIES(FuzzyLite_lib PROPERTIES COMPILE_FLAGS "-fPIC")
+if(NOT WIN32)
+ SET_TARGET_PROPERTIES(FuzzyLite_lib PROPERTIES COMPILE_FLAGS "-fPIC")
+endif()
\ No newline at end of file
diff --git a/AI/FuzzyLite/FuzzyLite.cbp b/AI/FuzzyLite/FuzzyLite.cbp
index 3c5171620..dd61ad6f4 100644
--- a/AI/FuzzyLite/FuzzyLite.cbp
+++ b/AI/FuzzyLite/FuzzyLite.cbp
@@ -1,130 +1,160 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AI/StupidAI/CMakeLists.txt b/AI/StupidAI/CMakeLists.txt
index b8751ef80..ac3891678 100644
--- a/AI/StupidAI/CMakeLists.txt
+++ b/AI/StupidAI/CMakeLists.txt
@@ -16,6 +16,6 @@ set_target_properties(StupidAI PROPERTIES ${PCH_PROPERTIES})
cotire(StupidAI)
if (NOT APPLE) # Already inside vcmiclient bundle
- install(TARGETS StupidAI DESTINATION ${AI_LIB_DIR})
+ install(TARGETS StupidAI RUNTIME DESTINATION ${AI_LIB_DIR} LIBRARY DESTINATION ${AI_LIB_DIR})
endif()
diff --git a/AI/StupidAI/StupidAI.cbp b/AI/StupidAI/StupidAI.cbp
index 2f3427121..e325afc06 100644
--- a/AI/StupidAI/StupidAI.cbp
+++ b/AI/StupidAI/StupidAI.cbp
@@ -6,7 +6,8 @@
-
+
+
@@ -15,7 +16,32 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AI/VCAI/CMakeLists.txt b/AI/VCAI/CMakeLists.txt
index 71154ec60..93aed4702 100644
--- a/AI/VCAI/CMakeLists.txt
+++ b/AI/VCAI/CMakeLists.txt
@@ -19,5 +19,5 @@ set_target_properties(VCAI PROPERTIES ${PCH_PROPERTIES})
cotire(VCAI)
if (NOT APPLE) # Already inside vcmiclient bundle
- install(TARGETS VCAI DESTINATION ${AI_LIB_DIR})
+ install(TARGETS VCAI RUNTIME DESTINATION ${AI_LIB_DIR} LIBRARY DESTINATION ${AI_LIB_DIR})
endif()
diff --git a/AI/VCAI/VCAI.cbp b/AI/VCAI/VCAI.cbp
index 72be88cb7..d5b632360 100644
--- a/AI/VCAI/VCAI.cbp
+++ b/AI/VCAI/VCAI.cbp
@@ -6,7 +6,8 @@
-
+
+
@@ -18,7 +19,36 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0db0737dc..7ef744909 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_HOME_DIRECTORY}/cmake_modules)
# enable Release mode but only if it was not set
if (NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE RelWithDebInfo)
+ set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()
# VCMI version
@@ -22,6 +22,7 @@ option(ENABLE_EDITOR "Enable compilation of map editor" OFF)
option(ENABLE_LAUNCHER "Enable compilation of launcher" ON)
option(ENABLE_TEST "Enable compilation of unit tests" OFF)
option(ENABLE_PCH "Enable compilation using precompiled headers" ON)
+option(ENABLE_SDL2 "Use SDL2 for compilation instead of SDL 1.2" ON)
############################################
# Building section #
@@ -53,12 +54,72 @@ if (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=256")
endif()
+if (WIN32)
+ add_definitions(-DBOOST_THREAD_USE_LIB)
+ add_definitions(-D_WIN32_WINNT=0x0501)
+ set(SYSTEM_LIBS ${SYSTEM_LIBS} ole32 oleaut32 ws2_32 mswsock)
+
+ #check for iconv (may be needed for boost.locale)
+ include(CheckLibraryExists)
+ check_library_exists(iconv libiconv_open "" ICONV_FOUND)
+ if(ICONV_FOUND)
+ set(SYSTEM_LIBS ${SYSTEM_LIBS} iconv)
+ endif()
+
+ #delete lib prefix for dlls
+ set(CMAKE_SHARED_LIBRARY_PREFIX "")
+
+ if(MINGW)
+ get_filename_component(MINGW_BIN_PATH ${CMAKE_CXX_COMPILER} PATH )
+
+ #copy libwinpthread-*.dll, libgcc_s_*.dll and libstdc++-*.dll to VCMI location
+ set(dep_files ${dep_files} "${MINGW_BIN_PATH}/libwinpthread-*.dll")
+ set(dep_files ${dep_files} "${MINGW_BIN_PATH}/libgcc_s_*.dll")
+ set(dep_files ${dep_files} "${MINGW_BIN_PATH}/libstdc++-*.dll")
+ endif()
+endif()
+
+if(APPLE)
+ set(SYSTEM_LIBS ${SYSTEM_LIBS} libiconv.dylib)
+endif()
+
+if(NOT WIN32)
+ INCLUDE(CheckLibraryExists)
+
+ #check if some platform-specific libraries are needed for linking
+ CHECK_LIBRARY_EXISTS(rt shm_open "" HAVE_RT_LIB)
+ if(HAVE_RT_LIB)
+ set(SYSTEM_LIBS ${SYSTEM_LIBS} rt)
+ endif()
+
+ CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_DL_LIB)
+ if(HAVE_DL_LIB)
+ set(SYSTEM_LIBS ${SYSTEM_LIBS} dl)
+ endif()
+endif()
+
+set(FFmpeg_FIND_COMPONENTS AVFORMAT SWSCALE)
find_package(Boost 1.48.0 COMPONENTS program_options filesystem system thread locale REQUIRED)
-find_package(SDL REQUIRED)
-find_package(SDL_image REQUIRED)
-find_package(SDL_mixer REQUIRED)
-find_package(SDL_ttf REQUIRED)
find_package(ZLIB REQUIRED)
+find_package(FFmpeg REQUIRED)
+
+if (ENABLE_SDL2)
+ find_package(SDL2 REQUIRED)
+ find_package(SDL2_image REQUIRED)
+ find_package(SDL2_mixer REQUIRED)
+ find_package(SDL2_ttf REQUIRED)
+
+ set(SDL_INCLUDE_DIR "${SDL2_INCLUDE_DIR}")
+ set(SDL_LIBRARY "${SDL2_LIBRARY}")
+ set(SDLTTF_LIBRARY "${SDL2_TTF_LIBRARY}")
+ set(SDLIMAGE_LIBRARY "${SDL2_IMAGE_LIBRARY}")
+ set(SDLMIXER_LIBRARY "${SDL2_MIXER_LIBRARY}")
+else()
+ find_package(SDL REQUIRED)
+ find_package(SDL_image REQUIRED)
+ find_package(SDL_mixer REQUIRED)
+ find_package(SDL_ttf REQUIRED)
+endif()
include(cotire)
if (ENABLE_EDITOR OR ENABLE_LAUNCHER)
@@ -71,38 +132,16 @@ if (ENABLE_LAUNCHER)
endif()
if(ENABLE_TEST)
- # find_package overwrites BOOST_* variables which are already set, so all components have to be
- # included again
- find_package(Boost 1.48.0 COMPONENTS program_options filesystem system thread locale unit_test_framework REQUIRED)
-endif()
-
-if(APPLE)
- set(Boost_LIBRARIES ${Boost_LIBRARIES} libiconv.dylib) # Our prebuilt boost_locale for OS X depends on iconv
-endif()
-
-if(NOT WIN32)
- set(FFmpeg_FIND_COMPONENTS AVFORMAT SWSCALE)
- find_package(FFmpeg REQUIRED)
-
- INCLUDE(CheckLibraryExists)
-
- #check if some platform-specific libraries are needed for linking
- CHECK_LIBRARY_EXISTS(rt shm_open "" HAVE_RT_LIB)
- if(HAVE_RT_LIB)
- set(RT_LIB -lrt)
- endif()
-
- CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_DL_LIB)
- if(HAVE_DL_LIB)
- set(DL_LIB -ldl)
- endif()
+ # find_package overwrites BOOST_* variables which are already set, so all components have to be included again
+ find_package(Boost 1.48.0 COMPONENTS program_options filesystem system thread locale unit_test_framework REQUIRED)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR NOT WIN32) #so far all *nix compilers support such parameters
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
- set(CLANG_SPECIFIC_FLAGS "-Wno-mismatched-tags")
+ set(CLANG_SPECIFIC_FLAGS "-Wno-mismatched-tags -Wno-unknown-warning-option")
endif()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wextra -Wpointer-arith -Wno-switch -Wno-sign-compare -Wno-unused-parameter -Wuninitialized -Wno-overloaded-virtual ${CLANG_SPECIFIC_FLAGS}")
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wextra -Wpointer-arith -Wno-strict-aliasing -Wno-switch -Wno-sign-compare -Wno-unused-local-typedefs -Wno-unused-parameter -Wuninitialized -Wno-overloaded-virtual -Wno-type-limits ${CLANG_SPECIFIC_FLAGS}")
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
@@ -111,9 +150,9 @@ if(CMAKE_COMPILER_IS_GNUCXX OR NOT WIN32) #so far all *nix compilers support suc
endif()
if(WIN32) # on Win everything goes into H3 root directory
- set(BIN_DIR "" CACHE STRING "Where to install binaries")
- set(LIB_DIR "" CACHE STRING "Where to install main library")
- set(DATA_DIR "" CACHE STRING "Where to install data files")
+ set(BIN_DIR "." CACHE STRING "Where to install binaries")
+ set(LIB_DIR "." CACHE STRING "Where to install main library")
+ set(DATA_DIR "." CACHE STRING "Where to install data files")
elseif(APPLE)
# includes lib path which determines where to install shared libraries (either /lib or /lib64)
include(GNUInstallDirs)
@@ -126,7 +165,7 @@ else()
include(GNUInstallDirs)
if (NOT BIN_DIR)
- set(BIN_DIR "bin" CACHE STRING "Where to install binaries")
+ set(BIN_DIR "bin" CACHE STRING "Where to install binaries")
endif()
if (NOT LIB_DIR)
set(LIB_DIR "${CMAKE_INSTALL_LIBDIR}/vcmi" CACHE STRING "Where to install main library")
@@ -155,7 +194,7 @@ SET(PCH_PROPERTIES
)
if (ENABLE_ERM)
- add_subdirectory(scripting/erm)
+ add_subdirectory(scripting/erm)
endif()
add_subdirectory(lib)
add_subdirectory(client)
@@ -193,9 +232,28 @@ if (NOT APPLE)
endif()
if(WIN32)
- #TODO: install any additional dll's. This version (may be broken) will copy all dll's including H3 ones
- #FILE(GLOB dll_files "${CMAKE_BINARY_DIR}/*.dll")
- #INSTALL(FILES ${dll_files} DESTINATION ${BIN_DIR})
+ file(GLOB dep_files
+ ${dep_files}
+ "${CMAKE_FIND_ROOT_PATH}/bin/*.dll")
+
+ if (ENABLE_EDITOR OR ENABLE_LAUNCHER)
+ get_target_property(QtCore_location Qt5::Core LOCATION)
+ get_filename_component(Qtbin_folder ${QtCore_location} PATH)
+ file(GLOB dep_files
+ ${dep_files}
+ ${Qtbin_folder}/Qt5Core.dll
+ ${Qtbin_folder}/Qt5Gui.dll
+ ${Qtbin_folder}/Qt5Widgets.dll
+ ${Qtbin_folder}/icu*.dll)
+ endif()
+
+ if (ENABLE_LAUNCHER)
+ file(GLOB dep_files
+ ${dep_files}
+ ${Qtbin_folder}/Qt5Network.dll)
+ endif()
+
+ install(FILES ${dep_files} DESTINATION ${BIN_DIR})
elseif(APPLE)
else()
#install icons and desktop file on Linux
diff --git a/Global.h b/Global.h
index def02d647..a596848cb 100644
--- a/Global.h
+++ b/Global.h
@@ -100,6 +100,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
#include
#include
#include
+#include
#include
#include
#include
@@ -116,6 +117,10 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
#include
#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
/* ---------------------------------------------------------------------------- */
/* Usings */
/* ---------------------------------------------------------------------------- */
diff --git a/client/AdventureMapClasses.cpp b/client/AdventureMapClasses.cpp
index 515a519ff..f7c01b093 100644
--- a/client/AdventureMapClasses.cpp
+++ b/client/AdventureMapClasses.cpp
@@ -177,7 +177,7 @@ CHeroList::CEmptyHeroItem::CEmptyHeroItem()
auto mana = new CAnimImage("IMANA", 0, 0, move->pos.w + img->pos.w + 2, 1 );
pos.w = mana->pos.w + mana->pos.x - pos.x;
- pos.h = std::max(std::max(move->pos.h + 1, mana->pos.h + 1), img->pos.h);
+ pos.h = std::max(std::max(move->pos.h + 1, mana->pos.h + 1), img->pos.h);
}
CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero):
@@ -190,7 +190,7 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero):
mana = new CAnimImage("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
pos.w = mana->pos.w + mana->pos.x - pos.x;
- pos.h = std::max(std::max(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
+ pos.h = std::max(std::max(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
update();
}
diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp
index d98364a3d..b0db7a16c 100644
--- a/client/CAdvmapInterface.cpp
+++ b/client/CAdvmapInterface.cpp
@@ -294,7 +294,7 @@ void CResDataBar::clickRight(tribool down, bool previousState)
CResDataBar::CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist)
{
bg = BitmapHandler::loadBitmap(defname);
- SDL_SetColorKey(bg,SDL_SRCCOLORKEY,SDL_MapRGB(bg->format,0,255,255));
+ CSDL_Ext::setDefaultColorKey(bg);
graphics->blueToPlayersAdv(bg,LOCPLINT->playerID);
pos = genRect(bg->h, bg->w, pos.x+x, pos.y+y);
@@ -313,7 +313,7 @@ CResDataBar::CResDataBar(const std::string &defname, int x, int y, int offx, int
CResDataBar::CResDataBar()
{
bg = BitmapHandler::loadBitmap(ADVOPT.resdatabarG);
- SDL_SetColorKey(bg,SDL_SRCCOLORKEY,SDL_MapRGB(bg->format,0,255,255));
+ CSDL_Ext::setDefaultColorKey(bg);
graphics->blueToPlayersAdv(bg,LOCPLINT->playerID);
pos = genRect(bg->h,bg->w,ADVOPT.resdatabarX,ADVOPT.resdatabarY);
@@ -723,9 +723,8 @@ void CAdvMapInt::show(SDL_Surface * to)
if((animValHitCount % (4/scrollSpeed)) == 0
&& (
(GH.topInt() == this)
- || SDL_GetKeyState(nullptr)[SDLK_LCTRL]
- || SDL_GetKeyState(nullptr)[SDLK_RCTRL]
-)
+ || isCtrlKeyDown()
+ )
)
{
if( (scrollingDir & LEFT) && (position.x>-CGI->mh->frameW) )
@@ -921,8 +920,12 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
//numpad arrow
if(CGuiHandler::isArrowKey(SDLKey(k)))
k = CGuiHandler::arrowToNum(SDLKey(k));
-
+
+ #ifdef VCMI_SDL1
k -= SDLK_KP0 + 1;
+ #else
+ k -= SDLK_KP_1;
+ #endif // VCMI_SDL1
if(k < 0 || k > 8)
return;
@@ -1041,7 +1044,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
{
//adventure map scrolling with mouse
- if(!SDL_GetKeyState(nullptr)[SDLK_LCTRL] && isActive())
+ if(!isCtrlKeyDown() && isActive())
{
if(sEvent.x<15)
{
diff --git a/client/CAnimation.cpp b/client/CAnimation.cpp
index 3dcf75b71..74ce7e13e 100644
--- a/client/CAnimation.cpp
+++ b/client/CAnimation.cpp
@@ -157,7 +157,7 @@ CDefFile::CDefFile(std::string Name):
palette[i].r = data[it++];
palette[i].g = data[it++];
palette[i].b = data[it++];
- palette[i].unused = 255;
+ CSDL_Ext::colorSetAlpha(palette[i],255);
}
if (type == 71 || type == 64)//Buttons/buildings don't have shadows\semi-transparency
memset(palette, 0, sizeof(SDL_Color)*2);
@@ -356,7 +356,6 @@ void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_C
//Prepare surface
SDL_SetColors(image->surf, pal, 0, 256);
SDL_LockSurface(image->surf);
-
lineStart = position = (ui8*)image->surf->pixels;
}
@@ -444,8 +443,14 @@ inline ui8 CompImageLoader::typeOf(ui8 color)
{
if (color == 0)
return 0;
+ #ifdef VCMI_SDL1
if (image->palette[color].unused != 255)
return 1;
+ #else
+ if (image->palette[color].a != 255)
+ return 1;
+ #endif // 0
+
return 2;
}
@@ -622,6 +627,7 @@ SDLImage::SDLImage(std::string filename, bool compressed):
{
SDL_Surface *temp = surf;
// add RLE flag
+ #ifdef VCMI_SDL1
if (surf->format->palette)
{
const SDL_Color &c = temp->format->palette->colors[0];
@@ -630,6 +636,13 @@ SDLImage::SDLImage(std::string filename, bool compressed):
}
else
SDL_SetColorKey(temp, SDL_RLEACCEL, 0);
+ #else
+ if (surf->format->palette)
+ {
+ CSDL_Ext::setColorKey(temp,temp->format->palette->colors[0]);
+ }
+ SDL_SetSurfaceRLE(temp, SDL_RLEACCEL);
+ #endif
// convert surface to enable RLE
surf = SDL_ConvertSurface(temp, temp->format, temp->flags);
@@ -797,13 +810,21 @@ void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha)
for (size_t i=0; i::PutColorAlpha(dest, col);
}
return;
}
-
+
+ #ifdef VCMI_SDL1
if (palette[color].unused == 255)
+ #else
+ if (palette[color].a == 255)
+ #endif // 0
{
//Put row of RGB data
for (size_t i=0; i::PutColorAlpha(dest, col);
return;
- }
+ }
switch (palette[type].unused)
+
+ #else
+ if (alpha != 255 && palette[type].a !=0)//Per-surface alpha is set
+ {
+ SDL_Color col = palette[type];
+ col.a = (int)col.a*(255-alpha)/255;
+ for (size_t i=0; i::PutColorAlpha(dest, col);
+ return;
+ }
+
+ switch (palette[type].a)
+ #endif // 0
{
case 0:
{
@@ -870,10 +905,7 @@ void CompImage::playerColored(PlayerColor player)
for(int i=0; i<32; ++i)
{
- palette[224+i].r = pal[i].r;
- palette[224+i].g = pal[i].g;
- palette[224+i].b = pal[i].b;
- palette[224+i].unused = pal[i].unused;
+ CSDL_Ext::colorAssign(palette[224+i],pal[i]);
}
}
diff --git a/client/CBitmapHandler.cpp b/client/CBitmapHandler.cpp
index 7ac2f53a4..cdd5582fa 100644
--- a/client/CBitmapHandler.cpp
+++ b/client/CBitmapHandler.cpp
@@ -70,7 +70,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
tp.r = pcx[it++];
tp.g = pcx[it++];
tp.b = pcx[it++];
- tp.unused = SDL_ALPHA_OPAQUE;
+ CSDL_Ext::colorSetAlpha(tp,SDL_ALPHA_OPAQUE);
ret->format->palette->colors[i] = tp;
}
}
@@ -121,8 +121,7 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
{
if(ret->format->BytesPerPixel == 1 && setKey)
{
- const SDL_Color &c = ret->format->palette->colors[0];
- SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format, c.r, c.g, c.b));
+ CSDL_Ext::setColorKey(ret,ret->format->palette->colors[0]);
}
}
else
@@ -142,8 +141,8 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
if (ret->format->palette)
{
//set correct value for alpha\unused channel
- for (int i=0; i< ret->format->palette->ncolors; i++)
- ret->format->palette->colors[i].unused = 255;
+ for (int i=0; i < ret->format->palette->ncolors; i++)
+ CSDL_Ext::colorSetAlpha(ret->format->palette->colors[i],SDL_ALPHA_OPAQUE);
}
}
else
@@ -154,23 +153,17 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
}
}
- // When modifyin anything here please check two use cases:
+ // When modifying anything here please check two use cases:
// 1) Vampire mansion in Necropolis (not 1st color is transparent)
// 2) Battle background when fighting on grass/dirt, topmost sky part (NO transparent color)
// 3) New objects that may use 24-bit images for icons (e.g. witchking arts)
- auto colorID = SDL_MapRGB(ret->format, 0, 255, 255);
-
if (ret->format->palette)
{
- auto & color = ret->format->palette->colors[colorID];
-
- // set color key only if exactly such color was found
- if (color.r == 0 && color.g == 255 && color.b == 255)
- SDL_SetColorKey(ret, SDL_SRCCOLORKEY, colorID);
+ CSDL_Ext::setDefaultColorKeyPresize(ret);
}
else // always set
{
- SDL_SetColorKey(ret, SDL_SRCCOLORKEY, colorID);
+ CSDL_Ext::setDefaultColorKey(ret);
}
return ret;
}
diff --git a/client/CDefHandler.cpp b/client/CDefHandler.cpp
index 0d88266ad..33deb5343 100644
--- a/client/CDefHandler.cpp
+++ b/client/CDefHandler.cpp
@@ -5,7 +5,7 @@
#include "../lib/filesystem/Filesystem.h"
#include "../lib/VCMI_Lib.h"
#include "CBitmapHandler.h"
-
+#include "gui/SDL_Extensions.h"
/*
* CDefHandler.cpp, part of VCMI engine
*
@@ -67,7 +67,7 @@ void CDefHandler::openFromMemory(ui8 *table, const std::string & name)
palette[it].r = de.palette[it].R;
palette[it].g = de.palette[it].G;
palette[it].b = de.palette[it].B;
- palette[it].unused = 255;
+ CSDL_Ext::colorSetAlpha(palette[it],SDL_ALPHA_OPAQUE);
}
// The SDefEntryBlock starts just after the SDefEntry
@@ -169,19 +169,35 @@ SDL_Surface * CDefHandler::getSprite (int SIndex, const ui8 * FDef, const SDL_Co
add=0;
ret = SDL_CreateRGBSurface(SDL_SWSURFACE, FullWidth, FullHeight, 8, 0, 0, 0, 0);
+
+ if(nullptr == ret)
+ {
+ logGlobal->errorStream() << __FUNCTION__ <<": Unable to create surface";
+ logGlobal->errorStream() << FullWidth << "X" << FullHeight;
+ logGlobal->errorStream() << SDL_GetError();
+ throw std::runtime_error("Unable to create surface");
+ }
BaseOffset += sizeof(SSpriteDef);
int BaseOffsetor = BaseOffset;
+ #ifdef VCMI_SDL1
for(int i=0; i<256; ++i)
- {
+ {
SDL_Color pr;
pr.r = palette[i].r;
pr.g = palette[i].g;
pr.b = palette[i].b;
pr.unused = palette[i].unused;
- (*(ret->format->palette->colors+i))=pr;
+ (*(ret->format->palette->colors+i))=pr;
}
+ #else
+ if(SDL_SetPaletteColors(ret->format->palette,palette,0,256) != 0)
+ {
+ throw std::runtime_error("Unable to set palette");
+ }
+
+ #endif
int ftcp=0;
@@ -347,8 +363,14 @@ SDL_Surface * CDefHandler::getSprite (int SIndex, const ui8 * FDef, const SDL_Co
}
SDL_Color ttcol = ret->format->palette->colors[0];
- Uint32 keycol = SDL_MapRGBA(ret->format, ttcol.r, ttcol.b, ttcol.g, ttcol.unused);
- SDL_SetColorKey(ret, SDL_SRCCOLORKEY, keycol);
+ #ifdef VCMI_SDL1
+ Uint32 keycol = SDL_MapRGBA(ret->format, ttcol.r, ttcol.b, ttcol.g, ttcol.unused);
+ SDL_SetColorKey(ret, SDL_SRCCOLORKEY, keycol);
+ #else
+ Uint32 keycol = SDL_MapRGBA(ret->format, ttcol.r, ttcol.b, ttcol.g, ttcol.a);
+ SDL_SetColorKey(ret, SDL_TRUE, keycol);
+ #endif // 0
+
return ret;
}
diff --git a/client/CMT.cpp b/client/CMT.cpp
index 6fed20903..11beac7bb 100644
--- a/client/CMT.cpp
+++ b/client/CMT.cpp
@@ -66,11 +66,21 @@ std::string NAME_AFFIX = "client";
std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + NAME_AFFIX + ')'; //application name
CGuiHandler GH;
static CClient *client=nullptr;
+
+#ifndef VCMI_SDL1
+int preferredDriverIndex = -1;
+SDL_Window * mainWindow = nullptr;
+SDL_Renderer * mainRenderer = nullptr;
+SDL_Texture * screenTexture = nullptr;
+
+#endif // VCMI_SDL1
+
+extern boost::thread_specific_ptr inGuiThread;
+
SDL_Surface *screen = nullptr, //main screen surface
*screen2 = nullptr,//and hlp surface (used to store not-active interfaces layer)
*screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
-static boost::thread *mainGUIThread;
-
+
std::queue events;
boost::mutex eventsM;
@@ -84,7 +94,7 @@ void processCommand(const std::string &message);
static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo=true);
void dispose();
void playIntro();
-static void listenForEvents();
+static void mainLoop();
//void requestChangingResolution();
void startGame(StartInfo * options, CConnection *serv = nullptr);
void endGame();
@@ -127,28 +137,16 @@ void startGameFromFile(const std::string &fname)
void init()
{
CStopWatch tmh, pomtime;
- logGlobal->infoStream() << "\tInitializing minors: " << pomtime.getDiff();
-
- //initializing audio
- // Note: because of interface button range, volume can only be a
- // multiple of 11, from 0 to 99.
- CCS->soundh = new CSoundHandler;
- CCS->soundh->init();
- CCS->soundh->setVolume(settings["general"]["sound"].Float());
- CCS->musich = new CMusicHandler;
- CCS->musich->init();
- CCS->musich->setVolume(settings["general"]["music"].Float());
- logGlobal->infoStream()<<"\tInitializing sound: "<infoStream()<<"Initializing screen and sound handling: "<(CGI)->setFromLib();
logGlobal->infoStream()<<"Initializing VCMI_Lib: "<curh = new CCursorHandler;
graphics = new Graphics(); // should be before curh->init()
@@ -158,7 +156,7 @@ void init()
pomtime.getDiff();
graphics->loadHeroAnims();
- logGlobal->infoStream()<<"\tMain graphics: "<infoStream()<<"\tMain graphics: "<infoStream()<<"Initializing game graphics: "<("onlyAI", po::variable_value()));
}
-
+#ifdef VCMI_SDL1
//Set environment vars to make window centered. Sometimes work, sometimes not. :/
putenv((char*)"SDL_VIDEO_WINDOW_POS");
putenv((char*)"SDL_VIDEO_CENTERED=1");
+#endif
// Have effect on X11 system only (Linux).
// For whatever reason in fullscreen mode SDL takes "raw" mouse input from DGA X11 extension
@@ -335,22 +334,50 @@ int main(int argc, char** argv)
if(!gNoGUI)
{
+ #ifdef VCMI_SDL1
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO))
+ #else
+ if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO|SDL_INIT_NOPARACHUTE))
+ #endif
{
logGlobal->errorStream()<<"Something was wrong: "<< SDL_GetError();
exit(-1);
}
GH.mainFPSmng->init(); //(!)init here AFTER SDL_Init() while using SDL for FPS management
atexit(SDL_Quit);
+
+ #ifndef VCMI_SDL1
+ int driversCount = SDL_GetNumRenderDrivers();
+ std::string preferredDriverName = video["driver"].String();
+
+ logGlobal->infoStream() << "Found " << driversCount << " render drivers";
+
+ for(int it = 0; it < driversCount; it++)
+ {
+ SDL_RendererInfo info;
+ SDL_GetRenderDriverInfo(it,&info);
+
+ std::string driverName(info.name);
+
+
+ logGlobal->infoStream() << "\t" << driverName;
+
+ if(!preferredDriverName.empty() && driverName == preferredDriverName)
+ {
+ preferredDriverIndex = it;
+ logGlobal->infoStream() << "\t\twill select this";
+ }
+ }
+ #endif // VCMI_SDL1
+
setScreenRes(res["width"].Float(), res["height"].Float(), video["bitsPerPixel"].Float(), video["fullscreen"].Bool());
logGlobal->infoStream() <<"\tInitializing screen: "<videoh = new CEmptyVideoPlayer;
#else
if (!gNoGUI && !vm.count("disable-video"))
@@ -361,13 +388,26 @@ int main(int argc, char** argv)
logGlobal->infoStream()<<"\tInitializing video: "<soundh = new CSoundHandler;
+ CCS->soundh->init();
+ CCS->soundh->setVolume(settings["general"]["sound"].Float());
+ CCS->musich = new CMusicHandler;
+ CCS->musich->init();
+ CCS->musich->setVolume(settings["general"]["music"].Float());
+ logGlobal->infoStream()<<"Initializing screen and sound handling: "<infoStream()<<"Initialization of VCMI (together): "<= mode.w && h >= mode.h)) {
+ return true;
+ }
+ }
+ return false;
+ #else
+ bpp = SDL_VideoModeOK(w, h, bpp, SDL_SWSURFACE|(fullscreen?SDL_FULLSCREEN:0));
+ return !(bpp==0);
+ #endif // VCMI_SDL1
+}
+
+#ifndef VCMI_SDL1
+static bool recreateWindow(int w, int h, int bpp, bool fullscreen)
+{
+ // VCMI will only work with 2 or 4 bytes per pixel
+ vstd::amax(bpp, 16);
+ vstd::amin(bpp, 32);
+ if(bpp>16)
+ bpp = 32;
+
+ int suggestedBpp = bpp;
+
+ if(!checkVideoMode(0,w,h,suggestedBpp,fullscreen))
+ {
+ logGlobal->errorStream() << "Error: SDL says that " << w << "x" << h << " resolution is not available!";
+ return false;
+ }
+
+ bool bufOnScreen = (screenBuf == screen);
+
+ screenBuf = nullptr; //it`s a link - just nullify
+
+ if(nullptr != screen2)
+ {
+ SDL_FreeSurface(screen2);
+ screen2 = nullptr;
+ }
+
+
+ if(nullptr != screen)
+ {
+ SDL_FreeSurface(screen);
+ screen = nullptr;
+ }
+
+
+ if(nullptr != screenTexture)
+ {
+ SDL_DestroyTexture(screenTexture);
+ screenTexture = nullptr;
+ }
+
+ if(nullptr != mainRenderer)
+ {
+ SDL_DestroyRenderer(mainRenderer);
+ mainRenderer = nullptr;
+ }
+
+ if(nullptr != mainWindow)
+ {
+ SDL_DestroyWindow(mainWindow);
+ mainWindow = nullptr;
+ }
+
+
+ if(fullscreen)
+ {
+ //in full-screen mode always use desktop resolution
+ mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP);
+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+ }
+ else
+ {
+ mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED, w, h, 0);
+ }
+
+
+
+ if(nullptr == mainWindow)
+ {
+ throw std::runtime_error("Unable to create window\n");
+ }
+
+
+ //create first available renderer if preferred not set. Use no flags, so HW accelerated will be preferred but SW renderer also will possible
+ mainRenderer = SDL_CreateRenderer(mainWindow,preferredDriverIndex,0);
+
+ if(nullptr == mainRenderer)
+ {
+ throw std::runtime_error("Unable to create renderer\n");
+ }
+
+ SDL_RendererInfo info;
+ SDL_GetRendererInfo(mainRenderer,&info);
+ logGlobal->infoStream() << "Created renderer " << info.name;
+
+ SDL_RenderSetLogicalSize(mainRenderer, w, h);
+
+ SDL_RenderSetViewport(mainRenderer, nullptr);
+
+
+
+ #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
+ int bmask = 0xff000000;
+ int gmask = 0x00ff0000;
+ int rmask = 0x0000ff00;
+ int amask = 0x000000ff;
+ #else
+ int bmask = 0x000000ff;
+ int gmask = 0x0000ff00;
+ int rmask = 0x00ff0000;
+ int amask = 0xFF000000;
+ #endif
+
+ screen = SDL_CreateRGBSurface(0,w,h,bpp,rmask,gmask,bmask,amask);
+ if(nullptr == screen)
+ {
+ logGlobal->errorStream() << "Unable to create surface";
+ logGlobal->errorStream() << w << " "<< h << " "<< bpp;
+
+ logGlobal->errorStream() << SDL_GetError();
+ throw std::runtime_error("Unable to create surface");
+ }
+ //No blending for screen itself. Required for proper cursor rendering.
+ SDL_SetSurfaceBlendMode(screen, SDL_BLENDMODE_NONE);
+
+ screenTexture = SDL_CreateTexture(mainRenderer,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_STREAMING,
+ w, h);
+
+ if(nullptr == screenTexture)
+ {
+ logGlobal->errorStream() << "Unable to create screen texture";
+ logGlobal->errorStream() << SDL_GetError();
+ throw std::runtime_error("Unable to create screen texture");
+ }
+
+ screen2 = CSDL_Ext::copySurface(screen);
+
+
+ if(nullptr == screen2)
+ {
+ throw std::runtime_error("Unable to copy surface\n");
+ }
+
+ screenBuf = bufOnScreen ? screen : screen2;
+
+ SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 0);
+ SDL_RenderClear(mainRenderer);
+ SDL_RenderPresent(mainRenderer);
+
+ return true;
+}
+#endif
+
+
+
//used only once during initialization
static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo)
{
+#ifdef VCMI_SDL1
+
// VCMI will only work with 2, 3 or 4 bytes per pixel
vstd::amax(bpp, 16);
vstd::amin(bpp, 32);
@@ -831,7 +1037,15 @@ static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo
//TODO: centering game window on other platforms (or does the environment do their job correctly there?)
screenBuf = bufOnScreen ? screen : screen2;
- //setResolution = true;
+ //setResolution = true;
+
+#else
+
+ if(!recreateWindow(w,h,bpp,fullscreen))
+ {
+ throw std::runtime_error("Requested screen resolution is not available\n");
+ }
+#endif // VCMI_SDL1
}
static void fullScreenChanged()
@@ -841,8 +1055,9 @@ static void fullScreenChanged()
Settings full = settings.write["video"]["fullscreen"];
const bool toFullscreen = full->Bool();
- int bitsPerPixel = screen->format->BitsPerPixel;
-
+ auto bitsPerPixel = screen->format->BitsPerPixel;
+
+ #ifdef VCMI_SDL1
bitsPerPixel = SDL_VideoModeOK(screen->w, screen->h, bitsPerPixel, SDL_SWSURFACE|(toFullscreen?SDL_FULLSCREEN:0));
if(bitsPerPixel == 0)
{
@@ -853,82 +1068,113 @@ static void fullScreenChanged()
bool bufOnScreen = (screenBuf == screen);
screen = SDL_SetVideoMode(screen->w, screen->h, bitsPerPixel, SDL_SWSURFACE|(toFullscreen?SDL_FULLSCREEN:0));
screenBuf = bufOnScreen ? screen : screen2;
-
+
+ #else
+ auto w = screen->w;
+ auto h = screen->h;
+
+ if(!recreateWindow(w,h,bitsPerPixel,toFullscreen))
+ {
+ //will return false and report error if video mode is not supported
+ return;
+ }
+ #endif
+
GH.totalRedraw();
}
-static void listenForEvents()
+static void handleEvent(SDL_Event & ev)
+{
+ if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
+ {
+ handleQuit();
+ return;
+ }
+
+ #ifdef VCMI_SDL1
+ //FIXME: this should work even in pregame
+ else if(LOCPLINT && ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
+ #else
+ else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
+ #endif // VCMI_SDL1
+ {
+ Settings full = settings.write["video"]["fullscreen"];
+ full->Bool() = !full->Bool();
+ return;
+ }
+ else if(ev.type == SDL_USEREVENT)
+ {
+ switch(ev.user.code)
+ {
+ case RETURN_TO_MAIN_MENU:
+ {
+ endGame();
+ GH.curInt = CGPreGame::create();;
+ GH.defActionsDef = 63;
+ }
+ break;
+ case STOP_CLIENT:
+ client->endGame(false);
+ break;
+ case RESTART_GAME:
+ {
+ StartInfo si = *client->getStartInfo(true);
+ endGame();
+ startGame(&si);
+ }
+ break;
+ case PREPARE_RESTART_CAMPAIGN:
+ {
+ auto si = reinterpret_cast(ev.user.data1);
+ endGame();
+ startGame(si);
+ }
+ break;
+ case RETURN_TO_MENU_LOAD:
+ endGame();
+ CGPreGame::create();
+ GH.defActionsDef = 63;
+ CGP->update();
+ CGP->menu->switchToTab(vstd::find_pos(CGP->menu->menuNameToEntry, "load"));
+ GH.curInt = CGP;
+ break;
+ case FULLSCREEN_TOGGLED:
+ fullScreenChanged();
+ break;
+ default:
+ logGlobal->errorStream() << "Unknown user event. Code " << ev.user.code;
+ break;
+ }
+
+ return;
+ }
+ {
+ boost::unique_lock lock(eventsM);
+ events.push(ev);
+ }
+
+}
+
+
+static void mainLoop()
{
SettingsListener resChanged = settings.listen["video"]["fullscreen"];
resChanged([](const JsonNode &newState){ CGuiHandler::pushSDLEvent(SDL_USEREVENT, FULLSCREEN_TOGGLED); });
+ inGuiThread.reset(new bool(true));
+ GH.mainFPSmng->init();
+
while(1) //main SDL events loop
{
SDL_Event ev;
+
+ while(1 == SDL_PollEvent(&ev))
+ {
+ handleEvent(ev);
+ }
+
+ GH.renderFrame();
- int ret = SDL_WaitEvent(&ev);
- if (ret == 0 || (ev.type==SDL_QUIT) ||
- (ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
- {
- handleQuit();
- continue;
- }
- else if(LOCPLINT && ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
- {
- Settings full = settings.write["video"]["fullscreen"];
- full->Bool() = !full->Bool();
- continue;
- }
- else if(ev.type == SDL_USEREVENT)
- {
- switch(ev.user.code)
- {
- case RETURN_TO_MAIN_MENU:
- {
- endGame();
- GH.curInt = CGPreGame::create();;
- GH.defActionsDef = 63;
- }
- break;
- case STOP_CLIENT:
- client->endGame(false);
- break;
- case RESTART_GAME:
- {
- StartInfo si = *client->getStartInfo(true);
- endGame();
- startGame(&si);
- }
- break;
- case PREPARE_RESTART_CAMPAIGN:
- {
- auto si = reinterpret_cast(ev.user.data1);
- endGame();
- startGame(si);
- }
- break;
- case RETURN_TO_MENU_LOAD:
- endGame();
- CGPreGame::create();
- GH.defActionsDef = 63;
- CGP->update();
- CGP->menu->switchToTab(vstd::find_pos(CGP->menu->menuNameToEntry, "load"));
- GH.curInt = CGP;
- break;
- case FULLSCREEN_TOGGLED:
- fullScreenChanged();
- break;
- default:
- logGlobal->errorStream() << "Error: unknown user event. Code " << ev.user.code;
- assert(0);
- }
-
- continue;
- }
- {
- boost::unique_lock lock(eventsM);
- events.push(ev);
- }
}
}
@@ -978,15 +1224,9 @@ void handleQuit()
{
auto quitApplication = []()
{
- if(client) client->endGame();
+ if(client)
+ endGame();
- if(mainGUIThread)
- {
- GH.terminate = true;
- if(mainGUIThread->get_id() != boost::this_thread::get_id()) mainGUIThread->join();
- delete mainGUIThread;
- mainGUIThread = nullptr;
- }
delete console;
console = nullptr;
boost::this_thread::sleep(boost::posix_time::milliseconds(750));
diff --git a/client/CMT.h b/client/CMT.h
index 256e8a79b..5148a01b7 100644
--- a/client/CMT.h
+++ b/client/CMT.h
@@ -1,9 +1,20 @@
#pragma once
+#ifndef VCMI_SDL1
+#include
+
+extern SDL_Texture * screenTexture;
+
+extern SDL_Window * mainWindow;
+extern SDL_Renderer * mainRenderer;
+
+#endif // VCMI_SDL2
+
extern SDL_Surface *screen; // main screen surface
extern SDL_Surface *screen2; // and hlp surface (used to store not-active interfaces layer)
extern SDL_Surface *screenBuf; // points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
+
extern bool gNoGUI; //if true there is no client window and game is silently played between AIs
-void handleQuit();
\ No newline at end of file
+void handleQuit();
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index b963a530c..785095a27 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -7,107 +7,105 @@ include_directories(${Boost_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${FFMPEG_INCLUDE_D
set(client_SRCS
StdInc.cpp
- ../CCallback.cpp
+ ../CCallback.cpp
battle/CBattleInterface.cpp
- battle/CBattleAnimations.cpp
- battle/CBattleInterfaceClasses.cpp
- battle/CCreatureAnimation.cpp
+ battle/CBattleAnimations.cpp
+ battle/CBattleInterfaceClasses.cpp
+ battle/CCreatureAnimation.cpp
- gui/CGuiHandler.cpp
- gui/CIntObject.cpp
- gui/CIntObjectClasses.cpp
- gui/Fonts.cpp
- gui/Geometries.cpp
- gui/CCursorHandler.cpp
- gui/SDL_Extensions.cpp
+ gui/CGuiHandler.cpp
+ gui/CIntObject.cpp
+ gui/CIntObjectClasses.cpp
+ gui/Fonts.cpp
+ gui/Geometries.cpp
+ gui/CCursorHandler.cpp
+ gui/SDL_Extensions.cpp
CPreGame.cpp
Client.cpp
CPlayerInterface.cpp
CMT.cpp
GUIClasses.cpp
- AdventureMapClasses.cpp
- CAdvmapInterface.cpp
- CAnimation.cpp
- CBitmapHandler.cpp
- CCastleInterface.cpp
- CCreatureWindow.cpp
- CDefHandler.cpp
- CGameInfo.cpp
- CHeroWindow.cpp
- CKingdomInterface.cpp
- CMessage.cpp
- CMusicHandler.cpp
- CSpellWindow.cpp
- CVideoHandler.cpp
- CQuestLog.cpp
- Graphics.cpp
- mapHandler.cpp
- NetPacksClient.cpp
+ AdventureMapClasses.cpp
+ CAdvmapInterface.cpp
+ CAnimation.cpp
+ CBitmapHandler.cpp
+ CCastleInterface.cpp
+ CCreatureWindow.cpp
+ CDefHandler.cpp
+ CGameInfo.cpp
+ CHeroWindow.cpp
+ CKingdomInterface.cpp
+ CMessage.cpp
+ CMusicHandler.cpp
+ CSpellWindow.cpp
+ CVideoHandler.cpp
+ CQuestLog.cpp
+ Graphics.cpp
+ mapHandler.cpp
+ NetPacksClient.cpp
)
-set(client_HEADERS
- gui/SDL_Pixels.h
-)
+if(APPLE)
+ # OS X specific includes
+ include_directories(${SPARKLE_INCLUDE_DIR})
-if(WIN32)
- add_executable(vcmiclient WIN32 ${client_SRCS} ${client_HEADERS})
-elseif(APPLE)
- # OS X specific includes
- include_directories(${SPARKLE_INCLUDE_DIR})
-
- # OS X specific source files
- set(client_SRCS ${client_SRCS} SDLMain.m OSX.mm Info.plist vcmi.icns ../osx/vcmi_dsa_public.pem)
+ # OS X specific source files
+ set(client_SRCS ${client_SRCS} SDLMain.m OSX.mm Info.plist vcmi.icns ../osx/vcmi_dsa_public.pem)
add_executable(vcmiclient MACOSX_BUNDLE ${client_SRCS} ${client_HEADERS})
- # OS X specific libraries
- target_link_libraries(vcmiclient ${SPARKLE_FRAMEWORK})
+ # OS X specific libraries
+ target_link_libraries(vcmiclient ${SPARKLE_FRAMEWORK})
- # Because server and AI libs would be copies to bundle they need to be built before client
- add_dependencies(vcmiclient vcmiserver VCAI EmptyAI StupidAI BattleAI minizip)
+ # Because server and AI libs would be copies to bundle they need to be built before client
+ add_dependencies(vcmiclient vcmiserver VCAI EmptyAI StupidAI BattleAI minizip)
- # Custom Info.plist
- set_target_properties(vcmiclient PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist)
+ # Custom Info.plist
+ set_target_properties(vcmiclient PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist)
- # Copy icon file and public key for Sparkle
- set_source_files_properties(vcmi.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
- set_source_files_properties(../osx/vcmi_dsa_public.pem PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
+ # Copy icon file and public key for Sparkle
+ set_source_files_properties(vcmi.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
+ set_source_files_properties(../osx/vcmi_dsa_public.pem PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
- set_target_properties(vcmiclient PROPERTIES XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks @executable_path/")
+ set_target_properties(vcmiclient PROPERTIES XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks @executable_path/")
- # Copy server executable, libs and game data to bundle
- set(BUNDLE_PATH ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/vcmiclient.app/Contents)
- set(MakeVCMIBundle
- # Copy all needed binaries
- mkdir -p ${BUNDLE_PATH}/MacOS/AI &&
- cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/vcmiserver ${BUNDLE_PATH}/MacOS/vcmiserver &&
- cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libvcmi.dylib ${BUNDLE_PATH}/MacOS/libvcmi.dylib &&
- cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libminizip.dylib ${BUNDLE_PATH}/MacOS/libminizip.dylib &&
- cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libVCAI.dylib ${BUNDLE_PATH}/MacOS/AI/libVCAI.dylib &&
- cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libStupidAI.dylib ${BUNDLE_PATH}/MacOS/AI/libStupidAI.dylib &&
- cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libEmptyAI.dylib ${BUNDLE_PATH}/MacOS/AI/libEmptyAI.dylib &&
- cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libBattleAI.dylib ${BUNDLE_PATH}/MacOS/AI/libBattleAI.dylib &&
- cp -r ${CMAKE_HOME_DIRECTORY}/osx/vcmibuilder.app ${BUNDLE_PATH}/MacOS/vcmibuilder.app &&
+ # Copy server executable, libs and game data to bundle
+ set(BUNDLE_PATH ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/vcmiclient.app/Contents)
+ set(MakeVCMIBundle
+ # Copy all needed binaries
+ mkdir -p ${BUNDLE_PATH}/MacOS/AI &&
+ cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/vcmiserver ${BUNDLE_PATH}/MacOS/vcmiserver &&
+ cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libvcmi.dylib ${BUNDLE_PATH}/MacOS/libvcmi.dylib &&
+ cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libminizip.dylib ${BUNDLE_PATH}/MacOS/libminizip.dylib &&
+ cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libVCAI.dylib ${BUNDLE_PATH}/MacOS/AI/libVCAI.dylib &&
+ cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libStupidAI.dylib ${BUNDLE_PATH}/MacOS/AI/libStupidAI.dylib &&
+ cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libEmptyAI.dylib ${BUNDLE_PATH}/MacOS/AI/libEmptyAI.dylib &&
+ cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libBattleAI.dylib ${BUNDLE_PATH}/MacOS/AI/libBattleAI.dylib &&
+ cp -r ${CMAKE_HOME_DIRECTORY}/osx/vcmibuilder.app ${BUNDLE_PATH}/MacOS/vcmibuilder.app &&
- # Copy frameworks
- cp -r ${CMAKE_HOME_DIRECTORY}/${CMAKE_FRAMEWORK_PATH} ${BUNDLE_PATH}/Frameworks/ &&
+ # Copy frameworks
+ cp -r ${CMAKE_HOME_DIRECTORY}/${CMAKE_FRAMEWORK_PATH} ${BUNDLE_PATH}/Frameworks/ &&
- # Copy vcmi data
- mkdir -p ${BUNDLE_PATH}/Data &&
- mkdir -p ${BUNDLE_PATH}/Data/Mods &&
- mkdir -p ${BUNDLE_PATH}/Data/launcher &&
- cp -r ${CMAKE_HOME_DIRECTORY}/config/ ${BUNDLE_PATH}/Data/config/ &&
- cp -r ${CMAKE_HOME_DIRECTORY}/Mods/vcmi/ ${BUNDLE_PATH}/Data/Mods/vcmi/ &&
- cp -r ${CMAKE_HOME_DIRECTORY}/Mods/WoG/ ${BUNDLE_PATH}/Data/Mods/WoG/ &&
- cp -r ${CMAKE_HOME_DIRECTORY}/launcher/icons/ ${BUNDLE_PATH}/Data/launcher/icons/)
-
- add_custom_command(TARGET vcmiclient POST_BUILD COMMAND ${MakeVCMIBundle})
+ # Copy vcmi data
+ mkdir -p ${BUNDLE_PATH}/Data &&
+ mkdir -p ${BUNDLE_PATH}/Data/Mods &&
+ mkdir -p ${BUNDLE_PATH}/Data/launcher &&
+ cp -r ${CMAKE_HOME_DIRECTORY}/config/ ${BUNDLE_PATH}/Data/config/ &&
+ cp -r ${CMAKE_HOME_DIRECTORY}/Mods/vcmi/ ${BUNDLE_PATH}/Data/Mods/vcmi/ &&
+ cp -r ${CMAKE_HOME_DIRECTORY}/Mods/WoG/ ${BUNDLE_PATH}/Data/Mods/WoG/ &&
+ cp -r ${CMAKE_HOME_DIRECTORY}/launcher/icons/ ${BUNDLE_PATH}/Data/launcher/icons/)
+
+ add_custom_command(TARGET vcmiclient POST_BUILD COMMAND ${MakeVCMIBundle})
else()
- add_executable(vcmiclient ${client_SRCS} ${client_HEADERS})
+ add_executable(vcmiclient ${client_SRCS})
endif()
-target_link_libraries(vcmiclient vcmi ${Boost_LIBRARIES} ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} ${SDLMIXER_LIBRARY} ${SDLTTF_LIBRARY} ${ZLIB_LIBRARIES} ${FFMPEG_LIBRARIES} ${RT_LIB} ${DL_LIB})
+if(WIN32)
+ set_target_properties(vcmiclient PROPERTIES OUTPUT_NAME VCMI_client)
+endif()
+
+target_link_libraries(vcmiclient vcmi ${Boost_LIBRARIES} ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} ${SDLMIXER_LIBRARY} ${SDLTTF_LIBRARY} ${ZLIB_LIBRARIES} ${FFMPEG_LIBRARIES} ${SYSTEM_LIBS})
set_target_properties(vcmiclient PROPERTIES ${PCH_PROPERTIES})
cotire(vcmiclient)
diff --git a/client/CMessage.cpp b/client/CMessage.cpp
index 25a046583..b14af97bf 100644
--- a/client/CMessage.cpp
+++ b/client/CMessage.cpp
@@ -91,7 +91,7 @@ void CMessage::init()
delete bluePieces;
}
background = BitmapHandler::loadBitmap("DIBOXBCK.BMP");
- SDL_SetColorKey(background,SDL_SRCCOLORKEY,SDL_MapRGB(background->format,0,255,255));
+ CSDL_Ext::setDefaultColorKey(background);
}
ok = CDefHandler::giveDef("IOKAY.DEF");
cancel = CDefHandler::giveDef("ICANCEL.DEF");
@@ -134,7 +134,7 @@ std::vector CMessage::breakText( std::string text, size_t maxLineWi
boost::algorithm::trim_right_if(text,boost::algorithm::is_any_of(std::string(" ")));
- // each interation generates one output line
+ // each iteration generates one output line
while (text.length())
{
ui32 lineWidth = 0; //in characters or given char metric
diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp
index 94e460dee..ae583235d 100644
--- a/client/CMusicHandler.cpp
+++ b/client/CMusicHandler.cpp
@@ -481,6 +481,8 @@ void MusicEntry::load(std::string musicURI)
data = CResourceHandler::get()->load(ResourceID(musicURI, EResType::MUSIC))->readAll();
musicFile = SDL_RWFromConstMem(data.first.get(), data.second);
+
+ #ifdef VCMI_SDL1
music = Mix_LoadMUS_RW(musicFile);
if(!music)
@@ -491,10 +493,19 @@ void MusicEntry::load(std::string musicURI)
return;
}
-#ifdef _WIN32
- //The assertion will fail if old MSVC libraries pack .dll is used
- assert(Mix_GetMusicType(music) != MUS_MP3);
-#endif
+ #else
+ music = Mix_LoadMUS_RW(musicFile, SDL_FALSE);
+
+ if(!music)
+ {
+ SDL_FreeRW(musicFile);
+ musicFile = nullptr;
+ logGlobal->warnStream() << "Warning: Cannot open " << currentName << ": " << Mix_GetError();
+ return;
+ }
+
+ #endif // 0
+
}
bool MusicEntry::play()
diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp
index 5654b867e..056f0d607 100644
--- a/client/CPlayerInterface.cpp
+++ b/client/CPlayerInterface.cpp
@@ -116,6 +116,10 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player)
firstCall = 1; //if loading will be overwritten in serialize
autosaveCount = 0;
isAutoFightOn = false;
+
+ duringMovement = false;
+ ignoreEvents = false;
+ locked = false;
}
CPlayerInterface::~CPlayerInterface()
@@ -313,8 +317,16 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
movementPxStep(details, i, hp, hero);
adventureInt->updateScreen = true;
adventureInt->show(screen);
- CSDL_Ext::update(screen);
- GH.mainFPSmng->framerateDelay(); //for animation purposes
+ {
+ //evil returns here ...
+ //todo: get rid of it
+ logGlobal->traceStream() << "before [un]locks in " << __FUNCTION__;
+ auto unlockPim = vstd::makeUnlockGuard(*pim); //let frame to be rendered
+ GH.mainFPSmng->framerateDelay(); //for animation purposes
+ logGlobal->traceStream() << "after [un]locks in " << __FUNCTION__;
+ }
+ //CSDL_Ext::update(screen);
+
} //for(int i=1; i<32; i+=4)
//main moving done
@@ -1257,19 +1269,20 @@ void CPlayerInterface::loadGame( CISer &h, const int version )
firstCall = -1;
}
-bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
+void CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
{
logGlobal->traceStream() << __FUNCTION__;
if(!LOCPLINT->makingTurn)
- return false;
+ return;
if (!h)
- return false; //can't find hero
+ return; //can't find hero
//It shouldn't be possible to move hero with open dialog (or dialog waiting in bg)
if(showingDialog->get() || !dialogs.empty())
- return false;
-
+ return;
+ duringMovement = true;
+
if (adventureInt && adventureInt->isHeroSleeping(h))
{
adventureInt->sleepWake.clickLeft(true, false);
@@ -1278,103 +1291,20 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
//adventureInt->fsleepWake();
//but no authentic button click/sound ;-)
}
+
+ boost::thread moveHeroTask(boost::bind(&CPlayerInterface::doMoveHero,this,h,path));
- int i = 1;
- bool result = false; //TODO why not set to true anywhere?
- {
- //evil...
-
- logGlobal->traceStream() << "before [un]locks in " << __FUNCTION__;
- auto unlockEvents = vstd::makeUnlockGuard(eventsM);
- auto unlockGs = vstd::makeUnlockSharedGuard(cb->getGsMutex()); //GS mutex is above PIM because CClient::run thread first locks PIM and then GS -> so this way we avoid deadlocks
- auto unlockPim = vstd::makeUnlockGuard(*pim);
- logGlobal->traceStream() << "after [un]locks in " << __FUNCTION__;
- //TODO the above combination works... but it should all be atomic (unlock all three or none)
-
- {
- path.convert(0);
- boost::unique_lock un(stillMoveHero.mx);
- stillMoveHero.data = CONTINUE_MOVE;
-
- ETerrainType currentTerrain = ETerrainType::BORDER; // not init yet
- ETerrainType newTerrain;
- int sh = -1;
-
- const TerrainTile * curTile = cb->getTile(CGHeroInstance::convertPosition(h->pos, false));
-
- for(i=path.nodes.size()-1; i>0 && (stillMoveHero.data == CONTINUE_MOVE || curTile->blocked); i--)
- {
- //changing z coordinate means we're moving through subterranean gate -> it's done automatically upon the visit, so we don't have to request that move here
- if(path.nodes[i-1].coord.z != path.nodes[i].coord.z)
- continue;
-
- //stop sending move requests if the next node can't be reached at the current turn (hero exhausted his move points)
- if(path.nodes[i-1].turns)
- {
- stillMoveHero.data = STOP_MOVE;
- break;
- }
-
- // Start a new sound for the hero movement or let the existing one carry on.
-#if 0
- // TODO
- if (hero is flying && sh == -1)
- sh = CCS->soundh->playSound(soundBase::horseFlying, -1);
-#endif
- {
- newTerrain = cb->getTile(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->terType;
-
- if (newTerrain != currentTerrain)
- {
- CCS->soundh->stopSound(sh);
- sh = CCS->soundh->playSound(CCS->soundh->horseSounds[newTerrain], -1);
- currentTerrain = newTerrain;
- }
- }
-
- stillMoveHero.data = WAITING_MOVE;
-
- int3 endpos(path.nodes[i-1].coord.x, path.nodes[i-1].coord.y, h->pos.z);
- bool guarded = CGI->mh->map->isInTheMap(cb->getGuardingCreaturePosition(endpos - int3(1, 0, 0)));
-
- logGlobal->traceStream() << "Requesting hero movement to " << endpos;
- cb->moveHero(h,endpos);
-
- while(stillMoveHero.data != STOP_MOVE && stillMoveHero.data != CONTINUE_MOVE)
- stillMoveHero.cond.wait(un);
-
- logGlobal->traceStream() << "Resuming " << __FUNCTION__;
- if (guarded || showingDialog->get() == true) // Abort movement if a guard was fought or there is a dialog to display (Mantis #1136)
- break;
- }
-
- CCS->soundh->stopSound(sh);
- }
-
- //Update cursor so icon can change if needed when it reappears; doesn;'t apply if a dialog box pops up at the end of the movement
- if(!showingDialog->get())
- GH.fakeMouseMove();
-
- //RAII unlocks
- }
-
- if (adventureInt)
- {
- // (i == 0) means hero went through all the path
- adventureInt->updateMoveHero(h, (i != 0));
- adventureInt->updateNextHero(h);
- }
- return result;
+
}
bool CPlayerInterface::shiftPressed() const
{
- return SDL_GetKeyState(nullptr)[SDLK_LSHIFT] || SDL_GetKeyState(nullptr)[SDLK_RSHIFT];
+ return isShiftKeyDown();
}
bool CPlayerInterface::altPressed() const
{
- return SDL_GetKeyState(nullptr)[SDLK_LALT] || SDL_GetKeyState(nullptr)[SDLK_RALT];
+ return isAltKeyDown();
}
void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID)
@@ -1569,8 +1499,16 @@ void CPlayerInterface::centerView (int3 pos, int focusTime)
if(focusTime)
{
GH.totalRedraw();
+ #ifdef VCMI_SDL1
CSDL_Ext::update(screen);
SDL_Delay(focusTime);
+ #else
+ {
+ auto unlockPim = vstd::makeUnlockGuard(*pim);
+ IgnoreEvents ignore(*this);
+ SDL_Delay(focusTime);
+ }
+ #endif
}
}
@@ -1586,36 +1524,16 @@ void CPlayerInterface::objectRemoved( const CGObjectInstance *obj )
bool CPlayerInterface::ctrlPressed() const
{
- return SDL_GetKeyState(nullptr)[SDLK_LCTRL] || SDL_GetKeyState(nullptr)[SDLK_RCTRL];
+ return isCtrlKeyDown();
}
void CPlayerInterface::update()
{
- // Updating GUI requires locking pim mutex (that protects screen and GUI state).
- // When ending the game, the pim mutex might be hold bo other thread,
- // that will notify us about the ending game by setting terminate_cond flag.
-
- bool acquiredTheLockOnPim = false; //for tracking whether pim mutex locking succeeded
- while(!terminate_cond.get() && !(acquiredTheLockOnPim = pim->try_lock())) //try acquiring long until it succeeds or we are told to terminate
- boost::this_thread::sleep(boost::posix_time::milliseconds(15));
-
- if(!acquiredTheLockOnPim)
+ if (!locked)
{
- // We broke the while loop above and not because of mutex, so we must be terminating.
- assert(terminate_cond.get());
+ logGlobal->errorStream() << "Non synchronized update of PlayerInterface";
return;
}
-
- // If we are here, pim mutex has been successfully locked - let's store it in a safe RAII lock.
- boost::unique_lock un(*pim, boost::adopt_lock);
-
- // While mutexes were locked away we may be have stopped being the active interface
- if(LOCPLINT != this)
- return;
-
- // Make sure that gamestate won't change when GUI objects may obtain its parts on event processing or drawing request
- boost::shared_lock gsLock(cb->getGsMutex());
-
//if there are any waiting dialogs, show them
if((howManyPeople <= 1 || makingTurn) && !dialogs.empty() && !showingDialog->get())
{
@@ -1641,11 +1559,38 @@ void CPlayerInterface::update()
if (settings["general"]["showfps"].Bool())
GH.drawFPSCounter();
+}
- // draw the mouse cursor and update the screen
- CCS->curh->drawWithScreenRestore();
- CSDL_Ext::update(screen);
- CCS->curh->drawRestored();
+void CPlayerInterface::runLocked(std::function functor)
+{
+ // Updating GUI requires locking pim mutex (that protects screen and GUI state).
+ // When ending the game, the pim mutex might be hold by other thread,
+ // that will notify us about the ending game by setting terminate_cond flag.
+
+ bool acquiredTheLockOnPim = false; //for tracking whether pim mutex locking succeeded
+ while(!terminate_cond.get() && !(acquiredTheLockOnPim = pim->try_lock())) //try acquiring long until it succeeds or we are told to terminate
+ boost::this_thread::sleep(boost::posix_time::milliseconds(15));
+
+ if(!acquiredTheLockOnPim)
+ {
+ // We broke the while loop above and not because of mutex, so we must be terminating.
+ assert(terminate_cond.get());
+ return;
+ }
+
+ // If we are here, pim mutex has been successfully locked - let's store it in a safe RAII lock.
+ boost::unique_lock un(*pim, boost::adopt_lock);
+
+ // While mutexes were locked away we may be have stopped being the active interface
+ if(LOCPLINT != this)
+ return;
+
+ // Make sure that gamestate won't change when GUI objects may obtain its parts on event processing or drawing request
+ boost::shared_lock gsLock(cb->getGsMutex());
+
+ locked = true;
+ functor(this);
+ locked = false;
}
int CPlayerInterface::getLastIndex( std::string namePrefix)
@@ -2608,3 +2553,104 @@ CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
spellbookLastPageBattle = spellbokLastPageAdvmap = 0;
spellbookLastTabBattle = spellbookLastTabAdvmap = 4;
}
+
+bool CPlayerInterface::capturedAllEvents()
+{
+ if(duringMovement)
+ {
+ //just inform that we are capturing events. they will be processed by heroMoved() in client thread.
+ return true;
+ }
+
+ if(ignoreEvents)
+ {
+ boost::unique_lock un(eventsM);
+ while(!events.empty())
+ {
+ events.pop();
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void CPlayerInterface::doMoveHero(const CGHeroInstance* h, CGPath path)
+{
+ int i = 1;
+
+ {
+ path.convert(0);
+ boost::unique_lock un(stillMoveHero.mx);
+ stillMoveHero.data = CONTINUE_MOVE;
+
+ ETerrainType currentTerrain = ETerrainType::BORDER; // not init yet
+ ETerrainType newTerrain;
+ int sh = -1;
+
+ const TerrainTile * curTile = cb->getTile(CGHeroInstance::convertPosition(h->pos, false));
+
+ for(i=path.nodes.size()-1; i>0 && (stillMoveHero.data == CONTINUE_MOVE || curTile->blocked); i--)
+ {
+ //changing z coordinate means we're moving through subterranean gate -> it's done automatically upon the visit, so we don't have to request that move here
+ if(path.nodes[i-1].coord.z != path.nodes[i].coord.z)
+ continue;
+
+ //stop sending move requests if the next node can't be reached at the current turn (hero exhausted his move points)
+ if(path.nodes[i-1].turns)
+ {
+ stillMoveHero.data = STOP_MOVE;
+ break;
+ }
+
+ // Start a new sound for the hero movement or let the existing one carry on.
+#if 0
+ // TODO
+ if (hero is flying && sh == -1)
+ sh = CCS->soundh->playSound(soundBase::horseFlying, -1);
+#endif
+ {
+ newTerrain = cb->getTile(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->terType;
+
+ if (newTerrain != currentTerrain)
+ {
+ CCS->soundh->stopSound(sh);
+ sh = CCS->soundh->playSound(CCS->soundh->horseSounds[newTerrain], -1);
+ currentTerrain = newTerrain;
+ }
+ }
+
+ stillMoveHero.data = WAITING_MOVE;
+
+ int3 endpos(path.nodes[i-1].coord.x, path.nodes[i-1].coord.y, h->pos.z);
+ bool guarded = CGI->mh->map->isInTheMap(cb->getGuardingCreaturePosition(endpos - int3(1, 0, 0)));
+
+ logGlobal->traceStream() << "Requesting hero movement to " << endpos;
+ cb->moveHero(h,endpos);
+
+ while(stillMoveHero.data != STOP_MOVE && stillMoveHero.data != CONTINUE_MOVE)
+ stillMoveHero.cond.wait(un);
+
+ logGlobal->traceStream() << "Resuming " << __FUNCTION__;
+ if (guarded || showingDialog->get() == true) // Abort movement if a guard was fought or there is a dialog to display (Mantis #1136)
+ break;
+ }
+
+ CCS->soundh->stopSound(sh);
+ }
+
+ //Update cursor so icon can change if needed when it reappears; doesn;'t apply if a dialog box pops up at the end of the movement
+ if(!showingDialog->get())
+ GH.fakeMouseMove();
+
+
+ //todo: this should be in main thread
+ if (adventureInt)
+ {
+ // (i == 0) means hero went through all the path
+ adventureInt->updateMoveHero(h, (i != 0));
+ adventureInt->updateNextHero(h);
+ }
+
+ duringMovement = false;
+}
diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h
index 7c1c0baf0..fe4ad9c6e 100644
--- a/client/CPlayerInterface.h
+++ b/client/CPlayerInterface.h
@@ -83,7 +83,7 @@ enum
};
/// Central class for managing user interface logic
-class CPlayerInterface : public CGameInterface, public IUpdateable
+class CPlayerInterface : public CGameInterface, public ILockedUpdatable
{
public:
bool observerInDuelMode;
@@ -129,7 +129,8 @@ public:
}
} spellbookSettings;
- void update();
+ void update() override;
+ void runLocked(std::function functor) override;
void initializeHeroTownList();
int getLastIndex(std::string namePrefix);
@@ -239,7 +240,7 @@ public:
void showYesNoDialog(const std::string &text, CFunctionList onYes, CFunctionList onNo, bool DelComps = false, const std::vector & components = std::vector()); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
void stopMovement();
- bool moveHero(const CGHeroInstance *h, CGPath path);
+ void moveHero(const CGHeroInstance *h, CGPath path);
void initMovement(const TryMoveHero &details, const CGHeroInstance * ho, const int3 &hp );//initializing objects and performing first step of move
void movementPxStep( const TryMoveHero &details, int i, const int3 &hp, const CGHeroInstance * ho );//performing step of movement
void finishMovement( const TryMoveHero &details, const int3 &hp, const CGHeroInstance * ho ); //finish movement
@@ -254,14 +255,44 @@ public:
void sendCustomEvent(int code);
void proposeLoadingGame();
+ ///returns true if all events are processed internally
+ bool capturedAllEvents();
+
CPlayerInterface(PlayerColor Player);//c-tor
~CPlayerInterface();//d-tor
static CondSh terminate_cond; // confirm termination
+
- //////////////////////////////////////////////////////////////////////////
+
+private:
template void serializeTempl(Handler &h, const int version);
+
+private:
+
+ struct IgnoreEvents
+ {
+ CPlayerInterface & owner;
+ IgnoreEvents(CPlayerInterface & Owner):owner(Owner)
+ {
+ owner.ignoreEvents = true;
+ };
+ ~IgnoreEvents()
+ {
+ owner.ignoreEvents = false;
+ };
+
+ };
+
+
+
+ bool duringMovement;
+ bool ignoreEvents;
+
+ bool locked;
+
+ void doMoveHero(const CGHeroInstance *h, CGPath path);
};
extern CPlayerInterface * LOCPLINT;
diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp
index 68a0ce393..7ae547fc9 100644
--- a/client/CPreGame.cpp
+++ b/client/CPreGame.cpp
@@ -536,11 +536,12 @@ void CGPreGame::update()
if (settings["general"]["showfps"].Bool())
GH.drawFPSCounter();
+}
- // draw the mouse cursor and update the screen
- CCS->curh->drawWithScreenRestore();
- CSDL_Ext::update(screen);
- CCS->curh->drawRestored();
+void CGPreGame::runLocked(std::function cb)
+{
+ boost::unique_lock lock(*CPlayerInterface::pim);
+ cb(this);
}
void CGPreGame::openCampaignScreen(std::string name)
@@ -1897,7 +1898,7 @@ CChatBox::CChatBox(const Rect &rect)
{
OBJ_CONSTRUCTION;
pos += rect;
- addUsedEvents(KEYBOARD);
+ addUsedEvents(KEYBOARD | TEXTINPUT);
captureAllKeys = true;
const int height = graphics->fonts[FONT_SMALL]->getLineHeight();
@@ -4193,7 +4194,7 @@ CPrologEpilogVideo::CPrologEpilogVideo( CCampaignScenario::SScenarioPrologEpilog
void CPrologEpilogVideo::show( SDL_Surface * to )
{
- CSDL_Ext::fillRect(to, &pos, 0); // fill screen with black
+ CSDL_Ext::fillRectBlack(to, &pos);
//BUG: some videos are 800x600 in size while some are 800x400
//VCMI should center them in the middle of the screen. Possible but needs modification
//of video player API which I'd like to avoid until we'll get rid of Windows-specific player
diff --git a/client/CPreGame.h b/client/CPreGame.h
index 6dfca80ab..21a67a3ce 100644
--- a/client/CPreGame.h
+++ b/client/CPreGame.h
@@ -589,7 +589,7 @@ private:
};
/// Handles background screen, loads graphics for victory/loss condition and random town or hero selection
-class CGPreGame : public CIntObject, public IUpdateable
+class CGPreGame : public CIntObject, public ILockedUpdatable
{
void loadGraphics();
void disposeGraphics();
@@ -602,7 +602,8 @@ public:
CDefHandler *victory, *loss;
~CGPreGame();
- void update();
+ void update() override;
+ void runLocked(std::function cb) override;
void openSel(CMenuScreen::EState type, CMenuScreen::EMultiMode multi = CMenuScreen::SINGLE_PLAYER);
void openCampaignScreen(std::string name);
diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp
index ceae0d58b..84f0c18cb 100644
--- a/client/CVideoHandler.cpp
+++ b/client/CVideoHandler.cpp
@@ -9,6 +9,7 @@
extern CGuiHandler GH; //global gui handler
+#ifndef DISABLE_VIDEO
//reads events and returns true on key down
static bool keyDown()
{
@@ -20,6 +21,7 @@ static bool keyDown()
}
return false;
}
+#endif
#if defined(_WIN32) && (_MSC_VER < 1800 || !defined(USE_FFMPEG))
@@ -29,12 +31,12 @@ void checkForError(bool throwing = true)
if(!error)
return;
- logGlobal->errorStream() << "Error " << error << " encountered!";
+ logGlobal->errorStream() << "Error " << error << " encountered!";
std::string msg;
char* pTemp = nullptr;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
nullptr, error, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPSTR)&pTemp, 1, nullptr );
- logGlobal->errorStream() << "Error: " << pTemp;
+ logGlobal->errorStream() << "Error: " << pTemp;
msg = pTemp;
LocalFree( pTemp );
pTemp = nullptr;
@@ -60,7 +62,7 @@ void DLLHandler::Instantiate(const char *filename)
dll = LoadLibraryA(filename);
if(!dll)
{
- logGlobal->errorStream() << "Failed loading " << filename;
+ logGlobal->errorStream() << "Failed loading " << filename;
checkForError(true);
}
}
@@ -71,13 +73,13 @@ void *DLLHandler::FindAddress(const char *symbol)
if(!dll)
{
- logGlobal->errorStream() << "Cannot look for " << symbol << " because DLL hasn't been appropriately loaded!";
+ logGlobal->errorStream() << "Cannot look for " << symbol << " because DLL hasn't been appropriately loaded!";
return nullptr;
}
ret = (void*) GetProcAddress(dll,symbol);
if(!ret)
{
- logGlobal->errorStream() << "Failed to find " << symbol << " in " << name;
+ logGlobal->errorStream() << "Failed to find " << symbol << " in " << name;
checkForError();
}
return ret;
@@ -89,7 +91,7 @@ DLLHandler::~DLLHandler()
{
if(!FreeLibrary(dll))
{
- logGlobal->errorStream() << "Failed to free " << name;
+ logGlobal->errorStream() << "Failed to free " << name;
checkForError();
}
}
@@ -136,21 +138,21 @@ bool CBIKHandler::open(std::string name)
if(hBinkFile == INVALID_HANDLE_VALUE)
{
- logGlobal->errorStream() << "BIK handler: failed to open " << name;
+ logGlobal->errorStream() << "BIK handler: failed to open " << name;
goto checkErrorAndClean;
}
//GCC wants scope of waveout to don`t cross labels/swith/goto
- {
- void *waveout = GetProcAddress(dll,"_BinkOpenWaveOut@4");
+ {
+ void *waveout = (void *)GetProcAddress(dll,"_BinkOpenWaveOut@4");
if(waveout)
binkSetSoundSystem(waveout,nullptr);
- }
+ }
hBink = binkOpen(hBinkFile, 0x8a800000);
if(!hBink)
{
- logGlobal->errorStream() << "bink failed to open " << name;
+ logGlobal->errorStream() << "bink failed to open " << name;
goto checkErrorAndClean;
}
@@ -300,7 +302,7 @@ bool CSmackPlayer::open( std::string name )
data = ptrSmackOpen( (void*)name.c_str(), flags[1], -1);
if (!data)
{
- logGlobal->errorStream() << "Smack cannot open " << name;
+ logGlobal->errorStream() << "Smack cannot open " << name;
checkForError();
throw std::runtime_error("SMACK failed opening video");
}
@@ -434,7 +436,7 @@ bool CVideoPlayer::open(std::string name)
catch(std::exception &e)
{
current = nullptr;
- logGlobal->warnStream() << "Failed to open video file " << name << ": " << e.what();
+ logGlobal->warnStream() << "Failed to open video file " << name << ": " << e.what();
}
return false;
@@ -444,7 +446,7 @@ void CVideoPlayer::close()
{
if(!current)
{
- logGlobal->warnStream() << "Closing no opened player...?";
+ logGlobal->warnStream() << "Closing no opened player...?";
return;
}
@@ -452,7 +454,7 @@ void CVideoPlayer::close()
current = nullptr;
if(!DeleteFileA(fname.c_str()))
{
- logGlobal->errorStream() << "Cannot remove temporarily extracted video file: " << fname;
+ logGlobal->errorStream() << "Cannot remove temporarily extracted video file: " << fname;
checkForError(false);
}
fname.clear();
@@ -603,7 +605,11 @@ CVideoPlayer::CVideoPlayer()
frame = nullptr;
codec = nullptr;
sws = nullptr;
+#ifdef VCMI_SDL1
overlay = nullptr;
+#else
+ texture = nullptr;
+#endif
dest = nullptr;
context = nullptr;
@@ -633,7 +639,7 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
if (!CResourceHandler::get()->existsResource(resource))
{
- logGlobal->errorStream() << "Error: video " << resource.getName() << " was not found";
+ logGlobal->errorStream() << "Error: video " << resource.getName() << " was not found";
return false;
}
@@ -706,8 +712,13 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
// Allocate a place to put our YUV image on that screen
if (useOverlay)
{
+#ifdef VCMI_SDL1
overlay = SDL_CreateYUVOverlay(codecContext->width, codecContext->height,
SDL_YV12_OVERLAY, screen);
+#else
+ texture = SDL_CreateTexture( mainRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STATIC, codecContext->width, codecContext->height);
+#endif
+
}
else
{
@@ -716,13 +727,18 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
destRect.w = codecContext->width;
destRect.h = codecContext->height;
}
-
+#ifdef VCMI_SDL1
if (overlay == nullptr && dest == nullptr)
return false;
- // Convert the image into YUV format that SDL uses
if (overlay)
- {
+#else
+ if (texture == nullptr && dest == nullptr)
+ return false;
+
+ if (texture)
+#endif
+ { // Convert the image into YUV format that SDL uses
sws = sws_getContext(codecContext->width, codecContext->height,
codecContext->pix_fmt, codecContext->width, codecContext->height,
PIX_FMT_YUV420P, SWS_BICUBIC, nullptr, nullptr, nullptr);
@@ -810,6 +826,7 @@ bool CVideoPlayer::nextFrame()
{
AVPicture pict;
+#ifdef VCMI_SDL1
if (overlay) {
SDL_LockYUVOverlay(overlay);
@@ -825,6 +842,18 @@ bool CVideoPlayer::nextFrame()
0, codecContext->height, pict.data, pict.linesize);
SDL_UnlockYUVOverlay(overlay);
+#else
+ if (texture) {
+ avpicture_alloc(&pict, AV_PIX_FMT_YUV420P, codecContext->width, codecContext->height);
+
+ sws_scale(sws, frame->data, frame->linesize,
+ 0, codecContext->height, pict.data, pict.linesize);
+
+ SDL_UpdateYUVTexture(texture, NULL, pict.data[0], pict.linesize[0],
+ pict.data[1], pict.linesize[1],
+ pict.data[2], pict.linesize[2]);
+ avpicture_free(&pict);
+#endif
}
else
{
@@ -900,11 +929,21 @@ void CVideoPlayer::close()
sws = nullptr;
}
+#ifdef VCMI_SDL1
if (overlay)
{
SDL_FreeYUVOverlay(overlay);
overlay = nullptr;
}
+#else
+ if (texture)
+ {
+ SDL_DestroyTexture(texture);
+ texture = nullptr;
+ }
+
+#endif
+
if (dest)
{
@@ -958,7 +997,13 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
if(stopOnKey && keyDown())
return false;
+#ifdef VCMI_SDL1
SDL_DisplayYUVOverlay(overlay, &pos);
+#else
+ SDL_RenderCopy(mainRenderer, texture, NULL, NULL);
+ SDL_RenderPresent(mainRenderer);
+#endif
+
// Wait 3 frames
GH.mainFPSmng->framerateDelay();
diff --git a/client/CVideoHandler.h b/client/CVideoHandler.h
index 216faa027..a300d93b9 100644
--- a/client/CVideoHandler.h
+++ b/client/CVideoHandler.h
@@ -221,7 +221,7 @@ public:
#include
#include
-#if SDL_VERSION_ATLEAST(1,3,0)
+#if SDL_VERSION_ATLEAST(1,3,0) && !SDL_VERSION_ATLEAST(2,0,0)
#include
#endif
@@ -242,7 +242,12 @@ class CVideoPlayer : public IMainVideoPlayer
AVIOContext * context;
// Destination. Either overlay or dest.
- SDL_Overlay *overlay;
+#ifdef VCMI_SDL1
+ SDL_Overlay * overlay;
+#else
+ SDL_Texture *texture;
+#endif
+
SDL_Surface *dest;
SDL_Rect destRect; // valid when dest is used
SDL_Rect pos; // destination on screen
diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp
index c17ff1466..10d814799 100644
--- a/client/GUIClasses.cpp
+++ b/client/GUIClasses.cpp
@@ -1799,7 +1799,7 @@ void CMinorResDataBar::showAll(SDL_Surface * to)
CMinorResDataBar::CMinorResDataBar()
{
bg = BitmapHandler::loadBitmap("KRESBAR.bmp");
- SDL_SetColorKey(bg,SDL_SRCCOLORKEY,SDL_MapRGB(bg->format,0,255,255));
+ CSDL_Ext::setDefaultColorKey(bg);
graphics->blueToPlayersAdv(bg,LOCPLINT->playerID);
pos.x = 7;
pos.y = 575;
@@ -3946,8 +3946,8 @@ void CInGameConsole::keyPressed (const SDL_KeyboardEvent & key)
{
if(enteredText.size() > 1)
{
- enteredText.resize(enteredText.size()-1);
- enteredText[enteredText.size()-1] = '_';
+ Unicode::trimRight(enteredText,2);
+ enteredText += '_';
refreshEnteredText();
}
break;
@@ -3989,6 +3989,7 @@ void CInGameConsole::keyPressed (const SDL_KeyboardEvent & key)
}
default:
{
+ #ifdef VCMI_SDL1
if(enteredText.size() > 0 && enteredText.size() < conf.go()->ac.inputLineLength)
{
if( key.keysym.unicode < 0x80 && key.keysym.unicode > 0 )
@@ -3998,13 +3999,37 @@ void CInGameConsole::keyPressed (const SDL_KeyboardEvent & key)
refreshEnteredText();
}
}
+ #endif // VCMI_SDL1
break;
}
}
}
+#ifndef VCMI_SDL1
+
+void CInGameConsole::textInputed(const SDL_TextInputEvent & event)
+{
+ if(!captureAllKeys || enteredText.size() == 0)
+ return;
+ enteredText.resize(enteredText.size()-1);
+
+ enteredText += event.text;
+ enteredText += "_";
+
+ refreshEnteredText();
+}
+
+void CInGameConsole::textEdited(const SDL_TextEditingEvent & event)
+{
+ //do nothing here
+}
+
+#endif // VCMI_SDL1
+
void CInGameConsole::startEnteringText()
{
+ CSDL_Ext::startTextInput(&pos);
+
enteredText = "_";
if(GH.topInt() == adventureInt)
{
@@ -4022,6 +4047,8 @@ void CInGameConsole::startEnteringText()
void CInGameConsole::endEnteringText(bool printEnteredText)
{
+ CSDL_Ext::stopTextInput();
+
prevEntDisp = -1;
if(printEnteredText)
{
@@ -4060,7 +4087,11 @@ void CInGameConsole::refreshEnteredText()
CInGameConsole::CInGameConsole() : prevEntDisp(-1), defaultTimeout(10000), maxDisplayedTexts(10)
{
+ #ifdef VCMI_SDL1
addUsedEvents(KEYBOARD);
+ #else
+ addUsedEvents(KEYBOARD | TEXTINPUT);
+ #endif
}
CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits ):
@@ -5341,6 +5372,9 @@ CPuzzleWindow::CPuzzleWindow(const int3 &GrailPos, double discoveredRatio):
piecesToRemove.push_back(piece);
piece->needRefresh = true;
piece->recActions = piece->recActions & ~SHOWALL;
+ #ifndef VCMI_SDL1
+ SDL_SetSurfaceBlendMode(piece->bg,SDL_BLENDMODE_BLEND);
+ #endif // VCMI_SDL1
}
}
}
diff --git a/client/GUIClasses.h b/client/GUIClasses.h
index 4da40b028..2126a315d 100644
--- a/client/GUIClasses.h
+++ b/client/GUIClasses.h
@@ -834,6 +834,11 @@ public:
void print(const std::string &txt);
void keyPressed (const SDL_KeyboardEvent & key); //call-in
+#ifndef VCMI_SDL1
+ void textInputed(const SDL_TextInputEvent & event) override;
+ void textEdited(const SDL_TextEditingEvent & event) override;
+#endif // VCMI_SDL1
+
void startEnteringText();
void endEnteringText(bool printEnteredText);
void refreshEnteredText();
diff --git a/client/Graphics.cpp b/client/Graphics.cpp
index b8d65ef0e..f068cabfb 100644
--- a/client/Graphics.cpp
+++ b/client/Graphics.cpp
@@ -60,7 +60,7 @@ void Graphics::loadPaletteAndColors()
col.r = pals[startPoint++];
col.g = pals[startPoint++];
col.b = pals[startPoint++];
- col.unused = 255;
+ CSDL_Ext::colorSetAlpha(col,SDL_ALPHA_OPAQUE);
startPoint++;
playerColorPalette[i] = col;
}
@@ -75,20 +75,26 @@ void Graphics::loadPaletteAndColors()
neutralColorPalette[i].r = reader.readUInt8();
neutralColorPalette[i].g = reader.readUInt8();
neutralColorPalette[i].b = reader.readUInt8();
- neutralColorPalette[i].unused = reader.readUInt8();
- neutralColorPalette[i].unused = !neutralColorPalette[i].unused;
+ CSDL_Ext::colorSetAlpha(neutralColorPalette[i], !reader.readUInt8());
}
//colors initialization
- int3 kolory[] = {int3(0xff,0,0),int3(0x31,0x52,0xff),int3(0x9c,0x73,0x52),int3(0x42,0x94,0x29),
- int3(0xff,0x84,0x0),int3(0x8c,0x29,0xa5),int3(0x09,0x9c,0xa5),int3(0xc6,0x7b,0x8c)};
+ SDL_Color colors[] = {
+ {0xff,0, 0, SDL_ALPHA_OPAQUE},
+ {0x31,0x52,0xff,SDL_ALPHA_OPAQUE},
+ {0x9c,0x73,0x52,SDL_ALPHA_OPAQUE},
+ {0x42,0x94,0x29,SDL_ALPHA_OPAQUE},
+
+ {0xff,0x84,0, SDL_ALPHA_OPAQUE},
+ {0x8c,0x29,0xa5,SDL_ALPHA_OPAQUE},
+ {0x09,0x9c,0xa5,SDL_ALPHA_OPAQUE},
+ {0xc6,0x7b,0x8c,SDL_ALPHA_OPAQUE}};
+
for(int i=0;i<8;i++)
{
- playerColors[i].r = kolory[i].x;
- playerColors[i].g = kolory[i].y;
- playerColors[i].b = kolory[i].z;
- playerColors[i].unused = 255;
+ playerColors[i] = colors[i];
}
- neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; neutralColor->unused = 255;//gray
+ neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; //gray
+ CSDL_Ext::colorSetAlpha(*neutralColor,SDL_ALPHA_OPAQUE);
}
void Graphics::initializeBattleGraphics()
@@ -119,6 +125,7 @@ void Graphics::initializeBattleGraphics()
}
Graphics::Graphics()
{
+ #if 0
std::vector tasks; //preparing list of graphics to load
tasks += boost::bind(&Graphics::loadFonts,this);
tasks += boost::bind(&Graphics::loadPaletteAndColors,this);
@@ -131,6 +138,16 @@ Graphics::Graphics()
CThreadHelper th(&tasks,std::max((ui32)1,boost::thread::hardware_concurrency()));
th.run();
+ #else
+ loadFonts();
+ loadPaletteAndColors();
+ loadHeroFlags();
+ initializeBattleGraphics();
+ loadErmuToPicture();
+ initializeImageLists();
+ resources32 = CDefHandler::giveDefEss("RESOURCE.DEF");
+ heroMoveArrows = CDefHandler::giveDefEss("ADAG.DEF");
+ #endif
for(auto & elem : heroMoveArrows->ourImages)
{
@@ -242,9 +259,10 @@ void Graphics::loadHeroFlagsDetail(std::pair Graphi
}
for(auto & curImg : curImgs)
{
- SDL_SetColorKey(curImg.bitmap, SDL_SRCCOLORKEY,
- SDL_MapRGB(curImg.bitmap->format, 0, 255, 255)
- );
+ CSDL_Ext::setDefaultColorKey(curImg.bitmap);
+ #ifndef VCMI_SDL1
+ SDL_SetSurfaceBlendMode(curImg.bitmap,SDL_BLENDMODE_NONE);
+ #endif
}
}
}
@@ -266,12 +284,19 @@ void Graphics::loadHeroFlags()
pr[3].first = &Graphics::flags4;
pr[3].second+=("AF00.DEF"),("AF01.DEF"),("AF02.DEF"),("AF03.DEF"),("AF04.DEF"),
("AF05.DEF"),("AF06.DEF"),("AF07.DEF");
+ #if 0
boost::thread_group grupa;
for(int g=3; g>=0; --g)
{
grupa.create_thread(boost::bind(&Graphics::loadHeroFlagsDetail, this, boost::ref(pr[g]), true));
}
grupa.join_all();
+ #else
+ for(auto p: pr)
+ {
+ loadHeroFlagsDetail(p,true);
+ }
+ #endif
logGlobal->infoStream() << "Loading and transforming heroes' flags: "<playerint)
+ {
+ if(cl->getPlayerRelations(i.first, player) == PlayerRelations::SAME_PLAYER && waitForDialogs && LOCPLINT == i.second.get())
+ {
+ LOCPLINT->waitWhileDialog();
+ }
if(cl->getPlayerRelations(i.first, player) != PlayerRelations::ENEMIES)
{
if(mode)
@@ -172,7 +177,7 @@ void FoWChange::applyCl( CClient *cl )
else
i.second->tileHidden(tiles);
}
-
+ }
cl->invalidatePaths();
}
diff --git a/client/StdInc.h b/client/StdInc.h
index 76e828312..b03f5812c 100644
--- a/client/StdInc.h
+++ b/client/StdInc.h
@@ -2,6 +2,8 @@
#include "../Global.h"
+#include "gui/SDL_Compat.h"
+
// This header should be treated as a pre compiled header file(PCH) in the compiler building settings.
-// Here you can add specific libraries and macros which are specific to this project.
\ No newline at end of file
+// Here you can add specific libraries and macros which are specific to this project.
diff --git a/client/VCMI_client.cbp b/client/VCMI_client.cbp
index 488fd2776..5a563e035 100644
--- a/client/VCMI_client.cbp
+++ b/client/VCMI_client.cbp
@@ -6,18 +6,28 @@
-
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
@@ -26,9 +36,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -45,7 +102,6 @@
-
@@ -58,13 +114,8 @@
-
-
-
-
-
@@ -139,6 +190,7 @@
+
diff --git a/client/VCMI_client.vcxproj b/client/VCMI_client.vcxproj
index 7b1226997..a366ab66e 100644
--- a/client/VCMI_client.vcxproj
+++ b/client/VCMI_client.vcxproj
@@ -234,6 +234,7 @@
+
diff --git a/client/VCMI_client.vcxproj.filters b/client/VCMI_client.vcxproj.filters
index ab9f794a4..afa62f7a5 100644
--- a/client/VCMI_client.vcxproj.filters
+++ b/client/VCMI_client.vcxproj.filters
@@ -126,6 +126,7 @@
gui
+
diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp
index 5179ce3b8..737913ed1 100644
--- a/client/battle/CBattleInterface.cpp
+++ b/client/battle/CBattleInterface.cpp
@@ -363,8 +363,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
{
idToObstacle[ID] = CDefHandler::giveDef(elem->getInfo().defName);
for(auto & _n : idToObstacle[ID]->ourImages)
- {
- SDL_SetColorKey(_n.bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(_n.bitmap->format,0,255,255));
+ {
+ CSDL_Ext::setDefaultColorKey(_n.bitmap);
}
}
else if(elem->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
diff --git a/client/battle/CCreatureAnimation.cpp b/client/battle/CCreatureAnimation.cpp
index 99641253b..155f853a7 100644
--- a/client/battle/CCreatureAnimation.cpp
+++ b/client/battle/CCreatureAnimation.cpp
@@ -178,7 +178,7 @@ CCreatureAnimation::CCreatureAnimation(std::string name, TSpeedController contro
elem.r = reader.readUInt8();
elem.g = reader.readUInt8();
elem.b = reader.readUInt8();
- elem.unused = 0;
+ CSDL_Ext::colorSetAlpha(elem,0);
}
for (int i=0; i CCreatureAnimation::genSpecialPalette()
@@ -413,7 +427,11 @@ inline void CCreatureAnimation::putPixel(ui8 * dest, const SDL_Color & color, si
if (index < 8)
{
const SDL_Color & pal = special[index];
+ #ifdef VCMI_SDL1
ColorPutter::PutColor(dest, pal.r, pal.g, pal.b, pal.unused);
+ #else
+ ColorPutter::PutColor(dest, pal.r, pal.g, pal.b, pal.a);
+ #endif // 0
}
else
{
diff --git a/client/gui/CCursorHandler.cpp b/client/gui/CCursorHandler.cpp
index 6a53cbb3b..5fd52e7df 100644
--- a/client/gui/CCursorHandler.cpp
+++ b/client/gui/CCursorHandler.cpp
@@ -25,6 +25,10 @@ void CCursorHandler::initCursor()
currentCursor = nullptr;
help = CSDL_Ext::newSurface(40,40);
+ #ifndef VCMI_SDL1
+ //No blending. Ensure, that we are copying pixels during "screen restore draw"
+ SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE);
+ #endif // VCMI_SDL1
SDL_ShowCursor(SDL_DISABLE);
changeGraphic(ECursor::ADVENTURE, 0);
@@ -223,6 +227,14 @@ void CCursorHandler::centerCursor()
SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
}
+void CCursorHandler::render()
+{
+ drawWithScreenRestore();
+ CSDL_Ext::update(screen);
+ drawRestored();
+}
+
+
CCursorHandler::~CCursorHandler()
{
if(help)
diff --git a/client/gui/CCursorHandler.h b/client/gui/CCursorHandler.h
index ab5afb4ad..907071eeb 100644
--- a/client/gui/CCursorHandler.h
+++ b/client/gui/CCursorHandler.h
@@ -32,6 +32,13 @@ class CCursorHandler
CAnimImage * dndObject; //if set, overrides currentCursor
bool showing;
+ /// Draw cursor preserving original image below cursor
+ void drawWithScreenRestore();
+ /// Restore original image below cursor
+ void drawRestored();
+ /// Simple draw cursor
+ void draw(SDL_Surface *to);
+
public:
/// position of cursor
int xpos, ypos;
@@ -53,13 +60,8 @@ public:
* cursor. CursorHandler takes ownership of object
*/
void dragAndDropCursor (CAnimImage * image);
-
- /// Draw cursor preserving original image below cursor
- void drawWithScreenRestore();
- /// Restore original image below cursor
- void drawRestored();
- /// Simple draw cursor
- void draw(SDL_Surface *to);
+
+ void render();
void shiftPos( int &x, int &y );
void hide() { showing=0; };
diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp
index 1eee3f292..2244e6e96 100644
--- a/client/gui/CGuiHandler.cpp
+++ b/client/gui/CGuiHandler.cpp
@@ -1,13 +1,14 @@
#include "StdInc.h"
#include "CGuiHandler.h"
-#include "SDL_Extensions.h"
+
#include "CIntObject.h"
#include "../CGameInfo.h"
#include "CCursorHandler.h"
#include "../../lib/CThreadHelper.h"
#include "../../lib/CConfigHandler.h"
#include "../CMT.h"
+#include "../CPlayerInterface.h"
extern std::queue events;
extern boost::mutex eventsM;
@@ -60,6 +61,10 @@ void CGuiHandler::processLists(const ui16 activityFlag, std::functioncapturedAllEvents())
+ return;
+
+ boost::unique_lock lock(eventsM);
+ while(!events.empty())
{
- SDL_Event ev;
- boost::unique_lock lock(eventsM);
- if(events.empty())
- {
- return;
- }
- else
- {
- ev = events.front();
- events.pop();
- }
- handleEvent(&ev);
+ SDL_Event ev = events.front();
+ events.pop();
+ this->handleEvent(&ev);
}
}
@@ -194,6 +195,9 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
if(key.keysym.sym == SDLK_KP_ENTER)
{
key.keysym.sym = (SDLKey)SDLK_RETURN;
+ #ifndef VCMI_SDL1
+ key.keysym.scancode = SDL_SCANCODE_RETURN;
+ #endif // VCMI_SDL1
}
bool keysCaptured = false;
@@ -264,6 +268,7 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
}
}
}
+ #ifdef VCMI_SDL1 //SDL1x only events
else if(sEvent->button.button == SDL_BUTTON_WHEELDOWN || sEvent->button.button == SDL_BUTTON_WHEELUP)
{
std::list hlp = wheelInterested;
@@ -273,7 +278,34 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
(*i)->wheelScrolled(sEvent->button.button == SDL_BUTTON_WHEELDOWN, isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y));
}
}
+ #endif
}
+ #ifndef VCMI_SDL1 //SDL2x only events
+ else if (sEvent->type == SDL_MOUSEWHEEL)
+ {
+ std::list hlp = wheelInterested;
+ for(auto i=hlp.begin(); i != hlp.end() && current; i++)
+ {
+ if(!vstd::contains(wheelInterested,*i)) continue;
+ (*i)->wheelScrolled(sEvent->wheel.y < 0, isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y));
+ }
+ }
+ else if(sEvent->type == SDL_TEXTINPUT)
+ {
+ for(auto it : textInterested)
+ {
+ it->textInputed(sEvent->text);
+ }
+ }
+ else if(sEvent->type == SDL_TEXTEDITING)
+ {
+ for(auto it : textInterested)
+ {
+ it->textEdited(sEvent->edit);
+ }
+ }
+ //todo: muiltitouch
+ #endif // VCMI_SDL1
else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_LEFT))
{
std::list hlp = lclickable;
@@ -360,8 +392,11 @@ void CGuiHandler::handleMoveInterested( const SDL_MouseMotionEvent & motion )
void CGuiHandler::fakeMouseMove()
{
SDL_Event evnt;
-
+#ifdef VCMI_SDL1
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0};
+#else
+ SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
+#endif
int x, y;
sme.state = SDL_GetMouseState(&x, &y);
sme.x = x;
@@ -372,37 +407,38 @@ void CGuiHandler::fakeMouseMove()
handleMouseMotion(&evnt);
}
-void CGuiHandler::run()
+void CGuiHandler::renderFrame()
{
- setThreadName("CGuiHandler::run");
- inGuiThread.reset(new bool(true));
- try
+ auto doUpdate = [](IUpdateable * target)
{
- if(settings["video"]["fullscreen"].Bool())
- CCS->curh->centerCursor();
+ if(nullptr != target)
+ target -> update();
+ // draw the mouse cursor and update the screen
+ CCS->curh->render();
- mainFPSmng->init(); // resets internal clock, needed for FPS manager
- while(!terminate)
- {
- if(curInt)
- curInt->update(); // calls a update and drawing process of the loaded game interface object at the moment
+ #ifndef VCMI_SDL1
+ if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr))
+ logGlobal->errorStream() << __FUNCTION__ << " SDL_RenderCopy " << SDL_GetError();
- mainFPSmng->framerateDelay(); // holds a constant FPS
- }
- }
- catch(const std::exception & e)
- {
- logGlobal->errorStream() << "Error: " << e.what();
- exit(EXIT_FAILURE);
- }
+ SDL_RenderPresent(mainRenderer);
+ #endif
+
+ };
+
+ if(curInt)
+ curInt->runLocked(doUpdate);
+ else
+ doUpdate(nullptr);
+
+ mainFPSmng->framerateDelay(); // holds a constant FPS
}
+
CGuiHandler::CGuiHandler()
:lastClick(-500, -500)
{
curInt = nullptr;
current = nullptr;
- terminate = false;
statusbar = nullptr;
// Creates the FPS manager and sets the framerate to 48 which is doubled the value of the original Heroes 3 FPS rate
@@ -432,6 +468,7 @@ void CGuiHandler::drawFPSCounter()
SDLKey CGuiHandler::arrowToNum( SDLKey key )
{
+ #ifdef VCMI_SDL1
switch(key)
{
case SDLK_DOWN:
@@ -443,23 +480,51 @@ SDLKey CGuiHandler::arrowToNum( SDLKey key )
case SDLK_RIGHT:
return SDLK_KP6;
default:
- assert(0);
- }
- throw std::runtime_error("Wrong key!");
+ throw std::runtime_error("Wrong key!");assert(0);
+ }
+ #else
+ switch(key)
+ {
+ case SDLK_DOWN:
+ return SDLK_KP_2;
+ case SDLK_UP:
+ return SDLK_KP_8;
+ case SDLK_LEFT:
+ return SDLK_KP_4;
+ case SDLK_RIGHT:
+ return SDLK_KP_6;
+ default:
+ throw std::runtime_error("Wrong key!");
+ }
+ #endif // 0
}
SDLKey CGuiHandler::numToDigit( SDLKey key )
{
+#ifdef VCMI_SDL1
if(key >= SDLK_KP0 && key <= SDLK_KP9)
return SDLKey(key - SDLK_KP0 + SDLK_0);
+#endif // 0
#define REMOVE_KP(keyName) case SDLK_KP_ ## keyName : return SDLK_ ## keyName;
switch(key)
{
+#ifndef VCMI_SDL1
+ REMOVE_KP(0)
+ REMOVE_KP(1)
+ REMOVE_KP(2)
+ REMOVE_KP(3)
+ REMOVE_KP(4)
+ REMOVE_KP(5)
+ REMOVE_KP(6)
+ REMOVE_KP(7)
+ REMOVE_KP(8)
+ REMOVE_KP(9)
+#endif // VCMI_SDL1
REMOVE_KP(PERIOD)
- REMOVE_KP(MINUS)
- REMOVE_KP(PLUS)
- REMOVE_KP(EQUALS)
+ REMOVE_KP(MINUS)
+ REMOVE_KP(PLUS)
+ REMOVE_KP(EQUALS)
case SDLK_KP_MULTIPLY:
return SDLK_ASTERISK;
@@ -475,15 +540,22 @@ SDLKey CGuiHandler::numToDigit( SDLKey key )
bool CGuiHandler::isNumKey( SDLKey key, bool number )
{
+ #ifdef VCMI_SDL1
if(number)
return key >= SDLK_KP0 && key <= SDLK_KP9;
else
return key >= SDLK_KP0 && key <= SDLK_KP_EQUALS;
+ #else
+ if(number)
+ return key >= SDLK_KP_1 && key <= SDLK_KP_0;
+ else
+ return (key >= SDLK_KP_1 && key <= SDLK_KP_0) || key == SDLK_KP_MINUS || key == SDLK_KP_PLUS || key == SDLK_KP_EQUALS;
+ #endif // 0
}
bool CGuiHandler::isArrowKey( SDLKey key )
{
- return key >= SDLK_UP && key <= SDLK_LEFT;
+ return key == SDLK_UP || key == SDLK_DOWN || key == SDLK_LEFT || key == SDLK_RIGHT;
}
bool CGuiHandler::amIGuiThread()
diff --git a/client/gui/CGuiHandler.h b/client/gui/CGuiHandler.h
index 77775cd07..262797841 100644
--- a/client/gui/CGuiHandler.h
+++ b/client/gui/CGuiHandler.h
@@ -2,11 +2,13 @@
#include "../../lib/CStopWatch.h"
#include "Geometries.h"
+#include "SDL_Extensions.h"
class CFramerateManager;
class CGStatusBar;
class CIntObject;
class IUpdateable;
+class ILockedUpdatable;
class IShowActivatable;
class IShowable;
@@ -57,6 +59,9 @@ private:
timeinterested,
wheelInterested,
doubleClickInterested;
+ #ifndef VCMI_SDL1
+ CIntObjectList textInterested;
+ #endif // VCMI_SDL1
void processLists(const ui16 activityFlag, std::function *)> cb);
public:
@@ -68,15 +73,15 @@ public:
std::vector objsToBlit;
SDL_Event * current; //current event - can be set to nullptr to stop handling event
- IUpdateable *curInt;
+ ILockedUpdatable *curInt;
Point lastClick;
unsigned lastClickTime;
- bool terminate;
CGuiHandler();
~CGuiHandler();
- void run(); // holds the main loop for the whole program after initialization and manages the update/rendering system
+
+ void renderFrame();
void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering
void simpleRedraw(); //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering
diff --git a/client/gui/CIntObject.cpp b/client/gui/CIntObject.cpp
index b71bea9bb..b952ae9de 100644
--- a/client/gui/CIntObject.cpp
+++ b/client/gui/CIntObject.cpp
@@ -4,6 +4,12 @@
#include "SDL_Extensions.h"
#include "../CMessage.h"
+void ILockedUpdatable::runLocked(std::function cb)
+{
+ boost::unique_lock lock(updateGuard);
+ cb(this);
+}
+
CIntObject::CIntObject(int used_, Point pos_):
parent_m(nullptr),
active_m(0),
diff --git a/client/gui/CIntObject.h b/client/gui/CIntObject.h
index 15d6c88a6..2e2d42ccc 100644
--- a/client/gui/CIntObject.h
+++ b/client/gui/CIntObject.h
@@ -1,13 +1,3 @@
-#pragma once
-
-#include
-#include "Geometries.h"
-#include "../Graphics.h"
-
-struct SDL_Surface;
-class CPicture;
-class CGuiHandler;
-
/*
* CIntObject.h, part of VCMI engine
*
@@ -17,6 +7,16 @@ class CGuiHandler;
* Full text of license available in license.txt file, in main folder
*
*/
+
+#pragma once
+
+#include
+#include "Geometries.h"
+#include "../Graphics.h"
+
+struct SDL_Surface;
+class CPicture;
+class CGuiHandler;
using boost::logic::tribool;
@@ -36,6 +36,14 @@ public:
virtual ~IUpdateable(){}; //d-tor
};
+class ILockedUpdatable: protected IUpdateable
+{
+ boost::recursive_mutex updateGuard;
+public:
+ virtual void runLocked(std::function cb);
+ virtual ~ILockedUpdatable(){}; //d-tor
+};
+
// Defines a show method
class IShowable
{
@@ -123,6 +131,11 @@ public:
bool captureAllKeys; //if true, only this object should get info about pressed keys
virtual void keyPressed(const SDL_KeyboardEvent & key){}
virtual bool captureThisEvent(const SDL_KeyboardEvent & key); //allows refining captureAllKeys against specific events (eg. don't capture ENTER)
+
+#ifndef VCMI_SDL1
+ virtual void textInputed(const SDL_TextInputEvent & event){};
+ virtual void textEdited(const SDL_TextEditingEvent & event){};
+#endif // VCMI_SDL1
//mouse movement handling
bool strongInterest; //if true - report all mouse movements, if not - only when hovered
@@ -138,7 +151,7 @@ public:
//double click
virtual void onDoubleClick(){}
- enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, ALL=0xffff};
+ enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, TEXTINPUT=512, ALL=0xffff};
const ui16 & active;
void addUsedEvents(ui16 newActions);
void removeUsedEvents(ui16 newActions);
diff --git a/client/gui/CIntObjectClasses.cpp b/client/gui/CIntObjectClasses.cpp
index c3059e9cc..baa35a1a2 100644
--- a/client/gui/CIntObjectClasses.cpp
+++ b/client/gui/CIntObjectClasses.cpp
@@ -18,6 +18,7 @@
#include "../GUIClasses.h"
#include "CGuiHandler.h"
#include "../CAdvmapInterface.h"
+#include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free )
{
@@ -128,13 +129,17 @@ void CPicture::convertToScreenBPP()
{
SDL_Surface *hlp = bg;
bg = SDL_ConvertSurface(hlp,screen->format,0);
- SDL_SetColorKey(bg,SDL_SRCCOLORKEY,SDL_MapRGB(bg->format,0,255,255));
+ CSDL_Ext::setDefaultColorKey(bg);
SDL_FreeSurface(hlp);
}
void CPicture::setAlpha(int value)
-{
- SDL_SetAlpha(bg, SDL_SRCALPHA, value);
+{
+ #ifdef VCMI_SDL1
+ SDL_SetAlpha(bg, SDL_SRCALPHA, value);
+ #else
+ SDL_SetSurfaceAlphaMod(bg,value);
+ #endif // 0
}
void CPicture::scaleTo(Point size)
@@ -285,7 +290,7 @@ void CButtonBase::block(bool on)
CAdventureMapButton::CAdventureMapButton ()
{
hoverable = actOnDown = borderEnabled = soundDisabled = false;
- borderColor.unused = 1; // represents a transparent color, used for HighlightableButton
+ CSDL_Ext::colorSetAlpha(borderColor,1);// represents a transparent color, used for HighlightableButton
addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD);
}
@@ -404,7 +409,7 @@ void CAdventureMapButton::init(const CFunctionList &Callback, const std:
addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD);
callback = Callback;
hoverable = actOnDown = borderEnabled = soundDisabled = false;
- borderColor.unused = 1; // represents a transparent color, used for HighlightableButton
+ CSDL_Ext::colorSetAlpha(borderColor,1);// represents a transparent color, used for HighlightableButton
hoverTexts = Name;
helpBox=HelpBox;
@@ -452,9 +457,14 @@ void CAdventureMapButton::setPlayerColor(PlayerColor player)
void CAdventureMapButton::showAll(SDL_Surface * to)
{
CIntObject::showAll(to);
-
+
+ #ifdef VCMI_SDL1
if (borderEnabled && borderColor.unused == 0)
- CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor.r, borderColor.g, borderColor.b));
+ CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor.r, borderColor.g, borderColor.b));
+ #else
+ if (borderEnabled && borderColor.a == 0)
+ CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor.r, borderColor.g, borderColor.b));
+ #endif // 0
}
void CHighlightableButton::select(bool on)
@@ -840,7 +850,7 @@ void CSlider::setAmount( int to )
void CSlider::showAll(SDL_Surface * to)
{
- CSDL_Ext::fillRect(to, &pos, 0);
+ CSDL_Ext::fillRectBlack(to, &pos);
CIntObject::showAll(to);
}
@@ -1536,7 +1546,7 @@ CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionListpos.w;
pos.h = bg->pos.h;
bg->pos = pos;
- addUsedEvents(LCLICK | KEYBOARD);
+ addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
giveFocus();
}
+void CTextInput::focusGot()
+{
+ CSDL_Ext::startTextInput(&pos);
+}
+
+void CTextInput::focusLost()
+{
+ CSDL_Ext::stopTextInput();
+}
+
+
std::string CTextInput::visibleText()
{
- return focus ? text + "_" : text;
+ return focus ? text + newText + "_" : text;
}
void CTextInput::clickLeft( tribool down, bool previousState )
@@ -1584,6 +1605,7 @@ void CTextInput::clickLeft( tribool down, bool previousState )
void CTextInput::keyPressed( const SDL_KeyboardEvent & key )
{
+
if(!focus || key.state != SDL_PRESSED)
return;
@@ -1594,29 +1616,46 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key )
return;
}
+ bool redrawNeeded = false;
+ #ifdef VCMI_SDL1
std::string oldText = text;
+ #endif // 0
switch(key.keysym.sym)
{
case SDLK_DELETE: // have index > ' ' so it won't be filtered out by default section
return;
case SDLK_BACKSPACE:
- if(!text.empty())
- text.resize(text.size()-1);
+ if(!newText.empty())
+ {
+ Unicode::trimRight(newText);
+ redrawNeeded = true;
+ }
+ else if(!text.empty())
+ {
+ Unicode::trimRight(text);
+ redrawNeeded = true;
+ }
break;
default:
+ #ifdef VCMI_SDL1
if (key.keysym.unicode < ' ')
return;
else
+ {
text += key.keysym.unicode; //TODO 16-/>8
+ redrawNeeded = true;
+ }
+ #endif // 0
break;
}
-
+ #ifdef VCMI_SDL1
filters(text, oldText);
- if (text != oldText)
+ #endif // 0
+ if (redrawNeeded)
{
redraw();
cb(text);
- }
+ }
}
void CTextInput::setText( const std::string &nText, bool callCb )
@@ -1630,14 +1669,49 @@ bool CTextInput::captureThisEvent(const SDL_KeyboardEvent & key)
{
if(key.keysym.sym == SDLK_RETURN || key.keysym.sym == SDLK_KP_ENTER)
return false;
-
+
+ #ifdef VCMI_SDL1
//this should allow all non-printable keys to go through (for example arrows)
if (key.keysym.unicode < ' ')
return false;
return true;
+ #else
+ return false;
+ #endif
}
+#ifndef VCMI_SDL1
+void CTextInput::textInputed(const SDL_TextInputEvent & event)
+{
+ if(!focus)
+ return;
+ std::string oldText = text;
+
+ text += event.text;
+
+ filters(text,oldText);
+ if (text != oldText)
+ {
+ redraw();
+ cb(text);
+ }
+ newText = "";
+}
+
+void CTextInput::textEdited(const SDL_TextEditingEvent & event)
+{
+ if(!focus)
+ return;
+
+ newText = event.text;
+ redraw();
+ cb(text+newText);
+}
+
+#endif
+
+
void CTextInput::filenameFilter(std::string & text, const std::string &)
{
static const std::string forbiddenChars = "<>:\"/\\|?*\r\n"; //if we are entering a filename, some special characters won't be allowed
@@ -1690,7 +1764,10 @@ CFocusable::CFocusable()
CFocusable::~CFocusable()
{
if(inputWithFocus == this)
+ {
+ focusLost();
inputWithFocus = nullptr;
+ }
focusables -= this;
}
@@ -1699,12 +1776,14 @@ void CFocusable::giveFocus()
if(inputWithFocus)
{
inputWithFocus->focus = false;
+ inputWithFocus->focusLost();
inputWithFocus->redraw();
}
focus = true;
inputWithFocus = this;
- redraw();
+ focusGot();
+ redraw();
}
void CFocusable::moveFocus()
diff --git a/client/gui/CIntObjectClasses.h b/client/gui/CIntObjectClasses.h
index f6d3c9341..6c35385a2 100644
--- a/client/gui/CIntObjectClasses.h
+++ b/client/gui/CIntObjectClasses.h
@@ -217,7 +217,7 @@ public:
void wheelScrolled(bool down, bool in);
void clickLeft(tribool down, bool previousState);
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
- void showAll(SDL_Surface * to);
+ void showAll(SDL_Surface * to);
CSlider(int x, int y, int totalw, std::function Moved, int Capacity, int Amount,
int Value=0, bool Horizontal=true, int style = 0); //style 0 - brown, 1 - blue
@@ -436,6 +436,9 @@ public:
/// UIElement which can get input focus
class CFocusable : public virtual CIntObject
{
+protected:
+ virtual void focusGot(){};
+ virtual void focusLost(){};
public:
bool focus; //only one focusable control can have focus at one moment
@@ -451,9 +454,12 @@ public:
/// Text input box where players can enter text
class CTextInput : public CLabel, public CFocusable
{
+ std::string newText;
protected:
std::string visibleText() override;
+ void focusGot() override;
+ void focusLost() override;
public:
CFunctionList cb;
CFunctionList filters;
@@ -466,6 +472,13 @@ public:
void clickLeft(tribool down, bool previousState) override;
void keyPressed(const SDL_KeyboardEvent & key) override;
bool captureThisEvent(const SDL_KeyboardEvent & key) override;
+
+#ifndef VCMI_SDL1
+ void textInputed(const SDL_TextInputEvent & event) override;
+ void textEdited(const SDL_TextEditingEvent & event) override;
+
+
+#endif // VCMI_SDL1
//Filter that will block all characters not allowed in filenames
static void filenameFilter(std::string &text, const std::string & oldText);
diff --git a/client/gui/SDL_Compat.h b/client/gui/SDL_Compat.h
new file mode 100644
index 000000000..ccda77c5d
--- /dev/null
+++ b/client/gui/SDL_Compat.h
@@ -0,0 +1,37 @@
+#pragma once
+
+/*
+ * SDL_Compat.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include
+
+#if (SDL_MAJOR_VERSION == 2)
+#define VCMI_SDL2
+
+#include
+typedef int SDLX_Coord;
+typedef int SDLX_Size;
+
+typedef SDL_Keycode SDLKey;
+
+#define SDL_SRCCOLORKEY SDL_TRUE
+
+#define SDL_FULLSCREEN SDL_WINDOW_FULLSCREEN
+
+#elif (SDL_MAJOR_VERSION == 1)
+#define VCMI_SDL1
+//SDL 1.x
+typedef Sint16 SDLX_Coord;
+typedef Uint16 SDLX_Size;
+#else
+#error "unknown or unsupported SDL version"
+#endif
+
+
diff --git a/client/gui/SDL_Extensions.cpp b/client/gui/SDL_Extensions.cpp
index ff5ff202e..f84cd07e9 100644
--- a/client/gui/SDL_Extensions.cpp
+++ b/client/gui/SDL_Extensions.cpp
@@ -7,11 +7,28 @@
#include "../CMessage.h"
#include "../CDefHandler.h"
#include "../Graphics.h"
+#include "../CMT.h"
const SDL_Color Colors::YELLOW = { 229, 215, 123, 0 };
const SDL_Color Colors::WHITE = { 255, 243, 222, 0 };
const SDL_Color Colors::METALLIC_GOLD = { 173, 142, 66, 0 };
const SDL_Color Colors::GREEN = { 0, 255, 0, 0 };
+const SDL_Color Colors::DEFAULT_KEY_COLOR = {0, 255, 255, 0};
+
+#if (SDL_MAJOR_VERSION == 2)
+void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h)
+{
+ Rect rect(x,y,w,h);
+ if(0 !=SDL_UpdateTexture(screenTexture, &rect, surface->pixels, surface->pitch))
+ logGlobal->errorStream() << __FUNCTION__ << "SDL_UpdateTexture " << SDL_GetError();
+
+ SDL_RenderClear(mainRenderer);
+ if(0 != SDL_RenderCopy(mainRenderer, screenTexture, NULL, NULL))
+ logGlobal->errorStream() << __FUNCTION__ << "SDL_RenderCopy " << SDL_GetError();
+ SDL_RenderPresent(mainRenderer);
+
+}
+#endif // VCMI_SDL1
SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given
{
@@ -444,7 +461,11 @@ int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * sr
for(int x = w; x; x--)
{
const SDL_Color &tbc = colors[*color++]; //color to blit
+ #ifdef VCMI_SDL1
ColorPutter::PutColorAlphaSwitch(p, tbc.r, tbc.g, tbc.b, tbc.unused);
+ #else
+ ColorPutter::PutColorAlphaSwitch(p, tbc.r, tbc.g, tbc.b, tbc.a);
+ #endif // 0
}
}
SDL_UnlockSurface(dst);
@@ -469,7 +490,11 @@ int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * src
Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color)
{
Uint32 ret = 0;
+ #ifdef VCMI_SDL1
ret+=color->unused;
+ #else
+ ret+=color->a;
+ #endif // 0
ret<<=8; //*=256
ret+=color->b;
ret<<=8; //*=256
@@ -481,8 +506,15 @@ Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color)
void CSDL_Ext::update(SDL_Surface * what)
{
+ #ifdef VCMI_SDL1
if(what)
- SDL_UpdateRect(what, 0, 0, what->w, what->h);
+ SDL_UpdateRect(what, 0, 0, what->w, what->h);
+ #else
+ if(!what)
+ return;
+ if(0 !=SDL_UpdateTexture(screenTexture, nullptr, what->pixels, what->pitch))
+ logGlobal->errorStream() << __FUNCTION__ << "SDL_UpdateTexture " << SDL_GetError();
+ #endif // VCMI_SDL1
}
void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color)
{
@@ -601,14 +633,22 @@ bool CSDL_Ext::isTransparent( SDL_Surface * srf, int x, int y )
return true;
SDL_Color color;
-
+
+ #ifdef VCMI_SDL1
SDL_GetRGBA(SDL_GetPixel(srf, x, y), srf->format, &color.r, &color.g, &color.b, &color.unused);
+ #else
+ SDL_GetRGBA(SDL_GetPixel(srf, x, y), srf->format, &color.r, &color.g, &color.b, &color.a);
+ #endif // 0
// color is considered transparent here if
// a) image has aplha: less than 50% transparency
// b) no alpha: color is cyan
if (srf->format->Amask)
+ #ifdef VCMI_SDL1
return color.unused < 128; // almost transparent
+ #else
+ return color.a < 128; // almost transparent
+ #endif // 0
else
return (color.r == 0 && color.g == 255 && color.b == 255);
}
@@ -915,6 +955,12 @@ void CSDL_Ext::fillRect( SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color )
SDL_FillRect(dst, &newRect, color);
}
+void CSDL_Ext::fillRectBlack( SDL_Surface *dst, SDL_Rect *dstrect)
+{
+ const Uint32 black = SDL_MapRGB(dst->format,0,0,0);
+ fillRect(dst,dstrect,black);
+}
+
void CSDL_Ext::fillTexture(SDL_Surface *dst, SDL_Surface * src)
{
SDL_Rect srcRect;
@@ -941,6 +987,59 @@ SDL_Color CSDL_Ext::makeColor(ui8 r, ui8 g, ui8 b, ui8 a)
return ret;
}
+void CSDL_Ext::startTextInput(SDL_Rect * where)
+{
+ #ifndef VCMI_SDL1
+ if (SDL_IsTextInputActive() == SDL_FALSE)
+ {
+ SDL_StartTextInput();
+ }
+ SDL_SetTextInputRect(where);
+ #endif
+}
+
+void CSDL_Ext::stopTextInput()
+{
+ #ifndef VCMI_SDL1
+ if (SDL_IsTextInputActive() == SDL_TRUE)
+ {
+ SDL_StopTextInput();
+ }
+ #endif
+}
+
+STRONG_INLINE static uint32_t mapColor(SDL_Surface * surface, SDL_Color color)
+{
+ #ifdef VCMI_SDL1
+ return SDL_MapRGB(surface->format, color.r, color.g, color.b);
+ #else
+ return SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a);
+ #endif
+}
+
+void CSDL_Ext::setColorKey(SDL_Surface * surface, SDL_Color color)
+{
+ uint32_t key = mapColor(surface,color);
+ SDL_SetColorKey(surface, SDL_SRCCOLORKEY, key);
+}
+
+void CSDL_Ext::setDefaultColorKey(SDL_Surface * surface)
+{
+ setColorKey(surface, Colors::DEFAULT_KEY_COLOR);
+}
+
+void CSDL_Ext::setDefaultColorKeyPresize(SDL_Surface * surface)
+{
+ uint32_t key = mapColor(surface,Colors::DEFAULT_KEY_COLOR);
+ auto & color = surface->format->palette->colors[key];
+
+ // set color key only if exactly such color was found
+ if (color.r == Colors::DEFAULT_KEY_COLOR.r && color.g == Colors::DEFAULT_KEY_COLOR.g && color.b == Colors::DEFAULT_KEY_COLOR.b)
+ SDL_SetColorKey(surface, SDL_SRCCOLORKEY, key);
+}
+
+
+
template SDL_Surface * CSDL_Ext::createSurfaceWithBpp<2>(int, int);
template SDL_Surface * CSDL_Ext::createSurfaceWithBpp<3>(int, int);
template SDL_Surface * CSDL_Ext::createSurfaceWithBpp<4>(int, int);
diff --git a/client/gui/SDL_Extensions.h b/client/gui/SDL_Extensions.h
index 0e88302fb..e74dc8cb0 100644
--- a/client/gui/SDL_Extensions.h
+++ b/client/gui/SDL_Extensions.h
@@ -1,11 +1,3 @@
-#pragma once
-
-#include
-#include
-#include "../../lib/int3.h"
-#include "../Graphics.h"
-#include "Geometries.h"
-
/*
* SDL_Extensions.h, part of VCMI engine
*
@@ -15,6 +7,20 @@
* Full text of license available in license.txt file, in main folder
*
*/
+
+#pragma once
+#include
+
+#ifndef VCMI_SDL1
+#include
+#endif
+
+#include
+#include
+#include "../../lib/int3.h"
+#include "../Graphics.h"
+#include "Geometries.h"
+
//A macro to force inlining some of our functions. Compiler (at least MSVC) is not so smart here-> without that displaying is MUCH slower
#ifdef _MSC_VER
@@ -29,6 +35,75 @@
#define SDL_GetKeyState SDL_GetKeyboardState
#endif
+//SDL2 support
+#if (SDL_MAJOR_VERSION == 2)
+
+extern SDL_Window * mainWindow;
+extern SDL_Renderer * mainRenderer;
+extern SDL_Texture * screenTexture;
+
+inline void SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors)
+{
+ SDL_SetPaletteColors(surface->format->palette,colors,firstcolor,ncolors);
+}
+
+inline void SDL_WarpMouse(int x, int y)
+{
+ SDL_WarpMouseInWindow(mainWindow,x,y);
+}
+
+void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h);
+#endif
+
+inline bool isCtrlKeyDown()
+{
+ #ifdef VCMI_SDL1
+ return SDL_GetKeyState(nullptr)[SDLK_LCTRL] || SDL_GetKeyState(nullptr)[SDLK_RCTRL];
+ #else
+ return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LCTRL] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RCTRL];
+ #endif
+}
+
+inline bool isAltKeyDown()
+{
+ #ifdef VCMI_SDL1
+ return SDL_GetKeyState(nullptr)[SDLK_LALT] || SDL_GetKeyState(nullptr)[SDLK_RALT];
+ #else
+ return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LALT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RALT];
+ #endif
+}
+
+inline bool isShiftKeyDown()
+{
+ #ifdef VCMI_SDL1
+ return SDL_GetKeyState(nullptr)[SDLK_LSHIFT] || SDL_GetKeyState(nullptr)[SDLK_RSHIFT];
+ #else
+ return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
+ #endif
+}
+namespace CSDL_Ext
+{
+ STRONG_INLINE void colorSetAlpha(SDL_Color & color, Uint8 alpha)
+ {
+ #ifdef VCMI_SDL1
+ color.unused = alpha;
+ #else
+ color.a = alpha;
+ #endif
+ }
+ //todo: should this better be assignment operator?
+ STRONG_INLINE void colorAssign(SDL_Color & dest, const SDL_Color & source)
+ {
+ dest.r = source.r;
+ dest.g = source.g;
+ dest.b = source.b;
+ #ifdef VCMI_SDL1
+ dest.unused = source.unused;
+ #else
+ dest.a = source.a;
+ #endif
+ }
+}
struct Rect;
extern SDL_Surface * screen, *screen2, *screenBuf;
@@ -53,6 +128,9 @@ public:
/** green color used for in-game console */
static const SDL_Color GREEN;
+
+ /** default key color for all 8 & 24 bit graphics */
+ static const SDL_Color DEFAULT_KEY_COLOR;
};
//MSVC gives an error when calling abs with ui64 -> we add template that will match calls with unsigned arg and return it
@@ -130,6 +208,7 @@ namespace CSDL_Ext
void blitSurface(SDL_Surface * src, SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect);
void fillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
+ void fillRectBlack(SDL_Surface * dst, SDL_Rect * dstrect);
//fill dest image with source texture.
void fillTexture(SDL_Surface *dst, SDL_Surface * sourceTexture);
@@ -188,4 +267,13 @@ namespace CSDL_Ext
template
void applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mode );
void applyEffect(SDL_Surface * surf, const SDL_Rect * rect, int mode); //mode: 0 - sepia, 1 - grayscale
+
+ void startTextInput(SDL_Rect * where);
+ void stopTextInput();
+
+ void setColorKey(SDL_Surface * surface, SDL_Color color);
+ ///set key-color to 0,255,255
+ void setDefaultColorKey(SDL_Surface * surface);
+ ///set key-color to 0,255,255 only if it exactly mapped
+ void setDefaultColorKeyPresize(SDL_Surface * surface);
}
diff --git a/client/gui/SDL_Pixels.h b/client/gui/SDL_Pixels.h
index 2c43a03eb..b35cb5e83 100644
--- a/client/gui/SDL_Pixels.h
+++ b/client/gui/SDL_Pixels.h
@@ -133,7 +133,11 @@ struct ColorPutter<2, incrementPtr>
template
STRONG_INLINE void ColorPutter::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color)
{
+ #ifdef VCMI_SDL1
PutColor(ptr, Color.r, Color.g, Color.b, Color.unused);
+ #else
+ PutColor(ptr, Color.r, Color.g, Color.b, Color.a);
+ #endif
}
template
@@ -262,7 +266,11 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uin
template
STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color)
{
+ #ifdef VCMI_SDL1
PutColor(ptr, Color.r, Color.g, Color.b, Color.unused);
+ #else
+ PutColor(ptr, Color.r, Color.g, Color.b, Color.a);
+ #endif
}
template
@@ -285,4 +293,4 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorRow(Uint8 *&ptr, const
if(incrementPtr == 1)
ptr += 2;
}
-}
\ No newline at end of file
+}
diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp
index 3080f5a11..86ede535d 100644
--- a/client/mapHandler.cpp
+++ b/client/mapHandler.cpp
@@ -80,6 +80,69 @@ static bool objectBlitOrderSorter(const std::pair > > & visibilityMap)
+ {
+ auto getTile = [&](int dx, int dy)->bool
+ {
+ if ( dx + pos.x < 0 || dx + pos.x >= sizes.x
+ || dy + pos.y < 0 || dy + pos.y >= sizes.y)
+ return false;
+ return visibilityMap[dx+pos.x][dy+pos.y][pos.z];
+ };
+ d7 = getTile(-1, -1); //789
+ d8 = getTile( 0, -1); //456
+ d9 = getTile(+1, -1); //123
+ d4 = getTile(-1, 0);
+ d5 = visibilityMap[pos.x][pos.y][pos.z];
+ d6 = getTile(+1, 0);
+ d1 = getTile(-1, +1);
+ d2 = getTile( 0, +1);
+ d3 = getTile(+1, +1);
+ }
+
+ bool areAllHidden() const
+ {
+ return !(d1 || d2 || d3 || d4 || d5 || d6 || d7 || d8 || d8 );
+ }
+
+ int getBitmapID() const
+ {
+ //NOTE: some images have unused in VCMI pair (same blockmap but a bit different look)
+ // 0-1, 2-3, 4-5, 11-13, 12-14
+ static const int visBitmaps[256] = {
+ -1, 34, 4, 4, 22, 23, 4, 4, 36, 36, 38, 38, 47, 47, 38, 38, //16
+ 3, 25, 12, 12, 3, 25, 12, 12, 9, 9, 6, 6, 9, 9, 6, 6, //32
+ 35, 39, 48, 48, 41, 43, 48, 48, 36, 36, 38, 38, 47, 47, 38, 38, //48
+ 26, 49, 28, 28, 26, 49, 28, 28, 9, 9, 6, 6, 9, 9, 6, 6, //64
+ 0, 45, 29, 29, 24, 33, 29, 29, 37, 37, 7, 7, 50, 50, 7, 7, //80
+ 13, 27, 44, 44, 13, 27, 44, 44, 8, 8, 10, 10, 8, 8, 10, 10, //96
+ 0, 45, 29, 29, 24, 33, 29, 29, 37, 37, 7, 7, 50, 50, 7, 7, //112
+ 13, 27, 44, 44, 13, 27, 44, 44, 8, 8, 10, 10, 8, 8, 10, 10, //128
+ 15, 17, 30, 30, 16, 19, 30, 30, 46, 46, 40, 40, 32, 32, 40, 40, //144
+ 2, 25, 12, 12, 2, 25, 12, 12, 9, 9, 6, 6, 9, 9, 6, 6, //160
+ 18, 42, 31, 31, 20, 21, 31, 31, 46, 46, 40, 40, 32, 32, 40, 40, //176
+ 26, 49, 28, 28, 26, 49, 28, 28, 9, 9, 6, 6, 9, 9, 6, 6, //192
+ 0, 45, 29, 29, 24, 33, 29, 29, 37, 37, 7, 7, 50, 50, 7, 7, //208
+ 13, 27, 44, 44, 13, 27, 44, 44, 8, 8, 10, 10, 8, 8, 10, 10, //224
+ 0, 45, 29, 29, 24, 33, 29, 29, 37, 37, 7, 7, 50, 50, 7, 7, //240
+ 13, 27, 44, 44, 13, 27, 44, 44, 8, 8, 10, 10, 8, 8, 10, 10 //256
+ };
+
+ return visBitmaps[d1 + d2 * 2 + d3 * 4 + d4 * 8 + d6 * 16 + d7 * 32 + d8 * 64 + d9 * 128]; // >=0 -> partial hide, <0 - full hide
+ }
+};
+
void CMapHandler::prepareFOWDefs()
{
graphics->FoWfullHide = CDefHandler::giveDef("TSHRC.DEF");
@@ -434,6 +497,15 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
// Skip tile if not in map
if (pos.y < 0 || pos.y >= sizes.y)
continue;
+
+ //we should not render fully hidden tiles
+ if(!puzzleMode)
+ {
+ const NeighborTilesInfo info(pos,sizes,*visibilityMap);
+
+ if(info.areAllHidden())
+ continue;
+ }
const TerrainTile2 & tile = ttiles[pos.x][pos.y][pos.z];
const TerrainTile &tinfo = map->getTile(int3(pos.x, pos.y, pos.z));
@@ -492,7 +564,7 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
if(obj->ID != Obj::HERO && !obj->coveringAt(top_tile.x + bx, top_tile.y + by))
continue;
- static const int notBlittedInPuzzleMode[] = {124};
+ static const int notBlittedInPuzzleMode[] = {Obj::HOLE};
//don't print flaggable objects in puzzle mode
if(puzzleMode && (obj->isVisitable() || std::find(notBlittedInPuzzleMode, notBlittedInPuzzleMode+1, obj->ID) != notBlittedInPuzzleMode+1)) //?
@@ -766,52 +838,13 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
std::pair CMapHandler::getVisBitmap( const int3 & pos, const std::vector< std::vector< std::vector > > & visibilityMap ) const
{
- //NOTE: some images have unused in VCMI pair (same blockmap but a bit different look)
- // 0-1, 2-3, 4-5, 11-13, 12-14
- static const int visBitmaps[256] = {
- -1, 34, 4, 4, 22, 23, 4, 4, 36, 36, 38, 38, 47, 47, 38, 38, //16
- 3, 25, 12, 12, 3, 25, 12, 12, 9, 9, 6, 6, 9, 9, 6, 6, //32
- 35, 39, 48, 48, 41, 43, 48, 48, 36, 36, 38, 38, 47, 47, 38, 38, //48
- 26, 49, 28, 28, 26, 49, 28, 28, 9, 9, 6, 6, 9, 9, 6, 6, //64
- 0, 45, 29, 29, 24, 33, 29, 29, 37, 37, 7, 7, 50, 50, 7, 7, //80
- 13, 27, 44, 44, 13, 27, 44, 44, 8, 8, 10, 10, 8, 8, 10, 10, //96
- 0, 45, 29, 29, 24, 33, 29, 29, 37, 37, 7, 7, 50, 50, 7, 7, //112
- 13, 27, 44, 44, 13, 27, 44, 44, 8, 8, 10, 10, 8, 8, 10, 10, //128
- 15, 17, 30, 30, 16, 19, 30, 30, 46, 46, 40, 40, 32, 32, 40, 40, //144
- 2, 25, 12, 12, 2, 25, 12, 12, 9, 9, 6, 6, 9, 9, 6, 6, //160
- 18, 42, 31, 31, 20, 21, 31, 31, 46, 46, 40, 40, 32, 32, 40, 40, //176
- 26, 49, 28, 28, 26, 49, 28, 28, 9, 9, 6, 6, 9, 9, 6, 6, //192
- 0, 45, 29, 29, 24, 33, 29, 29, 37, 37, 7, 7, 50, 50, 7, 7, //208
- 13, 27, 44, 44, 13, 27, 44, 44, 8, 8, 10, 10, 8, 8, 10, 10, //224
- 0, 45, 29, 29, 24, 33, 29, 29, 37, 37, 7, 7, 50, 50, 7, 7, //240
- 13, 27, 44, 44, 13, 27, 44, 44, 8, 8, 10, 10, 8, 8, 10, 10 //256
- };
+ const NeighborTilesInfo info(pos,sizes,visibilityMap);
- auto getTile = [&](int dx, int dy)->bool
- {
- if ( dx + pos.x < 0 || dx + pos.x >= sizes.x
- || dy + pos.y < 0 || dy + pos.y >= sizes.y)
- return false;
- return visibilityMap[dx+pos.x][dy+pos.y][pos.z];
- };
-
- //is tile visible. arrangement: (like num keyboard)
- bool d7 = getTile(-1, -1), //789
- d8 = getTile( 0, -1), //456
- d9 = getTile(+1, -1), //123
- d4 = getTile(-1, 0),
-
- d6 = getTile(+1, 0),
- d1 = getTile(-1, +1),
- d2 = getTile( 0, +1),
- d3 = getTile(+1, +1);
-
- int retBitmapID = visBitmaps[d1 + d2 * 2 + d3 * 4 + d4 * 8 + d6 * 16 + d7 * 32 + d8 * 64 + d9 * 128]; // >=0 -> partial hide, <0 - full hide
+ int retBitmapID = info.getBitmapID();// >=0 -> partial hide, <0 - full hide
if (retBitmapID < 0)
{
retBitmapID = - hideBitmap[pos.x][pos.y][pos.z] - 1; //fully hidden
}
-
if (retBitmapID >= 0)
{
diff --git a/cmake_modules/COPYING-CMAKE-SCRIPTS b/cmake_modules/COPYING-CMAKE-SCRIPTS
deleted file mode 100644
index 8ee3ea36b..000000000
--- a/cmake_modules/COPYING-CMAKE-SCRIPTS
+++ /dev/null
@@ -1,27 +0,0 @@
-The following files are derived from the Thermite project
-(http://www.thermite3d.org) and are covered under the license below.
-
-FindMYGUI.cmake, FindOGRE.cmake, FindOIS.cmake, FindBullet.cmake
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cmake_modules/FindSDL2.cmake b/cmake_modules/FindSDL2.cmake
new file mode 100644
index 000000000..14bc76f46
--- /dev/null
+++ b/cmake_modules/FindSDL2.cmake
@@ -0,0 +1,216 @@
+#.rst:
+# FindSDL2
+# --------
+#
+# Locate SDL2 library
+#
+# This module defines
+#
+# ::
+#
+# SDL2_LIBRARY, the name of the library to link against
+# SDL2_FOUND, if false, do not try to link to SDL
+# SDL2_INCLUDE_DIR, where to find SDL.h
+# SDL2_VERSION_STRING, human-readable string containing the version of SDL
+#
+#
+#
+# This module responds to the flag:
+#
+# ::
+#
+# SDL2_BUILDING_LIBRARY
+# If this is defined, then no SDL2_main will be linked in because
+# only applications need main().
+# Otherwise, it is assumed you are building an application and this
+# module will attempt to locate and set the proper link flags
+# as part of the returned SDL2_LIBRARY variable.
+#
+#
+#
+# Don't forget to include SDLmain.h and SDLmain.m your project for the
+# OS X framework based version. (Other versions link to -lSDL2main which
+# this module will try to find on your behalf.) Also for OS X, this
+# module will automatically add the -framework Cocoa on your behalf.
+#
+#
+#
+# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your
+# configuration and no SDL2_LIBRARY, it means CMake did not find your SDL
+# library (SDL2.dll, libSDL2.so, SDL.framework, etc). Set
+# SDL2_LIBRARY_TEMP to point to your SDL library, and configure again.
+# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this
+# value as appropriate. These values are used to generate the final
+# SDL2_LIBRARY variable, but when these values are unset, SDL2_LIBRARY
+# does not get created.
+#
+#
+#
+# $SDL2DIR is an environment variable that would correspond to the
+# ./configure --prefix=$SDL2DIR used in building SDL. l.e.galup 9-20-02
+#
+# Modified by Eric Wing. Added code to assist with automated building
+# by using environmental variables and providing a more
+# controlled/consistent search behavior. Added new modifications to
+# recognize OS X frameworks and additional Unix paths (FreeBSD, etc).
+# Also corrected the header search path to follow "proper" SDL
+# guidelines. Added a search for SDLmain which is needed by some
+# platforms. Added a search for threads which is needed by some
+# platforms. Added needed compile switches for MinGW.
+#
+# On OSX, this will prefer the Framework version (if found) over others.
+# People will have to manually change the cache values of SDL2_LIBRARY to
+# override this selection or set the CMake environment
+# CMAKE_INCLUDE_PATH to modify the search paths.
+#
+
+#=============================================================================
+# Copyright 2003-2009 Kitware, Inc.
+# Copyright 2012 Benjamin Eikel
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file kitware license.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+if (NOT WIN32)
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(_SDL2 sdl2)
+ set(SDL2_VERSION_STRING ${_SDL2_VERSION})
+ endif ()
+endif ()
+
+find_path(SDL2_INCLUDE_DIR
+ SDL.h
+ HINTS
+ ${_SDL2_INCLUDEDIR}
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ SDL2
+ include/SDL2
+ include
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(VC_LIB_PATH_SUFFIX lib/x64)
+else()
+ set(VC_LIB_PATH_SUFFIX lib/x86)
+endif()
+
+find_library(SDL2_LIBRARY_TEMP
+ NAMES
+ SDL2
+ HINTS
+ ${_SDL2_LIBDIR}
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ lib
+ ${VC_LIB_PATH_SUFFIX}
+)
+
+if(NOT SDL2_BUILDING_LIBRARY)
+ if(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
+ # Non-OS X framework versions expect you to also dynamically link to
+ # SDLmain. This is mainly for Windows and OS X. Other (Unix) platforms
+ # seem to provide SDLmain for compatibility even though they don't
+ # necessarily need it.
+ find_library(SDL2MAIN_LIBRARY
+ NAMES
+ SDL2main
+ HINTS
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ lib
+ ${VC_LIB_PATH_SUFFIX}
+ PATHS
+ /sw
+ /opt/local
+ /opt/csw
+ /opt
+ )
+ endif()
+endif()
+
+# SDL may require threads on your system.
+# The Apple build may not need an explicit flag because one of the
+# frameworks may already provide it.
+# But for non-OSX systems, I will use the CMake Threads package.
+if(NOT APPLE)
+ find_package(Threads)
+endif()
+
+# MinGW needs an additional library, mwindows
+# It's total link flags should look like -lmingw32 -lSDLmain -lSDL -lmwindows
+# (Actually on second look, I think it only needs one of the m* libraries.)
+if(MINGW)
+ set(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
+endif()
+
+if(SDL2_LIBRARY_TEMP)
+ # For SDLmain
+ if(SDL2MAIN_LIBRARY AND NOT SDL2_BUILDING_LIBRARY)
+ list(FIND SDL2_LIBRARY_TEMP "${SDL2MAIN_LIBRARY}" _SDL2_MAIN_INDEX)
+ if(_SDL2_MAIN_INDEX EQUAL -1)
+ set(SDL2_LIBRARY_TEMP "${SDL2MAIN_LIBRARY}" ${SDL2_LIBRARY_TEMP})
+ endif()
+ unset(_SDL2_MAIN_INDEX)
+ endif()
+
+ # For OS X, SDL uses Cocoa as a backend so it must link to Cocoa.
+ # CMake doesn't display the -framework Cocoa string in the UI even
+ # though it actually is there if I modify a pre-used variable.
+ # I think it has something to do with the CACHE STRING.
+ # So I use a temporary variable until the end so I can set the
+ # "real" variable in one-shot.
+ if(APPLE)
+ set(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
+ endif()
+
+ # For threads, as mentioned Apple doesn't need this.
+ # In fact, there seems to be a problem if I used the Threads package
+ # and try using this line, so I'm just skipping it entirely for OS X.
+ if(NOT APPLE)
+ set(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+
+ # For MinGW library
+ if(MINGW)
+ set(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
+ endif()
+
+ # Set the final string here so the GUI reflects the final state.
+ set(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL Library can be found")
+ # Set the temp variable to INTERNAL so it is not seen in the CMake GUI
+ set(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
+endif()
+
+if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL_version.h" AND NOT SDL2_VERSION_STRING)
+ file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MAJOR "${SDL2_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MINOR "${SDL2_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_PATCH "${SDL2_VERSION_PATCH_LINE}")
+ set(SDL2_VERSION_STRING ${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH})
+ unset(SDL2_VERSION_MAJOR_LINE)
+ unset(SDL2_VERSION_MINOR_LINE)
+ unset(SDL2_VERSION_PATCH_LINE)
+ unset(SDL2_VERSION_MAJOR)
+ unset(SDL2_VERSION_MINOR)
+ unset(SDL2_VERSION_PATCH)
+endif()
+
+set(SDL2_LIBRARIES ${SDL2_LIBRARY})
+set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2
+ REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR
+ VERSION_VAR SDL2_VERSION_STRING)
diff --git a/cmake_modules/FindSDL2_image.cmake b/cmake_modules/FindSDL2_image.cmake
new file mode 100644
index 000000000..5ae7e0e86
--- /dev/null
+++ b/cmake_modules/FindSDL2_image.cmake
@@ -0,0 +1,100 @@
+#.rst:
+# FindSDL2_image
+# --------------
+#
+# Locate SDL2_image library
+#
+# This module defines:
+#
+# ::
+#
+# SDL2_IMAGE_LIBRARIES, the name of the library to link against
+# SDL2_IMAGE_INCLUDE_DIRS, where to find the headers
+# SDL2_IMAGE_FOUND, if false, do not try to link against
+# SDL2_IMAGE_VERSION_STRING - human-readable string containing the version of SDL2_image
+#
+# $SDL2DIR is an environment variable that would correspond to the
+# ./configure --prefix=$SDL2DIR used in building SDL.
+#
+# Created by Eric Wing. This was influenced by the FindSDL2.cmake
+# module, but with modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+
+#=============================================================================
+# Copyright 2005-2009 Kitware, Inc.
+# Copyright 2012 Benjamin Eikel
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file kitware license.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+if (NOT WIN32)
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(_SDL2_IMAGE SDL2_image)
+ set(SDL2_IMAGE_VERSION_STRING ${_SDL2_IMAGE_VERSION})
+ endif ()
+endif ()
+
+find_path(SDL2_IMAGE_INCLUDE_DIR
+ SDL_image.h
+ HINTS
+ ${_SDL2_IMAGE_INCLUDEDIR}
+ ENV SDL2IMAGEDIR
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ SDL2
+ include/SDL2
+ include
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(VC_LIB_PATH_SUFFIX lib/x64)
+else()
+ set(VC_LIB_PATH_SUFFIX lib/x86)
+endif()
+
+find_library(SDL2_IMAGE_LIBRARY
+ NAMES
+ SDL2_image
+ HINTS
+ ${_SDL2_IMAGE_LIBDIR}
+ ENV SDL2IMAGEDIR
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ lib
+ ${VC_LIB_PATH_SUFFIX}
+)
+
+if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" AND NOT SDL2_IMAGE_VERSION_STRING)
+ file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL2_IMAGE_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL2_IMAGE_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL2_IMAGE_VERSION_PATCH_LINE}")
+ set(SDL2_IMAGE_VERSION_STRING ${SDL2_IMAGE_VERSION_MAJOR}.${SDL2_IMAGE_VERSION_MINOR}.${SDL2_IMAGE_VERSION_PATCH})
+ unset(SDL2_IMAGE_VERSION_MAJOR_LINE)
+ unset(SDL2_IMAGE_VERSION_MINOR_LINE)
+ unset(SDL2_IMAGE_VERSION_PATCH_LINE)
+ unset(SDL2_IMAGE_VERSION_MAJOR)
+ unset(SDL2_IMAGE_VERSION_MINOR)
+ unset(SDL2_IMAGE_VERSION_PATCH)
+endif()
+
+set(SDL2_IMAGE_LIBRARIES ${SDL2_IMAGE_LIBRARY})
+set(SDL2_IMAGE_INCLUDE_DIRS ${SDL2_IMAGE_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_image
+ REQUIRED_VARS SDL2_IMAGE_LIBRARIES SDL2_IMAGE_INCLUDE_DIRS
+ VERSION_VAR SDL2_IMAGE_VERSION_STRING)
+
+mark_as_advanced(SDL2_IMAGE_LIBRARY SDL2_IMAGE_INCLUDE_DIR)
diff --git a/cmake_modules/FindSDL2_mixer.cmake b/cmake_modules/FindSDL2_mixer.cmake
new file mode 100644
index 000000000..d7f71d8dd
--- /dev/null
+++ b/cmake_modules/FindSDL2_mixer.cmake
@@ -0,0 +1,101 @@
+#.rst:
+# FindSDL2_mixer
+# --------------
+#
+# Locate SDL2_mixer library
+#
+# This module defines:
+#
+# ::
+#
+# SDL2_MIXER_LIBRARIES, the name of the library to link against
+# SDL2_MIXER_INCLUDE_DIRS, where to find the headers
+# SDL2_MIXER_FOUND, if false, do not try to link against
+# SDL2_MIXER_VERSION_STRING - human-readable string containing the version of SDL_mixer
+#
+# $SDL2DIR is an environment variable that would correspond to the
+# ./configure --prefix=$SDL2DIR used in building SDL.
+#
+# Created by Eric Wing. This was influenced by the FindSDL2.cmake
+# module, but with modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+
+#=============================================================================
+# Copyright 2005-2009 Kitware, Inc.
+# Copyright 2012 Benjamin Eikel
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file kitware license.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+if (NOT WIN32)
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(_SDL2_MIXER SDL2_mixer)
+ set(SDL2_MIXER_STRING ${_SDL2_MIXER_VERSION})
+ endif ()
+endif ()
+
+
+find_path(SDL2_MIXER_INCLUDE_DIR
+ SDL_mixer.h
+ HINTS
+ ${_SDL2_MIXER_INCLUDEDIR}
+ ENV SDL2MIXERDIR
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ SDL2
+ include/SDL2
+ include
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(VC_LIB_PATH_SUFFIX lib/x64)
+else()
+ set(VC_LIB_PATH_SUFFIX lib/x86)
+endif()
+
+find_library(SDL2_MIXER_LIBRARY
+ NAMES
+ SDL2_mixer
+ HINTS
+ ${_SDL2_MIXER_LIBDIR}
+ ENV SDL2MIXERDIR
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ lib
+ ${VC_LIB_PATH_SUFFIX}
+)
+
+if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" AND NOT SDL2_MIXER_STRING)
+ file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}")
+ set(SDL2_MIXER_VERSION_STRING ${SDL2_MIXER_VERSION_MAJOR}.${SDL2_MIXER_VERSION_MINOR}.${SDL2_MIXER_VERSION_PATCH})
+ unset(SDL2_MIXER_VERSION_MAJOR_LINE)
+ unset(SDL2_MIXER_VERSION_MINOR_LINE)
+ unset(SDL2_MIXER_VERSION_PATCH_LINE)
+ unset(SDL2_MIXER_VERSION_MAJOR)
+ unset(SDL2_MIXER_VERSION_MINOR)
+ unset(SDL2_MIXER_VERSION_PATCH)
+endif()
+
+set(SDL2_MIXER_LIBRARIES ${SDL2_MIXER_LIBRARY})
+set(SDL2_MIXER_INCLUDE_DIRS ${SDL2_MIXER_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_mixer
+ REQUIRED_VARS SDL2_MIXER_LIBRARIES SDL2_MIXER_INCLUDE_DIRS
+ VERSION_VAR SDL2_MIXER_VERSION_STRING)
+
+mark_as_advanced(SDL2_MIXER_LIBRARY SDL2_MIXER_INCLUDE_DIR)
diff --git a/cmake_modules/FindSDL2_ttf.cmake b/cmake_modules/FindSDL2_ttf.cmake
new file mode 100644
index 000000000..67b40f9cf
--- /dev/null
+++ b/cmake_modules/FindSDL2_ttf.cmake
@@ -0,0 +1,100 @@
+#.rst:
+# FindSDL2_ttf
+# ------------
+#
+# Locate SDL2_ttf library
+#
+# This module defines:
+#
+# ::
+#
+# SDL2_TTF_LIBRARIES, the name of the library to link against
+# SDL2_TTF_INCLUDE_DIRS, where to find the headers
+# SDL2_TTF_FOUND, if false, do not try to link against
+# SDL2_TTF_VERSION_STRING - human-readable string containing the version of SDL2_ttf
+#
+# $SDL2DIR is an environment variable that would correspond to the
+# ./configure --prefix=$SDL2DIR used in building SDL.
+#
+# Created by Eric Wing. This was influenced by the FindSDL2.cmake
+# module, but with modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+
+#=============================================================================
+# Copyright 2005-2009 Kitware, Inc.
+# Copyright 2012 Benjamin Eikel
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file kitware license.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+if (NOT WIN32)
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(_SDL2_TTF SDL2_ttf)
+ set(SDL2_TTF_VERSION_STRING ${_SDL2_TTF_VERSION})
+ endif ()
+endif ()
+
+find_path(SDL2_TTF_INCLUDE_DIR
+ SDL_ttf.h
+ HINTS
+ ${_SDL2_TTF_INCLUDEDIR}
+ ENV SDL2TTFDIR
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ SDL2
+ include/SDL2
+ include
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(VC_LIB_PATH_SUFFIX lib/x64)
+else()
+ set(VC_LIB_PATH_SUFFIX lib/x86)
+endif()
+
+find_library(SDL2_TTF_LIBRARY
+ NAMES
+ SDL2_ttf
+ HINTS
+ ${_SDL2_TTF_LIBDIR}
+ ENV SDL2TTFDIR
+ ENV SDL2DIR
+ PATH_SUFFIXES
+ lib
+ ${VC_LIB_PATH_SUFFIX}
+)
+
+if(SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" AND NOT SDL2_TTF_VERSION_STRING)
+ file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MAJOR "${SDL2_TTF_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MINOR "${SDL2_TTF_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_PATCH "${SDL2_TTF_VERSION_PATCH_LINE}")
+ set(SDL2_TTF_VERSION_STRING ${SDL2_TTF_VERSION_MAJOR}.${SDL2_TTF_VERSION_MINOR}.${SDL2_TTF_VERSION_PATCH})
+ unset(SDL2_TTF_VERSION_MAJOR_LINE)
+ unset(SDL2_TTF_VERSION_MINOR_LINE)
+ unset(SDL2_TTF_VERSION_PATCH_LINE)
+ unset(SDL2_TTF_VERSION_MAJOR)
+ unset(SDL2_TTF_VERSION_MINOR)
+ unset(SDL2_TTF_VERSION_PATCH)
+endif()
+
+set(SDL2_TTF_LIBRARIES ${SDL2_TTF_LIBRARY})
+set(SDL2_TTF_INCLUDE_DIRS ${SDL2_TTF_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_ttf
+ REQUIRED_VARS SDL2_TTF_LIBRARIES SDL2_TTF_INCLUDE_DIRS
+ VERSION_VAR SDL2_TTF_VERSION_STRING)
+
+mark_as_advanced(SDL2_TTF_LIBRARY SDL2_TTF_INCLUDE_DIR)
diff --git a/cmake_modules/kitware license.txt b/cmake_modules/kitware license.txt
new file mode 100644
index 000000000..214d7dea8
--- /dev/null
+++ b/cmake_modules/kitware license.txt
@@ -0,0 +1,57 @@
+CMake - Cross Platform Makefile Generator
+Copyright 2000-2014 Kitware, Inc.
+Copyright 2000-2011 Insight Software Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the names of Kitware, Inc., the Insight Software Consortium,
+ nor the names of their contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+------------------------------------------------------------------------------
+
+The above copyright and license notice applies to distributions of
+CMake in source and binary form. Some source files contain additional
+notices of original copyright by their contributors; see each source
+for details. Third-party software packages supplied with CMake under
+compatible licenses provide their own copyright notices documented in
+corresponding subdirectories.
+
+------------------------------------------------------------------------------
+
+CMake was initially developed by Kitware with the following sponsorship:
+
+ * National Library of Medicine at the National Institutes of Health
+ as part of the Insight Segmentation and Registration Toolkit (ITK).
+
+ * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
+ Visualization Initiative.
+
+ * National Alliance for Medical Image Computing (NAMIC) is funded by the
+ National Institutes of Health through the NIH Roadmap for Medical Research,
+ Grant U54 EB005149.
+
+ * Kitware, Inc.
diff --git a/config/schemas/settings.json b/config/schemas/settings.json
index a4ba582a3..5bde69253 100644
--- a/config/schemas/settings.json
+++ b/config/schemas/settings.json
@@ -49,7 +49,7 @@
"type" : "object",
"additionalProperties" : false,
"default": {},
- "required" : [ "screenRes", "bitsPerPixel", "fullscreen", "spellbookAnimation" ],
+ "required" : [ "screenRes", "bitsPerPixel", "fullscreen", "spellbookAnimation","driver"],
"properties" : {
"screenRes" : {
"type" : "object",
@@ -63,7 +63,7 @@
},
"bitsPerPixel" : {
"type" : "number",
- "default" : 24
+ "default" : 32
},
"fullscreen" : {
"type" : "boolean",
@@ -73,6 +73,11 @@
"type" : "boolean",
"default" : true
},
+ "driver":{
+ "type" : "string",
+ "default" : "opengl",
+ "description" : "preferred graphics backend driver name for SDL2"
+ }
}
},
"adventure" : {
diff --git a/debian/rules b/debian/rules
index f3b8dfbc6..0cb46f89d 100755
--- a/debian/rules
+++ b/debian/rules
@@ -5,7 +5,7 @@
# override disabled by default rpath - we need to find libvcmi.so with it:
override_dh_auto_configure:
- dh_auto_configure -- -DCMAKE_SKIP_RPATH=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBIN_DIR=games
+ dh_auto_configure -- -DCMAKE_SKIP_RPATH=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_SDL2=OFF -DBIN_DIR=games
.PHONY: override_dh_strip
override_dh_strip:
dh_strip --dbg-package=vcmi-dbg
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index b778d1885..9bc5ca2d8 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -51,7 +51,12 @@ set(CMAKE_CXX_FLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS} ${CMAKE_CXX_FLAGS}")
qt5_wrap_ui(launcher_UI_HEADERS ${launcher_FORMS})
-add_executable(vcmilauncher ${launcher_SRCS} ${launcher_UI_HEADERS})
+if(WIN32)
+ add_executable(vcmilauncher WIN32 ${launcher_SRCS} ${launcher_UI_HEADERS})
+ set_target_properties(vcmilauncher PROPERTIES OUTPUT_NAME VCMI_launcher)
+else()
+ add_executable(vcmilauncher ${launcher_SRCS} ${launcher_UI_HEADERS})
+endif()
# The Qt5Widgets_LIBRARIES variable also includes QtGui and QtCore
target_link_libraries(vcmilauncher vcmi ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIBRARIES})
@@ -61,7 +66,7 @@ target_link_libraries(vcmilauncher vcmi ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIB
#cotire(vcmilauncher)
if (NOT APPLE) # Already inside bundle
- install(TARGETS vcmilauncher DESTINATION ${BIN_DIR})
+ install(TARGETS vcmilauncher DESTINATION ${BIN_DIR})
# copy whole directory but .svn control files
install(DIRECTORY icons DESTINATION ${DATA_DIR}/launcher PATTERN ".svn" EXCLUDE)
endif()
diff --git a/lib/CGeneralTextHandler.cpp b/lib/CGeneralTextHandler.cpp
index 6cd415dc8..c31261a27 100644
--- a/lib/CGeneralTextHandler.cpp
+++ b/lib/CGeneralTextHandler.cpp
@@ -19,7 +19,7 @@
*
*/
-size_t Unicode::getCharacterSize(ui8 firstByte)
+size_t Unicode::getCharacterSize(char firstByte)
{
// length of utf-8 character can be determined from 1st byte by counting number of highest bits set to 1:
// 0xxxxxxx -> 1 - ASCII chars
@@ -27,14 +27,14 @@ size_t Unicode::getCharacterSize(ui8 firstByte)
// 11110xxx -> 4 - last allowed in current standard
// 1111110x -> 6 - last allowed in original standard
- if (firstByte < 0x80)
+ if ((ui8)firstByte < 0x80)
return 1; // ASCII
size_t ret = 0;
for (size_t i=0; i<8; i++)
{
- if ((firstByte & (0x80 >> i)) != 0)
+ if (((ui8)firstByte & (0x80 >> i)) != 0)
ret++;
else
break;
@@ -42,12 +42,15 @@ size_t Unicode::getCharacterSize(ui8 firstByte)
return ret;
}
-bool Unicode::isValidCharacter(const ui8 *character, size_t maxSize)
+bool Unicode::isValidCharacter(const char * character, size_t maxSize)
{
+ // can't be first byte in UTF8
+ if ((ui8)character[0] >= 0x80 && (ui8)character[0] < 0xC0)
+ return false;
// first character must follow rules checked in getCharacterSize
- size_t size = getCharacterSize(character[0]);
+ size_t size = getCharacterSize((ui8)character[0]);
- if (character[0] > 0xF4)
+ if ((ui8)character[0] > 0xF4)
return false; // above maximum allowed in standard (UTF codepoints are capped at 0x0010FFFF)
if (size > maxSize)
@@ -56,7 +59,7 @@ bool Unicode::isValidCharacter(const ui8 *character, size_t maxSize)
// remaining characters must have highest bit set to 1
for (size_t i = 1; i < size; i++)
{
- if ((character[i] & 0x80) == 0)
+ if (((ui8)character[i] & 0x80) == 0)
return false;
}
return true;
@@ -82,7 +85,7 @@ bool Unicode::isValidString(const std::string & text)
{
for (size_t i=0; i(text.data() + i), text.size() - i))
+ if (!isValidCharacter(text.data() + i, text.size() - i))
return false;
}
return true;
@@ -92,7 +95,7 @@ bool Unicode::isValidString(const char * data, size_t size)
{
for (size_t i=0; i(data + i), size - i))
+ if (!isValidCharacter(data + i, size - i))
return false;
}
return true;
@@ -123,6 +126,35 @@ std::string Unicode::fromUnicode(const std::string &text, const std::string &enc
return boost::locale::conv::from_utf(text, encoding);
}
+void Unicode::trimRight(std::string & text, const size_t amount/* =1 */)
+{
+ if(text.empty())
+ return;
+ //todo: more efficient algorithm
+ for(int i = 0; i< amount; i++){
+ auto b = text.begin();
+ auto e = text.end();
+ size_t lastLen = 0;
+ size_t len = 0;
+ while (b != e) {
+ lastLen = len;
+ size_t n = getCharacterSize(*b);
+
+ if(!isValidCharacter(&(*b),e-b))
+ {
+ logGlobal->errorStream() << "Invalid UTF8 sequence";
+ break;//invalid sequence will be trimmed
+ }
+
+ len += n;
+ b += n;
+ }
+
+ text.resize(lastLen);
+ }
+}
+
+
//Helper for string -> float conversion
class LocaleWithComma: public std::numpunct
{
diff --git a/lib/CGeneralTextHandler.h b/lib/CGeneralTextHandler.h
index 269331b0e..a80531cfd 100644
--- a/lib/CGeneralTextHandler.h
+++ b/lib/CGeneralTextHandler.h
@@ -16,11 +16,11 @@
namespace Unicode
{
/// evaluates size of UTF-8 character
- size_t DLL_LINKAGE getCharacterSize(ui8 firstByte);
+ size_t DLL_LINKAGE getCharacterSize(char firstByte);
/// test if character is a valid UTF-8 symbol
/// maxSize - maximum number of bytes this symbol may consist from ( = remainer of string)
- bool DLL_LINKAGE isValidCharacter(const ui8 *character, size_t maxSize);
+ bool DLL_LINKAGE isValidCharacter(const char * character, size_t maxSize);
/// test if text contains ASCII-string (no need for unicode conversion)
bool DLL_LINKAGE isValidASCII(const std::string & text);
@@ -38,6 +38,9 @@ namespace Unicode
/// NOTE: usage of these functions should be avoided if possible
std::string DLL_LINKAGE fromUnicode(const std::string & text);
std::string DLL_LINKAGE fromUnicode(const std::string & text, const std::string & encoding);
+
+ ///delete (amount) UTF characters from right
+ DLL_LINKAGE void trimRight(std::string & text, const size_t amount = 1);
};
class CInputStream;
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 62764080e..d777b94be 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -95,7 +95,7 @@ set(lib_SRCS
registerTypes/TypesClientPacks2.cpp
registerTypes/TypesMapObjects1.cpp
registerTypes/TypesMapObjects2.cpp
- registerTypes/TypesMapObjects3.cpp
+ registerTypes/TypesMapObjects3.cpp
registerTypes/TypesPregamePacks.cpp
registerTypes/TypesServerPacks.cpp
)
@@ -132,11 +132,16 @@ set(lib_HEADERS
add_library(vcmi SHARED ${lib_SRCS} ${lib_HEADERS})
set_target_properties(vcmi PROPERTIES XCODE_ATTRIBUTE_LD_DYLIB_INSTALL_NAME "@rpath/libvcmi.dylib")
-target_link_libraries(vcmi minizip ${Boost_LIBRARIES} ${SDL_LIBRARY} ${ZLIB_LIBRARIES} ${RT_LIB} ${DL_LIB})
+set_target_properties(vcmi PROPERTIES COMPILE_DEFINITIONS "VCMI_DLL=1")
+target_link_libraries(vcmi minizip ${Boost_LIBRARIES} ${SDL_LIBRARY} ${ZLIB_LIBRARIES} ${SYSTEM_LIBS})
+
+if(WIN32)
+ set_target_properties(vcmi PROPERTIES OUTPUT_NAME VCMI_lib)
+endif()
set_target_properties(vcmi PROPERTIES ${PCH_PROPERTIES})
cotire(vcmi)
if (NOT APPLE) # Already inside vcmiclient bundle
- install(TARGETS vcmi DESTINATION ${LIB_DIR})
+ install(TARGETS vcmi RUNTIME DESTINATION ${LIB_DIR} LIBRARY DESTINATION ${LIB_DIR})
endif()
diff --git a/lib/NetPacks.h b/lib/NetPacks.h
index 61cfedba6..97639cf12 100644
--- a/lib/NetPacks.h
+++ b/lib/NetPacks.h
@@ -305,16 +305,17 @@ struct SetMovePoints : public CPackForClient //111
struct FoWChange : public CPackForClient //112
{
- FoWChange(){type = 112;};
+ FoWChange(){type = 112;waitForDialogs = false;};
void applyCl(CClient *cl);
DLL_LINKAGE void applyGs(CGameState *gs);
std::unordered_set tiles;
PlayerColor player;
ui8 mode; //mode==0 - hide, mode==1 - reveal
+ bool waitForDialogs;
template void serialize(Handler &h, const int version)
{
- h & tiles & player & mode;
+ h & tiles & player & mode & waitForDialogs;
}
};
diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp
index c2f0ef924..85c383cac 100644
--- a/lib/NetPacksLib.cpp
+++ b/lib/NetPacksLib.cpp
@@ -263,8 +263,7 @@ DLL_LINKAGE void GiveBonus::applyGs( CGameState *gs )
if(!bdescr.message.size()
&& bonus.source == Bonus::OBJECT
- && (bonus.type == Bonus::LUCK || bonus.type == Bonus::MORALE)
- && gs->map->objects[bonus.sid]->ID == Obj::EVENT) //it's morale/luck bonus from an event without description
+ && (bonus.type == Bonus::LUCK || bonus.type == Bonus::MORALE))
{
descr = VLC->generaltexth->arraytxt[bonus.val > 0 ? 110 : 109]; //+/-%d Temporary until next battle"
}
diff --git a/lib/VCMI_lib.cbp b/lib/VCMI_lib.cbp
index 83a15af5b..5090a46b3 100644
--- a/lib/VCMI_lib.cbp
+++ b/lib/VCMI_lib.cbp
@@ -7,7 +7,7 @@
-
+
@@ -19,9 +19,13 @@
+
+
+
+
-
+
@@ -31,9 +35,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -50,14 +91,14 @@
+
-
-
+
@@ -65,7 +106,7 @@
-
+
diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp
index 9339c811a..57680916b 100644
--- a/lib/mapObjects/MiscObjects.cpp
+++ b/lib/mapObjects/MiscObjects.cpp
@@ -1327,6 +1327,7 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
FoWChange fw;
fw.player = h->tempOwner;
fw.mode = 1;
+ fw.waitForDialogs = true;
for(auto it : eyelist[subID])
{
diff --git a/lib/minizip/CMakeLists.txt b/lib/minizip/CMakeLists.txt
index bf4e8b95d..f80e9b383 100644
--- a/lib/minizip/CMakeLists.txt
+++ b/lib/minizip/CMakeLists.txt
@@ -16,5 +16,5 @@ set_target_properties(minizip PROPERTIES XCODE_ATTRIBUTE_LD_DYLIB_INSTALL_NAME "
target_link_libraries(minizip ${ZLIB_LIBRARIES})
if (NOT APPLE) # Already inside vcmiclient bundle
- install(TARGETS minizip DESTINATION ${LIB_DIR})
+ install(TARGETS minizip RUNTIME DESTINATION ${LIB_DIR} LIBRARY DESTINATION ${LIB_DIR})
endif()
diff --git a/lib/minizip/minizip.cbp b/lib/minizip/minizip.cbp
index 81c6c8769..84c247929 100644
--- a/lib/minizip/minizip.cbp
+++ b/lib/minizip/minizip.cbp
@@ -6,7 +6,7 @@
-
+
@@ -19,7 +19,37 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -36,11 +66,11 @@
-
+
-
-
+
+
diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt
index fd97b656e..44d0c1fda 100644
--- a/server/CMakeLists.txt
+++ b/server/CMakeLists.txt
@@ -6,25 +6,25 @@ include_directories(${Boost_INCLUDE_DIRS})
set(server_SRCS
StdInc.cpp
- CGameHandler.cpp
- CVCMIServer.cpp
- CQuery.cpp
- NetPacksServer.cpp
+ CGameHandler.cpp
+ CVCMIServer.cpp
+ CQuery.cpp
+ NetPacksServer.cpp
)
-if(WIN32)
- add_executable(vcmiserver WIN32 ${server_SRCS})
-else()
- add_executable(vcmiserver ${server_SRCS})
-endif()
+add_executable(vcmiserver ${server_SRCS})
-target_link_libraries(vcmiserver vcmi ${Boost_LIBRARIES} ${RT_LIB} ${DL_LIB})
+target_link_libraries(vcmiserver vcmi ${Boost_LIBRARIES} ${SYSTEM_LIBS})
+
+if(WIN32)
+ set_target_properties(vcmiserver PROPERTIES OUTPUT_NAME VCMI_server)
+endif()
set_target_properties(vcmiserver PROPERTIES ${PCH_PROPERTIES})
set_target_properties(vcmiserver PROPERTIES XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks @executable_path/")
cotire(vcmiserver)
if (NOT APPLE) # Already inside vcmiclient bundle
- install(TARGETS vcmiserver DESTINATION ${BIN_DIR})
+ install(TARGETS vcmiserver DESTINATION ${BIN_DIR})
endif()
diff --git a/server/VCMI_server.cbp b/server/VCMI_server.cbp
index 53d4fec99..83b381f2f 100644
--- a/server/VCMI_server.cbp
+++ b/server/VCMI_server.cbp
@@ -6,25 +6,59 @@
-
+
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -42,8 +76,8 @@
+
-
diff --git a/test/Test.cbp b/test/Test.cbp
index a15ea9d08..eca595705 100644
--- a/test/Test.cbp
+++ b/test/Test.cbp
@@ -6,7 +6,20 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+