Bläddra i källkod

Merge branch 'develop' of https://github.com/vcmi/vcmi into RMG

DjWarmonger 11 år sedan
förälder
incheckning
173111955e
73 ändrade filer med 2840 tillägg och 811 borttagningar
  1. 62 0
      .travis.yml
  2. 27 2
      AI/BattleAI/BattleAI.cbp
  3. 1 1
      AI/BattleAI/CMakeLists.txt
  4. 1 1
      AI/EmptyAI/CMakeLists.txt
  5. 28 2
      AI/EmptyAI/EmptyAI.cbp
  6. 3 1
      AI/FuzzyLite/CMakeLists.txt
  7. 160 130
      AI/FuzzyLite/FuzzyLite.cbp
  8. 1 1
      AI/StupidAI/CMakeLists.txt
  9. 28 2
      AI/StupidAI/StupidAI.cbp
  10. 1 1
      AI/VCAI/CMakeLists.txt
  11. 32 2
      AI/VCAI/VCAI.cbp
  12. 94 36
      CMakeLists.txt
  13. 5 0
      Global.h
  14. 2 2
      client/AdventureMapClasses.cpp
  15. 10 7
      client/CAdvmapInterface.cpp
  16. 40 8
      client/CAnimation.cpp
  17. 7 14
      client/CBitmapHandler.cpp
  18. 28 6
      client/CDefHandler.cpp
  19. 340 100
      client/CMT.cpp
  20. 12 1
      client/CMT.h
  21. 83 85
      client/CMakeLists.txt
  22. 2 2
      client/CMessage.cpp
  23. 15 4
      client/CMusicHandler.cpp
  24. 168 122
      client/CPlayerInterface.cpp
  25. 35 4
      client/CPlayerInterface.h
  26. 7 6
      client/CPreGame.cpp
  27. 3 2
      client/CPreGame.h
  28. 64 19
      client/CVideoHandler.cpp
  29. 7 2
      client/CVideoHandler.h
  30. 37 3
      client/GUIClasses.cpp
  31. 5 0
      client/GUIClasses.h
  32. 38 13
      client/Graphics.cpp
  33. 6 1
      client/NetPacksClient.cpp
  34. 3 1
      client/StdInc.h
  35. 60 8
      client/VCMI_client.cbp
  36. 1 0
      client/VCMI_client.vcxproj
  37. 1 0
      client/VCMI_client.vcxproj.filters
  38. 2 2
      client/battle/CBattleInterface.cpp
  39. 24 6
      client/battle/CCreatureAnimation.cpp
  40. 12 0
      client/gui/CCursorHandler.cpp
  41. 9 7
      client/gui/CCursorHandler.h
  42. 116 44
      client/gui/CGuiHandler.cpp
  43. 8 3
      client/gui/CGuiHandler.h
  44. 6 0
      client/gui/CIntObject.cpp
  45. 24 11
      client/gui/CIntObject.h
  46. 98 19
      client/gui/CIntObjectClasses.cpp
  47. 14 1
      client/gui/CIntObjectClasses.h
  48. 37 0
      client/gui/SDL_Compat.h
  49. 101 2
      client/gui/SDL_Extensions.cpp
  50. 96 8
      client/gui/SDL_Extensions.h
  51. 9 1
      client/gui/SDL_Pixels.h
  52. 76 43
      client/mapHandler.cpp
  53. 0 27
      cmake_modules/COPYING-CMAKE-SCRIPTS
  54. 216 0
      cmake_modules/FindSDL2.cmake
  55. 100 0
      cmake_modules/FindSDL2_image.cmake
  56. 101 0
      cmake_modules/FindSDL2_mixer.cmake
  57. 100 0
      cmake_modules/FindSDL2_ttf.cmake
  58. 57 0
      cmake_modules/kitware license.txt
  59. 7 2
      config/schemas/settings.json
  60. 1 1
      debian/rules
  61. 7 2
      launcher/CMakeLists.txt
  62. 41 9
      lib/CGeneralTextHandler.cpp
  63. 5 2
      lib/CGeneralTextHandler.h
  64. 8 3
      lib/CMakeLists.txt
  65. 3 2
      lib/NetPacks.h
  66. 1 2
      lib/NetPacksLib.cpp
  67. 46 5
      lib/VCMI_lib.cbp
  68. 1 0
      lib/mapObjects/MiscObjects.cpp
  69. 1 1
      lib/minizip/CMakeLists.txt
  70. 35 5
      lib/minizip/minizip.cbp
  71. 10 10
      server/CMakeLists.txt
  72. 37 3
      server/VCMI_server.cbp
  73. 14 1
      test/Test.cbp

+ 62 - 0
.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:
+      - [email protected]
+      - [email protected]
+    on_success: change
+    on_failure: always

+ 27 - 2
AI/BattleAI/BattleAI.cbp

@@ -6,7 +6,8 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
+				<Option platforms="Windows;" />
 				<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Debug/" />
 				<Option type="3" />
@@ -15,7 +16,31 @@
 					<Add option="-g" />
 				</Compiler>
 			</Target>
-			<Target title="Release">
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-O2" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-g" />
+				</Compiler>
+			</Target>
+			<Target title="Release-win32-SDL1">
+				<Option platforms="Windows;" />
 				<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Release/" />
 				<Option type="3" />

+ 1 - 1
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()
 

+ 1 - 1
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()

+ 28 - 2
AI/EmptyAI/EmptyAI.cbp

@@ -6,7 +6,8 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
+				<Option platforms="Windows;" />
 				<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Debug/" />
 				<Option type="3" />
@@ -15,7 +16,32 @@
 					<Add option="-ggdb" />
 				</Compiler>
 			</Target>
-			<Target title="Release">
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O3" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-ggdb" />
+				</Compiler>
+			</Target>
+			<Target title="Release-win32-SDL1">
+				<Option platforms="Windows;" />
 				<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Release/" />
 				<Option type="3" />

+ 3 - 1
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()

+ 160 - 130
AI/FuzzyLite/FuzzyLite.cbp

@@ -1,130 +1,160 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<CodeBlocks_project_file>
-	<FileVersion major="1" minor="6" />
-	<Project>
-		<Option title="FuzzyLite" />
-		<Option pch_mode="2" />
-		<Option compiler="gcc" />
-		<Build>
-			<Target title="Debug">
-				<Option output="bin\Debug\FuzzyLite" prefix_auto="1" extension_auto="1" />
-				<Option working_dir="" />
-				<Option object_output="obj\Debug\" />
-				<Option type="2" />
-				<Option compiler="gcc" />
-				<Option createDefFile="1" />
-				<Compiler>
-					<Add option="-g" />
-				</Compiler>
-			</Target>
-			<Target title="Release">
-				<Option output="bin\Release\FuzzyLite" prefix_auto="1" extension_auto="1" />
-				<Option working_dir="" />
-				<Option object_output="obj\Release\" />
-				<Option type="2" />
-				<Option compiler="gcc" />
-				<Option createDefFile="1" />
-				<Compiler>
-					<Add option="-fomit-frame-pointer" />
-					<Add option="-O2" />
-				</Compiler>
-				<Linker>
-					<Add option="-s" />
-				</Linker>
-			</Target>
-		</Build>
-		<Compiler>
-			<Add option="-Wextra" />
-			<Add option="-Wall" />
-			<Add option="-fexceptions" />
-			<Add option="-Wpointer-arith" />
-			<Add option="-Wno-switch" />
-			<Add option="-Wno-sign-compare" />
-			<Add option="-Wno-unused-parameter" />
-			<Add option="-Wno-overloaded-virtual" />
-		</Compiler>
-		<Unit filename="AreaCentroidAlgorithm.cpp" />
-		<Unit filename="AreaCentroidAlgorithm.h" />
-		<Unit filename="CompoundTerm.cpp" />
-		<Unit filename="CompoundTerm.h" />
-		<Unit filename="DescriptiveAntecedent.cpp" />
-		<Unit filename="DescriptiveAntecedent.h" />
-		<Unit filename="DiscreteTerm.cpp" />
-		<Unit filename="DiscreteTerm.h" />
-		<Unit filename="FunctionTerm.cpp" />
-		<Unit filename="FunctionTerm.h" />
-		<Unit filename="FuzzyAnd.cpp" />
-		<Unit filename="FuzzyAnd.h" />
-		<Unit filename="FuzzyAntecedent.cpp" />
-		<Unit filename="FuzzyAntecedent.h" />
-		<Unit filename="FuzzyConsequent.cpp" />
-		<Unit filename="FuzzyConsequent.h" />
-		<Unit filename="FuzzyDefuzzifier.cpp" />
-		<Unit filename="FuzzyDefuzzifier.h" />
-		<Unit filename="FuzzyEngine.cpp" />
-		<Unit filename="FuzzyEngine.h" />
-		<Unit filename="FuzzyException.cpp" />
-		<Unit filename="FuzzyException.h" />
-		<Unit filename="FuzzyExceptions.cpp" />
-		<Unit filename="FuzzyExceptions.h" />
-		<Unit filename="FuzzyLite.h" />
-		<Unit filename="FuzzyModulation.cpp" />
-		<Unit filename="FuzzyModulation.h" />
-		<Unit filename="FuzzyOperation.cpp" />
-		<Unit filename="FuzzyOperation.h" />
-		<Unit filename="FuzzyOperator.cpp" />
-		<Unit filename="FuzzyOperator.h" />
-		<Unit filename="FuzzyOr.cpp" />
-		<Unit filename="FuzzyOr.h" />
-		<Unit filename="FuzzyRule.cpp" />
-		<Unit filename="FuzzyRule.h" />
-		<Unit filename="Hedge.cpp" />
-		<Unit filename="Hedge.h" />
-		<Unit filename="HedgeSet.cpp" />
-		<Unit filename="HedgeSet.h" />
-		<Unit filename="InfixToPostfix.cpp" />
-		<Unit filename="InfixToPostfix.h" />
-		<Unit filename="InputLVar.cpp" />
-		<Unit filename="InputLVar.h" />
-		<Unit filename="LinguisticTerm.cpp" />
-		<Unit filename="LinguisticTerm.h" />
-		<Unit filename="LinguisticVariable.cpp" />
-		<Unit filename="LinguisticVariable.h" />
-		<Unit filename="MamdaniConsequent.cpp" />
-		<Unit filename="MamdaniConsequent.h" />
-		<Unit filename="MamdaniRule.cpp" />
-		<Unit filename="MamdaniRule.h" />
-		<Unit filename="OutputLVar.cpp" />
-		<Unit filename="OutputLVar.h" />
-		<Unit filename="RectangularTerm.cpp" />
-		<Unit filename="RectangularTerm.h" />
-		<Unit filename="RuleBlock.cpp" />
-		<Unit filename="RuleBlock.h" />
-		<Unit filename="ShoulderTerm.cpp" />
-		<Unit filename="ShoulderTerm.h" />
-		<Unit filename="SingletonTerm.cpp" />
-		<Unit filename="SingletonTerm.h" />
-		<Unit filename="StrOp.cpp" />
-		<Unit filename="StrOp.h" />
-		<Unit filename="TakagiSugenoConsequent.cpp" />
-		<Unit filename="TakagiSugenoConsequent.h" />
-		<Unit filename="TakagiSugenoRule.cpp" />
-		<Unit filename="TakagiSugenoRule.h" />
-		<Unit filename="TakagiSugenoTerm.cpp" />
-		<Unit filename="TakagiSugenoTerm.h" />
-		<Unit filename="TrapezoidalTerm.cpp" />
-		<Unit filename="TrapezoidalTerm.h" />
-		<Unit filename="TriangularTerm.cpp" />
-		<Unit filename="TriangularTerm.h" />
-		<Unit filename="defs.h" />
-		<Unit filename="flScalar.h" />
-		<Unit filename="main.cpp" />
-		<Unit filename="test.h" />
-		<Extensions>
-			<code_completion />
-			<envvars />
-			<debugger />
-			<lib_finder disable_auto="1" />
-		</Extensions>
-	</Project>
-</CodeBlocks_project_file>
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="FuzzyLite" />
+		<Option pch_mode="2" />
+		<Option compiler="gcc" />
+		<Build>
+			<Target title="Debug-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="bin/Debug/FuzzyLite" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="" />
+				<Option object_output="obj/Debug/" />
+				<Option type="2" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Compiler>
+					<Add option="-g" />
+				</Compiler>
+			</Target>
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="bin/Release/FuzzyLite" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="" />
+				<Option object_output="obj/Release/" />
+				<Option type="2" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Compiler>
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O2" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="bin/Debug/FuzzyLite" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="" />
+				<Option object_output="obj/Debug/" />
+				<Option type="2" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Compiler>
+					<Add option="-g" />
+				</Compiler>
+			</Target>
+			<Target title="Release-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="bin/Release/FuzzyLite" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="" />
+				<Option object_output="obj/Release/" />
+				<Option type="2" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Compiler>
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O2" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="-Wextra" />
+			<Add option="-Wall" />
+			<Add option="-fexceptions" />
+			<Add option="-Wpointer-arith" />
+			<Add option="-Wno-switch" />
+			<Add option="-Wno-sign-compare" />
+			<Add option="-Wno-unused-parameter" />
+			<Add option="-Wno-overloaded-virtual" />
+		</Compiler>
+		<Unit filename="AreaCentroidAlgorithm.cpp" />
+		<Unit filename="AreaCentroidAlgorithm.h" />
+		<Unit filename="CompoundTerm.cpp" />
+		<Unit filename="CompoundTerm.h" />
+		<Unit filename="DescriptiveAntecedent.cpp" />
+		<Unit filename="DescriptiveAntecedent.h" />
+		<Unit filename="DiscreteTerm.cpp" />
+		<Unit filename="DiscreteTerm.h" />
+		<Unit filename="FunctionTerm.cpp" />
+		<Unit filename="FunctionTerm.h" />
+		<Unit filename="FuzzyAnd.cpp" />
+		<Unit filename="FuzzyAnd.h" />
+		<Unit filename="FuzzyAntecedent.cpp" />
+		<Unit filename="FuzzyAntecedent.h" />
+		<Unit filename="FuzzyConsequent.cpp" />
+		<Unit filename="FuzzyConsequent.h" />
+		<Unit filename="FuzzyDefuzzifier.cpp" />
+		<Unit filename="FuzzyDefuzzifier.h" />
+		<Unit filename="FuzzyEngine.cpp" />
+		<Unit filename="FuzzyEngine.h" />
+		<Unit filename="FuzzyException.cpp" />
+		<Unit filename="FuzzyException.h" />
+		<Unit filename="FuzzyExceptions.cpp" />
+		<Unit filename="FuzzyExceptions.h" />
+		<Unit filename="FuzzyLite.h" />
+		<Unit filename="FuzzyModulation.cpp" />
+		<Unit filename="FuzzyModulation.h" />
+		<Unit filename="FuzzyOperation.cpp" />
+		<Unit filename="FuzzyOperation.h" />
+		<Unit filename="FuzzyOperator.cpp" />
+		<Unit filename="FuzzyOperator.h" />
+		<Unit filename="FuzzyOr.cpp" />
+		<Unit filename="FuzzyOr.h" />
+		<Unit filename="FuzzyRule.cpp" />
+		<Unit filename="FuzzyRule.h" />
+		<Unit filename="Hedge.cpp" />
+		<Unit filename="Hedge.h" />
+		<Unit filename="HedgeSet.cpp" />
+		<Unit filename="HedgeSet.h" />
+		<Unit filename="InfixToPostfix.cpp" />
+		<Unit filename="InfixToPostfix.h" />
+		<Unit filename="InputLVar.cpp" />
+		<Unit filename="InputLVar.h" />
+		<Unit filename="LinguisticTerm.cpp" />
+		<Unit filename="LinguisticTerm.h" />
+		<Unit filename="LinguisticVariable.cpp" />
+		<Unit filename="LinguisticVariable.h" />
+		<Unit filename="MamdaniConsequent.cpp" />
+		<Unit filename="MamdaniConsequent.h" />
+		<Unit filename="MamdaniRule.cpp" />
+		<Unit filename="MamdaniRule.h" />
+		<Unit filename="OutputLVar.cpp" />
+		<Unit filename="OutputLVar.h" />
+		<Unit filename="RectangularTerm.cpp" />
+		<Unit filename="RectangularTerm.h" />
+		<Unit filename="RuleBlock.cpp" />
+		<Unit filename="RuleBlock.h" />
+		<Unit filename="ShoulderTerm.cpp" />
+		<Unit filename="ShoulderTerm.h" />
+		<Unit filename="SingletonTerm.cpp" />
+		<Unit filename="SingletonTerm.h" />
+		<Unit filename="StrOp.cpp" />
+		<Unit filename="StrOp.h" />
+		<Unit filename="TakagiSugenoConsequent.cpp" />
+		<Unit filename="TakagiSugenoConsequent.h" />
+		<Unit filename="TakagiSugenoRule.cpp" />
+		<Unit filename="TakagiSugenoRule.h" />
+		<Unit filename="TakagiSugenoTerm.cpp" />
+		<Unit filename="TakagiSugenoTerm.h" />
+		<Unit filename="TrapezoidalTerm.cpp" />
+		<Unit filename="TrapezoidalTerm.h" />
+		<Unit filename="TriangularTerm.cpp" />
+		<Unit filename="TriangularTerm.h" />
+		<Unit filename="defs.h" />
+		<Unit filename="flScalar.h" />
+		<Unit filename="main.cpp" />
+		<Unit filename="test.h" />
+		<Extensions>
+			<code_completion />
+			<envvars />
+			<debugger />
+			<lib_finder disable_auto="1" />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>

+ 1 - 1
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()
 

+ 28 - 2
AI/StupidAI/StupidAI.cbp

@@ -6,7 +6,8 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
+				<Option platforms="Windows;" />
 				<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Debug/" />
 				<Option type="3" />
@@ -15,7 +16,32 @@
 					<Add option="-ggdb" />
 				</Compiler>
 			</Target>
-			<Target title="Release">
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O3" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-ggdb" />
+				</Compiler>
+			</Target>
+			<Target title="Release-win32-SDL1">
+				<Option platforms="Windows;" />
 				<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Release/" />
 				<Option type="3" />

+ 1 - 1
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()

+ 32 - 2
AI/VCAI/VCAI.cbp

@@ -6,7 +6,8 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
+				<Option platforms="Windows;" />
 				<Option output="../VCAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Debug/" />
 				<Option type="3" />
@@ -18,7 +19,36 @@
 					<Add directory="../FuzzyLite/bin/Debug" />
 				</Linker>
 			</Target>
-			<Target title="Release">
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../VCAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O3" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+					<Add directory="../FuzzyLite/bin/Release" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="../VCAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-g" />
+				</Compiler>
+				<Linker>
+					<Add directory="../FuzzyLite/bin/Debug" />
+				</Linker>
+			</Target>
+			<Target title="Release-win32-SDL1">
+				<Option platforms="Windows;" />
 				<Option output="../VCAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Release/" />
 				<Option type="3" />

+ 94 - 36
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,56 +54,94 @@ if (APPLE)
 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=256")
 endif()
 
-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)
-include(cotire)
+if (WIN32)
+	add_definitions(-DBOOST_THREAD_USE_LIB)
+	add_definitions(-D_WIN32_WINNT=0x0501)
+	set(SYSTEM_LIBS ${SYSTEM_LIBS} ole32 oleaut32 ws2_32 mswsock)
 
-if (ENABLE_EDITOR OR ENABLE_LAUNCHER)
-	# Widgets finds its own dependencies (QtGui and QtCore).
-	find_package(Qt5Widgets REQUIRED)
-endif()
+	#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()
 
-if (ENABLE_LAUNCHER)
-	find_package(Qt5Network REQUIRED)
-endif()
+	#delete lib prefix for dlls
+	set(CMAKE_SHARED_LIBRARY_PREFIX "") 
 
-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)
+	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(Boost_LIBRARIES ${Boost_LIBRARIES} libiconv.dylib) # Our prebuilt boost_locale for OS X depends on iconv
+	set(SYSTEM_LIBS ${SYSTEM_LIBS} libiconv.dylib)
 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 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)
+		set(SYSTEM_LIBS ${SYSTEM_LIBS} rt)
 	endif()
 
 	CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_DL_LIB)
 	if(HAVE_DL_LIB)
-		set(DL_LIB -ldl)
+		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(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)
+	# Widgets finds its own dependencies (QtGui and QtCore).
+	find_package(Qt5Widgets REQUIRED)
+endif()
+
+if (ENABLE_LAUNCHER)
+	find_package(Qt5Network REQUIRED)
+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(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

+ 5 - 0
Global.h

@@ -100,6 +100,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
 #include <boost/date_time/posix_time/posix_time_io.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/format.hpp>
+#include <boost/functional/hash.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/logic/tribool.hpp>
 #include <boost/optional.hpp>
@@ -116,6 +117,10 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
 #include <android/log.h>
 #endif
 
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
 /* ---------------------------------------------------------------------------- */
 /* Usings */
 /* ---------------------------------------------------------------------------- */

+ 2 - 2
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<ui16>(move->pos.h + 1, mana->pos.h + 1), img->pos.h);
+	pos.h = std::max(std::max<SDLX_Size>(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<ui16>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
+	pos.h = std::max(std::max<SDLX_Size>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
 
 	update();
 }

+ 10 - 7
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)
 		{

+ 40 - 8
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<size; i++)
 			{
 				SDL_Color col = palette[*(data++)];
+				#ifdef VCMI_SDL1
 				col.unused = (ui32)col.unused*alpha/255;
+				#else
+				col.a = (ui32)col.a*alpha/255;
+				#endif // 0				
 				ColorPutter<bpp, 1>::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<size; i++)
@@ -820,6 +841,7 @@ void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha)
 	//RLE-d sequence
 	else
 	{
+		#ifdef VCMI_SDL1
 		if (alpha != 255 && palette[type].unused !=0)//Per-surface alpha is set
 		{
 			SDL_Color col = palette[type];
@@ -827,9 +849,22 @@ void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha)
 			for (size_t i=0; i<size; i++)
 				ColorPutter<bpp, 1>::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<size; i++)
+				ColorPutter<bpp, 1>::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]);
 	}
 }
 

+ 7 - 14
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;
 }

+ 28 - 6
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;
 }
 

+ 340 - 100
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<bool> 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<SDL_Event> 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: "<<pomtime.getDiff();
-    logGlobal->infoStream()<<"Initializing screen and sound handling: "<<tmh.getDiff();
 
 	loadDLLClasses();
 	const_cast<CGameInfo*>(CGI)->setFromLib();
 
     logGlobal->infoStream()<<"Initializing VCMI_Lib: "<<tmh.getDiff();
 
-	pomtime.getDiff();
+
 	if(!gNoGUI)
 	{
+		pomtime.getDiff();
 		CCS->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: "<<tmh.getDiff();
+		logGlobal->infoStream()<<"\tMain graphics: "<<pomtime.getDiff();
 		logGlobal->infoStream()<<"Initializing game graphics: "<<tmh.getDiff();
 
 		CMessage::init();
@@ -257,10 +255,11 @@ int main(int argc, char** argv)
 		gNoGUI = true;
 		vm.insert(std::pair<std::string, po::variable_value>("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: "<<pomtime.getDiff();
 	}
 
-
 	CCS = new CClientState;
 	CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler etc.)
 	// Initialize video
-#if DISABLE_VIDEO
+#ifdef DISABLE_VIDEO
 	CCS->videoh = new CEmptyVideoPlayer;
 #else
 	if (!gNoGUI && !vm.count("disable-video"))
@@ -361,13 +388,26 @@ int main(int argc, char** argv)
 
     logGlobal->infoStream()<<"\tInitializing video: "<<pomtime.getDiff();
 
+#if defined(__ANDROID__)
+	//on Android threaded init is broken
+	#define VCMI_NO_THREADED_LOAD
+#endif // defined
 
+	//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()<<"Initializing screen and sound handling: "<<pomtime.getDiff();
 
-#ifndef __ANDROID__
+#ifndef VCMI_NO_THREADED_LOAD
 	//we can properly play intro only in the main thread, so we have to move loading to the separate thread
 	boost::thread loading(init);
-#else
-	// on Android threaded init is broken
+#else	 
 	init();
 #endif
 
@@ -379,7 +419,7 @@ int main(int argc, char** argv)
 	}
 
 	CSDL_Ext::update(screen);
-#ifndef __ANDROID__
+#ifndef VCMI_NO_THREADED_LOAD
 	loading.join();
 #endif
     logGlobal->infoStream()<<"Initialization of VCMI (together): "<<total.getDiff();
@@ -418,8 +458,7 @@ int main(int argc, char** argv)
 
 	if(!gNoGUI)
 	{
-		mainGUIThread = new boost::thread(&CGuiHandler::run, &GH);
-		listenForEvents();
+		mainLoop();
 	}
 	else
 	{
@@ -761,9 +800,176 @@ void dispose()
 	CMessage::dispose();
 }
 
+static bool checkVideoMode(int monitorIndex, int w, int h, int& bpp, bool fullscreen)
+{
+	#ifndef VCMI_SDL1
+	SDL_DisplayMode mode;
+	const int modeCount = SDL_GetNumDisplayModes(monitorIndex);
+	for (int i = 0; i < modeCount; i++) {
+		SDL_GetDisplayMode(0, i, &mode);
+		if (!mode.w || !mode.h || (w >= 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)
 {
-	SettingsListener resChanged = settings.listen["video"]["fullscreen"];
-	resChanged([](const JsonNode &newState){  CGuiHandler::pushSDLEvent(SDL_USEREVENT, FULLSCREEN_TOGGLED); });
-
-	while(1) //main SDL events loop
+	if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
 	{
-		SDL_Event ev;
+		handleQuit();	
+		return;
+	}
 
-		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)
+	#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)
 		{
-			switch(ev.user.code)
+		case RETURN_TO_MAIN_MENU:
 			{
-			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<StartInfo *>(ev.user.data1);
-					endGame();
-					startGame(si);
-				}
-				break;
-			case RETURN_TO_MENU_LOAD:
 				endGame();
-				CGPreGame::create();
+				GH.curInt = 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;
+			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<StartInfo *>(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<boost::mutex> 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))
 		{
-			boost::unique_lock<boost::mutex> lock(eventsM);
-			events.push(ev);
+			handleEvent(ev);
 		}
+		
+		GH.renderFrame();
+
 	}
 }
 
@@ -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));

+ 12 - 1
client/CMT.h

@@ -1,9 +1,20 @@
 #pragma once
 
+#ifndef VCMI_SDL1
+#include <SDL_render.h>
+
+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();
+void handleQuit();

+ 83 - 85
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
-
-        gui/CGuiHandler.cpp
-        gui/CIntObject.cpp
-        gui/CIntObjectClasses.cpp
-        gui/Fonts.cpp
-        gui/Geometries.cpp
-        gui/CCursorHandler.cpp
-        gui/SDL_Extensions.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
 
 		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(WIN32)
-	add_executable(vcmiclient WIN32 ${client_SRCS} ${client_HEADERS})
-elseif(APPLE)
-    # OS X specific includes
-    include_directories(${SPARKLE_INCLUDE_DIR})
+if(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})
-
-    # 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)
-
-    # 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/")
-
-    # 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 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})
+	# 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)
+
+	# 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)
+
+	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 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})
 else()
-	add_executable(vcmiclient ${client_SRCS} ${client_HEADERS})
+	add_executable(vcmiclient ${client_SRCS})
+endif()
+
+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} ${RT_LIB} ${DL_LIB})
+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)

+ 2 - 2
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<std::string> 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

+ 15 - 4
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()

+ 168 - 122
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<CLoadFile> &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<boost::mutex> 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<boost::recursive_mutex> 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<boost::shared_mutex> 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<void(IUpdateable * )> 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<boost::recursive_mutex> 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<boost::shared_mutex> 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<boost::mutex> 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<boost::mutex> 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;
+}

+ 35 - 4
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<void(IUpdateable * )> functor) override;
 	void initializeHeroTownList();
 	int getLastIndex(std::string namePrefix);
 
@@ -239,7 +240,7 @@ public:
 	void showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps = false, const std::vector<CComponent*> & components = std::vector<CComponent*>()); //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<bool> terminate_cond; // confirm termination
+	
+
 
-	//////////////////////////////////////////////////////////////////////////
+private:
 
 	template <typename Handler> 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;

+ 7 - 6
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<void(IUpdateable * )> cb)
+{
+	boost::unique_lock<boost::recursive_mutex> 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

+ 3 - 2
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<void(IUpdateable * )> cb) override;
 	void openSel(CMenuScreen::EState type, CMenuScreen::EMultiMode multi = CMenuScreen::SINGLE_PLAYER);
 
 	void openCampaignScreen(std::string name);

+ 64 - 19
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();

+ 7 - 2
client/CVideoHandler.h

@@ -221,7 +221,7 @@ public:
 
 #include <SDL.h>
 #include <SDL_video.h>
-#if SDL_VERSION_ATLEAST(1,3,0)
+#if SDL_VERSION_ATLEAST(1,3,0) && !SDL_VERSION_ATLEAST(2,0,0)
 #include <SDL_compat.h>
 #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

+ 37 - 3
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
 		}
 	}
 }

+ 5 - 0
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();

+ 38 - 13
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<Task> 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<std::vector<CDefEssential *> 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: "<<th.getDiff();
 }
 

+ 6 - 1
client/NetPacksClient.cpp

@@ -165,6 +165,11 @@ void SetMovePoints::applyCl( CClient *cl )
 void FoWChange::applyCl( CClient *cl )
 {
 	for(auto &i : cl->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();
 }
 

+ 3 - 1
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.
+// Here you can add specific libraries and macros which are specific to this project.

+ 60 - 8
client/VCMI_client.cbp

@@ -6,18 +6,69 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
+				<Option platforms="Windows;" />
 				<Option output="../VCMI_client" prefix_auto="1" extension_auto="1" />
 				<Option working_dir="../" />
 				<Option object_output="../obj/Debug/" />
 				<Option type="1" />
 				<Option compiler="gcc" />
 				<Compiler>
+					<Add option="-Og" />
 					<Add option="-g" />
+					<Add directory="$(#sdl2.include)" />
+				</Compiler>
+				<Linker>
+					<Add option="-lSDL2.dll" />
+					<Add option="-lSDL2_image.dll" />
+					<Add option="-lSDL2_mixer.dll" />
+					<Add option="-lSDL2_ttf.dll" />
+					<Add directory="$(#sdl2.lib)" />
+				</Linker>
+			</Target>
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../VCMI_client" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="../" />
+				<Option object_output="../obj/Release/" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O2" />
+					<Add directory="$(#sdl2.include)" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+					<Add option="-lSDL2.dll" />
+					<Add option="-lSDL2_image.dll" />
+					<Add option="-lSDL2_mixer.dll" />
+					<Add option="-lSDL2_ttf.dll" />
+					<Add directory="$(#sdl2.lib)" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="../VCMI_client" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="../" />
+				<Option object_output="../obj/Debug/" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Compiler>
 					<Add option="-Og" />
+					<Add option="-g" />
+					<Add directory="$(#sdl.include)" />
 				</Compiler>
+				<Linker>
+					<Add option="-lSDL" />
+					<Add option="-lSDL_image" />
+					<Add option="-lSDL_mixer" />
+					<Add option="-lSDL_ttf" />
+					<Add directory="$(#sdl.lib)" />
+				</Linker>
 			</Target>
-			<Target title="Release">
+			<Target title="Release-win32-SDL1">
+				<Option platforms="Windows;" />
 				<Option output="../VCMI_client" prefix_auto="1" extension_auto="1" />
 				<Option working_dir="../" />
 				<Option object_output="../obj/Release/" />
@@ -26,9 +77,15 @@
 				<Compiler>
 					<Add option="-fomit-frame-pointer" />
 					<Add option="-O2" />
+					<Add directory="$(#sdl.include)" />
 				</Compiler>
 				<Linker>
 					<Add option="-s" />
+					<Add option="-lSDL" />
+					<Add option="-lSDL_image" />
+					<Add option="-lSDL_mixer" />
+					<Add option="-lSDL_ttf" />
+					<Add directory="$(#sdl.lib)" />
 				</Linker>
 			</Target>
 		</Build>
@@ -45,7 +102,6 @@
 			<Add option="-DBOOST_THREAD_USE_LIB" />
 			<Add option="-D_WIN32_WINNT=0x0501" />
 			<Add directory="$(#boost.include)" />
-			<Add directory="$(#sdl.include)" />
 			<Add directory="../include" />
 			<Add directory="../client" />
 		</Compiler>
@@ -58,13 +114,8 @@
 			<Add option="-lboost_system$(#boost.libsuffix)" />
 			<Add option="-lboost_thread$(#boost.libsuffix)" />
 			<Add option="-lboost_chrono$(#boost.libsuffix)" />
-			<Add option="-lSDL" />
-			<Add option="-lSDL_image" />
-			<Add option="-lSDL_mixer" />
-			<Add option="-lSDL_ttf" />
 			<Add option="-lVCMI_lib" />
 			<Add directory="$(#boost.lib32)" />
-			<Add directory="$(#sdl.lib)" />
 			<Add directory="../" />
 		</Linker>
 		<Unit filename="../CCallback.cpp" />
@@ -139,6 +190,7 @@
 		<Unit filename="gui/Fonts.h" />
 		<Unit filename="gui/Geometries.cpp" />
 		<Unit filename="gui/Geometries.h" />
+		<Unit filename="gui/SDL_Compat.h" />
 		<Unit filename="gui/SDL_Extensions.cpp" />
 		<Unit filename="gui/SDL_Extensions.h" />
 		<Unit filename="gui/SDL_Pixels.h" />

+ 1 - 0
client/VCMI_client.vcxproj

@@ -234,6 +234,7 @@
     <ClInclude Include="FontBase.h" />
     <ClInclude Include="Graphics.h" />
     <ClInclude Include="GUIClasses.h" />
+    <ClInclude Include="gui\SDL_Compat.h" />
     <ClInclude Include="mapHandler.h" />
     <ClInclude Include="resource.h" />
     <ClInclude Include="StdInc.h" />

+ 1 - 0
client/VCMI_client.vcxproj.filters

@@ -126,6 +126,7 @@
     <ClInclude Include="gui\SDL_Pixels.h">
       <Filter>gui</Filter>
     </ClInclude>
+    <ClInclude Include="gui\SDL_Compat.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="VCMI_client.rc" />

+ 2 - 2
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)

+ 24 - 6
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<totalBlocks; i++)
@@ -267,7 +267,11 @@ static SDL_Color genShadow(ui8 alpha)
 
 static SDL_Color genBorderColor(ui8 alpha, const SDL_Color & base)
 {
+	#ifdef VCMI_SDL1
 	return CSDL_Ext::makeColor(base.r, base.g, base.b, ui8(base.unused * alpha / 256));
+	#else
+	return CSDL_Ext::makeColor(base.r, base.g, base.b, ui8(base.a * alpha / 256));
+	#endif
 }
 
 static ui8 mixChannels(ui8 c1, ui8 c2, ui8 a1, ui8 a2)
@@ -277,12 +281,22 @@ static ui8 mixChannels(ui8 c1, ui8 c2, ui8 a1, ui8 a2)
 
 static SDL_Color addColors(const SDL_Color & base, const SDL_Color & over)
 {
+	#ifdef VCMI_SDL1
 	return CSDL_Ext::makeColor(
-	            mixChannels(over.r, base.r, over.unused, base.unused),
-	            mixChannels(over.g, base.g, over.unused, base.unused),
-	            mixChannels(over.b, base.b, over.unused, base.unused),
-	            ui8(over.unused + base.unused * (255 - over.unused) / 256)
-	            );
+			mixChannels(over.r, base.r, over.unused, base.unused),
+			mixChannels(over.g, base.g, over.unused, base.unused),
+			mixChannels(over.b, base.b, over.unused, base.unused),
+			ui8(over.unused + base.unused * (255 - over.unused) / 256)
+			);
+	#else
+	return CSDL_Ext::makeColor(
+			mixChannels(over.r, base.r, over.a, base.a),
+			mixChannels(over.g, base.g, over.a, base.a),
+			mixChannels(over.b, base.b, over.a, base.a),
+			ui8(over.a + base.a * (255 - over.a) / 256)
+			);
+
+	#endif // VCMI_SDL1
 }
 
 std::array<SDL_Color, 8> 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<bpp, 0>::PutColor(dest, pal.r, pal.g, pal.b, pal.unused);
+		#else
+		ColorPutter<bpp, 0>::PutColor(dest, pal.r, pal.g, pal.b, pal.a);
+		#endif // 0		
 	}
 	else
 	{

+ 12 - 0
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)

+ 9 - 7
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; };

+ 116 - 44
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<SDL_Event> events;
 extern boost::mutex eventsM;
@@ -60,6 +61,10 @@ void CGuiHandler::processLists(const ui16 activityFlag, std::function<void (std:
 	processList(CIntObject::TIME,activityFlag,&timeinterested,cb);
 	processList(CIntObject::WHEEL,activityFlag,&wheelInterested,cb);
 	processList(CIntObject::DOUBLECLICK,activityFlag,&doubleClickInterested,cb);
+	
+	#ifndef VCMI_SDL1
+	processList(CIntObject::TEXTINPUT,activityFlag,&textInterested,cb);
+	#endif // VCMI_SDL1
 }
 
 void CGuiHandler::handleElementActivate(CIntObject * elem, ui16 activityFlag)
@@ -164,20 +169,16 @@ void CGuiHandler::updateTime()
 
 void CGuiHandler::handleEvents()
 {
-	while(true)
+	//player interface may want special event handling 	
+	if(nullptr != LOCPLINT && LOCPLINT->capturedAllEvents())
+		return;
+	
+	boost::unique_lock<boost::mutex> lock(eventsM);	
+	while(!events.empty())
 	{
-		SDL_Event ev;
-		boost::unique_lock<boost::mutex> 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<CIntObject*> 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<CIntObject*> 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<CIntObject*> 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();
-
-		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
-
-			mainFPSmng->framerateDelay(); // holds a constant FPS
-		}
-	}
-	catch(const std::exception & e)
-	{
-        logGlobal->errorStream() << "Error: " << e.what();
-		exit(EXIT_FAILURE);
-	}
+		if(nullptr != target)
+			target -> update();
+		// draw the mouse cursor and update the screen
+		CCS->curh->render();
+
+		#ifndef	VCMI_SDL1
+		if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr))
+			logGlobal->errorStream() << __FUNCTION__ << " SDL_RenderCopy " << SDL_GetError();
+
+		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()

+ 8 - 3
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<void (std::list<CIntObject*> *)> cb);               
 public:
@@ -68,15 +73,15 @@ public:
 	std::vector<IShowable*> 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

+ 6 - 0
client/gui/CIntObject.cpp

@@ -4,6 +4,12 @@
 #include "SDL_Extensions.h"
 #include "../CMessage.h"
 
+void ILockedUpdatable::runLocked(std::function<void(IUpdateable*)> cb)
+{
+	boost::unique_lock<boost::recursive_mutex> lock(updateGuard);	
+	cb(this);
+}
+
 CIntObject::CIntObject(int used_, Point pos_):
 	parent_m(nullptr),
 	active_m(0),

+ 24 - 11
client/gui/CIntObject.h

@@ -1,13 +1,3 @@
-#pragma once
-
-#include <SDL_events.h>
-#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 <SDL_events.h>
+#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<void(IUpdateable * )> 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);

+ 98 - 19
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<void()> &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 CFunctionList<void(co
 	pos.w = Pos.w;
 	captureAllKeys = true;
 	bg = nullptr;
-	addUsedEvents(LCLICK | KEYBOARD);
+	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
 	giveFocus();
 }
 
@@ -1548,7 +1558,7 @@ CTextInput::CTextInput( const Rect &Pos, const Point &bgOffset, const std::strin
 	captureAllKeys = true;
 	OBJ_CONSTRUCTION;
 	bg = new CPicture(bgName, bgOffset.x, bgOffset.y);
-	addUsedEvents(LCLICK | KEYBOARD);
+	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
 	giveFocus();
 }
 
@@ -1567,13 +1577,24 @@ CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf)
 	pos.w = bg->pos.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()

+ 14 - 1
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<void(int)> 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<void(const std::string &)> cb;
 	CFunctionList<void(std::string &, const std::string &)> 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);

+ 37 - 0
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 <SDL_version.h>
+
+#if (SDL_MAJOR_VERSION == 2)
+#define VCMI_SDL2
+
+#include <SDL_keycode.h>
+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
+ 
+

+ 101 - 2
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<bpp, +1>::PutColorAlphaSwitch(p, tbc.r, tbc.g, tbc.b, tbc.unused);
+					#else
+					ColorPutter<bpp, +1>::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);

+ 96 - 8
client/gui/SDL_Extensions.h

@@ -1,11 +1,3 @@
-#pragma once
-
-#include <SDL_video.h>
-#include <SDL_ttf.h>
-#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 <SDL_version.h>
+
+#ifndef VCMI_SDL1
+#include <SDL_render.h>
+#endif
+
+#include <SDL_video.h>
+#include <SDL_ttf.h>
+#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<int bpp>
 	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);
 }

+ 9 - 1
client/gui/SDL_Pixels.h

@@ -133,7 +133,11 @@ struct ColorPutter<2, incrementPtr>
 template<int bpp, int incrementPtr>
 STRONG_INLINE void ColorPutter<bpp, 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<int bpp, int incrementPtr>
@@ -262,7 +266,11 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uin
 template <int incrementPtr>
 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 <int incrementPtr>
@@ -285,4 +293,4 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorRow(Uint8 *&ptr, const
 		if(incrementPtr == 1)
 			ptr += 2;
 	}
-}
+}

+ 76 - 43
client/mapHandler.cpp

@@ -80,6 +80,69 @@ static bool objectBlitOrderSorter(const std::pair<const CGObjectInstance*,SDL_Re
 	return CMapHandler::compareObjectBlitOrder(a.first, b.first);
 }
 
+struct NeighborTilesInfo
+{
+	bool d7, //789
+		 d8, //456
+		 d9, //123
+		 d4,
+		 d5,
+		 d6,
+		 d1,
+		 d2,
+		 d3;
+	NeighborTilesInfo(const int3 & pos, const int3 & sizes, const std::vector< std::vector< std::vector<ui8> > > & 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<SDL_Surface *, bool> CMapHandler::getVisBitmap( const int3 & pos, const std::vector< std::vector< std::vector<ui8> > > & 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
-	};
-
-	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
+	const NeighborTilesInfo info(pos,sizes,visibilityMap);
+
+	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)
 	{

+ 0 - 27
cmake_modules/COPYING-CMAKE-SCRIPTS

@@ -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.

+ 216 - 0
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)

+ 100 - 0
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)

+ 101 - 0
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)

+ 100 - 0
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)

+ 57 - 0
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.

+ 7 - 2
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" : {

+ 1 - 1
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

+ 7 - 2
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()

+ 41 - 9
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.size(); i += getCharacterSize(text[i]))
 	{
-		if (!isValidCharacter(reinterpret_cast<const ui8*>(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<size; i += getCharacterSize(data[i]))
 	{
-		if (!isValidCharacter(reinterpret_cast<const ui8*>(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<char>(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<char>
 {

+ 5 - 2
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;

+ 8 - 3
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()

+ 3 - 2
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<int3, struct ShashInt3 > tiles;
 	PlayerColor player;
 	ui8 mode; //mode==0 - hide, mode==1 - reveal
+	bool waitForDialogs;
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & tiles & player & mode;
+		h & tiles & player & mode & waitForDialogs;
 	}
 };
 

+ 1 - 2
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"
 	}

+ 46 - 5
lib/VCMI_lib.cbp

@@ -7,7 +7,7 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
 				<Option platforms="Windows;" />
 				<Option output="../VCMI_lib" prefix_auto="0" extension_auto="1" />
 				<Option object_output="../obj/Debug/Lib" />
@@ -19,9 +19,48 @@
 				<Compiler>
 					<Add option="-Og" />
 					<Add option="-g" />
+					<Add directory="$(#sdl2.include)" />
 				</Compiler>
+				<Linker>
+					<Add directory="$(#sdl2.lib)" />
+				</Linker>
+			</Target>
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../VCMI_lib" prefix_auto="0" extension_auto="1" />
+				<Option object_output="../obj/Release/Lib" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O2" />
+					<Add directory="$(#sdl2.include)" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+					<Add directory="$(#sdl2.lib)" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="../VCMI_lib" prefix_auto="0" extension_auto="1" />
+				<Option object_output="../obj/Debug/Lib" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option host_application="D:/projects/vcmi/engine/VCMI_client.exe" />
+				<Option run_host_application_in_terminal="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-Og" />
+					<Add option="-g" />
+					<Add directory="$(#sdl.include)" />
+				</Compiler>
+				<Linker>
+					<Add directory="$(#sdl.lib)" />
+				</Linker>
 			</Target>
-			<Target title="Release">
+			<Target title="Release-win32-SDL1">
 				<Option platforms="Windows;" />
 				<Option output="../VCMI_lib" prefix_auto="0" extension_auto="1" />
 				<Option object_output="../obj/Release/Lib" />
@@ -31,9 +70,11 @@
 				<Compiler>
 					<Add option="-fomit-frame-pointer" />
 					<Add option="-O2" />
+					<Add directory="$(#sdl.include)" />
 				</Compiler>
 				<Linker>
 					<Add option="-s" />
+					<Add directory="$(#sdl.lib)" />
 				</Linker>
 			</Target>
 		</Build>
@@ -50,14 +91,14 @@
 			<Add option="-DVCMI_DLL" />
 			<Add option="-DBOOST_THREAD_USE_LIB" />
 			<Add option="-D_WIN32_WINNT=0x0501" />
+			<Add directory="$(#zlib.include)" />
 			<Add directory="$(#boost.include)" />
-			<Add directory="$(#sdl.include)" />
 			<Add directory="../include" />
 			<Add directory="../lib" />
 		</Compiler>
 		<Linker>
 			<Add option="-lws2_32" />
-			<Add option="-lzlib" />
+			<Add option="-lz" />
 			<Add option="-lminizip" />
 			<Add option="-lboost_filesystem$(#boost.libsuffix)" />
 			<Add option="-lboost_system$(#boost.libsuffix)" />
@@ -65,7 +106,7 @@
 			<Add option="-lboost_chrono$(#boost.libsuffix)" />
 			<Add option="-lboost_locale$(#boost.libsuffix)" />
 			<Add directory="$(#boost.lib32)" />
-			<Add directory="$(#sdl.lib)" />
+			<Add directory="$(#zlib.lib)" />
 			<Add directory="../" />
 		</Linker>
 		<Unit filename="AI_Base.h" />

+ 1 - 0
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])
 			{

+ 1 - 1
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()

+ 35 - 5
lib/minizip/minizip.cbp

@@ -6,7 +6,7 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
 				<Option platforms="Windows;" />
 				<Option output="../../minizip" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Debug/" />
@@ -19,7 +19,37 @@
 					<Add option="-DBUILD_DLL" />
 				</Compiler>
 			</Target>
-			<Target title="Release">
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../../minizip" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-O2" />
+					<Add option="-Wall" />
+					<Add option="-DBUILD_DLL" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="../../minizip" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-Wall" />
+					<Add option="-g" />
+					<Add option="-DBUILD_DLL" />
+				</Compiler>
+			</Target>
+			<Target title="Release-win32-SDL1">
+				<Option platforms="Windows;" />
 				<Option output="../../minizip" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Release/" />
 				<Option type="3" />
@@ -36,11 +66,11 @@
 			</Target>
 		</Build>
 		<Compiler>
-			<Add directory="$(#sdl.include)" />
+			<Add directory="$(#zlib.include)" />
 		</Compiler>
 		<Linker>
-			<Add option="-lzlib" />
-			<Add directory="$(#sdl.lib)" />
+			<Add option="-lz" />
+			<Add directory="$(#zlib.lib)" />
 		</Linker>
 		<Unit filename="ioapi.c">
 			<Option compilerVar="CC" />

+ 10 - 10
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
 )
 
+add_executable(vcmiserver ${server_SRCS})
+
+target_link_libraries(vcmiserver vcmi ${Boost_LIBRARIES} ${SYSTEM_LIBS})
+
 if(WIN32)
-    add_executable(vcmiserver WIN32 ${server_SRCS})
-else()
-    add_executable(vcmiserver ${server_SRCS})
+	set_target_properties(vcmiserver PROPERTIES OUTPUT_NAME VCMI_server)
 endif()
 
-target_link_libraries(vcmiserver vcmi ${Boost_LIBRARIES} ${RT_LIB} ${DL_LIB})
-
 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()
 

+ 37 - 3
server/VCMI_server.cbp

@@ -6,25 +6,59 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
+				<Option platforms="Windows;" />
 				<Option output="../VCMI_server" prefix_auto="1" extension_auto="1" />
 				<Option object_output="../obj/Debug/Server" />
 				<Option type="1" />
 				<Option compiler="gcc" />
 				<Option use_console_runner="0" />
 				<Compiler>
+					<Add option="-Og" />
 					<Add option="-ggdb" />
+					<Add directory="$(#sdl2.include)" />
+				</Compiler>
+			</Target>
+			<Target title="Release-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../VCMI_server" prefix_auto="1" extension_auto="1" />
+				<Option object_output="../obj/Release/Server" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Option use_console_runner="0" />
+				<Compiler>
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O2" />
+					<Add directory="$(#sdl2.include)" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
+				<Option output="../VCMI_server" prefix_auto="1" extension_auto="1" />
+				<Option object_output="../obj/Debug/Server" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Option use_console_runner="0" />
+				<Compiler>
 					<Add option="-Og" />
+					<Add option="-ggdb" />
+					<Add directory="$(#sdl.include)" />
 				</Compiler>
 			</Target>
-			<Target title="Release">
+			<Target title="Release-win32-SDL1">
+				<Option platforms="Windows;" />
 				<Option output="../VCMI_server" prefix_auto="1" extension_auto="1" />
 				<Option object_output="../obj/Release/Server" />
 				<Option type="1" />
 				<Option compiler="gcc" />
+				<Option use_console_runner="0" />
 				<Compiler>
 					<Add option="-fomit-frame-pointer" />
 					<Add option="-O2" />
+					<Add directory="$(#sdl.include)" />
 				</Compiler>
 				<Linker>
 					<Add option="-s" />
@@ -42,8 +76,8 @@
 			<Add option="-Wno-overloaded-virtual" />
 			<Add option="-D_WIN32_WINNT=0x0501" />
 			<Add option="-DBOOST_THREAD_USE_LIB" />
+			<Add directory="$(#zlib.include)" />
 			<Add directory="$(#boost.include)" />
-			<Add directory="$(#sdl.include)" />
 			<Add directory="../include" />
 		</Compiler>
 		<Linker>

+ 14 - 1
test/Test.cbp

@@ -6,7 +6,20 @@
 		<Option pch_mode="2" />
 		<Option compiler="gcc" />
 		<Build>
-			<Target title="Debug">
+			<Target title="Debug-win32-SDL2">
+				<Option platforms="Windows;" />
+				<Option output="../Test" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Debug/" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-march=athlon-xp" />
+					<Add option="-Wextra" />
+					<Add option="-g" />
+				</Compiler>
+			</Target>
+			<Target title="Debug-win32-SDL1">
+				<Option platforms="Windows;" />
 				<Option output="../Test" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Debug/" />
 				<Option type="1" />