Browse Source

Merge pull request #1 from urho3d/master

Update fork
bengtsts 9 years ago
parent
commit
02abed0da5
100 changed files with 15910 additions and 7483 deletions
  1. 0 1
      .appveyor.yml
  2. 36 91
      .travis.yml
  3. 114 0
      Docs/AngelScriptAPI.h
  4. 1 0
      Docs/GettingStarted.dox
  5. 172 6
      Docs/LuaScriptAPI.dox
  6. 16 6
      Docs/Reference.dox
  7. 121 0
      Docs/ScriptAPI.dox
  8. 21 19
      Docs/Urho3D.dox
  9. 27 33
      License.txt
  10. 23 21
      README.md
  11. 37 0
      Source/Samples/43_HttpRequestDemo/CMakeLists.txt
  12. 123 0
      Source/Samples/43_HttpRequestDemo/HttpRequestDemo.cpp
  13. 68 0
      Source/Samples/43_HttpRequestDemo/HttpRequestDemo.h
  14. 2 2
      Source/Samples/Sample.inl
  15. 108 33
      Source/ThirdParty/Civetweb/LICENSE.md
  16. 62 40
      Source/ThirdParty/Civetweb/README.md
  17. 114 10
      Source/ThirdParty/Civetweb/RELEASE_NOTES.md
  18. 686 431
      Source/ThirdParty/Civetweb/include/civetweb.h
  19. 8828 4648
      Source/ThirdParty/Civetweb/src/civetweb.c
  20. 260 258
      Source/ThirdParty/Civetweb/src/md5.inl
  21. 471 35
      Source/ThirdParty/GLEW/glew.c
  22. 515 150
      Source/ThirdParty/GLEW/glew.h
  23. 156 21
      Source/ThirdParty/GLEW/glxew.h
  24. 58 2
      Source/ThirdParty/GLEW/wglew.h
  25. 16 0
      Source/ThirdParty/JO/jo_jpeg.cpp
  26. 0 10
      Source/ThirdParty/LZ4/NEWS
  27. 720 385
      Source/ThirdParty/LZ4/lz4.c
  28. 267 112
      Source/ThirdParty/LZ4/lz4.h
  29. 0 120
      Source/ThirdParty/LZ4/lz4_format_description.txt
  30. 445 531
      Source/ThirdParty/LZ4/lz4hc.c
  31. 129 51
      Source/ThirdParty/LZ4/lz4hc.h
  32. 12 11
      Source/ThirdParty/STB/README.md
  33. 26 0
      Source/ThirdParty/STB/release_notes.md
  34. 197 56
      Source/ThirdParty/STB/stb_image.h
  35. 14 2
      Source/ThirdParty/STB/stb_image_write.h
  36. 28 93
      Source/ThirdParty/STB/stb_vorbis.h
  37. 32 1
      Source/Tools/AssetImporter/AssetImporter.cpp
  38. 1 0
      Source/Tools/PackageTool/CMakeLists.txt
  39. 1 1
      Source/Urho3D/.soversion
  40. 6 0
      Source/Urho3D/AngelScript/CoreAPI.cpp
  41. 1 0
      Source/Urho3D/AngelScript/EngineAPI.cpp
  42. 6 0
      Source/Urho3D/AngelScript/GraphicsAPI.cpp
  43. 21 0
      Source/Urho3D/AngelScript/IOAPI.cpp
  44. 1 0
      Source/Urho3D/AngelScript/ResourceAPI.cpp
  45. 6 4
      Source/Urho3D/AngelScript/UIAPI.cpp
  46. 1 1
      Source/Urho3D/Audio/SoundSource.h
  47. 177 0
      Source/Urho3D/Core/EventProfiler.cpp
  48. 235 0
      Source/Urho3D/Core/EventProfiler.h
  49. 50 1
      Source/Urho3D/Core/Object.cpp
  50. 11 1
      Source/Urho3D/Core/Object.h
  51. 30 1
      Source/Urho3D/Engine/DebugHud.cpp
  52. 3 0
      Source/Urho3D/Engine/DebugHud.h
  53. 18 1
      Source/Urho3D/Engine/Engine.cpp
  54. 1 1
      Source/Urho3D/Graphics/Batch.cpp
  55. 48 2
      Source/Urho3D/Graphics/BillboardSet.cpp
  56. 13 2
      Source/Urho3D/Graphics/BillboardSet.h
  57. 12 9
      Source/Urho3D/Graphics/Light.cpp
  58. 3 0
      Source/Urho3D/Graphics/Light.h
  59. 1 3
      Source/Urho3D/Graphics/Material.cpp
  60. 7 2
      Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp
  61. 13 0
      Source/Urho3D/Graphics/ParticleEffect.cpp
  62. 10 3
      Source/Urho3D/Graphics/ParticleEffect.h
  63. 1 0
      Source/Urho3D/Graphics/ParticleEmitter.cpp
  64. 8 9
      Source/Urho3D/Graphics/Renderer.cpp
  65. 3 3
      Source/Urho3D/Graphics/Renderer.h
  66. 39 31
      Source/Urho3D/Graphics/View.cpp
  67. 3 3
      Source/Urho3D/Graphics/View.h
  68. 2 3
      Source/Urho3D/IO/Deserializer.h
  69. 381 0
      Source/Urho3D/IO/NamedPipe.cpp
  70. 85 0
      Source/Urho3D/IO/NamedPipe.h
  71. 2 0
      Source/Urho3D/LuaScript/pkgs/Engine/DebugHud.pkg
  72. 3 1
      Source/Urho3D/LuaScript/pkgs/Graphics/BillboardSet.pkg
  73. 3 0
      Source/Urho3D/LuaScript/pkgs/Graphics/ParticleEffect.pkg
  74. 174 0
      Source/Urho3D/LuaScript/pkgs/IO/NamedPipe.pkg
  75. 1 0
      Source/Urho3D/LuaScript/pkgs/IOLuaAPI.pkg
  76. 8 0
      Source/Urho3D/LuaScript/pkgs/LuaScript/LuaScript.pkg
  77. 58 1
      Source/Urho3D/LuaScript/pkgs/Network/HttpRequest.pkg
  78. 1 0
      Source/Urho3D/LuaScript/pkgs/Resource/JSONFile.pkg
  79. 1 1
      Source/Urho3D/LuaScript/pkgs/UI/ScrollBar.pkg
  80. 3 3
      Source/Urho3D/LuaScript/pkgs/UI/Text.pkg
  81. 6 3
      Source/Urho3D/LuaScript/pkgs/UI/Text3D.pkg
  82. 18 14
      Source/Urho3D/Network/HttpRequest.cpp
  83. 4 2
      Source/Urho3D/Network/HttpRequest.h
  84. 3 15
      Source/Urho3D/Resource/Image.cpp
  85. 10 0
      Source/Urho3D/Resource/JSONFile.cpp
  86. 3 0
      Source/Urho3D/Resource/JSONFile.h
  87. 7 4
      Source/Urho3D/UI/ScrollBar.cpp
  88. 2 2
      Source/Urho3D/UI/ScrollBar.h
  89. 2 2
      Source/Urho3D/UI/Sprite.cpp
  90. 12 11
      Source/Urho3D/UI/Text.cpp
  91. 2 2
      Source/Urho3D/UI/Text.h
  92. 43 6
      Source/Urho3D/UI/Text3D.cpp
  93. 11 8
      Source/Urho3D/UI/Text3D.h
  94. 93 0
      bin/Data/LuaScripts/43_HttpRequestDemo.lua
  95. 97 0
      bin/Data/Scripts/43_HttpRequestDemo.as
  96. 28 0
      bin/Data/Scripts/Editor/EditorImport.as
  97. 24 1
      bin/Data/Scripts/Editor/EditorParticleEffect.as
  98. 155 144
      bin/Data/Scripts/Editor/EditorUI.as
  99. 11 0
      bin/Data/Scripts/NinjaSnowWar.as
  100. 22 3
      bin/Data/UI/EditorParticleEffectWindow.xml

+ 0 - 1
.appveyor.yml

@@ -39,7 +39,6 @@ environment:
 # Using neither-in-nor-out-of-source (Urho3D-legacy) build tree when on AppVeyor; using out-of-source (and in-the-source) build tree when on Travis-CI for test coverage
 # Using neither-in-nor-out-of-source (Urho3D-legacy) build tree when on AppVeyor; using out-of-source (and in-the-source) build tree when on Travis-CI for test coverage
   build_tree: Build
   build_tree: Build
   config: Release
   config: Release
-  excluded_sample: PLATFORM=x64 39_CrowdNavigation
 # We cannot afford to have a large matrix on AppVeyor at the moment
 # We cannot afford to have a large matrix on AppVeyor at the moment
   URHO3D_D3D11: 1
   URHO3D_D3D11: 1
   matrix:
   matrix:

+ 36 - 91
.travis.yml

@@ -23,6 +23,7 @@
 ---
 ---
 
 
 language: cpp
 language: cpp
+compiler: gcc
 cache: ccache
 cache: ccache
 sudo: false
 sudo: false
 addons: {apt: {sources: &default_sources [george-edison55-precise-backports, kubuntu-backports], packages: &default_packages [doxygen, graphviz, cmake]}}
 addons: {apt: {sources: &default_sources [george-edison55-precise-backports, kubuntu-backports], packages: &default_packages [doxygen, graphviz, cmake]}}
@@ -38,70 +39,68 @@ env:
     - URHO3D_DEPLOYMENT_TARGET=generic
     - URHO3D_DEPLOYMENT_TARGET=generic
 matrix:
 matrix:
   fast_finish: true
   fast_finish: true
+  exclude:
+    - compiler: gcc
   include:
   include:
     - &Linux-64bit
     - &Linux-64bit
       addons: {apt: {sources: [*default_sources, ubuntu-toolchain-r-test], packages: [g++-4.9, &linux_packages [*default_packages, libasound2-dev, libpulse-dev, rpm]]}}
       addons: {apt: {sources: [*default_sources, ubuntu-toolchain-r-test], packages: [g++-4.9, &linux_packages [*default_packages, libasound2-dev, libpulse-dev, rpm]]}}
-      compiler: gcc-64bit-static
       env: LINUX=1 URHO3D_LIB_TYPE=STATIC URHO3D_UPDATE_SOURCE_TREE=1 COVERITY_SCAN_THRESHOLD=100 SF_DEFAULT=linux:Linux-64bit-STATIC.tar.gz
       env: LINUX=1 URHO3D_LIB_TYPE=STATIC URHO3D_UPDATE_SOURCE_TREE=1 COVERITY_SCAN_THRESHOLD=100 SF_DEFAULT=linux:Linux-64bit-STATIC.tar.gz
     - &Linux-64bit-shared
     - &Linux-64bit-shared
       addons: {apt: {sources: *default_sources, packages: *linux_packages}}
       addons: {apt: {sources: *default_sources, packages: *linux_packages}}
-      compiler: gcc-64bit-shared
       env: LINUX=1 URHO3D_LIB_TYPE=SHARED
       env: LINUX=1 URHO3D_LIB_TYPE=SHARED
     - <<: *Linux-64bit-shared
     - <<: *Linux-64bit-shared
-      compiler: clang-64bit-static
+      compiler: clang
       env: LINUX=1 URHO3D_LIB_TYPE=STATIC
       env: LINUX=1 URHO3D_LIB_TYPE=STATIC
     - <<: *Linux-64bit-shared
     - <<: *Linux-64bit-shared
-      compiler: clang-64bit-shared
+      compiler: clang
     - &Linux-32bit
     - &Linux-32bit
-      compiler: gcc-32bit-static
       addons: {apt: {sources: *default_sources, packages: [*linux_packages, g++-multilib, "libxrandr-dev:i386", "libglapi-mesa:i386", "libgl1-mesa-glx:i386", "libgl1-mesa-dev:i386", "libxext-dev:i386", "libxrender-dev:i386", lib32readline6-dev]}}
       addons: {apt: {sources: *default_sources, packages: [*linux_packages, g++-multilib, "libxrandr-dev:i386", "libglapi-mesa:i386", "libgl1-mesa-glx:i386", "libgl1-mesa-dev:i386", "libxext-dev:i386", "libxrender-dev:i386", lib32readline6-dev]}}
       env: LINUX=1 URHO3D_LIB_TYPE=STATIC URHO3D_64BIT=0
       env: LINUX=1 URHO3D_LIB_TYPE=STATIC URHO3D_64BIT=0
     - &Linux-32bit-shared
     - &Linux-32bit-shared
       <<: *Linux-32bit
       <<: *Linux-32bit
-      compiler: gcc-32bit-shared
       env: LINUX=1 URHO3D_LIB_TYPE=SHARED URHO3D_64BIT=0
       env: LINUX=1 URHO3D_LIB_TYPE=SHARED URHO3D_64BIT=0
     - <<: *Linux-32bit
     - <<: *Linux-32bit
-      compiler: clang-32bit-static
+      compiler: clang
     - <<: *Linux-32bit-shared
     - <<: *Linux-32bit-shared
-      compiler: clang-32bit-shared
+      compiler: clang
     - &MinGW-64bit
     - &MinGW-64bit
-      compiler: x86_64-w64-mingw32-gcc-static
+      compiler: x86_64-w64-mingw32-gcc
       addons: {apt: {sources: *default_sources, packages: [*default_packages, gcc-mingw-w64-x86-64, g++-mingw-w64-x86-64, binutils-mingw-w64-x86-64]}}
       addons: {apt: {sources: *default_sources, packages: [*default_packages, gcc-mingw-w64-x86-64, g++-mingw-w64-x86-64, binutils-mingw-w64-x86-64]}}
       env: WIN32=1 URHO3D_LIB_TYPE=STATIC
       env: WIN32=1 URHO3D_LIB_TYPE=STATIC
     - <<: *MinGW-64bit
     - <<: *MinGW-64bit
-      compiler: x86_64-w64-mingw32-gcc-shared
+      compiler: x86_64-w64-mingw32-gcc
       env: WIN32=1 URHO3D_LIB_TYPE=SHARED
       env: WIN32=1 URHO3D_LIB_TYPE=SHARED
     - <<: *MinGW-64bit
     - <<: *MinGW-64bit
-      compiler: x86_64-w64-mingw32-gcc-d3d9-static
+      compiler: x86_64-w64-mingw32-gcc
       env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_OPENGL=0
       env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_OPENGL=0
     - <<: *MinGW-64bit
     - <<: *MinGW-64bit
-      compiler: x86_64-w64-mingw32-gcc-d3d9-shared
+      compiler: x86_64-w64-mingw32-gcc
       env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_OPENGL=0
       env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_OPENGL=0
     # Ubuntu 12.04 LTS does not have up-to-date D3D11 headers, disable the CI build jobs for D3D11 for now until Travis-CI upgrades their OS to 14.04 LTS or better (We may not need these anymore because now we already have CI jobs on AppVeyor to cover the D3D11 build)
     # Ubuntu 12.04 LTS does not have up-to-date D3D11 headers, disable the CI build jobs for D3D11 for now until Travis-CI upgrades their OS to 14.04 LTS or better (We may not need these anymore because now we already have CI jobs on AppVeyor to cover the D3D11 build)
     # <<: *MinGW-64bit
     # <<: *MinGW-64bit
-    # compiler: x86_64-w64-mingw32-gcc-d3d11-static
+    # compiler: x86_64-w64-mingw32-gcc
     # env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_D3D11=1
     # env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_D3D11=1
     # <<: *MinGW-64bit
     # <<: *MinGW-64bit
-    # compiler: x86_64-w64-mingw32-gcc-d3d11-shared
+    # compiler: x86_64-w64-mingw32-gcc
     # env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_D3D11=1
     # env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_D3D11=1
     - &MinGW-32bit
     - &MinGW-32bit
-      compiler: i686-w64-mingw32-gcc-static
+      compiler: i686-w64-mingw32-gcc
       addons: {apt: {sources: *default_sources, packages: [*default_packages, gcc-mingw-w64-i686, g++-mingw-w64-i686, binutils-mingw-w64-i686]}}
       addons: {apt: {sources: *default_sources, packages: [*default_packages, gcc-mingw-w64-i686, g++-mingw-w64-i686, binutils-mingw-w64-i686]}}
       env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_64BIT=0
       env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_64BIT=0
     - <<: *MinGW-32bit
     - <<: *MinGW-32bit
-      compiler: i686-w64-mingw32-gcc-shared
+      compiler: i686-w64-mingw32-gcc
       env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_64BIT=0
       env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_64BIT=0
     - <<: *MinGW-32bit
     - <<: *MinGW-32bit
-      compiler: i686-w64-mingw32-gcc-d3d9-static
+      compiler: i686-w64-mingw32-gcc
       env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_64BIT=0 URHO3D_OPENGL=0
       env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_64BIT=0 URHO3D_OPENGL=0
     - <<: *MinGW-32bit
     - <<: *MinGW-32bit
-      compiler: i686-w64-mingw32-gcc-d3d9-shared
+      compiler: i686-w64-mingw32-gcc
       env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_64BIT=0 URHO3D_OPENGL=0
       env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_64BIT=0 URHO3D_OPENGL=0
     # <<: *MinGW-32bit
     # <<: *MinGW-32bit
-    # compiler: i686-w64-mingw32-gcc-d3d11-static
+    # compiler: i686-w64-mingw32-gcc
     # env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_64BIT=0 URHO3D_D3D11=1
     # env: WIN32=1 URHO3D_LIB_TYPE=STATIC URHO3D_64BIT=0 URHO3D_D3D11=1
     # <<: *MinGW-32bit
     # <<: *MinGW-32bit
-    # compiler: i686-w64-mingw32-gcc-d3d11-shared
+    # compiler: i686-w64-mingw32-gcc
     # env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_64BIT=0 URHO3D_D3D11=1
     # env: WIN32=1 URHO3D_LIB_TYPE=SHARED URHO3D_64BIT=0 URHO3D_D3D11=1
 before_script:
 before_script:
   - rake ci_timer
   - rake ci_timer
@@ -126,56 +125,6 @@ notifications: {email: {on_success: never, on_failure: change}}
 
 
 ---
 ---
 
 
-branch: {name: VS-CI, active: yes, appveyor: yes, last_job: 'x64:SHARED'}
-version: '{build}'
-platform: x64
-clone_depth: 50
-environment:
-  GIT_NAME:
-    secure: onlJNy/nGFT1GXNdusL4jokojSPZ732EFaXwdhPnpM0=
-  GIT_EMAIL:
-    secure: RdTdiZIl3fnggJFH8JhmqT2TAg/23ENX/4sFCrJfQ3s=
-  GH_TOKEN:
-    secure: VP9a1Mu28nO7cN+RVyccA9bNvIG92pGQ0zgFjTIds62In6BdiIxj3FgIb8G3XR0K
-  SF_KEY:
-    secure: JgsjFoVAP5yjNxyS/+S+4byhtnTKCWfI3bkCmHws3P1MwSaUS5+0C6WV1pHIJTVW00Qvo3+JsgVqMYUJ7fo2m/bXvUPNCoSa4BifXZlS6bE=
-  SF_API:
-    secure: cc1q9CXo5BwIYqtgigHpkCGG90zEVM45xx/YzXTOjVp512oQNUzTJq0AmxEYXP78
-# Using neither-in-nor-out-of-source (Urho3D-legacy) build tree when on AppVeyor; using out-of-source (and in-the-source) build tree when on Travis-CI for test coverage
-  build_tree: Build
-  config: Release
-  included_sample: PLATFORM=x64 39_CrowdNavigation
-# We cannot afford to have a large matrix on AppVeyor at the moment
-  URHO3D_D3D11: 1
-  matrix:
-    - URHO3D_LIB_TYPE: STATIC
-    - URHO3D_LIB_TYPE: SHARED
-install:
-  - ps: if ($env:APPVEYOR_REPO_TAG -eq "true") { $env:RELEASE_TAG = $env:APPVEYOR_REPO_TAG_NAME };
-        if ($env:RELEASE_TAG -or ($env:APPVEYOR_REPO_BRANCH -eq "master" -and (!$env:APPVEYOR_PULL_REQUEST_NUMBER -and (select-string '\[ci package\]' -inputobject $env:APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED))))
-        {
-          $env:PACKAGE_UPLOAD = "1";
-          if ($env:URHO3D_LIB_TYPE -eq "STATIC" -and ($env:Platform -eq "x64")) { $env:SF_DEFAULT = "windows:Windows-64bit-STATIC-3D11.zip" };
-          do { "Installing doxygen and graphviz..."; choco install doxygen.portable graphviz.portable >$null } until ($?);
-        }
-        else
-        {
-          iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-desktop.ps1'))
-        }
-build_script:
-  - set "APPVEYOR_REPO_COMMIT=%APPVEYOR_REPO_COMMIT%~"
-  - ps: $env:COMMIT_MESSAGE = $(git log --format=%B -n 1 $env:APPVEYOR_REPO_COMMIT)
-  - if "%PLATFORM%" == "x64" set "URHO3D_64BIT=1"
-# Our free AppVeyor account is slow for normal daily CI, speed up the build a little bit by excluding Assimp and other tools in the normal build and use the Debug build configuration instead
-  - if "%PACKAGE_UPLOAD%" == "" set "URHO3D_TOOLS=0" && set "config=Debug"
-  - rake ci && if "%PACKAGE_UPLOAD%" == "1" rake ci_package_upload
-test: off
-artifacts:
-  - path: Build\*.zip
-deploy: off
-
----
-
 branch: {name: Coverity-Scan, active: no, mandatory: yes}
 branch: {name: Coverity-Scan, active: no, mandatory: yes}
 language: cpp
 language: cpp
 compiler: gcc
 compiler: gcc
@@ -240,6 +189,7 @@ after_script: rake ci_teardown_cache
 
 
 branch: {name: Android-CI, active: yes}
 branch: {name: Android-CI, active: yes}
 language: android
 language: android
+cache: {directories: $HOME/.ccache}
 android: {components: [build-tools-22.0.1]}
 android: {components: [build-tools-22.0.1]}
 jdk: oraclejdk8
 jdk: oraclejdk8
 sudo: false
 sudo: false
@@ -251,7 +201,7 @@ env:
     - numjobs=4
     - numjobs=4
     - ANDROID=1
     - ANDROID=1
     - ANDROID_TMP=~/tmp
     - ANDROID_TMP=~/tmp
-    - USE_CCACHE=2
+    - USE_CCACHE=1
     - CCACHE_SLOPPINESS=pch_defines,time_macros
     - CCACHE_SLOPPINESS=pch_defines,time_macros
     - CCACHE_COMPRESS=1
     - CCACHE_COMPRESS=1
     - CCACHE_MAXSIZE=100M
     - CCACHE_MAXSIZE=100M
@@ -291,6 +241,7 @@ after_script: rake ci_teardown_cache
 
 
 branch: {name: RPI-CI, active: yes}
 branch: {name: RPI-CI, active: yes}
 language: cpp
 language: cpp
+compiler: gcc
 cache: ccache
 cache: ccache
 sudo: false
 sudo: false
 addons: {apt: {sources: &default_sources george-edison55-precise-backports, packages: &default_packages [doxygen, graphviz, g++-multilib, rpm]}}
 addons: {apt: {sources: &default_sources george-edison55-precise-backports, packages: &default_packages [doxygen, graphviz, g++-multilib, rpm]}}
@@ -305,21 +256,15 @@ env:
     - CCACHE_SLOPPINESS=pch_defines,time_macros
     - CCACHE_SLOPPINESS=pch_defines,time_macros
     - CCACHE_COMPRESS=1
     - CCACHE_COMPRESS=1
     - CCACHE_MAXSIZE=100M
     - CCACHE_MAXSIZE=100M
+  matrix:
+    - URHO3D_LIB_TYPE=STATIC
+    - URHO3D_LIB_TYPE=SHARED
+    - URHO3D_LIB_TYPE=STATIC RPI_ABI=armeabi-v7a
+    - URHO3D_LIB_TYPE=SHARED RPI_ABI=armeabi-v7a
+    - URHO3D_LIB_TYPE=STATIC RPI_ABI='armeabi-v7a with NEON'
+    - URHO3D_LIB_TYPE=SHARED RPI_ABI='armeabi-v7a with NEON'
 matrix:
 matrix:
   fast_finish: true
   fast_finish: true
-  include:
-    - compiler: gcc-armeabi-v6-static
-      env: URHO3D_LIB_TYPE=STATIC
-    - compiler: gcc-armeabi-v6-shared
-      env: URHO3D_LIB_TYPE=SHARED
-    - compiler: gcc-armeabi-v7a-static
-      env: URHO3D_LIB_TYPE=STATIC RPI_ABI=armeabi-v7a
-    - compiler: gcc-armeabi-v7a-shared
-      env: URHO3D_LIB_TYPE=SHARED RPI_ABI=armeabi-v7a
-    - compiler: gcc-armeabi-v7a-with-NEON-static
-      env: URHO3D_LIB_TYPE=STATIC RPI_ABI='armeabi-v7a with NEON'
-    - compiler: gcc-armeabi-v7a-with-NEON-shared
-      env: URHO3D_LIB_TYPE=SHARED RPI_ABI='armeabi-v7a with NEON'
 before_script:
 before_script:
   - rake ci_timer
   - rake ci_timer
   - git clone --depth 1 https://github.com/raspberrypi/tools.git rpi-tools && export RPI_PREFIX=$(pwd)/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf && git clone --depth 1 https://github.com/urho3d/rpi-sysroot.git && export RPI_SYSROOT=$(pwd)/rpi-sysroot && for f in $RPI_PREFIX-{gcc,g++}; do touch -d "2015-01-01 00:00:00 +0800" $f; done
   - git clone --depth 1 https://github.com/raspberrypi/tools.git rpi-tools && export RPI_PREFIX=$(pwd)/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf && git clone --depth 1 https://github.com/urho3d/rpi-sysroot.git && export RPI_SYSROOT=$(pwd)/rpi-sysroot && for f in $RPI_PREFIX-{gcc,g++}; do touch -d "2015-01-01 00:00:00 +0800" $f; done
@@ -336,6 +281,7 @@ after_script: rake ci_teardown_cache
 
 
 branch: {name: OSX-CI, active: yes, mandatory: yes}
 branch: {name: OSX-CI, active: yes, mandatory: yes}
 language: objective-c
 language: objective-c
+cache: {directories: $HOME/.ccache}
 osx_image: xcode7.1
 osx_image: xcode7.1
 env:
 env:
   global:
   global:
@@ -343,7 +289,7 @@ env:
     - secure: ecj/PwpbHkH9AYFsc2TMeRuNm5E3xMM8A0x4AcGhzpwDuZWdFx3R1T4G9u45Z5aUyTJWGqOeX1JPaEVVFZuYnNBKRy0kmiUrM9EE0j7WsT57K48tP1ysn2ynyvHgbYkKOfYR0t8XAMWTBbulT9DVVk3DS69//2WgiXGDVUEJTyI=
     - secure: ecj/PwpbHkH9AYFsc2TMeRuNm5E3xMM8A0x4AcGhzpwDuZWdFx3R1T4G9u45Z5aUyTJWGqOeX1JPaEVVFZuYnNBKRy0kmiUrM9EE0j7WsT57K48tP1ysn2ynyvHgbYkKOfYR0t8XAMWTBbulT9DVVk3DS69//2WgiXGDVUEJTyI=
     - numjobs=3
     - numjobs=3
     - OSX=1
     - OSX=1
-    - USE_CCACHE=2
+    - USE_CCACHE=1
     - CCACHE_SLOPPINESS=pch_defines,time_macros
     - CCACHE_SLOPPINESS=pch_defines,time_macros
     - CCACHE_COMPRESS=1
     - CCACHE_COMPRESS=1
     - CCACHE_MAXSIZE=300M
     - CCACHE_MAXSIZE=300M
@@ -365,7 +311,7 @@ before_script:
   - which cmake >/dev/null 2>&1 || cmake=cmake
   - which cmake >/dev/null 2>&1 || cmake=cmake
   - if [ $PACKAGE_UPLOAD ]; then doxygen='doxygen graphviz'; fi
   - if [ $PACKAGE_UPLOAD ]; then doxygen='doxygen graphviz'; fi
   - travis_retry brew install ccache $cmake $doxygen
   - travis_retry brew install ccache $cmake $doxygen
-  - whitelist='brew-cask ccache cmake doxygen graphviz libpng libyaml openssl pkg-config readline'
+  - whitelist='brew-cask ccache cmake doxygen graphviz libpng libyaml md5deep openssl pkg-config readline'
   - for f in $(brew list); do [[ $whitelist =~ $f ]] || brew uninstall --force $f; done
   - for f in $(brew list); do [[ $whitelist =~ $f ]] || brew uninstall --force $f; done
   - for f in $(brew cask list |grep -v Uninstalling); do [[ $whitelist =~ $f ]] || brew cask uninstall --force $f; done
   - for f in $(brew cask list |grep -v Uninstalling); do [[ $whitelist =~ $f ]] || brew cask uninstall --force $f; done
   - brew cleanup
   - brew cleanup
@@ -385,6 +331,7 @@ data:
 
 
 branch: {name: Web-CI, active: yes}
 branch: {name: Web-CI, active: yes}
 language: cpp
 language: cpp
+compiler: gcc
 cache: ccache
 cache: ccache
 sudo: false
 sudo: false
 addons: {apt: {sources: [george-edison55-precise-backports, kubuntu-backports, ubuntu-toolchain-r-test], packages: [cmake, doxygen, graphviz, g++-4.9]}}
 addons: {apt: {sources: [george-edison55-precise-backports, kubuntu-backports, ubuntu-toolchain-r-test], packages: [cmake, doxygen, graphviz, g++-4.9]}}
@@ -399,13 +346,11 @@ env:
     - CCACHE_SLOPPINESS=pch_defines,time_macros
     - CCACHE_SLOPPINESS=pch_defines,time_macros
     - CCACHE_COMPRESS=1
     - CCACHE_COMPRESS=1
     - CCACHE_MAXSIZE=100M
     - CCACHE_MAXSIZE=100M
+  matrix:
+    - URHO3D_LIB_TYPE=STATIC
+    - URHO3D_LIB_TYPE=SHARED
 matrix:
 matrix:
   fast_finish: true
   fast_finish: true
-  include:
-    - compiler: gcc-archived-bitcode
-      env: URHO3D_LIB_TYPE=STATIC
-    - compiler: gcc-linked-bitcode
-      env: URHO3D_LIB_TYPE=SHARED
 before_script:
 before_script:
   - rake ci_timer
   - rake ci_timer
   - export TRAVIS_COMMIT=$TRAVIS_COMMIT~
   - export TRAVIS_COMMIT=$TRAVIS_COMMIT~

+ 114 - 0
Docs/AngelScriptAPI.h

@@ -702,6 +702,7 @@ bool enabled;
 /* readonly */
 /* readonly */
 bool enabledEffective;
 bool enabledEffective;
 FaceCameraMode faceCameraMode;
 FaceCameraMode faceCameraMode;
+bool fixedScreenSize;
 /* readonly */
 /* readonly */
 uint id;
 uint id;
 /* readonly */
 /* readonly */
@@ -5477,6 +5478,7 @@ int y;
 class JSONFile
 class JSONFile
 {
 {
 // Methods:
 // Methods:
+bool FromString(const String&);
 JSONValue& GetRoot();
 JSONValue& GetRoot();
 bool HasSubscribedToEvent(Object, const String&);
 bool HasSubscribedToEvent(Object, const String&);
 bool HasSubscribedToEvent(const String&);
 bool HasSubscribedToEvent(const String&);
@@ -6669,6 +6671,107 @@ uint useTimer;
 int weakRefs;
 int weakRefs;
 };
 };
 
 
+class NamedPipe
+{
+// Methods:
+void Close();
+bool HasSubscribedToEvent(Object, const String&);
+bool HasSubscribedToEvent(const String&);
+bool Open(const String&, bool);
+Array<uint8> Read(uint);
+bool ReadBool();
+BoundingBox ReadBoundingBox();
+int8 ReadByte();
+Color ReadColor();
+double ReadDouble();
+String ReadFileID();
+float ReadFloat();
+int ReadInt();
+IntRect ReadIntRect();
+IntVector2 ReadIntVector2();
+String ReadLine();
+Matrix3 ReadMatrix3();
+Matrix3x4 ReadMatrix3x4();
+Matrix4 ReadMatrix4();
+uint ReadNetID();
+Quaternion ReadPackedQuaternion();
+Vector3 ReadPackedVector3(float);
+Quaternion ReadQuaternion();
+int16 ReadShort();
+String ReadString();
+StringHash ReadStringHash();
+uint8 ReadUByte();
+uint ReadUInt();
+uint16 ReadUShort();
+uint ReadVLE();
+Variant ReadVariant();
+VariantMap ReadVariantMap();
+Vector2 ReadVector2();
+Vector3 ReadVector3();
+Vector4 ReadVector4();
+VectorBuffer ReadVectorBuffer(uint);
+uint Seek(uint);
+void SendEvent(const String&, VariantMap& = VariantMap ( ));
+uint Write(Array<uint8>);
+bool WriteBool(bool);
+bool WriteBoundingBox(const BoundingBox&);
+bool WriteByte(int8);
+bool WriteColor(const Color&);
+bool WriteDouble(double);
+bool WriteFileID(const String&);
+bool WriteFloat(float);
+bool WriteInt(int);
+bool WriteIntRect(const IntRect&);
+bool WriteIntVector2(const IntVector2&);
+bool WriteLine(const String&);
+bool WriteMatrix3(const Matrix3&);
+bool WriteMatrix3x4(const Matrix3x4&);
+bool WriteMatrix4(const Matrix4&);
+bool WriteNetID(uint);
+bool WritePackedQuaternion(const Quaternion&);
+bool WritePackedVector3(const Vector3&, float);
+bool WriteQuaternion(const Quaternion&);
+bool WriteShort(int16);
+bool WriteString(const String&);
+bool WriteStringHash(const StringHash&);
+bool WriteUByte(uint8);
+bool WriteUInt(uint);
+bool WriteUShort(uint16);
+bool WriteVLE(uint);
+bool WriteVariant(const Variant&);
+bool WriteVariantMap(const VariantMap&);
+bool WriteVector2(const Vector2&);
+bool WriteVector3(const Vector3&);
+bool WriteVector4(const Vector4&);
+bool WriteVectorBuffer(const VectorBuffer&);
+
+// Properties:
+/* readonly */
+String category;
+/* readonly */
+uint checksum;
+/* readonly */
+bool eof;
+/* readonly */
+String name;
+/* readonly */
+bool open;
+/* readonly */
+uint position;
+/* readonly */
+int refs;
+/* readonly */
+bool server;
+/* readonly */
+uint size;
+/* readonly */
+StringHash type;
+/* readonly */
+String typeName;
+/* readonly */
+int weakRefs;
+};
+
 class NavArea
 class NavArea
 {
 {
 // Methods:
 // Methods:
@@ -7571,6 +7674,7 @@ float dampingForce;
 Vector3 emitterSize;
 Vector3 emitterSize;
 EmitterType emitterType;
 EmitterType emitterType;
 FaceCameraMode faceCameraMode;
 FaceCameraMode faceCameraMode;
+bool fixedScreenSize;
 float inactiveTime;
 float inactiveTime;
 Material material;
 Material material;
 Vector3 maxDirection;
 Vector3 maxDirection;
@@ -7705,6 +7809,7 @@ bool enabled;
 /* readonly */
 /* readonly */
 bool enabledEffective;
 bool enabledEffective;
 FaceCameraMode faceCameraMode;
 FaceCameraMode faceCameraMode;
+bool fixedScreenSize;
 /* readonly */
 /* readonly */
 uint id;
 uint id;
 /* readonly */
 /* readonly */
@@ -11382,6 +11487,9 @@ int dragButtonCount;
 uint dragDropMode;
 uint dragDropMode;
 bool editable;
 bool editable;
 Color effectColor;
 Color effectColor;
+bool effectRoundStroke;
+IntVector2 effectShadowOffset;
+int effectStrokeThickness;
 bool elementEventSender;
 bool elementEventSender;
 bool enabled;
 bool enabled;
 /* readonly */
 /* readonly */
@@ -11541,10 +11649,14 @@ Array<Color> colors;
 float drawDistance;
 float drawDistance;
 Color effectColor;
 Color effectColor;
 float effectDepthBias;
 float effectDepthBias;
+bool effectRoundStroke;
+IntVector2 effectShadowOffset;
+int effectStrokeThickness;
 bool enabled;
 bool enabled;
 /* readonly */
 /* readonly */
 bool enabledEffective;
 bool enabledEffective;
 FaceCameraMode faceCameraMode;
 FaceCameraMode faceCameraMode;
+bool fixedScreenSize;
 /* readonly */
 /* readonly */
 Font font;
 Font font;
 /* readonly */
 /* readonly */
@@ -14349,6 +14461,7 @@ int RandomInt();
 int RandomInt(int);
 int RandomInt(int);
 int RandomInt(int, int);
 int RandomInt(int, int);
 float RandomNormal(float, float);
 float RandomNormal(float, float);
+void RegisterEventName(const String&);
 void Remove();
 void Remove();
 String RemoveTrailingSlash(const String&);
 String RemoveTrailingSlash(const String&);
 String ReplaceExtension(const String&, const String&);
 String ReplaceExtension(const String&, const String&);
@@ -14449,6 +14562,7 @@ uint DD_SOURCE_AND_TARGET;
 uint DD_TARGET;
 uint DD_TARGET;
 uint DEBUGHUD_SHOW_ALL;
 uint DEBUGHUD_SHOW_ALL;
 uint DEBUGHUD_SHOW_ALL_MEMORY;
 uint DEBUGHUD_SHOW_ALL_MEMORY;
+uint DEBUGHUD_SHOW_EVENTPROFILER;
 uint DEBUGHUD_SHOW_MEMORY;
 uint DEBUGHUD_SHOW_MEMORY;
 uint DEBUGHUD_SHOW_MODE;
 uint DEBUGHUD_SHOW_MODE;
 uint DEBUGHUD_SHOW_NONE;
 uint DEBUGHUD_SHOW_NONE;

+ 1 - 0
Docs/GettingStarted.dox

@@ -460,6 +460,7 @@ F1          Toggle console
 F2          Toggle profiling display
 F2          Toggle profiling display
 F3          Toggle physics debug geometry
 F3          Toggle physics debug geometry
 F4          Toggle octree debug geometry
 F4          Toggle octree debug geometry
+F5          Toggle event profiling display
 \endverbatim
 \endverbatim
 
 
 If a joystick is connected, it can also be used for controlling the player character.
 If a joystick is connected, it can also be used for controlling the player character.

+ 172 - 6
Docs/LuaScriptAPI.dox

@@ -114,6 +114,7 @@ namespace Urho3D
 <a href="#Class_Menu"><b>Menu</b></a>
 <a href="#Class_Menu"><b>Menu</b></a>
 <a href="#Class_MessageBox"><b>MessageBox</b></a>
 <a href="#Class_MessageBox"><b>MessageBox</b></a>
 <a href="#Class_Model"><b>Model</b></a>
 <a href="#Class_Model"><b>Model</b></a>
+<a href="#Class_NamedPipe"><b>NamedPipe</b></a>
 <a href="#Class_NavArea"><b>NavArea</b></a>
 <a href="#Class_NavArea"><b>NavArea</b></a>
 <a href="#Class_Navigable"><b>Navigable</b></a>
 <a href="#Class_Navigable"><b>Navigable</b></a>
 <a href="#Class_NavigationGeometryInfo"><b>NavigationGeometryInfo</b></a>
 <a href="#Class_NavigationGeometryInfo"><b>NavigationGeometryInfo</b></a>
@@ -589,7 +590,6 @@ Properties:
 - Color color
 - Color color
 - float rotation
 - float rotation
 - bool enabled
 - bool enabled
-- float sortDistance
 
 
 <a name="Class_BillboardSet"></a>
 <a name="Class_BillboardSet"></a>
 ### BillboardSet : Drawable
 ### BillboardSet : Drawable
@@ -601,6 +601,7 @@ Methods:
 - void SetRelative(bool enable)
 - void SetRelative(bool enable)
 - void SetScaled(bool enable)
 - void SetScaled(bool enable)
 - void SetSorted(bool enable)
 - void SetSorted(bool enable)
+- void SetFixedScreenSize(bool enable)
 - void SetFaceCameraMode(FaceCameraMode mode)
 - void SetFaceCameraMode(FaceCameraMode mode)
 - void SetAnimationLodBias(float bias)
 - void SetAnimationLodBias(float bias)
 - void Commit()
 - void Commit()
@@ -610,6 +611,7 @@ Methods:
 - bool IsRelative() const
 - bool IsRelative() const
 - bool IsScaled() const
 - bool IsScaled() const
 - bool IsSorted() const
 - bool IsSorted() const
+- bool IsFixedScreenSize() const
 - FaceCameraMode GetFaceCameraMode() const
 - FaceCameraMode GetFaceCameraMode() const
 - float GetAnimationLodBias() const
 - float GetAnimationLodBias() const
 
 
@@ -620,6 +622,7 @@ Properties:
 - bool relative
 - bool relative
 - bool scaled
 - bool scaled
 - bool sorted
 - bool sorted
+- bool fixedScreenSize
 - FaceCameraMode faceCameraMode
 - FaceCameraMode faceCameraMode
 - float animationLodBias
 - float animationLodBias
 
 
@@ -2614,7 +2617,8 @@ Properties:
 ### HierarchyContainer : UIElement
 ### HierarchyContainer : UIElement
 
 
 <a name="Class_HttpRequest"></a>
 <a name="Class_HttpRequest"></a>
-### HttpRequest : Deserializer
+### HttpRequest
+
 
 
 Methods:
 Methods:
 
 
@@ -2624,6 +2628,44 @@ Methods:
 - HttpRequestState GetState() const
 - HttpRequestState GetState() const
 - unsigned GetAvailableSize() const
 - unsigned GetAvailableSize() const
 - bool IsOpen() const
 - bool IsOpen() const
+- VectorBuffer Read(unsigned size)
+- bool IsEof() const
+- int ReadInt()
+- short ReadShort()
+- char ReadByte()
+- unsigned ReadUInt()
+- short ReadUShort()
+- char ReadUByte()
+- bool ReadBool()
+- float ReadFloat()
+- double ReadDouble()
+- IntRect ReadIntRect()
+- IntVector2 ReadIntVector2()
+- Rect ReadRect()
+- Vector2 ReadVector2()
+- Vector3 ReadVector3()
+- Vector3 ReadPackedVector3(float maxAbsCoord)
+- Vector4 ReadVector4()
+- Quaternion ReadQuaternion()
+- Quaternion ReadPackedQuaternion()
+- Matrix3 ReadMatrix3()
+- Matrix3x4 ReadMatrix3x4()
+- Matrix4 ReadMatrix4()
+- Color ReadColor()
+- BoundingBox ReadBoundingBox()
+- String ReadString()
+- String ReadFileID()
+- StringHash ReadStringHash()
+- VectorBuffer ReadBuffer()
+- ResourceRef ReadResourceRef()
+- ResourceRefList ReadResourceRefList()
+- Variant ReadVariant()
+- Variant ReadVariant(VariantType type)
+- VariantVector ReadVariantVector()
+- VariantMap ReadVariantMap()
+- unsigned ReadVLE()
+- unsigned ReadNetID()
+- String ReadLine()
 
 
 Properties:
 Properties:
 
 
@@ -2860,6 +2902,7 @@ Methods:
 - JSONFile() (GC)
 - JSONFile() (GC)
 - JSONFile* new()
 - JSONFile* new()
 - void delete()
 - void delete()
+- bool FromString(const String source)
 - const JSONValue& GetRoot() const
 - const JSONValue& GetRoot() const
 - bool Save(const String fileName, const String indentation = "\t") const
 - bool Save(const String fileName, const String indentation = "\t") const
 
 
@@ -3494,6 +3537,102 @@ Properties:
 - unsigned numGeometries
 - unsigned numGeometries
 - unsigned numMorphs (readonly)
 - unsigned numMorphs (readonly)
 
 
+<a name="Class_NamedPipe"></a>
+### NamedPipe : Object
+
+Methods:
+
+- NamedPipe() (GC)
+- NamedPipe* new()
+- NamedPipe(const String pipeName, bool isServer) (GC)
+- NamedPipe* new(const String pipeName, bool isServer)
+- void delete()
+- bool Open(const String pipeName, bool isServer)
+- void Close()
+- bool IsOpen() const
+- VectorBuffer Read(unsigned size)
+- const String GetName() const
+- bool IsEof() const
+- int ReadInt()
+- short ReadShort()
+- char ReadByte()
+- unsigned ReadUInt()
+- short ReadUShort()
+- char ReadUByte()
+- bool ReadBool()
+- float ReadFloat()
+- double ReadDouble()
+- IntRect ReadIntRect()
+- IntVector2 ReadIntVector2()
+- Rect ReadRect()
+- Vector2 ReadVector2()
+- Vector3 ReadVector3()
+- Vector3 ReadPackedVector3(float maxAbsCoord)
+- Vector4 ReadVector4()
+- Quaternion ReadQuaternion()
+- Quaternion ReadPackedQuaternion()
+- Matrix3 ReadMatrix3()
+- Matrix3x4 ReadMatrix3x4()
+- Matrix4 ReadMatrix4()
+- Color ReadColor()
+- BoundingBox ReadBoundingBox()
+- String ReadString()
+- String ReadFileID()
+- StringHash ReadStringHash()
+- VectorBuffer ReadBuffer()
+- ResourceRef ReadResourceRef()
+- ResourceRefList ReadResourceRefList()
+- Variant ReadVariant()
+- Variant ReadVariant(VariantType type)
+- VariantVector ReadVariantVector()
+- VariantMap ReadVariantMap()
+- unsigned ReadVLE()
+- unsigned ReadNetID()
+- String ReadLine()
+- unsigned Write(const VectorBuffer& buffer)
+- bool WriteInt(int value)
+- bool WriteShort(short value)
+- bool WriteByte(char value)
+- bool WriteUInt(unsigned value)
+- bool WriteUShort(short value)
+- bool WriteUByte(char value)
+- bool WriteBool(bool value)
+- bool WriteFloat(float value)
+- bool WriteDouble(double value)
+- bool WriteIntRect(const IntRect& value)
+- bool WriteIntVector2(const IntVector2& value)
+- bool WriteRect(const Rect& value)
+- bool WriteVector2(const Vector2& value)
+- bool WriteVector3(const Vector3& value)
+- bool WritePackedVector3(const Vector3& value, float maxAbsCoord)
+- bool WriteVector4(const Vector4& value)
+- bool WriteQuaternion(const Quaternion& value)
+- bool WritePackedQuaternion(const Quaternion& value)
+- bool WriteMatrix3(const Matrix3& value)
+- bool WriteMatrix3x4(const Matrix3x4& value)
+- bool WriteMatrix4(const Matrix4& value)
+- bool WriteColor(const Color& value)
+- bool WriteBoundingBox(const BoundingBox& value)
+- bool WriteString(const String value)
+- bool WriteFileID(const String value)
+- bool WriteStringHash(const StringHash& value)
+- bool WriteBuffer(const VectorBuffer& buffer)
+- bool WriteResourceRef(const ResourceRef& value)
+- bool WriteResourceRefList(const ResourceRefList& value)
+- bool WriteVariant(const Variant& value)
+- bool WriteVariantData(const Variant& value)
+- bool WriteVariantVector(const VariantVector& value)
+- bool WriteVariantMap(const VariantMap& value)
+- bool WriteVLE(unsigned value)
+- bool WriteNetID(unsigned value)
+- bool WriteLine(const String value)
+
+Properties:
+
+- String name (readonly)
+- bool eof (readonly)
+- bool open (readonly)
+
 <a name="Class_NavArea"></a>
 <a name="Class_NavArea"></a>
 ### NavArea : Component
 ### NavArea : Component
 
 
@@ -4048,6 +4187,7 @@ Methods:
 - void SetRelative(bool enable)
 - void SetRelative(bool enable)
 - void SetScaled(bool enable)
 - void SetScaled(bool enable)
 - void SetSorted(bool enable)
 - void SetSorted(bool enable)
+- void SetFixedScreenSize(bool enable)
 - void SetAnimationLodBias(float lodBias)
 - void SetAnimationLodBias(float lodBias)
 - void SetEmitterType(EmitterType type)
 - void SetEmitterType(EmitterType type)
 - void SetEmitterSize(const Vector3& size)
 - void SetEmitterSize(const Vector3& size)
@@ -4089,6 +4229,7 @@ Methods:
 - bool IsRelative() const
 - bool IsRelative() const
 - bool IsScaled() const
 - bool IsScaled() const
 - bool IsSorted() const
 - bool IsSorted() const
+- bool IsFixedScreenSize() const
 - float GetAnimationLodBias() const
 - float GetAnimationLodBias() const
 - EmitterType GetEmitterType() const
 - EmitterType GetEmitterType() const
 - const Vector3& GetEmitterSize() const
 - const Vector3& GetEmitterSize() const
@@ -4125,6 +4266,7 @@ Properties:
 - bool relative
 - bool relative
 - bool scaled
 - bool scaled
 - bool sorted
 - bool sorted
+- bool fixedScreenSize
 - float animationLodBias
 - float animationLodBias
 - EmitterType emitterType
 - EmitterType emitterType
 - const Vector3& emitterSize
 - const Vector3& emitterSize
@@ -5232,7 +5374,7 @@ Properties:
 - String varNamesAttr
 - String varNamesAttr
 
 
 <a name="Class_ScrollBar"></a>
 <a name="Class_ScrollBar"></a>
-### ScrollBar : UIElement
+### ScrollBar : BorderImage
 
 
 Methods:
 Methods:
 
 
@@ -5974,6 +6116,9 @@ Methods:
 - void SetSelectionColor(const Color& color)
 - void SetSelectionColor(const Color& color)
 - void SetHoverColor(const Color& color)
 - void SetHoverColor(const Color& color)
 - void SetTextEffect(TextEffect textEffect)
 - void SetTextEffect(TextEffect textEffect)
+- void SetEffectShadowOffset(const IntVector2& offset)
+- void SetEffectStrokeThickness(int thickness)
+- void SetEffectRoundStroke(bool roundStroke)
 - void SetEffectColor(const Color& effectColor)
 - void SetEffectColor(const Color& effectColor)
 - bool GetAutoLocalizable() const
 - bool GetAutoLocalizable() const
 - void SetAutoLocalizable(bool enable)
 - void SetAutoLocalizable(bool enable)
@@ -5988,6 +6133,9 @@ Methods:
 - const Color& GetSelectionColor() const
 - const Color& GetSelectionColor() const
 - const Color& GetHoverColor() const
 - const Color& GetHoverColor() const
 - TextEffect GetTextEffect() const
 - TextEffect GetTextEffect() const
+- const IntVector2& GetEffectShadowOffset() const
+- int GetEffectStrokeThickness() const
+- bool GetEffectRoundStroke() const
 - const Color& GetEffectColor() const
 - const Color& GetEffectColor() const
 - int GetRowHeight() const
 - int GetRowHeight() const
 - unsigned GetNumRows() const
 - unsigned GetNumRows() const
@@ -6012,6 +6160,9 @@ Properties:
 - Color& selectionColor
 - Color& selectionColor
 - Color& hoverColor
 - Color& hoverColor
 - TextEffect textEffect
 - TextEffect textEffect
+- IntVector2& effectShadowOffset
+- int effectStrokeThickness
+- bool effectRoundStroke
 - Color& effectColor
 - Color& effectColor
 - int rowHeight (readonly)
 - int rowHeight (readonly)
 - unsigned numRows (readonly)
 - unsigned numRows (readonly)
@@ -6036,12 +6187,16 @@ Methods:
 - void SetRowSpacing(float spacing)
 - void SetRowSpacing(float spacing)
 - void SetWordwrap(bool enable)
 - void SetWordwrap(bool enable)
 - void SetTextEffect(TextEffect textEffect)
 - void SetTextEffect(TextEffect textEffect)
+- void SetEffectShadowOffset(const IntVector2& offset)
+- void SetEffectStrokeThickness(int thickness)
+- void SetEffectRoundStroke(bool roundStroke)
 - void SetEffectColor(const Color& effectColor)
 - void SetEffectColor(const Color& effectColor)
 - void SetEffectDepthBias(float bias)
 - void SetEffectDepthBias(float bias)
 - void SetWidth(int width)
 - void SetWidth(int width)
 - void SetColor(const Color& color)
 - void SetColor(const Color& color)
 - void SetColor(Corner corner, const Color& color)
 - void SetColor(Corner corner, const Color& color)
 - void SetOpacity(float opacity)
 - void SetOpacity(float opacity)
+- void SetFixedScreenSize(bool enable)
 - void SetFaceCameraMode(FaceCameraMode mode)
 - void SetFaceCameraMode(FaceCameraMode mode)
 - Font* GetFont() const
 - Font* GetFont() const
 - Material* GetMaterial() const
 - Material* GetMaterial() const
@@ -6053,6 +6208,9 @@ Methods:
 - float GetRowSpacing() const
 - float GetRowSpacing() const
 - bool GetWordwrap() const
 - bool GetWordwrap() const
 - TextEffect GetTextEffect() const
 - TextEffect GetTextEffect() const
+- const IntVector2& GetEffectShadowOffset() const
+- int GetEffectStrokeThickness() const
+- bool GetEffectRoundStroke() const
 - const Color& GetEffectColor() const
 - const Color& GetEffectColor() const
 - float GetEffectDepthBias() const
 - float GetEffectDepthBias() const
 - int GetWidth() const
 - int GetWidth() const
@@ -6064,6 +6222,7 @@ Methods:
 - IntVector2 GetCharSize(unsigned index)
 - IntVector2 GetCharSize(unsigned index)
 - const Color& GetColor(Corner corner) const
 - const Color& GetColor(Corner corner) const
 - float GetOpacity() const
 - float GetOpacity() const
+- bool IsFixedScreenSize() const
 - FaceCameraMode GetFaceCameraMode() const
 - FaceCameraMode GetFaceCameraMode() const
 
 
 Properties:
 Properties:
@@ -6078,6 +6237,9 @@ Properties:
 - float rowSpacing
 - float rowSpacing
 - bool wordwrap
 - bool wordwrap
 - TextEffect textEffect
 - TextEffect textEffect
+- IntVector2& effectShadowOffset
+- int effectStrokeThickness
+- bool effectRoundStroke
 - Color& effectColor
 - Color& effectColor
 - float effectDepthBias
 - float effectDepthBias
 - int width
 - int width
@@ -6086,6 +6248,7 @@ Properties:
 - unsigned numRows (readonly)
 - unsigned numRows (readonly)
 - unsigned numChars (readonly)
 - unsigned numChars (readonly)
 - float opacity
 - float opacity
+- bool fixedScreenSize
 - FaceCameraMode faceCameraMode
 - FaceCameraMode faceCameraMode
 
 
 <a name="Class_Texture"></a>
 <a name="Class_Texture"></a>
@@ -7952,8 +8115,8 @@ Properties:
 - Renderer* GetRenderer()
 - Renderer* GetRenderer()
 - Time* GetTime()
 - Time* GetTime()
 - UI* GetUI()
 - UI* GetUI()
-- bool HasSubscribedToEvent(const String eventName)
 - bool HasSubscribedToEvent(Object* sender, const String eventName)
 - bool HasSubscribedToEvent(Object* sender, const String eventName)
+- bool HasSubscribedToEvent(const String eventName)
 - bool IsAbsolutePath(const String pathName)
 - bool IsAbsolutePath(const String pathName)
 - bool IsAlpha(unsigned ch)
 - bool IsAlpha(unsigned ch)
 - bool IsDigit(unsigned ch)
 - bool IsDigit(unsigned ch)
@@ -7972,9 +8135,10 @@ Properties:
 - float Random()
 - float Random()
 - float Random(float range)
 - float Random(float range)
 - float Random(float min, float max)
 - float Random(float min, float max)
-- int RandomInt(int min, int max)
 - int RandomInt(int range)
 - int RandomInt(int range)
+- int RandomInt(int min, int max)
 - float RandomNormal(float meanValue, float variance)
 - float RandomNormal(float meanValue, float variance)
+- void RegisterEventName(const String eventName)
 - String RemoveTrailingSlash(const String pathName)
 - String RemoveTrailingSlash(const String pathName)
 - String ReplaceExtension(const String fullPath, const String newExtension)
 - String ReplaceExtension(const String fullPath, const String newExtension)
 - unsigned SDBMHash(unsigned hash, char c)
 - unsigned SDBMHash(unsigned hash, char c)
@@ -7986,8 +8150,8 @@ Properties:
 - float Sign(float value)
 - float Sign(float value)
 - float Sin(float angle)
 - float Sin(float angle)
 - float SmoothStep(float lhs, float rhs, float t)
 - float SmoothStep(float lhs, float rhs, float t)
-- void SubscribeToEvent(void* sender, const String eventName, void* functionOrFunctionName)
 - void SubscribeToEvent(const String eventName, void* functionOrFunctionName)
 - void SubscribeToEvent(const String eventName, void* functionOrFunctionName)
+- void SubscribeToEvent(void* sender, const String eventName, void* functionOrFunctionName)
 - float Tan(float angle)
 - float Tan(float angle)
 - bool ToBool(const String source)
 - bool ToBool(const String source)
 - Color ToColor(const String source)
 - Color ToColor(const String source)
@@ -8070,6 +8234,8 @@ Properties:
 - unsigned DD_TARGET
 - unsigned DD_TARGET
 - unsigned DEBUGHUD_SHOW_ALL
 - unsigned DEBUGHUD_SHOW_ALL
 - unsigned DEBUGHUD_SHOW_ALL_MEMORY
 - unsigned DEBUGHUD_SHOW_ALL_MEMORY
+- unsigned DEBUGHUD_SHOW_EVENTPROFILER
+- unsigned DEBUGHUD_SHOW_MEMORY
 - unsigned DEBUGHUD_SHOW_MODE
 - unsigned DEBUGHUD_SHOW_MODE
 - unsigned DEBUGHUD_SHOW_NONE
 - unsigned DEBUGHUD_SHOW_NONE
 - unsigned DEBUGHUD_SHOW_PROFILER
 - unsigned DEBUGHUD_SHOW_PROFILER

+ 16 - 6
Docs/Reference.dox

@@ -77,6 +77,7 @@ After Engine initialization, the following subsystems will always exist:
 The following subsystems are optional, so GetSubsystem() may return null if they have not been created:
 The following subsystems are optional, so GetSubsystem() may return null if they have not been created:
 
 
 - Profiler: Provides hierarchical function execution time measurement using the operating system performance counter. Exists if profiling has been compiled in (configurable from the root CMakeLists.txt)
 - Profiler: Provides hierarchical function execution time measurement using the operating system performance counter. Exists if profiling has been compiled in (configurable from the root CMakeLists.txt)
+- EventProfiler: Same as Profiler but for events.
 - Graphics: Manages the application window, the rendering context and resources. Exists if not in headless mode.
 - Graphics: Manages the application window, the rendering context and resources. Exists if not in headless mode.
 - Renderer: Renders scenes in 3D and manages rendering quality settings. Exists if not in headless mode.
 - Renderer: Renders scenes in 3D and manages rendering quality settings. Exists if not in headless mode.
 - Script: Provides the AngelScript execution environment. Needs to be created and registered manually.
 - Script: Provides the AngelScript execution environment. Needs to be created and registered manually.
@@ -185,6 +186,7 @@ The full list of supported parameters, their datatypes and default values:
 - LogName (string) %Log filename. Default "Urho3D.log".
 - LogName (string) %Log filename. Default "Urho3D.log".
 - FrameLimiter (bool) Whether to cap maximum framerate to 200 (desktop) or 60 (Android/iOS.) Default true.
 - FrameLimiter (bool) Whether to cap maximum framerate to 200 (desktop) or 60 (Android/iOS.) Default true.
 - WorkerThreads (bool) Whether to create worker threads for the %WorkQueue subsystem according to available CPU cores. Default true.
 - WorkerThreads (bool) Whether to create worker threads for the %WorkQueue subsystem according to available CPU cores. Default true.
+- EventProfiler (bool) Whether to create the EventProfiler subsystem. Default true.
 - ResourcePrefixPaths (string) A semicolon-separated list of resource prefix paths to use. If not specified then the default prefix path is set to executable path. The resource prefix paths can also be defined using URHO3D_PREFIX_PATH env-var. When both are defined, the paths set by -pp takes higher precedence.
 - ResourcePrefixPaths (string) A semicolon-separated list of resource prefix paths to use. If not specified then the default prefix path is set to executable path. The resource prefix paths can also be defined using URHO3D_PREFIX_PATH env-var. When both are defined, the paths set by -pp takes higher precedence.
 - ResourcePaths (string) A semicolon-separated list of resource paths to use. If corresponding packages (ie. Data.pak for Data directory) exist they will be used instead. Default "Data;CoreData".
 - ResourcePaths (string) A semicolon-separated list of resource paths to use. If corresponding packages (ie. Data.pak for Data directory) exist they will be used instead. Default "Data;CoreData".
 - ResourcePackages (string) A semicolon-separated list of resource packages to use. Default empty.
 - ResourcePackages (string) A semicolon-separated list of resource packages to use. Default empty.
@@ -1612,13 +1614,11 @@ Additionally there are shadow fade distance, shadow intensity, shadow resolution
 
 
 - The shadow near/far ratio controls shadow camera near clip distance for point & spot lights. The default ratio is 0.002, which means a light with range 100 would have its shadow camera near plane set at the distance of 0.2. Set this as high as you can for better shadow depth resolution, but note that the bias parameters will likely have to be adjusted as well.
 - The shadow near/far ratio controls shadow camera near clip distance for point & spot lights. The default ratio is 0.002, which means a light with range 100 would have its shadow camera near plane set at the distance of 0.2. Set this as high as you can for better shadow depth resolution, but note that the bias parameters will likely have to be adjusted as well.
 
 
-Finally, there are global settings for the shadow map base resolution, shadow map bit depth (16 or 24 bit) & filtering quality in Renderer.
+\section Lights_ShadowGlobal Global shadow settings
 
 
-\section Lights_ShadowCulling Shadow culling
-
-Similarly to light culling with lightmasks, shadowmasks can be used to select which objects should cast shadows with respect to each light. See \ref Drawable::SetShadowMask "SetShadowMask()". A potential shadow caster's shadow mask will be ANDed with the light's lightmask to see if it should be rendered to the light's shadow map. Also, when an object is inside a zone, its shadowmask will be ANDed with the zone's shadowmask as well. By default all bits are set in the shadowmask.
+The shadow map base resolution and quality (bit depth & sampling mode) are set through functions in the Renderer subsystem, see \ref Renderer::SetShadowMapSize "SetShadowMapSize()" and \ref Renderer::SetShadowQuality "SetShadowQuality()".
 
 
-For an example of shadow culling, imagine a house (which itself is a shadow caster) containing several objects inside, and a shadowed directional light shining in from the windows. In that case shadow map rendering can be avoided for objects already in shadow by clearing the respective bit from their shadowmasks.
+The shadow quality enum allows choosing also variance (VSM) shadows instead of the default hardware depth shadows. VSM shadows behave markedly differently; depth bias settings are no longer relevant, but you should make sure all your large surfaces (also ground & terrain) are marked as shadow casters, otherwise shadows cast by objects moving over them can appear unnaturally thin. For VSM shadows, see the functions \ref Renderer::SetShadowSoftness "SetShadowSoftness()" and \ref Renderer::SetVSMShadowParameters "SetVSMShadowParameters()" to control the softness (blurring) and in-shadow detection behavior. Instead of self-shadowing artifacts common with hardware depth shadows, you may encounter light bleeding when shadow casting surfaces are close in light direction to each other, which adjusting the VSM shadow parameters may help.
 
 
 \section Lights_ShadowMapReuse Shadow map reuse
 \section Lights_ShadowMapReuse Shadow map reuse
 
 
@@ -1628,6 +1628,12 @@ When reuse is enabled, only one shadow texture of each shadow map size needs to
 
 
 When reuse is disabled, all shadow maps are rendered before the actual scene rendering. Now multiple shadow textures need to be reserved based on the number of simultaneous shadow casting lights. See the function \ref Renderer::SetNumShadowMaps "SetNumShadowMaps()". If there are not enough shadow textures, they will be assigned to the closest/brightest lights, and the rest will be rendered unshadowed. Now more texture memory is needed, but the advantage is that also transparent objects can receive shadows.
 When reuse is disabled, all shadow maps are rendered before the actual scene rendering. Now multiple shadow textures need to be reserved based on the number of simultaneous shadow casting lights. See the function \ref Renderer::SetNumShadowMaps "SetNumShadowMaps()". If there are not enough shadow textures, they will be assigned to the closest/brightest lights, and the rest will be rendered unshadowed. Now more texture memory is needed, but the advantage is that also transparent objects can receive shadows.
 
 
+\section Lights_ShadowCulling Shadow culling
+
+Similarly to light culling with lightmasks, shadowmasks can be used to select which objects should cast shadows with respect to each light. See \ref Drawable::SetShadowMask "SetShadowMask()". A potential shadow caster's shadow mask will be ANDed with the light's lightmask to see if it should be rendered to the light's shadow map. Also, when an object is inside a zone, its shadowmask will be ANDed with the zone's shadowmask as well. By default all bits are set in the shadowmask.
+
+For an example of shadow culling, imagine a house (which itself is a shadow caster) containing several objects inside, and a shadowed directional light shining in from the windows. In that case shadow map rendering can be avoided for objects already in shadow by clearing the respective bit from their shadowmasks.
+
 
 
 \page SkeletalAnimation Skeletal animation
 \page SkeletalAnimation Skeletal animation
 
 
@@ -1700,6 +1706,7 @@ The parameters of the particle system are stored in a ParticleEffect resource cl
     <relative enable="true|false" />
     <relative enable="true|false" />
     <scaled enable="true|false" />
     <scaled enable="true|false" />
     <sorted enable="true|false" />
     <sorted enable="true|false" />
+    <fixedscreensize enable="true|false" />
     <emittertype value="sphere|box" />
     <emittertype value="sphere|box" />
     <emittersize value="x y z" />
     <emittersize value="x y z" />
     <emitterradius value="x" />
     <emitterradius value="x" />
@@ -1859,7 +1866,9 @@ The Audio subsystem implements an audio output stream. Once it has been initiali
 - Playing raw audio, Ogg Vorbis or WAV Sound resources using the SoundSource component. This allows manual stereo panning of mono sounds; stereo sounds will be output with their original stereo mix.
 - Playing raw audio, Ogg Vorbis or WAV Sound resources using the SoundSource component. This allows manual stereo panning of mono sounds; stereo sounds will be output with their original stereo mix.
 - Playing the above sound formats in pseudo-3D using the SoundSource3D component. It has stereo positioning and distance attenuation, but does not (at least yet) filter the sound depending on the direction.
 - Playing the above sound formats in pseudo-3D using the SoundSource3D component. It has stereo positioning and distance attenuation, but does not (at least yet) filter the sound depending on the direction.
 
 
-To hear pseudo-3D positional sounds, a SoundListener component must exist in a scene node and be assigned to the audio subsystem by calling \ref Audio::SetListener "SetListener()". If the sound listener's scene node exists within a specific scene, it will only hear sounds from that scene, but if it has been created into a "sceneless" node it will hear sounds from all scenes.
+A sound source component needs to be created into a Node to be considered "enabled" and be able to play, however that node does not need to belong to a scene (e.g. for positionless %UI / HUD sounds, which would be just unnecessarily clutter in a 3D scene, you can just instantiate a node in application code, similar to a camera existing outside the scene.)
+
+To hear pseudo-3D positional sounds, a SoundListener component must likewise exist in a node and be assigned to the audio subsystem by calling \ref Audio::SetListener "SetListener()". The node's position & rotation define the listening spot. If the sound listener's node belongs to a scene, it only hears sounds from within that specific scene, but if it has been created outside of a scene it will hear any sounds.
 
 
 The output is software mixed for an unlimited amount of simultaneous sounds. Ogg Vorbis sounds are decoded on the fly, and decoding them can be memory- and CPU-intensive, so WAV files are recommended when a large number of short sound effects need to be played.
 The output is software mixed for an unlimited amount of simultaneous sounds. Ogg Vorbis sounds are decoded on the fly, and decoding them can be memory- and CPU-intensive, so WAV files are recommended when a large number of short sound effects need to be played.
 
 
@@ -2997,6 +3006,7 @@ AssetImporter <command> <input file> <output file> [options]
 
 
 Commands:
 Commands:
 model       Output a model
 model       Output a model
+anim        Output animation(s)
 scene       Output a scene
 scene       Output a scene
 node        Output a node and its children (prefab)
 node        Output a node and its children (prefab)
 dump        Dump scene node structure. No output file is generated
 dump        Dump scene node structure. No output file is generated

+ 121 - 0
Docs/ScriptAPI.dox

@@ -875,6 +875,7 @@ namespace Urho3D
 - %Relative %Position : bool
 - %Relative %Position : bool
 - %Relative %Scale : bool
 - %Relative %Scale : bool
 - %Sort %By %Distance : bool
 - %Sort %By %Distance : bool
+- %Fixed %Screen %Size : bool
 - %Can %Be %Occluded : bool
 - %Can %Be %Occluded : bool
 - %Cast %Shadows : bool
 - %Cast %Shadows : bool
 - %Face %Camera %Mode : int
 - %Face %Camera %Mode : int
@@ -1768,6 +1769,13 @@ namespace Urho3D
 - %Indent %Spacing : int
 - %Indent %Spacing : int
 - %Variables : VariantMap
 - %Variables : VariantMap
 - %Tags : StringVector
 - %Tags : StringVector
+- %Texture : ResourceRef
+- %Image %Rect : IntRect
+- %Border : IntRect
+- %Image %Border : IntRect
+- %Hover %Image %Offset : IntVector2
+- %Tiled : bool
+- %Blend %Mode : int
 - %Orientation : int
 - %Orientation : int
 - %Range : float
 - %Range : float
 - %Value : float
 - %Value : float
@@ -2055,6 +2063,9 @@ namespace Urho3D
 - %Selection %Color : Color
 - %Selection %Color : Color
 - %Hover %Color : Color
 - %Hover %Color : Color
 - %Text %Effect : int
 - %Text %Effect : int
+- %Shadow %Offset : IntVector2
+- %Stroke %Thickness : int
+- %Round %Stroke : bool
 - %Effect %Color : Color
 - %Effect %Color : Color
 
 
 ### Text3D
 ### Text3D
@@ -2067,6 +2078,7 @@ namespace Urho3D
 - %Row %Spacing : float
 - %Row %Spacing : float
 - %Word %Wrap : bool
 - %Word %Wrap : bool
 - %Can %Be %Occluded : bool
 - %Can %Be %Occluded : bool
+- %Fixed %Screen %Size : bool
 - %Face %Camera %Mode : int
 - %Face %Camera %Mode : int
 - %Draw %Distance : float
 - %Draw %Distance : float
 - %Width : int
 - %Width : int
@@ -2079,6 +2091,9 @@ namespace Urho3D
 - %Bottom %Left %Color : Color
 - %Bottom %Left %Color : Color
 - %Bottom %Right %Color : Color
 - %Bottom %Right %Color : Color
 - %Text %Effect : int
 - %Text %Effect : int
+- %Shadow %Offset : IntVector2
+- %Stroke %Thickness : int
+- %Round %Stroke : bool
 - %Effect %Color : Color
 - %Effect %Color : Color
 - %Effect %Depth %Bias : float
 - %Effect %Depth %Bias : float
 
 
@@ -2389,6 +2404,7 @@ namespace Urho3D
 <a href="#Class_Menu"><b>Menu</b></a>
 <a href="#Class_Menu"><b>Menu</b></a>
 <a href="#Class_MessageBox"><b>MessageBox</b></a>
 <a href="#Class_MessageBox"><b>MessageBox</b></a>
 <a href="#Class_Model"><b>Model</b></a>
 <a href="#Class_Model"><b>Model</b></a>
+<a href="#Class_NamedPipe"><b>NamedPipe</b></a>
 <a href="#Class_NavArea"><b>NavArea</b></a>
 <a href="#Class_NavArea"><b>NavArea</b></a>
 <a href="#Class_Navigable"><b>Navigable</b></a>
 <a href="#Class_Navigable"><b>Navigable</b></a>
 <a href="#Class_NavigationMesh"><b>NavigationMesh</b></a>
 <a href="#Class_NavigationMesh"><b>NavigationMesh</b></a>
@@ -3133,6 +3149,7 @@ Properties:
 - bool enabled
 - bool enabled
 - bool enabledEffective // readonly
 - bool enabledEffective // readonly
 - FaceCameraMode faceCameraMode
 - FaceCameraMode faceCameraMode
+- bool fixedScreenSize
 - uint id // readonly
 - uint id // readonly
 - bool inView // readonly
 - bool inView // readonly
 - uint lightMask
 - uint lightMask
@@ -7290,6 +7307,7 @@ Properties:
 
 
 Methods:
 Methods:
 
 
+- bool FromString(const String&)
 - JSONValue& GetRoot()
 - JSONValue& GetRoot()
 - bool HasSubscribedToEvent(Object@, const String&)
 - bool HasSubscribedToEvent(Object@, const String&)
 - bool HasSubscribedToEvent(const String&)
 - bool HasSubscribedToEvent(const String&)
@@ -8341,6 +8359,98 @@ Properties:
 - uint useTimer // readonly
 - uint useTimer // readonly
 - int weakRefs // readonly
 - int weakRefs // readonly
 
 
+<a name="Class_NamedPipe"></a>
+
+### NamedPipe
+
+Methods:
+
+- void Close()
+- bool HasSubscribedToEvent(Object@, const String&)
+- bool HasSubscribedToEvent(const String&)
+- bool Open(const String&, bool)
+- uint8[]@ Read(uint)
+- bool ReadBool()
+- BoundingBox ReadBoundingBox()
+- int8 ReadByte()
+- Color ReadColor()
+- double ReadDouble()
+- String ReadFileID()
+- float ReadFloat()
+- int ReadInt()
+- IntRect ReadIntRect()
+- IntVector2 ReadIntVector2()
+- String ReadLine()
+- Matrix3 ReadMatrix3()
+- Matrix3x4 ReadMatrix3x4()
+- Matrix4 ReadMatrix4()
+- uint ReadNetID()
+- Quaternion ReadPackedQuaternion()
+- Vector3 ReadPackedVector3(float)
+- Quaternion ReadQuaternion()
+- int16 ReadShort()
+- String ReadString()
+- StringHash ReadStringHash()
+- uint8 ReadUByte()
+- uint ReadUInt()
+- uint16 ReadUShort()
+- uint ReadVLE()
+- Variant ReadVariant()
+- VariantMap ReadVariantMap()
+- Vector2 ReadVector2()
+- Vector3 ReadVector3()
+- Vector4 ReadVector4()
+- VectorBuffer ReadVectorBuffer(uint)
+- uint Seek(uint)
+- void SendEvent(const String&, VariantMap& = VariantMap ( ))
+- uint Write(uint8[]@)
+- bool WriteBool(bool)
+- bool WriteBoundingBox(const BoundingBox&)
+- bool WriteByte(int8)
+- bool WriteColor(const Color&)
+- bool WriteDouble(double)
+- bool WriteFileID(const String&)
+- bool WriteFloat(float)
+- bool WriteInt(int)
+- bool WriteIntRect(const IntRect&)
+- bool WriteIntVector2(const IntVector2&)
+- bool WriteLine(const String&)
+- bool WriteMatrix3(const Matrix3&)
+- bool WriteMatrix3x4(const Matrix3x4&)
+- bool WriteMatrix4(const Matrix4&)
+- bool WriteNetID(uint)
+- bool WritePackedQuaternion(const Quaternion&)
+- bool WritePackedVector3(const Vector3&, float)
+- bool WriteQuaternion(const Quaternion&)
+- bool WriteShort(int16)
+- bool WriteString(const String&)
+- bool WriteStringHash(const StringHash&)
+- bool WriteUByte(uint8)
+- bool WriteUInt(uint)
+- bool WriteUShort(uint16)
+- bool WriteVLE(uint)
+- bool WriteVariant(const Variant&)
+- bool WriteVariantMap(const VariantMap&)
+- bool WriteVector2(const Vector2&)
+- bool WriteVector3(const Vector3&)
+- bool WriteVector4(const Vector4&)
+- bool WriteVectorBuffer(const VectorBuffer&)
+
+Properties:
+
+- String category // readonly
+- uint checksum // readonly
+- bool eof // readonly
+- String name // readonly
+- bool open // readonly
+- uint position // readonly
+- int refs // readonly
+- bool server // readonly
+- uint size // readonly
+- StringHash type // readonly
+- String typeName // readonly
+- int weakRefs // readonly
+
 <a name="Class_NavArea"></a>
 <a name="Class_NavArea"></a>
 
 
 ### NavArea
 ### NavArea
@@ -9139,6 +9249,7 @@ Properties:
 - Vector3 emitterSize
 - Vector3 emitterSize
 - EmitterType emitterType
 - EmitterType emitterType
 - FaceCameraMode faceCameraMode
 - FaceCameraMode faceCameraMode
+- bool fixedScreenSize
 - float inactiveTime
 - float inactiveTime
 - Material@ material
 - Material@ material
 - Vector3 maxDirection
 - Vector3 maxDirection
@@ -9260,6 +9371,7 @@ Properties:
 - bool enabled
 - bool enabled
 - bool enabledEffective // readonly
 - bool enabledEffective // readonly
 - FaceCameraMode faceCameraMode
 - FaceCameraMode faceCameraMode
+- bool fixedScreenSize
 - uint id // readonly
 - uint id // readonly
 - bool inView // readonly
 - bool inView // readonly
 - uint lightMask
 - uint lightMask
@@ -12546,6 +12658,9 @@ Properties:
 - uint dragDropMode
 - uint dragDropMode
 - bool editable
 - bool editable
 - Color effectColor
 - Color effectColor
+- bool effectRoundStroke
+- IntVector2 effectShadowOffset
+- int effectStrokeThickness
 - bool elementEventSender
 - bool elementEventSender
 - bool enabled
 - bool enabled
 - bool enabledSelf // readonly
 - bool enabledSelf // readonly
@@ -12675,9 +12790,13 @@ Properties:
 - float drawDistance
 - float drawDistance
 - Color effectColor
 - Color effectColor
 - float effectDepthBias
 - float effectDepthBias
+- bool effectRoundStroke
+- IntVector2 effectShadowOffset
+- int effectStrokeThickness
 - bool enabled
 - bool enabled
 - bool enabledEffective // readonly
 - bool enabledEffective // readonly
 - FaceCameraMode faceCameraMode
 - FaceCameraMode faceCameraMode
+- bool fixedScreenSize
 - Font@ font // readonly
 - Font@ font // readonly
 - int fontSize // readonly
 - int fontSize // readonly
 - HorizontalAlignment horizontalAlignment
 - HorizontalAlignment horizontalAlignment
@@ -15202,6 +15321,7 @@ Properties:
 - int RandomInt(int)
 - int RandomInt(int)
 - int RandomInt(int, int)
 - int RandomInt(int, int)
 - float RandomNormal(float, float)
 - float RandomNormal(float, float)
+- void RegisterEventName(const String&)
 - void Remove()
 - void Remove()
 - String RemoveTrailingSlash(const String&)
 - String RemoveTrailingSlash(const String&)
 - String ReplaceExtension(const String&, const String&)
 - String ReplaceExtension(const String&, const String&)
@@ -15300,6 +15420,7 @@ Properties:
 - uint DD_TARGET
 - uint DD_TARGET
 - uint DEBUGHUD_SHOW_ALL
 - uint DEBUGHUD_SHOW_ALL
 - uint DEBUGHUD_SHOW_ALL_MEMORY
 - uint DEBUGHUD_SHOW_ALL_MEMORY
+- uint DEBUGHUD_SHOW_EVENTPROFILER
 - uint DEBUGHUD_SHOW_MEMORY
 - uint DEBUGHUD_SHOW_MEMORY
 - uint DEBUGHUD_SHOW_MODE
 - uint DEBUGHUD_SHOW_MODE
 - uint DEBUGHUD_SHOW_NONE
 - uint DEBUGHUD_SHOW_NONE

+ 21 - 19
Docs/Urho3D.dox

@@ -93,6 +93,7 @@ Urho3D development, contributions and bugfixes by:
 - Pranjal Raihan
 - Pranjal Raihan
 - Nick Royer
 - Nick Royer
 - Miika Santala
 - Miika Santala
+- Bengt Soderstrom
 - Hualin Song
 - Hualin Song
 - James Thomas
 - James Thomas
 - Joshua Tippetts
 - Joshua Tippetts
@@ -157,31 +158,32 @@ Urho3D is greatly inspired by OGRE (http://www.ogre3d.org/) and Horde3D (http://
 
 
 Urho3D uses the following third-party libraries:
 Urho3D uses the following third-party libraries:
 
 
-- AngelScript 2.30.2 (http://www.angelcode.com/angelscript/)
-- Box2D 2.3.0 (http://box2d.org/)
-- Bullet 2.83.6 (http://www.bulletphysics.org/)
-- Civetweb (http://sourceforge.net/projects/civetweb/)
-- FreeType 2.5.0 (http://www.freetype.org/)
-- GLEW 1.9.0 (http://glew.sourceforge.net/)
+- AngelScript 2.30.2 (http://www.angelcode.com/angelscript)
+- Box2D 2.3.0 (http://box2d.org)
+- Bullet 2.83.6 (http://www.bulletphysics.org)
+- Civetweb 1.7 (https://github.com/civetweb/civetweb)
+- FreeType 2.5.0 (http://www.freetype.org)
+- GLEW 1.13.0 (http://glew.sourceforge.net)
 - jo_jpeg 1.52 (http://www.jonolick.com/uploads/7/9/2/1/7921194/jo_jpeg.cpp)
 - jo_jpeg 1.52 (http://www.jonolick.com/uploads/7/9/2/1/7921194/jo_jpeg.cpp)
 - kNet (https://github.com/juj/kNet)
 - kNet (https://github.com/juj/kNet)
 - libcpuid 0.2.2 (https://github.com/anrieff/libcpuid)
 - libcpuid 0.2.2 (https://github.com/anrieff/libcpuid)
 - Lua 5.1 (http://www.lua.org)
 - Lua 5.1 (http://www.lua.org)
 - LuaJIT 2.1.0+ (http://www.luajit.org)
 - LuaJIT 2.1.0+ (http://www.luajit.org)
-- LZ4 (http://code.google.com/p/lz4/)
-- MojoShader (http://icculus.org/mojoshader/)
-- Mustache 1.0 (http://mustache.github.io/, https://github.com/kainjow/Mustache)
-- nanodbc 2.12.4 (http://lexicalunit.github.io/nanodbc/)
-- Open Asset Import Library (http://assimp.sourceforge.net/)
-- rapidjson 0.11 (https://code.google.com/p/rapidjson/)
-- pugixml 1.7 (http://pugixml.org/)
-- Recast/Detour (http://code.google.com/p/recastnavigation/)
-- SDL 2.0.4 (http://www.libsdl.org/)
+- LZ4 r131 (https://github.com/Cyan4973/lz4)
+- MojoShader (http://icculus.org/mojoshader)
+- Mustache 1.0 (http://mustache.github.io, https://github.com/kainjow/Mustache)
+- nanodbc 2.12.4 (http://lexicalunit.github.io/nanodbc)
+- Open Asset Import Library (http://assimp.sourceforge.net)
+- pugixml 1.7 (http://pugixml.org)
+- rapidjson 0.11 (https://code.google.com/p/rapidjson)
+- Recast/Detour (https://github.com/memononen/recastnavigation)
+- SDL 2.0.4 (http://www.libsdl.org)
+- SQLite 3.8.10.2 (https://www.sqlite.org)
 - StanHull (http://codesuppository.blogspot.com/2006/03/john-ratcliffs-code-suppository-blog.html)
 - StanHull (http://codesuppository.blogspot.com/2006/03/john-ratcliffs-code-suppository-blog.html)
-- stb_image 2.10 (http://nothings.org/)
-- stb_image_write 1.01 (http://nothings.org/)
-- stb_vorbis 1.07 (http://nothings.org/)
-- SQLite 3.8.10.2 (https://www.sqlite.org/)
+- stb_image 2.12 (http://nothings.org)
+- stb_image_write 1.02 (http://nothings.org)
+- stb_rect_pack 0.08 (http://nothings.org)
+- stb_vorbis 1.09 (http://nothings.org)
 - tolua++ 1.0.93 (http://www.codenix.com/~tolua)
 - tolua++ 1.0.93 (http://www.codenix.com/~tolua)
 
 
 DXT / ETC1 / PVRTC decompression code based on the Squish library and the Oolong %Engine.<br>
 DXT / ETC1 / PVRTC decompression code based on the Squish library and the Oolong %Engine.<br>

+ 27 - 33
License.txt

@@ -101,7 +101,8 @@ misrepresented as being the original software.
 Civetweb license
 Civetweb license
 ----------------
 ----------------
 
 
-Copyright (c) 2004-2012 Sergey Lyubka
+Copyright (c) 2013-2015 the Civetweb developers
+Copyright (c) 2004-2013 Sergey Lyubka
 
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 of this software and associated documentation files (the "Software"), to deal
@@ -307,37 +308,30 @@ THE SOFTWARE.
 LZ4 license
 LZ4 license
 -----------
 -----------
 
 
-LZ4 - Fast LZ compression algorithm
-Header File
-Copyright (C) 2011-2013, Yann Collet.
-BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
-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.
-
-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
-OWNER 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.
+LZ4 Library
+Copyright (c) 2011-2015, Yann Collet
+All rights reserved.
 
 
-You can contact the author at :
-- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
-- LZ4 source repository : http://code.google.com/p/lz4/
+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.
+
+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.
 
 
 
 
 MojoShader license
 MojoShader license
@@ -482,7 +476,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 pugixml license
 pugixml license
 ---------------
 ---------------
 
 
-Copyright (c) 2006-2010 Arseny Kapoulkine
+Copyright (c) 2006-2015 Arseny Kapoulkine
 
 
 Permission is hereby granted, free of charge, to any person
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
 obtaining a copy of this software and associated documentation
@@ -556,7 +550,7 @@ SDL license
 -----------
 -----------
 
 
 Simple DirectMedia Layer
 Simple DirectMedia Layer
-Copyright (C) 1997-2012 Sam Lantinga <[email protected]>
+Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
 
 
 This software is provided 'as-is', without any express or implied
 This software is provided 'as-is', without any express or implied
 warranty.  In no event will the authors be held liable for any damages
 warranty.  In no event will the authors be held liable for any damages

+ 23 - 21
README.md

@@ -1,8 +1,8 @@
 ![Urho3D logo](https://raw.githubusercontent.com/urho3d/Urho3D/master/bin/Data/Textures/LogoLarge.png)
 ![Urho3D logo](https://raw.githubusercontent.com/urho3d/Urho3D/master/bin/Data/Textures/LogoLarge.png)
 
 
 #Urho3D
 #Urho3D
-
-[![Join the chat at https://gitter.im/urho3d/Urho3D](https://badges.gitter.im/urho3d/Urho3D.svg)](https://gitter.im/urho3d/Urho3D?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+[![Join the chat at https://gitter.im/urho3d/Urho3D](https://badges.gitter.im/urho3d/Urho3D.svg)](https://gitter.im/urho3d/Urho3D?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
 
 **Urho3D** is a free lightweight, cross-platform 2D and 3D game engine implemented in C++ and released under the MIT license. Greatly inspired by OGRE and Horde3D.
 **Urho3D** is a free lightweight, cross-platform 2D and 3D game engine implemented in C++ and released under the MIT license. Greatly inspired by OGRE and Horde3D.
 
 
@@ -47,6 +47,7 @@ Urho3D development, contributions and bugfixes by:
 - Pranjal Raihan
 - Pranjal Raihan
 - Nick Royer
 - Nick Royer
 - Miika Santala
 - Miika Santala
+- Bengt Soderstrom
 - Hualin Song
 - Hualin Song
 - James Thomas
 - James Thomas
 - Joshua Tippetts
 - Joshua Tippetts
@@ -120,31 +121,32 @@ Urho3D is greatly inspired by OGRE (http://www.ogre3d.org) and Horde3D
   http://warp.povusers.org/SortComparison/
   http://warp.povusers.org/SortComparison/
 
 
 Urho3D uses the following third-party libraries:
 Urho3D uses the following third-party libraries:
-- AngelScript 2.30.2 (http://www.angelcode.com/angelscript/)
-- Box2D 2.3.0 (http://box2d.org/)
-- Bullet 2.83.6 (http://www.bulletphysics.org/)
-- Civetweb (http://sourceforge.net/projects/civetweb/)
-- FreeType 2.5.0 (http://www.freetype.org/)
-- GLEW 1.9.0 (http://glew.sourceforge.net/)
+- AngelScript 2.30.2 (http://www.angelcode.com/angelscript)
+- Box2D 2.3.0 (http://box2d.org)
+- Bullet 2.83.6 (http://www.bulletphysics.org)
+- Civetweb 1.7 (https://github.com/civetweb/civetweb)
+- FreeType 2.5.0 (http://www.freetype.org)
+- GLEW 1.13.0 (http://glew.sourceforge.net)
 - jo_jpeg 1.52 (http://www.jonolick.com/uploads/7/9/2/1/7921194/jo_jpeg.cpp)
 - jo_jpeg 1.52 (http://www.jonolick.com/uploads/7/9/2/1/7921194/jo_jpeg.cpp)
 - kNet (https://github.com/juj/kNet)
 - kNet (https://github.com/juj/kNet)
 - libcpuid 0.2.2 (https://github.com/anrieff/libcpuid)
 - libcpuid 0.2.2 (https://github.com/anrieff/libcpuid)
 - Lua 5.1 (http://www.lua.org)
 - Lua 5.1 (http://www.lua.org)
 - LuaJIT 2.1.0+ (http://www.luajit.org)
 - LuaJIT 2.1.0+ (http://www.luajit.org)
-- LZ4 (http://code.google.com/p/lz4/)
-- MojoShader (http://icculus.org/mojoshader/)
-- Mustache 1.0 (http://mustache.github.io/, https://github.com/kainjow/Mustache)
-- nanodbc 2.12.4 (http://lexicalunit.github.io/nanodbc/)
-- Open Asset Import Library (http://assimp.sourceforge.net/)
-- pugixml 1.7 (http://pugixml.org/)
-- rapidjson 0.11 (https://code.google.com/p/rapidjson/)
-- Recast/Detour (https://github.com/memononen/recastnavigation/)
-- SDL 2.0.4 (http://www.libsdl.org/)
+- LZ4 r131 (https://github.com/Cyan4973/lz4)
+- MojoShader (http://icculus.org/mojoshader)
+- Mustache 1.0 (http://mustache.github.io, https://github.com/kainjow/Mustache)
+- nanodbc 2.12.4 (http://lexicalunit.github.io/nanodbc)
+- Open Asset Import Library (http://assimp.sourceforge.net)
+- pugixml 1.7 (http://pugixml.org)
+- rapidjson 0.11 (https://code.google.com/p/rapidjson)
+- Recast/Detour (https://github.com/memononen/recastnavigation)
+- SDL 2.0.4 (http://www.libsdl.org)
+- SQLite 3.8.10.2 (https://www.sqlite.org)
 - StanHull (http://codesuppository.blogspot.com/2006/03/john-ratcliffs-code-suppository-blog.html)
 - StanHull (http://codesuppository.blogspot.com/2006/03/john-ratcliffs-code-suppository-blog.html)
-- stb_image 2.10 (http://nothings.org/)
-- stb_image_write 1.01 (http://nothings.org/)
-- stb_vorbis 1.07 (http://nothings.org/)
-- SQLite 3.8.10.2 (https://www.sqlite.org/)
+- stb_image 2.12 (http://nothings.org)
+- stb_image_write 1.02 (http://nothings.org)
+- stb_rect_pack 0.08 (http://nothings.org)
+- stb_vorbis 1.09 (http://nothings.org)
 - tolua++ 1.0.93 (http://www.codenix.com/~tolua)
 - tolua++ 1.0.93 (http://www.codenix.com/~tolua)
 
 
 DXT / ETC1 / PVRTC decompression code based on the Squish library and the Oolong
 DXT / ETC1 / PVRTC decompression code based on the Squish library and the Oolong

+ 37 - 0
Source/Samples/43_HttpRequestDemo/CMakeLists.txt

@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2008-2016 the Urho3D project.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+if (NOT URHO3D_NETWORK)
+    return ()
+endif ()
+
+# Define target name
+set (TARGET_NAME 43_HttpRequestDemo)
+
+# Define source files
+define_source_files (EXTRA_H_FILES ${COMMON_SAMPLE_H_FILES})
+
+# Setup target with resource copying
+setup_main_executable ()
+
+# Setup test cases
+setup_test ()

+ 123 - 0
Source/Samples/43_HttpRequestDemo/HttpRequestDemo.cpp

@@ -0,0 +1,123 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <Urho3D/Core/CoreEvents.h>
+#include <Urho3D/Core/ProcessUtils.h>
+#include <Urho3D/Input/Input.h>
+#include <Urho3D/Network/Network.h>
+#include <Urho3D/Network/HttpRequest.h>
+#include <Urho3D/UI/Font.h>
+#include <Urho3D/UI/Text.h>
+#include <Urho3D/UI/UI.h>
+
+#include "HttpRequestDemo.h"
+
+#include <Urho3D/DebugNew.h>
+
+URHO3D_DEFINE_APPLICATION_MAIN(HttpRequestDemo)
+
+HttpRequestDemo::HttpRequestDemo(Context* context) :
+    Sample(context)
+{
+}
+
+void HttpRequestDemo::Start()
+{
+    // Execute base class startup
+    Sample::Start();
+
+    // Create the user interface
+    CreateUI();
+
+    // Subscribe to basic events such as update
+    SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
+}
+
+void HttpRequestDemo::CreateUI()
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+    // Construct new Text object
+    text_ = new Text(context_);
+
+    // Set font and text color
+    text_->SetFont(cache->GetResource<Font>("Fonts/Anonymous Pro.ttf"), 15);
+    text_->SetColor(Color(1.0f, 1.0f, 0.0f));
+
+    // Align Text center-screen
+    text_->SetHorizontalAlignment(HA_CENTER);
+    text_->SetVerticalAlignment(VA_CENTER);
+
+    // Add Text instance to the UI root element
+    GetSubsystem<UI>()->GetRoot()->AddChild(text_);
+}
+
+void HttpRequestDemo::SubscribeToEvents()
+{
+    // Subscribe HandleUpdate() function for processing HTTP request
+    SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(HttpRequestDemo, HandleUpdate));
+}
+
+void HttpRequestDemo::HandleUpdate(StringHash eventType, VariantMap& eventData)
+{
+    Network* network = GetSubsystem<Network>();
+
+    if (httpRequest_.Null())
+        httpRequest_ = network->MakeHttpRequest("http://httpbin.org/ip");
+    else
+    {
+        // Initializing HTTP request
+        if (httpRequest_->GetState() == HTTP_INITIALIZING)
+            return;
+        // An error has occured
+        else if (httpRequest_->GetState() == HTTP_ERROR)
+        {
+            text_->SetText("An error has occured.");
+            UnsubscribeFromEvent("Update");
+        }
+        // Get message data
+        else
+        {
+            if (httpRequest_->GetAvailableSize() > 0)
+                message_ += httpRequest_->ReadLine();
+            else
+            {
+                text_->SetText("Processing...");
+
+                SharedPtr<JSONFile> json(new JSONFile(context_));
+                json->FromString(message_);
+
+                JSONValue val = json->GetRoot().Get("origin");
+
+                if (val.IsNull())
+                    text_->SetText("Invalid string.");
+                else
+                    text_->SetText("Your IP is: " + val.GetString());
+
+                UnsubscribeFromEvent("Update");
+            }
+        }
+    }
+}

+ 68 - 0
Source/Samples/43_HttpRequestDemo/HttpRequestDemo.h

@@ -0,0 +1,68 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "Sample.h"
+
+namespace Urho3D
+{
+    class HttpRequest;
+    class Text;
+}
+
+/// Http request example.
+/// This example demonstrates:
+///     - How to use Http request API
+class HttpRequestDemo : public Sample
+{
+    URHO3D_OBJECT(HttpRequestDemo, Sample);
+
+public:
+    /// Construct.
+    HttpRequestDemo(Context* context);
+
+    /// Setup after engine initialization and before running the main loop.
+    virtual void Start();
+
+protected:
+    /// Return XML patch instructions for screen joystick layout for a specific sample app, if any.
+    virtual String GetScreenJoystickPatchString() const { return
+        "<patch>"
+        "    <add sel=\"/element/element[./attribute[@name='Name' and @value='Hat0']]\">"
+        "        <attribute name=\"Is Visible\" value=\"false\" />"
+        "    </add>"
+        "</patch>";
+    }
+
+private:
+    /// Create the user interface.
+    void CreateUI();
+    /// Subscribe to application-wide logic update events.
+    void SubscribeToEvents();
+    /// Handle the logic update event.
+    void HandleUpdate(StringHash eventType, VariantMap& eventData);
+    
+    String message_;
+    SharedPtr<Text> text_;
+    SharedPtr<HttpRequest> httpRequest_;
+};

+ 2 - 2
Source/Samples/Sample.inl

@@ -247,8 +247,8 @@ void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData)
 
 
     int key = eventData[P_KEY].GetInt();
     int key = eventData[P_KEY].GetInt();
 
 
-    // Toggle console with F1 or Z
-    if (key == KEY_F1 || key == 'Z')
+    // Toggle console with F1
+    if (key == KEY_F1)
         GetSubsystem<Console>()->Toggle();
         GetSubsystem<Console>()->Toggle();
 
 
     // Toggle debug HUD with F2
     // Toggle debug HUD with F2

+ 108 - 33
Source/ThirdParty/Civetweb/LICENSE.md

@@ -5,11 +5,14 @@ This document includes several copyright licenses for different
 aspects of the software.  Not all licenses may apply depending
 aspects of the software.  Not all licenses may apply depending
 on the features chosen.
 on the features chosen.
 
 
+
 Civetweb License
 Civetweb License
 -----
 -----
 
 
 ### Included with all features.
 ### Included with all features.
 
 
+> Copyright (c) 2013-2015 The CivetWeb developers ([CREDITS.md](https://github.com/bel2125/civetweb/blob/master/CREDITS.md))
+>
 > Copyright (c) 2004-2013 Sergey Lyubka
 > Copyright (c) 2004-2013 Sergey Lyubka
 >
 >
 > Copyright (c) 2013 No Face Press, LLC (Thomas Davis)
 > Copyright (c) 2013 No Face Press, LLC (Thomas Davis)
@@ -22,10 +25,10 @@ Civetweb License
 > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 > copies of the Software, and to permit persons to whom the Software is
 > copies of the Software, and to permit persons to whom the Software is
 > furnished to do so, subject to the following conditions:
 > furnished to do so, subject to the following conditions:
-> 
+>
 > The above copyright notice and this permission notice shall be included in
 > The above copyright notice and this permission notice shall be included in
 > all copies or substantial portions of the Software.
 > all copies or substantial portions of the Software.
-> 
+>
 > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -34,6 +37,7 @@ Civetweb License
 > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 > THE SOFTWARE.
 > THE SOFTWARE.
 
 
+
 Lua License
 Lua License
 ------
 ------
 
 
@@ -41,18 +45,31 @@ Lua License
 
 
 http://www.lua.org/license.html
 http://www.lua.org/license.html
 
 
-> Copyright � 1994-2013 Lua.org, PUC-Rio.
-> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+> Copyright (C) 1994-2015 Lua.org, PUC-Rio.
+>
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), to deal
+> in the Software without restriction, including without limitation the rights
+> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+> copies of the Software, and to permit persons to whom the Software is
+> furnished to do so, subject to the following conditions:
 >
 >
-> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-> 
-> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+> The above copyright notice and this permission notice shall be included in
+> all copies or substantial portions of the Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+> THE SOFTWARE.
 
 
 
 
 SQLite3 License
 SQLite3 License
 ------
 ------
 
 
-### Included only if built with Lua support.
+### Included only if built with Lua and SQLite support.
 
 
 http://www.sqlite.org/copyright.html
 http://www.sqlite.org/copyright.html
 
 
@@ -65,34 +82,92 @@ http://www.sqlite.org/copyright.html
 >    May you find forgiveness for yourself and forgive others.
 >    May you find forgiveness for yourself and forgive others.
 >    May you share freely, never taking more than you give.
 >    May you share freely, never taking more than you give.
 
 
+
 lsqlite3 License
 lsqlite3 License
 ------
 ------
 
 
+### Included only if built with Lua and SQLite support.
+
+> Copyright (C) 2002-2013 Tiago Dionizio, Doug Currie
+> All rights reserved.
+> Author    : Tiago Dionizio <[email protected]>
+> Author    : Doug Currie <[email protected]>
+> Library   : lsqlite3 - a SQLite 3 database binding for Lua 5
+>
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), to deal
+> in the Software without restriction, including without limitation the rights
+> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+> copies of the Software, and to permit persons to whom the Software is
+> furnished to do so, subject to the following conditions:
+>
+> The above copyright notice and this permission notice shall be included in
+> all copies or substantial portions of the Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+> THE SOFTWARE.
+
+
+Lua File System License
+------
+
 ### Included only if built with Lua support.
 ### Included only if built with Lua support.
 
 
-> lsqlite3                                                              
-> Copyright (C) 2002-2007 Tiago Dionizio, Doug Currie                   
-> All rights reserved.                                                  
-> Author    : Tiago Dionizio <[email protected]>                
-> Author    : Doug Currie <[email protected]>                    
-> Library   : lsqlite3 - a SQLite 3 database binding for Lua 5          
->                                                                      
-> Permission is hereby granted, free of charge, to any person obtaining 
-> a copy of this software and associated documentation files (the       
-> "Software"), to deal in the Software without restriction, including   
-> without limitation the rights to use, copy, modify, merge, publish,   
-> distribute, sublicense, and/or sell copies of the Software, and to    
-> permit persons to whom the Software is furnished to do so, subject to 
-> the following conditions:                                             
->                                                                      
-> The above copyright notice and this permission notice shall be        
-> included in all copies or substantial portions of the Software.       
->                                                                      
-> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       
-> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    
-> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  
-> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  
-> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     
-> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                
+http://keplerproject.github.io/luafilesystem/license.html
+
+> Copyright © 2003 Kepler Project.
+>
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), to deal
+> in the Software without restriction, including without limitation the rights
+> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+> copies of the Software, and to permit persons to whom the Software is
+> furnished to do so, subject to the following conditions:
+>
+> The above copyright notice and this permission notice shall be included in
+> all copies or substantial portions of the Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+> THE SOFTWARE.
+
 
 
+LuaXML License
+------
+
+### Included only if built with Lua and LuaXML support.
+
+> LuaXML License
+>
+> LuaXml is licensed under the terms of the MIT license reproduced below,
+> the same as Lua itself. This means that LuaXml is free software and can be
+> used for both academic and commercial purposes at absolutely no cost.
+>
+> Copyright (C) 2007-2013 Gerald Franz, eludi.net
+>
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), to deal
+> in the Software without restriction, including without limitation the rights
+> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+> copies of the Software, and to permit persons to whom the Software is
+> furnished to do so, subject to the following conditions:
+>
+> The above copyright notice and this permission notice shall be included in
+> all copies or substantial portions of the Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+> THE SOFTWARE.

+ 62 - 40
Source/ThirdParty/Civetweb/README.md

@@ -1,10 +1,18 @@
-![Civetweb](https://raw.github.com/sunsetbrew/civetweb/master/resources/civetweb_64x64.png "Civetweb") Civetweb
+![Civetweb](https://raw.github.com/bel2125/civetweb/master/resources/civetweb_64x64.png "Civetweb") Civetweb
 =======
 =======
 
 
+There is a new home!!!
+-----------------
+https://github.com/bel2125/civetweb
+
+Bel has been taking the lead on Civetweb, so the official repository is being
+moved under his control for ease of maintenance.
+
 Project Mission
 Project Mission
 -----------------
 -----------------
 
 
-Project mission is to provide easy to use, powerful, C/C++ embeddable web server with optional CGI, SSL and Lua support.
+Project mission is to provide easy to use, powerful, C/C++ embeddable web
+server with optional CGI, SSL and Lua support.
 Civetweb has a MIT license so you can innovate without restrictions.
 Civetweb has a MIT license so you can innovate without restrictions.
 
 
 Where to find the official version?
 Where to find the official version?
@@ -14,61 +22,79 @@ End users can download Civetweb at SourceForge
 https://sourceforge.net/projects/civetweb/
 https://sourceforge.net/projects/civetweb/
 
 
 Developers can contribute to CivetWeb via GitHub
 Developers can contribute to CivetWeb via GitHub
-https://github.com/sunsetbrew/civetweb
+https://github.com/bel2125/civetweb
 
 
 Trouble tickets should be filed on GitHub
 Trouble tickets should be filed on GitHub
-https://github.com/sunsetbrew/civetweb/issues
+https://github.com/bel2125/civetweb/issues
 
 
-Discussion group is at Google Groups
+Discussion/support group and announcements are at Google Groups
 https://groups.google.com/d/forum/civetweb
 https://groups.google.com/d/forum/civetweb
 
 
 Quick start documentation
 Quick start documentation
 --------------------------
 --------------------------
 
 
-- [docs/Installing.md](https://github.com/sunsetbrew/civetweb/blob/master/docs/Installing.md) - Install Guide
-- [docs/UserManual.md](https://github.com/sunsetbrew/civetweb/blob/master/docs/UserManual.md) - End User Guide
-- [docs/Building.md](https://github.com/sunsetbrew/civetweb/blob/master/docs/Building.md) - Buildiing the Server Quick Start
-- [docs/Embedding.md](https://github.com/sunsetbrew/civetweb/blob/master/docs/Embedding.md) - Embedding Quick Start
-- [RELEASE_NOTES.md](https://github.com/sunsetbrew/civetweb/blob/master/RELEASE_NOTES.md) - Release Notes
-- [LICENSE.md](https://github.com/sunsetbrew/civetweb/blob/master/LICENSE.md) - Copyright License
+- [docs/Installing.md](https://github.com/bel2125/civetweb/blob/master/docs/Installing.md) - Install Guide
+- [docs/UserManual.md](https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md) - End User Guide
+- [docs/Building.md](https://github.com/bel2125/civetweb/blob/master/docs/Building.md) - Buildiing the Server Quick Start
+- [docs/Embedding.md](https://github.com/bel2125/civetweb/blob/master/docs/Embedding.md) - Embedding Quick Start
+- [RELEASE_NOTES.md](https://github.com/bel2125/civetweb/blob/master/RELEASE_NOTES.md) - Release Notes
+- [LICENSE.md](https://github.com/bel2125/civetweb/blob/master/LICENSE.md) - Copyright License
 
 
 Overview
 Overview
 --------
 --------
 
 
 Civetweb keeps the balance between functionality and
 Civetweb keeps the balance between functionality and
-simplicity by carefully selected list of features:
+simplicity by a carefully selected list of features:
 
 
 - Liberal, commercial-friendly, permissive,
 - Liberal, commercial-friendly, permissive,
   [MIT license](http://en.wikipedia.org/wiki/MIT_License)
   [MIT license](http://en.wikipedia.org/wiki/MIT_License)
-- Free from copy-left licenses, like GPL, because you should innovate without restrictions.
-- Based on [Mongoose](https://code.google.com/p/mongoose/)
-- Works on Windows, Mac, UNIX, iPhone, Android, Buildroot, and many other platforms
-- Scripting and database support (Lua Server Pages + Sqlite
-  which provides ready to go, powerful web development platform in
-  one single-click executable with **no dependencies**: forget LAMP!
-- Support for CGI, SSL, SSI, Digest (MD5) authorization, Websocket, WEbDAV
-- Resumed download, URL rewrite, file blacklist, IP-based ACL, Windows service
-- Download speed limit based on client subnet or URI pattern
-- Simple and clean embedding API,
-  The source is in single file
-  to make things easy. Embedding examples included.
-- HTTP client capable of sending arbitrary HTTP/HTTPS requests
-
-
-### Other optionally included software
+- Free from copy-left licenses, like GPL, because you should innovate without
+  restrictions.
+- Forked from [Mongoose](https://code.google.com/p/mongoose/) in 2013, before
+  it changed the licence from MIT to commercial + GPL. A lot of enchancements
+  have been added since that time, see
+  [RELEASE_NOTES.md](https://github.com/bel2125/civetweb/blob/master/RELEASE_NOTES.md).
+- Works on Windows, Mac, Linux, UNIX, iPhone, Android, Buildroot, and many
+  other platforms.
+- Scripting and database support (Lua scipts, Lua Server Pages, CGI + SQLite
+  database).
+  This provides a ready to go, powerful web development platform in a one
+  single-click executable with **no dependencies**.
+- Support for CGI, HTTPS/SSL, SSI, HTTP digest (MD5) authorization, Websocket,
+  WEbDAV.
+- Resumed download, URL rewrite, file blacklist, IP-based ACL, Windows service.
+- Download speed limit based on client subnet or URI pattern.
+- Simple and clean embedding API.
+- The source is in single file to make things easy.
+- Embedding examples included.
+- HTTP client capable of sending arbitrary HTTP/HTTPS requests.
+
+
+### Optionally included software
 
 
 <a href="http://lua.org">
 <a href="http://lua.org">
-![Lua](https://raw.github.com/sunsetbrew/civetweb/master/resources/lua-logo.jpg "Lua Logo")
+![Lua](https://raw.github.com/bel2125/civetweb/master/resources/lua-logo.jpg "Lua Logo")
 </a>
 </a>
 <a href="http://sqlite.org">
 <a href="http://sqlite.org">
-![Sqlite3](https://raw.github.com/sunsetbrew/civetweb/master/resources/sqlite3-logo.jpg "Sqlite3 Logo")
+![Sqlite3](https://raw.github.com/bel2125/civetweb/master/resources/sqlite3-logo.jpg "Sqlite3 Logo")
+</a>
+<a href=http://keplerproject.github.io/luafilesystem/">
+![LuaFileSystem](https://raw.github.com/bel2125/civetweb/master/resources/luafilesystem-logo.jpg "LuaFileSystem Logo")
+</a>
+<a href=http://lua.sqlite.org/index.cgi/index">
+![LuaSQLite3](https://raw.github.com/bel2125/civetweb/master/resources/luasqlite-logo.jpg "LuaSQLite3 Logo")
+</a>
+<a href=http://viremo.eludi.net/LuaXML/index.html">
+![LuaXML](https://raw.github.com/bel2125/civetweb/master/resources/luaxml-logo.jpg "LuaXML Logo")
 </a>
 </a>
 
 
 Support
 Support
 -------
 -------
 
 
-The original Mongoose project is recommended if support is needed.  However,
-this is very easy to install and use. 
+This project is very easy to install and use. Please read the [documentation](https://github.com/bel2125/civetweb/blob/master/docs/)
+and have a look at the [examples] (https://github.com/bel2125/civetweb/blob/master/examples/).
+More information may be found on the [mailing list](https://groups.google.com/d/forum/civetweb).
+
 
 
 Contributions
 Contributions
 ---------------
 ---------------
@@ -79,18 +105,14 @@ DO NOT APPLY fixes copied from Mongoose to this project to prevent GPL tainting.
 
 
 ### Author
 ### Author
 
 
-The original Author was Sergey Lyubka.  He still controls the original
-Mongoose project.  However, he has changed or said he would 
+Civetweb is based on the Mongoose project - the original Author was Sergey Lyubka.  He still
+controls the original Mongoose project.  However, he has changed or said he would
 change licenses after writing and distributing the original code this
 change licenses after writing and distributing the original code this
 project is based on.
 project is based on.
 
 
 Using this project ensures the MIT licenses terms are applied and
 Using this project ensures the MIT licenses terms are applied and
 GPL cannot be imposed on any of this code as long as it is sourced from
 GPL cannot be imposed on any of this code as long as it is sourced from
-here.
+here. This code will remain free with the MIT license protection.
 
 
-For the latest and greatest code and features, please use the Mongoose
-code from Sergey Lyubka.  However, doing so will require adherence to
-the new licenses.
+A list of authors can be found in [CREDITS.md](https://github.com/bel2125/civetweb/blob/master/CREDITS.md)
 
 
-This project ensures that GPL license cannot be applied to this code.
-This code will remain free with the MIT license protection.

+ 114 - 10
Source/ThirdParty/Civetweb/RELEASE_NOTES.md

@@ -1,21 +1,125 @@
-Release Notes v1.5 (UNDER DEVELOPMENT)
+Release Notes v1.7
 ===
 ===
-### Objectives: *TBD*
-In planning.
+### Objectives: *Examples, documentation, additional API functions, some functions rewritten, bug fixes and updates*
 
 
 Changes
 Changes
 -------
 -------
 
 
+- Format source with clang_format
+- Use function 'sendfile' for Linux
+- Fix for CRAMFS in Linux
+- Fix for file modification times in Windows
+- Use SO_EXCLUSIVEADDRUSE instead of SO_REUSEADDR for Windows
+- Rewrite push/pull functions
+- Allow to use Lua as shared objects (WITH_LUA_SHARED)
+- Fixes for many warnings
+- URI specific callbacks and different timeouts for websockets
+- Add chunked transfer support
+- Update LuaFileSystem
+- Update Lua to 5.2.4
+- Fix build for MinGW-x64, TDM-GCC and clang
+- Update SQLite to 3.8.10.2
+- Fix CGI variables SCRIPT_NAME and PATH_TRANSLATED
+- Set TCP_USER_TIMEOUT to deal faster with broken connections
+- Add a Lua form handling example
+- Return more differentiated HTTP error codes
+- Add log_access callback
+- Rewrite and comment request handling function
+- Specify in detail and document return values of callback functions
+- Set names for all threads (unless NO_THREAD_NAME is defined)
+- New API functions for TCP/HTTP clients
+- Fix upload of huge files
+- Allow multiple SSL instances within one application
+- Improve API and user documentation
+- Allow to choose between static and dynamic Lua library
+- Improve unit test
+- Use temporary file name for partially uploaded files
+- Additional API functions exported to C++
+- Add a websocket client example
+- Add a websocket client API
+- Update websocket example
+- Make content length available in request_info
+- New API functions: access context, callback for create/delete, access user data
+- Upgraded Lua from 5.2.2 to 5.2.3 and finally 5.2.4
+- Integrate LuaXML (for testing purposes)
+- Fix compiler warnings
+- Updated version number
+
+Release Notes v1.6
+===
+### Objectives: *Enhance Lua support, configuration dialog for windows, new examples, bug fixes and updates*
+
+Changes
+-------
+
+- Add examples of Lua pages, scripts and websockets to the test directory (bel)
+- Add dialog to change htpasswd files for the Windows standalone server (bel)
+- Fix compiler warnings and warnings from static code analysis (Danny Al-Gaaf, jmc-, Thomas, bel, ...)
+- Add new unit tests (bel)
+- Support includes in htpasswd files (bel)
+- Add a basic option check for the standalone executable (bel)
+- Support user defined error pages (bel)
+- Method to get POST request parameters via C++ interface (bel)
+- Re-Add unit tests for Linux and Windows (jmc-, bel)
+- Allow to specify title and tray icon for the Windows standalone server (bel)
+- Fix minor memory leaks (bel)
+- Redirect all memory allocation/deallocation through mg functions which may be overwritten (bel)
+- Support Cross-Origin Resource Sharing (CORS) for static files and scripts (bel)
+- Win32: Replace dll.def file by export macros in civetweb.h (CSTAJ)
+- Base64 encode and decode functions for Lua (bel)
+- Support pre-loaded files for the Lua environment (bel)
+- Server should check the nonce for http digest access authentication (bel)
+- Hide read-only flag in file dialogs opened by the Edit Settings dialog for the Windows executable (bel)
+- Add all functions to dll.def, that are in the header (bel)
+- Added Lua extensions: send_file, get_var, get_mime_type, get_cookie, url_decode, url_encode (bel)
+- mg_set_request_handler() mod to use pattern (bel, Patch from Toni Wilk)
+- Solved, tested and documented SSL support for Windows (bel)
+- Fixed: select for Linux needs the nfds parameter set correctly (bel)
+- Add methods for returning the ports civetweb is listening on (keithel)
+- Fixes for Lua Server Pages, as described within the google groups thread. (bel)
+- Added support for plain Lua Scripts, and an example script. (bel)
+- A completely new, and more illustrative websocket example for C. (bel)
+- Websocket for Lua (bel)
+- An optional websocket_root directory, including URL rewriting (bel)
+- Update of SQLite3 to 3.8.1. (bel)
+- Add "date" header field to replies, according to the requirements of RFC 2616 (the HTTP standard), Section 14.18 (bel)
+- Fix websocket long pull (celeron55)
+- Updated API documentation (Alex Kozlov)
+- Fixed Posix locking functions for Windows (bel2125)
+- Updated version number
+
+Release Notes v1.5
+===
+### Objectives: *Bug fixes and updates, repository restoration*
+
+Changes
+-------
+
+- Corrected bad mask flag/opcode passing to websocket callback (William Greathouse)
+- Moved CEVITWEB_VERSION define into civetweb.h
+- Added new simple zip deployment build for Windows.
+- Removed windows install package build.
+- Fixes page violation in mod_lua.inl (apkbox)
+- Use C style comments to enable compiling most of civetweb with -ansi. (F-Secure Corporation)
+- Allow directories with non ASCII characters in Windows in UTF-8 encoded (bel2125)
+- Added Lua File System support (bel2125)
+- Added mongoose history back in repository thanks to (Paul Sokolovsky)
+- Fixed keep alive (bel2125)
+- Updated of MIME types (bel2125)
+- Updated lsqlite (bel2125)
+- Fixed master thread priority (bel2125)
+- Fixed IPV6 defines under Windowe (grenclave)
+- Fixed potential dead lock in connection_close() (Morgan McGuire)
 - Added WebSocket example using asynchronous server messages (William Greathouse)
 - Added WebSocket example using asynchronous server messages (William Greathouse)
 - Fixed the getcwd() warning (William Greathouse)
 - Fixed the getcwd() warning (William Greathouse)
 - Implemented the connection_close() callback (William Greathouse)
 - Implemented the connection_close() callback (William Greathouse)
-- Replaced Windows AdvancedInstaller with Inno Setup to solve install problems.
 - Fixed support URL's in civetweb.c (Daniel Oaks)
 - Fixed support URL's in civetweb.c (Daniel Oaks)
 - Allow port number to be zero to use a random free port (F-Secure Corporation)
 - Allow port number to be zero to use a random free port (F-Secure Corporation)
 - Wait for threads to finish when stopping for a clean shutdown (F-Secure Corporation)
 - Wait for threads to finish when stopping for a clean shutdown (F-Secure Corporation)
 - More static analysis fixes against Coverity tool (F-Secure Corporation)
 - More static analysis fixes against Coverity tool (F-Secure Corporation)
 - Travis automated build testing support added (Daniel Oaks)
 - Travis automated build testing support added (Daniel Oaks)
 - Updated version numbers.
 - Updated version numbers.
+- Added contributor credits file.
 
 
 Release Notes v1.4
 Release Notes v1.4
 ===
 ===
@@ -42,7 +146,7 @@ Changes
 - Conformed source files to UNIX line endings for consistency.
 - Conformed source files to UNIX line endings for consistency.
 - Unified the coding style to improve reability.
 - Unified the coding style to improve reability.
 
 
-Release Notes v1.3 
+Release Notes v1.3
 ===
 ===
 ### Objectives: *Buildroot Integration*
 ### Objectives: *Buildroot Integration*
 
 
@@ -54,7 +158,7 @@ Changes
 - Updated documentation
 - Updated documentation
 - Updated Buildroot config example
 - Updated Buildroot config example
 
 
-Release Notes v1.2 
+Release Notes v1.2
 ===
 ===
 ### Objectives: *Installation Improvements, buildroot, cross compile support*
 ### Objectives: *Installation Improvements, buildroot, cross compile support*
 The objective of this release is to make installation seamless.
 The objective of this release is to make installation seamless.
@@ -78,7 +182,7 @@ Known Issues
 
 
 - The prebuilt Window's version requires [Visual C++ Redistributable for Visual Studio 2012](http://www.microsoft.com/en-us/download/details.aspx?id=30679)
 - The prebuilt Window's version requires [Visual C++ Redistributable for Visual Studio 2012](http://www.microsoft.com/en-us/download/details.aspx?id=30679)
 
 
-Release Notes v1.1 
+Release Notes v1.1
 ===
 ===
 ### Objectives: *Build, Documentation, License Improvements*
 ### Objectives: *Build, Documentation, License Improvements*
 The objective of this release is to establish a maintable code base, ensure MIT license rights and improve usability and documentation.
 The objective of this release is to establish a maintable code base, ensure MIT license rights and improve usability and documentation.
@@ -107,7 +211,7 @@ Changes
      + Removed yaSSL from the OSX build, not needed.
      + Removed yaSSL from the OSX build, not needed.
 - Added new Visual Studio projects for Windows builds.
 - Added new Visual Studio projects for Windows builds.
      + Removed Windows support from Makefiles
      + Removed Windows support from Makefiles
-     + Provided additional, examples with Lua, and another with yaSSL. 
+     + Provided additional, examples with Lua, and another with yaSSL.
 - Changed Zombie Reaping policy to not ignore SIGCHLD.
 - Changed Zombie Reaping policy to not ignore SIGCHLD.
      + The previous method caused trouble in applciations that spawn children.
      + The previous method caused trouble in applciations that spawn children.
 
 
@@ -117,7 +221,7 @@ Known Issues
 - Build support for VS6 and some other has been deprecated.
 - Build support for VS6 and some other has been deprecated.
     + This does not impact embedded programs, just the stand-alone build.
     + This does not impact embedded programs, just the stand-alone build.
     + The old Makefile was renamed to Makefile.deprecated.
     + The old Makefile was renamed to Makefile.deprecated.
-    + This is partcially do to lack fo testing. 
+    + This is partcially do to lack fo testing.
     + Need to find out what is actually in demand.
     + Need to find out what is actually in demand.
 - Build changes may impact current users.
 - Build changes may impact current users.
     + As with any change of this type, changes may impact some users.
     + As with any change of this type, changes may impact some users.
@@ -133,6 +237,6 @@ Changes
 
 
 - Renamed Mongoose to Civetweb in the code and documentation.
 - Renamed Mongoose to Civetweb in the code and documentation.
 - Replaced copyrighted images with new images
 - Replaced copyrighted images with new images
-- Created a new code respository at https://github.com/sunsetbrew/civetweb
+- Created a new code respository at https://github.com/bel2125/civetweb
 - Created a distribution site at https://sourceforge.net/projects/civetweb/
 - Created a distribution site at https://sourceforge.net/projects/civetweb/
 - Basic build testing
 - Basic build testing

+ 686 - 431
Source/ThirdParty/Civetweb/include/civetweb.h

@@ -1,283 +1,461 @@
-// Copyright (c) 2004-2012 Sergey Lyubka
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+/* Copyright (c) 2013-2015 the Civetweb developers
+ * Copyright (c) 2004-2013 Sergey Lyubka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
 
 
 #ifndef CIVETWEB_HEADER_INCLUDED
 #ifndef CIVETWEB_HEADER_INCLUDED
 #define CIVETWEB_HEADER_INCLUDED
 #define CIVETWEB_HEADER_INCLUDED
 
 
+#define CIVETWEB_VERSION "1.7"
+
+#ifndef CIVETWEB_API
+#if defined(_WIN32)
+#if defined(CIVETWEB_DLL_EXPORTS)
+#define CIVETWEB_API __declspec(dllexport)
+#elif defined(CIVETWEB_DLL_IMPORTS)
+#define CIVETWEB_API __declspec(dllimport)
+#else
+#define CIVETWEB_API
+#endif
+#elif __GNUC__ >= 4
+#define CIVETWEB_API __attribute__((visibility("default")))
+#else
+#define CIVETWEB_API
+#endif
+#endif
+
 #include <stdio.h>
 #include <stdio.h>
 #include <stddef.h>
 #include <stddef.h>
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
-#endif // __cplusplus
+#endif /* __cplusplus */
 
 
-struct mg_context;     // Handle for the HTTP service itself
-struct mg_connection;  // Handle for the individual connection
+struct mg_context;    /* Handle for the HTTP service itself */
+struct mg_connection; /* Handle for the individual connection */
 
 
-
-// This structure contains information about the HTTP request.
+/* This structure contains information about the HTTP request. */
 struct mg_request_info {
 struct mg_request_info {
-    const char *request_method; // "GET", "POST", etc
-    const char *uri;            // URL-decoded URI
-    const char *http_version;   // E.g. "1.0", "1.1"
-    const char *query_string;   // URL part after '?', not including '?', or NULL
-    const char *remote_user;    // Authenticated user, or NULL if no auth used
-    long remote_ip;             // Client's IP address
-    int remote_port;            // Client's port
-    int is_ssl;                 // 1 if SSL-ed, 0 if not
-    void *user_data;            // User data pointer passed to mg_start()
-    void *conn_data;            // Connection-specific user data
-
-    int num_headers;            // Number of HTTP headers
-    struct mg_header {
-        const char *name;         // HTTP header name
-        const char *value;        // HTTP header value
-    } http_headers[64];         // Maximum 64 headers
+	const char *request_method; /* "GET", "POST", etc */
+	const char *uri;            /* URL-decoded URI */
+	const char *http_version;   /* E.g. "1.0", "1.1" */
+	const char *query_string;   /* URL part after '?', not including '?', or
+	                               NULL */
+	const char *remote_user;    /* Authenticated user, or NULL if no auth
+	                               used */
+	char remote_addr[48];       /* Client's IP address as a string. */
+	long remote_ip; /* Client's IP address. Deprecated: use remote_addr instead
+	                   */
+
+	long long content_length; /* Length (in bytes) of the request body,
+	                             can be -1 if no length was given. */
+	int remote_port;          /* Client's port */
+	int is_ssl;               /* 1 if SSL-ed, 0 if not */
+	void *user_data;          /* User data pointer passed to mg_start() */
+	void *conn_data;          /* Connection-specific user data */
+
+	int num_headers; /* Number of HTTP headers */
+	struct mg_header {
+		const char *name;  /* HTTP header name */
+		const char *value; /* HTTP header value */
+	} http_headers[64];    /* Maximum 64 headers */
 };
 };
 
 
-
-// This structure needs to be passed to mg_start(), to let civetweb know
-// which callbacks to invoke. For detailed description, see
-// https://github.com/sunsetbrew/civetweb/blob/master/docs/UserManual.md
+/* This structure needs to be passed to mg_start(), to let civetweb know
+   which callbacks to invoke. For a detailed description, see
+   https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md */
 struct mg_callbacks {
 struct mg_callbacks {
-    // Called when civetweb has received new HTTP request.
-    // If callback returns non-zero,
-    // callback must process the request by sending valid HTTP headers and body,
-    // and civetweb will not do any further processing.
-    // If callback returns 0, civetweb processes the request itself. In this case,
-    // callback must not send any data to the client.
-    int  (*begin_request)(struct mg_connection *);
-
-    // Called when civetweb has finished processing request.
-    void (*end_request)(const struct mg_connection *, int reply_status_code);
-
-    // Called when civetweb is about to log a message. If callback returns
-    // non-zero, civetweb does not log anything.
-    int  (*log_message)(const struct mg_connection *, const char *message);
-
-    // Called when civetweb initializes SSL library.
-    int  (*init_ssl)(void *ssl_context, void *user_data);
-
-    // Called when websocket request is received, before websocket handshake.
-    // If callback returns 0, civetweb proceeds with handshake, otherwise
-    // cinnection is closed immediately.
-    int (*websocket_connect)(const struct mg_connection *);
-
-    // Called when websocket handshake is successfully completed, and
-    // connection is ready for data exchange.
-    void (*websocket_ready)(struct mg_connection *);
-
-    // Called when data frame has been received from the client.
-    // Parameters:
-    //    bits: first byte of the websocket frame, see websocket RFC at
-    //          http://tools.ietf.org/html/rfc6455, section 5.2
-    //    data, data_len: payload, with mask (if any) already applied.
-    // Return value:
-    //    non-0: keep this websocket connection opened.
-    //    0:     close this websocket connection.
-    int  (*websocket_data)(struct mg_connection *, int bits,
-                           char *data, size_t data_len);
-
-    // Called when civetweb is closing a connection.  The per-context mutex is locked when this
-    // is invoked.  This is primarily useful for noting when a websocket is closing and removing it
-    // from any application-maintained list of clients.
-    void (*connection_close)(struct mg_connection *);
-
-    // Called when civetweb tries to open a file. Used to intercept file open
-    // calls, and serve file data from memory instead.
-    // Parameters:
-    //    path:     Full path to the file to open.
-    //    data_len: Placeholder for the file size, if file is served from memory.
-    // Return value:
-    //    NULL: do not serve file from memory, proceed with normal file open.
-    //    non-NULL: pointer to the file contents in memory. data_len must be
-    //              initilized with the size of the memory block.
-    const char * (*open_file)(const struct mg_connection *,
-                              const char *path, size_t *data_len);
-
-    // Called when civetweb is about to serve Lua server page (.lp file), if
-    // Lua support is enabled.
-    // Parameters:
-    //   lua_context: "lua_State *" pointer.
-    void (*init_lua)(struct mg_connection *, void *lua_context);
-
-    // Called when civetweb has uploaded a file to a temporary directory as a
-    // result of mg_upload() call.
-    // Parameters:
-    //    file_file: full path name to the uploaded file.
-    void (*upload)(struct mg_connection *, const char *file_name);
-
-    // Called when civetweb is about to send HTTP error to the client.
-    // Implementing this callback allows to create custom error pages.
-    // Parameters:
-    //   status: HTTP error status code.
-    int  (*http_error)(struct mg_connection *, int status);
+	/* Called when civetweb has received new HTTP request.
+	   If the callback returns one, it must process the request
+	   by sending valid HTTP headers and a body. Civetweb will not do
+	   any further processing. Otherwise it must return zero.
+	   Note that since V1.7 the "begin_request" function is called
+	   before an authorization check. If an authorization check is
+	   required, use a request_handler instead.
+	   Return value:
+	     0: civetweb will process the request itself. In this case,
+	        the callback must not send any data to the client.
+	     1: callback already processed the request. Civetweb will
+	        not send any data after the callback returned. */
+	int (*begin_request)(struct mg_connection *);
+
+	/* Called when civetweb has finished processing request. */
+	void (*end_request)(const struct mg_connection *, int reply_status_code);
+
+	/* Called when civetweb is about to log a message. If callback returns
+	   non-zero, civetweb does not log anything. */
+	int (*log_message)(const struct mg_connection *, const char *message);
+
+	/* Called when civetweb is about to log access. If callback returns
+	   non-zero, civetweb does not log anything. */
+	int (*log_access)(const struct mg_connection *, const char *message);
+
+	/* Called when civetweb initializes SSL library.
+	   Parameters:
+	     user_data: parameter user_data passed when starting the server.
+	   Return value:
+	     0: civetweb will set up the SSL certificate.
+	     1: civetweb assumes the callback already set up the certificate.
+	    -1: initializing ssl fails. */
+	int (*init_ssl)(void *ssl_context, void *user_data);
+
+	/* Called when websocket request is received, before websocket handshake.
+	   Return value:
+	     0: civetweb proceeds with websocket handshake.
+	     1: connection is closed immediately.
+	   This callback is deprecated, use mg_set_websocket_handler instead. */
+	int (*websocket_connect)(const struct mg_connection *);
+
+	/* Called when websocket handshake is successfully completed, and
+	   connection is ready for data exchange.
+	   This callback is deprecated, use mg_set_websocket_handler instead. */
+	void (*websocket_ready)(struct mg_connection *);
+
+	/* Called when data frame has been received from the client.
+	   Parameters:
+	     bits: first byte of the websocket frame, see websocket RFC at
+	           http://tools.ietf.org/html/rfc6455, section 5.2
+	     data, data_len: payload, with mask (if any) already applied.
+	   Return value:
+	     1: keep this websocket connection open.
+	     0: close this websocket connection.
+	   This callback is deprecated, use mg_set_websocket_handler instead. */
+	int (*websocket_data)(struct mg_connection *,
+	                      int bits,
+	                      char *data,
+	                      size_t data_len);
+
+	/* Called when civetweb is closing a connection.  The per-context mutex is
+	   locked when this is invoked.  This is primarily useful for noting when
+	   a websocket is closing and removing it from any application-maintained
+	   list of clients.
+	   Using this callback for websocket connections is deprecated, use
+	   mg_set_websocket_handler instead. */
+	void (*connection_close)(const struct mg_connection *);
+
+	/* Called when civetweb tries to open a file. Used to intercept file open
+	   calls, and serve file data from memory instead.
+	   Parameters:
+	      path:     Full path to the file to open.
+	      data_len: Placeholder for the file size, if file is served from
+	                memory.
+	   Return value:
+	     NULL: do not serve file from memory, proceed with normal file open.
+	     non-NULL: pointer to the file contents in memory. data_len must be
+	       initilized with the size of the memory block. */
+	const char *(*open_file)(const struct mg_connection *,
+	                         const char *path,
+	                         size_t *data_len);
+
+	/* Called when civetweb is about to serve Lua server page, if
+	   Lua support is enabled.
+	   Parameters:
+	     lua_context: "lua_State *" pointer. */
+	void (*init_lua)(const struct mg_connection *, void *lua_context);
+
+	/* Called when civetweb has uploaded a file to a temporary directory as a
+	   result of mg_upload() call.
+	   Parameters:
+	     file_name: full path name to the uploaded file. */
+	void (*upload)(struct mg_connection *, const char *file_name);
+
+	/* Called when civetweb is about to send HTTP error to the client.
+	   Implementing this callback allows to create custom error pages.
+	   Parameters:
+	     status: HTTP error status code.
+	   Return value:
+	     1: run civetweb error handler.
+	     0: callback already handled the error. */
+	int (*http_error)(struct mg_connection *, int status);
+
+	/* Called after civetweb context has been created, before requests
+	   are processed.
+	   Parameters:
+	     ctx: context handle */
+	void (*init_context)(const struct mg_context *ctx);
+
+	/* Called when civetweb context is deleted.
+	   Parameters:
+	     ctx: context handle */
+	void (*exit_context)(const struct mg_context *ctx);
+};
+
+/* Start web server.
+
+   Parameters:
+     callbacks: mg_callbacks structure with user-defined callbacks.
+     options: NULL terminated list of option_name, option_value pairs that
+              specify Civetweb configuration parameters.
+
+   Side-effects: on UNIX, ignores SIGCHLD and SIGPIPE signals. If custom
+      processing is required for these, signal handlers must be set up
+      after calling mg_start().
+
+
+   Example:
+     const char *options[] = {
+       "document_root", "/var/www",
+       "listening_ports", "80,443s",
+       NULL
+     };
+     struct mg_context *ctx = mg_start(&my_func, NULL, options);
+
+   Refer to https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md
+   for the list of valid option and their possible values.
+
+   Return:
+     web server context, or NULL on error. */
+CIVETWEB_API struct mg_context *mg_start(const struct mg_callbacks *callbacks,
+                                         void *user_data,
+                                         const char **configuration_options);
+
+/* Stop the web server.
+
+   Must be called last, when an application wants to stop the web server and
+   release all associated resources. This function blocks until all Civetweb
+   threads are stopped. Context pointer becomes invalid. */
+CIVETWEB_API void mg_stop(struct mg_context *);
+
+/* mg_request_handler
+
+   Called when a new request comes in.  This callback is URI based
+   and configured with mg_set_request_handler().
+
+   Parameters:
+      conn: current connection information.
+      cbdata: the callback data configured with mg_set_request_handler().
+   Returns:
+      0: the handler could not handle the request, so fall through.
+      1: the handler processed the request. */
+typedef int (*mg_request_handler)(struct mg_connection *conn, void *cbdata);
+
+/* mg_set_request_handler
+
+   Sets or removes a URI mapping for a request handler.
+   This function uses mg_lock_context internally.
+
+   URI's are ordered and prefixed URI's are supported. For example,
+   consider two URIs: /a/b and /a
+           /a   matches /a
+           /a/b matches /a/b
+           /a/c matches /a
+
+   Parameters:
+      ctx: server context
+      uri: the URI (exact or pattern) for the handler
+      handler: the callback handler to use when the URI is requested.
+               If NULL, an already registered handler for this URI will be
+   removed.
+               The URI used to remove a handler must match exactly the one used
+   to
+               register it (not only a pattern match).
+      cbdata: the callback data to give to the handler when it is called. */
+CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx,
+                                         const char *uri,
+                                         mg_request_handler handler,
+                                         void *cbdata);
+
+/* Callback types for websocket handlers in C/C++.
+
+   mg_websocket_connect_handler
+       Is called when the client intends to establish a websocket connection,
+       before websocket handshake.
+       Return value:
+         0: civetweb proceeds with websocket handshake.
+         1: connection is closed immediately.
+
+   mg_websocket_ready_handler
+       Is called when websocket handshake is successfully completed, and
+       connection is ready for data exchange.
+
+   mg_websocket_data_handler
+       Is called when a data frame has been received from the client.
+       Parameters:
+         bits: first byte of the websocket frame, see websocket RFC at
+               http://tools.ietf.org/html/rfc6455, section 5.2
+         data, data_len: payload, with mask (if any) already applied.
+       Return value:
+         1: keep this websocket connection open.
+         0: close this websocket connection.
+
+   mg_connection_close_handler
+       Is called, when the connection is closed.*/
+typedef int (*mg_websocket_connect_handler)(const struct mg_connection *,
+                                            void *);
+typedef void (*mg_websocket_ready_handler)(struct mg_connection *, void *);
+typedef int (*mg_websocket_data_handler)(
+    struct mg_connection *, int, char *, size_t, void *);
+typedef void (*mg_websocket_close_handler)(const struct mg_connection *,
+                                           void *);
+
+/* mg_set_websocket_handler
+
+   Set or remove handler functions for websocket connections.
+   This function works similar to mg_set_request_handler - see there. */
+CIVETWEB_API void
+mg_set_websocket_handler(struct mg_context *ctx,
+                         const char *uri,
+                         mg_websocket_connect_handler connect_handler,
+                         mg_websocket_ready_handler ready_handler,
+                         mg_websocket_data_handler data_handler,
+                         mg_websocket_close_handler close_handler,
+                         void *cbdata);
+
+/* Get the value of particular configuration parameter.
+   The value returned is read-only. Civetweb does not allow changing
+   configuration at run time.
+   If given parameter name is not valid, NULL is returned. For valid
+   names, return value is guaranteed to be non-NULL. If parameter is not
+   set, zero-length string is returned. */
+CIVETWEB_API const char *mg_get_option(const struct mg_context *ctx,
+                                       const char *name);
+
+/* Get context from connection. */
+CIVETWEB_API struct mg_context *
+mg_get_context(const struct mg_connection *conn);
+
+/* Get user data passed to mg_start from context. */
+CIVETWEB_API void *mg_get_user_data(const struct mg_context *ctx);
+
+/* Set user data for the current connection. */
+CIVETWEB_API void mg_set_user_connection_data(const struct mg_connection *conn,
+                                              void *data);
+
+/* Get user data set for the current connection. */
+CIVETWEB_API void *
+mg_get_user_connection_data(const struct mg_connection *conn);
+
+#if defined(MG_LEGACY_INTERFACE)
+/* Return array of strings that represent valid configuration options.
+   For each option, option name and default value is returned, i.e. the
+   number of entries in the array equals to number_of_options x 2.
+   Array is NULL terminated. */
+/* Deprecated: Use mg_get_valid_options instead. */
+CIVETWEB_API const char **mg_get_valid_option_names(void);
+#endif
+
+struct mg_option {
+	const char *name;
+	int type;
+	const char *default_value;
 };
 };
 
 
-// Start web server.
-//
-// Parameters:
-//   callbacks: mg_callbacks structure with user-defined callbacks.
-//   options: NULL terminated list of option_name, option_value pairs that
-//            specify Civetweb configuration parameters.
-//
-// Side-effects: on UNIX, ignores SIGCHLD and SIGPIPE signals. If custom
-//    processing is required for these, signal handlers must be set up
-//    after calling mg_start().
-//
-//
-// Example:
-//   const char *options[] = {
-//     "document_root", "/var/www",
-//     "listening_ports", "80,443s",
-//     NULL
-//   };
-//   struct mg_context *ctx = mg_start(&my_func, NULL, options);
-//
-// Refer to https://github.com/sunsetbrew/civetweb/blob/master/docs/UserManual.md
-// for the list of valid option and their possible values.
-//
-// Return:
-//   web server context, or NULL on error.
-struct mg_context *mg_start(const struct mg_callbacks *callbacks,
-                            void *user_data,
-                            const char **configuration_options);
-
-
-// Stop the web server.
-//
-// Must be called last, when an application wants to stop the web server and
-// release all associated resources. This function blocks until all Civetweb
-// threads are stopped. Context pointer becomes invalid.
-void mg_stop(struct mg_context *);
-
-// mg_request_handler
-//
-// Called when a new request comes in.  This callback is URI based
-// and configured with mg_set_request_handler().
-//
-// Parameters:
-//    conn: current connection information.
-//    cbdata: the callback data configured with mg_set_request_handler().
-// Returns:
-//    0: the handler could not handle the request, so fall through.
-//    1: the handler processed the request.
-typedef int (* mg_request_handler)(struct mg_connection *conn, void *cbdata);
-
-// mg_set_request_handler
-//
-// Sets or removes a URI mapping for a request handler.
-//
-// URI's are ordered and prefixed URI's are supported. For example,
-// consider two URIs: /a/b and /a
-//         /a   matches /a
-//         /a/b matches /a/b
-//         /a/c matches /a
-//
-// Parameters:
-//    ctx: server context
-//    uri: the URI to configure
-//    handler: the callback handler to use when the URI is requested.
-//             If NULL, the URI will be removed.
-//    cbdata: the callback data to give to the handler when it s requested.
-void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata);
-
-
-// Get the value of particular configuration parameter.
-// The value returned is read-only. Civetweb does not allow changing
-// configuration at run time.
-// If given parameter name is not valid, NULL is returned. For valid
-// names, return value is guaranteed to be non-NULL. If parameter is not
-// set, zero-length string is returned.
-const char *mg_get_option(const struct mg_context *ctx, const char *name);
-
-
-// Return array of strings that represent valid configuration options.
-// For each option, option name and default value is returned, i.e. the
-// number of entries in the array equals to number_of_options x 2.
-// Array is NULL terminated.
-const char **mg_get_valid_option_names(void);
-
-
-// Add, edit or delete the entry in the passwords file.
-//
-// This function allows an application to manipulate .htpasswd files on the
-// fly by adding, deleting and changing user records. This is one of the
-// several ways of implementing authentication on the server side. For another,
-// cookie-based way please refer to the examples/chat in the source tree.
-//
-// If password is not NULL, entry is added (or modified if already exists).
-// If password is NULL, entry is deleted.
-//
-// Return:
-//   1 on success, 0 on error.
-int mg_modify_passwords_file(const char *passwords_file_name,
-                             const char *domain,
-                             const char *user,
-                             const char *password);
-
-
-// Return information associated with the request.
-struct mg_request_info *mg_get_request_info(struct mg_connection *);
-
-
-// Send data to the client.
-// Return:
-//  0   when the connection has been closed
-//  -1  on error
-//  >0  number of bytes written on success
-int mg_write(struct mg_connection *, const void *buf, size_t len);
-
-
-// Send data to a websocket client wrapped in a websocket frame.  Uses mg_lock to ensure
-// that the transmission is not interrupted, i.e., when the application is proactively
-// communicating and responding to a request simultaneously.
-//
-// Send data to a websocket client wrapped in a websocket frame.
-// This function is available when civetweb is compiled with -DUSE_WEBSOCKET
-//
-// Return:
-//  0   when the connection has been closed
-//  -1  on error
-//  >0  number of bytes written on success
-int mg_websocket_write(struct mg_connection* conn, int opcode,
-                       const char *data, size_t data_len);
-
-// Blocks until unique access is obtained to this connection. Intended for use with websockets only.
-// Invoke this before mg_write or mg_printf when communicating with a websocket if your code has
-// server-initiated communication as well as communication in direct response to a message.
-void mg_lock(struct mg_connection* conn);
-void mg_unlock(struct mg_connection* conn);
-
-// Opcodes, from http://tools.ietf.org/html/rfc6455
 enum {
 enum {
-    WEBSOCKET_OPCODE_CONTINUATION = 0x0,
-    WEBSOCKET_OPCODE_TEXT = 0x1,
-    WEBSOCKET_OPCODE_BINARY = 0x2,
-    WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
-    WEBSOCKET_OPCODE_PING = 0x9,
-    WEBSOCKET_OPCODE_PONG = 0xa
+	CONFIG_TYPE_UNKNOWN = 0x0,
+	CONFIG_TYPE_NUMBER = 0x1,
+	CONFIG_TYPE_STRING = 0x2,
+	CONFIG_TYPE_FILE = 0x3,
+	CONFIG_TYPE_DIRECTORY = 0x4,
+	CONFIG_TYPE_BOOLEAN = 0x5,
+	CONFIG_TYPE_EXT_PATTERN = 0x6
 };
 };
 
 
+/* Return array of struct mg_option, representing all valid configuration
+   options of civetweb.c.
+   The array is terminated by a NULL name option. */
+CIVETWEB_API const struct mg_option *mg_get_valid_options(void);
+
+/* Get the list of ports that civetweb is listening on.
+   size is the size of the ports int array and ssl int array to fill.
+   It is the caller's responsibility to make sure ports and ssl each
+   contain at least size int elements worth of memory to write into.
+   Return value is the number of ports and ssl information filled in.
+   The value returned is read-only. Civetweb does not allow changing
+   configuration at run time. */
+CIVETWEB_API size_t
+mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl);
+
+/* Add, edit or delete the entry in the passwords file.
+
+   This function allows an application to manipulate .htpasswd files on the
+   fly by adding, deleting and changing user records. This is one of the
+   several ways of implementing authentication on the server side. For another,
+   cookie-based way please refer to the examples/chat in the source tree.
+
+   If password is not NULL, entry is added (or modified if already exists).
+   If password is NULL, entry is deleted.
+
+   Return:
+     1 on success, 0 on error. */
+CIVETWEB_API int mg_modify_passwords_file(const char *passwords_file_name,
+                                          const char *domain,
+                                          const char *user,
+                                          const char *password);
+
+/* Return information associated with the request. */
+CIVETWEB_API const struct mg_request_info *
+mg_get_request_info(const struct mg_connection *);
+
+/* Send data to the client.
+   Return:
+    0   when the connection has been closed
+    -1  on error
+    >0  number of bytes written on success */
+CIVETWEB_API int mg_write(struct mg_connection *, const void *buf, size_t len);
+
+/* Send data to a websocket client wrapped in a websocket frame.  Uses
+   mg_lock_connection to ensure that the transmission is not interrupted,
+   i.e., when the application is proactively communicating and responding to
+   a request simultaneously.
+
+   Send data to a websocket client wrapped in a websocket frame.
+   This function is available when civetweb is compiled with -DUSE_WEBSOCKET
+
+   Return:
+    0   when the connection has been closed
+    -1  on error
+    >0  number of bytes written on success */
+CIVETWEB_API int mg_websocket_write(struct mg_connection *conn,
+                                    int opcode,
+                                    const char *data,
+                                    size_t data_len);
+
+/* Blocks until unique access is obtained to this connection. Intended for use
+   with websockets only.
+   Invoke this before mg_write or mg_printf when communicating with a
+   websocket if your code has server-initiated communication as well as
+   communication in direct response to a message. */
+CIVETWEB_API void mg_lock_connection(struct mg_connection *conn);
+CIVETWEB_API void mg_unlock_connection(struct mg_connection *conn);
+
+#if defined(MG_LEGACY_INTERFACE)
+#define mg_lock mg_lock_connection
+#define mg_unlock mg_unlock_connection
+#endif
+
+/* Lock server context.  This lock may be used to protect resources
+   that are shared between different connection/worker threads. */
+CIVETWEB_API void mg_lock_context(struct mg_context *ctx);
+CIVETWEB_API void mg_unlock_context(struct mg_context *ctx);
+
+/* Opcodes, from http://tools.ietf.org/html/rfc6455 */
+enum {
+	WEBSOCKET_OPCODE_CONTINUATION = 0x0,
+	WEBSOCKET_OPCODE_TEXT = 0x1,
+	WEBSOCKET_OPCODE_BINARY = 0x2,
+	WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
+	WEBSOCKET_OPCODE_PING = 0x9,
+	WEBSOCKET_OPCODE_PONG = 0xa
+};
 
 
-// Macros for enabling compiler-specific checks for printf-like arguments.
+/* Macros for enabling compiler-specific checks for printf-like arguments. */
 #undef PRINTF_FORMAT_STRING
 #undef PRINTF_FORMAT_STRING
 #if defined(_MSC_VER) && _MSC_VER >= 1400
 #if defined(_MSC_VER) && _MSC_VER >= 1400
 #include <sal.h>
 #include <sal.h>
@@ -296,179 +474,256 @@ enum {
 #define PRINTF_ARGS(x, y)
 #define PRINTF_ARGS(x, y)
 #endif
 #endif
 
 
-// Send data to the client using printf() semantics.
-//
-// Works exactly like mg_write(), but allows to do message formatting.
-int mg_printf(struct mg_connection *,
-              PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
-
-
-// Send contents of the entire file together with HTTP headers.
-void mg_send_file(struct mg_connection *conn, const char *path);
-
-
-// Read data from the remote end, return number of bytes read.
-// Return:
-//   0     connection has been closed by peer. No more data could be read.
-//   < 0   read error. No more data could be read from the connection.
-//   > 0   number of bytes read into the buffer.
-int mg_read(struct mg_connection *, void *buf, size_t len);
-
-
-// Get the value of particular HTTP header.
-//
-// This is a helper function. It traverses request_info->http_headers array,
-// and if the header is present in the array, returns its value. If it is
-// not present, NULL is returned.
-const char *mg_get_header(const struct mg_connection *, const char *name);
-
-
-// Get a value of particular form variable.
-//
-// Parameters:
-//   data: pointer to form-uri-encoded buffer. This could be either POST data,
-//         or request_info.query_string.
-//   data_len: length of the encoded data.
-//   var_name: variable name to decode from the buffer
-//   dst: destination buffer for the decoded variable
-//   dst_len: length of the destination buffer
-//
-// Return:
-//   On success, length of the decoded variable.
-//   On error:
-//      -1 (variable not found).
-//      -2 (destination buffer is NULL, zero length or too small to hold the
-//          decoded variable).
-//
-// Destination buffer is guaranteed to be '\0' - terminated if it is not
-// NULL or zero length.
-int mg_get_var(const char *data, size_t data_len,
-               const char *var_name, char *dst, size_t dst_len);
-
-// Get a value of particular form variable.
-//
-// Parameters:
-//   data: pointer to form-uri-encoded buffer. This could be either POST data,
-//         or request_info.query_string.
-//   data_len: length of the encoded data.
-//   var_name: variable name to decode from the buffer
-//   dst: destination buffer for the decoded variable
-//   dst_len: length of the destination buffer
-//   occurrence: which occurrence of the variable, 0 is the first, 1 the second...
-//              this makes it possible to parse a query like
-//              b=x&a=y&a=z which will have occurrence values b:0, a:0 and a:1
-//
-// Return:
-//   On success, length of the decoded variable.
-//   On error:
-//      -1 (variable not found).
-//      -2 (destination buffer is NULL, zero length or too small to hold the
-//          decoded variable).
-//
-// Destination buffer is guaranteed to be '\0' - terminated if it is not
-// NULL or zero length.
-int mg_get_var2(const char *data, size_t data_len,
-                const char *var_name, char *dst, size_t dst_len, size_t occurrence);
-
-// Fetch value of certain cookie variable into the destination buffer.
-//
-// Destination buffer is guaranteed to be '\0' - terminated. In case of
-// failure, dst[0] == '\0'. Note that RFC allows many occurrences of the same
-// parameter. This function returns only first occurrence.
-//
-// Return:
-//   On success, value length.
-//   On error:
-//      -1 (either "Cookie:" header is not present at all or the requested
-//          parameter is not found).
-//      -2 (destination buffer is NULL, zero length or too small to hold the
-//          value).
-int mg_get_cookie(const char *cookie, const char *var_name,
-                  char *buf, size_t buf_len);
-
-
-// Download data from the remote web server.
-//   host: host name to connect to, e.g. "foo.com", or "10.12.40.1".
-//   port: port number, e.g. 80.
-//   use_ssl: wether to use SSL connection.
-//   error_buffer, error_buffer_size: error message placeholder.
-//   request_fmt,...: HTTP request.
-// Return:
-//   On success, valid pointer to the new connection, suitable for mg_read().
-//   On error, NULL. error_buffer contains error message.
-// Example:
-//   char ebuf[100];
-//   struct mg_connection *conn;
-//   conn = mg_download("google.com", 80, 0, ebuf, sizeof(ebuf),
-//                      "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
-struct mg_connection *mg_download(const char *host, int port, int use_ssl,
-                                  char *error_buffer, size_t error_buffer_size,
-                                  PRINTF_FORMAT_STRING(const char *request_fmt),
-                                  ...) PRINTF_ARGS(6, 7);
-
-
-// Close the connection opened by mg_download().
-void mg_close_connection(struct mg_connection *conn);
-
-
-// File upload functionality. Each uploaded file gets saved into a temporary
-// file and MG_UPLOAD event is sent.
-// Return number of uploaded files.
-int mg_upload(struct mg_connection *conn, const char *destination_dir);
-
-
-// Convenience function -- create detached thread.
-// Return: 0 on success, non-0 on error.
-typedef void * (*mg_thread_func_t)(void *);
-int mg_start_thread(mg_thread_func_t f, void *p);
-
-
-// Return builtin mime type for the given file name.
-// For unrecognized extensions, "text/plain" is returned.
-const char *mg_get_builtin_mime_type(const char *file_name);
-
-
-// Return Civetweb version.
-const char *mg_version(void);
-
-// URL-decode input buffer into destination buffer.
-// 0-terminate the destination buffer.
-// form-url-encoded data differs from URI encoding in a way that it
-// uses '+' as character for space, see RFC 1866 section 8.2.1
-// http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
-// Return: length of the decoded data, or -1 if dst buffer is too small.
-int mg_url_decode(const char *src, int src_len, char *dst,
-                  int dst_len, int is_form_url_encoded);
-
-// URL-encode input buffer into destination buffer.
-// returns the length of the resulting buffer or -1
-// is the buffer is too small.
-int mg_url_encode(const char *src, char *dst, size_t dst_len);
-
-// MD5 hash given strings.
-// Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of
-// ASCIIz strings. When function returns, buf will contain human-readable
-// MD5 hash. Example:
-//   char buf[33];
-//   mg_md5(buf, "aa", "bb", NULL);
-char *mg_md5(char buf[33], ...);
-
-
-// Print error message to the opened error log stream.
-// This utilizes the provided logging configuration.
-//   conn: connection
-//   fmt: format string without the line return
-//   ...: variable argument list
-// Example:
-//   mg_cry(conn,"i like %s", "logging");
-void mg_cry(struct mg_connection *conn,
-            PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
-
-// utility method to compare two buffers, case incensitive.
-int mg_strncasecmp(const char *s1, const char *s2, size_t len);
+/* Send data to the client using printf() semantics.
+   Works exactly like mg_write(), but allows to do message formatting. */
+CIVETWEB_API int mg_printf(struct mg_connection *,
+                           PRINTF_FORMAT_STRING(const char *fmt),
+                           ...) PRINTF_ARGS(2, 3);
+
+/* Send contents of the entire file together with HTTP headers. */
+CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path);
+
+/* Read data from the remote end, return number of bytes read.
+   Return:
+     0     connection has been closed by peer. No more data could be read.
+     < 0   read error. No more data could be read from the connection.
+     > 0   number of bytes read into the buffer. */
+CIVETWEB_API int mg_read(struct mg_connection *, void *buf, size_t len);
+
+/* Get the value of particular HTTP header.
+
+   This is a helper function. It traverses request_info->http_headers array,
+   and if the header is present in the array, returns its value. If it is
+   not present, NULL is returned. */
+CIVETWEB_API const char *mg_get_header(const struct mg_connection *,
+                                       const char *name);
+
+/* Get a value of particular form variable.
+
+   Parameters:
+     data: pointer to form-uri-encoded buffer. This could be either POST data,
+           or request_info.query_string.
+     data_len: length of the encoded data.
+     var_name: variable name to decode from the buffer
+     dst: destination buffer for the decoded variable
+     dst_len: length of the destination buffer
+
+   Return:
+     On success, length of the decoded variable.
+     On error:
+        -1 (variable not found).
+        -2 (destination buffer is NULL, zero length or too small to hold the
+            decoded variable).
+
+   Destination buffer is guaranteed to be '\0' - terminated if it is not
+   NULL or zero length. */
+CIVETWEB_API int mg_get_var(const char *data,
+                            size_t data_len,
+                            const char *var_name,
+                            char *dst,
+                            size_t dst_len);
+
+/* Get a value of particular form variable.
+
+   Parameters:
+     data: pointer to form-uri-encoded buffer. This could be either POST data,
+           or request_info.query_string.
+     data_len: length of the encoded data.
+     var_name: variable name to decode from the buffer
+     dst: destination buffer for the decoded variable
+     dst_len: length of the destination buffer
+     occurrence: which occurrence of the variable, 0 is the first, 1 the
+                 second...
+                this makes it possible to parse a query like
+                b=x&a=y&a=z which will have occurrence values b:0, a:0 and a:1
+
+   Return:
+     On success, length of the decoded variable.
+     On error:
+        -1 (variable not found).
+        -2 (destination buffer is NULL, zero length or too small to hold the
+            decoded variable).
+
+   Destination buffer is guaranteed to be '\0' - terminated if it is not
+   NULL or zero length. */
+CIVETWEB_API int mg_get_var2(const char *data,
+                             size_t data_len,
+                             const char *var_name,
+                             char *dst,
+                             size_t dst_len,
+                             size_t occurrence);
+
+/* Fetch value of certain cookie variable into the destination buffer.
+
+   Destination buffer is guaranteed to be '\0' - terminated. In case of
+   failure, dst[0] == '\0'. Note that RFC allows many occurrences of the same
+   parameter. This function returns only first occurrence.
+
+   Return:
+     On success, value length.
+     On error:
+        -1 (either "Cookie:" header is not present at all or the requested
+            parameter is not found).
+        -2 (destination buffer is NULL, zero length or too small to hold the
+            value). */
+CIVETWEB_API int mg_get_cookie(const char *cookie,
+                               const char *var_name,
+                               char *buf,
+                               size_t buf_len);
+
+/* Download data from the remote web server.
+     host: host name to connect to, e.g. "foo.com", or "10.12.40.1".
+     port: port number, e.g. 80.
+     use_ssl: wether to use SSL connection.
+     error_buffer, error_buffer_size: error message placeholder.
+     request_fmt,...: HTTP request.
+   Return:
+     On success, valid pointer to the new connection, suitable for mg_read().
+     On error, NULL. error_buffer contains error message.
+   Example:
+     char ebuf[100];
+     struct mg_connection *conn;
+     conn = mg_download("google.com", 80, 0, ebuf, sizeof(ebuf),
+                        "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
+ */
+CIVETWEB_API struct mg_connection *
+mg_download(const char *host,
+            int port,
+            int use_ssl,
+            char *error_buffer,
+            size_t error_buffer_size,
+            PRINTF_FORMAT_STRING(const char *request_fmt),
+            ...) PRINTF_ARGS(6, 7);
+
+/* Close the connection opened by mg_download(). */
+CIVETWEB_API void mg_close_connection(struct mg_connection *conn);
+
+/* File upload functionality. Each uploaded file gets saved into a temporary
+   file and MG_UPLOAD event is sent.
+   Return number of uploaded files. */
+CIVETWEB_API int mg_upload(struct mg_connection *conn,
+                           const char *destination_dir);
+
+/* Convenience function -- create detached thread.
+   Return: 0 on success, non-0 on error. */
+typedef void *(*mg_thread_func_t)(void *);
+CIVETWEB_API int mg_start_thread(mg_thread_func_t f, void *p);
+
+/* Return builtin mime type for the given file name.
+   For unrecognized extensions, "text/plain" is returned. */
+CIVETWEB_API const char *mg_get_builtin_mime_type(const char *file_name);
+
+/* Return Civetweb version. */
+CIVETWEB_API const char *mg_version(void);
+
+/* URL-decode input buffer into destination buffer.
+   0-terminate the destination buffer.
+   form-url-encoded data differs from URI encoding in a way that it
+   uses '+' as character for space, see RFC 1866 section 8.2.1
+   http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
+   Return: length of the decoded data, or -1 if dst buffer is too small. */
+CIVETWEB_API int mg_url_decode(const char *src,
+                               int src_len,
+                               char *dst,
+                               int dst_len,
+                               int is_form_url_encoded);
+
+/* URL-encode input buffer into destination buffer.
+   returns the length of the resulting buffer or -1
+   is the buffer is too small. */
+CIVETWEB_API int mg_url_encode(const char *src, char *dst, size_t dst_len);
+
+/* MD5 hash given strings.
+   Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of
+   ASCIIz strings. When function returns, buf will contain human-readable
+   MD5 hash. Example:
+     char buf[33];
+     mg_md5(buf, "aa", "bb", NULL); */
+CIVETWEB_API char *mg_md5(char buf[33], ...);
+
+/* Print error message to the opened error log stream.
+   This utilizes the provided logging configuration.
+     conn: connection
+     fmt: format string without the line return
+     ...: variable argument list
+   Example:
+     mg_cry(conn,"i like %s", "logging"); */
+CIVETWEB_API void mg_cry(const struct mg_connection *conn,
+                         PRINTF_FORMAT_STRING(const char *fmt),
+                         ...) PRINTF_ARGS(2, 3);
+
+/* utility method to compare two buffers, case incensitive. */
+CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len);
+
+/* Connect to a websocket as a client
+   Parameters:
+     host: host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or
+   "localhost"
+     port: server port
+     use_ssl: make a secure connection to server
+     error_buffer, error_buffer_size: buffer for an error message
+     path: server path you are trying to connect to, i.e. if connection to
+   localhost/app, path should be "/app"
+     origin: value of the Origin HTTP header
+     data_func: callback that should be used when data is received from the
+   server
+     user_data: user supplied argument
+
+   Return:
+     On success, valid mg_connection object.
+     On error, NULL. Se error_buffer for details.
+*/
+
+CIVETWEB_API struct mg_connection *
+mg_connect_websocket_client(const char *host,
+                            int port,
+                            int use_ssl,
+                            char *error_buffer,
+                            size_t error_buffer_size,
+                            const char *path,
+                            const char *origin,
+                            mg_websocket_data_handler data_func,
+                            mg_websocket_close_handler close_func,
+                            void *user_data);
+
+/* Connect to a TCP server as a client (can be used to connect to a HTTP server)
+   Parameters:
+     host: host to connect to, i.e. "www.wikipedia.org" or "192.168.1.1" or
+   "localhost"
+     port: server port
+     use_ssl: make a secure connection to server
+     error_buffer, error_buffer_size: buffer for an error message
+
+   Return:
+     On success, valid mg_connection object.
+     On error, NULL. Se error_buffer for details.
+*/
+CIVETWEB_API struct mg_connection *mg_connect_client(const char *host,
+                                                     int port,
+                                                     int use_ssl,
+                                                     char *error_buffer,
+                                                     size_t error_buffer_size);
+
+enum { TIMEOUT_INFINITE = -1 };
+
+/* Wait for a response from the server
+   Parameters:
+     conn: connection
+     ebuf, ebuf_len: error message placeholder.
+     timeout: time to wait for a response in milliseconds (if < 0 then wait
+   forever)
+
+   Return:
+     On success, >= 0
+     On error/timeout, < 0
+*/
+CIVETWEB_API int mg_get_response(struct mg_connection *conn,
+                                 char *ebuf,
+                                 size_t ebuf_len,
+                                 int timeout);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
-#endif // __cplusplus
+#endif /* __cplusplus */
 
 
-#endif // CIVETWEB_HEADER_INCLUDED
+#endif /* CIVETWEB_HEADER_INCLUDED */

File diff suppressed because it is too large
+ 8828 - 4648
Source/ThirdParty/Civetweb/src/civetweb.c


+ 260 - 258
Source/ThirdParty/Civetweb/src/md5.inl

@@ -14,7 +14,7 @@
 
 
   This code implements the MD5 Algorithm defined in RFC 1321, whose
   This code implements the MD5 Algorithm defined in RFC 1321, whose
   text is available at
   text is available at
-	http://www.ietf.org/rfc/rfc1321.txt
+    http://www.ietf.org/rfc/rfc1321.txt
   The code is derived from the text of the RFC, including the test suite
   The code is derived from the text of the RFC, including the test suite
   (section A.5) but excluding the rest of Appendix A.  It does not include
   (section A.5) but excluding the rest of Appendix A.  It does not include
   any code or documentation that is identified in the RFC as being
   any code or documentation that is identified in the RFC as being
@@ -25,17 +25,17 @@
   that follows (in reverse chronological order):
   that follows (in reverse chronological order):
 
 
   2002-04-13 lpd Removed support for non-ANSI compilers; removed
   2002-04-13 lpd Removed support for non-ANSI compilers; removed
-	references to Ghostscript; clarified derivation from RFC 1321;
-	now handles byte order either statically or dynamically.
+    references to Ghostscript; clarified derivation from RFC 1321;
+    now handles byte order either statically or dynamically.
   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
-	added conditionalization for C++ compilation from Martin
-	Purschke <[email protected]>.
+    added conditionalization for C++ compilation from Martin
+    Purschke <[email protected]>.
   1999-05-03 lpd Original version.
   1999-05-03 lpd Original version.
  */
  */
 
 
 #ifndef md5_INCLUDED
 #ifndef md5_INCLUDED
-#  define md5_INCLUDED
+#define md5_INCLUDED
 
 
 /*
 /*
  * This package supports both compile-time and run-time determination of CPU
  * This package supports both compile-time and run-time determination of CPU
@@ -48,31 +48,31 @@
  */
  */
 
 
 typedef unsigned char md5_byte_t; /* 8-bit byte */
 typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
+typedef unsigned int md5_word_t;  /* 32-bit word */
 
 
 /* Define the state of the MD5 Algorithm. */
 /* Define the state of the MD5 Algorithm. */
 typedef struct md5_state_s {
 typedef struct md5_state_s {
-    md5_word_t count[2];	/* message length in bits, lsw first */
-    md5_word_t abcd[4];		/* digest buffer */
-    md5_byte_t buf[64];		/* accumulate block */
+	md5_word_t count[2]; /* message length in bits, lsw first */
+	md5_word_t abcd[4];  /* digest buffer */
+	md5_byte_t buf[64];  /* accumulate block */
 } md5_state_t;
 } md5_state_t;
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
-extern "C"
-{
+extern "C" {
 #endif
 #endif
 
 
 /* Initialize the algorithm. */
 /* Initialize the algorithm. */
 MD5_STATIC void md5_init(md5_state_t *pms);
 MD5_STATIC void md5_init(md5_state_t *pms);
 
 
 /* Append a string to the message. */
 /* Append a string to the message. */
-MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+MD5_STATIC void
+md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes);
 
 
 /* Finish the message and return the digest. */
 /* Finish the message and return the digest. */
 MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
 MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
-}  /* end extern "C" */
+} /* end extern "C" */
 #endif
 #endif
 
 
 #endif /* md5_INCLUDED */
 #endif /* md5_INCLUDED */
@@ -106,7 +106,7 @@ MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
 
 
   This code implements the MD5 Algorithm defined in RFC 1321, whose
   This code implements the MD5 Algorithm defined in RFC 1321, whose
   text is available at
   text is available at
-	http://www.ietf.org/rfc/rfc1321.txt
+    http://www.ietf.org/rfc/rfc1321.txt
   The code is derived from the text of the RFC, including the test suite
   The code is derived from the text of the RFC, including the test suite
   (section A.5) but excluding the rest of Appendix A.  It does not include
   (section A.5) but excluding the rest of Appendix A.  It does not include
   any code or documentation that is identified in the RFC as being
   any code or documentation that is identified in the RFC as being
@@ -117,14 +117,14 @@ MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
   that follows (in reverse chronological order):
   that follows (in reverse chronological order):
 
 
   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
-	either statically or dynamically; added missing #include <string.h>
-	in library.
+    either statically or dynamically; added missing #include <string.h>
+    in library.
   2002-03-11 lpd Corrected argument list for main(), and added int return
   2002-03-11 lpd Corrected argument list for main(), and added int return
-	type, in test program and T value program.
+    type, in test program and T value program.
   2002-02-21 lpd Added missing #include <stdio.h> in test program.
   2002-02-21 lpd Added missing #include <stdio.h> in test program.
   2000-07-03 lpd Patched to eliminate warnings about "constant is
   2000-07-03 lpd Patched to eliminate warnings about "constant is
-	unsigned in ANSI C, signed in traditional"; made test program
-	self-checking.
+    unsigned in ANSI C, signed in traditional"; made test program
+    self-checking.
   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
   1999-05-03 lpd Original version.
   1999-05-03 lpd Original version.
@@ -134,328 +134,330 @@ MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
 #include <string.h>
 #include <string.h>
 #endif
 #endif
 
 
-#undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
 #ifdef ARCH_IS_BIG_ENDIAN
 #ifdef ARCH_IS_BIG_ENDIAN
-#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
 #else
 #else
-#  define BYTE_ORDER 0
+#define BYTE_ORDER (0)
 #endif
 #endif
 
 
 #define T_MASK ((md5_word_t)~0)
 #define T_MASK ((md5_word_t)~0)
 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3    0x242070db
+#define T3 (0x242070db)
 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6    0x4787c62a
+#define T6 (0x4787c62a)
 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9    0x698098d8
+#define T9 (0x698098d8)
 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13    0x6b901122
+#define T13 (0x6b901122)
 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16    0x49b40821
+#define T16 (0x49b40821)
 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19    0x265e5a51
+#define T19 (0x265e5a51)
 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22    0x02441453
+#define T22 (0x02441453)
 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25    0x21e1cde6
+#define T25 (0x21e1cde6)
 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28    0x455a14ed
+#define T28 (0x455a14ed)
 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31    0x676f02d9
+#define T31 (0x676f02d9)
 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35    0x6d9d6122
+#define T35 (0x6d9d6122)
 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38    0x4bdecfa9
+#define T38 (0x4bdecfa9)
 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41    0x289b7ec6
+#define T41 (0x289b7ec6)
 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44    0x04881d05
+#define T44 (0x04881d05)
 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47    0x1fa27cf8
+#define T47 (0x1fa27cf8)
 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50    0x432aff97
+#define T50 (0x432aff97)
 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53    0x655b59c3
+#define T53 (0x655b59c3)
 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57    0x6fa87e4f
+#define T57 (0x6fa87e4f)
 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60    0x4e0811a1
+#define T60 (0x4e0811a1)
 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63    0x2ad7d2bb
+#define T63 (0x2ad7d2bb)
 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
 
 
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
 {
 {
-    md5_word_t
-    a = pms->abcd[0], b = pms->abcd[1],
-    c = pms->abcd[2], d = pms->abcd[3];
-    md5_word_t t;
+	md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2],
+	           d = pms->abcd[3];
+	md5_word_t t;
 #if BYTE_ORDER > 0
 #if BYTE_ORDER > 0
-    /* Define storage only for big-endian CPUs. */
-    md5_word_t X[16];
+	/* Define storage only for big-endian CPUs. */
+	md5_word_t X[16];
 #else
 #else
-    /* Define storage for little-endian or both types of CPUs. */
-    md5_word_t xbuf[16];
-    const md5_word_t *X;
+	/* Define storage for little-endian or both types of CPUs. */
+	md5_word_t xbuf[16];
+	const md5_word_t *X;
 #endif
 #endif
 
 
-    {
+	{
 #if BYTE_ORDER == 0
 #if BYTE_ORDER == 0
-        /*
-         * Determine dynamically whether this is a big-endian or
-         * little-endian machine, since we can use a more efficient
-         * algorithm on the latter.
-         */
-        static const int w = 1;
-
-        if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+		/*
+		 * Determine dynamically whether this is a big-endian or
+		 * little-endian machine, since we can use a more efficient
+		 * algorithm on the latter.
+		 */
+		static const int w = 1;
+
+		if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
 #endif
 #endif
-#if BYTE_ORDER <= 0		/* little-endian */
-        {
-            /*
-             * On little-endian machines, we can process properly aligned
-             * data without copying it.
-             */
-            if (!((data - (const md5_byte_t *)0) & 3)) {
-                /* data are properly aligned */
-                X = (const md5_word_t *)data;
-            } else {
-                /* not aligned */
-                memcpy(xbuf, data, 64);
-                X = xbuf;
-            }
-        }
+#if BYTE_ORDER <= 0 /* little-endian */
+		{
+			/*
+			 * On little-endian machines, we can process properly aligned
+			 * data without copying it.
+			 */
+			if (!((data - (const md5_byte_t *)0) & 3)) {
+				/* data are properly aligned, a direct assignment is possible */
+				/* cast through a (void *) should avoid a compiler warning,
+				   see
+				   https://github.com/bel2125/civetweb/issues/94#issuecomment-98112861
+				   */
+				X = (const md5_word_t *)(void *)data;
+			} else {
+				/* not aligned */
+				memcpy(xbuf, data, 64);
+				X = xbuf;
+			}
+		}
 #endif
 #endif
 #if BYTE_ORDER == 0
 #if BYTE_ORDER == 0
-        else			/* dynamic big-endian */
+		else /* dynamic big-endian */
 #endif
 #endif
-#if BYTE_ORDER >= 0		/* big-endian */
-        {
-            /*
-             * On big-endian machines, we must arrange the bytes in the
-             * right order.
-             */
-            const md5_byte_t *xp = data;
-            int i;
-
-#  if BYTE_ORDER == 0
-            X = xbuf;		/* (dynamic only) */
-#  else
-#    define xbuf X		/* (static only) */
-#  endif
-            for (i = 0; i < 16; ++i, xp += 4)
-                xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
-        }
+#if BYTE_ORDER >= 0 /* big-endian */
+		{
+			/*
+			 * On big-endian machines, we must arrange the bytes in the
+			 * right order.
+			 */
+			const md5_byte_t *xp = data;
+			int i;
+
+#if BYTE_ORDER == 0
+			X = xbuf; /* (dynamic only) */
+#else
+#define xbuf X /* (static only) */
+#endif
+			for (i = 0; i < 16; ++i, xp += 4)
+				xbuf[i] = (md5_word_t)(xp[0]) + (md5_word_t)(xp[1] << 8) +
+				          (md5_word_t)(xp[2] << 16) + (md5_word_t)(xp[3] << 24);
+		}
 #endif
 #endif
-    }
+	}
 
 
 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
 
 
-    /* Round 1. */
-    /* Let [abcd k s i] denote the operation
-       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+/* Round 1. */
+/* Let [abcd k s i] denote the operation
+   a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + F(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  7,  T1);
-    SET(d, a, b, c,  1, 12,  T2);
-    SET(c, d, a, b,  2, 17,  T3);
-    SET(b, c, d, a,  3, 22,  T4);
-    SET(a, b, c, d,  4,  7,  T5);
-    SET(d, a, b, c,  5, 12,  T6);
-    SET(c, d, a, b,  6, 17,  T7);
-    SET(b, c, d, a,  7, 22,  T8);
-    SET(a, b, c, d,  8,  7,  T9);
-    SET(d, a, b, c,  9, 12, T10);
-    SET(c, d, a, b, 10, 17, T11);
-    SET(b, c, d, a, 11, 22, T12);
-    SET(a, b, c, d, 12,  7, T13);
-    SET(d, a, b, c, 13, 12, T14);
-    SET(c, d, a, b, 14, 17, T15);
-    SET(b, c, d, a, 15, 22, T16);
+#define SET(a, b, c, d, k, s, Ti)                                              \
+	t = a + F(b, c, d) + X[k] + Ti;                                            \
+	a = ROTATE_LEFT(t, s) + b
+
+	/* Do the following 16 operations. */
+	SET(a, b, c, d, 0, 7, T1);
+	SET(d, a, b, c, 1, 12, T2);
+	SET(c, d, a, b, 2, 17, T3);
+	SET(b, c, d, a, 3, 22, T4);
+	SET(a, b, c, d, 4, 7, T5);
+	SET(d, a, b, c, 5, 12, T6);
+	SET(c, d, a, b, 6, 17, T7);
+	SET(b, c, d, a, 7, 22, T8);
+	SET(a, b, c, d, 8, 7, T9);
+	SET(d, a, b, c, 9, 12, T10);
+	SET(c, d, a, b, 10, 17, T11);
+	SET(b, c, d, a, 11, 22, T12);
+	SET(a, b, c, d, 12, 7, T13);
+	SET(d, a, b, c, 13, 12, T14);
+	SET(c, d, a, b, 14, 17, T15);
+	SET(b, c, d, a, 15, 22, T16);
 #undef SET
 #undef SET
 
 
-    /* Round 2. */
-    /* Let [abcd k s i] denote the operation
-         a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+/* Round 2. */
+/* Let [abcd k s i] denote the operation
+     a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + G(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  1,  5, T17);
-    SET(d, a, b, c,  6,  9, T18);
-    SET(c, d, a, b, 11, 14, T19);
-    SET(b, c, d, a,  0, 20, T20);
-    SET(a, b, c, d,  5,  5, T21);
-    SET(d, a, b, c, 10,  9, T22);
-    SET(c, d, a, b, 15, 14, T23);
-    SET(b, c, d, a,  4, 20, T24);
-    SET(a, b, c, d,  9,  5, T25);
-    SET(d, a, b, c, 14,  9, T26);
-    SET(c, d, a, b,  3, 14, T27);
-    SET(b, c, d, a,  8, 20, T28);
-    SET(a, b, c, d, 13,  5, T29);
-    SET(d, a, b, c,  2,  9, T30);
-    SET(c, d, a, b,  7, 14, T31);
-    SET(b, c, d, a, 12, 20, T32);
+#define SET(a, b, c, d, k, s, Ti)                                              \
+	t = a + G(b, c, d) + X[k] + Ti;                                            \
+	a = ROTATE_LEFT(t, s) + b
+
+	/* Do the following 16 operations. */
+	SET(a, b, c, d, 1, 5, T17);
+	SET(d, a, b, c, 6, 9, T18);
+	SET(c, d, a, b, 11, 14, T19);
+	SET(b, c, d, a, 0, 20, T20);
+	SET(a, b, c, d, 5, 5, T21);
+	SET(d, a, b, c, 10, 9, T22);
+	SET(c, d, a, b, 15, 14, T23);
+	SET(b, c, d, a, 4, 20, T24);
+	SET(a, b, c, d, 9, 5, T25);
+	SET(d, a, b, c, 14, 9, T26);
+	SET(c, d, a, b, 3, 14, T27);
+	SET(b, c, d, a, 8, 20, T28);
+	SET(a, b, c, d, 13, 5, T29);
+	SET(d, a, b, c, 2, 9, T30);
+	SET(c, d, a, b, 7, 14, T31);
+	SET(b, c, d, a, 12, 20, T32);
 #undef SET
 #undef SET
 
 
-    /* Round 3. */
-    /* Let [abcd k s t] denote the operation
-         a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+/* Round 3. */
+/* Let [abcd k s t] denote the operation
+     a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
 #define H(x, y, z) ((x) ^ (y) ^ (z))
 #define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + H(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  5,  4, T33);
-    SET(d, a, b, c,  8, 11, T34);
-    SET(c, d, a, b, 11, 16, T35);
-    SET(b, c, d, a, 14, 23, T36);
-    SET(a, b, c, d,  1,  4, T37);
-    SET(d, a, b, c,  4, 11, T38);
-    SET(c, d, a, b,  7, 16, T39);
-    SET(b, c, d, a, 10, 23, T40);
-    SET(a, b, c, d, 13,  4, T41);
-    SET(d, a, b, c,  0, 11, T42);
-    SET(c, d, a, b,  3, 16, T43);
-    SET(b, c, d, a,  6, 23, T44);
-    SET(a, b, c, d,  9,  4, T45);
-    SET(d, a, b, c, 12, 11, T46);
-    SET(c, d, a, b, 15, 16, T47);
-    SET(b, c, d, a,  2, 23, T48);
+#define SET(a, b, c, d, k, s, Ti)                                              \
+	t = a + H(b, c, d) + X[k] + Ti;                                            \
+	a = ROTATE_LEFT(t, s) + b
+
+	/* Do the following 16 operations. */
+	SET(a, b, c, d, 5, 4, T33);
+	SET(d, a, b, c, 8, 11, T34);
+	SET(c, d, a, b, 11, 16, T35);
+	SET(b, c, d, a, 14, 23, T36);
+	SET(a, b, c, d, 1, 4, T37);
+	SET(d, a, b, c, 4, 11, T38);
+	SET(c, d, a, b, 7, 16, T39);
+	SET(b, c, d, a, 10, 23, T40);
+	SET(a, b, c, d, 13, 4, T41);
+	SET(d, a, b, c, 0, 11, T42);
+	SET(c, d, a, b, 3, 16, T43);
+	SET(b, c, d, a, 6, 23, T44);
+	SET(a, b, c, d, 9, 4, T45);
+	SET(d, a, b, c, 12, 11, T46);
+	SET(c, d, a, b, 15, 16, T47);
+	SET(b, c, d, a, 2, 23, T48);
 #undef SET
 #undef SET
 
 
-    /* Round 4. */
-    /* Let [abcd k s t] denote the operation
-         a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+/* Round 4. */
+/* Let [abcd k s t] denote the operation
+     a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + I(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  6, T49);
-    SET(d, a, b, c,  7, 10, T50);
-    SET(c, d, a, b, 14, 15, T51);
-    SET(b, c, d, a,  5, 21, T52);
-    SET(a, b, c, d, 12,  6, T53);
-    SET(d, a, b, c,  3, 10, T54);
-    SET(c, d, a, b, 10, 15, T55);
-    SET(b, c, d, a,  1, 21, T56);
-    SET(a, b, c, d,  8,  6, T57);
-    SET(d, a, b, c, 15, 10, T58);
-    SET(c, d, a, b,  6, 15, T59);
-    SET(b, c, d, a, 13, 21, T60);
-    SET(a, b, c, d,  4,  6, T61);
-    SET(d, a, b, c, 11, 10, T62);
-    SET(c, d, a, b,  2, 15, T63);
-    SET(b, c, d, a,  9, 21, T64);
+#define SET(a, b, c, d, k, s, Ti)                                              \
+	t = a + I(b, c, d) + X[k] + Ti;                                            \
+	a = ROTATE_LEFT(t, s) + b
+
+	/* Do the following 16 operations. */
+	SET(a, b, c, d, 0, 6, T49);
+	SET(d, a, b, c, 7, 10, T50);
+	SET(c, d, a, b, 14, 15, T51);
+	SET(b, c, d, a, 5, 21, T52);
+	SET(a, b, c, d, 12, 6, T53);
+	SET(d, a, b, c, 3, 10, T54);
+	SET(c, d, a, b, 10, 15, T55);
+	SET(b, c, d, a, 1, 21, T56);
+	SET(a, b, c, d, 8, 6, T57);
+	SET(d, a, b, c, 15, 10, T58);
+	SET(c, d, a, b, 6, 15, T59);
+	SET(b, c, d, a, 13, 21, T60);
+	SET(a, b, c, d, 4, 6, T61);
+	SET(d, a, b, c, 11, 10, T62);
+	SET(c, d, a, b, 2, 15, T63);
+	SET(b, c, d, a, 9, 21, T64);
 #undef SET
 #undef SET
 
 
-    /* Then perform the following additions. (That is increment each
-       of the four registers by the value it had before this block
-       was started.) */
-    pms->abcd[0] += a;
-    pms->abcd[1] += b;
-    pms->abcd[2] += c;
-    pms->abcd[3] += d;
+	/* Then perform the following additions. (That is increment each
+	   of the four registers by the value it had before this block
+	   was started.) */
+	pms->abcd[0] += a;
+	pms->abcd[1] += b;
+	pms->abcd[2] += c;
+	pms->abcd[3] += d;
 }
 }
 
 
-MD5_STATIC void
-md5_init(md5_state_t *pms)
+MD5_STATIC void md5_init(md5_state_t *pms)
 {
 {
-    pms->count[0] = pms->count[1] = 0;
-    pms->abcd[0] = 0x67452301;
-    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
-    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
-    pms->abcd[3] = 0x10325476;
+	pms->count[0] = pms->count[1] = 0;
+	pms->abcd[0] = 0x67452301;
+	pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+	pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+	pms->abcd[3] = 0x10325476;
 }
 }
 
 
 MD5_STATIC void
 MD5_STATIC void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes)
 {
 {
-    const md5_byte_t *p = data;
-    int left = nbytes;
-    int offset = (pms->count[0] >> 3) & 63;
-    md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
-    if (nbytes <= 0)
-        return;
-
-    /* Update the message length. */
-    pms->count[1] += nbytes >> 29;
-    pms->count[0] += nbits;
-    if (pms->count[0] < nbits)
-        pms->count[1]++;
-
-    /* Process an initial partial block. */
-    if (offset) {
-        int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
-        memcpy(pms->buf + offset, p, copy);
-        if (offset + copy < 64)
-            return;
-        p += copy;
-        left -= copy;
-        md5_process(pms, pms->buf);
-    }
-
-    /* Process full blocks. */
-    for (; left >= 64; p += 64, left -= 64)
-        md5_process(pms, p);
-
-    /* Process a final partial block. */
-    if (left)
-        memcpy(pms->buf, p, left);
+	const md5_byte_t *p = data;
+	size_t left = nbytes;
+	size_t offset = (pms->count[0] >> 3) & 63;
+	md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+	if (nbytes <= 0)
+		return;
+
+	/* Update the message length. */
+	pms->count[1] += (md5_word_t)(nbytes >> 29);
+	pms->count[0] += nbits;
+	if (pms->count[0] < nbits)
+		pms->count[1]++;
+
+	/* Process an initial partial block. */
+	if (offset) {
+		size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+		memcpy(pms->buf + offset, p, copy);
+		if (offset + copy < 64)
+			return;
+		p += copy;
+		left -= copy;
+		md5_process(pms, pms->buf);
+	}
+
+	/* Process full blocks. */
+	for (; left >= 64; p += 64, left -= 64)
+		md5_process(pms, p);
+
+	/* Process a final partial block. */
+	if (left)
+		memcpy(pms->buf, p, left);
 }
 }
 
 
-MD5_STATIC void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16])
 {
 {
-    static const md5_byte_t pad[64] = {
-        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-    };
-    md5_byte_t data[8];
-    int i;
-
-    /* Save the length before padding. */
-    for (i = 0; i < 8; ++i)
-        data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
-    /* Pad to 56 bytes mod 64. */
-    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
-    /* Append the length. */
-    md5_append(pms, data, 8);
-    for (i = 0; i < 16; ++i)
-        digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+	static const md5_byte_t pad[64] = {
+	    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	md5_byte_t data[8];
+	int i;
+
+	/* Save the length before padding. */
+	for (i = 0; i < 8; ++i)
+		data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+	/* Pad to 56 bytes mod 64. */
+	md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+	/* Append the length. */
+	md5_append(pms, data, 8);
+	for (i = 0; i < 16; ++i)
+		digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
 }
 }

File diff suppressed because it is too large
+ 471 - 35
Source/ThirdParty/GLEW/glew.c


File diff suppressed because it is too large
+ 515 - 150
Source/ThirdParty/GLEW/glew.h


+ 156 - 21
Source/ThirdParty/GLEW/glxew.h

@@ -1,5 +1,6 @@
 /*
 /*
 ** The OpenGL Extension Wrangler Library
 ** The OpenGL Extension Wrangler Library
+** Copyright (C) 2008-2015, Nigel Stewart <nigels[]users sourceforge net>
 ** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
 ** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
 ** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
 ** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
 ** Copyright (C) 2002, Lev Povalahev
 ** Copyright (C) 2002, Lev Povalahev
@@ -200,12 +201,12 @@ typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void);
 #ifndef GLX_VERSION_1_3
 #ifndef GLX_VERSION_1_3
 #define GLX_VERSION_1_3 1
 #define GLX_VERSION_1_3 1
 
 
-#define GLX_RGBA_BIT 0x00000001
 #define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
 #define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_RGBA_BIT 0x00000001
 #define GLX_WINDOW_BIT 0x00000001
 #define GLX_WINDOW_BIT 0x00000001
 #define GLX_COLOR_INDEX_BIT 0x00000002
 #define GLX_COLOR_INDEX_BIT 0x00000002
-#define GLX_PIXMAP_BIT 0x00000002
 #define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
 #define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_PIXMAP_BIT 0x00000002
 #define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
 #define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
 #define GLX_PBUFFER_BIT 0x00000004
 #define GLX_PBUFFER_BIT 0x00000004
 #define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
 #define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
@@ -362,10 +363,43 @@ extern void ( * glXGetProcAddress (const GLubyte *procName)) (void);
 #define GLX_GPU_NUM_RB_AMD 0x21A7
 #define GLX_GPU_NUM_RB_AMD 0x21A7
 #define GLX_GPU_NUM_SPI_AMD 0x21A8
 #define GLX_GPU_NUM_SPI_AMD 0x21A8
 
 
+typedef void ( * PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC) (GLXContext dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef GLXContext ( * PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC) (unsigned int id, GLXContext share_list);
+typedef GLXContext ( * PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (unsigned int id, GLXContext share_context, const int* attribList);
+typedef Bool ( * PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC) (GLXContext ctx);
+typedef unsigned int ( * PFNGLXGETCONTEXTGPUIDAMDPROC) (GLXContext ctx);
+typedef GLXContext ( * PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void);
+typedef unsigned int ( * PFNGLXGETGPUIDSAMDPROC) (unsigned int maxCount, unsigned int* ids);
+typedef int ( * PFNGLXGETGPUINFOAMDPROC) (unsigned int id, int property, GLenum dataType, unsigned int size, void* data);
+typedef Bool ( * PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (GLXContext ctx);
+
+#define glXBlitContextFramebufferAMD GLXEW_GET_FUN(__glewXBlitContextFramebufferAMD)
+#define glXCreateAssociatedContextAMD GLXEW_GET_FUN(__glewXCreateAssociatedContextAMD)
+#define glXCreateAssociatedContextAttribsAMD GLXEW_GET_FUN(__glewXCreateAssociatedContextAttribsAMD)
+#define glXDeleteAssociatedContextAMD GLXEW_GET_FUN(__glewXDeleteAssociatedContextAMD)
+#define glXGetContextGPUIDAMD GLXEW_GET_FUN(__glewXGetContextGPUIDAMD)
+#define glXGetCurrentAssociatedContextAMD GLXEW_GET_FUN(__glewXGetCurrentAssociatedContextAMD)
+#define glXGetGPUIDsAMD GLXEW_GET_FUN(__glewXGetGPUIDsAMD)
+#define glXGetGPUInfoAMD GLXEW_GET_FUN(__glewXGetGPUInfoAMD)
+#define glXMakeAssociatedContextCurrentAMD GLXEW_GET_FUN(__glewXMakeAssociatedContextCurrentAMD)
+
 #define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association)
 #define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association)
 
 
 #endif /* GLX_AMD_gpu_association */
 #endif /* GLX_AMD_gpu_association */
 
 
+/* --------------------- GLX_ARB_context_flush_control --------------------- */
+
+#ifndef GLX_ARB_context_flush_control
+#define GLX_ARB_context_flush_control 1
+
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+
+#define GLXEW_ARB_context_flush_control GLXEW_GET_VAR(__GLXEW_ARB_context_flush_control)
+
+#endif /* GLX_ARB_context_flush_control */
+
 /* ------------------------- GLX_ARB_create_context ------------------------ */
 /* ------------------------- GLX_ARB_create_context ------------------------ */
 
 
 #ifndef GLX_ARB_create_context
 #ifndef GLX_ARB_create_context
@@ -417,8 +451,8 @@ typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBCo
 #ifndef GLX_ARB_fbconfig_float
 #ifndef GLX_ARB_fbconfig_float
 #define GLX_ARB_fbconfig_float 1
 #define GLX_ARB_fbconfig_float 1
 
 
-#define GLX_RGBA_FLOAT_BIT 0x00000004
-#define GLX_RGBA_FLOAT_TYPE 0x20B9
+#define GLX_RGBA_FLOAT_BIT_ARB 0x00000004
+#define GLX_RGBA_FLOAT_TYPE_ARB 0x20B9
 
 
 #define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float)
 #define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float)
 
 
@@ -555,6 +589,17 @@ typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, i
 
 
 #endif /* GLX_ATI_render_texture */
 #endif /* GLX_ATI_render_texture */
 
 
+/* --------------------------- GLX_EXT_buffer_age -------------------------- */
+
+#ifndef GLX_EXT_buffer_age
+#define GLX_EXT_buffer_age 1
+
+#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
+
+#define GLXEW_EXT_buffer_age GLXEW_GET_VAR(__GLXEW_EXT_buffer_age)
+
+#endif /* GLX_EXT_buffer_age */
+
 /* ------------------- GLX_EXT_create_context_es2_profile ------------------ */
 /* ------------------- GLX_EXT_create_context_es2_profile ------------------ */
 
 
 #ifndef GLX_EXT_create_context_es2_profile
 #ifndef GLX_EXT_create_context_es2_profile
@@ -634,6 +679,19 @@ typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context
 
 
 #endif /* GLX_EXT_scene_marker */
 #endif /* GLX_EXT_scene_marker */
 
 
+/* -------------------------- GLX_EXT_stereo_tree -------------------------- */
+
+#ifndef GLX_EXT_stereo_tree
+#define GLX_EXT_stereo_tree 1
+
+#define GLX_STEREO_NOTIFY_EXT 0x00000000
+#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001
+#define GLX_STEREO_TREE_EXT 0x20F5
+
+#define GLXEW_EXT_stereo_tree GLXEW_GET_VAR(__GLXEW_EXT_stereo_tree)
+
+#endif /* GLX_EXT_stereo_tree */
+
 /* -------------------------- GLX_EXT_swap_control ------------------------- */
 /* -------------------------- GLX_EXT_swap_control ------------------------- */
 
 
 #ifndef GLX_EXT_swap_control
 #ifndef GLX_EXT_swap_control
@@ -800,6 +858,38 @@ typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo
 
 
 #endif /* GLX_MESA_pixmap_colormap */
 #endif /* GLX_MESA_pixmap_colormap */
 
 
+/* ------------------------ GLX_MESA_query_renderer ------------------------ */
+
+#ifndef GLX_MESA_query_renderer
+#define GLX_MESA_query_renderer 1
+
+#define GLX_RENDERER_VENDOR_ID_MESA 0x8183
+#define GLX_RENDERER_DEVICE_ID_MESA 0x8184
+#define GLX_RENDERER_VERSION_MESA 0x8185
+#define GLX_RENDERER_ACCELERATED_MESA 0x8186
+#define GLX_RENDERER_VIDEO_MEMORY_MESA 0x8187
+#define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188
+#define GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189
+#define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A
+#define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B
+#define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C
+#define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D
+#define GLX_RENDERER_ID_MESA 0x818E
+
+typedef Bool ( * PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) (int attribute, unsigned int* value);
+typedef const char* ( * PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC) (int attribute);
+typedef Bool ( * PFNGLXQUERYRENDERERINTEGERMESAPROC) (Display* dpy, int screen, int renderer, int attribute, unsigned int *value);
+typedef const char* ( * PFNGLXQUERYRENDERERSTRINGMESAPROC) (Display *dpy, int screen, int renderer, int attribute);
+
+#define glXQueryCurrentRendererIntegerMESA GLXEW_GET_FUN(__glewXQueryCurrentRendererIntegerMESA)
+#define glXQueryCurrentRendererStringMESA GLXEW_GET_FUN(__glewXQueryCurrentRendererStringMESA)
+#define glXQueryRendererIntegerMESA GLXEW_GET_FUN(__glewXQueryRendererIntegerMESA)
+#define glXQueryRendererStringMESA GLXEW_GET_FUN(__glewXQueryRendererStringMESA)
+
+#define GLXEW_MESA_query_renderer GLXEW_GET_VAR(__GLXEW_MESA_query_renderer)
+
+#endif /* GLX_MESA_query_renderer */
+
 /* ------------------------ GLX_MESA_release_buffers ----------------------- */
 /* ------------------------ GLX_MESA_release_buffers ----------------------- */
 
 
 #ifndef GLX_MESA_release_buffers
 #ifndef GLX_MESA_release_buffers
@@ -844,6 +934,21 @@ typedef int ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned int interval);
 
 
 #endif /* GLX_MESA_swap_control */
 #endif /* GLX_MESA_swap_control */
 
 
+/* --------------------------- GLX_NV_copy_buffer -------------------------- */
+
+#ifndef GLX_NV_copy_buffer
+#define GLX_NV_copy_buffer 1
+
+typedef void ( * PFNGLXCOPYBUFFERSUBDATANVPROC) (Display* dpy, GLXContext readCtx, GLXContext writeCtx, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void ( * PFNGLXNAMEDCOPYBUFFERSUBDATANVPROC) (Display* dpy, GLXContext readCtx, GLXContext writeCtx, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+
+#define glXCopyBufferSubDataNV GLXEW_GET_FUN(__glewXCopyBufferSubDataNV)
+#define glXNamedCopyBufferSubDataNV GLXEW_GET_FUN(__glewXNamedCopyBufferSubDataNV)
+
+#define GLXEW_NV_copy_buffer GLXEW_GET_VAR(__GLXEW_NV_copy_buffer)
+
+#endif /* GLX_NV_copy_buffer */
+
 /* --------------------------- GLX_NV_copy_image --------------------------- */
 /* --------------------------- GLX_NV_copy_image --------------------------- */
 
 
 #ifndef GLX_NV_copy_image
 #ifndef GLX_NV_copy_image
@@ -857,6 +962,19 @@ typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx,
 
 
 #endif /* GLX_NV_copy_image */
 #endif /* GLX_NV_copy_image */
 
 
+/* ------------------------ GLX_NV_delay_before_swap ----------------------- */
+
+#ifndef GLX_NV_delay_before_swap
+#define GLX_NV_delay_before_swap 1
+
+typedef Bool ( * PFNGLXDELAYBEFORESWAPNVPROC) (Display* dpy, GLXDrawable drawable, GLfloat seconds);
+
+#define glXDelayBeforeSwapNV GLXEW_GET_FUN(__glewXDelayBeforeSwapNV)
+
+#define GLXEW_NV_delay_before_swap GLXEW_GET_VAR(__GLXEW_NV_delay_before_swap)
+
+#endif /* GLX_NV_delay_before_swap */
+
 /* -------------------------- GLX_NV_float_buffer -------------------------- */
 /* -------------------------- GLX_NV_float_buffer -------------------------- */
 
 
 #ifndef GLX_NV_float_buffer
 #ifndef GLX_NV_float_buffer
@@ -1047,16 +1165,6 @@ typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, i
 #ifndef GLX_SGIS_color_range
 #ifndef GLX_SGIS_color_range
 #define GLX_SGIS_color_range 1
 #define GLX_SGIS_color_range 1
 
 
-#define GLX_MIN_RED_SGIS 0
-#define GLX_MAX_GREEN_SGIS 0
-#define GLX_MIN_BLUE_SGIS 0
-#define GLX_MAX_ALPHA_SGIS 0
-#define GLX_MIN_GREEN_SGIS 0
-#define GLX_MIN_ALPHA_SGIS 0
-#define GLX_MAX_RED_SGIS 0
-#define GLX_EXTENDED_RANGE_SGIS 0
-#define GLX_MAX_BLUE_SGIS 0
-
 #define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range)
 #define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range)
 
 
 #endif /* GLX_SGIS_color_range */
 #endif /* GLX_SGIS_color_range */
@@ -1090,10 +1198,10 @@ typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, i
 #ifndef GLX_SGIX_fbconfig
 #ifndef GLX_SGIX_fbconfig
 #define GLX_SGIX_fbconfig 1
 #define GLX_SGIX_fbconfig 1
 
 
-#define GLX_WINDOW_BIT_SGIX 0x00000001
 #define GLX_RGBA_BIT_SGIX 0x00000001
 #define GLX_RGBA_BIT_SGIX 0x00000001
-#define GLX_PIXMAP_BIT_SGIX 0x00000002
+#define GLX_WINDOW_BIT_SGIX 0x00000001
 #define GLX_COLOR_INDEX_BIT_SGIX 0x00000002
 #define GLX_COLOR_INDEX_BIT_SGIX 0x00000002
+#define GLX_PIXMAP_BIT_SGIX 0x00000002
 #define GLX_SCREEN_EXT 0x800C
 #define GLX_SCREEN_EXT 0x800C
 #define GLX_DRAWABLE_TYPE_SGIX 0x8010
 #define GLX_DRAWABLE_TYPE_SGIX 0x8010
 #define GLX_RENDER_TYPE_SGIX 0x8011
 #define GLX_RENDER_TYPE_SGIX 0x8011
@@ -1130,8 +1238,8 @@ typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLX
 
 
 #define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001
 #define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001
 #define GLX_PIPE_RECT_SGIX 0x00000001
 #define GLX_PIPE_RECT_SGIX 0x00000001
-#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002
 #define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002
 #define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002
+#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002
 #define GLX_HYPERPIPE_STEREO_SGIX 0x00000003
 #define GLX_HYPERPIPE_STEREO_SGIX 0x00000003
 #define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004
 #define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004
 #define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80
 #define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80
@@ -1197,8 +1305,8 @@ typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Disp
 
 
 #define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001
 #define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001
 #define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002
 #define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002
-#define GLX_PBUFFER_BIT_SGIX 0x00000004
 #define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004
 #define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004
+#define GLX_PBUFFER_BIT_SGIX 0x00000004
 #define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008
 #define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008
 #define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010
 #define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010
 #define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020
 #define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020
@@ -1393,7 +1501,7 @@ typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window,
 /* ------------------------------------------------------------------------- */
 /* ------------------------------------------------------------------------- */
 
 
 #ifdef GLEW_MX
 #ifdef GLEW_MX
-#define GLXEW_FUN_EXPORT
+#define GLXEW_FUN_EXPORT GLEW_FUN_EXPORT
 #define GLXEW_VAR_EXPORT
 #define GLXEW_VAR_EXPORT
 #else
 #else
 #define GLXEW_FUN_EXPORT GLEW_FUN_EXPORT
 #define GLXEW_FUN_EXPORT GLEW_FUN_EXPORT
@@ -1420,6 +1528,16 @@ GLXEW_FUN_EXPORT PFNGLXQUERYCONTEXTPROC __glewXQueryContext;
 GLXEW_FUN_EXPORT PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable;
 GLXEW_FUN_EXPORT PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable;
 GLXEW_FUN_EXPORT PFNGLXSELECTEVENTPROC __glewXSelectEvent;
 GLXEW_FUN_EXPORT PFNGLXSELECTEVENTPROC __glewXSelectEvent;
 
 
+GLXEW_FUN_EXPORT PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC __glewXBlitContextFramebufferAMD;
+GLXEW_FUN_EXPORT PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC __glewXCreateAssociatedContextAMD;
+GLXEW_FUN_EXPORT PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __glewXCreateAssociatedContextAttribsAMD;
+GLXEW_FUN_EXPORT PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC __glewXDeleteAssociatedContextAMD;
+GLXEW_FUN_EXPORT PFNGLXGETCONTEXTGPUIDAMDPROC __glewXGetContextGPUIDAMD;
+GLXEW_FUN_EXPORT PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC __glewXGetCurrentAssociatedContextAMD;
+GLXEW_FUN_EXPORT PFNGLXGETGPUIDSAMDPROC __glewXGetGPUIDsAMD;
+GLXEW_FUN_EXPORT PFNGLXGETGPUINFOAMDPROC __glewXGetGPUInfoAMD;
+GLXEW_FUN_EXPORT PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __glewXMakeAssociatedContextCurrentAMD;
+
 GLXEW_FUN_EXPORT PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB;
 GLXEW_FUN_EXPORT PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB;
 
 
 GLXEW_FUN_EXPORT PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI;
 GLXEW_FUN_EXPORT PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI;
@@ -1442,6 +1560,11 @@ GLXEW_FUN_EXPORT PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA;
 
 
 GLXEW_FUN_EXPORT PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA;
 GLXEW_FUN_EXPORT PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA;
 
 
+GLXEW_FUN_EXPORT PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC __glewXQueryCurrentRendererIntegerMESA;
+GLXEW_FUN_EXPORT PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC __glewXQueryCurrentRendererStringMESA;
+GLXEW_FUN_EXPORT PFNGLXQUERYRENDERERINTEGERMESAPROC __glewXQueryRendererIntegerMESA;
+GLXEW_FUN_EXPORT PFNGLXQUERYRENDERERSTRINGMESAPROC __glewXQueryRendererStringMESA;
+
 GLXEW_FUN_EXPORT PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA;
 GLXEW_FUN_EXPORT PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA;
 
 
 GLXEW_FUN_EXPORT PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA;
 GLXEW_FUN_EXPORT PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA;
@@ -1449,8 +1572,13 @@ GLXEW_FUN_EXPORT PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA;
 GLXEW_FUN_EXPORT PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA;
 GLXEW_FUN_EXPORT PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA;
 GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA;
 GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA;
 
 
+GLXEW_FUN_EXPORT PFNGLXCOPYBUFFERSUBDATANVPROC __glewXCopyBufferSubDataNV;
+GLXEW_FUN_EXPORT PFNGLXNAMEDCOPYBUFFERSUBDATANVPROC __glewXNamedCopyBufferSubDataNV;
+
 GLXEW_FUN_EXPORT PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV;
 GLXEW_FUN_EXPORT PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV;
 
 
+GLXEW_FUN_EXPORT PFNGLXDELAYBEFORESWAPNVPROC __glewXDelayBeforeSwapNV;
+
 GLXEW_FUN_EXPORT PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV;
 GLXEW_FUN_EXPORT PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV;
 GLXEW_FUN_EXPORT PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV;
 GLXEW_FUN_EXPORT PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV;
 
 
@@ -1543,6 +1671,7 @@ GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_3;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_4;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_4;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_3DFX_multisample;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_3DFX_multisample;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_AMD_gpu_association;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_AMD_gpu_association;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_context_flush_control;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context_profile;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context_profile;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context_robustness;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context_robustness;
@@ -1555,12 +1684,14 @@ GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_robustness_share_group_isolation;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ATI_pixel_format_float;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ATI_pixel_format_float;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ATI_render_texture;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_ATI_render_texture;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_buffer_age;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_create_context_es_profile;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_create_context_es_profile;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_import_context;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_import_context;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_scene_marker;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_scene_marker;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_stereo_tree;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control_tear;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control_tear;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap;
@@ -1570,10 +1701,13 @@ GLXEW_VAR_EXPORT GLboolean __GLXEW_INTEL_swap_event;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_agp_offset;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_agp_offset;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_query_renderer;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_release_buffers;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_release_buffers;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_swap_control;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_swap_control;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_copy_buffer;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_copy_image;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_copy_image;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_delay_before_swap;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_float_buffer;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_float_buffer;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_multisample_coverage;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_multisample_coverage;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_present_video;
 GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_present_video;
@@ -1621,11 +1755,12 @@ GLEWAPI GLboolean GLEWAPIENTRY glxewContextIsSupported (const GLXEWContext *ctx,
 
 
 #else /* GLEW_MX */
 #else /* GLEW_MX */
 
 
+GLEWAPI GLenum GLEWAPIENTRY glxewInit ();
+GLEWAPI GLboolean GLEWAPIENTRY glxewIsSupported (const char *name);
+
 #define GLXEW_GET_VAR(x) (*(const GLboolean*)&x)
 #define GLXEW_GET_VAR(x) (*(const GLboolean*)&x)
 #define GLXEW_GET_FUN(x) x
 #define GLXEW_GET_FUN(x) x
 
 
-GLEWAPI GLboolean GLEWAPIENTRY glxewIsSupported (const char *name);
-
 #endif /* GLEW_MX */
 #endif /* GLEW_MX */
 
 
 GLEWAPI GLboolean GLEWAPIENTRY glxewGetExtension (const char *name);
 GLEWAPI GLboolean GLEWAPIENTRY glxewGetExtension (const char *name);

+ 58 - 2
Source/ThirdParty/GLEW/wglew.h

@@ -1,5 +1,6 @@
 /*
 /*
 ** The OpenGL Extension Wrangler Library
 ** The OpenGL Extension Wrangler Library
+** Copyright (C) 2008-2015, Nigel Stewart <nigels[]users sourceforge net>
 ** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
 ** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
 ** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
 ** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
 ** Copyright (C) 2002, Lev Povalahev
 ** Copyright (C) 2002, Lev Povalahev
@@ -182,6 +183,19 @@ typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, in
 
 
 #endif /* WGL_ARB_buffer_region */
 #endif /* WGL_ARB_buffer_region */
 
 
+/* --------------------- WGL_ARB_context_flush_control --------------------- */
+
+#ifndef WGL_ARB_context_flush_control
+#define WGL_ARB_context_flush_control 1
+
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+
+#define WGLEW_ARB_context_flush_control WGLEW_GET_VAR(__WGLEW_ARB_context_flush_control)
+
+#endif /* WGL_ARB_context_flush_control */
+
 /* ------------------------- WGL_ARB_create_context ------------------------ */
 /* ------------------------- WGL_ARB_create_context ------------------------ */
 
 
 #ifndef WGL_ARB_create_context
 #ifndef WGL_ARB_create_context
@@ -446,6 +460,28 @@ typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, con
 
 
 #endif /* WGL_ARB_render_texture */
 #endif /* WGL_ARB_render_texture */
 
 
+/* ---------------- WGL_ARB_robustness_application_isolation --------------- */
+
+#ifndef WGL_ARB_robustness_application_isolation
+#define WGL_ARB_robustness_application_isolation 1
+
+#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define WGLEW_ARB_robustness_application_isolation WGLEW_GET_VAR(__WGLEW_ARB_robustness_application_isolation)
+
+#endif /* WGL_ARB_robustness_application_isolation */
+
+/* ---------------- WGL_ARB_robustness_share_group_isolation --------------- */
+
+#ifndef WGL_ARB_robustness_share_group_isolation
+#define WGL_ARB_robustness_share_group_isolation 1
+
+#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define WGLEW_ARB_robustness_share_group_isolation WGLEW_GET_VAR(__WGLEW_ARB_robustness_share_group_isolation)
+
+#endif /* WGL_ARB_robustness_share_group_isolation */
+
 /* ----------------------- WGL_ATI_pixel_format_float ---------------------- */
 /* ----------------------- WGL_ATI_pixel_format_float ---------------------- */
 
 
 #ifndef WGL_ATI_pixel_format_float
 #ifndef WGL_ATI_pixel_format_float
@@ -906,6 +942,19 @@ typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcNa
 
 
 #endif /* WGL_NV_copy_image */
 #endif /* WGL_NV_copy_image */
 
 
+/* ------------------------ WGL_NV_delay_before_swap ----------------------- */
+
+#ifndef WGL_NV_delay_before_swap
+#define WGL_NV_delay_before_swap 1
+
+typedef BOOL (WINAPI * PFNWGLDELAYBEFORESWAPNVPROC) (HDC hDC, GLfloat seconds);
+
+#define wglDelayBeforeSwapNV WGLEW_GET_FUN(__wglewDelayBeforeSwapNV)
+
+#define WGLEW_NV_delay_before_swap WGLEW_GET_VAR(__WGLEW_NV_delay_before_swap)
+
+#endif /* WGL_NV_delay_before_swap */
+
 /* -------------------------- WGL_NV_float_buffer -------------------------- */
 /* -------------------------- WGL_NV_float_buffer -------------------------- */
 
 
 #ifndef WGL_NV_float_buffer
 #ifndef WGL_NV_float_buffer
@@ -1269,6 +1318,8 @@ WGLEW_FUN_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV;
 
 
 WGLEW_FUN_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV;
 WGLEW_FUN_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV;
 
 
+WGLEW_FUN_EXPORT PFNWGLDELAYBEFORESWAPNVPROC __wglewDelayBeforeSwapNV;
+
 WGLEW_FUN_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV;
 WGLEW_FUN_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV;
 WGLEW_FUN_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV;
 WGLEW_FUN_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV;
 WGLEW_FUN_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV;
 WGLEW_FUN_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV;
@@ -1312,6 +1363,7 @@ WGLEW_VAR_EXPORT GLboolean __WGLEW_3DFX_multisample;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_3DL_stereo_control;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_3DL_stereo_control;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_AMD_gpu_association;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_AMD_gpu_association;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_buffer_region;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_buffer_region;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_context_flush_control;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context_profile;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context_profile;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context_robustness;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context_robustness;
@@ -1323,6 +1375,8 @@ WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pbuffer;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pixel_format;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pixel_format;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pixel_format_float;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pixel_format_float;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_render_texture;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_render_texture;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_robustness_application_isolation;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_robustness_share_group_isolation;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ATI_pixel_format_float;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ATI_pixel_format_float;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile;
@@ -1347,6 +1401,7 @@ WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop2;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop2;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_copy_image;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_copy_image;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_delay_before_swap;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_float_buffer;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_float_buffer;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_gpu_affinity;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_gpu_affinity;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_multisample_coverage;
 WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_multisample_coverage;
@@ -1379,11 +1434,12 @@ GLEWAPI GLboolean GLEWAPIENTRY wglewContextIsSupported (const WGLEWContext *ctx,
 
 
 #else /* GLEW_MX */
 #else /* GLEW_MX */
 
 
+GLEWAPI GLenum GLEWAPIENTRY wglewInit ();
+GLEWAPI GLboolean GLEWAPIENTRY wglewIsSupported (const char *name);
+
 #define WGLEW_GET_VAR(x) (*(const GLboolean*)&x)
 #define WGLEW_GET_VAR(x) (*(const GLboolean*)&x)
 #define WGLEW_GET_FUN(x) x
 #define WGLEW_GET_FUN(x) x
 
 
-GLEWAPI GLboolean GLEWAPIENTRY wglewIsSupported (const char *name);
-
 #endif /* GLEW_MX */
 #endif /* GLEW_MX */
 
 
 GLEWAPI GLboolean GLEWAPIENTRY wglewGetExtension (const char *name);
 GLEWAPI GLboolean GLEWAPIENTRY wglewGetExtension (const char *name);

+ 16 - 0
Source/ThirdParty/JO/jo_jpeg.cpp

@@ -19,6 +19,8 @@
  * 	
  * 	
  * */
  * */
 
 
+// Modified by Lasse Oorni for Urho3D
+
 #ifndef JO_JPEG_HEADER_FILE_ONLY
 #ifndef JO_JPEG_HEADER_FILE_ONLY
 
 
 #if defined(_MSC_VER) && _MSC_VER >= 0x1400
 #if defined(_MSC_VER) && _MSC_VER >= 0x1400
@@ -29,6 +31,11 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <math.h>
 #include <math.h>
 
 
+// Urho3D: for MultiByteToWideChar
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
 static const unsigned char s_jo_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
 static const unsigned char s_jo_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
 
 
 static void jo_writeBits(FILE *fp, int &bitBuf, int &bitCnt, const unsigned short *bs) {
 static void jo_writeBits(FILE *fp, int &bitBuf, int &bitCnt, const unsigned short *bs) {
@@ -231,7 +238,16 @@ bool jo_write_jpg(const char *filename, const void *data, int width, int height,
 		return false;
 		return false;
 	}
 	}
 
 
+	// Urho3D: proper UTF8 handling for Windows
+#ifndef _WIN32
 	FILE *fp = fopen(filename, "wb");
 	FILE *fp = fopen(filename, "wb");
+#else
+	int wcharsize = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
+	wchar_t* wstr = new wchar_t[wcharsize];
+	MultiByteToWideChar(CP_UTF8, 0, filename, -1, wstr, wcharsize);
+	FILE *fp = _wfopen(wstr, L"wb");
+	delete[] wstr;
+#endif
 	if(!fp) {
 	if(!fp) {
 		return false;
 		return false;
 	}
 	}

+ 0 - 10
Source/ThirdParty/LZ4/NEWS

@@ -1,10 +0,0 @@
-r106 :
-Makefile : make dist modify text files in the package to respect Unix EoL convention
-lz4cli : corrected small display bug in HC mode
-
-r105 :
-Makefile : New install script and man page, contributed by Prasad Pandit
-lz4cli.c : Minor modifications, for easier extensibility
-COPYING : added license file
-LZ4_Streaming_Format.odt : modified file name to remove white space characters
-exe : .exe suffix now properly added only for Windows target

File diff suppressed because it is too large
+ 720 - 385
Source/ThirdParty/LZ4/lz4.c


+ 267 - 112
Source/ThirdParty/LZ4/lz4.h

@@ -1,7 +1,8 @@
 /*
 /*
    LZ4 - Fast LZ compression algorithm
    LZ4 - Fast LZ compression algorithm
    Header File
    Header File
-   Copyright (C) 2011-2013, Yann Collet.
+   Copyright (C) 2011-2015, Yann Collet.
+
    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
 
 
    Redistribution and use in source and binary forms, with or without
    Redistribution and use in source and binary forms, with or without
@@ -28,8 +29,8 @@
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
    You can contact the author at :
    You can contact the author at :
-   - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
-   - LZ4 source repository : http://code.google.com/p/lz4/
+   - LZ4 source repository : https://github.com/Cyan4973/lz4
+   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
 */
 */
 #pragma once
 #pragma once
 
 
@@ -37,167 +38,321 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
+/*
+ * lz4.h provides block compression functions, and gives full buffer control to programmer.
+ * If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
+ * and can let the library handle its own memory, please use lz4frame.h instead.
+*/
 
 
-//**************************************
-// Compiler Options
-//**************************************
-#if defined(_MSC_VER) && !defined(__cplusplus)   // Visual Studio
-#  define inline __inline           // Visual C is not C99, but supports some kind of inline
-#endif
+/**************************************
+*  Version
+**************************************/
+#define LZ4_VERSION_MAJOR    1    /* for breaking interface changes  */
+#define LZ4_VERSION_MINOR    7    /* for new (non-breaking) interface capabilities */
+#define LZ4_VERSION_RELEASE  1    /* for tweaks, bug-fixes, or development */
+#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
+int LZ4_versionNumber (void);
+
+/**************************************
+*  Tuning parameter
+**************************************/
+/*
+ * LZ4_MEMORY_USAGE :
+ * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
+ * Increasing memory usage improves compression ratio
+ * Reduced memory usage can improve speed, due to cache effect
+ * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
+ */
+#define LZ4_MEMORY_USAGE 14
 
 
 
 
-//****************************
-// Simple Functions
-//****************************
+/**************************************
+*  Simple Functions
+**************************************/
 
 
-int LZ4_compress        (const char* source, char* dest, int inputSize);
-int LZ4_decompress_safe (const char* source, char* dest, int inputSize, int maxOutputSize);
+int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
+int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
 
 
 /*
 /*
-LZ4_compress() :
-    Compresses 'inputSize' bytes from 'source' into 'dest'.
-    Destination buffer must be already allocated,
-    and must be sized to handle worst cases situations (input data not compressible)
-    Worst case size evaluation is provided by function LZ4_compressBound()
-    inputSize : Max supported value is ~1.9GB
-    return : the number of bytes written in buffer dest
-             or 0 if the compression fails
+LZ4_compress_default() :
+    Compresses 'sourceSize' bytes from buffer 'source'
+    into already allocated 'dest' buffer of size 'maxDestSize'.
+    Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
+    It also runs faster, so it's a recommended setting.
+    If the function cannot compress 'source' into a more limited 'dest' budget,
+    compression stops *immediately*, and the function result is zero.
+    As a consequence, 'dest' content is not valid.
+    This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
+        sourceSize  : Max supported value is LZ4_MAX_INPUT_VALUE
+        maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
+        return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
+              or 0 if compression fails
 
 
 LZ4_decompress_safe() :
 LZ4_decompress_safe() :
-    maxOutputSize : is the size of the destination buffer (which must be already allocated)
-    return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize)
+    compressedSize : is the precise full size of the compressed block.
+    maxDecompressedSize : is the size of destination buffer, which must be already allocated.
+    return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
+             If destination buffer is not large enough, decoding will stop and output an error code (<0).
              If the source stream is detected malformed, the function will stop decoding and return a negative result.
              If the source stream is detected malformed, the function will stop decoding and return a negative result.
-             This function is protected against buffer overflow exploits (never writes outside of output buffer, and never reads outside of input buffer). Therefore, it is protected against malicious data packets
+             This function is protected against buffer overflow exploits, including malicious data packets.
+             It never writes outside output buffer, nor reads outside input buffer.
 */
 */
 
 
 
 
-//****************************
-// Advanced Functions
-//****************************
-
-static inline int LZ4_compressBound(int isize)   { return ((isize) + ((isize)/255) + 16); }
-#define           LZ4_COMPRESSBOUND(    isize)            ((isize) + ((isize)/255) + 16)
+/**************************************
+*  Advanced Functions
+**************************************/
+#define LZ4_MAX_INPUT_SIZE        0x7E000000   /* 2 113 929 216 bytes */
+#define LZ4_COMPRESSBOUND(isize)  ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
 
 
 /*
 /*
 LZ4_compressBound() :
 LZ4_compressBound() :
-    Provides the maximum size that LZ4 may output in a "worst case" scenario (input data not compressible)
-    primarily useful for memory allocation of output buffer.
-    inline function is recommended for the general case,
-    macro is also provided when result needs to be evaluated at compilation (such as stack memory allocation).
-
-    isize  : is the input size. Max supported value is ~1.9GB
-    return : maximum output size in a "worst case" scenario
-    note : this function is limited by "int" range (2^31-1)
+    Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
+    This function is primarily useful for memory allocation purposes (destination buffer size).
+    Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
+    Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
+        inputSize  : max supported value is LZ4_MAX_INPUT_SIZE
+        return : maximum output size in a "worst case" scenario
+              or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
 */
 */
+int LZ4_compressBound(int inputSize);
 
 
+/*
+LZ4_compress_fast() :
+    Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
+    The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
+    It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
+    An acceleration value of "1" is the same as regular LZ4_compress_default()
+    Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
+*/
+int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
 
 
-int LZ4_compress_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
 
 
 /*
 /*
-LZ4_compress_limitedOutput() :
-    Compress 'inputSize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'.
-    If it cannot achieve it, compression will stop, and result of the function will be zero.
-    This function never writes outside of provided output buffer.
-
-    inputSize  : Max supported value is ~1.9GB
-    maxOutputSize : is the size of the destination buffer (which must be already allocated)
-    return : the number of bytes written in buffer 'dest'
-             or 0 if the compression fails
+LZ4_compress_fast_extState() :
+    Same compression function, just using an externally allocated memory space to store compression state.
+    Use LZ4_sizeofState() to know how much memory must be allocated,
+    and allocate it on 8-bytes boundaries (using malloc() typically).
+    Then, provide it as 'void* state' to compression function.
 */
 */
+int LZ4_sizeofState(void);
+int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
+
 
 
+/*
+LZ4_compress_destSize() :
+    Reverse the logic, by compressing as much data as possible from 'source' buffer
+    into already allocated buffer 'dest' of size 'targetDestSize'.
+    This function either compresses the entire 'source' content into 'dest' if it's large enough,
+    or fill 'dest' buffer completely with as much data as possible from 'source'.
+        *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
+                         New value is necessarily <= old value.
+        return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
+              or 0 if compression fails
+*/
+int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
 
 
-int LZ4_decompress_fast (const char* source, char* dest, int outputSize);
 
 
 /*
 /*
 LZ4_decompress_fast() :
 LZ4_decompress_fast() :
-    outputSize : is the original (uncompressed) size
+    originalSize : is the original and therefore uncompressed size
     return : the number of bytes read from the source buffer (in other words, the compressed size)
     return : the number of bytes read from the source buffer (in other words, the compressed size)
-             If the source stream is malformed, the function will stop decoding and return a negative result.
-    note : This function is a bit faster than LZ4_decompress_safe()
-           This function never writes outside of output buffers, but may read beyond input buffer in case of malicious data packet.
-           Use this function preferably into a trusted environment (data to decode comes from a trusted source).
-           Destination buffer must be already allocated. Its size must be a minimum of 'outputSize' bytes.
+             If the source stream is detected malformed, the function will stop decoding and return a negative result.
+             Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
+    note : This function fully respect memory boundaries for properly formed compressed data.
+           It is a bit faster than LZ4_decompress_safe().
+           However, it does not provide any protection against intentionally modified data stream (malicious input).
+           Use this function in trusted environment only (data to decode comes from a trusted source).
 */
 */
-
-int LZ4_decompress_safe_partial (const char* source, char* dest, int inputSize, int targetOutputSize, int maxOutputSize);
+int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
 
 
 /*
 /*
 LZ4_decompress_safe_partial() :
 LZ4_decompress_safe_partial() :
-    This function decompress a compressed block of size 'inputSize' at position 'source'
-    into output buffer 'dest' of size 'maxOutputSize'.
-    The function stops decompressing operation as soon as 'targetOutputSize' has been reached,
+    This function decompress a compressed block of size 'compressedSize' at position 'source'
+    into destination buffer 'dest' of size 'maxDecompressedSize'.
+    The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
     reducing decompression time.
     reducing decompression time.
-    return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize)
+    return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
        Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
        Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
              Always control how many bytes were decoded.
              Always control how many bytes were decoded.
              If the source stream is detected malformed, the function will stop decoding and return a negative result.
              If the source stream is detected malformed, the function will stop decoding and return a negative result.
              This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
              This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
 */
 */
+int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
 
 
 
 
-//****************************
-// Stream Functions
-//****************************
-
-void* LZ4_create (const char* inputBuffer);
-int   LZ4_compress_continue (void* LZ4_Data, const char* source, char* dest, int inputSize);
-int   LZ4_compress_limitedOutput_continue (void* LZ4_Data, const char* source, char* dest, int inputSize, int maxOutputSize);
-char* LZ4_slideInputBuffer (void* LZ4_Data);
-int   LZ4_free (void* LZ4_Data);
-
-/* 
-These functions allow the compression of dependent blocks, where each block benefits from prior 64 KB within preceding blocks.
-In order to achieve this, it is necessary to start creating the LZ4 Data Structure, thanks to the function :
-
-void* LZ4_create (const char* inputBuffer);
-The result of the function is the (void*) pointer on the LZ4 Data Structure.
-This pointer will be needed in all other functions.
-If the pointer returned is NULL, then the allocation has failed, and compression must be aborted.
-The only parameter 'const char* inputBuffer' must, obviously, point at the beginning of input buffer.
-The input buffer must be already allocated, and size at least 192KB.
-'inputBuffer' will also be the 'const char* source' of the first block.
+/***********************************************
+*  Streaming Compression Functions
+***********************************************/
+#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
+#define LZ4_STREAMSIZE     (LZ4_STREAMSIZE_U64 * sizeof(long long))
+/*
+ * LZ4_stream_t
+ * information structure to track an LZ4 stream.
+ * important : init this structure content before first use !
+ * note : only allocated directly the structure if you are statically linking LZ4
+ *        If you are using liblz4 as a DLL, please use below construction methods instead.
+ */
+typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t;
 
 
-All blocks are expected to lay next to each other within the input buffer, starting from 'inputBuffer'.
-To compress each block, use either LZ4_compress_continue() or LZ4_compress_limitedOutput_continue().
-Their behavior are identical to LZ4_compress() or LZ4_compress_limitedOutput(), 
-but require the LZ4 Data Structure as their first argument, and check that each block starts right after the previous one.
-If next block does not begin immediately after the previous one, the compression will fail (return 0).
+/*
+ * LZ4_resetStream
+ * Use this function to init an allocated LZ4_stream_t structure
+ */
+void LZ4_resetStream (LZ4_stream_t* streamPtr);
 
 
-When it's no longer possible to lay the next block after the previous one (not enough space left into input buffer), a call to : 
-char* LZ4_slideInputBuffer(void* LZ4_Data);
-must be performed. It will typically copy the latest 64KB of input at the beginning of input buffer.
-Note that, for this function to work properly, minimum size of an input buffer must be 192KB.
-==> The memory position where the next input data block must start is provided as the result of the function.
+/*
+ * LZ4_createStream will allocate and initialize an LZ4_stream_t structure
+ * LZ4_freeStream releases its memory.
+ * In the context of a DLL (liblz4), please use these methods rather than the static struct.
+ * They are more future proof, in case of a change of LZ4_stream_t size.
+ */
+LZ4_stream_t* LZ4_createStream(void);
+int           LZ4_freeStream (LZ4_stream_t* streamPtr);
 
 
-Compression can then resume, using LZ4_compress_continue() or LZ4_compress_limitedOutput_continue(), as usual.
+/*
+ * LZ4_loadDict
+ * Use this function to load a static dictionary into LZ4_stream.
+ * Any previous data will be forgotten, only 'dictionary' will remain in memory.
+ * Loading a size of 0 is allowed.
+ * Return : dictionary size, in bytes (necessarily <= 64 KB)
+ */
+int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
 
 
-When compression is completed, a call to LZ4_free() will release the memory used by the LZ4 Data Structure.
-*/
+/*
+ * LZ4_compress_fast_continue
+ * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
+ * Important : Previous data blocks are assumed to still be present and unmodified !
+ * 'dst' buffer must be already allocated.
+ * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
+ * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
+ */
+int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
 
 
+/*
+ * LZ4_saveDict
+ * If previously compressed data block is not guaranteed to remain available at its memory location
+ * save it into a safer place (char* safeBuffer)
+ * Note : you don't need to call LZ4_loadDict() afterwards,
+ *        dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
+ * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
+ */
+int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
+
+
+/************************************************
+*  Streaming Decompression Functions
+************************************************/
+
+#define LZ4_STREAMDECODESIZE_U64  4
+#define LZ4_STREAMDECODESIZE     (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
+typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t;
+/*
+ * LZ4_streamDecode_t
+ * information structure to track an LZ4 stream.
+ * init this structure content using LZ4_setStreamDecode or memset() before first use !
+ *
+ * In the context of a DLL (liblz4) please prefer usage of construction methods below.
+ * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future.
+ * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure
+ * LZ4_freeStreamDecode releases its memory.
+ */
+LZ4_streamDecode_t* LZ4_createStreamDecode(void);
+int                 LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
 
 
-int LZ4_decompress_safe_withPrefix64k (const char* source, char* dest, int inputSize, int maxOutputSize);
-int LZ4_decompress_fast_withPrefix64k (const char* source, char* dest, int outputSize);
+/*
+ * LZ4_setStreamDecode
+ * Use this function to instruct where to find the dictionary.
+ * Setting a size of 0 is allowed (same effect as reset).
+ * Return : 1 if OK, 0 if error
+ */
+int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
 
 
 /*
 /*
-*_withPrefix64k() :
-    These decoding functions work the same as their "normal name" versions,
-    but can use up to 64KB of data in front of 'char* dest'.
-    These functions are necessary to decode inter-dependant blocks.
+*_continue() :
+    These decoding functions allow decompression of multiple blocks in "streaming" mode.
+    Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
+    In the case of a ring buffers, decoding buffer must be either :
+    - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
+      In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
+    - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
+      maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
+      In which case, encoding and decoding buffers do not need to be synchronized,
+      and encoding ring buffer can have any size, including small ones ( < 64 KB).
+    - _At least_ 64 KB + 8 bytes + maxBlockSize.
+      In which case, encoding and decoding buffers do not need to be synchronized,
+      and encoding ring buffer can have any size, including larger than decoding buffer.
+    Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
+    and indicate where it is saved using LZ4_setStreamDecode()
 */
 */
+int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
+int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
 
 
 
 
-//****************************
-// Obsolete Functions
-//****************************
-
-static inline int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); }
-static inline int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); }
-
 /*
 /*
-These functions are deprecated and should no longer be used.
-They are provided here for compatibility with existing user programs.
+Advanced decoding functions :
+*_usingDict() :
+    These decoding functions work the same as
+    a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
+    They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
 */
 */
-
+int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
+int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
+
+
+
+/**************************************
+*  Obsolete Functions
+**************************************/
+/* Deprecate Warnings */
+/* Should these warnings messages be a problem,
+   it is generally possible to disable them,
+   with -Wno-deprecated-declarations for gcc
+   or _CRT_SECURE_NO_WARNINGS in Visual for example.
+   You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
+#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
+#  define LZ4_DEPRECATE_WARNING_DEFBLOCK
+#  define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#  if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
+#    define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
+#  elif (LZ4_GCC_VERSION >= 301)
+#    define LZ4_DEPRECATED(message) __attribute__((deprecated))
+#  elif defined(_MSC_VER)
+#    define LZ4_DEPRECATED(message) __declspec(deprecated(message))
+#  else
+#    pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
+#    define LZ4_DEPRECATED(message)
+#  endif
+#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */
+
+/* Obsolete compression functions */
+/* These functions are planned to start generate warnings by r131 approximately */
+int LZ4_compress               (const char* source, char* dest, int sourceSize);
+int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
+int LZ4_compress_withState               (void* state, const char* source, char* dest, int inputSize);
+int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
+int LZ4_compress_continue                (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
+int LZ4_compress_limitedOutput_continue  (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
+
+/* Obsolete decompression functions */
+/* These function names are completely deprecated and must no longer be used.
+   They are only provided here for compatibility with older programs.
+    - LZ4_uncompress is the same as LZ4_decompress_fast
+    - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
+   These function prototypes are now disabled; uncomment them only if you really need them.
+   It is highly recommended to stop using these prototypes and migrate to maintained ones */
+/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
+/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
+
+/* Obsolete streaming functions; use new streaming interface whenever possible */
+LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer);
+LZ4_DEPRECATED("use LZ4_createStream() instead") int   LZ4_sizeofStreamState(void);
+LZ4_DEPRECATED("use LZ4_resetStream() instead")  int   LZ4_resetStreamState(void* state, char* inputBuffer);
+LZ4_DEPRECATED("use LZ4_saveDict() instead")     char* LZ4_slideInputBuffer (void* state);
+
+/* Obsolete streaming decoding functions */
+LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
+LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
 
 
 
 
 #if defined (__cplusplus)
 #if defined (__cplusplus)

+ 0 - 120
Source/ThirdParty/LZ4/lz4_format_description.txt

@@ -1,120 +0,0 @@
-LZ4 Format Description
-Last revised: 2012-02-27
-Author : Y. Collet
-
-
-
-This small specification intents to provide enough information
-to anyone willing to produce LZ4-compatible compressed data blocks
-using any programming language.
-
-LZ4 is an LZ77-type compressor with a fixed, byte-oriented encoding.
-The most important design principle behind LZ4 is simplicity.
-It helps to create an easy to read and maintain source code.
-It also helps later on for optimisations, compactness, and speed.
-There is no entropy encoder backend nor framing layer.
-The latter is assumed to be handled by other parts of the system.
-
-This document only describes the format,
-not how the LZ4 compressor nor decompressor actually work.
-The correctness of the decompressor should not depend
-on implementation details of the compressor, and vice versa.
-
-
-
--- Compressed block format --
-
-An LZ4 compressed block is composed of sequences.
-Schematically, a sequence is a suite of literals, followed by a match copy.
-
-Each sequence starts with a token.
-The token is a one byte value, separated into two 4-bits fields.
-Therefore each field ranges from 0 to 15.
-
-
-The first field uses the 4 high-bits of the token.
-It provides the length of literals to follow.
-(Note : a literal is a not-compressed byte).
-If the field value is 0, then there is no literal.
-If it is 15, then we need to add some more bytes to indicate the full length.
-Each additionnal byte then represent a value from 0 to 255,
-which is added to the previous value to produce a total length.
-When the byte value is 255, another byte is output.
-There can be any number of bytes following the token. There is no "size limit".
-(Sidenote this is why a not-compressible input block is expanded by 0.4%).
-
-Example 1 : A length of 48 will be represented as :
-- 15 : value for the 4-bits High field
-- 33 : (=48-15) remaining length to reach 48
-
-Example 2 : A length of 280 will be represented as :
-- 15  : value for the 4-bits High field
-- 255 : following byte is maxed, since 280-15 >= 255
-- 10  : (=280 - 15 - 255) ) remaining length to reach 280
-
-Example 3 : A length of 15 will be represented as :
-- 15 : value for the 4-bits High field
-- 0  : (=15-15) yes, the zero must be output
-
-Following the token and optional length bytes, are the literals themselves.
-They are exactly as numerous as previously decoded (length of literals).
-It's possible that there are zero literal.
-
-
-Following the literals is the match copy operation.
-
-It starts by the offset.
-This is a 2 bytes value, in little endian format.
-
-The offset represents the position of the match to be copied from.
-1 means "current position - 1 byte".
-The maximum offset value is 65535, 65536 cannot be coded.
-Note that 0 is an invalid value, not used. 
-
-Then we need to extract the match length.
-For this, we use the second token field, the low 4-bits.
-Value, obviously, ranges from 0 to 15.
-However here, 0 means that the copy operation will be minimal.
-The minimum length of a match, called minmatch, is 4. 
-As a consequence, a 0 value means 4 bytes, and a value of 15 means 19+ bytes.
-Similar to literal length, on reaching the highest possible value (15), 
-we output additional bytes, one at a time, with values ranging from 0 to 255.
-They are added to total to provide the final match length.
-A 255 value means there is another byte to read and add.
-There is no limit to the number of optional bytes that can be output this way.
-(This points towards a maximum achievable compression ratio of ~250).
-
-With the offset and the matchlength,
-the decoder can now proceed to copy the data from the already decoded buffer.
-On decoding the matchlength, we reach the end of the compressed sequence,
-and therefore start another one.
-
-
--- Parsing restrictions --
-
-There are specific parsing rules to respect in order to remain compatible
-with assumptions made by the decoder :
-1) The last 5 bytes are always literals
-2) The last match must start at least 12 bytes before end of block
-Consequently, a block with less than 13 bytes cannot be compressed.
-These rules are in place to ensure that the decoder
-will never read beyond the input buffer, nor write beyond the output buffer.
-
-Note that the last sequence is also incomplete,
-and stops right after literals.
-
-
--- Additional notes --
-
-There is no assumption nor limits to the way the compressor
-searches and selects matches within the source data block.
-It could be a fast scan, a multi-probe, a full search using BST,
-standard hash chains or MMC, well whatever.
-
-Advanced parsing strategies can also be implemented, such as lazy match,
-or full optimal parsing.
-
-All these trade-off offer distinctive speed/memory/compression advantages.
-Whatever the method used by the compressor, its result will be decodable
-by any LZ4 decoder if it follows the format specification described above.
-

+ 445 - 531
Source/ThirdParty/LZ4/lz4hc.c

@@ -1,541 +1,279 @@
 /*
 /*
-   LZ4 HC - High Compression Mode of LZ4
-   Copyright (C) 2011-2013, Yann Collet.
-   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
-   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.
-
-   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
-   OWNER 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.
-
-   You can contact the author at :
-   - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
-   - LZ4 source repository : http://code.google.com/p/lz4/
+    LZ4 HC - High Compression Mode of LZ4
+    Copyright (C) 2011-2015, Yann Collet.
+
+    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+    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.
+
+    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
+    OWNER 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.
+
+    You can contact the author at :
+       - LZ4 source repository : https://github.com/Cyan4973/lz4
+       - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
 */
 */
 
 
-//**************************************
-// Memory routines
-//**************************************
-#include <stdlib.h>   // calloc, free
-#define ALLOCATOR(s)  calloc(1,s)
-#define FREEMEM       free
-#include <string.h>   // memset, memcpy
-#define MEM_INIT      memset
-
-
-//**************************************
-// CPU Feature Detection
-//**************************************
-// 32 or 64 bits ?
-#if (defined(__x86_64__) || defined(_M_X64) || defined(_WIN64) \
-  || defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) \
-  || defined(__64BIT__) || defined(_LP64) || defined(__LP64__) \
-  || defined(__ia64) || defined(__itanium__) || defined(_M_IA64) )   // Detects 64 bits mode
-#  define LZ4_ARCH64 1
-#else
-#  define LZ4_ARCH64 0
-#endif
-
-// Little Endian or Big Endian ?
-// Overwrite the #define below if you know your architecture endianess
-#if defined (__GLIBC__)
-#  include <endian.h>
-#  if (__BYTE_ORDER == __BIG_ENDIAN)
-#     define LZ4_BIG_ENDIAN 1
-#  endif
-#elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN))
-#  define LZ4_BIG_ENDIAN 1
-#elif defined(__sparc) || defined(__sparc__) \
-   || defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \
-   || defined(__hpux)  || defined(__hppa) \
-   || defined(_MIPSEB) || defined(__s390__)
-#  define LZ4_BIG_ENDIAN 1
-#else
-// Little Endian assumed. PDP Endian and other very rare endian format are unsupported.
-#endif
-
-// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
-// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected
-// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance
-#if defined(__ARM_FEATURE_UNALIGNED)
-#  define LZ4_FORCE_UNALIGNED_ACCESS 1
-#endif
-
-// Define this parameter if your target system or compiler does not support hardware bit count
-#if defined(_MSC_VER) && defined(_WIN32_WCE)            // Visual Studio for Windows CE does not support Hardware bit count
-#  define LZ4_FORCE_SW_BITCOUNT
-#endif
-
-
-//**************************************
-// Compiler Options
-//**************************************
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   // C99
-  /* "restrict" is a known keyword */
-#else
-#  define restrict  // Disable restrict
-#endif
 
 
-#ifdef _MSC_VER    // Visual Studio
-#  define FORCE_INLINE static __forceinline
-#  include <intrin.h>                    // For Visual 2005
-#  if LZ4_ARCH64   // 64-bits
-#    pragma intrinsic(_BitScanForward64) // For Visual 2005
-#    pragma intrinsic(_BitScanReverse64) // For Visual 2005
-#  else            // 32-bits
-#    pragma intrinsic(_BitScanForward)   // For Visual 2005
-#    pragma intrinsic(_BitScanReverse)   // For Visual 2005
-#  endif
-#  pragma warning(disable : 4127)        // disable: C4127: conditional expression is constant
-#  pragma warning(disable : 4701)        // disable: C4701: potentially uninitialized local variable used
-#else 
-#  ifdef __GNUC__
-#    define FORCE_INLINE static inline __attribute__((always_inline))
-#  else
-#    define FORCE_INLINE static inline
-#  endif
-#endif
 
 
-#ifdef _MSC_VER  // Visual Studio
-#  define lz4_bswap16(x) _byteswap_ushort(x)
-#else
-#  define lz4_bswap16(x)  ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)))
-#endif
+/**************************************
+*  Tuning Parameter
+**************************************/
+static const int LZ4HC_compressionLevel_default = 9;
 
 
 
 
-//**************************************
-// Includes
-//**************************************
+/**************************************
+*  Includes
+**************************************/
 #include "lz4hc.h"
 #include "lz4hc.h"
-#include "lz4.h"
-
-
-//**************************************
-// Basic Types
-//**************************************
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   // C99
-# include <stdint.h>
-  typedef uint8_t  BYTE;
-  typedef uint16_t U16;
-  typedef uint32_t U32;
-  typedef  int32_t S32;
-  typedef uint64_t U64;
-#else
-  typedef unsigned char       BYTE;
-  typedef unsigned short      U16;
-  typedef unsigned int        U32;
-  typedef   signed int        S32;
-  typedef unsigned long long  U64;
-#endif
 
 
-#if defined(__GNUC__)  && !defined(LZ4_FORCE_UNALIGNED_ACCESS)
-#  define _PACKED __attribute__ ((packed))
-#else
-#  define _PACKED
-#endif
 
 
-#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__)
-#  ifdef __IBMC__
-#    pragma pack(1)
-#  else
-#    pragma pack(push, 1)
-#  endif
+/**************************************
+*  Local Compiler Options
+**************************************/
+#if defined(__GNUC__)
+#  pragma GCC diagnostic ignored "-Wunused-function"
 #endif
 #endif
 
 
-typedef struct _U16_S { U16 v; } _PACKED U16_S;
-typedef struct _U32_S { U32 v; } _PACKED U32_S;
-typedef struct _U64_S { U64 v; } _PACKED U64_S;
-
-#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__)
-#  pragma pack(pop)
+#if defined (__clang__)
+#  pragma clang diagnostic ignored "-Wunused-function"
 #endif
 #endif
 
 
-#define A64(x) (((U64_S *)(x))->v)
-#define A32(x) (((U32_S *)(x))->v)
-#define A16(x) (((U16_S *)(x))->v)
 
 
+/**************************************
+*  Common LZ4 definition
+**************************************/
+#define LZ4_COMMONDEFS_ONLY
+#include "lz4.c"
 
 
-//**************************************
-// Constants
-//**************************************
-#define MINMATCH 4
 
 
+/**************************************
+*  Local Constants
+**************************************/
 #define DICTIONARY_LOGSIZE 16
 #define DICTIONARY_LOGSIZE 16
 #define MAXD (1<<DICTIONARY_LOGSIZE)
 #define MAXD (1<<DICTIONARY_LOGSIZE)
-#define MAXD_MASK ((U32)(MAXD - 1))
-#define MAX_DISTANCE (MAXD - 1)
+#define MAXD_MASK (MAXD - 1)
 
 
 #define HASH_LOG (DICTIONARY_LOGSIZE-1)
 #define HASH_LOG (DICTIONARY_LOGSIZE-1)
 #define HASHTABLESIZE (1 << HASH_LOG)
 #define HASHTABLESIZE (1 << HASH_LOG)
 #define HASH_MASK (HASHTABLESIZE - 1)
 #define HASH_MASK (HASHTABLESIZE - 1)
 
 
-#define MAX_NB_ATTEMPTS 256
-
-#define ML_BITS  4
-#define ML_MASK  (size_t)((1U<<ML_BITS)-1)
-#define RUN_BITS (8-ML_BITS)
-#define RUN_MASK ((1U<<RUN_BITS)-1)
-
-#define COPYLENGTH 8
-#define LASTLITERALS 5
-#define MFLIMIT (COPYLENGTH+MINMATCH)
-#define MINLENGTH (MFLIMIT+1)
 #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
 #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
 
 
-#define KB *(1U<<10)
-#define MB *(1U<<20)
-#define GB *(1U<<30)
-
-
-//**************************************
-// Architecture-specific macros
-//**************************************
-#if LZ4_ARCH64   // 64-bit
-#  define STEPSIZE 8
-#  define LZ4_COPYSTEP(s,d)     A64(d) = A64(s); d+=8; s+=8;
-#  define LZ4_COPYPACKET(s,d)   LZ4_COPYSTEP(s,d)
-#  define UARCH U64
-#  define AARCH A64
-#  define HTYPE                 U32
-#  define INITBASE(b,s)         const BYTE* const b = s
-#else   // 32-bit
-#  define STEPSIZE 4
-#  define LZ4_COPYSTEP(s,d)     A32(d) = A32(s); d+=4; s+=4;
-#  define LZ4_COPYPACKET(s,d)   LZ4_COPYSTEP(s,d); LZ4_COPYSTEP(s,d);
-#  define UARCH U32
-#  define AARCH A32
-//#  define HTYPE                 const BYTE*
-//#  define INITBASE(b,s)         const int b = 0
-#  define HTYPE                 U32
-#  define INITBASE(b,s)         const BYTE* const b = s
-#endif
-
-#if defined(LZ4_BIG_ENDIAN)
-#  define LZ4_READ_LITTLEENDIAN_16(d,s,p) { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }
-#  define LZ4_WRITE_LITTLEENDIAN_16(p,i)  { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p+=2; }
-#else   // Little Endian
-#  define LZ4_READ_LITTLEENDIAN_16(d,s,p) { d = (s) - A16(p); }
-#  define LZ4_WRITE_LITTLEENDIAN_16(p,v)  { A16(p) = v; p+=2; }
-#endif
+static const int g_maxCompressionLevel = 16;
 
 
 
 
-//************************************************************
-// Local Types
-//************************************************************
-typedef struct 
+/**************************************
+*  Local Types
+**************************************/
+typedef struct
 {
 {
-    const BYTE* inputBuffer;
-    const BYTE* base;
-    const BYTE* end;
-    HTYPE hashTable[HASHTABLESIZE];
-    U16 chainTable[MAXD];
-    const BYTE* nextToUpdate;
+    U32   hashTable[HASHTABLESIZE];
+    U16   chainTable[MAXD];
+    const BYTE* end;        /* next block here to continue on current prefix */
+    const BYTE* base;       /* All index relative to this position */
+    const BYTE* dictBase;   /* alternate base for extDict */
+    BYTE* inputBuffer;      /* deprecated */
+    U32   dictLimit;        /* below that point, need extDict */
+    U32   lowLimit;         /* below that point, no more dict */
+    U32   nextToUpdate;     /* index from which to continue dictionary update */
+    U32   compressionLevel;
 } LZ4HC_Data_Structure;
 } LZ4HC_Data_Structure;
 
 
 
 
-//**************************************
-// Macros
-//**************************************
-#define LZ4_WILDCOPY(s,d,e)    do { LZ4_COPYPACKET(s,d) } while (d<e);
-#define LZ4_BLINDCOPY(s,d,l)   { BYTE* e=d+l; LZ4_WILDCOPY(s,d,e); d=e; }
+/**************************************
+*  Local Macros
+**************************************/
 #define HASH_FUNCTION(i)       (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))
 #define HASH_FUNCTION(i)       (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))
-#define HASH_VALUE(p)          HASH_FUNCTION(A32(p))
-#define HASH_POINTER(p)        (HashTable[HASH_VALUE(p)] + base)
-#define DELTANEXT(p)           chainTable[(size_t)(p) & MAXD_MASK] 
-#define GETNEXT(p)             ((p) - (size_t)DELTANEXT(p))
-
-
-//**************************************
-// Private functions
-//**************************************
-#if LZ4_ARCH64
-
-FORCE_INLINE int LZ4_NbCommonBytes (register U64 val)
-{
-#if defined(LZ4_BIG_ENDIAN)
-#  if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
-    unsigned long r = 0;
-    _BitScanReverse64( &r, val );
-    return (int)(r>>3);
-#  elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
-    return (__builtin_clzll(val) >> 3); 
-#  else
-    int r;
-    if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
-    if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
-    r += (!val);
-    return r;
-#  endif
-#else
-#  if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
-    unsigned long r = 0;
-    _BitScanForward64( &r, val );
-    return (int)(r>>3);
-#  elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
-    return (__builtin_ctzll(val) >> 3); 
-#  else
-    static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
-    return DeBruijnBytePos[((U64)((val & -val) * 0x0218A392CDABBD3F)) >> 58];
-#  endif
-#endif
-}
-
-#else
+//#define DELTANEXTU16(p)        chainTable[(p) & MAXD_MASK]   /* flexible, MAXD dependent */
+#define DELTANEXTU16(p)        chainTable[(U16)(p)]   /* faster */
 
 
-FORCE_INLINE int LZ4_NbCommonBytes (register U32 val)
-{
-#if defined(LZ4_BIG_ENDIAN)
-#  if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
-    unsigned long r;
-    _BitScanReverse( &r, val );
-    return (int)(r>>3);
-#  elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
-    return (__builtin_clz(val) >> 3); 
-#  else
-    int r;
-    if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
-    r += (!val);
-    return r;
-#  endif
-#else
-#  if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
-    unsigned long r;
-    _BitScanForward( &r, val );
-    return (int)(r>>3);
-#  elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
-    return (__builtin_ctz(val) >> 3); 
-#  else
-    static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
-    return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
-#  endif
-#endif
-}
+static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
 
 
-#endif
 
 
 
 
-FORCE_INLINE void LZ4_initHC (LZ4HC_Data_Structure* hc4, const BYTE* base)
+/**************************************
+*  HC Compression
+**************************************/
+static void LZ4HC_init (LZ4HC_Data_Structure* hc4, const BYTE* start)
 {
 {
     MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
     MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
     MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
     MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
-    hc4->nextToUpdate = base + 1;
-    hc4->base = base;
-    hc4->inputBuffer = base;
-    hc4->end = base;
-}
-
-
-void* LZ4_createHC (const char* inputBuffer)
-{
-    void* hc4 = ALLOCATOR(sizeof(LZ4HC_Data_Structure));
-    LZ4_initHC ((LZ4HC_Data_Structure*)hc4, (const BYTE*)inputBuffer);
-    return hc4;
+    hc4->nextToUpdate = 64 KB;
+    hc4->base = start - 64 KB;
+    hc4->end = start;
+    hc4->dictBase = start - 64 KB;
+    hc4->dictLimit = 64 KB;
+    hc4->lowLimit = 64 KB;
 }
 }
 
 
 
 
-int LZ4_freeHC (void* LZ4HC_Data)
-{
-    FREEMEM(LZ4HC_Data);
-    return (0);
-}
-
-
-// Update chains up to ip (excluded)
+/* Update chains up to ip (excluded) */
 FORCE_INLINE void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip)
 FORCE_INLINE void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip)
 {
 {
-    U16*   chainTable = hc4->chainTable;
-    HTYPE* HashTable  = hc4->hashTable;
-    INITBASE(base,hc4->base);
-
-    while(hc4->nextToUpdate < ip)
-    {
-        const BYTE* const p = hc4->nextToUpdate;
-        size_t delta = (p) - HASH_POINTER(p); 
-        if (delta>MAX_DISTANCE) delta = MAX_DISTANCE; 
-        DELTANEXT(p) = (U16)delta; 
-        HashTable[HASH_VALUE(p)] = (HTYPE)((p) - base);
-        hc4->nextToUpdate++;
-    }
-}
-
+    U16* chainTable = hc4->chainTable;
+    U32* HashTable  = hc4->hashTable;
+    const BYTE* const base = hc4->base;
+    const U32 target = (U32)(ip - base);
+    U32 idx = hc4->nextToUpdate;
 
 
-char* LZ4_slideInputBufferHC(void* LZ4HC_Data)
-{
-    LZ4HC_Data_Structure* hc4 = (LZ4HC_Data_Structure*)LZ4HC_Data;
-    U32 distance = (U32)(hc4->end - hc4->inputBuffer) - 64 KB;
-    distance = (distance >> 16) << 16;   // Must be a multiple of 64 KB
-    LZ4HC_Insert(hc4, hc4->end - MINMATCH);
-    memcpy((void*)(hc4->end - 64 KB - distance), (const void*)(hc4->end - 64 KB), 64 KB);
-    hc4->nextToUpdate -= distance;
-    hc4->base -= distance;
-    if ((U32)(hc4->inputBuffer - hc4->base) > 1 GB + 64 KB)   // Avoid overflow
+    while(idx < target)
     {
     {
-        int i;
-        hc4->base += 1 GB;
-        for (i=0; i<HASHTABLESIZE; i++) hc4->hashTable[i] -= 1 GB;
+        U32 h = LZ4HC_hashPtr(base+idx);
+        size_t delta = idx - HashTable[h];
+        if (delta>MAX_DISTANCE) delta = MAX_DISTANCE;
+        DELTANEXTU16(idx) = (U16)delta;
+        HashTable[h] = idx;
+        idx++;
     }
     }
-    hc4->end -= distance;
-    return (char*)(hc4->end);
-}
-
-
-FORCE_INLINE size_t LZ4HC_CommonLength (const BYTE* p1, const BYTE* p2, const BYTE* const matchlimit)
-{
-    const BYTE* p1t = p1;
 
 
-    while (p1t<matchlimit-(STEPSIZE-1))
-    {
-        UARCH diff = AARCH(p2) ^ AARCH(p1t);
-        if (!diff) { p1t+=STEPSIZE; p2+=STEPSIZE; continue; }
-        p1t += LZ4_NbCommonBytes(diff);
-        return (p1t - p1);
-    }
-    if (LZ4_ARCH64) if ((p1t<(matchlimit-3)) && (A32(p2) == A32(p1t))) { p1t+=4; p2+=4; }
-    if ((p1t<(matchlimit-1)) && (A16(p2) == A16(p1t))) { p1t+=2; p2+=2; }
-    if ((p1t<matchlimit) && (*p2 == *p1t)) p1t++;
-    return (p1t - p1);
+    hc4->nextToUpdate = target;
 }
 }
 
 
 
 
-FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4, const BYTE* ip, const BYTE* const matchlimit, const BYTE** matchpos)
+FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4,   /* Index table will be updated */
+                                               const BYTE* ip, const BYTE* const iLimit,
+                                               const BYTE** matchpos,
+                                               const int maxNbAttempts)
 {
 {
     U16* const chainTable = hc4->chainTable;
     U16* const chainTable = hc4->chainTable;
-    HTYPE* const HashTable = hc4->hashTable;
-    const BYTE* ref;
-    INITBASE(base,hc4->base);
-    int nbAttempts=MAX_NB_ATTEMPTS;
-    size_t repl=0, ml=0;
-    U16 delta=0;  // useless assignment, to remove an uninitialization warning
-
-    // HC4 match finder
+    U32* const HashTable = hc4->hashTable;
+    const BYTE* const base = hc4->base;
+    const BYTE* const dictBase = hc4->dictBase;
+    const U32 dictLimit = hc4->dictLimit;
+    const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
+    U32 matchIndex;
+    const BYTE* match;
+    int nbAttempts=maxNbAttempts;
+    size_t ml=0;
+
+    /* HC4 match finder */
     LZ4HC_Insert(hc4, ip);
     LZ4HC_Insert(hc4, ip);
-    ref = HASH_POINTER(ip);
-
-#define REPEAT_OPTIMIZATION
-#ifdef REPEAT_OPTIMIZATION
-    // Detect repetitive sequences of length <= 4
-    if ((U32)(ip-ref) <= 4)        // potential repetition
-    {
-        if (A32(ref) == A32(ip))   // confirmed
-        {
-            delta = (U16)(ip-ref);
-            repl = ml  = LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit) + MINMATCH;
-            *matchpos = ref;
-        }
-        ref = GETNEXT(ref);
-    }
-#endif
+    matchIndex = HashTable[LZ4HC_hashPtr(ip)];
 
 
-    while (((U32)(ip-ref) <= MAX_DISTANCE) && (nbAttempts))
+    while ((matchIndex>=lowLimit) && (nbAttempts))
     {
     {
         nbAttempts--;
         nbAttempts--;
-        if (*(ref+ml) == *(ip+ml))
-        if (A32(ref) == A32(ip))
+        if (matchIndex >= dictLimit)
         {
         {
-            size_t mlt = LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit) + MINMATCH;
-            if (mlt > ml) { ml = mlt; *matchpos = ref; }
+            match = base + matchIndex;
+            if (*(match+ml) == *(ip+ml)
+                && (LZ4_read32(match) == LZ4_read32(ip)))
+            {
+                size_t mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
+                if (mlt > ml) { ml = mlt; *matchpos = match; }
+            }
         }
         }
-        ref = GETNEXT(ref);
-    }
-
-#ifdef REPEAT_OPTIMIZATION
-    // Complete table
-    if (repl)
-    {
-        const BYTE* ptr = ip;
-        const BYTE* end;
-
-        end = ip + repl - (MINMATCH-1);
-        while(ptr < end-delta)
+        else
         {
         {
-            DELTANEXT(ptr) = delta;    // Pre-Load
-            ptr++;
+            match = dictBase + matchIndex;
+            if (LZ4_read32(match) == LZ4_read32(ip))
+            {
+                size_t mlt;
+                const BYTE* vLimit = ip + (dictLimit - matchIndex);
+                if (vLimit > iLimit) vLimit = iLimit;
+                mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
+                if ((ip+mlt == vLimit) && (vLimit < iLimit))
+                    mlt += LZ4_count(ip+mlt, base+dictLimit, iLimit);
+                if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */
+            }
         }
         }
-        do
-        {
-            DELTANEXT(ptr) = delta;    
-            HashTable[HASH_VALUE(ptr)] = (HTYPE)((ptr) - base);     // Head of chain
-            ptr++;
-        } while(ptr < end);
-        hc4->nextToUpdate = end;
+        matchIndex -= DELTANEXTU16(matchIndex);
     }
     }
-#endif 
 
 
     return (int)ml;
     return (int)ml;
 }
 }
 
 
 
 
-FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (LZ4HC_Data_Structure* hc4, const BYTE* ip, const BYTE* startLimit, const BYTE* matchlimit, int longest, const BYTE** matchpos, const BYTE** startpos)
+FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
+    LZ4HC_Data_Structure* hc4,
+    const BYTE* const ip,
+    const BYTE* const iLowLimit,
+    const BYTE* const iHighLimit,
+    int longest,
+    const BYTE** matchpos,
+    const BYTE** startpos,
+    const int maxNbAttempts)
 {
 {
-    U16* const  chainTable = hc4->chainTable;
-    HTYPE* const HashTable = hc4->hashTable;
-    INITBASE(base,hc4->base);
-    const BYTE*  ref;
-    int nbAttempts = MAX_NB_ATTEMPTS;
-    int delta = (int)(ip-startLimit);
-
-    // First Match
+    U16* const chainTable = hc4->chainTable;
+    U32* const HashTable = hc4->hashTable;
+    const BYTE* const base = hc4->base;
+    const U32 dictLimit = hc4->dictLimit;
+    const BYTE* const lowPrefixPtr = base + dictLimit;
+    const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
+    const BYTE* const dictBase = hc4->dictBase;
+    U32   matchIndex;
+    int nbAttempts = maxNbAttempts;
+    int delta = (int)(ip-iLowLimit);
+
+
+    /* First Match */
     LZ4HC_Insert(hc4, ip);
     LZ4HC_Insert(hc4, ip);
-    ref = HASH_POINTER(ip);
+    matchIndex = HashTable[LZ4HC_hashPtr(ip)];
 
 
-    while (((U32)(ip-ref) <= MAX_DISTANCE) && (nbAttempts))
+    while ((matchIndex>=lowLimit) && (nbAttempts))
     {
     {
         nbAttempts--;
         nbAttempts--;
-        if (*(startLimit + longest) == *(ref - delta + longest))
-        if (A32(ref) == A32(ip))
+        if (matchIndex >= dictLimit)
         {
         {
-#if 1
-            const BYTE* reft = ref+MINMATCH;
-            const BYTE* ipt = ip+MINMATCH;
-            const BYTE* startt = ip;
+            const BYTE* matchPtr = base + matchIndex;
+            if (*(iLowLimit + longest) == *(matchPtr - delta + longest))
+                if (LZ4_read32(matchPtr) == LZ4_read32(ip))
+                {
+                    int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
+                    int back = 0;
 
 
-            while (ipt<matchlimit-(STEPSIZE-1))
-            {
-                UARCH diff = AARCH(reft) ^ AARCH(ipt);
-                if (!diff) { ipt+=STEPSIZE; reft+=STEPSIZE; continue; }
-                ipt += LZ4_NbCommonBytes(diff);
-                goto _endCount;
-            }
-            if (LZ4_ARCH64) if ((ipt<(matchlimit-3)) && (A32(reft) == A32(ipt))) { ipt+=4; reft+=4; }
-            if ((ipt<(matchlimit-1)) && (A16(reft) == A16(ipt))) { ipt+=2; reft+=2; }
-            if ((ipt<matchlimit) && (*reft == *ipt)) ipt++;
-_endCount:
-            reft = ref;
-#else
-            // Easier for code maintenance, but unfortunately slower too
-            const BYTE* startt = ip;
-            const BYTE* reft = ref;
-            const BYTE* ipt = ip + MINMATCH + LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit);
-#endif
+                    while ((ip+back>iLowLimit)
+                           && (matchPtr+back > lowPrefixPtr)
+                           && (ip[back-1] == matchPtr[back-1]))
+                            back--;
 
 
-            while ((startt>startLimit) && (reft > hc4->inputBuffer) && (startt[-1] == reft[-1])) {startt--; reft--;}
+                    mlt -= back;
 
 
-            if ((ipt-startt) > longest)
+                    if (mlt > longest)
+                    {
+                        longest = (int)mlt;
+                        *matchpos = matchPtr+back;
+                        *startpos = ip+back;
+                    }
+                }
+        }
+        else
+        {
+            const BYTE* matchPtr = dictBase + matchIndex;
+            if (LZ4_read32(matchPtr) == LZ4_read32(ip))
             {
             {
-                longest = (int)(ipt-startt);
-                *matchpos = reft;
-                *startpos = startt;
+                size_t mlt;
+                int back=0;
+                const BYTE* vLimit = ip + (dictLimit - matchIndex);
+                if (vLimit > iHighLimit) vLimit = iHighLimit;
+                mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
+                if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
+                    mlt += LZ4_count(ip+mlt, base+dictLimit, iHighLimit);
+                while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchPtr[back-1])) back--;
+                mlt -= back;
+                if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
             }
             }
         }
         }
-        ref = GETNEXT(ref);
+        matchIndex -= DELTANEXTU16(matchIndex);
     }
     }
 
 
     return longest;
     return longest;
@@ -544,53 +282,64 @@ _endCount:
 
 
 typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
 typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
 
 
+#define LZ4HC_DEBUG 0
+#if LZ4HC_DEBUG
+static unsigned debug = 0;
+#endif
+
 FORCE_INLINE int LZ4HC_encodeSequence (
 FORCE_INLINE int LZ4HC_encodeSequence (
-                       const BYTE** ip,
-                       BYTE** op,
-                       const BYTE** anchor,
-                       int matchLength,
-                       const BYTE* ref,
-                       limitedOutput_directive limitedOutputBuffer,
-                       BYTE* oend)
+    const BYTE** ip,
+    BYTE** op,
+    const BYTE** anchor,
+    int matchLength,
+    const BYTE* const match,
+    limitedOutput_directive limitedOutputBuffer,
+    BYTE* oend)
 {
 {
     int length;
     int length;
     BYTE* token;
     BYTE* token;
 
 
-    // Encode Literal length
+#if LZ4HC_DEBUG
+    if (debug) printf("literal : %u  --  match : %u  --  offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
+#endif
+
+    /* Encode Literal length */
     length = (int)(*ip - *anchor);
     length = (int)(*ip - *anchor);
     token = (*op)++;
     token = (*op)++;
-    if ((limitedOutputBuffer) && ((*op + length + (2 + 1 + LASTLITERALS) + (length>>8)) > oend)) return 1;   // Check output limit
-    if (length>=(int)RUN_MASK) { int len; *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255;  *(*op)++ = (BYTE)len; } 
+    if ((limitedOutputBuffer) && ((*op + (length>>8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1;   /* Check output limit */
+    if (length>=(int)RUN_MASK) { int len; *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255;  *(*op)++ = (BYTE)len; }
     else *token = (BYTE)(length<<ML_BITS);
     else *token = (BYTE)(length<<ML_BITS);
 
 
-    // Copy Literals
-    LZ4_BLINDCOPY(*anchor, *op, length);
+    /* Copy Literals */
+    LZ4_wildCopy(*op, *anchor, (*op) + length);
+    *op += length;
 
 
-    // Encode Offset
-    LZ4_WRITE_LITTLEENDIAN_16(*op,(U16)(*ip-ref));
+    /* Encode Offset */
+    LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2;
 
 
-    // Encode MatchLength
+    /* Encode MatchLength */
     length = (int)(matchLength-MINMATCH);
     length = (int)(matchLength-MINMATCH);
-    if ((limitedOutputBuffer) && (*op + (1 + LASTLITERALS) + (length>>8) > oend)) return 1;   // Check output limit
-    if (length>=(int)ML_MASK) { *token+=ML_MASK; length-=ML_MASK; for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (length > 254) { length-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; } 
-    else *token += (BYTE)(length);	
+    if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1;   /* Check output limit */
+    if (length>=(int)ML_MASK) { *token+=ML_MASK; length-=ML_MASK; for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (length > 254) { length-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; }
+    else *token += (BYTE)(length);
 
 
-    // Prepare next loop
+    /* Prepare next loop */
     *ip += matchLength;
     *ip += matchLength;
-    *anchor = *ip; 
+    *anchor = *ip;
 
 
     return 0;
     return 0;
 }
 }
 
 
 
 
 static int LZ4HC_compress_generic (
 static int LZ4HC_compress_generic (
-                 void* ctxvoid,
-                 const char* source, 
-                 char* dest,
-                 int inputSize,
-                 int maxOutputSize,
-                 limitedOutput_directive limit
-                )
+    void* ctxvoid,
+    const char* source,
+    char* dest,
+    int inputSize,
+    int maxOutputSize,
+    int compressionLevel,
+    limitedOutput_directive limit
+    )
 {
 {
     LZ4HC_Data_Structure* ctx = (LZ4HC_Data_Structure*) ctxvoid;
     LZ4HC_Data_Structure* ctx = (LZ4HC_Data_Structure*) ctxvoid;
     const BYTE* ip = (const BYTE*) source;
     const BYTE* ip = (const BYTE*) source;
@@ -602,6 +351,7 @@ static int LZ4HC_compress_generic (
     BYTE* op = (BYTE*) dest;
     BYTE* op = (BYTE*) dest;
     BYTE* const oend = op + maxOutputSize;
     BYTE* const oend = op + maxOutputSize;
 
 
+    unsigned maxNbAttempts;
     int   ml, ml2, ml3, ml0;
     int   ml, ml2, ml3, ml0;
     const BYTE* ref=NULL;
     const BYTE* ref=NULL;
     const BYTE* start2=NULL;
     const BYTE* start2=NULL;
@@ -612,29 +362,31 @@ static int LZ4HC_compress_generic (
     const BYTE* ref0;
     const BYTE* ref0;
 
 
 
 
-    // Ensure blocks follow each other
-    if (ip != ctx->end) return 0;
+    /* init */
+    if (compressionLevel > g_maxCompressionLevel) compressionLevel = g_maxCompressionLevel;
+    if (compressionLevel < 1) compressionLevel = LZ4HC_compressionLevel_default;
+    maxNbAttempts = 1 << (compressionLevel-1);
     ctx->end += inputSize;
     ctx->end += inputSize;
 
 
     ip++;
     ip++;
 
 
-    // Main Loop
+    /* Main Loop */
     while (ip < mflimit)
     while (ip < mflimit)
     {
     {
-        ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref));
+        ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts);
         if (!ml) { ip++; continue; }
         if (!ml) { ip++; continue; }
 
 
-        // saved, in case we would skip too much
+        /* saved, in case we would skip too much */
         start0 = ip;
         start0 = ip;
         ref0 = ref;
         ref0 = ref;
         ml0 = ml;
         ml0 = ml;
 
 
 _Search2:
 _Search2:
         if (ip+ml < mflimit)
         if (ip+ml < mflimit)
-            ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);
+            ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2, maxNbAttempts);
         else ml2 = ml;
         else ml2 = ml;
 
 
-        if (ml2 == ml)  // No better match
+        if (ml2 == ml)  /* No better match */
         {
         {
             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
             continue;
             continue;
@@ -642,7 +394,7 @@ _Search2:
 
 
         if (start0 < ip)
         if (start0 < ip)
         {
         {
-            if (start2 < ip + ml0)   // empirical
+            if (start2 < ip + ml0)   /* empirical */
             {
             {
                 ip = start0;
                 ip = start0;
                 ref = ref0;
                 ref = ref0;
@@ -650,8 +402,8 @@ _Search2:
             }
             }
         }
         }
 
 
-        // Here, start0==ip
-        if ((start2 - ip) < 3)   // First Match too small : removed
+        /* Here, start0==ip */
+        if ((start2 - ip) < 3)   /* First Match too small : removed */
         {
         {
             ml = ml2;
             ml = ml2;
             ip = start2;
             ip = start2;
@@ -660,9 +412,11 @@ _Search2:
         }
         }
 
 
 _Search3:
 _Search3:
-        // Currently we have :
-        // ml2 > ml1, and
-        // ip1+3 <= ip2 (usually < ip1+ml1)
+        /*
+        * Currently we have :
+        * ml2 > ml1, and
+        * ip1+3 <= ip2 (usually < ip1+ml1)
+        */
         if ((start2 - ip) < OPTIMAL_ML)
         if ((start2 - ip) < OPTIMAL_ML)
         {
         {
             int correction;
             int correction;
@@ -677,26 +431,26 @@ _Search3:
                 ml2 -= correction;
                 ml2 -= correction;
             }
             }
         }
         }
-        // Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18)
+        /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
 
 
         if (start2 + ml2 < mflimit)
         if (start2 + ml2 < mflimit)
-            ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);
+            ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts);
         else ml3 = ml2;
         else ml3 = ml2;
 
 
-        if (ml3 == ml2) // No better match : 2 sequences to encode
+        if (ml3 == ml2) /* No better match : 2 sequences to encode */
         {
         {
-            // ip & ref are known; Now for ml
+            /* ip & ref are known; Now for ml */
             if (start2 < ip+ml)  ml = (int)(start2 - ip);
             if (start2 < ip+ml)  ml = (int)(start2 - ip);
-            // Now, encode 2 sequences
+            /* Now, encode 2 sequences */
             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
             ip = start2;
             ip = start2;
             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) return 0;
             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) return 0;
             continue;
             continue;
         }
         }
 
 
-        if (start3 < ip+ml+3) // Not enough space for match 2 : remove it
+        if (start3 < ip+ml+3) /* Not enough space for match 2 : remove it */
         {
         {
-            if (start3 >= (ip+ml)) // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1
+            if (start3 >= (ip+ml)) /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
             {
             {
                 if (start2 < ip+ml)
                 if (start2 < ip+ml)
                 {
                 {
@@ -729,8 +483,10 @@ _Search3:
             goto _Search3;
             goto _Search3;
         }
         }
 
 
-        // OK, now we have 3 ascending matches; let's write at least the first one
-        // ip & ref are known; Now for ml
+        /*
+        * OK, now we have 3 ascending matches; let's write at least the first one
+        * ip & ref are known; Now for ml
+        */
         if (start2 < ip+ml)
         if (start2 < ip+ml)
         {
         {
             if ((start2 - ip) < (int)ML_MASK)
             if ((start2 - ip) < (int)ML_MASK)
@@ -762,56 +518,214 @@ _Search3:
         ml2 = ml3;
         ml2 = ml3;
 
 
         goto _Search3;
         goto _Search3;
-
     }
     }
 
 
-    // Encode Last Literals
+    /* Encode Last Literals */
     {
     {
         int lastRun = (int)(iend - anchor);
         int lastRun = (int)(iend - anchor);
-        if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  // Check output limit
-        if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } 
+        if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  /* Check output limit */
+        if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
         else *op++ = (BYTE)(lastRun<<ML_BITS);
         else *op++ = (BYTE)(lastRun<<ML_BITS);
         memcpy(op, anchor, iend - anchor);
         memcpy(op, anchor, iend - anchor);
         op += iend-anchor;
         op += iend-anchor;
-    } 
+    }
 
 
-    // End
+    /* End */
     return (int) (((char*)op)-dest);
     return (int) (((char*)op)-dest);
 }
 }
 
 
 
 
-int LZ4_compressHC(const char* source, char* dest, int inputSize)
+int LZ4_sizeofStateHC(void) { return sizeof(LZ4HC_Data_Structure); }
+
+int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
+{
+    if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0;   /* Error : state is not aligned for pointers (32 or 64 bits) */
+    LZ4HC_init ((LZ4HC_Data_Structure*)state, (const BYTE*)src);
+    if (maxDstSize < LZ4_compressBound(srcSize))
+        return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput);
+    else
+        return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, noLimit);
+}
+
+int LZ4_compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
+{
+    LZ4HC_Data_Structure state;
+    return LZ4_compress_HC_extStateHC(&state, src, dst, srcSize, maxDstSize, compressionLevel);
+}
+
+
+
+/**************************************
+*  Streaming Functions
+**************************************/
+/* allocation */
+LZ4_streamHC_t* LZ4_createStreamHC(void) { return (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t)); }
+int             LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { free(LZ4_streamHCPtr); return 0; }
+
+
+/* initialization */
+void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
+{
+    LZ4_STATIC_ASSERT(sizeof(LZ4HC_Data_Structure) <= sizeof(LZ4_streamHC_t));   /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
+    ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->base = NULL;
+    ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->compressionLevel = (unsigned)compressionLevel;
+}
+
+int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize)
+{
+    LZ4HC_Data_Structure* ctxPtr = (LZ4HC_Data_Structure*) LZ4_streamHCPtr;
+    if (dictSize > 64 KB)
+    {
+        dictionary += dictSize - 64 KB;
+        dictSize = 64 KB;
+    }
+    LZ4HC_init (ctxPtr, (const BYTE*)dictionary);
+    if (dictSize >= 4) LZ4HC_Insert (ctxPtr, (const BYTE*)dictionary +(dictSize-3));
+    ctxPtr->end = (const BYTE*)dictionary + dictSize;
+    return dictSize;
+}
+
+
+/* compression */
+
+static void LZ4HC_setExternalDict(LZ4HC_Data_Structure* ctxPtr, const BYTE* newBlock)
 {
 {
-    void* ctx = LZ4_createHC(source);
-    int result;
-    if (ctx==NULL) return 0;
+    if (ctxPtr->end >= ctxPtr->base + 4)
+        LZ4HC_Insert (ctxPtr, ctxPtr->end-3);   /* Referencing remaining dictionary content */
+    /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
+    ctxPtr->lowLimit  = ctxPtr->dictLimit;
+    ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
+    ctxPtr->dictBase  = ctxPtr->base;
+    ctxPtr->base = newBlock - ctxPtr->dictLimit;
+    ctxPtr->end  = newBlock;
+    ctxPtr->nextToUpdate = ctxPtr->dictLimit;   /* match referencing will resume from there */
+}
+
+static int LZ4_compressHC_continue_generic (LZ4HC_Data_Structure* ctxPtr,
+                                            const char* source, char* dest,
+                                            int inputSize, int maxOutputSize, limitedOutput_directive limit)
+{
+    /* auto-init if forgotten */
+    if (ctxPtr->base == NULL)
+        LZ4HC_init (ctxPtr, (const BYTE*) source);
+
+    /* Check overflow */
+    if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)
+    {
+        size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
+        if (dictSize > 64 KB) dictSize = 64 KB;
+
+        LZ4_loadDictHC((LZ4_streamHC_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
+    }
+
+    /* Check if blocks follow each other */
+    if ((const BYTE*)source != ctxPtr->end)
+        LZ4HC_setExternalDict(ctxPtr, (const BYTE*)source);
 
 
-    result = LZ4HC_compress_generic (ctx, source, dest, inputSize, 0, noLimit);
+    /* Check overlapping input/dictionary space */
+    {
+        const BYTE* sourceEnd = (const BYTE*) source + inputSize;
+        const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
+        const BYTE* dictEnd   = ctxPtr->dictBase + ctxPtr->dictLimit;
+        if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd))
+        {
+            if (sourceEnd > dictEnd) sourceEnd = dictEnd;
+            ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
+            if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
+        }
+    }
 
 
-    LZ4_freeHC(ctx);
-    return result;
+    return LZ4HC_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
 }
 }
 
 
-int LZ4_compressHC_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize)
+int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize)
+{
+    if (maxOutputSize < LZ4_compressBound(inputSize))
+        return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput);
+    else
+        return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit);
+}
+
+
+/* dictionary saving */
+
+int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
 {
 {
-    return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, 0, noLimit);
+    LZ4HC_Data_Structure* streamPtr = (LZ4HC_Data_Structure*)LZ4_streamHCPtr;
+    int prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
+    if (dictSize > 64 KB) dictSize = 64 KB;
+    if (dictSize < 4) dictSize = 0;
+    if (dictSize > prefixSize) dictSize = prefixSize;
+    memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
+    {
+        U32 endIndex = (U32)(streamPtr->end - streamPtr->base);
+        streamPtr->end = (const BYTE*)safeBuffer + dictSize;
+        streamPtr->base = streamPtr->end - endIndex;
+        streamPtr->dictLimit = endIndex - dictSize;
+        streamPtr->lowLimit = endIndex - dictSize;
+        if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;
+    }
+    return dictSize;
 }
 }
 
 
 
 
-int LZ4_compressHC_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize)
+/***********************************
+*  Deprecated Functions
+***********************************/
+/* Deprecated compression functions */
+/* These functions are planned to start generate warnings by r131 approximately */
+int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
+int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }
+int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
+int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
+int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
+int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); }
+int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
+int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); }
+int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); }
+int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); }
+
+
+/* Deprecated streaming functions */
+/* These functions currently generate deprecation warnings */
+int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; }
+
+int LZ4_resetStreamStateHC(void* state, char* inputBuffer)
 {
 {
-    void* ctx = LZ4_createHC(source);
-    int result;
-    if (ctx==NULL) return 0;
+    if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1;   /* Error : pointer is not aligned for pointer (32 or 64 bits) */
+    LZ4HC_init((LZ4HC_Data_Structure*)state, (const BYTE*)inputBuffer);
+    ((LZ4HC_Data_Structure*)state)->inputBuffer = (BYTE*)inputBuffer;
+    return 0;
+}
 
 
-    result = LZ4HC_compress_generic (ctx, source, dest, inputSize, maxOutputSize, limitedOutput);
+void* LZ4_createHC (char* inputBuffer)
+{
+    void* hc4 = ALLOCATOR(1, sizeof(LZ4HC_Data_Structure));
+    if (hc4 == NULL) return NULL;   /* not enough memory */
+    LZ4HC_init ((LZ4HC_Data_Structure*)hc4, (const BYTE*)inputBuffer);
+    ((LZ4HC_Data_Structure*)hc4)->inputBuffer = (BYTE*)inputBuffer;
+    return hc4;
+}
+
+int LZ4_freeHC (void* LZ4HC_Data)
+{
+    FREEMEM(LZ4HC_Data);
+    return (0);
+}
 
 
-    LZ4_freeHC(ctx);
-    return result;
+int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel)
+{
+    return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, 0, compressionLevel, noLimit);
 }
 }
 
 
-int LZ4_compressHC_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize)
+int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel)
 {
 {
-    return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, maxOutputSize, limitedOutput);
+    return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput);
 }
 }
 
 
+char* LZ4_slideInputBufferHC(void* LZ4HC_Data)
+{
+    LZ4HC_Data_Structure* hc4 = (LZ4HC_Data_Structure*)LZ4HC_Data;
+    int dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB);
+    return (char*)(hc4->inputBuffer + dictSize);
+}

+ 129 - 51
Source/ThirdParty/LZ4/lz4hc.h

@@ -1,7 +1,7 @@
 /*
 /*
    LZ4 HC - High Compression Mode of LZ4
    LZ4 HC - High Compression Mode of LZ4
    Header File
    Header File
-   Copyright (C) 2011-2013, Yann Collet.
+   Copyright (C) 2011-2015, Yann Collet.
    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
 
 
    Redistribution and use in source and binary forms, with or without
    Redistribution and use in source and binary forms, with or without
@@ -28,8 +28,8 @@
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
    You can contact the author at :
    You can contact the author at :
-   - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
-   - LZ4 source repository : http://code.google.com/p/lz4/
+   - LZ4 source repository : https://github.com/Cyan4973/lz4
+   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
 */
 */
 #pragma once
 #pragma once
 
 
@@ -38,74 +38,152 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
+/*****************************
+*  Includes
+*****************************/
+#include <stddef.h>   /* size_t */
 
 
-int LZ4_compressHC (const char* source, char* dest, int inputSize);
-/*
-LZ4_compressHC :
-    return : the number of bytes in compressed buffer dest
-             or 0 if compression fails.
-    note : destination buffer must be already allocated. 
-        To avoid any problem, size it to handle worst cases situations (input data not compressible)
-        Worst case size evaluation is provided by function LZ4_compressBound() (see "lz4.h")
-*/
 
 
-int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
+/**************************************
+*  Block Compression
+**************************************/
+int LZ4_compress_HC (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
 /*
 /*
-LZ4_compress_limitedOutput() :
-    Compress 'inputSize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'.
-    If it cannot achieve it, compression will stop, and result of the function will be zero.
-    This function never writes outside of provided output buffer.
-
-    inputSize  : Max supported value is 1 GB
-    maxOutputSize : is maximum allowed size into the destination buffer (which must be already allocated)
-    return : the number of output bytes written in buffer 'dest'
-             or 0 if compression fails.
+LZ4_compress_HC :
+    Destination buffer 'dst' must be already allocated.
+    Compression completion is guaranteed if 'dst' buffer is sized to handle worst circumstances (data not compressible)
+    Worst size evaluation is provided by function LZ4_compressBound() (see "lz4.h")
+      srcSize  : Max supported value is LZ4_MAX_INPUT_SIZE (see "lz4.h")
+      compressionLevel : Recommended values are between 4 and 9, although any value between 0 and 16 will work.
+                         0 means "use default value" (see lz4hc.c).
+                         Values >16 behave the same as 16.
+      return : the number of bytes written into buffer 'dst'
+            or 0 if compression fails.
 */
 */
 
 
 
 
 /* Note :
 /* Note :
-Decompression functions are provided within LZ4 source code (see "lz4.h") (BSD license)
+   Decompression functions are provided within LZ4 source code (see "lz4.h") (BSD license)
+*/
+
+
+int LZ4_sizeofStateHC(void);
+int LZ4_compress_HC_extStateHC(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
+/*
+LZ4_compress_HC_extStateHC() :
+   Use this function if you prefer to manually allocate memory for compression tables.
+   To know how much memory must be allocated for the compression tables, use :
+      int LZ4_sizeofStateHC();
+
+   Allocated memory must be aligned on 8-bytes boundaries (which a normal malloc() will do properly).
+
+   The allocated memory can then be provided to the compression functions using 'void* state' parameter.
+   LZ4_compress_HC_extStateHC() is equivalent to previously described function.
+   It just uses externally allocated memory for stateHC.
 */
 */
 
 
 
 
-/* Advanced Functions */
+/**************************************
+*  Streaming Compression
+**************************************/
+#define LZ4_STREAMHCSIZE        262192
+#define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t))
+typedef struct { size_t table[LZ4_STREAMHCSIZE_SIZET]; } LZ4_streamHC_t;
+/*
+  LZ4_streamHC_t
+  This structure allows static allocation of LZ4 HC streaming state.
+  State must then be initialized using LZ4_resetStreamHC() before first use.
 
 
-void* LZ4_createHC (const char* inputBuffer);
-int   LZ4_compressHC_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize);
-int   LZ4_compressHC_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize);
-char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
-int   LZ4_freeHC (void* LZ4HC_Data);
+  Static allocation should only be used in combination with static linking.
+  If you want to use LZ4 as a DLL, please use construction functions below, which are future-proof.
+*/
 
 
-/* 
-These functions allow the compression of dependent blocks, where each block benefits from prior 64 KB within preceding blocks.
-In order to achieve this, it is necessary to start creating the LZ4HC Data Structure, thanks to the function :
 
 
-void* LZ4_createHC (const char* inputBuffer);
-The result of the function is the (void*) pointer on the LZ4HC Data Structure.
-This pointer will be needed in all other functions.
-If the pointer returned is NULL, then the allocation has failed, and compression must be aborted.
-The only parameter 'const char* inputBuffer' must, obviously, point at the beginning of input buffer.
-The input buffer must be already allocated, and size at least 192KB.
-'inputBuffer' will also be the 'const char* source' of the first block.
+LZ4_streamHC_t* LZ4_createStreamHC(void);
+int             LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr);
+/*
+  These functions create and release memory for LZ4 HC streaming state.
+  Newly created states are already initialized.
+  Existing state space can be re-used anytime using LZ4_resetStreamHC().
+  If you use LZ4 as a DLL, use these functions instead of static structure allocation,
+  to avoid size mismatch between different versions.
+*/
 
 
-All blocks are expected to lay next to each other within the input buffer, starting from 'inputBuffer'.
-To compress each block, use either LZ4_compressHC_continue() or LZ4_compressHC_limitedOutput_continue().
-Their behavior are identical to LZ4_compressHC() or LZ4_compressHC_limitedOutput(), 
-but require the LZ4HC Data Structure as their first argument, and check that each block starts right after the previous one.
-If next block does not begin immediately after the previous one, the compression will fail (return 0).
+void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);
+int  LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);
 
 
-When it's no longer possible to lay the next block after the previous one (not enough space left into input buffer), a call to : 
-char* LZ4_slideInputBufferHC(void* LZ4HC_Data);
-must be performed. It will typically copy the latest 64KB of input at the beginning of input buffer.
-Note that, for this function to work properly, minimum size of an input buffer must be 192KB.
-==> The memory position where the next input data block must start is provided as the result of the function.
+int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr, const char* src, char* dst, int srcSize, int maxDstSize);
 
 
-Compression can then resume, using LZ4_compressHC_continue() or LZ4_compressHC_limitedOutput_continue(), as usual.
+int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);
 
 
-When compression is completed, a call to LZ4_freeHC() will release the memory used by the LZ4HC Data Structure.
+/*
+  These functions compress data in successive blocks of any size, using previous blocks as dictionary.
+  One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.
+  There is an exception for ring buffers, which can be smaller 64 KB.
+  Such case is automatically detected and correctly handled by LZ4_compress_HC_continue().
+
+  Before starting compression, state must be properly initialized, using LZ4_resetStreamHC().
+  A first "fictional block" can then be designated as initial dictionary, using LZ4_loadDictHC() (Optional).
+
+  Then, use LZ4_compress_HC_continue() to compress each successive block.
+  It works like LZ4_compress_HC(), but use previous memory blocks as dictionary to improve compression.
+  Previous memory blocks (including initial dictionary when present) must remain accessible and unmodified during compression.
+  As a reminder, size 'dst' buffer to handle worst cases, using LZ4_compressBound(), to ensure success of compression operation.
+
+  If, for any reason, previous data blocks can't be preserved unmodified in memory during next compression block,
+  you must save it to a safer memory space, using LZ4_saveDictHC().
+  Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer'.
 */
 */
 
 
 
 
+
+/**************************************
+*  Deprecated Functions
+**************************************/
+/* Deprecate Warnings */
+/* Should these warnings messages be a problem,
+   it is generally possible to disable them,
+   with -Wno-deprecated-declarations for gcc
+   or _CRT_SECURE_NO_WARNINGS in Visual for example.
+   You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
+#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
+#  define LZ4_DEPRECATE_WARNING_DEFBLOCK
+#  define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#  if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
+#    define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
+#  elif (LZ4_GCC_VERSION >= 301)
+#    define LZ4_DEPRECATED(message) __attribute__((deprecated))
+#  elif defined(_MSC_VER)
+#    define LZ4_DEPRECATED(message) __declspec(deprecated(message))
+#  else
+#    pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
+#    define LZ4_DEPRECATED(message)
+#  endif
+#endif // LZ4_DEPRECATE_WARNING_DEFBLOCK
+
+/* compression functions */
+/* these functions are planned to trigger warning messages by r131 approximately */
+int LZ4_compressHC                (const char* source, char* dest, int inputSize);
+int LZ4_compressHC_limitedOutput  (const char* source, char* dest, int inputSize, int maxOutputSize);
+int LZ4_compressHC2               (const char* source, char* dest, int inputSize, int compressionLevel);
+int LZ4_compressHC2_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
+int LZ4_compressHC_withStateHC               (void* state, const char* source, char* dest, int inputSize);
+int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
+int LZ4_compressHC2_withStateHC              (void* state, const char* source, char* dest, int inputSize, int compressionLevel);
+int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
+int LZ4_compressHC_continue               (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize);
+int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
+
+/* Streaming functions following the older model; should no longer be used */
+LZ4_DEPRECATED("use LZ4_createStreamHC() instead") void* LZ4_createHC (char* inputBuffer);
+LZ4_DEPRECATED("use LZ4_saveDictHC() instead")     char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
+LZ4_DEPRECATED("use LZ4_freeStreamHC() instead")   int   LZ4_freeHC (void* LZ4HC_Data);
+LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int   LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
+LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int   LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
+LZ4_DEPRECATED("use LZ4_createStreamHC() instead") int   LZ4_sizeofStreamStateHC(void);
+LZ4_DEPRECATED("use LZ4_resetStreamHC() instead")  int   LZ4_resetStreamStateHC(void* state, char* inputBuffer);
+
+
 #if defined (__cplusplus)
 #if defined (__cplusplus)
 }
 }
 #endif
 #endif

+ 12 - 11
Source/ThirdParty/STB/README.md

@@ -7,15 +7,15 @@ single-file public domain libraries for C/C++ <a name="stb_libs"></a>
 
 
 library    | lastest version | category | LoC | description
 library    | lastest version | category | LoC | description
 --------------------- | ---- | -------- | --- | --------------------------------
 --------------------- | ---- | -------- | --- | --------------------------------
-**stb_vorbis.c** | 1.07 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output
-**stb_image.h** | 2.10 | graphics | 6614 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
-**stb_truetype.h** | 1.09 | graphics | 3249 | parse, decode, and rasterize characters from truetype fonts
-**stb_image_write.h** | 1.01 | graphics | 1044 | image writing to disk: PNG, TGA, BMP
-**stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality
+**stb_vorbis.c** | 1.09 | audio | 5397 | decode ogg vorbis files from file/memory to float/16-bit signed output
+**stb_image.h** | 2.12 | graphics | 6755 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
+**stb_truetype.h** | 1.11 | graphics | 3267 | parse, decode, and rasterize characters from truetype fonts
+**stb_image_write.h** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP
+**stb_image_resize.h** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality
 **stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality
 **stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality
 **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++
 **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++
-**stb_textedit.h** | 1.7 | user&nbsp;interface | 1301 | guts of a text editor for games etc implementing them from scratch
-**stb_voxel_render.h** | 0.83 | 3D&nbsp;graphics | 3750 | Minecraft-esque voxel rendering "engine" with many more features
+**stb_textedit.h** | 1.8 | user&nbsp;interface | 1304 | guts of a text editor for games etc implementing them from scratch
+**stb_voxel_render.h** | 0.84 | 3D&nbsp;graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features
 **stb_dxt.h** | 1.04 | 3D&nbsp;graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor
 **stb_dxt.h** | 1.04 | 3D&nbsp;graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor
 **stb_perlin.h** | 0.2 | 3D&nbsp;graphics | 182 | revised Perlin noise (3D input, 1D output)
 **stb_perlin.h** | 0.2 | 3D&nbsp;graphics | 182 | revised Perlin noise (3D input, 1D output)
 **stb_easy_font.h** | 0.7 | 3D&nbsp;graphics | 258 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
 **stb_easy_font.h** | 0.7 | 3D&nbsp;graphics | 258 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
@@ -23,11 +23,12 @@ library    | lastest version | category | LoC | description
 **stb_herringbone_wa...** | 0.6 | game&nbsp;dev | 1220 | herringbone Wang tile map generator
 **stb_herringbone_wa...** | 0.6 | game&nbsp;dev | 1220 | herringbone Wang tile map generator
 **stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages
 **stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages
 **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide"
 **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide"
-**stb.h** | 2.26 | misc | 14184 | helper functions for C, mostly redundant in C++; basically author's personal stuff
+**stb_connected_comp...** | 0.94 | misc | 1000 | incrementally compute reachability on grids
+**stb.h** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff
 **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking
 **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking
 
 
-Total libraries: 18  
-Total lines of C code: 46718
+Total libraries: 19  
+Total lines of C code: 47814
 
 
 
 
 FAQ
 FAQ
@@ -99,7 +100,7 @@ No, they are just the initials for my name, Sean T. Barrett.
 This was not chosen out of egomania, but as a moderately sane
 This was not chosen out of egomania, but as a moderately sane
 way of namespacing the filenames and source function names.
 way of namespacing the filenames and source function names.
 
 
-#### Will you add more image types to stb_image.c?
+#### Will you add more image types to stb_image.h?
 
 
 If people submit them, I generally add them, but the goal of stb_image
 If people submit them, I generally add them, but the goal of stb_image
 is less for applications like image viewer apps (which need to support
 is less for applications like image viewer apps (which need to support

+ 26 - 0
Source/ThirdParty/STB/release_notes.md

@@ -0,0 +1,26 @@
+----
+
+2016-04-02:
+
+- other_libs: cro_mipmap, greatest, munit, parg, dr_flac
+- stb_image_write: allocate large structures on stack for embedded (Thatcher Ulrich)
+- stb_image: allocate large structures on stack for embedded (Thatcher Ulrich)
+- stb_image: remove white matting for transparent PSD (stb, Oriol Ferrer Mesia)
+- stb_image: fix reported channel count in PNG when req_comp is non-zero
+- stb_image: re-enable SSE2 in x64 (except in gcc)
+- stb_image: fix harmless typo in name (Matthew Gregan)
+- stb_image: support JPEG images coded as RGB
+- stb_image: bmp could return wrong channel count (snagar@github)
+- stb_image: read 16-bit PNGs as 8-bit (socks-the-fox)
+- stb_image_resize: fix handling of subpixel regions
+- stb_image_resize: avoid warnings on asserts (Wu Shuang)
+- stb_truetype: allow fabs() to be supplied by user (Simon Glass)
+- stb_truetype: duplicate typedef
+- stb_truetype: don't leak memory if fontsize=0
+- stb_vorbis: warnings (Thiago Goulart)
+- stb_vorbis: fix multiple memory leaks of setup-memory (manxorist@github)
+- stb_vorbis: avoid dropping final frame of audio data
+- stb_textedit: better support for keying while holding mouse drag button (ocornut)
+- stb_voxel_render: fix type of glModelview matrix (Stephen Olsen)
+- stb_leakcheck: typo in comment (Lukas Meller)
+- stb.h: fix _WIN32 when defining STB_THREADS

+ 197 - 56
Source/ThirdParty/STB/stb_image.h

@@ -1,4 +1,4 @@
-/* stb_image - v2.10 - public domain image loader - http://nothings.org/stb_image.h
+/* stb_image - v2.12 - public domain image loader - http://nothings.org/stb_image.h
                                      no warranty implied; use at your own risk
                                      no warranty implied; use at your own risk
 
 
    Do this:
    Do this:
@@ -146,6 +146,11 @@
 
 
 
 
    Latest revision history:
    Latest revision history:
+      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+      2.11  (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
+                         RGB-format JPEG; remove white matting in PSD;
+                         allocate large structures on the stack; 
+                         correct channel count for PNG & BMP
       2.10  (2016-01-22) avoid warning introduced in 2.09
       2.10  (2016-01-22) avoid warning introduced in 2.09
       2.09  (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
       2.09  (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
       2.08  (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
       2.08  (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
@@ -167,10 +172,6 @@
                          STBI_MALLOC,STBI_REALLOC,STBI_FREE
                          STBI_MALLOC,STBI_REALLOC,STBI_FREE
                          STBI_NO_*, STBI_ONLY_*
                          STBI_NO_*, STBI_ONLY_*
                          GIF bugfix
                          GIF bugfix
-      1.48  (2014-12-14) fix incorrectly-named assert()
-      1.47  (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted)
-                         optimize PNG
-                         fix bug in interlaced PNG with user-specified channel count
 
 
    See end of file for full revision history.
    See end of file for full revision history.
 
 
@@ -201,10 +202,10 @@
     Janez Zemva             John Bartholomew   Michal Cichon      svdijk@github
     Janez Zemva             John Bartholomew   Michal Cichon      svdijk@github
     Jonathan Blow           Ken Hamada         Tero Hanninen      Baldur Karlsson
     Jonathan Blow           Ken Hamada         Tero Hanninen      Baldur Karlsson
     Laurent Gomila          Cort Stratton      Sergio Gonzalez    romigrou@github
     Laurent Gomila          Cort Stratton      Sergio Gonzalez    romigrou@github
-    Aruelien Pocheville     Thibault Reuille   Cass Everitt
-    Ryamond Barbiero        Paul Du Bois       Engin Manap
+    Aruelien Pocheville     Thibault Reuille   Cass Everitt       Matthew Gregan
+    Ryamond Barbiero        Paul Du Bois       Engin Manap        snagar@github
+    Michaelangel007@github  Oriol Ferrer Mesia socks-the-fox
     Blazej Dariusz Roszkowski
     Blazej Dariusz Roszkowski
-    Michaelangel007@github
 
 
 
 
 LICENSE
 LICENSE
@@ -672,7 +673,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
 #define STBI_NO_SIMD
 #define STBI_NO_SIMD
 #endif
 #endif
 
 
-#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET)
+#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
 #define STBI_SSE2
 #define STBI_SSE2
 #include <emmintrin.h>
 #include <emmintrin.h>
 
 
@@ -1506,6 +1507,7 @@ typedef struct
    int            succ_high;
    int            succ_high;
    int            succ_low;
    int            succ_low;
    int            eob_run;
    int            eob_run;
+   int            rgb;
 
 
    int scan_n, order[4];
    int scan_n, order[4];
    int restart_interval, todo;
    int restart_interval, todo;
@@ -2717,11 +2719,17 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
 
 
    if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
    if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
 
 
+   z->rgb = 0;
    for (i=0; i < s->img_n; ++i) {
    for (i=0; i < s->img_n; ++i) {
+      static unsigned char rgb[3] = { 'R', 'G', 'B' };
       z->img_comp[i].id = stbi__get8(s);
       z->img_comp[i].id = stbi__get8(s);
       if (z->img_comp[i].id != i+1)   // JFIF requires
       if (z->img_comp[i].id != i+1)   // JFIF requires
-         if (z->img_comp[i].id != i)  // some version of jpegtran outputs non-JFIF-compliant files!
-            return stbi__err("bad component ID","Corrupt JPEG");
+         if (z->img_comp[i].id != i) {  // some version of jpegtran outputs non-JFIF-compliant files!
+            // somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format)
+            if (z->img_comp[i].id != rgb[i])
+               return stbi__err("bad component ID","Corrupt JPEG");
+            ++z->rgb;
+         }
       q = stbi__get8(s);
       q = stbi__get8(s);
       z->img_comp[i].h = (q >> 4);  if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
       z->img_comp[i].h = (q >> 4);  if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
       z->img_comp[i].v = q & 15;    if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
       z->img_comp[i].v = q & 15;    if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
@@ -3383,7 +3391,17 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
          if (n >= 3) {
          if (n >= 3) {
             stbi_uc *y = coutput[0];
             stbi_uc *y = coutput[0];
             if (z->s->img_n == 3) {
             if (z->s->img_n == 3) {
-               z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+               if (z->rgb == 3) {
+                  for (i=0; i < z->s->img_x; ++i) {
+                     out[0] = y[i];
+                     out[1] = coutput[1][i];
+                     out[2] = coutput[2][i];
+                     out[3] = 255;
+                     out += n;
+                  }
+               } else {
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+               }
             } else
             } else
                for (i=0; i < z->s->img_x; ++i) {
                for (i=0; i < z->s->img_x; ++i) {
                   out[0] = out[1] = out[2] = y[i];
                   out[0] = out[1] = out[2] = y[i];
@@ -3408,10 +3426,13 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
 
 
 static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
 static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
 {
 {
-   stbi__jpeg j;
-   j.s = s;
-   stbi__setup_jpeg(&j);
-   return load_jpeg_image(&j, x,y,comp,req_comp);
+   unsigned char* result;
+   stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
+   j->s = s;
+   stbi__setup_jpeg(j);
+   result = load_jpeg_image(j, x,y,comp,req_comp);
+   STBI_FREE(j);
+   return result;
 }
 }
 
 
 static int stbi__jpeg_test(stbi__context *s)
 static int stbi__jpeg_test(stbi__context *s)
@@ -3439,9 +3460,12 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
 
 
 static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
 static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
 {
 {
-   stbi__jpeg j;
-   j.s = s;
-   return stbi__jpeg_info_raw(&j, x, y, comp);
+   int result;
+   stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
+   j->s = s;
+   result = stbi__jpeg_info_raw(j, x, y, comp);
+   STBI_FREE(j);
+   return result;
 }
 }
 #endif
 #endif
 
 
@@ -3732,7 +3756,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
    return 1;
    return 1;
 }
 }
 
 
-static int stbi__parse_uncomperssed_block(stbi__zbuf *a)
+static int stbi__parse_uncompressed_block(stbi__zbuf *a)
 {
 {
    stbi_uc header[4];
    stbi_uc header[4];
    int len,nlen,k;
    int len,nlen,k;
@@ -3798,7 +3822,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
       final = stbi__zreceive(a,1);
       final = stbi__zreceive(a,1);
       type = stbi__zreceive(a,2);
       type = stbi__zreceive(a,2);
       if (type == 0) {
       if (type == 0) {
-         if (!stbi__parse_uncomperssed_block(a)) return 0;
+         if (!stbi__parse_uncompressed_block(a)) return 0;
       } else if (type == 3) {
       } else if (type == 3) {
          return 0;
          return 0;
       } else {
       } else {
@@ -3940,6 +3964,7 @@ typedef struct
 {
 {
    stbi__context *s;
    stbi__context *s;
    stbi_uc *idata, *expanded, *out;
    stbi_uc *idata, *expanded, *out;
+   int depth;
 } stbi__png;
 } stbi__png;
 
 
 
 
@@ -3979,14 +4004,19 @@ static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x0
 // create the png data from post-deflated data
 // create the png data from post-deflated data
 static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
 static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
 {
 {
+   int bytes = (depth == 16? 2 : 1);
    stbi__context *s = a->s;
    stbi__context *s = a->s;
-   stbi__uint32 i,j,stride = x*out_n;
+   stbi__uint32 i,j,stride = x*out_n*bytes;
    stbi__uint32 img_len, img_width_bytes;
    stbi__uint32 img_len, img_width_bytes;
    int k;
    int k;
    int img_n = s->img_n; // copy it into a local for later
    int img_n = s->img_n; // copy it into a local for later
 
 
+   int output_bytes = out_n*bytes;
+   int filter_bytes = img_n*bytes;
+   int width = x;
+
    STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
    STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
-   a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into
+   a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into
    if (!a->out) return stbi__err("outofmem", "Out of memory");
    if (!a->out) return stbi__err("outofmem", "Out of memory");
 
 
    img_width_bytes = (((img_n * x * depth) + 7) >> 3);
    img_width_bytes = (((img_n * x * depth) + 7) >> 3);
@@ -4001,8 +4031,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
       stbi_uc *cur = a->out + stride*j;
       stbi_uc *cur = a->out + stride*j;
       stbi_uc *prior = cur - stride;
       stbi_uc *prior = cur - stride;
       int filter = *raw++;
       int filter = *raw++;
-      int filter_bytes = img_n;
-      int width = x;
+
       if (filter > 4)
       if (filter > 4)
          return stbi__err("invalid filter","Corrupt PNG");
          return stbi__err("invalid filter","Corrupt PNG");
 
 
@@ -4035,6 +4064,14 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
          raw += img_n;
          raw += img_n;
          cur += out_n;
          cur += out_n;
          prior += out_n;
          prior += out_n;
+      } else if (depth == 16) {
+         if (img_n != out_n) {
+            cur[filter_bytes]   = 255; // first pixel top byte
+            cur[filter_bytes+1] = 255; // first pixel bottom byte
+         }
+         raw += filter_bytes;
+         cur += output_bytes;
+         prior += output_bytes;
       } else {
       } else {
          raw += 1;
          raw += 1;
          cur += 1;
          cur += 1;
@@ -4043,7 +4080,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
 
 
       // this is a little gross, so that we don't switch per-pixel or per-component
       // this is a little gross, so that we don't switch per-pixel or per-component
       if (depth < 8 || img_n == out_n) {
       if (depth < 8 || img_n == out_n) {
-         int nk = (width - 1)*img_n;
+         int nk = (width - 1)*filter_bytes;
          #define CASE(f) \
          #define CASE(f) \
              case f:     \
              case f:     \
                 for (k=0; k < nk; ++k)
                 for (k=0; k < nk; ++k)
@@ -4063,18 +4100,27 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
          STBI_ASSERT(img_n+1 == out_n);
          STBI_ASSERT(img_n+1 == out_n);
          #define CASE(f) \
          #define CASE(f) \
              case f:     \
              case f:     \
-                for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \
-                   for (k=0; k < img_n; ++k)
+                for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
+                   for (k=0; k < filter_bytes; ++k)
          switch (filter) {
          switch (filter) {
             CASE(STBI__F_none)         cur[k] = raw[k]; break;
             CASE(STBI__F_none)         cur[k] = raw[k]; break;
-            CASE(STBI__F_sub)          cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break;
+            CASE(STBI__F_sub)          cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break;
             CASE(STBI__F_up)           cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
             CASE(STBI__F_up)           cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
-            CASE(STBI__F_avg)          cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break;
-            CASE(STBI__F_paeth)        cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break;
-            CASE(STBI__F_avg_first)    cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break;
-            CASE(STBI__F_paeth_first)  cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break;
+            CASE(STBI__F_avg)          cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break;
+            CASE(STBI__F_paeth)        cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break;
+            CASE(STBI__F_avg_first)    cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break;
+            CASE(STBI__F_paeth_first)  cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break;
          }
          }
          #undef CASE
          #undef CASE
+
+         // the loop above sets the high byte of the pixels' alpha, but for
+         // 16 bit png files we also need the low byte set. we'll do that here.
+         if (depth == 16) {
+            cur = a->out + stride*j; // start at the beginning of the row again
+            for (i=0; i < x; ++i,cur+=output_bytes) {
+               cur[filter_bytes+1] = 255;
+            }
+         }
       }
       }
    }
    }
 
 
@@ -4150,6 +4196,17 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
             }
             }
          }
          }
       }
       }
+   } else if (depth == 16) {
+      // force the image data from big-endian to platform-native.
+      // this is done in a separate pass due to the decoding relying
+      // on the data being untouched, but could probably be done
+      // per-line during decode if care is taken.
+      stbi_uc *cur = a->out;
+      stbi__uint16 *cur16 = (stbi__uint16*)cur;
+
+      for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
+         *cur16 = (cur[0] << 8) | cur[1];
+      }
    }
    }
 
 
    return 1;
    return 1;
@@ -4222,6 +4279,31 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
    return 1;
    return 1;
 }
 }
 
 
+static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi__uint16 *p = (stbi__uint16*) z->out;
+
+   // compute color-based transparency, assuming we've
+   // already got 65535 as the alpha value in the output
+   STBI_ASSERT(out_n == 2 || out_n == 4);
+
+   if (out_n == 2) {
+      for (i = 0; i < pixel_count; ++i) {
+         p[1] = (p[0] == tc[0] ? 0 : 65535);
+         p += 2;
+      }
+   } else {
+      for (i = 0; i < pixel_count; ++i) {
+         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+            p[3] = 0;
+         p += 4;
+      }
+   }
+   return 1;
+}
+
 static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
 static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
 {
 {
    stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
    stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
@@ -4259,6 +4341,26 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
    return 1;
    return 1;
 }
 }
 
 
+static int stbi__reduce_png(stbi__png *p)
+{
+   int i;
+   int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n;
+   stbi_uc *reduced;
+   stbi__uint16 *orig = (stbi__uint16*)p->out;
+
+   if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data
+
+   reduced = (stbi_uc *)stbi__malloc(img_len);
+   if (p == NULL) return stbi__err("outofmem", "Out of memory");
+
+   for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling
+
+   p->out = reduced;
+   STBI_FREE(orig);
+
+   return 1;
+}
+
 static int stbi__unpremultiply_on_load = 0;
 static int stbi__unpremultiply_on_load = 0;
 static int stbi__de_iphone_flag = 0;
 static int stbi__de_iphone_flag = 0;
 
 
@@ -4320,8 +4422,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
 {
 {
    stbi_uc palette[1024], pal_img_n=0;
    stbi_uc palette[1024], pal_img_n=0;
    stbi_uc has_trans=0, tc[3];
    stbi_uc has_trans=0, tc[3];
+   stbi__uint16 tc16[3];
    stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
    stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
-   int first=1,k,interlace=0, color=0, depth=0, is_iphone=0;
+   int first=1,k,interlace=0, color=0, is_iphone=0;
    stbi__context *s = z->s;
    stbi__context *s = z->s;
 
 
    z->expanded = NULL;
    z->expanded = NULL;
@@ -4346,8 +4449,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
             if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
             if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
             s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
             s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
             s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
             s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
-            depth = stbi__get8(s);  if (depth != 1 && depth != 2 && depth != 4 && depth != 8)  return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only");
+            z->depth = stbi__get8(s);  if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16)  return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
             color = stbi__get8(s);  if (color > 6)         return stbi__err("bad ctype","Corrupt PNG");
             color = stbi__get8(s);  if (color > 6)         return stbi__err("bad ctype","Corrupt PNG");
+			if (color == 3 && z->depth == 16)                  return stbi__err("bad ctype","Corrupt PNG");
             if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
             if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
             comp  = stbi__get8(s);  if (comp) return stbi__err("bad comp method","Corrupt PNG");
             comp  = stbi__get8(s);  if (comp) return stbi__err("bad comp method","Corrupt PNG");
             filter= stbi__get8(s);  if (filter) return stbi__err("bad filter method","Corrupt PNG");
             filter= stbi__get8(s);  if (filter) return stbi__err("bad filter method","Corrupt PNG");
@@ -4395,8 +4499,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
                if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
                if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
                if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
                if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
                has_trans = 1;
                has_trans = 1;
-               for (k=0; k < s->img_n; ++k)
-                  tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger
+               if (z->depth == 16) {
+                  for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is
+               } else {
+                  for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
+               }
             }
             }
             break;
             break;
          }
          }
@@ -4427,7 +4534,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
             if (scan != STBI__SCAN_load) return 1;
             if (scan != STBI__SCAN_load) return 1;
             if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
             if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
             // initial guess for decoded data size to avoid unnecessary reallocs
             // initial guess for decoded data size to avoid unnecessary reallocs
-            bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component
+            bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
             raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
             raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
             z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
             z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
             if (z->expanded == NULL) return 0; // zlib should set error
             if (z->expanded == NULL) return 0; // zlib should set error
@@ -4436,9 +4543,14 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
                s->img_out_n = s->img_n+1;
                s->img_out_n = s->img_n+1;
             else
             else
                s->img_out_n = s->img_n;
                s->img_out_n = s->img_n;
-            if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0;
-            if (has_trans)
-               if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
+            if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
+            if (has_trans) {
+               if (z->depth == 16) {
+                  if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
+               } else {
+                  if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
+               }
+            }
             if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
             if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
                stbi__de_iphone(z);
                stbi__de_iphone(z);
             if (pal_img_n) {
             if (pal_img_n) {
@@ -4480,6 +4592,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
    unsigned char *result=NULL;
    unsigned char *result=NULL;
    if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
    if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
    if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
    if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
+      if (p->depth == 16) {
+         if (!stbi__reduce_png(p)) {
+            return result;
+         }
+      }
       result = p->out;
       result = p->out;
       p->out = NULL;
       p->out = NULL;
       if (req_comp && req_comp != p->s->img_out_n) {
       if (req_comp && req_comp != p->s->img_out_n) {
@@ -4489,7 +4606,7 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
       }
       }
       *x = p->s->img_x;
       *x = p->s->img_x;
       *y = p->s->img_y;
       *y = p->s->img_y;
-      if (n) *n = p->s->img_out_n;
+      if (n) *n = p->s->img_n;
    }
    }
    STBI_FREE(p->out);      p->out      = NULL;
    STBI_FREE(p->out);      p->out      = NULL;
    STBI_FREE(p->expanded); p->expanded = NULL;
    STBI_FREE(p->expanded); p->expanded = NULL;
@@ -4614,6 +4731,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
    stbi__get16le(s); // discard reserved
    stbi__get16le(s); // discard reserved
    info->offset = stbi__get32le(s);
    info->offset = stbi__get32le(s);
    info->hsz = hsz = stbi__get32le(s);
    info->hsz = hsz = stbi__get32le(s);
+   info->mr = info->mg = info->mb = info->ma = 0;
    
    
    if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
    if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
    if (hsz == 12) {
    if (hsz == 12) {
@@ -4642,7 +4760,6 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
             stbi__get32le(s);
             stbi__get32le(s);
          }
          }
          if (info->bpp == 16 || info->bpp == 32) {
          if (info->bpp == 16 || info->bpp == 32) {
-            info->mr = info->mg = info->mb = 0;
             if (compress == 0) {
             if (compress == 0) {
                if (info->bpp == 32) {
                if (info->bpp == 32) {
                   info->mr = 0xffu << 16;
                   info->mr = 0xffu << 16;
@@ -5337,6 +5454,21 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
       }
       }
    }
    }
 
 
+   if (channelCount >= 4) {
+      for (i=0; i < w*h; ++i) {
+         unsigned char *pixel = out + 4*i;
+         if (pixel[3] != 0 && pixel[3] != 255) {
+            // remove weird white matte from PSD
+            float a = pixel[3] / 255.0f;
+            float ra = 1.0f / a;
+            float inv_a = 255.0f * (1 - ra);
+            pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
+            pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
+            pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
+         }
+      }
+   }
+
    if (req_comp && req_comp != 4) {
    if (req_comp && req_comp != 4) {
       out = stbi__convert_format(out, 4, req_comp, w, h);
       out = stbi__convert_format(out, 4, req_comp, w, h);
       if (out == NULL) return out; // stbi__convert_format frees input on failure
       if (out == NULL) return out; // stbi__convert_format frees input on failure
@@ -5649,13 +5781,15 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
 
 
 static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
 static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
 {
 {
-   stbi__gif g;
-   if (!stbi__gif_header(s, &g, comp, 1)) {
+   stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
+   if (!stbi__gif_header(s, g, comp, 1)) {
+      STBI_FREE(g);
       stbi__rewind( s );
       stbi__rewind( s );
       return 0;
       return 0;
    }
    }
-   if (x) *x = g.w;
-   if (y) *y = g.h;
+   if (x) *x = g->w;
+   if (y) *y = g->h;
+   STBI_FREE(g);
    return 1;
    return 1;
 }
 }
 
 
@@ -5908,20 +6042,20 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
 static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
 static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
 {
 {
    stbi_uc *u = 0;
    stbi_uc *u = 0;
-   stbi__gif g;
-   memset(&g, 0, sizeof(g));
+   stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
+   memset(g, 0, sizeof(*g));
 
 
-   u = stbi__gif_load_next(s, &g, comp, req_comp);
+   u = stbi__gif_load_next(s, g, comp, req_comp);
    if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
    if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
    if (u) {
    if (u) {
-      *x = g.w;
-      *y = g.h;
+      *x = g->w;
+      *y = g->h;
       if (req_comp && req_comp != 4)
       if (req_comp && req_comp != 4)
-         u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
+         u = stbi__convert_format(u, 4, req_comp, g->w, g->h);
    }
    }
-   else if (g.out)
-      STBI_FREE(g.out);
-
+   else if (g->out)
+      STBI_FREE(g->out);
+   STBI_FREE(g);
    return u;
    return u;
 }
 }
 
 
@@ -6459,6 +6593,13 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
 
 
 /*
 /*
    revision history:
    revision history:
+      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+      2.11  (2016-04-02) allocate large structures on the stack
+                         remove white matting for transparent PSD
+                         fix reported channel count for PNG & BMP
+                         re-enable SSE2 in non-gcc 64-bit
+                         support RGB-formatted JPEG
+                         read 16-bit PNGs (only as 8-bit)
       2.10  (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
       2.10  (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
       2.09  (2016-01-16) allow comments in PNM files
       2.09  (2016-01-16) allow comments in PNM files
                          16-bit-per-pixel TGA (not bit-per-component)
                          16-bit-per-pixel TGA (not bit-per-component)

+ 14 - 2
Source/ThirdParty/STB/stb_image_write.h

@@ -1,4 +1,4 @@
-/* stb_image_write - v1.01 - public domain - http://nothings.org/stb/stb_image_write.h
+/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h
    writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
    writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
                                      no warranty implied; use at your own risk
                                      no warranty implied; use at your own risk
 
 
@@ -102,6 +102,7 @@ CREDITS:
       Sergio Gonzalez
       Sergio Gonzalez
       Jonas Karlsson
       Jonas Karlsson
       Filip Wasil
       Filip Wasil
+      Thatcher Ulrich
       
       
 LICENSE
 LICENSE
 
 
@@ -111,6 +112,8 @@ publish, and distribute this file as you see fit.
 
 
 */
 */
 
 
+// Modified by Lasse Oorni for Urho3D
+
 #ifndef INCLUDE_STB_IMAGE_WRITE_H
 #ifndef INCLUDE_STB_IMAGE_WRITE_H
 #define INCLUDE_STB_IMAGE_WRITE_H
 #define INCLUDE_STB_IMAGE_WRITE_H
 
 
@@ -218,7 +221,13 @@ static void stbi__stdio_write(void *context, void *data, int size)
 
 
 static int stbi__start_write_file(stbi__write_context *s, const char *filename)
 static int stbi__start_write_file(stbi__write_context *s, const char *filename)
 {
 {
+   // Urho3D: proper UTF8 handling for Windows, requires Urho3D WString class
+#ifndef _WIN32
    FILE *f = fopen(filename, "wb");
    FILE *f = fopen(filename, "wb");
+#else
+    Urho3D::WString wstr(filename);
+    FILE *f = _wfopen(wstr.CString(), L"wb");
+#endif
    stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
    stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
    return f != NULL;
    return f != NULL;
 }
 }
@@ -736,7 +745,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
    unsigned int bitbuf=0;
    unsigned int bitbuf=0;
    int i,j, bitcount=0;
    int i,j, bitcount=0;
    unsigned char *out = NULL;
    unsigned char *out = NULL;
-   unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack!
+   unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
    if (quality < 5) quality = 5;
    if (quality < 5) quality = 5;
 
 
    stbiw__sbpush(out, 0x78);   // DEFLATE 32K window
    stbiw__sbpush(out, 0x78);   // DEFLATE 32K window
@@ -808,6 +817,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
 
 
    for (i=0; i < stbiw__ZHASH; ++i)
    for (i=0; i < stbiw__ZHASH; ++i)
       (void) stbiw__sbfree(hash_table[i]);
       (void) stbiw__sbfree(hash_table[i]);
+   STBIW_FREE(hash_table);
 
 
    {
    {
       // compute adler32 on input
       // compute adler32 on input
@@ -1015,6 +1025,8 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x,
 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
 
 
 /* Revision history
 /* Revision history
+      1.02 (2016-04-02)
+             avoid allocating large structures on the stack
       1.01 (2016-01-16)
       1.01 (2016-01-16)
              STBIW_REALLOC_SIZED: support allocators with no realloc support
              STBIW_REALLOC_SIZED: support allocators with no realloc support
              avoid race-condition in crc initialization
              avoid race-condition in crc initialization

+ 28 - 93
Source/ThirdParty/STB/stb_vorbis.h

@@ -1,4 +1,4 @@
-// Ogg Vorbis audio decoder - v1.07 - public domain
+// Ogg Vorbis audio decoder - v1.09 - public domain
 // http://nothings.org/stb_vorbis/
 // http://nothings.org/stb_vorbis/
 //
 //
 // Original version written by Sean Barrett in 2007.
 // Original version written by Sean Barrett in 2007.
@@ -31,11 +31,14 @@
 //    Terje Mathisen     Niklas Frykholm     Andy Hill
 //    Terje Mathisen     Niklas Frykholm     Andy Hill
 //    Casey Muratori     John Bolton         Gargaj
 //    Casey Muratori     John Bolton         Gargaj
 //    Laurent Gomila     Marc LeBlanc        Ronny Chevalier
 //    Laurent Gomila     Marc LeBlanc        Ronny Chevalier
-//    Bernhard Wodo      Evan Balster        "alxprd"@github
+//    Bernhard Wodo      Evan Balster        alxprd@github
 //    Tom Beaumont       Ingo Leitgeb        Nicolas Guillemot
 //    Tom Beaumont       Ingo Leitgeb        Nicolas Guillemot
-//    Phillip Bennefall  Rohit
+//    Phillip Bennefall  Rohit               Thiago Goulart
+//    manxorist@github   saga musix
 //
 //
 // Partial history:
 // Partial history:
+//    1.09    - 2016/04/04 - back out 'truncation of last frame' fix from previous version
+//    1.08    - 2016/04/02 - warnings; setup memory leaks; truncation of last frame
 //    1.07    - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
 //    1.07    - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
 //    1.06    - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
 //    1.06    - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
 //                           some crash fixes when out of memory or with corrupt files
 //                           some crash fixes when out of memory or with corrupt files
@@ -552,6 +555,9 @@ enum STBVorbisError
 #include <math.h>
 #include <math.h>
 #if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh))
 #if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh))
 #include <malloc.h>
 #include <malloc.h>
+#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__)
+#include <alloca.h>
+#endif
 #endif
 #endif
 #else // STB_VORBIS_NO_CRT
 #else // STB_VORBIS_NO_CRT
 #define NULL 0
 #define NULL 0
@@ -1868,85 +1874,6 @@ static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **out
    return TRUE;
    return TRUE;
 }
 }
 
 
-#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
-static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **outputs, int *c_inter_p, int *p_inter_p, int len, int total_decode)
-{
-   int c_inter = *c_inter_p;
-   int p_inter = *p_inter_p;
-   int i,z, effective = c->dimensions;
-
-   // type 0 is only legal in a scalar context
-   if (c->lookup_type == 0)   return error(f, VORBIS_invalid_stream);
-
-   while (total_decode > 0) {
-      float last = CODEBOOK_ELEMENT_BASE(c);
-      DECODE_VQ(z,f,c);
-
-      if (z < 0) {
-         if (!f->bytes_in_seg)
-            if (f->last_seg) return FALSE;
-         return error(f, VORBIS_invalid_stream);
-      }
-
-      // if this will take us off the end of the buffers, stop short!
-      // we check by computing the length of the virtual interleaved
-      // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter),
-      // and the length we'll be using (effective)
-      if (c_inter + p_inter*2 + effective > len * 2) {
-         effective = len*2 - (p_inter*2 - c_inter);
-      }
-
-      {
-         z *= c->dimensions;
-         if (c->sequence_p) {
-            // haven't optimized this case because I don't have any examples
-            for (i=0; i < effective; ++i) {
-               float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-               if (outputs[c_inter])
-                  outputs[c_inter][p_inter] += val;
-               if (++c_inter == 2) { c_inter = 0; ++p_inter; }
-               last = val;
-            }
-         } else {
-            i=0;
-            if (c_inter == 1 && i < effective) {
-               float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-               if (outputs[c_inter])
-                  outputs[c_inter][p_inter] += val;
-               c_inter = 0; ++p_inter;
-               ++i;
-            }
-            {
-               float *z0 = outputs[0];
-               float *z1 = outputs[1];
-               for (; i+1 < effective;) {
-                  float v0 = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-                  float v1 = CODEBOOK_ELEMENT_FAST(c,z+i+1) + last;
-                  if (z0)
-                     z0[p_inter] += v0;
-                  if (z1)
-                     z1[p_inter] += v1;
-                  ++p_inter;
-                  i += 2;
-               }
-            }
-            if (i < effective) {
-               float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-               if (outputs[c_inter])
-                  outputs[c_inter][p_inter] += val;
-               if (++c_inter == 2) { c_inter = 0; ++p_inter; }
-            }
-         }
-      }
-
-      total_decode -= effective;
-   }
-   *c_inter_p = c_inter;
-   *p_inter_p = p_inter;
-   return TRUE;
-}
-#endif
-
 static int predict_point(int x, int x0, int x1, int y0, int y1)
 static int predict_point(int x, int x0, int x1, int y0, int y1)
 {
 {
    int dy = y1 - y0;
    int dy = y1 - y0;
@@ -2325,6 +2252,11 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
    }
    }
   done:
   done:
    CHECK(f);
    CHECK(f);
+   #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
+   temp_free(f,part_classdata);
+   #else
+   temp_free(f,classifications);
+   #endif
    temp_alloc_restore(f,temp_alloc_point);
    temp_alloc_restore(f,temp_alloc_point);
 }
 }
 
 
@@ -2970,6 +2902,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
       }
       }
    }
    }
 
 
+   temp_free(f,buf2);
    temp_alloc_restore(f,save_point);
    temp_alloc_restore(f,save_point);
 }
 }
 
 
@@ -3883,7 +3816,6 @@ static int start_decoder(vorb *f)
                   }
                   }
                }
                }
             }
             }
-            setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
             c->lookup_type = 2;
             c->lookup_type = 2;
          }
          }
          else
          else
@@ -3899,11 +3831,11 @@ static int start_decoder(vorb *f)
                if (c->sequence_p)
                if (c->sequence_p)
                   last = val;
                   last = val;
             }
             }
-            setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
          }
          }
 #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
 #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
         skip:;
         skip:;
 #endif
 #endif
+         setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);
 
 
          CHECK(f);
          CHECK(f);
       }
       }
@@ -4429,7 +4361,7 @@ int stb_vorbis_decode_frame_pushdata(
          while (get8_packet(f) != EOP)
          while (get8_packet(f) != EOP)
             if (f->eof) break;
             if (f->eof) break;
          *samples = 0;
          *samples = 0;
-         return f->stream - data;
+         return (int) (f->stream - data);
       }
       }
       if (error == VORBIS_continued_packet_flag_invalid) {
       if (error == VORBIS_continued_packet_flag_invalid) {
          if (f->previous_length == 0) {
          if (f->previous_length == 0) {
@@ -4439,7 +4371,7 @@ int stb_vorbis_decode_frame_pushdata(
             while (get8_packet(f) != EOP)
             while (get8_packet(f) != EOP)
                if (f->eof) break;
                if (f->eof) break;
             *samples = 0;
             *samples = 0;
-            return f->stream - data;
+            return (int) (f->stream - data);
          }
          }
       }
       }
       // if we get an error while parsing, what to do?
       // if we get an error while parsing, what to do?
@@ -4459,7 +4391,7 @@ int stb_vorbis_decode_frame_pushdata(
    if (channels) *channels = f->channels;
    if (channels) *channels = f->channels;
    *samples = len;
    *samples = len;
    *output = f->outputs;
    *output = f->outputs;
-   return f->stream - data;
+   return (int) (f->stream - data);
 }
 }
 
 
 stb_vorbis *stb_vorbis_open_pushdata(
 stb_vorbis *stb_vorbis_open_pushdata(
@@ -4482,7 +4414,7 @@ stb_vorbis *stb_vorbis_open_pushdata(
    f = vorbis_alloc(&p);
    f = vorbis_alloc(&p);
    if (f) {
    if (f) {
       *f = p;
       *f = p;
-      *data_used = f->stream - data;
+      *data_used = (int) (f->stream - data);
       *error = 0;
       *error = 0;
       return f;
       return f;
    } else {
    } else {
@@ -4497,9 +4429,9 @@ unsigned int stb_vorbis_get_file_offset(stb_vorbis *f)
    #ifndef STB_VORBIS_NO_PUSHDATA_API
    #ifndef STB_VORBIS_NO_PUSHDATA_API
    if (f->push_mode) return 0;
    if (f->push_mode) return 0;
    #endif
    #endif
-   if (USE_MEMORY(f)) return f->stream - f->stream_start;
+   if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start);
    #ifndef STB_VORBIS_NO_STDIO
    #ifndef STB_VORBIS_NO_STDIO
-   return ftell(f->f) - f->f_start;
+   return (unsigned int) (ftell(f->f) - f->f_start);
    #endif
    #endif
 }
 }
 
 
@@ -4995,7 +4927,7 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er
    stb_vorbis *f, p;
    stb_vorbis *f, p;
    vorbis_init(&p, alloc);
    vorbis_init(&p, alloc);
    p.f = file;
    p.f = file;
-   p.f_start = ftell(file);
+   p.f_start = (uint32) ftell(file);
    p.stream_len   = length;
    p.stream_len   = length;
    p.close_on_free = close_on_free;
    p.close_on_free = close_on_free;
    if (start_decoder(&p)) {
    if (start_decoder(&p)) {
@@ -5014,9 +4946,9 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er
 stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc)
 stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc)
 {
 {
    unsigned int len, start;
    unsigned int len, start;
-   start = ftell(file);
+   start = (unsigned int) ftell(file);
    fseek(file, 0, SEEK_END);
    fseek(file, 0, SEEK_END);
-   len = ftell(file) - start;
+   len = (unsigned int) (ftell(file) - start);
    fseek(file, start, SEEK_SET);
    fseek(file, start, SEEK_SET);
    return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len);
    return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len);
 }
 }
@@ -5411,6 +5343,9 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
 #endif // STB_VORBIS_NO_PULLDATA_API
 #endif // STB_VORBIS_NO_PULLDATA_API
 
 
 /* Version history
 /* Version history
+    1.09    - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version
+    1.08    - 2016/04/02 - fixed multiple warnings; fix setup memory leaks;
+                           avoid discarding last frame of audio data
     1.07    - 2015/01/16 - fixed some warnings, fix mingw, const-correct API
     1.07    - 2015/01/16 - fixed some warnings, fix mingw, const-correct API
                            some more crash fixes when out of memory or with corrupt files 
                            some more crash fixes when out of memory or with corrupt files 
     1.06    - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
     1.06    - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)

+ 32 - 1
Source/Tools/AssetImporter/AssetImporter.cpp

@@ -135,6 +135,7 @@ void Run(const Vector<String>& arguments);
 void DumpNodes(aiNode* rootNode, unsigned level);
 void DumpNodes(aiNode* rootNode, unsigned level);
 
 
 void ExportModel(const String& outName, bool animationOnly);
 void ExportModel(const String& outName, bool animationOnly);
+void ExportAnimation(const String& outName, bool animationOnly);
 void CollectMeshes(OutModel& model, aiNode* node);
 void CollectMeshes(OutModel& model, aiNode* node);
 void CollectBones(OutModel& model, bool animationOnly = false);
 void CollectBones(OutModel& model, bool animationOnly = false);
 void CollectBonesFinal(PODVector<aiNode*>& dest, const HashSet<aiNode*>& necessary, aiNode* node);
 void CollectBonesFinal(PODVector<aiNode*>& dest, const HashSet<aiNode*>& necessary, aiNode* node);
@@ -213,6 +214,7 @@ void Run(const Vector<String>& arguments)
             "See http://assimp.sourceforge.net/main_features_formats.html for input formats\n\n"
             "See http://assimp.sourceforge.net/main_features_formats.html for input formats\n\n"
             "Commands:\n"
             "Commands:\n"
             "model       Output a model\n"
             "model       Output a model\n"
+            "anim        Output animation(s)\n"
             "scene       Output a scene\n"
             "scene       Output a scene\n"
             "node        Output a node and its children (prefab)\n"
             "node        Output a node and its children (prefab)\n"
             "dump        Dump scene node structure. No output file is generated\n"
             "dump        Dump scene node structure. No output file is generated\n"
@@ -410,7 +412,7 @@ void Run(const Vector<String>& arguments)
         }
         }
     }
     }
 
 
-    if (command == "model" || command == "scene" || command == "node" || command == "dump")
+    if (command == "model" || command == "scene" || command == "anim" || command == "node" || command == "dump")
     {
     {
         String inFile = arguments[1];
         String inFile = arguments[1];
         String outFile;
         String outFile;
@@ -467,6 +469,11 @@ void Run(const Vector<String>& arguments)
         if (command == "model")
         if (command == "model")
             ExportModel(outFile, scene_->mFlags & AI_SCENE_FLAGS_INCOMPLETE);
             ExportModel(outFile, scene_->mFlags & AI_SCENE_FLAGS_INCOMPLETE);
 
 
+        if (command == "anim")
+        {
+            noMaterials_ = true;
+            ExportAnimation(outFile, scene_->mFlags & AI_SCENE_FLAGS_INCOMPLETE);
+        }
         if (command == "scene" || command == "node")
         if (command == "scene" || command == "node")
         {
         {
             bool asPrefab = command == "node";
             bool asPrefab = command == "node";
@@ -573,6 +580,30 @@ void ExportModel(const String& outName, bool animationOnly)
     }
     }
 }
 }
 
 
+void ExportAnimation(const String& outName, bool animationOnly)
+{
+    if (outName.Empty())
+        ErrorExit("No output file defined");
+
+    OutModel model;
+    model.rootNode_ = rootNode_;
+    model.outName_ = outName;
+
+    CollectMeshes(model, model.rootNode_);
+    CollectBones(model, animationOnly);
+    BuildBoneCollisionInfo(model);
+    //    BuildAndSaveModel(model);
+    if (!noAnimations_)
+    {
+        CollectAnimations(&model);
+        BuildAndSaveAnimations(&model);
+
+        // Save scene-global animations
+        CollectAnimations();
+        BuildAndSaveAnimations();
+    }
+}
+
 void CollectMeshes(OutModel& model, aiNode* node)
 void CollectMeshes(OutModel& model, aiNode* node)
 {
 {
     for (unsigned i = 0; i < node->mNumMeshes; ++i)
     for (unsigned i = 0; i < node->mNumMeshes; ++i)

+ 1 - 0
Source/Tools/PackageTool/CMakeLists.txt

@@ -58,6 +58,7 @@ if (NOT CMAKE_PROJECT_NAME STREQUAL Urho3D)
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Container/Str.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Container/Str.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Container/VectorBase.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Container/VectorBase.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/Context.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/Context.cpp
+        ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/EventProfiler.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/Mutex.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/Mutex.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/Object.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/Object.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/ProcessUtils.cpp
         ${BAKED_CMAKE_SOURCE_DIR}/Source/Urho3D/Core/ProcessUtils.cpp

+ 1 - 1
Source/Urho3D/.soversion

@@ -1 +1 @@
-0.0.222
+0.0.230

+ 6 - 0
Source/Urho3D/AngelScript/CoreAPI.cpp

@@ -887,6 +887,11 @@ static bool HasSubscribedToSenderEvent(Object* sender, const String& eventType)
     return listener ? listener->HasEventHandler(sender, StringHash(eventType)) : false;
     return listener ? listener->HasEventHandler(sender, StringHash(eventType)) : false;
 }
 }
 
 
+static void RegisterEventName(const String& eventName)
+{
+    EventNameRegistrar::RegisterEventName(eventName.CString());
+}
+
 static Object* GetEventSender()
 static Object* GetEventSender()
 {
 {
     return GetScriptContext()->GetEventSender();
     return GetScriptContext()->GetEventSender();
@@ -957,6 +962,7 @@ void RegisterObject(asIScriptEngine* engine)
     engine->RegisterGlobalFunction("void UnsubscribeFromAllEventsExcept(Array<String>@+)", asFUNCTION(UnsubscribeFromAllEventsExcept), asCALL_CDECL);
     engine->RegisterGlobalFunction("void UnsubscribeFromAllEventsExcept(Array<String>@+)", asFUNCTION(UnsubscribeFromAllEventsExcept), asCALL_CDECL);
     engine->RegisterGlobalFunction("bool HasSubscribedToEvent(const String&in)", asFUNCTION(HasSubscribedToEvent), asCALL_CDECL);
     engine->RegisterGlobalFunction("bool HasSubscribedToEvent(const String&in)", asFUNCTION(HasSubscribedToEvent), asCALL_CDECL);
     engine->RegisterGlobalFunction("bool HasSubscribedToEvent(Object@+, const String&in)", asFUNCTION(HasSubscribedToSenderEvent), asCALL_CDECL);
     engine->RegisterGlobalFunction("bool HasSubscribedToEvent(Object@+, const String&in)", asFUNCTION(HasSubscribedToSenderEvent), asCALL_CDECL);
+    engine->RegisterGlobalFunction("void RegisterEventName(const String&in)", asFUNCTION(RegisterEventName), asCALL_CDECL);
     engine->RegisterGlobalFunction("Object@+ GetEventSender()", asFUNCTION(GetEventSender), asCALL_CDECL);
     engine->RegisterGlobalFunction("Object@+ GetEventSender()", asFUNCTION(GetEventSender), asCALL_CDECL);
     engine->RegisterGlobalFunction("const String& GetTypeName(StringHash)", asFUNCTION(GetTypeName), asCALL_CDECL);
     engine->RegisterGlobalFunction("const String& GetTypeName(StringHash)", asFUNCTION(GetTypeName), asCALL_CDECL);
     engine->RegisterGlobalFunction("void SetGlobalVar(const String&in, Variant&in)", asFUNCTION(SetGlobalVar), asCALL_CDECL);
     engine->RegisterGlobalFunction("void SetGlobalVar(const String&in, Variant&in)", asFUNCTION(SetGlobalVar), asCALL_CDECL);

+ 1 - 0
Source/Urho3D/AngelScript/EngineAPI.cpp

@@ -76,6 +76,7 @@ static void RegisterDebugHud(asIScriptEngine* engine)
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_STATS", (void*)&DEBUGHUD_SHOW_STATS);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_STATS", (void*)&DEBUGHUD_SHOW_STATS);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_MODE", (void*)&DEBUGHUD_SHOW_MODE);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_MODE", (void*)&DEBUGHUD_SHOW_MODE);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_PROFILER", (void*)&DEBUGHUD_SHOW_PROFILER);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_PROFILER", (void*)&DEBUGHUD_SHOW_PROFILER);
+    engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_EVENTPROFILER", (void*)&DEBUGHUD_SHOW_EVENTPROFILER);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_MEMORY", (void*)&DEBUGHUD_SHOW_MEMORY);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_MEMORY", (void*)&DEBUGHUD_SHOW_MEMORY);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_ALL", (void*)&DEBUGHUD_SHOW_ALL);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_ALL", (void*)&DEBUGHUD_SHOW_ALL);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_ALL_MEMORY", (void*)&DEBUGHUD_SHOW_ALL_MEMORY);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_ALL_MEMORY", (void*)&DEBUGHUD_SHOW_ALL_MEMORY);

+ 6 - 0
Source/Urho3D/AngelScript/GraphicsAPI.cpp

@@ -1458,6 +1458,8 @@ static void RegisterBillboardSet(asIScriptEngine* engine)
     engine->RegisterObjectMethod("BillboardSet", "bool get_sorted() const", asMETHOD(BillboardSet, IsSorted), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "bool get_sorted() const", asMETHOD(BillboardSet, IsSorted), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "void set_scaled(bool)", asMETHOD(BillboardSet, SetScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "void set_scaled(bool)", asMETHOD(BillboardSet, SetScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "bool get_scaled() const", asMETHOD(BillboardSet, IsScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "bool get_scaled() const", asMETHOD(BillboardSet, IsScaled), asCALL_THISCALL);
+    engine->RegisterObjectMethod("BillboardSet", "void set_fixedScreenSize(bool)", asMETHOD(BillboardSet, SetFixedScreenSize), asCALL_THISCALL);
+    engine->RegisterObjectMethod("BillboardSet", "bool get_fixedScreenSize() const", asMETHOD(BillboardSet, IsFixedScreenSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "void set_faceCameraMode(FaceCameraMode)", asMETHOD(BillboardSet, SetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "void set_faceCameraMode(FaceCameraMode)", asMETHOD(BillboardSet, SetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "FaceCameraMode get_faceCameraMode() const", asMETHOD(BillboardSet, GetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "FaceCameraMode get_faceCameraMode() const", asMETHOD(BillboardSet, GetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "void set_animationLodBias(float)", asMETHOD(BillboardSet, SetAnimationLodBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("BillboardSet", "void set_animationLodBias(float)", asMETHOD(BillboardSet, SetAnimationLodBias), asCALL_THISCALL);
@@ -1499,6 +1501,8 @@ static void RegisterParticleEffect(asIScriptEngine* engine)
     engine->RegisterObjectMethod("ParticleEffect", "bool get_sorted() const", asMETHOD(ParticleEffect, IsSorted), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "bool get_sorted() const", asMETHOD(ParticleEffect, IsSorted), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_scaled(bool)", asMETHOD(ParticleEffect, SetScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_scaled(bool)", asMETHOD(ParticleEffect, SetScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "bool get_scaled() const", asMETHOD(ParticleEffect, IsScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "bool get_scaled() const", asMETHOD(ParticleEffect, IsScaled), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ParticleEffect", "void set_fixedScreenSize(bool)", asMETHOD(ParticleEffect, SetFixedScreenSize), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ParticleEffect", "bool get_fixedScreenSize() const", asMETHOD(ParticleEffect, IsFixedScreenSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_animationLodBias(float)", asMETHOD(ParticleEffect, SetAnimationLodBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_animationLodBias(float)", asMETHOD(ParticleEffect, SetAnimationLodBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "float get_animationLodBias() const", asMETHOD(ParticleEffect, GetAnimationLodBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "float get_animationLodBias() const", asMETHOD(ParticleEffect, GetAnimationLodBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_emitterType(EmitterType)", asMETHOD(ParticleEffect, SetEmitterType), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_emitterType(EmitterType)", asMETHOD(ParticleEffect, SetEmitterType), asCALL_THISCALL);
@@ -1582,6 +1586,8 @@ static void RegisterParticleEmitter(asIScriptEngine* engine)
     engine->RegisterObjectMethod("ParticleEmitter", "bool get_sorted() const", asMETHOD(ParticleEmitter, IsSorted), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "bool get_sorted() const", asMETHOD(ParticleEmitter, IsSorted), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "void set_scaled(bool)", asMETHOD(ParticleEmitter, SetScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "void set_scaled(bool)", asMETHOD(ParticleEmitter, SetScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "bool get_scaled() const", asMETHOD(ParticleEmitter, IsScaled), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "bool get_scaled() const", asMETHOD(ParticleEmitter, IsScaled), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ParticleEmitter", "void set_fixedScreenSize(bool)", asMETHOD(ParticleEmitter, SetFixedScreenSize), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ParticleEmitter", "bool get_fixedScreenSize() const", asMETHOD(ParticleEmitter, IsFixedScreenSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "void set_faceCameraMode(FaceCameraMode)", asMETHOD(ParticleEmitter, SetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "void set_faceCameraMode(FaceCameraMode)", asMETHOD(ParticleEmitter, SetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "FaceCameraMode get_faceCameraMode() const", asMETHOD(ParticleEmitter, GetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "FaceCameraMode get_faceCameraMode() const", asMETHOD(ParticleEmitter, GetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "void set_animationLodBias(float)", asMETHOD(ParticleEmitter, SetAnimationLodBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEmitter", "void set_animationLodBias(float)", asMETHOD(ParticleEmitter, SetAnimationLodBias), asCALL_THISCALL);

+ 21 - 0
Source/Urho3D/AngelScript/IOAPI.cpp

@@ -25,6 +25,7 @@
 #include "../AngelScript/APITemplates.h"
 #include "../AngelScript/APITemplates.h"
 #include "../IO/Compression.h"
 #include "../IO/Compression.h"
 #include "../IO/FileSystem.h"
 #include "../IO/FileSystem.h"
+#include "../IO/NamedPipe.h"
 #include "../IO/PackageFile.h"
 #include "../IO/PackageFile.h"
 
 
 namespace Urho3D
 namespace Urho3D
@@ -169,6 +170,16 @@ static File* ConstructFileAndOpen(const String& fileName, FileMode mode)
     return new File(GetScriptContext(), fileName, mode);
     return new File(GetScriptContext(), fileName, mode);
 }
 }
 
 
+static NamedPipe* ConstructNamedPipe()
+{
+    return new NamedPipe(GetScriptContext());
+}
+
+static NamedPipe* ConstructNamedPipeAndOpen(const String& fileName, bool isServer)
+{
+    return new NamedPipe(GetScriptContext(), fileName, isServer);
+}
+
 static void ConstructVectorBuffer(VectorBuffer* ptr)
 static void ConstructVectorBuffer(VectorBuffer* ptr)
 {
 {
     new(ptr) VectorBuffer();
     new(ptr) VectorBuffer();
@@ -291,6 +302,16 @@ static void RegisterSerialization(asIScriptEngine* engine)
     RegisterSerializer<File>(engine, "File");
     RegisterSerializer<File>(engine, "File");
     RegisterDeserializer<File>(engine, "File");
     RegisterDeserializer<File>(engine, "File");
 
 
+    RegisterObject<NamedPipe>(engine, "NamedPipe");
+    engine->RegisterObjectBehaviour("NamedPipe", asBEHAVE_FACTORY, "NamedPipe@+ f()", asFUNCTION(ConstructNamedPipe), asCALL_CDECL);
+    engine->RegisterObjectBehaviour("NamedPipe", asBEHAVE_FACTORY, "NamedPipe@+ f(const String&in, bool)", asFUNCTION(ConstructNamedPipeAndOpen), asCALL_CDECL);
+    engine->RegisterObjectMethod("NamedPipe", "bool Open(const String&in, bool)", asMETHODPR(NamedPipe, Open, (const String&, bool), bool), asCALL_THISCALL);
+    engine->RegisterObjectMethod("NamedPipe", "void Close()", asMETHOD(NamedPipe, Close), asCALL_THISCALL);
+    engine->RegisterObjectMethod("NamedPipe", "bool get_server() const", asMETHOD(NamedPipe, IsServer), asCALL_THISCALL);
+    engine->RegisterObjectMethod("NamedPipe", "bool get_open() const", asMETHOD(NamedPipe, IsOpen), asCALL_THISCALL);
+    RegisterSerializer<File>(engine, "NamedPipe");
+    RegisterDeserializer<File>(engine, "NamedPipe");
+
     engine->RegisterObjectBehaviour("VectorBuffer", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructVectorBuffer), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("VectorBuffer", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructVectorBuffer), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("VectorBuffer", asBEHAVE_CONSTRUCT, "void f(const VectorBuffer&in)", asFUNCTION(ConstructVectorBufferCopy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("VectorBuffer", asBEHAVE_CONSTRUCT, "void f(const VectorBuffer&in)", asFUNCTION(ConstructVectorBufferCopy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("VectorBuffer", asBEHAVE_CONSTRUCT, "void f(Deserializer@+, uint)", asFUNCTION(ConstructVectorBufferFromStream), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("VectorBuffer", asBEHAVE_CONSTRUCT, "void f(Deserializer@+, uint)", asFUNCTION(ConstructVectorBufferFromStream), asCALL_CDECL_OBJLAST);

+ 1 - 0
Source/Urho3D/AngelScript/ResourceAPI.cpp

@@ -360,6 +360,7 @@ static bool JSONFileSave(File* file, const String& indendation, JSONFile* ptr)
 static void RegisterJSONFile(asIScriptEngine* engine)
 static void RegisterJSONFile(asIScriptEngine* engine)
 {
 {
     RegisterResource<JSONFile>(engine, "JSONFile");
     RegisterResource<JSONFile>(engine, "JSONFile");
+    engine->RegisterObjectMethod("JSONFile", "bool FromString(const String&in)", asMETHOD(JSONFile, FromString), asCALL_THISCALL);
     engine->RegisterObjectMethod("JSONFile", "JSONValue& GetRoot()", asMETHODPR(JSONFile, GetRoot, () const, const JSONValue&), asCALL_THISCALL);
     engine->RegisterObjectMethod("JSONFile", "JSONValue& GetRoot()", asMETHODPR(JSONFile, GetRoot, () const, const JSONValue&), asCALL_THISCALL);
     engine->RegisterObjectMethod("JSONFile", "bool Save(File@+, const String&in) const", asFUNCTION(JSONFileSave), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("JSONFile", "bool Save(File@+, const String&in) const", asFUNCTION(JSONFileSave), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("JSONFile", "JSONValue& get_root()", asMETHODPR(JSONFile, GetRoot, () const, const JSONValue&), asCALL_THISCALL);
     engine->RegisterObjectMethod("JSONFile", "JSONValue& get_root()", asMETHODPR(JSONFile, GetRoot, () const, const JSONValue&), asCALL_THISCALL);

+ 6 - 4
Source/Urho3D/AngelScript/UIAPI.cpp

@@ -386,8 +386,8 @@ static void RegisterText(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Text", "const Color& get_hoverColor() const", asMETHOD(Text, GetHoverColor), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "const Color& get_hoverColor() const", asMETHOD(Text, GetHoverColor), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "void set_textEffect(TextEffect)", asMETHOD(Text, SetTextEffect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "void set_textEffect(TextEffect)", asMETHOD(Text, SetTextEffect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "TextEffect get_textEffect() const", asMETHOD(Text, GetTextEffect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "TextEffect get_textEffect() const", asMETHOD(Text, GetTextEffect), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Text", "void set_effectShadowOffset(IntVector2)", asMETHOD(Text, SetEffectShadowOffset), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Text", "IntVector2 get_effectShadowOffset() const", asMETHOD(Text, GetEffectShadowOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Text", "void set_effectShadowOffset(const IntVector2&in)", asMETHOD(Text, SetEffectShadowOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Text", "const IntVector2& get_effectShadowOffset() const", asMETHOD(Text, GetEffectShadowOffset), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "void set_effectStrokeThickness(int)", asMETHOD(Text, SetEffectStrokeThickness), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "void set_effectStrokeThickness(int)", asMETHOD(Text, SetEffectStrokeThickness), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "int get_effectStrokeThickness() const", asMETHOD(Text, GetEffectStrokeThickness), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "int get_effectStrokeThickness() const", asMETHOD(Text, GetEffectStrokeThickness), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "void set_effectRoundStroke(bool)", asMETHOD(Text, SetEffectRoundStroke), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text", "void set_effectRoundStroke(bool)", asMETHOD(Text, SetEffectRoundStroke), asCALL_THISCALL);
@@ -426,8 +426,8 @@ static void RegisterText3D(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Text3D", "bool get_wordwrap() const", asMETHOD(Text3D, GetWordwrap), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "bool get_wordwrap() const", asMETHOD(Text3D, GetWordwrap), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_textEffect(TextEffect)", asMETHOD(Text3D, SetTextEffect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_textEffect(TextEffect)", asMETHOD(Text3D, SetTextEffect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "TextEffect get_textEffect() const", asMETHOD(Text3D, GetTextEffect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "TextEffect get_textEffect() const", asMETHOD(Text3D, GetTextEffect), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Text3D", "void set_effectShadowOffset(IntVector2)", asMETHOD(Text3D, SetEffectShadowOffset), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Text3D", "IntVector2 get_effectShadowOffset() const", asMETHOD(Text3D, GetEffectShadowOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Text3D", "void set_effectShadowOffset(const IntVector2&in)", asMETHOD(Text3D, SetEffectShadowOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Text3D", "const IntVector2& get_effectShadowOffset() const", asMETHOD(Text3D, GetEffectShadowOffset), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_effectStrokeThickness(int)", asMETHOD(Text3D, SetEffectStrokeThickness), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_effectStrokeThickness(int)", asMETHOD(Text3D, SetEffectStrokeThickness), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "int get_effectStrokeThickness() const", asMETHOD(Text3D, GetEffectStrokeThickness), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "int get_effectStrokeThickness() const", asMETHOD(Text3D, GetEffectStrokeThickness), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_effectRoundStroke(bool)", asMETHOD(Text3D, SetEffectRoundStroke), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_effectRoundStroke(bool)", asMETHOD(Text3D, SetEffectRoundStroke), asCALL_THISCALL);
@@ -443,6 +443,8 @@ static void RegisterText3D(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Text3D", "const Color& get_colors(Corner) const", asMETHOD(Text3D, GetColor), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "const Color& get_colors(Corner) const", asMETHOD(Text3D, GetColor), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_opacity(float)", asMETHOD(Text3D, SetOpacity), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_opacity(float)", asMETHOD(Text3D, SetOpacity), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "float get_opacity() const", asMETHOD(Text3D, GetOpacity), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "float get_opacity() const", asMETHOD(Text3D, GetOpacity), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Text3D", "void set_fixedScreenSize(bool)", asMETHOD(Text3D, SetFixedScreenSize), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Text3D", "bool get_fixedScreenSize() const", asMETHOD(Text3D, IsFixedScreenSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_faceCameraMode(FaceCameraMode)", asMETHOD(Text3D, SetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "void set_faceCameraMode(FaceCameraMode)", asMETHOD(Text3D, SetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "FaceCameraMode get_faceCameraMode() const", asMETHOD(Text3D, GetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "FaceCameraMode get_faceCameraMode() const", asMETHOD(Text3D, GetFaceCameraMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "uint get_numRows() const", asMETHOD(Text3D, GetNumRows), asCALL_THISCALL);
     engine->RegisterObjectMethod("Text3D", "uint get_numRows() const", asMETHOD(Text3D, GetNumRows), asCALL_THISCALL);

+ 1 - 1
Source/Urho3D/Audio/SoundSource.h

@@ -35,7 +35,7 @@ class SoundStream;
 // Compressed audio decode buffer length in milliseconds
 // Compressed audio decode buffer length in milliseconds
 static const int STREAM_BUFFER_LENGTH = 100;
 static const int STREAM_BUFFER_LENGTH = 100;
 
 
-/// %Sound source component with stereo position.
+/// %Sound source component with stereo position. A sound source needs to be created to a node to be considered "enabled" and be able to play, however that node does not need to belong to a scene.
 class URHO3D_API SoundSource : public Component
 class URHO3D_API SoundSource : public Component
 {
 {
     URHO3D_OBJECT(SoundSource, Component);
     URHO3D_OBJECT(SoundSource, Component);

+ 177 - 0
Source/Urho3D/Core/EventProfiler.cpp

@@ -0,0 +1,177 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "../Precompiled.h"
+
+#include "../Core/CoreEvents.h"
+#include "../Core/EventProfiler.h"
+
+#include <cstdio>
+
+#include "../DebugNew.h"
+
+namespace Urho3D
+{
+
+static const int LINE_MAX_LENGTH = 256;
+static const int NAME_MAX_LENGTH = 30;
+
+bool EventProfiler::active = false;
+
+EventProfiler::EventProfiler(Context* context) : 
+    Object(context),
+    current_(0),
+    root_(0),
+    intervalFrames_(0),
+    totalFrames_(0)
+{
+    root_ = new EventProfilerBlock(0, "Root");
+    current_ = root_;
+    current_->name_ = "Root";
+}
+
+EventProfiler::~EventProfiler()
+{
+    delete root_;
+    root_ = 0;
+}
+
+void EventProfiler::SetActive(bool newActive)
+{
+    active = newActive;
+}
+
+void EventProfiler::BeginFrame()
+{
+    // End the previous frame if any
+    EndFrame();
+
+    BeginBlock("RunFrame");
+    current_->name_ = "RunFrame";
+}
+
+void EventProfiler::EndFrame()
+{
+    if (current_ != root_)
+    {
+        EndBlock();
+        ++intervalFrames_;
+        ++totalFrames_;
+        if (!totalFrames_)
+            ++totalFrames_;
+        root_->EndFrame();
+        current_ = root_;
+    }
+}
+
+void EventProfiler::BeginInterval()
+{
+
+    root_->BeginInterval();
+    intervalFrames_ = 0;
+}
+
+void EventProfiler::Clear()
+{
+    delete root_;
+    root_ = new EventProfilerBlock(0, "Root");
+    current_ = root_;
+    current_->name_ = "Root";
+}
+
+Urho3D::String EventProfiler::PrintData(bool showUnused /*= false*/, bool showTotal /*= false*/, unsigned maxDepth /*= M_MAX_UNSIGNED*/) const
+{
+    String output;
+
+    if (!showTotal)
+        output += "Block                            Cnt     Avg      Max     Frame     Total\n\n";
+    else
+    {
+        output += "Block                                       Last frame                       Whole execution time\n\n";
+        output += "                                 Cnt     Avg      Max      Total      Cnt      Avg       Max        Total\n\n";
+    }
+
+    if (!maxDepth)
+        maxDepth = 1;
+
+    PrintData(root_, output, 0, maxDepth, showUnused, showTotal);
+
+    return output;
+}
+
+void EventProfiler::PrintData(EventProfilerBlock* block, String& output, unsigned depth, unsigned maxDepth, bool showUnused, bool showTotal) const
+{
+    char line[LINE_MAX_LENGTH];
+    char indentedName[LINE_MAX_LENGTH];
+
+    unsigned intervalFrames = Max(intervalFrames_, 1U);
+
+    if (depth >= maxDepth)
+        return;
+
+    // Do not print the root block as it does not collect any actual data
+    if (block != root_)
+    {
+        if (showUnused || block->intervalCount_ || (showTotal && block->totalCount_))
+        {
+            memset(indentedName, ' ', NAME_MAX_LENGTH);
+            indentedName[depth] = 0;
+
+            strcat(indentedName, block->name_.Empty() ? block->eventID_.ToString().CString() : block->name_.CString());
+            indentedName[strlen(indentedName)] = ' ';
+            indentedName[NAME_MAX_LENGTH] = 0;
+
+            if (!showTotal)
+            {
+                float avg = (block->intervalCount_ ? block->intervalTime_ / block->intervalCount_ : 0.0f) / 1000.0f;
+                float max = block->intervalMaxTime_ / 1000.0f;
+                float frame = block->intervalTime_ / intervalFrames / 1000.0f;
+                float all = block->intervalTime_ / 1000.0f;
+
+                sprintf(line, "%s %5u %8.3f %8.3f %8.3f %9.3f\n", indentedName, Min(block->intervalCount_, 99999U),
+                    avg, max, frame, all);
+            }
+            else
+            {
+                float avg = (block->frameCount_ ? block->frameTime_ / block->frameCount_ : 0.0f) / 1000.0f;
+                float max = block->frameMaxTime_ / 1000.0f;
+                float all = block->frameTime_ / 1000.0f;
+
+                float totalAvg = (block->totalCount_ ? block->totalTime_ / block->totalCount_ : 0.0f) / 1000.0f;
+                float totalMax = block->totalMaxTime_ / 1000.0f;
+                float totalAll = block->totalTime_ / 1000.0f;
+
+                sprintf(line, "%s %5u %8.3f %8.3f %9.3f  %7u %9.3f %9.3f %11.3f\n", indentedName, Min(block->frameCount_, 99999U),
+                    avg, max, all, Min(block->totalCount_, 99999U), totalAvg, totalMax, totalAll);
+            }
+
+            output += String(line);
+        }
+
+        ++depth;
+    }
+
+    for (HashMap<StringHash, EventProfilerBlock*>::ConstIterator i = block->children_.Begin(); i != block->children_.End(); ++i)
+        PrintData(i->second_, output, depth, maxDepth, showUnused, showTotal);
+}
+
+}

+ 235 - 0
Source/Urho3D/Core/EventProfiler.h

@@ -0,0 +1,235 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "../Container/Str.h"
+#include "../Core/Thread.h"
+#include "../Core/Timer.h"
+
+#include "../Core/Profiler.h"
+
+
+namespace Urho3D
+{
+/// Event profiling data for one block in the event profiling tree.
+class URHO3D_API EventProfilerBlock
+{
+public:
+    /// Construct with the specified parent block and event id.
+    EventProfilerBlock(EventProfilerBlock* parent, StringHash eventID) :
+        eventID_(eventID),
+        name_(0),
+        time_(0),
+        maxTime_(0),
+        count_(0),
+        parent_(parent),
+        frameTime_(0),
+        frameMaxTime_(0),
+        frameCount_(0),
+        intervalTime_(0),
+        intervalMaxTime_(0),
+        intervalCount_(0),
+        totalTime_(0),
+        totalMaxTime_(0),
+        totalCount_(0)
+    {
+        name_ = EventNameRegistrar::GetEventName(eventID);
+    }
+
+    /// Destruct. Free the child blocks.
+    ~EventProfilerBlock()
+    {
+        for (HashMap<StringHash, EventProfilerBlock* >::Iterator i = children_.Begin(); i != children_.End(); ++i)
+        {
+            delete i->second_;
+            i->second_ = 0;
+        }
+    }
+
+    /// Begin timing.
+    void Begin()
+    {
+        timer_.Reset();
+        ++count_;
+    }
+
+    /// End timing.
+    void End()
+    {
+        long long time = timer_.GetUSec(false);
+        if (time > maxTime_)
+            maxTime_ = time;
+        time_ += time;
+    }
+
+    /// End profiling frame and update interval and total values.
+    void EndFrame()
+    {
+        frameTime_ = time_;
+        frameMaxTime_ = maxTime_;
+        frameCount_ = count_;
+        intervalTime_ += time_;
+        if (maxTime_ > intervalMaxTime_)
+            intervalMaxTime_ = maxTime_;
+        intervalCount_ += count_;
+        totalTime_ += time_;
+        if (maxTime_ > totalMaxTime_)
+            totalMaxTime_ = maxTime_;
+        totalCount_ += count_;
+        time_ = 0;
+        maxTime_ = 0;
+        count_ = 0;
+
+        for (HashMap<StringHash, EventProfilerBlock* >::Iterator i = children_.Begin(); i != children_.End(); ++i)
+            i->second_->EndFrame();
+    }
+
+    /// Begin new profiling interval.
+    void BeginInterval()
+    {
+        intervalTime_ = 0;
+        intervalMaxTime_ = 0;
+        intervalCount_ = 0;
+
+        for (HashMap<StringHash, EventProfilerBlock*>::Iterator i = children_.Begin(); i != children_.End(); ++i)
+            i->second_->BeginInterval();
+    }
+
+    /// Return child block with the specified name.
+    EventProfilerBlock* GetChild(StringHash eventID)
+    {
+        HashMap<StringHash, EventProfilerBlock*>::Iterator it = children_.Find(eventID);
+        if (it != children_.End())
+            return it->second_;
+
+        EventProfilerBlock* newBlock = new EventProfilerBlock(this, eventID);
+        children_[eventID] = newBlock;
+
+        return newBlock;
+    }
+    /// Event ID.
+    StringHash eventID_;
+    /// Block name.
+    String name_;
+    /// High-resolution timer for measuring the block duration.
+    HiresTimer timer_;
+    /// Time on current frame.
+    long long time_;
+    /// Maximum time on current frame.
+    long long maxTime_;
+    /// Calls on current frame.
+    unsigned count_;
+    /// Parent block.
+    EventProfilerBlock* parent_;
+    /// Child blocks.
+    HashMap<StringHash,EventProfilerBlock*> children_;
+    /// Time on the previous frame.
+    long long frameTime_;
+    /// Maximum time on the previous frame.
+    long long frameMaxTime_;
+    /// Calls on the previous frame.
+    unsigned frameCount_;
+    /// Time during current profiler interval.
+    long long intervalTime_;
+    /// Maximum time during current profiler interval.
+    long long intervalMaxTime_;
+    /// Calls during current profiler interval.
+    unsigned intervalCount_;
+    /// Total accumulated time.
+    long long totalTime_;
+    /// All-time maximum time.
+    long long totalMaxTime_;
+    /// Total accumulated calls.
+    unsigned totalCount_;
+};
+
+/// Hierarchical performance event profiler subsystem.
+class URHO3D_API EventProfiler : public Object
+{
+    URHO3D_OBJECT(EventProfiler, Object);
+
+public:
+    /// Construct.
+    EventProfiler(Context* context);
+    /// Destruct.
+    virtual ~EventProfiler();
+
+    /// Activate the event profiler to collect information. This incurs slight performance hit on each SendEvent. By default inactive.
+    static void SetActive(bool active);
+    /// Return true if active.
+    static bool IsActive() { return active; }
+
+    /// Begin timing a profiling block.
+    void BeginBlock(StringHash eventID)
+    {
+        // Profiler supports only the main thread currently
+        if ( !Thread::IsMainThread())
+            return;
+
+        current_ = current_->GetChild(eventID);
+        current_->Begin();
+    }
+
+    /// End timing the current profiling block.
+    void EndBlock()
+    {
+        if (!Thread::IsMainThread())
+            return;
+
+        if (current_ != root_)
+        {
+            current_->End();
+            current_ = current_->parent_;
+        }
+    }
+
+    /// Begin the profiling frame. Called by Engine::RunFrame().
+    void BeginFrame();
+    /// End the profiling frame. Called by Engine::RunFrame().
+    void EndFrame();
+    /// Begin a new interval.
+    void BeginInterval();
+    /// Delete all blocks and recreate root block.
+    void Clear();
+    /// Return profiling data as text output.
+    String PrintData(bool showUnused = false, bool showTotal = false, unsigned maxDepth = M_MAX_UNSIGNED) const;
+    /// Return the current profiling block.
+    const EventProfilerBlock* GetCurrentBlock() { return current_; }
+    /// Return the root profiling block.
+    const EventProfilerBlock* GetRootBlock() { return root_; }
+private:
+    /// Return profiling data as text output for a specified profiling block.
+    void PrintData(EventProfilerBlock* block, String& output, unsigned depth, unsigned maxDepth, bool showUnused, bool showTotal) const;
+    /// Current profiling block.
+    EventProfilerBlock* current_;
+    /// Root profiling block.
+    EventProfilerBlock* root_;
+    /// Frames in the current interval.
+    unsigned intervalFrames_;
+    /// Total frames.
+    unsigned totalFrames_;
+    /// Profiler active. Default false.
+    static bool active;
+};
+
+}

+ 50 - 1
Source/Urho3D/Core/Object.cpp

@@ -1,4 +1,3 @@
-
 //
 //
 // Copyright (c) 2008-2016 the Urho3D project.
 // Copyright (c) 2008-2016 the Urho3D project.
 //
 //
@@ -26,9 +25,12 @@
 #include "../Core/Context.h"
 #include "../Core/Context.h"
 #include "../Core/Thread.h"
 #include "../Core/Thread.h"
 #include "../IO/Log.h"
 #include "../IO/Log.h"
+#include "../Core/EventProfiler.h"
+#include "../Container/HashMap.h"
 
 
 #include "../DebugNew.h"
 #include "../DebugNew.h"
 
 
+
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
@@ -303,6 +305,16 @@ void Object::SendEvent(StringHash eventType, VariantMap& eventData)
         return;
         return;
     }
     }
 
 
+#ifdef URHO3D_PROFILING
+    EventProfiler* eventProfiler = 0;
+    if (EventProfiler::IsActive())
+    {
+        eventProfiler = GetSubsystem<EventProfiler>();
+        if (eventProfiler)
+            eventProfiler->BeginBlock(eventType);
+    }
+#endif
+
     // Make a weak pointer to self to check for destruction during event handling
     // Make a weak pointer to self to check for destruction during event handling
     WeakPtr<Object> self(this);
     WeakPtr<Object> self(this);
     Context* context = context_;
     Context* context = context_;
@@ -329,6 +341,10 @@ void Object::SendEvent(StringHash eventType, VariantMap& eventData)
             if (self.Expired())
             if (self.Expired())
             {
             {
                 context->EndSendEvent();
                 context->EndSendEvent();
+#ifdef URHO3D_PROFILING
+                if (eventProfiler)
+                    eventProfiler->EndBlock();
+#endif
                 return;
                 return;
             }
             }
 
 
@@ -361,6 +377,10 @@ void Object::SendEvent(StringHash eventType, VariantMap& eventData)
                 if (self.Expired())
                 if (self.Expired())
                 {
                 {
                     context->EndSendEvent();
                     context->EndSendEvent();
+#ifdef URHO3D_PROFILING
+                    if (eventProfiler)
+                         eventProfiler->EndBlock();
+#endif
                     return;
                     return;
                 }
                 }
 
 
@@ -387,6 +407,10 @@ void Object::SendEvent(StringHash eventType, VariantMap& eventData)
                     if (self.Expired())
                     if (self.Expired())
                     {
                     {
                         context->EndSendEvent();
                         context->EndSendEvent();
+#ifdef URHO3D_PROFILING
+                        if (eventProfiler)
+                            eventProfiler->EndBlock();
+#endif
                         return;
                         return;
                     }
                     }
 
 
@@ -398,6 +422,11 @@ void Object::SendEvent(StringHash eventType, VariantMap& eventData)
     }
     }
 
 
     context->EndSendEvent();
     context->EndSendEvent();
+
+#ifdef URHO3D_PROFILING
+    if (eventProfiler)
+        eventProfiler->EndBlock();
+#endif
 }
 }
 
 
 VariantMap& Object::GetEventDataMap() const
 VariantMap& Object::GetEventDataMap() const
@@ -535,4 +564,24 @@ void Object::RemoveEventSender(Object* sender)
     }
     }
 }
 }
 
 
+
+Urho3D::StringHash EventNameRegistrar::RegisterEventName(const char* eventName)
+{  
+    StringHash id(eventName);
+    GetEventNameMap()[id] = eventName;
+    return id;
+}
+
+const String& EventNameRegistrar::GetEventName(StringHash eventID) 
+{
+    HashMap<StringHash, String>::ConstIterator it = GetEventNameMap().Find(eventID);
+    return  it != GetEventNameMap().End() ? it->second_ : String::EMPTY ;
+}
+
+HashMap<StringHash, String>& EventNameRegistrar::GetEventNameMap()
+{
+    static HashMap<StringHash, String> eventNames_;
+    return eventNames_;
+}
+
 }
 }

+ 11 - 1
Source/Urho3D/Core/Object.h

@@ -356,8 +356,18 @@ private:
 };
 };
 #endif
 #endif
 
 
+/// Register event names.
+struct URHO3D_API EventNameRegistrar
+{
+    static StringHash RegisterEventName(const char* eventName);
+    /// Return Event name or empty string if not found.
+    static const String& GetEventName(StringHash eventID);
+    /// Return Event name map.
+    static HashMap<StringHash, String>& GetEventNameMap();
+};
+
 /// Describe an event's hash ID and begin a namespace in which to define its parameters.
 /// Describe an event's hash ID and begin a namespace in which to define its parameters.
-#define URHO3D_EVENT(eventID, eventName) static const Urho3D::StringHash eventID(#eventName); namespace eventName
+#define URHO3D_EVENT(eventID, eventName) static const Urho3D::StringHash eventID(Urho3D::EventNameRegistrar::RegisterEventName(#eventName)); namespace eventName
 /// Describe an event's parameter hash ID. Should be used inside an event namespace.
 /// Describe an event's parameter hash ID. Should be used inside an event namespace.
 #define URHO3D_PARAM(paramID, paramName) static const Urho3D::StringHash paramID(#paramName)
 #define URHO3D_PARAM(paramID, paramName) static const Urho3D::StringHash paramID(#paramName)
 /// Convenience macro to construct an EventHandler that points to a receiver object and its member function.
 /// Convenience macro to construct an EventHandler that points to a receiver object and its member function.

+ 30 - 1
Source/Urho3D/Engine/DebugHud.cpp

@@ -24,6 +24,8 @@
 
 
 #include "../Core/CoreEvents.h"
 #include "../Core/CoreEvents.h"
 #include "../Core/Profiler.h"
 #include "../Core/Profiler.h"
+#include "../Core/EventProfiler.h"
+#include "../Core/Context.h"
 #include "../Engine/DebugHud.h"
 #include "../Engine/DebugHud.h"
 #include "../Engine/Engine.h"
 #include "../Engine/Engine.h"
 #include "../Graphics/Graphics.h"
 #include "../Graphics/Graphics.h"
@@ -90,6 +92,12 @@ DebugHud::DebugHud(Context* context) :
     memoryText_->SetVisible(false);
     memoryText_->SetVisible(false);
     uiRoot->AddChild(memoryText_);
     uiRoot->AddChild(memoryText_);
 
 
+    eventProfilerText_ = new Text(context_);
+    eventProfilerText_->SetAlignment(HA_RIGHT, VA_TOP);
+    eventProfilerText_->SetPriority(100);
+    eventProfilerText_->SetVisible(false);
+    uiRoot->AddChild(eventProfilerText_);
+
     SubscribeToEvent(E_POSTUPDATE, URHO3D_HANDLER(DebugHud, HandlePostUpdate));
     SubscribeToEvent(E_POSTUPDATE, URHO3D_HANDLER(DebugHud, HandlePostUpdate));
 }
 }
 
 
@@ -99,6 +107,7 @@ DebugHud::~DebugHud()
     modeText_->Remove();
     modeText_->Remove();
     profilerText_->Remove();
     profilerText_->Remove();
     memoryText_->Remove();
     memoryText_->Remove();
+    eventProfilerText_->Remove();
 }
 }
 
 
 void DebugHud::Update()
 void DebugHud::Update()
@@ -169,6 +178,7 @@ void DebugHud::Update()
     }
     }
 
 
     Profiler* profiler = GetSubsystem<Profiler>();
     Profiler* profiler = GetSubsystem<Profiler>();
+    EventProfiler* eventProfiler = GetSubsystem<EventProfiler>();
     if (profiler)
     if (profiler)
     {
     {
         if (profilerTimer_.GetMSec(false) >= profilerInterval_)
         if (profilerTimer_.GetMSec(false) >= profilerInterval_)
@@ -182,6 +192,17 @@ void DebugHud::Update()
             }
             }
 
 
             profiler->BeginInterval();
             profiler->BeginInterval();
+
+            if (eventProfiler)
+            {
+                if (eventProfilerText_->IsVisible())
+                {
+                    String profilerOutput = eventProfiler->PrintData(false, false, profilerMaxDepth_);
+                    eventProfilerText_->SetText(profilerOutput);
+                }
+
+                eventProfiler->BeginInterval();
+            }
         }
         }
     }
     }
 
 
@@ -205,6 +226,8 @@ void DebugHud::SetDefaultStyle(XMLFile* style)
     profilerText_->SetStyle("DebugHudText");
     profilerText_->SetStyle("DebugHudText");
     memoryText_->SetDefaultStyle(style);
     memoryText_->SetDefaultStyle(style);
     memoryText_->SetStyle("DebugHudText");
     memoryText_->SetStyle("DebugHudText");
+    eventProfilerText_->SetDefaultStyle(style);
+    eventProfilerText_->SetStyle("DebugHudText");
 }
 }
 
 
 void DebugHud::SetMode(unsigned mode)
 void DebugHud::SetMode(unsigned mode)
@@ -213,7 +236,13 @@ void DebugHud::SetMode(unsigned mode)
     modeText_->SetVisible((mode & DEBUGHUD_SHOW_MODE) != 0);
     modeText_->SetVisible((mode & DEBUGHUD_SHOW_MODE) != 0);
     profilerText_->SetVisible((mode & DEBUGHUD_SHOW_PROFILER) != 0);
     profilerText_->SetVisible((mode & DEBUGHUD_SHOW_PROFILER) != 0);
     memoryText_->SetVisible((mode & DEBUGHUD_SHOW_MEMORY) != 0);
     memoryText_->SetVisible((mode & DEBUGHUD_SHOW_MEMORY) != 0);
-
+    eventProfilerText_->SetVisible((mode & DEBUGHUD_SHOW_EVENTPROFILER) != 0);
+#ifdef URHO3D_PROFILING
+    // Event profiler is created on engine initialization if "EventProfiler" parameter is set
+    EventProfiler* eventProfiler = GetSubsystem<EventProfiler>();
+    if (eventProfiler)
+        EventProfiler::SetActive((mode & DEBUGHUD_SHOW_EVENTPROFILER) != 0);
+#endif
     mode_ = mode;
     mode_ = mode;
 }
 }
 
 

+ 3 - 0
Source/Urho3D/Engine/DebugHud.h

@@ -40,6 +40,7 @@ static const unsigned DEBUGHUD_SHOW_PROFILER = 0x4;
 static const unsigned DEBUGHUD_SHOW_MEMORY = 0x8;
 static const unsigned DEBUGHUD_SHOW_MEMORY = 0x8;
 static const unsigned DEBUGHUD_SHOW_ALL = 0x7;
 static const unsigned DEBUGHUD_SHOW_ALL = 0x7;
 static const unsigned DEBUGHUD_SHOW_ALL_MEMORY = 0xB;
 static const unsigned DEBUGHUD_SHOW_ALL_MEMORY = 0xB;
+static const unsigned DEBUGHUD_SHOW_EVENTPROFILER = 0x10;
 
 
 /// Displays rendering stats and profiling information.
 /// Displays rendering stats and profiling information.
 class URHO3D_API DebugHud : public Object
 class URHO3D_API DebugHud : public Object
@@ -115,6 +116,8 @@ private:
     SharedPtr<Text> modeText_;
     SharedPtr<Text> modeText_;
     /// Profiling information text.
     /// Profiling information text.
     SharedPtr<Text> profilerText_;
     SharedPtr<Text> profilerText_;
+    /// Event profiling information text.
+    SharedPtr<Text> eventProfilerText_;
     /// Memory stats text.
     /// Memory stats text.
     SharedPtr<Text> memoryText_;
     SharedPtr<Text> memoryText_;
     /// Hashmap containing application specific stats.
     /// Hashmap containing application specific stats.

+ 18 - 1
Source/Urho3D/Engine/Engine.cpp

@@ -27,6 +27,7 @@
 #include "../Core/CoreEvents.h"
 #include "../Core/CoreEvents.h"
 #include "../Core/ProcessUtils.h"
 #include "../Core/ProcessUtils.h"
 #include "../Core/Profiler.h"
 #include "../Core/Profiler.h"
+#include "../Core/EventProfiler.h"
 #include "../Core/WorkQueue.h"
 #include "../Core/WorkQueue.h"
 #include "../Engine/Console.h"
 #include "../Engine/Console.h"
 #include "../Engine/DebugHud.h"
 #include "../Engine/DebugHud.h"
@@ -64,6 +65,7 @@
 
 
 #include "../DebugNew.h"
 #include "../DebugNew.h"
 
 
+
 #if defined(_MSC_VER) && defined(_DEBUG)
 #if defined(_MSC_VER) && defined(_DEBUG)
 // From dbgint.h
 // From dbgint.h
 #define nNoMansLandSize 4
 #define nNoMansLandSize 4
@@ -422,7 +424,13 @@ bool Engine::Initialize(const VariantMap& parameters)
             SharedPtr<Object> object = i->second_->CreateObject();
             SharedPtr<Object> object = i->second_->CreateObject();
     }
     }
 #endif
 #endif
-
+#ifdef URHO3D_PROFILING
+    if (GetParameter(parameters, "EventProfiler", true).GetBool())
+    {
+        context_->RegisterSubsystem(new EventProfiler(context_));
+        EventProfiler::SetActive(true);
+    }
+#endif
     frameTimer_.Reset();
     frameTimer_.Reset();
 
 
     URHO3D_LOGINFO("Initialized engine");
     URHO3D_LOGINFO("Initialized engine");
@@ -447,6 +455,15 @@ void Engine::RunFrame()
     Input* input = GetSubsystem<Input>();
     Input* input = GetSubsystem<Input>();
     Audio* audio = GetSubsystem<Audio>();
     Audio* audio = GetSubsystem<Audio>();
 
 
+#ifdef URHO3D_PROFILING
+    if (EventProfiler::IsActive())
+    {
+        EventProfiler* eventProfiler = GetSubsystem<EventProfiler>();
+        if (eventProfiler)
+            eventProfiler->BeginFrame();
+    }
+#endif
+
     time->BeginFrame(timeStep_);
     time->BeginFrame(timeStep_);
 
 
     // If pause when minimized -mode is in use, stop updates and audio as necessary
     // If pause when minimized -mode is in use, stop updates and audio as necessary

+ 1 - 1
Source/Urho3D/Graphics/Batch.cpp

@@ -235,7 +235,7 @@ void Batch::Prepare(View* view, Camera* camera, bool setModelTransform, bool all
     unsigned viewportHash = (unsigned)(viewSize.x_ | (viewSize.y_ << 16));
     unsigned viewportHash = (unsigned)(viewSize.x_ | (viewSize.y_ << 16));
     if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<const void*>(cameraHash + viewportHash)))
     if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<const void*>(cameraHash + viewportHash)))
     {
     {
-        view->SetCameraShaderParameters(camera, true);
+        view->SetCameraShaderParameters(camera);
         // During renderpath commands the G-Buffer or viewport texture is assumed to always be viewport-sized
         // During renderpath commands the G-Buffer or viewport texture is assumed to always be viewport-sized
         view->SetGBufferShaderParameters(viewSize, IntRect(0, 0, viewSize.x_, viewSize.y_));
         view->SetGBufferShaderParameters(viewSize, IntRect(0, 0, viewSize.x_, viewSize.y_));
     }
     }

+ 48 - 2
Source/Urho3D/Graphics/BillboardSet.cpp

@@ -69,6 +69,7 @@ BillboardSet::BillboardSet(Context* context) :
     relative_(true),
     relative_(true),
     scaled_(true),
     scaled_(true),
     sorted_(false),
     sorted_(false),
+    fixedScreenSize_(false),
     faceCameraMode_(FC_ROTATE_XYZ),
     faceCameraMode_(FC_ROTATE_XYZ),
     geometry_(new Geometry(context)),
     geometry_(new Geometry(context)),
     vertexBuffer_(new VertexBuffer(context_)),
     vertexBuffer_(new VertexBuffer(context_)),
@@ -104,6 +105,7 @@ void BillboardSet::RegisterObject(Context* context)
     URHO3D_ACCESSOR_ATTRIBUTE("Relative Position", IsRelative, SetRelative, bool, true, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Relative Position", IsRelative, SetRelative, bool, true, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Relative Scale", IsScaled, SetScaled, bool, true, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Relative Scale", IsScaled, SetScaled, bool, true, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Sort By Distance", IsSorted, SetSorted, bool, false, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Sort By Distance", IsSorted, SetSorted, bool, false, AM_DEFAULT);
+    URHO3D_ACCESSOR_ATTRIBUTE("Fixed Screen Size", IsFixedScreenSize, SetFixedScreenSize, bool, false, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Can Be Occluded", IsOccludee, SetOccludee, bool, true, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Can Be Occluded", IsOccludee, SetOccludee, bool, true, AM_DEFAULT);
     URHO3D_ATTRIBUTE("Cast Shadows", bool, castShadows_, false, AM_DEFAULT);
     URHO3D_ATTRIBUTE("Cast Shadows", bool, castShadows_, false, AM_DEFAULT);
     URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Face Camera Mode", GetFaceCameraMode, SetFaceCameraMode, FaceCameraMode, faceCameraModeNames, FC_ROTATE_XYZ, AM_DEFAULT);
     URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Face Camera Mode", GetFaceCameraMode, SetFaceCameraMode, FaceCameraMode, faceCameraModeNames, FC_ROTATE_XYZ, AM_DEFAULT);
@@ -141,6 +143,8 @@ void BillboardSet::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQue
 
 
         // Approximate the billboards as spheres for raycasting
         // Approximate the billboards as spheres for raycasting
         float size = INV_SQRT_TWO * (billboards_[i].size_.x_ * billboardScale.x_ + billboards_[i].size_.y_ * billboardScale.y_);
         float size = INV_SQRT_TWO * (billboards_[i].size_.x_ * billboardScale.x_ + billboards_[i].size_.y_ * billboardScale.y_);
+        if (fixedScreenSize_)
+            size *= billboards_[i].screenScaleFactor_;
         Vector3 center = billboardTransform * billboards_[i].position_;
         Vector3 center = billboardTransform * billboards_[i].position_;
         Sphere billboardSphere(center, size);
         Sphere billboardSphere(center, size);
 
 
@@ -174,10 +178,38 @@ void BillboardSet::UpdateBatches(const FrameInfo& frame)
     // Sort if position relative to camera has changed
     // Sort if position relative to camera has changed
     if (offset != previousOffset_)
     if (offset != previousOffset_)
     {
     {
-        if(sorted_)
+        if (sorted_)
             sortThisFrame_ = true;
             sortThisFrame_ = true;
-        if(faceCameraMode_ == FC_DIRECTION)
+        if (faceCameraMode_ == FC_DIRECTION)
             bufferDirty_ = true;
             bufferDirty_ = true;
+
+        // Calculate fixed screen size scale factor for billboards if needed
+        if (fixedScreenSize_)
+        {
+            bufferDirty_ = true;
+            worldBoundingBoxDirty_ = true;
+            float invViewHeight = 1.0f / frame.viewSize_.y_;
+            float halfViewWorldSize = frame.camera_->GetHalfViewSize();
+
+            if (!frame.camera_->IsOrthographic())
+            {
+                Matrix4 viewProj(frame.camera_->GetProjection(false) * frame.camera_->GetView());
+                const Matrix3x4& worldTransform = node_->GetWorldTransform();
+                Matrix3x4 billboardTransform = relative_ ? worldTransform : Matrix3x4::IDENTITY;
+                Vector3 billboardScale = scaled_ ? worldTransform.Scale() : Vector3::ONE;
+
+                for (unsigned i = 0; i < billboards_.Size(); ++i)
+                {
+                    Vector4 projPos(viewProj * Vector4(billboardTransform * billboards_[i].position_, 1.0f));
+                    billboards_[i].screenScaleFactor_ = invViewHeight * halfViewWorldSize * projPos.w_;
+                }
+            }
+            else
+            {
+                for (unsigned i = 0; i < billboards_.Size(); ++i)
+                    billboards_[i].screenScaleFactor_ = invViewHeight * halfViewWorldSize;
+            }
+        }
     }
     }
 
 
     distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());
     distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());
@@ -254,6 +286,7 @@ void BillboardSet::SetNumBillboards(unsigned num)
         billboards_[i].rotation_ = 0.0f;
         billboards_[i].rotation_ = 0.0f;
         billboards_[i].direction_ = Vector3::UP;
         billboards_[i].direction_ = Vector3::UP;
         billboards_[i].enabled_ = false;
         billboards_[i].enabled_ = false;
+        billboards_[i].screenScaleFactor_ = 1.0f;
     }
     }
 
 
     bufferSizeDirty_ = true;
     bufferSizeDirty_ = true;
@@ -278,6 +311,12 @@ void BillboardSet::SetSorted(bool enable)
     Commit();
     Commit();
 }
 }
 
 
+void BillboardSet::SetFixedScreenSize(bool enable)
+{
+    fixedScreenSize_ = enable;
+    Commit();
+}
+
 void BillboardSet::SetFaceCameraMode(FaceCameraMode mode)
 void BillboardSet::SetFaceCameraMode(FaceCameraMode mode)
 {
 {
     if ((faceCameraMode_ != FC_DIRECTION && mode == FC_DIRECTION) || (faceCameraMode_ == FC_DIRECTION && mode != FC_DIRECTION))
     if ((faceCameraMode_ != FC_DIRECTION && mode == FC_DIRECTION) || (faceCameraMode_ == FC_DIRECTION && mode != FC_DIRECTION))
@@ -443,6 +482,9 @@ void BillboardSet::OnWorldBoundingBoxUpdate()
             continue;
             continue;
 
 
         float size = INV_SQRT_TWO * (billboards_[i].size_.x_ * billboardScale.x_ + billboards_[i].size_.y_ * billboardScale.y_);
         float size = INV_SQRT_TWO * (billboards_[i].size_.x_ * billboardScale.x_ + billboards_[i].size_.y_ * billboardScale.y_);
+        if (fixedScreenSize_)
+            size *= billboards_[i].screenScaleFactor_;
+
         Vector3 center = billboardTransform * billboards_[i].position_;
         Vector3 center = billboardTransform * billboards_[i].position_;
         Vector3 edge = Vector3::ONE * size;
         Vector3 edge = Vector3::ONE * size;
         worldBox.Merge(BoundingBox(center - edge, center + edge));
         worldBox.Merge(BoundingBox(center - edge, center + edge));
@@ -579,6 +621,8 @@ void BillboardSet::UpdateVertexBuffer(const FrameInfo& frame)
 
 
             Vector2 size(billboard.size_.x_ * billboardScale.x_, billboard.size_.y_ * billboardScale.y_);
             Vector2 size(billboard.size_.x_ * billboardScale.x_, billboard.size_.y_ * billboardScale.y_);
             unsigned color = billboard.color_.ToUInt();
             unsigned color = billboard.color_.ToUInt();
+            if (fixedScreenSize_)
+                size *= billboard.screenScaleFactor_;
 
 
             float rotationMatrix[2][2];
             float rotationMatrix[2][2];
             SinCos(billboard.rotation_, rotationMatrix[0][1], rotationMatrix[0][0]);
             SinCos(billboard.rotation_, rotationMatrix[0][1], rotationMatrix[0][0]);
@@ -634,6 +678,8 @@ void BillboardSet::UpdateVertexBuffer(const FrameInfo& frame)
 
 
             Vector2 size(billboard.size_.x_ * billboardScale.x_, billboard.size_.y_ * billboardScale.y_);
             Vector2 size(billboard.size_.x_ * billboardScale.x_, billboard.size_.y_ * billboardScale.y_);
             unsigned color = billboard.color_.ToUInt();
             unsigned color = billboard.color_.ToUInt();
+            if (fixedScreenSize_)
+                size *= billboard.screenScaleFactor_;
 
 
             float rot2D[2][2];
             float rot2D[2][2];
             SinCos(billboard.rotation_, rot2D[0][1], rot2D[0][0]);
             SinCos(billboard.rotation_, rot2D[0][1], rot2D[0][0]);

+ 13 - 2
Source/Urho3D/Graphics/BillboardSet.h

@@ -39,7 +39,7 @@ struct URHO3D_API Billboard
 {
 {
     /// Position.
     /// Position.
     Vector3 position_;
     Vector3 position_;
-    /// Two-dimensional size.
+    /// Two-dimensional size. If BillboardSet has fixed screen size enabled, this is measured in pixels instead of world units.
     Vector2 size_;
     Vector2 size_;
     /// UV coordinates.
     /// UV coordinates.
     Rect uv_;
     Rect uv_;
@@ -51,8 +51,10 @@ struct URHO3D_API Billboard
     Vector3 direction_;
     Vector3 direction_;
     /// Enabled flag.
     /// Enabled flag.
     bool enabled_;
     bool enabled_;
-    /// Sort distance.
+    /// Sort distance. Used internally.
     float sortDistance_;
     float sortDistance_;
+    /// Scale factor for fixed screen size mode. Used internally.
+    float screenScaleFactor_;
 };
 };
 
 
 static const unsigned MAX_BILLBOARDS = 65536 / 4;
 static const unsigned MAX_BILLBOARDS = 65536 / 4;
@@ -89,6 +91,8 @@ public:
     void SetScaled(bool enable);
     void SetScaled(bool enable);
     /// Set whether billboards are sorted by distance. Default false.
     /// Set whether billboards are sorted by distance. Default false.
     void SetSorted(bool enable);
     void SetSorted(bool enable);
+    /// Set whether billboards have fixed size on screen (measured in pixels) regardless of distance to camera. Default false.
+    void SetFixedScreenSize(bool enable);
     /// Set how the billboards should rotate in relation to the camera. Default is to follow camera rotation on all axes (FC_ROTATE_XYZ.)
     /// Set how the billboards should rotate in relation to the camera. Default is to follow camera rotation on all axes (FC_ROTATE_XYZ.)
     void SetFaceCameraMode(FaceCameraMode mode);
     void SetFaceCameraMode(FaceCameraMode mode);
     /// Set animation LOD bias.
     /// Set animation LOD bias.
@@ -117,6 +121,9 @@ public:
     /// Return whether billboards are sorted.
     /// Return whether billboards are sorted.
     bool IsSorted() const { return sorted_; }
     bool IsSorted() const { return sorted_; }
 
 
+    /// Return whether billboards are fixed screen size.
+    bool IsFixedScreenSize() const { return fixedScreenSize_; }
+
     /// Return how the billboards rotate in relation to the camera.
     /// Return how the billboards rotate in relation to the camera.
     FaceCameraMode GetFaceCameraMode() const { return faceCameraMode_; }
     FaceCameraMode GetFaceCameraMode() const { return faceCameraMode_; }
 
 
@@ -156,6 +163,8 @@ protected:
     bool scaled_;
     bool scaled_;
     /// Billboards sorted flag.
     /// Billboards sorted flag.
     bool sorted_;
     bool sorted_;
+    /// Billboards fixed screen size flag.
+    bool fixedScreenSize_;
     /// Billboard rotation mode in relation to the camera.
     /// Billboard rotation mode in relation to the camera.
     FaceCameraMode faceCameraMode_;
     FaceCameraMode faceCameraMode_;
 
 
@@ -187,6 +196,8 @@ private:
     unsigned sortFrameNumber_;
     unsigned sortFrameNumber_;
     /// Previous offset to camera for determining whether sorting is necessary.
     /// Previous offset to camera for determining whether sorting is necessary.
     Vector3 previousOffset_;
     Vector3 previousOffset_;
+    /// Scale factor for fixed screen size mode.
+    float fixedScaleFactor_;
     /// Billboard pointers for sorting.
     /// Billboard pointers for sorting.
     Vector<Billboard*> sortedBillboards_;
     Vector<Billboard*> sortedBillboards_;
     /// Attribute buffer for network replication.
     /// Attribute buffer for network replication.

+ 12 - 9
Source/Urho3D/Graphics/Light.cpp

@@ -422,15 +422,7 @@ const Matrix3x4& Light::GetVolumeTransform(Camera* camera)
     switch (lightType_)
     switch (lightType_)
     {
     {
     case LIGHT_DIRECTIONAL:
     case LIGHT_DIRECTIONAL:
-        {
-            Matrix3x4 quadTransform;
-            Vector3 near, far;
-            // Position the directional light quad in halfway between far & near planes to prevent depth clipping
-            camera->GetFrustumSize(near, far);
-            quadTransform.SetTranslation(Vector3(0.0f, 0.0f, (camera->GetNearClip() + camera->GetFarClip()) * 0.5f));
-            quadTransform.SetScale(Vector3(far.x_, far.y_, 1.0f)); // Will be oversized, but doesn't matter (gets frustum clipped)
-            volumeTransform_ = camera->GetEffectiveWorldTransform() * quadTransform;
-        }
+        volumeTransform_ = GetFullscreenQuadTransform(camera);
         break;
         break;
 
 
     case LIGHT_SPOT:
     case LIGHT_SPOT:
@@ -573,4 +565,15 @@ void Light::SetLightQueue(LightBatchQueue* queue)
     lightQueue_ = queue;
     lightQueue_ = queue;
 }
 }
 
 
+Matrix3x4 Light::GetFullscreenQuadTransform(Camera* camera)
+{
+    Matrix3x4 quadTransform;
+    Vector3 near, far;
+    // Position the directional light quad in halfway between far & near planes to prevent depth clipping
+    camera->GetFrustumSize(near, far);
+    quadTransform.SetTranslation(Vector3(0.0f, 0.0f, (camera->GetNearClip() + camera->GetFarClip()) * 0.5f));
+    quadTransform.SetScale(Vector3(far.x_, far.y_, 1.0f)); // Will be oversized, but doesn't matter (gets frustum clipped)
+    return camera->GetEffectiveWorldTransform() * quadTransform;
+}
+
 }
 }

+ 3 - 0
Source/Urho3D/Graphics/Light.h

@@ -304,6 +304,9 @@ public:
     /// Return shape texture attribute.
     /// Return shape texture attribute.
     ResourceRef GetShapeTextureAttr() const;
     ResourceRef GetShapeTextureAttr() const;
 
 
+    /// Return a transform for deferred fullscreen quad (directional light) rendering.
+    static Matrix3x4 GetFullscreenQuadTransform(Camera* camera);
+
 protected:
 protected:
     /// Recalculate the world-space bounding box.
     /// Recalculate the world-space bounding box.
     virtual void OnWorldBoundingBoxUpdate();
     virtual void OnWorldBoundingBoxUpdate();

+ 1 - 3
Source/Urho3D/Graphics/Material.cpp

@@ -962,8 +962,6 @@ void Material::SetUVTransform(const Vector2& offset, float rotation, const Vecto
     Matrix3x4 transform(Matrix3x4::IDENTITY);
     Matrix3x4 transform(Matrix3x4::IDENTITY);
     transform.m00_ = repeat.x_;
     transform.m00_ = repeat.x_;
     transform.m11_ = repeat.y_;
     transform.m11_ = repeat.y_;
-    transform.m03_ = -0.5f * transform.m00_ + 0.5f;
-    transform.m13_ = -0.5f * transform.m11_ + 0.5f;
 
 
     Matrix3x4 rotationMatrix(Matrix3x4::IDENTITY);
     Matrix3x4 rotationMatrix(Matrix3x4::IDENTITY);
     rotationMatrix.m00_ = Cos(rotation);
     rotationMatrix.m00_ = Cos(rotation);
@@ -973,7 +971,7 @@ void Material::SetUVTransform(const Vector2& offset, float rotation, const Vecto
     rotationMatrix.m03_ = 0.5f - 0.5f * (rotationMatrix.m00_ + rotationMatrix.m01_);
     rotationMatrix.m03_ = 0.5f - 0.5f * (rotationMatrix.m00_ + rotationMatrix.m01_);
     rotationMatrix.m13_ = 0.5f - 0.5f * (rotationMatrix.m10_ + rotationMatrix.m11_);
     rotationMatrix.m13_ = 0.5f - 0.5f * (rotationMatrix.m10_ + rotationMatrix.m11_);
 
 
-    transform = rotationMatrix * transform;
+    transform = transform * rotationMatrix;
 
 
     Matrix3x4 offsetMatrix = Matrix3x4::IDENTITY;
     Matrix3x4 offsetMatrix = Matrix3x4::IDENTITY;
     offsetMatrix.m03_ = offset.x_;
     offsetMatrix.m03_ = offset.x_;

+ 7 - 2
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -2517,7 +2517,12 @@ void Graphics::Restore()
         }
         }
 
 
         // Enable seamless cubemap if possible
         // Enable seamless cubemap if possible
-        glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+        // Note: even though we check the extension, this can lead to software fallback on some old GPU's
+        // See https://github.com/urho3d/Urho3D/issues/1380 or
+        // http://distrustsimplicity.net/articles/gl_texture_cube_map_seamless-on-os-x/
+        // In case of trouble or for wanting maximum compatibility, simply remove the glEnable below.
+        if (gl3Support || GLEW_ARB_seamless_cube_map)
+            glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
 #endif
 #endif
 
 
         // Set up texture data read/write alignment. It is important that this is done before uploading any texture data
         // Set up texture data read/write alignment. It is important that this is done before uploading any texture data
@@ -3142,7 +3147,7 @@ void Graphics::PrepareDraw()
                     SetVBO(buffer->GetGPUObject());
                     SetVBO(buffer->GetGPUObject());
                     glVertexAttribPointer(location, glElementComponents[element.type_], glElementTypes[element.type_],
                     glVertexAttribPointer(location, glElementComponents[element.type_], glElementTypes[element.type_],
                         element.type_ == TYPE_UBYTE4_NORM ? GL_TRUE : GL_FALSE, (unsigned)buffer->GetVertexSize(),
                         element.type_ == TYPE_UBYTE4_NORM ? GL_TRUE : GL_FALSE, (unsigned)buffer->GetVertexSize(),
-                        (const void *)dataStart);
+                        (const void *)(size_t)dataStart);
                 }
                 }
             }
             }
         }
         }

+ 13 - 0
Source/Urho3D/Graphics/ParticleEffect.cpp

@@ -60,6 +60,7 @@ ParticleEffect::ParticleEffect(Context* context) :
     relative_(true),
     relative_(true),
     scaled_(true),
     scaled_(true),
     sorted_(false),
     sorted_(false),
+    fixedScreenSize_(false),
     animationLodBias_(0.0f),
     animationLodBias_(0.0f),
     emitterType_(EMITTER_SPHERE),
     emitterType_(EMITTER_SPHERE),
     emitterSize_(Vector3::ZERO),
     emitterSize_(Vector3::ZERO),
@@ -136,6 +137,7 @@ bool ParticleEffect::Load(const XMLElement& source)
     relative_ = true;
     relative_ = true;
     scaled_ = true;
     scaled_ = true;
     sorted_ = false;
     sorted_ = false;
+    fixedScreenSize_ = false;
     animationLodBias_ = 0.0f;
     animationLodBias_ = 0.0f;
     emitterType_ = EMITTER_SPHERE;
     emitterType_ = EMITTER_SPHERE;
     emitterSize_ = Vector3::ZERO;
     emitterSize_ = Vector3::ZERO;
@@ -192,6 +194,9 @@ bool ParticleEffect::Load(const XMLElement& source)
     if (source.HasChild("sorted"))
     if (source.HasChild("sorted"))
         sorted_ = source.GetChild("sorted").GetBool("enable");
         sorted_ = source.GetChild("sorted").GetBool("enable");
 
 
+    if (source.HasChild("fixedscreensize"))
+        fixedScreenSize_ = source.GetChild("fixedscreensize").GetBool("enable");
+
     if (source.HasChild("animlodbias"))
     if (source.HasChild("animlodbias"))
         SetAnimationLodBias(source.GetChild("animlodbias").GetFloat("value"));
         SetAnimationLodBias(source.GetChild("animlodbias").GetFloat("value"));
 
 
@@ -346,6 +351,9 @@ bool ParticleEffect::Save(XMLElement& dest) const
     childElem = dest.CreateChild("sorted");
     childElem = dest.CreateChild("sorted");
     childElem.SetBool("enable", sorted_);
     childElem.SetBool("enable", sorted_);
 
 
+    childElem = dest.CreateChild("fixedscreensize");
+    childElem.SetBool("enable", fixedScreenSize_);
+
     childElem = dest.CreateChild("animlodbias");
     childElem = dest.CreateChild("animlodbias");
     childElem.SetFloat("value", animationLodBias_);
     childElem.SetFloat("value", animationLodBias_);
 
 
@@ -458,6 +466,11 @@ void ParticleEffect::SetSorted(bool enable)
     sorted_ = enable;
     sorted_ = enable;
 }
 }
 
 
+void ParticleEffect::SetFixedScreenSize(bool enable)
+{
+    fixedScreenSize_ = enable;
+}
+
 void ParticleEffect::SetAnimationLodBias(float lodBias)
 void ParticleEffect::SetAnimationLodBias(float lodBias)
 {
 {
     animationLodBias_ = lodBias;
     animationLodBias_ = lodBias;

+ 10 - 3
Source/Urho3D/Graphics/ParticleEffect.h

@@ -129,12 +129,14 @@ public:
     void SetNumParticles(unsigned num);
     void SetNumParticles(unsigned num);
     /// Set whether to update when particles are not visible.
     /// Set whether to update when particles are not visible.
     void SetUpdateInvisible(bool enable);
     void SetUpdateInvisible(bool enable);
-    /// Set whether billboards are relative to the scene node. Default true.
+    /// Set whether billboards are relative to the scene node.
     void SetRelative(bool enable);
     void SetRelative(bool enable);
-    /// Set scaled.
+    /// Set whether scene node scale affects billboards' size.
     void SetScaled(bool enable);
     void SetScaled(bool enable);
-    /// Set sorted.
+    /// Set whether billboards are sorted by distance.
     void SetSorted(bool enable);
     void SetSorted(bool enable);
+    /// Set whether billboards have fixed size on screen (measured in pixels) regardless of distance to camera.
+    void SetFixedScreenSize(bool enable);
     /// Set animation LOD bias.
     /// Set animation LOD bias.
     void SetAnimationLodBias(float lodBias);
     void SetAnimationLodBias(float lodBias);
     /// Set emitter type.
     /// Set emitter type.
@@ -232,6 +234,9 @@ public:
     /// Return whether billboards are sorted.
     /// Return whether billboards are sorted.
     bool IsSorted() const { return sorted_; }
     bool IsSorted() const { return sorted_; }
 
 
+    /// Return whether billboards are fixed screen size.
+    bool IsFixedScreenSize() const { return fixedScreenSize_; }
+
     /// Return animation Lod bias.
     /// Return animation Lod bias.
     float GetAnimationLodBias() const { return animationLodBias_; }
     float GetAnimationLodBias() const { return animationLodBias_; }
 
 
@@ -355,6 +360,8 @@ private:
     bool scaled_;
     bool scaled_;
     /// Billboards sorted flag.
     /// Billboards sorted flag.
     bool sorted_;
     bool sorted_;
+    /// Billboards fixed screen size flag.
+    bool fixedScreenSize_;
     /// Animation LOD bias.
     /// Animation LOD bias.
     float animationLodBias_;
     float animationLodBias_;
     /// Emitter shape.
     /// Emitter shape.

+ 1 - 0
Source/Urho3D/Graphics/ParticleEmitter.cpp

@@ -337,6 +337,7 @@ void ParticleEmitter::ApplyEffect()
     SetRelative(effect_->IsRelative());
     SetRelative(effect_->IsRelative());
     SetScaled(effect_->IsScaled());
     SetScaled(effect_->IsScaled());
     SetSorted(effect_->IsSorted());
     SetSorted(effect_->IsSorted());
+    SetFixedScreenSize(effect_->IsFixedScreenSize());
     SetAnimationLodBias(effect_->GetAnimationLodBias());
     SetAnimationLodBias(effect_->GetAnimationLodBias());
     SetFaceCameraMode(effect_->GetFaceCameraMode());
     SetFaceCameraMode(effect_->GetFaceCameraMode());
 }
 }

+ 8 - 9
Source/Urho3D/Graphics/Renderer.cpp

@@ -262,7 +262,7 @@ Renderer::Renderer(Context* context) :
     materialQuality_(QUALITY_HIGH),
     materialQuality_(QUALITY_HIGH),
     shadowMapSize_(1024),
     shadowMapSize_(1024),
     shadowQuality_(SHADOWQUALITY_PCF_16BIT),
     shadowQuality_(SHADOWQUALITY_PCF_16BIT),
-    shadowSoftness_(2.0f),
+    shadowSoftness_(1.0f),
     vsmShadowParams_(0.0000001f, 0.2f),
     vsmShadowParams_(0.0000001f, 0.2f),
     maxShadowMaps_(1),
     maxShadowMaps_(1),
     minInstances_(2),
     minInstances_(2),
@@ -528,10 +528,10 @@ void Renderer::ReloadShaders()
     shadersDirty_ = true;
     shadersDirty_ = true;
 }
 }
 
 
-void Renderer::ApplyShadowMapFilter(View* view, Texture2D* shadowMap)
+void Renderer::ApplyShadowMapFilter(View* view, Texture2D* shadowMap, float blurScale)
 {
 {
     if (shadowMapFilterInstance_ && shadowMapFilter_)
     if (shadowMapFilterInstance_ && shadowMapFilter_)
-        (shadowMapFilterInstance_->*shadowMapFilter_)(view, shadowMap);
+        (shadowMapFilterInstance_->*shadowMapFilter_)(view, shadowMap, blurScale);
 }
 }
 
 
 Viewport* Renderer::GetViewport(unsigned index) const
 Viewport* Renderer::GetViewport(unsigned index) const
@@ -1921,7 +1921,7 @@ void Renderer::HandleRenderUpdate(StringHash eventType, VariantMap& eventData)
 }
 }
 
 
 
 
-void Renderer::BlurShadowMap(View* view, Texture2D* shadowMap)
+void Renderer::BlurShadowMap(View* view, Texture2D* shadowMap, float blurScale)
 {
 {
     graphics_->SetBlendMode(BLEND_REPLACE);
     graphics_->SetBlendMode(BLEND_REPLACE);
     graphics_->SetDepthTest(CMP_ALWAYS);
     graphics_->SetDepthTest(CMP_ALWAYS);
@@ -1944,18 +1944,17 @@ void Renderer::BlurShadowMap(View* view, Texture2D* shadowMap)
 
 
     // Horizontal blur of the shadow map
     // Horizontal blur of the shadow map
     static const StringHash blurOffsetParam("BlurOffsets");
     static const StringHash blurOffsetParam("BlurOffsets");
-    graphics_->SetShaderParameter(blurOffsetParam, Vector2(shadowSoftness_ / shadowMap->GetWidth(), 0.0f));
 
 
+    graphics_->SetShaderParameter(blurOffsetParam, Vector2(shadowSoftness_ * blurScale / shadowMap->GetWidth(), 0.0f));
     graphics_->SetTexture(TU_DIFFUSE, shadowMap);
     graphics_->SetTexture(TU_DIFFUSE, shadowMap);
-    view->DrawFullscreenQuad(false);
+    view->DrawFullscreenQuad(true);
 
 
     // Vertical blur
     // Vertical blur
     graphics_->SetRenderTarget(0, shadowMap);
     graphics_->SetRenderTarget(0, shadowMap);
     graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
     graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
-
-    graphics_->SetShaderParameter(blurOffsetParam, Vector2(0.0f, shadowSoftness_ / shadowMap->GetHeight()));
+    graphics_->SetShaderParameter(blurOffsetParam, Vector2(0.0f, shadowSoftness_ * blurScale / shadowMap->GetHeight()));
 
 
     graphics_->SetTexture(TU_DIFFUSE, tmpBuffer);
     graphics_->SetTexture(TU_DIFFUSE, tmpBuffer);
-    view->DrawFullscreenQuad(false);
+    view->DrawFullscreenQuad(true);
 }
 }
 }
 }

+ 3 - 3
Source/Urho3D/Graphics/Renderer.h

@@ -173,7 +173,7 @@ class URHO3D_API Renderer : public Object
     URHO3D_OBJECT(Renderer, Object);
     URHO3D_OBJECT(Renderer, Object);
 
 
 public:
 public:
-    typedef void(Object::*ShadowMapFilter)(View* view, Texture2D* shadowMap);
+    typedef void(Object::*ShadowMapFilter)(View* view, Texture2D* shadowMap, float blurScale);
 
 
     /// Construct.
     /// Construct.
     Renderer(Context* context);
     Renderer(Context* context);
@@ -242,7 +242,7 @@ public:
     void ReloadShaders();
     void ReloadShaders();
 
 
     /// Apply post processing filter to the shadow map. Called by View.
     /// Apply post processing filter to the shadow map. Called by View.
-    void ApplyShadowMapFilter(View* view, Texture2D* shadowMap);
+    void ApplyShadowMapFilter(View* view, Texture2D* shadowMap, float blurScale);
 
 
     /// Return number of backbuffer viewports.
     /// Return number of backbuffer viewports.
     unsigned GetNumViewports() const { return viewports_.Size(); }
     unsigned GetNumViewports() const { return viewports_.Size(); }
@@ -456,7 +456,7 @@ private:
     /// Handle render update event.
     /// Handle render update event.
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
     /// Blur the shadow map.
     /// Blur the shadow map.
-    void BlurShadowMap(View* view, Texture2D* shadowMap);
+    void BlurShadowMap(View* view, Texture2D* shadowMap, float blurScale);
 
 
     /// Graphics subsystem.
     /// Graphics subsystem.
     WeakPtr<Graphics> graphics_;
     WeakPtr<Graphics> graphics_;

+ 39 - 31
Source/Urho3D/Graphics/View.cpp

@@ -706,7 +706,7 @@ void View::SetGlobalShaderParameters()
     }
     }
 }
 }
 
 
-void View::SetCameraShaderParameters(Camera* camera, bool setProjection)
+void View::SetCameraShaderParameters(Camera* camera)
 {
 {
     if (!camera)
     if (!camera)
         return;
         return;
@@ -750,18 +750,15 @@ void View::SetCameraShaderParameters(Camera* camera, bool setProjection)
     camera->GetFrustumSize(nearVector, farVector);
     camera->GetFrustumSize(nearVector, farVector);
     graphics_->SetShaderParameter(VSP_FRUSTUMSIZE, farVector);
     graphics_->SetShaderParameter(VSP_FRUSTUMSIZE, farVector);
 
 
-    if (setProjection)
-    {
-        Matrix4 projection = camera->GetProjection();
+    Matrix4 projection = camera->GetProjection();
 #ifdef URHO3D_OPENGL
 #ifdef URHO3D_OPENGL
-        // Add constant depth bias manually to the projection matrix due to glPolygonOffset() inconsistency
-        float constantBias = 2.0f * graphics_->GetDepthConstantBias();
-        projection.m22_ += projection.m32_ * constantBias;
-        projection.m23_ += projection.m33_ * constantBias;
+    // Add constant depth bias manually to the projection matrix due to glPolygonOffset() inconsistency
+    float constantBias = 2.0f * graphics_->GetDepthConstantBias();
+    projection.m22_ += projection.m32_ * constantBias;
+    projection.m23_ += projection.m33_ * constantBias;
 #endif
 #endif
 
 
-        graphics_->SetShaderParameter(VSP_VIEWPROJ, projection * camera->GetView());
-    }
+    graphics_->SetShaderParameter(VSP_VIEWPROJ, projection * camera->GetView());
 }
 }
 
 
 void View::SetGBufferShaderParameters(const IntVector2& texSize, const IntRect& viewRect)
 void View::SetGBufferShaderParameters(const IntVector2& texSize, const IntRect& viewRect)
@@ -1800,12 +1797,8 @@ void View::RenderQuad(RenderPathCommand& command)
     // Set shaders & shader parameters and textures
     // Set shaders & shader parameters and textures
     graphics_->SetShaders(vs, ps);
     graphics_->SetShaders(vs, ps);
 
 
-    const HashMap<StringHash, Variant>& parameters = command.shaderParameters_;
-    for (HashMap<StringHash, Variant>::ConstIterator k = parameters.Begin(); k != parameters.End(); ++k)
-        graphics_->SetShaderParameter(k->first_, k->second_);
-
     SetGlobalShaderParameters();
     SetGlobalShaderParameters();
-    SetCameraShaderParameters(camera_, false);
+    SetCameraShaderParameters(camera_);
 
 
     // During renderpath commands the G-Buffer or viewport texture is assumed to always be viewport-sized
     // During renderpath commands the G-Buffer or viewport texture is assumed to always be viewport-sized
     IntRect viewport = graphics_->GetViewport();
     IntRect viewport = graphics_->GetViewport();
@@ -1833,6 +1826,11 @@ void View::RenderQuad(RenderPathCommand& command)
         graphics_->SetShaderParameter(offsetsName, Vector2(pixelUVOffset.x_ / width, pixelUVOffset.y_ / height));
         graphics_->SetShaderParameter(offsetsName, Vector2(pixelUVOffset.x_ / width, pixelUVOffset.y_ / height));
     }
     }
 
 
+    // Set command's shader parameters last to allow them to override any of the above
+    const HashMap<StringHash, Variant>& parameters = command.shaderParameters_;
+    for (HashMap<StringHash, Variant>::ConstIterator k = parameters.Begin(); k != parameters.End(); ++k)
+        graphics_->SetShaderParameter(k->first_, k->second_);
+
     graphics_->SetBlendMode(command.blendMode_);
     graphics_->SetBlendMode(command.blendMode_);
     graphics_->SetDepthTest(CMP_ALWAYS);
     graphics_->SetDepthTest(CMP_ALWAYS);
     graphics_->SetDepthWrite(false);
     graphics_->SetDepthWrite(false);
@@ -2079,27 +2077,36 @@ void View::BlitFramebuffer(Texture* source, RenderSurface* destination, bool dep
     SetGBufferShaderParameters(srcSize, srcRect);
     SetGBufferShaderParameters(srcSize, srcRect);
 
 
     graphics_->SetTexture(TU_DIFFUSE, source);
     graphics_->SetTexture(TU_DIFFUSE, source);
-    DrawFullscreenQuad(false);
+    DrawFullscreenQuad(true);
 }
 }
 
 
-void View::DrawFullscreenQuad(bool nearQuad)
+void View::DrawFullscreenQuad(bool setIdentityProjection)
 {
 {
     Geometry* geometry = renderer_->GetQuadGeometry();
     Geometry* geometry = renderer_->GetQuadGeometry();
 
 
-    Matrix3x4 model = Matrix3x4::IDENTITY;
-    Matrix4 projection = Matrix4::IDENTITY;
+    // If no camera, no choice but to use identity projection
+    if (!camera_)
+        setIdentityProjection = true;
 
 
+    if (setIdentityProjection)
+    {
+        Matrix3x4 model = Matrix3x4::IDENTITY;
+        Matrix4 projection = Matrix4::IDENTITY;
 #ifdef URHO3D_OPENGL
 #ifdef URHO3D_OPENGL
-    if (camera_ && camera_->GetFlipVertical())
-        projection.m11_ = -1.0f;
-    model.m23_ = nearQuad ? -1.0f : 1.0f;
+        if (camera_ && camera_->GetFlipVertical())
+            projection.m11_ = -1.0f;
+        model.m23_ = 0.0f;
 #else
 #else
-    model.m23_ = nearQuad ? 0.0f : 1.0f;
+        model.m23_ = 0.5f;
 #endif
 #endif
 
 
+        graphics_->SetShaderParameter(VSP_MODEL, model);
+        graphics_->SetShaderParameter(VSP_VIEWPROJ, projection);
+    }
+    else
+        graphics_->SetShaderParameter(VSP_MODEL, Light::GetFullscreenQuadTransform(camera_));
+
     graphics_->SetCullMode(CULL_NONE);
     graphics_->SetCullMode(CULL_NONE);
-    graphics_->SetShaderParameter(VSP_MODEL, model);
-    graphics_->SetShaderParameter(VSP_VIEWPROJ, projection);
     graphics_->ClearTransformSources();
     graphics_->ClearTransformSources();
 
 
     geometry->Draw(graphics_);
     geometry->Draw(graphics_);
@@ -2967,23 +2974,23 @@ void View::RenderShadowMap(const LightBatchQueue& queue)
     // Set shadow depth bias
     // Set shadow depth bias
     BiasParameters parameters = queue.light_->GetShadowBias();
     BiasParameters parameters = queue.light_->GetShadowBias();
 
 
-    // the shadow map is a depth stencil map
+    // The shadow map is a depth stencil texture
     if (shadowMap->GetUsage() == TEXTURE_DEPTHSTENCIL)
     if (shadowMap->GetUsage() == TEXTURE_DEPTHSTENCIL)
     {
     {
         graphics_->SetColorWrite(false);
         graphics_->SetColorWrite(false);
         graphics_->SetDepthStencil(shadowMap);
         graphics_->SetDepthStencil(shadowMap);
         graphics_->SetRenderTarget(0, shadowMap->GetRenderSurface()->GetLinkedRenderTarget());
         graphics_->SetRenderTarget(0, shadowMap->GetRenderSurface()->GetLinkedRenderTarget());
-        // disable other render targets
+        // Disable other render targets
         for (unsigned i = 1; i < MAX_RENDERTARGETS; ++i)
         for (unsigned i = 1; i < MAX_RENDERTARGETS; ++i)
             graphics_->SetRenderTarget(i, (RenderSurface*) 0);
             graphics_->SetRenderTarget(i, (RenderSurface*) 0);
         graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
         graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
         graphics_->Clear(CLEAR_DEPTH);
         graphics_->Clear(CLEAR_DEPTH);
     }
     }
-    else // if the shadow map is a render texture
+    else // if the shadow map is a color rendertarget
     {
     {
         graphics_->SetColorWrite(true);
         graphics_->SetColorWrite(true);
         graphics_->SetRenderTarget(0, shadowMap);
         graphics_->SetRenderTarget(0, shadowMap);
-        // disable other render targets
+        // Disable other render targets
         for (unsigned i = 1; i < MAX_RENDERTARGETS; ++i)
         for (unsigned i = 1; i < MAX_RENDERTARGETS; ++i)
             graphics_->SetRenderTarget(i, (RenderSurface*) 0);
             graphics_->SetRenderTarget(i, (RenderSurface*) 0);
         graphics_->SetDepthStencil(renderer_->GetDepthStencil(shadowMap->GetWidth(), shadowMap->GetHeight()));
         graphics_->SetDepthStencil(renderer_->GetDepthStencil(shadowMap->GetWidth(), shadowMap->GetHeight()));
@@ -3025,8 +3032,9 @@ void View::RenderShadowMap(const LightBatchQueue& queue)
         }
         }
     }
     }
 
 
-    renderer_->ApplyShadowMapFilter(this, shadowMap);
-
+    // Scale filter blur amount to shadow map viewport size so that different shadow map resolutions don't behave differently
+    float blurScale = queue.shadowSplits_[0].shadowViewport_.Width() / 1024.0f;
+    renderer_->ApplyShadowMapFilter(this, shadowMap, blurScale);
 
 
     // reset some parameters
     // reset some parameters
     graphics_->SetColorWrite(true);
     graphics_->SetColorWrite(true);

+ 3 - 3
Source/Urho3D/Graphics/View.h

@@ -177,12 +177,12 @@ public:
     /// Set global (per-frame) shader parameters. Called by Batch and internally by View.
     /// Set global (per-frame) shader parameters. Called by Batch and internally by View.
     void SetGlobalShaderParameters();
     void SetGlobalShaderParameters();
     /// Set camera-specific shader parameters. Called by Batch and internally by View.
     /// Set camera-specific shader parameters. Called by Batch and internally by View.
-    void SetCameraShaderParameters(Camera* camera, bool setProjectionMatrix);
+    void SetCameraShaderParameters(Camera* camera);
     /// Set G-buffer offset and inverse size shader parameters. Called by Batch and internally by View.
     /// Set G-buffer offset and inverse size shader parameters. Called by Batch and internally by View.
     void SetGBufferShaderParameters(const IntVector2& texSize, const IntRect& viewRect);
     void SetGBufferShaderParameters(const IntVector2& texSize, const IntRect& viewRect);
 
 
-    /// Draw a fullscreen quad. Shaders and renderstates must have been set beforehand.
-    void DrawFullscreenQuad(bool nearQuad);
+    /// Draw a fullscreen quad. Shaders and renderstates must have been set beforehand. Quad will be drawn to the middle of depth range, similarly to deferred directional lights.
+    void DrawFullscreenQuad(bool setIdentityProjection = false);
 
 
 private:
 private:
     /// Query the octree for drawable objects.
     /// Query the octree for drawable objects.

+ 2 - 3
Source/Urho3D/IO/Deserializer.h

@@ -48,6 +48,8 @@ public:
     virtual const String& GetName() const;
     virtual const String& GetName() const;
     /// Return a checksum if applicable.
     /// Return a checksum if applicable.
     virtual unsigned GetChecksum();
     virtual unsigned GetChecksum();
+    /// Return whether the end of stream has been reached.
+    virtual bool IsEof() const { return position_ >= size_; }
 
 
     /// Return current position.
     /// Return current position.
     unsigned GetPosition() const { return position_; }
     unsigned GetPosition() const { return position_; }
@@ -55,9 +57,6 @@ public:
     /// Return size.
     /// Return size.
     unsigned GetSize() const { return size_; }
     unsigned GetSize() const { return size_; }
 
 
-    /// Return whether the end of stream has been reached.
-    bool IsEof() const { return position_ >= size_; }
-
     /// Read a 32-bit integer.
     /// Read a 32-bit integer.
     int ReadInt();
     int ReadInt();
     /// Read a 16-bit integer.
     /// Read a 16-bit integer.

+ 381 - 0
Source/Urho3D/IO/NamedPipe.cpp

@@ -0,0 +1,381 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "../Precompiled.h"
+
+#include "../Core/Profiler.h"
+#include "../IO/NamedPipe.h"
+#include "../IO/Log.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <unistd.h>
+#endif
+
+#include "../DebugNew.h"
+
+namespace Urho3D
+{
+
+static const unsigned PIPE_BUFFER_SIZE = 65536;
+
+NamedPipe::NamedPipe(Context* context) :
+    Object(context),
+    isServer_(false),
+#ifdef _WIN32
+    handle_(INVALID_HANDLE_VALUE)
+#else
+    readHandle_(-1),
+    writeHandle_(-1)
+#endif
+{
+}
+
+NamedPipe::NamedPipe(Context* context, const String& pipeName, bool isServer) :
+    Object(context),
+    isServer_(false),
+#ifdef _WIN32
+    handle_(INVALID_HANDLE_VALUE)
+#else
+    readHandle_(-1),
+    writeHandle_(-1)
+#endif
+{
+    Open(pipeName, isServer);
+}
+
+NamedPipe::~NamedPipe()
+{
+    Close();
+}
+
+unsigned NamedPipe::Seek(unsigned position)
+{
+    return 0;
+}
+
+#ifdef _WIN32
+
+static const String pipePath("\\\\.\\pipe\\");
+
+bool NamedPipe::Open(const String& pipeName, bool isServer)
+{
+    URHO3D_PROFILE(OpenNamedPipe);
+
+    Close();
+
+    isServer_ = false;
+
+    if (isServer)
+    {
+        handle_ = CreateNamedPipeW(WString(pipePath + pipeName).CString(),
+            PIPE_ACCESS_DUPLEX,
+            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT,
+            1,
+            PIPE_BUFFER_SIZE,
+            PIPE_BUFFER_SIZE,
+            0,
+            0
+        );
+
+        if (handle_ == INVALID_HANDLE_VALUE)
+        {
+            URHO3D_LOGERROR("Failed to create named pipe " + pipeName);
+            return false;
+        }
+        else
+        {
+            URHO3D_LOGDEBUG("Created named pipe " + pipeName);
+            pipeName_ = pipeName;
+            isServer_ = true;
+            return true;
+        }
+    }
+    else
+    {
+        handle_ = CreateFileW(
+            WString(pipePath + pipeName).CString(),
+            GENERIC_READ | GENERIC_WRITE,
+            0,
+            0,
+            OPEN_EXISTING,
+            0,
+            0
+        );
+
+        if (handle_ == INVALID_HANDLE_VALUE)
+        {
+            URHO3D_LOGERROR("Failed to connect to named pipe " + pipeName);
+            return false;
+        }
+        else
+        {
+            URHO3D_LOGDEBUG("Connected to named pipe " + pipeName);
+            pipeName_ = pipeName;
+            return true;
+        }
+    }
+}
+
+unsigned NamedPipe::Read(void* dest, unsigned size)
+{
+    if (handle_ != INVALID_HANDLE_VALUE)
+    {
+        DWORD read = 0;
+        ReadFile(handle_, dest, size, &read, 0);
+        return read;
+    }
+
+    return 0;
+}
+
+unsigned NamedPipe::Write(const void* data, unsigned size)
+{
+    if (handle_ != INVALID_HANDLE_VALUE)
+    {
+        DWORD written = 0;
+        WriteFile(handle_, data, size, &written, 0);
+        return written;
+    }
+
+    return 0;
+}
+
+void NamedPipe::Close()
+{
+    if (handle_ != INVALID_HANDLE_VALUE)
+    {
+        URHO3D_PROFILE(CloseNamedPipe);
+
+        if (isServer_)
+        {
+            DisconnectNamedPipe(handle_);
+            isServer_ = false;
+        }
+
+        CloseHandle(handle_);
+        handle_ = INVALID_HANDLE_VALUE;
+        pipeName_.Clear();
+
+        URHO3D_LOGDEBUG("Closed named pipe " + pipeName_);
+    }
+}
+
+bool NamedPipe::IsOpen() const
+{
+    return handle_ != INVALID_HANDLE_VALUE;
+}
+
+bool NamedPipe::IsEof() const
+{
+    if (handle_ != INVALID_HANDLE_VALUE)
+    {
+        DWORD bytesAvailable = 0;
+        PeekNamedPipe(handle_, 0, 0, 0, &bytesAvailable, 0);
+        return bytesAvailable == 0;
+    }
+    else
+        return true;
+}
+
+#else
+
+static const String pipePath("/tmp/");
+
+#define SAFE_CLOSE(handle) if (handle != -1) { close(handle); handle = -1; }
+
+bool NamedPipe::Open(const String& pipeName, bool isServer)
+{
+#ifdef __EMSCRIPTEN__
+    URHO3D_LOGERROR("Opening a named pipe not supported on Web platform");
+    return false;
+#else
+    URHO3D_PROFILE(OpenNamedPipe);
+
+    Close();
+
+    isServer_ = false;
+
+    String serverReadName = pipePath + pipeName + "SR";
+    String clientReadName = pipePath + pipeName + "CR";
+
+    // Make sure SIGPIPE is ignored and will not lead to process termination
+    signal(SIGPIPE, SIG_IGN);
+
+    if (isServer)
+    {
+        mkfifo(serverReadName.CString(), 0660);
+        mkfifo(clientReadName.CString(), 0660);
+
+        readHandle_ = open(serverReadName.CString(), O_RDONLY | O_NDELAY);
+        writeHandle_ = open(clientReadName.CString(), O_WRONLY | O_NDELAY);
+
+        if (readHandle_ == -1 && writeHandle_ == -1)
+        {
+            URHO3D_LOGERROR("Failed to create named pipe " + pipeName);
+            SAFE_CLOSE(readHandle_);
+            SAFE_CLOSE(writeHandle_);
+            unlink(serverReadName.CString());
+            unlink(clientReadName.CString());
+            return false;
+        }
+        else
+        {
+            URHO3D_LOGDEBUG("Created named pipe " + pipeName);
+            pipeName_ = pipeName;
+            isServer_ = true;
+            return true;
+        }
+    }
+    else
+    {
+        readHandle_ = open(clientReadName.CString(), O_RDONLY | O_NDELAY);
+        writeHandle_ = open(serverReadName.CString(), O_WRONLY | O_NDELAY);
+        if (readHandle_ == -1 && writeHandle_ == -1)
+        {
+            URHO3D_LOGERROR("Failed to connect to named pipe " + pipeName);
+            SAFE_CLOSE(readHandle_);
+            SAFE_CLOSE(writeHandle_);
+            return false;
+        }
+        else
+        {
+            URHO3D_LOGDEBUG("Connected to named pipe " + pipeName);
+            pipeName_ = pipeName;
+            return true;
+        }
+    }
+#endif
+}
+
+unsigned NamedPipe::Read(void* dest, unsigned size)
+{
+    // Attempt to open late if only the write handle is open yet
+    if (readHandle_ == -1 && writeHandle_ != -1)
+    {
+        if (isServer_)
+            readHandle_ = open((pipePath + pipeName_ + "SR").CString(), O_RDONLY | O_NDELAY);
+        else
+            readHandle_ = open((pipePath + pipeName_ + "CR").CString(), O_RDONLY | O_NDELAY);
+    }
+
+    if (readHandle_ != -1)
+    {
+        ssize_t readNow = read(readHandle_, dest, size);
+        return readNow < 0 ? 0 : (unsigned)readNow;
+    }
+    else
+        return 0;
+}
+
+unsigned NamedPipe::Write(const void* data, unsigned size)
+{
+    // Attempt to open late if only the read handle is open yet
+    if (writeHandle_ == -1 && readHandle_ != -1)
+    {
+        if (isServer_)
+            writeHandle_ = open((pipePath + pipeName_ + "CR").CString(), O_WRONLY | O_NDELAY);
+        else
+            writeHandle_ = open((pipePath + pipeName_ + "SR").CString(), O_WRONLY | O_NDELAY);
+    }
+
+    // Loop until all bytes written in case of partial write
+    if (writeHandle_ != -1)
+    {
+        ssize_t written = 0;
+        while (written < (ssize_t)size)
+        {
+            ssize_t writtenNow = write(writeHandle_, ((const unsigned char*)data) + written, size - written);
+            if (writtenNow < 0)
+                return 0; // Error while writing
+            written += writtenNow;
+        }
+
+        return (unsigned)written;
+    }
+    else
+        return 0;
+}
+
+void NamedPipe::Close()
+{
+    if (readHandle_ != -1 || writeHandle_ != -1)
+    {
+        URHO3D_PROFILE(CloseNamedPipe);
+        SAFE_CLOSE(readHandle_);
+        SAFE_CLOSE(writeHandle_);
+
+        if (isServer_)
+        {
+            String serverReadName = pipePath + pipeName_ + "SR";
+            String clientReadName = pipePath + pipeName_ + "CR";
+            unlink(serverReadName.CString());
+            unlink(clientReadName.CString());
+            isServer_ = false;
+        }
+
+        pipeName_.Clear();
+    }
+}
+
+bool NamedPipe::IsOpen() const
+{
+    return readHandle_ != -1 || writeHandle_ != -1;
+}
+
+bool NamedPipe::IsEof() const
+{
+#ifdef __EMSCRIPTEN__
+    return true;
+#else
+    // Attempt to open late if only the write handle is open yet
+    if (readHandle_ == -1 && writeHandle_ != -1)
+    {
+        if (isServer_)
+            readHandle_ = open((pipePath + pipeName_ + "SR").CString(), O_RDONLY | O_NDELAY);
+        else
+            readHandle_ = open((pipePath + pipeName_ + "CR").CString(), O_RDONLY | O_NDELAY);
+    }
+
+    if (readHandle_ != -1)
+    {
+        fd_set set;
+        FD_ZERO(&set);
+        FD_SET(readHandle_, &set);
+
+        struct timeval timeout;
+        timeout.tv_sec = 0;
+        timeout.tv_usec = 1000; // 1ms timeout for select
+
+        return select(readHandle_ + 1, &set, 0, 0, &timeout) <= 0;
+    }
+    else
+        return true;
+#endif
+}
+#endif
+
+}

+ 85 - 0
Source/Urho3D/IO/NamedPipe.h

@@ -0,0 +1,85 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "../Container/ArrayPtr.h"
+#include "../Core/Object.h"
+#include "../IO/Deserializer.h"
+#include "../IO/Serializer.h"
+
+#ifdef ANDROID
+#include <SDL/SDL_rwops.h>
+#endif
+
+namespace Urho3D
+{
+
+/// Named pipe for interprocess communication.
+class URHO3D_API NamedPipe : public Object, public Deserializer, public Serializer
+{
+    URHO3D_OBJECT(NamedPipe, Object);
+
+public:
+    /// Construct.
+    NamedPipe(Context* context);
+    /// Construct and open in either server or client mode.
+    NamedPipe(Context* context, const String& pipeName, bool isServer);
+    /// Destruct and close.
+    virtual ~NamedPipe();
+
+    /// Read bytes from the pipe without blocking if there is less data available. Return number of bytes actually read. 
+    virtual unsigned Read(void* dest, unsigned size);
+    /// Set position. No-op for pipes.
+    virtual unsigned Seek(unsigned position);
+    /// Write bytes to the pipe. Return number of bytes actually written.
+    virtual unsigned Write(const void* data, unsigned size);
+    /// Return whether pipe has no data available.
+    virtual bool IsEof() const;
+    /// Return the pipe name.
+    virtual const String& GetName() const { return pipeName_; }
+
+    /// Open the pipe in either server or client mode. If already open, the existing pipe is closed. For a client end to open successfully the server end must already to be open. Return true if successful.
+    bool Open(const String& pipeName, bool isServer);
+    /// Close the pipe. Note that once a client has disconnected, the server needs to close and reopen the pipe so that another client can connect. At least on Windows this is not possible to detect automatically, so the communication protocol should include a "bye" message to handle this situation.
+    void Close();
+
+    /// Return whether is open.
+    bool IsOpen() const;
+    /// Return whether is in server mode.
+    bool IsServer() const { return isServer_; }
+
+private:
+    /// Pipe name.
+    String pipeName_;
+    /// Server mode flag.
+    bool isServer_;
+    /// Pipe handle.
+#ifdef _WIN32
+    void* handle_;
+#else
+    mutable int readHandle_;
+    mutable int writeHandle_;
+#endif
+};
+
+}

+ 2 - 0
Source/Urho3D/LuaScript/pkgs/Engine/DebugHud.pkg

@@ -4,8 +4,10 @@ static const unsigned DEBUGHUD_SHOW_NONE;
 static const unsigned DEBUGHUD_SHOW_STATS;
 static const unsigned DEBUGHUD_SHOW_STATS;
 static const unsigned DEBUGHUD_SHOW_MODE;
 static const unsigned DEBUGHUD_SHOW_MODE;
 static const unsigned DEBUGHUD_SHOW_PROFILER;
 static const unsigned DEBUGHUD_SHOW_PROFILER;
+static const unsigned DEBUGHUD_SHOW_MEMORY;
 static const unsigned DEBUGHUD_SHOW_ALL;
 static const unsigned DEBUGHUD_SHOW_ALL;
 static const unsigned DEBUGHUD_SHOW_ALL_MEMORY;
 static const unsigned DEBUGHUD_SHOW_ALL_MEMORY;
+static const unsigned DEBUGHUD_SHOW_EVENTPROFILER;
 
 
 class DebugHud : public Object
 class DebugHud : public Object
 {
 {

+ 3 - 1
Source/Urho3D/LuaScript/pkgs/Graphics/BillboardSet.pkg

@@ -8,7 +8,6 @@ struct Billboard
     Color color_ @ color;
     Color color_ @ color;
     float rotation_ @ rotation;
     float rotation_ @ rotation;
     bool enabled_ @ enabled;
     bool enabled_ @ enabled;
-    float sortDistance_ @ sortDistance;
 };
 };
 
 
 class BillboardSet : public Drawable
 class BillboardSet : public Drawable
@@ -18,6 +17,7 @@ class BillboardSet : public Drawable
     void SetRelative(bool enable);
     void SetRelative(bool enable);
     void SetScaled(bool enable);
     void SetScaled(bool enable);
     void SetSorted(bool enable);
     void SetSorted(bool enable);
+    void SetFixedScreenSize(bool enable);
     void SetFaceCameraMode(FaceCameraMode mode);
     void SetFaceCameraMode(FaceCameraMode mode);
     void SetAnimationLodBias(float bias);
     void SetAnimationLodBias(float bias);
 
 
@@ -29,6 +29,7 @@ class BillboardSet : public Drawable
     bool IsRelative() const;
     bool IsRelative() const;
     bool IsScaled() const;
     bool IsScaled() const;
     bool IsSorted() const;
     bool IsSorted() const;
+    bool IsFixedScreenSize() const;
     FaceCameraMode GetFaceCameraMode() const;
     FaceCameraMode GetFaceCameraMode() const;
     float GetAnimationLodBias() const;
     float GetAnimationLodBias() const;
     
     
@@ -37,6 +38,7 @@ class BillboardSet : public Drawable
     tolua_property__is_set bool relative;
     tolua_property__is_set bool relative;
     tolua_property__is_set bool scaled;
     tolua_property__is_set bool scaled;
     tolua_property__is_set bool sorted;
     tolua_property__is_set bool sorted;
+    tolua_property__is_set bool fixedScreenSize;
     tolua_property__get_set FaceCameraMode faceCameraMode;
     tolua_property__get_set FaceCameraMode faceCameraMode;
     tolua_property__get_set float animationLodBias;
     tolua_property__get_set float animationLodBias;
 };
 };

+ 3 - 0
Source/Urho3D/LuaScript/pkgs/Graphics/ParticleEffect.pkg

@@ -38,6 +38,7 @@ class ParticleEffect : public Resource
     void SetRelative(bool enable);
     void SetRelative(bool enable);
     void SetScaled(bool enable);
     void SetScaled(bool enable);
     void SetSorted(bool enable);
     void SetSorted(bool enable);
+    void SetFixedScreenSize(bool enable);
     void SetAnimationLodBias(float lodBias);
     void SetAnimationLodBias(float lodBias);
     void SetEmitterType(EmitterType type);
     void SetEmitterType(EmitterType type);
     void SetEmitterSize(const Vector3& size);
     void SetEmitterSize(const Vector3& size);
@@ -80,6 +81,7 @@ class ParticleEffect : public Resource
     bool IsRelative() const;
     bool IsRelative() const;
     bool IsScaled() const;
     bool IsScaled() const;
     bool IsSorted() const;
     bool IsSorted() const;
+    bool IsFixedScreenSize() const;
     float GetAnimationLodBias() const;
     float GetAnimationLodBias() const;
     EmitterType GetEmitterType() const;
     EmitterType GetEmitterType() const;
     const Vector3& GetEmitterSize() const;
     const Vector3& GetEmitterSize() const;
@@ -114,6 +116,7 @@ class ParticleEffect : public Resource
     tolua_property__is_set bool relative;
     tolua_property__is_set bool relative;
     tolua_property__is_set bool scaled;
     tolua_property__is_set bool scaled;
     tolua_property__is_set bool sorted;
     tolua_property__is_set bool sorted;
+    tolua_property__is_set bool fixedScreenSize;
     tolua_property__get_set float animationLodBias;
     tolua_property__get_set float animationLodBias;
     tolua_property__get_set EmitterType emitterType;
     tolua_property__get_set EmitterType emitterType;
     tolua_property__get_set const Vector3& emitterSize;
     tolua_property__get_set const Vector3& emitterSize;

+ 174 - 0
Source/Urho3D/LuaScript/pkgs/IO/NamedPipe.pkg

@@ -0,0 +1,174 @@
+$#include "IO/NamedPipe.h"
+
+class NamedPipe : public Object
+{
+    NamedPipe();
+    NamedPipe(const String pipeName, bool isServer);
+    ~NamedPipe();
+
+    bool Open(const String pipeName, bool isServer);
+    void Close();
+    bool IsOpen() const;
+
+    // From Deserializer
+    // unsigned Read(void* dest, unsigned size);
+    tolua_outside VectorBuffer DeserializerRead @ Read(unsigned size);
+    const String GetName() const;
+    bool IsEof() const;
+
+    int ReadInt();
+    short ReadShort();
+    signed char ReadByte();
+    unsigned ReadUInt();
+    unsigned short ReadUShort();
+    unsigned char ReadUByte();
+    bool ReadBool();
+    float ReadFloat();
+    double ReadDouble();
+    IntRect ReadIntRect();
+    IntVector2 ReadIntVector2();
+    Rect ReadRect();
+    Vector2 ReadVector2();
+    Vector3 ReadVector3();
+    Vector3 ReadPackedVector3(float maxAbsCoord);
+    Vector4 ReadVector4();
+    Quaternion ReadQuaternion();
+    Quaternion ReadPackedQuaternion();
+    Matrix3 ReadMatrix3();
+    Matrix3x4 ReadMatrix3x4();
+    Matrix4 ReadMatrix4();
+    Color ReadColor();
+    BoundingBox ReadBoundingBox();
+    String ReadString();
+    String ReadFileID();
+    StringHash ReadStringHash();
+
+    // PODVector<unsigned char> ReadBuffer();
+    VectorBuffer ReadBuffer();
+
+    ResourceRef ReadResourceRef();
+    ResourceRefList ReadResourceRefList();
+    Variant ReadVariant();
+    Variant ReadVariant(VariantType type);
+    VariantVector ReadVariantVector();
+    VariantMap ReadVariantMap();
+    unsigned ReadVLE();
+    unsigned ReadNetID();
+    String ReadLine();
+
+    // From Serializer
+    // unsigned Write(const void* data, unsigned size);
+    tolua_outside unsigned SerializerWrite @ Write(const VectorBuffer& buffer);
+
+    bool WriteInt(int value);
+    bool WriteShort(short value);
+    bool WriteByte(signed char value);
+    bool WriteUInt(unsigned value);
+    bool WriteUShort(unsigned short value);
+    bool WriteUByte(unsigned char value);
+    bool WriteBool(bool value);
+    bool WriteFloat(float value);
+    bool WriteDouble(double value);
+    bool WriteIntRect(const IntRect& value);
+    bool WriteIntVector2(const IntVector2& value);
+    bool WriteRect(const Rect& value);
+    bool WriteVector2(const Vector2& value);
+    bool WriteVector3(const Vector3& value);
+    bool WritePackedVector3(const Vector3& value, float maxAbsCoord);
+    bool WriteVector4(const Vector4& value);
+    bool WriteQuaternion(const Quaternion& value);
+    bool WritePackedQuaternion(const Quaternion& value);
+    bool WriteMatrix3(const Matrix3& value);
+    bool WriteMatrix3x4(const Matrix3x4& value);
+    bool WriteMatrix4(const Matrix4& value);
+    bool WriteColor(const Color& value);
+    bool WriteBoundingBox(const BoundingBox& value);
+    bool WriteString(const String value);
+    bool WriteFileID(const String value);
+    bool WriteStringHash(const StringHash& value);
+
+    // bool WriteBuffer(const PODVector<unsigned char>& buffer);
+    tolua_outside bool SerializerWriteBuffer @ WriteBuffer(const VectorBuffer& buffer);
+
+    bool WriteResourceRef(const ResourceRef& value);
+    bool WriteResourceRefList(const ResourceRefList& value);
+    bool WriteVariant(const Variant& value);
+    bool WriteVariantData(const Variant& value);
+    bool WriteVariantVector(const VariantVector& value);
+    bool WriteVariantMap(const VariantMap& value);
+    bool WriteVLE(unsigned value);
+    bool WriteNetID(unsigned value);
+    bool WriteLine(const String value);
+
+    // From Deserializer
+    tolua_readonly tolua_property__get_set String name;
+    tolua_readonly tolua_property__is_set bool eof;
+
+    tolua_readonly tolua_property__is_set bool open;
+};
+
+${
+#define TOLUA_DISABLE_tolua_IOLuaAPI_NamedPipe_new00
+static int tolua_IOLuaAPI_NamedPipe_new00(lua_State* tolua_S)
+{
+    return ToluaNewObject<NamedPipe>(tolua_S);
+}
+
+#define TOLUA_DISABLE_tolua_IOLuaAPI_NamedPipe_new00_local
+static int tolua_IOLuaAPI_NamedPipe_new00_local(lua_State* tolua_S)
+{
+    return ToluaNewObjectGC<NamedPipe>(tolua_S);
+}
+
+#define TOLUA_DISABLE_tolua_IOLuaAPI_NamedPipe_new01
+static int tolua_IOLuaAPI_NamedPipe_new01(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"NamedPipe",0,&tolua_err) ||
+ !tolua_isurho3dstring(tolua_S,2,0,&tolua_err) ||
+ !tolua_isboolean(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+  const String pipeName = ((const String)  tolua_tourho3dstring(tolua_S,2,0));
+  bool isServer = ((bool)  tolua_toboolean(tolua_S,3,0));
+ {
+  NamedPipe* tolua_ret = (NamedPipe*)  Mtolua_new((NamedPipe)(GetContext(tolua_S),pipeName,isServer));
+  tolua_pushusertype(tolua_S,(void*)tolua_ret,"NamedPipe");
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_IOLuaAPI_NamedPipe_new00(tolua_S);
+}
+
+#define TOLUA_DISABLE_tolua_IOLuaAPI_NamedPipe_new01_local
+static int tolua_IOLuaAPI_NamedPipe_new01_local(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"NamedPipe",0,&tolua_err) ||
+ !tolua_isurho3dstring(tolua_S,2,0,&tolua_err) ||
+ !tolua_isboolean(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+  const String pipeName = ((const String)  tolua_tourho3dstring(tolua_S,2,0));
+  bool isServer = ((bool)  tolua_toboolean(tolua_S,3,0));
+ {
+  NamedPipe* tolua_ret = (NamedPipe*)  Mtolua_new((NamedPipe)(GetContext(tolua_S),pipeName,isServer));
+  tolua_pushusertype(tolua_S,(void*)tolua_ret,"NamedPipe");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_IOLuaAPI_NamedPipe_new00_local(tolua_S);
+}
+
+$}

+ 1 - 0
Source/Urho3D/LuaScript/pkgs/IOLuaAPI.pkg

@@ -3,6 +3,7 @@ $pfile "IO/Deserializer.pkg"
 $pfile "IO/File.pkg"
 $pfile "IO/File.pkg"
 $pfile "IO/FileSystem.pkg"
 $pfile "IO/FileSystem.pkg"
 $pfile "IO/Log.pkg"
 $pfile "IO/Log.pkg"
+$pfile "IO/NamedPipe.pkg"
 $pfile "IO/PackageFile.pkg"
 $pfile "IO/PackageFile.pkg"
 $pfile "IO/Serializer.pkg"
 $pfile "IO/Serializer.pkg"
 $pfile "IO/VectorBuffer.pkg"
 $pfile "IO/VectorBuffer.pkg"

+ 8 - 0
Source/Urho3D/LuaScript/pkgs/LuaScript/LuaScript.pkg

@@ -20,7 +20,15 @@ void LuaScriptSetGlobalVar @ SetGlobalVar(const String key, Variant value);
 Variant LuaScriptGetGlobalVar @ GetGlobalVar(const String key);
 Variant LuaScriptGetGlobalVar @ GetGlobalVar(const String key);
 VariantMap& LuaScriptGetGlobalVars @ GetGlobalVars();
 VariantMap& LuaScriptGetGlobalVars @ GetGlobalVars();
 
 
+void RegisterEventName(const String eventName);
+
 ${
 ${
+
+static void RegisterEventName(const String eventName)
+{
+    EventNameRegistrar::RegisterEventName(eventName.CString());
+}
+
 static LuaScript* GetLuaScript(lua_State* L)
 static LuaScript* GetLuaScript(lua_State* L)
 {
 {
     return GetContext(L)->GetSubsystem<LuaScript>();
     return GetContext(L)->GetSubsystem<LuaScript>();

+ 58 - 1
Source/Urho3D/LuaScript/pkgs/Network/HttpRequest.pkg

@@ -8,7 +8,7 @@ enum HttpRequestState
     HTTP_CLOSED
     HTTP_CLOSED
 };
 };
 
 
-class HttpRequest : public Deserializer
+class HttpRequest
 {
 {
     const String GetURL() const;
     const String GetURL() const;
     const String GetVerb() const;
     const String GetVerb() const;
@@ -16,7 +16,52 @@ class HttpRequest : public Deserializer
     HttpRequestState GetState() const;
     HttpRequestState GetState() const;
     unsigned GetAvailableSize() const;
     unsigned GetAvailableSize() const;
     bool IsOpen() const;
     bool IsOpen() const;
+
+    // From Deserializer
+    // unsigned Read(void* dest, unsigned size);
+    tolua_outside VectorBuffer HttpRequestRead @ Read(unsigned size);
+    bool IsEof() const;
+    
+    int ReadInt();
+    short ReadShort();
+    signed char ReadByte();
+    unsigned ReadUInt();
+    unsigned short ReadUShort();
+    unsigned char ReadUByte();
+    bool ReadBool();
+    float ReadFloat();
+    double ReadDouble();
+    IntRect ReadIntRect();
+    IntVector2 ReadIntVector2();
+    Rect ReadRect();
+    Vector2 ReadVector2();
+    Vector3 ReadVector3();
+    Vector3 ReadPackedVector3(float maxAbsCoord);
+    Vector4 ReadVector4();
+    Quaternion ReadQuaternion();
+    Quaternion ReadPackedQuaternion();
+    Matrix3 ReadMatrix3();
+    Matrix3x4 ReadMatrix3x4();
+    Matrix4 ReadMatrix4();
+    Color ReadColor();
+    BoundingBox ReadBoundingBox();
+    String ReadString();
+    String ReadFileID();
+    StringHash ReadStringHash();
     
     
+    // PODVector<unsigned char> ReadBuffer();
+    VectorBuffer ReadBuffer();
+    
+    ResourceRef ReadResourceRef();
+    ResourceRefList ReadResourceRefList();
+    Variant ReadVariant();
+    Variant ReadVariant(VariantType type);
+    VariantVector ReadVariantVector();
+    VariantMap ReadVariantMap();
+    unsigned ReadVLE();
+    unsigned ReadNetID();
+    String ReadLine();
+
     tolua_readonly tolua_property__get_set String URL;
     tolua_readonly tolua_property__get_set String URL;
     tolua_readonly tolua_property__get_set String verb;
     tolua_readonly tolua_property__get_set String verb;
     tolua_readonly tolua_property__get_set String error;
     tolua_readonly tolua_property__get_set String error;
@@ -24,3 +69,15 @@ class HttpRequest : public Deserializer
     tolua_readonly tolua_property__get_set unsigned availableSize;
     tolua_readonly tolua_property__get_set unsigned availableSize;
     tolua_readonly tolua_property__is_set bool open;
     tolua_readonly tolua_property__is_set bool open;
 };
 };
+
+${
+static VectorBuffer HttpRequestRead(HttpRequest* request, unsigned size)
+{
+    unsigned char* data = new unsigned char[size];
+    request->Read(data, size);
+    VectorBuffer buffer(data, size);
+    delete [] data;
+    return buffer;
+}
+$}
+

+ 1 - 0
Source/Urho3D/LuaScript/pkgs/Resource/JSONFile.pkg

@@ -5,6 +5,7 @@ class JSONFile : Resource
     JSONFile();
     JSONFile();
     ~JSONFile();
     ~JSONFile();
 
 
+    bool FromString(const String source);
     const JSONValue& GetRoot() const;
     const JSONValue& GetRoot() const;
 
 
     tolua_outside bool JSONFileSave @ Save(const String fileName, const String indentation = "\t") const;
     tolua_outside bool JSONFileSave @ Save(const String fileName, const String indentation = "\t") const;

+ 1 - 1
Source/Urho3D/LuaScript/pkgs/UI/ScrollBar.pkg

@@ -1,6 +1,6 @@
 $#include "UI/ScrollBar.h"
 $#include "UI/ScrollBar.h"
 
 
-class ScrollBar : public UIElement
+class ScrollBar : public BorderImage
 {
 {
     ScrollBar();
     ScrollBar();
     virtual ~ScrollBar();
     virtual ~ScrollBar();

+ 3 - 3
Source/Urho3D/LuaScript/pkgs/UI/Text.pkg

@@ -25,7 +25,7 @@ class Text : public UIElement
     void SetSelectionColor(const Color& color);
     void SetSelectionColor(const Color& color);
     void SetHoverColor(const Color& color);
     void SetHoverColor(const Color& color);
     void SetTextEffect(TextEffect textEffect);
     void SetTextEffect(TextEffect textEffect);
-    void SetEffectShadowOffset(IntVector2 offset);
+    void SetEffectShadowOffset(const IntVector2& offset);
     void SetEffectStrokeThickness(int thickness);
     void SetEffectStrokeThickness(int thickness);
     void SetEffectRoundStroke(bool roundStroke);
     void SetEffectRoundStroke(bool roundStroke);
     void SetEffectColor(const Color& effectColor);
     void SetEffectColor(const Color& effectColor);
@@ -44,7 +44,7 @@ class Text : public UIElement
     const Color& GetSelectionColor() const;
     const Color& GetSelectionColor() const;
     const Color& GetHoverColor() const;
     const Color& GetHoverColor() const;
     TextEffect GetTextEffect() const;
     TextEffect GetTextEffect() const;
-    IntVector2 GetEffectShadowOffset() const;
+    const IntVector2& GetEffectShadowOffset() const;
     int GetEffectStrokeThickness() const;
     int GetEffectStrokeThickness() const;
     bool GetEffectRoundStroke() const;
     bool GetEffectRoundStroke() const;
     const Color& GetEffectColor() const;
     const Color& GetEffectColor() const;
@@ -70,7 +70,7 @@ class Text : public UIElement
     tolua_property__get_set Color& selectionColor;
     tolua_property__get_set Color& selectionColor;
     tolua_property__get_set Color& hoverColor;
     tolua_property__get_set Color& hoverColor;
     tolua_property__get_set TextEffect textEffect;
     tolua_property__get_set TextEffect textEffect;
-    tolua_property__get_set IntVector2 effectShadowOffset;
+    tolua_property__get_set IntVector2& effectShadowOffset;
     tolua_property__get_set int effectStrokeThickness;
     tolua_property__get_set int effectStrokeThickness;
     tolua_property__get_set bool effectRoundStroke;
     tolua_property__get_set bool effectRoundStroke;
     tolua_property__get_set Color& effectColor;
     tolua_property__get_set Color& effectColor;

+ 6 - 3
Source/Urho3D/LuaScript/pkgs/UI/Text3D.pkg

@@ -29,7 +29,7 @@ class Text3D : public Drawable
     void SetRowSpacing(float spacing);
     void SetRowSpacing(float spacing);
     void SetWordwrap(bool enable);
     void SetWordwrap(bool enable);
     void SetTextEffect(TextEffect textEffect);
     void SetTextEffect(TextEffect textEffect);
-    void SetEffectShadowOffset(IntVector2 offset);
+    void SetEffectShadowOffset(const IntVector2& offset);
     void SetEffectStrokeThickness(int thickness);
     void SetEffectStrokeThickness(int thickness);
     void SetEffectRoundStroke(bool roundStroke);
     void SetEffectRoundStroke(bool roundStroke);
     void SetEffectColor(const Color& effectColor);
     void SetEffectColor(const Color& effectColor);
@@ -38,6 +38,7 @@ class Text3D : public Drawable
     void SetColor(const Color& color);
     void SetColor(const Color& color);
     void SetColor(Corner corner, const Color& color);
     void SetColor(Corner corner, const Color& color);
     void SetOpacity(float opacity);
     void SetOpacity(float opacity);
+    void SetFixedScreenSize(bool enable);
     void SetFaceCameraMode(FaceCameraMode mode);
     void SetFaceCameraMode(FaceCameraMode mode);
 
 
     Font* GetFont() const;
     Font* GetFont() const;
@@ -50,7 +51,7 @@ class Text3D : public Drawable
     float GetRowSpacing() const;
     float GetRowSpacing() const;
     bool GetWordwrap() const;
     bool GetWordwrap() const;
     TextEffect GetTextEffect() const;
     TextEffect GetTextEffect() const;
-    IntVector2 GetEffectShadowOffset() const;
+    const IntVector2& GetEffectShadowOffset() const;
     int GetEffectStrokeThickness() const;
     int GetEffectStrokeThickness() const;
     bool GetEffectRoundStroke() const;
     bool GetEffectRoundStroke() const;
     const Color& GetEffectColor() const;
     const Color& GetEffectColor() const;
@@ -64,6 +65,7 @@ class Text3D : public Drawable
     IntVector2 GetCharSize(unsigned index);
     IntVector2 GetCharSize(unsigned index);
     const Color& GetColor(Corner corner) const;
     const Color& GetColor(Corner corner) const;
     float GetOpacity() const;
     float GetOpacity() const;
+    bool IsFixedScreenSize() const;
     FaceCameraMode GetFaceCameraMode() const;
     FaceCameraMode GetFaceCameraMode() const;
 
 
     tolua_property__get_set Font* font;
     tolua_property__get_set Font* font;
@@ -76,7 +78,7 @@ class Text3D : public Drawable
     tolua_property__get_set float rowSpacing;
     tolua_property__get_set float rowSpacing;
     tolua_property__get_set bool wordwrap;
     tolua_property__get_set bool wordwrap;
     tolua_property__get_set TextEffect textEffect;
     tolua_property__get_set TextEffect textEffect;
-    tolua_property__get_set IntVector2 effectShadowOffset;
+    tolua_property__get_set IntVector2& effectShadowOffset;
     tolua_property__get_set int effectStrokeThickness;
     tolua_property__get_set int effectStrokeThickness;
     tolua_property__get_set bool effectRoundStroke;
     tolua_property__get_set bool effectRoundStroke;
     tolua_property__get_set Color& effectColor;
     tolua_property__get_set Color& effectColor;
@@ -87,6 +89,7 @@ class Text3D : public Drawable
     tolua_readonly tolua_property__get_set unsigned numRows;
     tolua_readonly tolua_property__get_set unsigned numRows;
     tolua_readonly tolua_property__get_set unsigned numChars;
     tolua_readonly tolua_property__get_set unsigned numChars;
     tolua_property__get_set float opacity;
     tolua_property__get_set float opacity;
+    tolua_property__is_set bool fixedScreenSize;
     tolua_property__get_set FaceCameraMode faceCameraMode;
     tolua_property__get_set FaceCameraMode faceCameraMode;
 };
 };
 
 

+ 18 - 14
Source/Urho3D/Network/HttpRequest.cpp

@@ -207,12 +207,12 @@ unsigned HttpRequest::Read(void* dest, unsigned size)
 
 
     for (;;)
     for (;;)
     {
     {
-        unsigned bytesAvailable;
+        Pair<unsigned, bool> status;
 
 
         for (;;)
         for (;;)
         {
         {
-            bytesAvailable = CheckEofAndAvailableSize();
-            if (bytesAvailable || IsEof())
+            status = CheckAvailableSizeAndEof();
+            if (status.first_ || status.second_)
                 break;
                 break;
             // While no bytes and connection is still open, block until has some data
             // While no bytes and connection is still open, block until has some data
             mutex_.Release();
             mutex_.Release();
@@ -220,6 +220,8 @@ unsigned HttpRequest::Read(void* dest, unsigned size)
             mutex_.Acquire();
             mutex_.Acquire();
         }
         }
 
 
+        unsigned bytesAvailable = status.first_;
+
         if (bytesAvailable)
         if (bytesAvailable)
         {
         {
             if (bytesAvailable > sizeLeft)
             if (bytesAvailable > sizeLeft)
@@ -247,8 +249,6 @@ unsigned HttpRequest::Read(void* dest, unsigned size)
             break;
             break;
     }
     }
 
 
-    // Check for end-of-file once more after reading the bytes
-    CheckEofAndAvailableSize();
     mutex_.Release();
     mutex_.Release();
     return totalRead;
     return totalRead;
 #else
 #else
@@ -259,35 +259,39 @@ unsigned HttpRequest::Read(void* dest, unsigned size)
 
 
 unsigned HttpRequest::Seek(unsigned position)
 unsigned HttpRequest::Seek(unsigned position)
 {
 {
-    return position_;
+    return 0;
+}
+
+bool HttpRequest::IsEof() const
+{
+    MutexLock lock(mutex_);
+    return CheckAvailableSizeAndEof().second_;
 }
 }
 
 
 String HttpRequest::GetError() const
 String HttpRequest::GetError() const
 {
 {
     MutexLock lock(mutex_);
     MutexLock lock(mutex_);
-    const_cast<HttpRequest*>(this)->CheckEofAndAvailableSize();
     return error_;
     return error_;
 }
 }
 
 
 HttpRequestState HttpRequest::GetState() const
 HttpRequestState HttpRequest::GetState() const
 {
 {
     MutexLock lock(mutex_);
     MutexLock lock(mutex_);
-    const_cast<HttpRequest*>(this)->CheckEofAndAvailableSize();
     return state_;
     return state_;
 }
 }
 
 
 unsigned HttpRequest::GetAvailableSize() const
 unsigned HttpRequest::GetAvailableSize() const
 {
 {
     MutexLock lock(mutex_);
     MutexLock lock(mutex_);
-    return const_cast<HttpRequest*>(this)->CheckEofAndAvailableSize();
+    return CheckAvailableSizeAndEof().first_;
 }
 }
 
 
-unsigned HttpRequest::CheckEofAndAvailableSize()
+Pair<unsigned, bool> HttpRequest::CheckAvailableSizeAndEof() const
 {
 {
-    unsigned bytesAvailable = (writePosition_ - readPosition_) & (READ_BUFFER_SIZE - 1);
-    if (state_ == HTTP_ERROR || (state_ == HTTP_CLOSED && !bytesAvailable))
-        position_ = M_MAX_UNSIGNED;
-    return bytesAvailable;
+    Pair<unsigned, bool> ret;
+    ret.first_ = (writePosition_ - readPosition_) & (READ_BUFFER_SIZE - 1);
+    ret.second_ = (state_ == HTTP_ERROR || (state_ == HTTP_CLOSED && !ret.first_));
+    return ret;
 }
 }
 
 
 }
 }

+ 4 - 2
Source/Urho3D/Network/HttpRequest.h

@@ -56,6 +56,8 @@ public:
     virtual unsigned Read(void* dest, unsigned size);
     virtual unsigned Read(void* dest, unsigned size);
     /// Set position from the beginning of the stream. Not supported.
     /// Set position from the beginning of the stream. Not supported.
     virtual unsigned Seek(unsigned position);
     virtual unsigned Seek(unsigned position);
+    /// Return whether all response data has been read.
+    virtual bool IsEof() const;
 
 
     /// Return URL used in the request.
     /// Return URL used in the request.
     const String& GetURL() const { return url_; }
     const String& GetURL() const { return url_; }
@@ -74,8 +76,8 @@ public:
     bool IsOpen() const { return GetState() == HTTP_OPEN; }
     bool IsOpen() const { return GetState() == HTTP_OPEN; }
 
 
 private:
 private:
-    /// Check for end of the data stream and return available size in buffer. Must only be called when the mutex is held by the main thread.
-    unsigned CheckEofAndAvailableSize();
+    /// Check for available read data in buffer and whether end has been reached. Must only be called when the mutex is held by the main thread.
+    Pair<unsigned, bool> CheckAvailableSizeAndEof() const;
 
 
     /// URL.
     /// URL.
     String url_;
     String url_;

+ 3 - 15
Source/Urho3D/Resource/Image.cpp

@@ -1159,21 +1159,9 @@ bool Image::SavePNG(const String& fileName) const
 {
 {
     URHO3D_PROFILE(SaveImagePNG);
     URHO3D_PROFILE(SaveImagePNG);
 
 
-    FileSystem* fileSystem = GetSubsystem<FileSystem>();
-    if (fileSystem && !fileSystem->CheckAccess(GetPath(fileName)))
-    {
-        URHO3D_LOGERROR("Access denied to " + fileName);
-        return false;
-    }
-
-    if (IsCompressed())
-    {
-        URHO3D_LOGERROR("Can not save compressed image to PNG");
-        return false;
-    }
-
-    if (data_)
-        return stbi_write_png(GetNativePath(fileName).CString(), width_, height_, components_, data_.Get(), 0) != 0;
+    File outFile(context_, fileName, FILE_WRITE);
+    if (outFile.IsOpen())
+        return Image::Save(outFile); // Save uses PNG format
     else
     else
         return false;
         return false;
 }
 }

+ 10 - 0
Source/Urho3D/Resource/JSONFile.cpp

@@ -27,6 +27,7 @@
 #include "../Core/Context.h"
 #include "../Core/Context.h"
 #include "../IO/Deserializer.h"
 #include "../IO/Deserializer.h"
 #include "../IO/Log.h"
 #include "../IO/Log.h"
+#include "../IO/MemoryBuffer.h"
 #include "../Resource/JSONFile.h"
 #include "../Resource/JSONFile.h"
 #include "../Resource/ResourceCache.h"
 #include "../Resource/ResourceCache.h"
 
 
@@ -230,4 +231,13 @@ bool JSONFile::Save(Serializer& dest, const String& indendation) const
     return dest.Write(buffer.GetString(), size) == size;
     return dest.Write(buffer.GetString(), size) == size;
 }
 }
 
 
+bool JSONFile::FromString(const String & source)
+{
+    if (source.Empty())
+        return false;
+
+    MemoryBuffer buffer(source.CString(), source.Length());
+    return Load(buffer);
+}
+
 }
 }

+ 3 - 0
Source/Urho3D/Resource/JSONFile.h

@@ -47,6 +47,9 @@ public:
     virtual bool Save(Serializer& dest) const;
     virtual bool Save(Serializer& dest) const;
     /// Save resource with user-defined indentation, only the first character (if any) of the string is used and the length of the string defines the character count. Return true if successful.
     /// Save resource with user-defined indentation, only the first character (if any) of the string is used and the length of the string defines the character count. Return true if successful.
     bool Save(Serializer& dest, const String& indendation) const;
     bool Save(Serializer& dest, const String& indendation) const;
+    
+    /// Deserialize from a string. Return true if successful.
+    bool FromString(const String& source);
 
 
     /// Return root value.
     /// Return root value.
     JSONValue& GetRoot() { return root_; }
     JSONValue& GetRoot() { return root_; }

+ 7 - 4
Source/Urho3D/UI/ScrollBar.cpp

@@ -40,7 +40,7 @@ extern const char* orientations[];
 extern const char* UI_CATEGORY;
 extern const char* UI_CATEGORY;
 
 
 ScrollBar::ScrollBar(Context* context) :
 ScrollBar::ScrollBar(Context* context) :
-    UIElement(context),
+    BorderImage(context),
     scrollStep_(DEFAULT_SCROLL_STEP),
     scrollStep_(DEFAULT_SCROLL_STEP),
     stepFactor_(1.0f),
     stepFactor_(1.0f),
     leftRect_(IntRect::ZERO),
     leftRect_(IntRect::ZERO),
@@ -62,6 +62,9 @@ ScrollBar::ScrollBar(Context* context) :
     forwardButton_->SetRepeat(DEFAULT_REPEAT_DELAY, DEFAULT_REPEAT_RATE);
     forwardButton_->SetRepeat(DEFAULT_REPEAT_DELAY, DEFAULT_REPEAT_RATE);
     forwardButton_->SetFocusMode(FM_NOTFOCUSABLE);
     forwardButton_->SetFocusMode(FM_NOTFOCUSABLE);
 
 
+    // For backward compatibility
+    SetColor(Color(0.0f, 0.0f, 0.0f, 0.0f));
+
     SubscribeToEvent(backButton_, E_PRESSED, URHO3D_HANDLER(ScrollBar, HandleBackButtonPressed));
     SubscribeToEvent(backButton_, E_PRESSED, URHO3D_HANDLER(ScrollBar, HandleBackButtonPressed));
     SubscribeToEvent(forwardButton_, E_PRESSED, URHO3D_HANDLER(ScrollBar, HandleForwardButtonPressed));
     SubscribeToEvent(forwardButton_, E_PRESSED, URHO3D_HANDLER(ScrollBar, HandleForwardButtonPressed));
     SubscribeToEvent(slider_, E_SLIDERCHANGED, URHO3D_HANDLER(ScrollBar, HandleSliderChanged));
     SubscribeToEvent(slider_, E_SLIDERCHANGED, URHO3D_HANDLER(ScrollBar, HandleSliderChanged));
@@ -79,7 +82,7 @@ void ScrollBar::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<ScrollBar>(UI_CATEGORY);
     context->RegisterFactory<ScrollBar>(UI_CATEGORY);
 
 
-    URHO3D_COPY_BASE_ATTRIBUTES(UIElement);
+    URHO3D_COPY_BASE_ATTRIBUTES(BorderImage);
     URHO3D_UPDATE_ATTRIBUTE_DEFAULT_VALUE("Is Enabled", true);
     URHO3D_UPDATE_ATTRIBUTE_DEFAULT_VALUE("Is Enabled", true);
     URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Orientation", GetOrientation, SetOrientation, Orientation, orientations, O_HORIZONTAL, AM_FILE);
     URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Orientation", GetOrientation, SetOrientation, Orientation, orientations, O_HORIZONTAL, AM_FILE);
     URHO3D_ACCESSOR_ATTRIBUTE("Range", GetRange, SetRange, float, 1.0f, AM_FILE);
     URHO3D_ACCESSOR_ATTRIBUTE("Range", GetRange, SetRange, float, 1.0f, AM_FILE);
@@ -94,7 +97,7 @@ void ScrollBar::RegisterObject(Context* context)
 
 
 void ScrollBar::ApplyAttributes()
 void ScrollBar::ApplyAttributes()
 {
 {
-    UIElement::ApplyAttributes();
+    BorderImage::ApplyAttributes();
 
 
     // Reapply orientation to the button images
     // Reapply orientation to the button images
     if (slider_->GetOrientation() == O_HORIZONTAL)
     if (slider_->GetOrientation() == O_HORIZONTAL)
@@ -219,7 +222,7 @@ float ScrollBar::GetEffectiveScrollStep() const
 
 
 bool ScrollBar::FilterImplicitAttributes(XMLElement& dest) const
 bool ScrollBar::FilterImplicitAttributes(XMLElement& dest) const
 {
 {
-    if (!UIElement::FilterImplicitAttributes(dest))
+    if (!BorderImage::FilterImplicitAttributes(dest))
         return false;
         return false;
 
 
     if (!RemoveChildXML(dest, "Layout Mode"))
     if (!RemoveChildXML(dest, "Layout Mode"))

+ 2 - 2
Source/Urho3D/UI/ScrollBar.h

@@ -31,9 +31,9 @@ class Button;
 class Slider;
 class Slider;
 
 
 /// Scroll bar %UI element with forward and back buttons.
 /// Scroll bar %UI element with forward and back buttons.
-class URHO3D_API ScrollBar : public UIElement
+class URHO3D_API ScrollBar : public BorderImage
 {
 {
-    URHO3D_OBJECT(ScrollBar, UIElement);
+    URHO3D_OBJECT(ScrollBar, BorderImage);
 
 
 public:
 public:
     /// Construct.
     /// Construct.

+ 2 - 2
Source/Urho3D/UI/Sprite.cpp

@@ -97,14 +97,14 @@ const IntVector2& Sprite::GetScreenPosition() const
 
 
 IntVector2 Sprite::ScreenToElement(const IntVector2& screenPosition)
 IntVector2 Sprite::ScreenToElement(const IntVector2& screenPosition)
 {
 {
-    Vector3 floatPos(screenPosition.x_, screenPosition.y_, 0.0f);
+    Vector3 floatPos((float)screenPosition.x_, (float)screenPosition.y_, 0.0f);
     Vector3 transformedPos = GetTransform().Inverse() * floatPos;
     Vector3 transformedPos = GetTransform().Inverse() * floatPos;
     return IntVector2((int)transformedPos.x_, (int)transformedPos.y_);
     return IntVector2((int)transformedPos.x_, (int)transformedPos.y_);
 }
 }
 
 
 IntVector2 Sprite::ElementToScreen(const IntVector2& position)
 IntVector2 Sprite::ElementToScreen(const IntVector2& position)
 {
 {
-    Vector3 floatPos(position.x_, position.y_, 0.0f);
+    Vector3 floatPos((float)position.x_, (float)position.y_, 0.0f);
     Vector3 transformedPos = GetTransform() * floatPos;
     Vector3 transformedPos = GetTransform() * floatPos;
     return IntVector2((int)transformedPos.x_, (int)transformedPos.y_);
     return IntVector2((int)transformedPos.x_, (int)transformedPos.y_);
 }
 }

+ 12 - 11
Source/Urho3D/UI/Text.cpp

@@ -207,29 +207,30 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData,
                 // Samples should be even or glyph may be redrawn in wrong x y pos making stroke corners rough
                 // Samples should be even or glyph may be redrawn in wrong x y pos making stroke corners rough
                 // Adding to thickness helps with thickness of 1 not having enought samples for this formula
                 // Adding to thickness helps with thickness of 1 not having enought samples for this formula
                 // or certain fonts with reflex corners requiring more glyph samples for a smooth stroke when large
                 // or certain fonts with reflex corners requiring more glyph samples for a smooth stroke when large
-                int samples = strokeThickness_ * strokeThickness_ + (strokeThickness_ % 2 == 0 ? 4 : 3);
+                int thickness = Clamp(strokeThickness_, 0, fontSize_);
+                int samples = thickness * thickness + (thickness % 2 == 0 ? 4 : 3);
                 float angle = 360.f / samples;
                 float angle = 360.f / samples;
+                float floatThickness = (float)thickness;
                 for (int i = 0; i < samples; ++i)
                 for (int i = 0; i < samples; ++i)
                 {
                 {
-                    float x = cos(angle * i * M_PI / 180.f) * strokeThickness_;
-                    float y = sin(angle * i * M_PI / 180.f) * strokeThickness_;
+                    float x = Cos(angle * i) * floatThickness;
+                    float y = Sin(angle * i) * floatThickness;
                     ConstructBatch(pageBatch, pageGlyphLocation, (int)x, (int)y, &effectColor_, effectDepthBias_);
                     ConstructBatch(pageBatch, pageGlyphLocation, (int)x, (int)y, &effectColor_, effectDepthBias_);
                 }
                 }
             }
             }
             else
             else
             {
             {
-                float offset = strokeThickness_ / 2.f;
-                offset = floor(offset + .5f);
+                int thickness = Clamp(strokeThickness_, 0, fontSize_);
                 int x, y;
                 int x, y;
-                for (x = -(int)offset; x <= (int)offset; ++x)
+                for (x = -thickness; x <= thickness; ++x)
                 {
                 {
-                    for (y = -(int)offset; y <= (int)offset; ++y)
+                    for (y = -thickness; y <= thickness; ++y)
                     {
                     {
                         // Don't draw glyphs that aren't on the edges
                         // Don't draw glyphs that aren't on the edges
-                        if (x > -(int)offset && x < (int)offset &&
-                            y > -(int)offset && y < (int)offset)
+                        if (x > -thickness && x < thickness &&
+                            y > -thickness && y < thickness)
                             continue;
                             continue;
-
+    
                         ConstructBatch(pageBatch, pageGlyphLocation, x, y, &effectColor_, effectDepthBias_);
                         ConstructBatch(pageBatch, pageGlyphLocation, x, y, &effectColor_, effectDepthBias_);
                     }
                     }
                 }
                 }
@@ -395,7 +396,7 @@ void Text::SetTextEffect(TextEffect textEffect)
     textEffect_ = textEffect;
     textEffect_ = textEffect;
 }
 }
 
 
-void Text::SetEffectShadowOffset(IntVector2 offset)
+void Text::SetEffectShadowOffset(const IntVector2& offset)
 {
 {
     shadowOffset_ = offset;
     shadowOffset_ = offset;
 }
 }

+ 2 - 2
Source/Urho3D/UI/Text.h

@@ -118,7 +118,7 @@ public:
     /// Set text effect.
     /// Set text effect.
     void SetTextEffect(TextEffect textEffect);
     void SetTextEffect(TextEffect textEffect);
     /// Set shadow offset.
     /// Set shadow offset.
-    void SetEffectShadowOffset(IntVector2 offset);
+    void SetEffectShadowOffset(const IntVector2& offset);
     /// Set stroke thickness.
     /// Set stroke thickness.
     void SetEffectStrokeThickness(int thickness);
     void SetEffectStrokeThickness(int thickness);
     /// Set stroke rounding. Corners of the font will be rounded off in the stroke so the stroke won't have corners.
     /// Set stroke rounding. Corners of the font will be rounded off in the stroke so the stroke won't have corners.
@@ -163,7 +163,7 @@ public:
     TextEffect GetTextEffect() const { return textEffect_; }
     TextEffect GetTextEffect() const { return textEffect_; }
 
 
     /// Return effect shadow offset.
     /// Return effect shadow offset.
-    IntVector2 GetEffectShadowOffset() const { return shadowOffset_; }
+    const IntVector2& GetEffectShadowOffset() const { return shadowOffset_; }
 
 
     /// Return effect stroke thickness.
     /// Return effect stroke thickness.
     int GetEffectStrokeThickness() const { return strokeThickness_; }
     int GetEffectStrokeThickness() const { return strokeThickness_; }

+ 43 - 6
Source/Urho3D/UI/Text3D.cpp

@@ -53,6 +53,7 @@ Text3D::Text3D(Context* context) :
     vertexBuffer_(new VertexBuffer(context_)),
     vertexBuffer_(new VertexBuffer(context_)),
     customWorldTransform_(Matrix3x4::IDENTITY),
     customWorldTransform_(Matrix3x4::IDENTITY),
     faceCameraMode_(FC_NONE),
     faceCameraMode_(FC_NONE),
+    fixedScreenSize_(false),
     textDirty_(true),
     textDirty_(true),
     geometryDirty_(true),
     geometryDirty_(true),
     usingSDFShader_(false),
     usingSDFShader_(false),
@@ -79,6 +80,7 @@ void Text3D::RegisterObject(Context* context)
     URHO3D_ATTRIBUTE("Row Spacing", float, text_.rowSpacing_, 1.0f, AM_DEFAULT);
     URHO3D_ATTRIBUTE("Row Spacing", float, text_.rowSpacing_, 1.0f, AM_DEFAULT);
     URHO3D_ATTRIBUTE("Word Wrap", bool, text_.wordWrap_, false, AM_DEFAULT);
     URHO3D_ATTRIBUTE("Word Wrap", bool, text_.wordWrap_, false, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Can Be Occluded", IsOccludee, SetOccludee, bool, true, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Can Be Occluded", IsOccludee, SetOccludee, bool, true, AM_DEFAULT);
+    URHO3D_ACCESSOR_ATTRIBUTE("Fixed Screen Size", IsFixedScreenSize, SetFixedScreenSize, bool, false, AM_DEFAULT);
     URHO3D_ENUM_ATTRIBUTE("Face Camera Mode", faceCameraMode_, faceCameraModeNames, FC_NONE, AM_DEFAULT);
     URHO3D_ENUM_ATTRIBUTE("Face Camera Mode", faceCameraMode_, faceCameraModeNames, FC_NONE, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Draw Distance", GetDrawDistance, SetDrawDistance, float, 0.0f, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Draw Distance", GetDrawDistance, SetDrawDistance, float, 0.0f, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Width", GetWidth, SetWidth, int, 0, AM_DEFAULT);
     URHO3D_ACCESSOR_ATTRIBUTE("Width", GetWidth, SetWidth, int, 0, AM_DEFAULT);
@@ -113,11 +115,28 @@ void Text3D::UpdateBatches(const FrameInfo& frame)
 {
 {
     distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());
     distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());
 
 
-    if (faceCameraMode_ != FC_NONE)
+    if (faceCameraMode_ != FC_NONE || fixedScreenSize_)
     {
     {
         Vector3 worldPosition = node_->GetWorldPosition();
         Vector3 worldPosition = node_->GetWorldPosition();
+        Vector3 worldScale = node_->GetWorldScale();
+
+        if (fixedScreenSize_)
+        {
+            float textScaling = 2.0f / TEXT_SCALING / frame.viewSize_.y_;
+            float halfViewWorldSize = frame.camera_->GetHalfViewSize();
+
+            if (!frame.camera_->IsOrthographic())
+            {
+                Matrix4 viewProj(frame.camera_->GetProjection(false) * frame.camera_->GetView());
+                Vector4 projPos(viewProj * Vector4(worldPosition, 1.0f));
+                worldScale *= textScaling * halfViewWorldSize * projPos.w_;
+            }
+            else
+                worldScale *= textScaling * halfViewWorldSize;
+        }
+
         customWorldTransform_ = Matrix3x4(worldPosition, frame.camera_->GetFaceCameraRotation(
         customWorldTransform_ = Matrix3x4(worldPosition, frame.camera_->GetFaceCameraRotation(
-            worldPosition, node_->GetWorldRotation(), faceCameraMode_), node_->GetWorldScale());
+            worldPosition, node_->GetWorldRotation(), faceCameraMode_), worldScale);
         worldBoundingBoxDirty_ = true;
         worldBoundingBoxDirty_ = true;
     }
     }
 
 
@@ -267,7 +286,7 @@ void Text3D::SetTextEffect(TextEffect textEffect)
     UpdateTextMaterials(true);
     UpdateTextMaterials(true);
 }
 }
 
 
-void Text3D::SetEffectShadowOffset(IntVector2 offset)
+void Text3D::SetEffectShadowOffset(const IntVector2& offset)
 {
 {
     text_.SetEffectShadowOffset(offset);
     text_.SetEffectShadowOffset(offset);
 }
 }
@@ -343,6 +362,18 @@ void Text3D::SetOpacity(float opacity)
     }
     }
 }
 }
 
 
+void Text3D::SetFixedScreenSize(bool enable)
+{
+    if (enable != fixedScreenSize_)
+    {
+        fixedScreenSize_ = enable;
+
+        // Bounding box must be recalculated
+        OnMarkedDirty(node_);
+        MarkNetworkUpdate();
+    }
+}
+
 void Text3D::SetFaceCameraMode(FaceCameraMode mode)
 void Text3D::SetFaceCameraMode(FaceCameraMode mode)
 {
 {
     if (mode != faceCameraMode_)
     if (mode != faceCameraMode_)
@@ -351,6 +382,7 @@ void Text3D::SetFaceCameraMode(FaceCameraMode mode)
 
 
         // Bounding box must be recalculated
         // Bounding box must be recalculated
         OnMarkedDirty(node_);
         OnMarkedDirty(node_);
+        MarkNetworkUpdate();
     }
     }
 }
 }
 
 
@@ -404,7 +436,7 @@ TextEffect Text3D::GetTextEffect() const
     return text_.GetTextEffect();
     return text_.GetTextEffect();
 }
 }
 
 
-IntVector2 Text3D::GetEffectShadowOffset() const
+const IntVector2& Text3D::GetEffectShadowOffset() const
 {
 {
     return text_.GetEffectShadowOffset();
     return text_.GetEffectShadowOffset();
 }
 }
@@ -488,8 +520,13 @@ void Text3D::OnWorldBoundingBoxUpdate()
         UpdateTextBatches();
         UpdateTextBatches();
 
 
     // In face camera mode, use the last camera rotation to build the world bounding box
     // In face camera mode, use the last camera rotation to build the world bounding box
-    worldBoundingBox_ = boundingBox_.Transformed(faceCameraMode_ != FC_NONE ? Matrix3x4(node_->GetWorldPosition(),
-        customWorldTransform_.Rotation(), node_->GetWorldScale()) : node_->GetWorldTransform());
+    if (faceCameraMode_ != FC_NONE || fixedScreenSize_)
+    {
+        worldBoundingBox_ = boundingBox_.Transformed(Matrix3x4(node_->GetWorldPosition(),
+            customWorldTransform_.Rotation(), customWorldTransform_.Scale()));
+    }
+    else
+        worldBoundingBox_ = boundingBox_.Transformed(node_->GetWorldTransform());
 }
 }
 
 
 void Text3D::MarkTextDirty()
 void Text3D::MarkTextDirty()

+ 11 - 8
Source/Urho3D/UI/Text3D.h

@@ -77,7 +77,7 @@ public:
     /// Set text effect.
     /// Set text effect.
     void SetTextEffect(TextEffect textEffect);
     void SetTextEffect(TextEffect textEffect);
     /// Set shadow offset.
     /// Set shadow offset.
-    void SetEffectShadowOffset(IntVector2 offset);
+    void SetEffectShadowOffset(const IntVector2& offset);
     /// Set stroke thickness.
     /// Set stroke thickness.
     void SetEffectStrokeThickness(int thickness);
     void SetEffectStrokeThickness(int thickness);
     /// Set stroke rounding. Corners of the font will be rounded off in the stroke so the stroke won't have corners.
     /// Set stroke rounding. Corners of the font will be rounded off in the stroke so the stroke won't have corners.
@@ -94,15 +94,17 @@ public:
     void SetColor(Corner corner, const Color& color);
     void SetColor(Corner corner, const Color& color);
     /// Set opacity.
     /// Set opacity.
     void SetOpacity(float opacity);
     void SetOpacity(float opacity);
+    /// Set whether text has fixed size on screen (pixel-perfect) regardless of distance to camera. Works best when combined with face camera rotation. Default false.
+    void SetFixedScreenSize(bool enable);
     /// Set how the text should rotate in relation to the camera. Default is to not rotate (FC_NONE.)
     /// Set how the text should rotate in relation to the camera. Default is to not rotate (FC_NONE.)
     void SetFaceCameraMode(FaceCameraMode mode);
     void SetFaceCameraMode(FaceCameraMode mode);
 
 
     /// Return font.
     /// Return font.
     Font* GetFont() const;
     Font* GetFont() const;
-    /// Return material.
-    Material* GetMaterial() const;
     /// Return font size.
     /// Return font size.
     int GetFontSize() const;
     int GetFontSize() const;
+    /// Return material.
+    Material* GetMaterial() const;
     /// Return text.
     /// Return text.
     const String& GetText() const;
     const String& GetText() const;
     /// Return row alignment.
     /// Return row alignment.
@@ -118,7 +120,7 @@ public:
     /// Return text effect.
     /// Return text effect.
     TextEffect GetTextEffect() const;
     TextEffect GetTextEffect() const;
     /// Return effect shadow offset.
     /// Return effect shadow offset.
-    IntVector2 GetEffectShadowOffset() const;
+    const IntVector2& GetEffectShadowOffset() const;
     /// Return effect stroke thickness.
     /// Return effect stroke thickness.
     int GetEffectStrokeThickness() const;
     int GetEffectStrokeThickness() const;
     /// Return effect round stroke.
     /// Return effect round stroke.
@@ -145,7 +147,8 @@ public:
     const Color& GetColor(Corner corner) const;
     const Color& GetColor(Corner corner) const;
     /// Return opacity.
     /// Return opacity.
     float GetOpacity() const;
     float GetOpacity() const;
-
+    /// Return whether text has fixed screen size.
+    bool IsFixedScreenSize() const { return fixedScreenSize_; }
     /// Return how the text rotates in relation to the camera.
     /// Return how the text rotates in relation to the camera.
     FaceCameraMode GetFaceCameraMode() const { return faceCameraMode_; }
     FaceCameraMode GetFaceCameraMode() const { return faceCameraMode_; }
 
 
@@ -166,15 +169,13 @@ protected:
     virtual void OnNodeSet(Node* node);
     virtual void OnNodeSet(Node* node);
     /// Recalculate the world-space bounding box.
     /// Recalculate the world-space bounding box.
     virtual void OnWorldBoundingBoxUpdate();
     virtual void OnWorldBoundingBoxUpdate();
-
-private:
     /// Mark text & geometry dirty.
     /// Mark text & geometry dirty.
     void MarkTextDirty();
     void MarkTextDirty();
     /// Update text %UI batches.
     /// Update text %UI batches.
     void UpdateTextBatches();
     void UpdateTextBatches();
     /// Create materials for text rendering. May only be called from the main thread. Text %UI batches must be up-to-date.
     /// Create materials for text rendering. May only be called from the main thread. Text %UI batches must be up-to-date.
     void UpdateTextMaterials(bool forceUpdate = false);
     void UpdateTextMaterials(bool forceUpdate = false);
-
+    
     /// Internally used text element.
     /// Internally used text element.
     Text text_;
     Text text_;
     /// Geometries.
     /// Geometries.
@@ -191,6 +192,8 @@ private:
     Matrix3x4 customWorldTransform_;
     Matrix3x4 customWorldTransform_;
     /// Text rotation mode in relation to the camera.
     /// Text rotation mode in relation to the camera.
     FaceCameraMode faceCameraMode_;
     FaceCameraMode faceCameraMode_;
+    /// Fixed screen size flag.
+    bool fixedScreenSize_;
     /// Text needs update flag.
     /// Text needs update flag.
     bool textDirty_;
     bool textDirty_;
     /// Geometry dirty flag.
     /// Geometry dirty flag.

+ 93 - 0
bin/Data/LuaScripts/43_HttpRequestDemo.lua

@@ -0,0 +1,93 @@
+-- Http request example.
+-- This example demonstrates:
+--     - How to use Http request API
+
+require "LuaScripts/Utilities/Sample"
+
+local message = ""
+local text = nil
+local httpRequest = nil
+
+function Start()
+    -- Execute the common startup for samples
+    SampleStart()
+
+    -- Create the user interface
+    CreateUI()
+
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
+    -- Subscribe to basic events such as update
+    SubscribeToEvents()
+end
+
+function CreateUI()
+    -- Construct new Text object
+    text = Text:new()
+
+    -- Set font and text color
+    text:SetFont(cache:GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15)
+    text.color = Color(1.0, 1.0, 0.0)
+
+    -- Align Text center-screen
+    text.horizontalAlignment = HA_CENTER
+    text.verticalAlignment = VA_CENTER
+
+    -- Add Text instance to the UI root element
+    ui.root:AddChild(text)
+end
+
+function SubscribeToEvents()
+    -- Subscribe HandleUpdate() function for processing HTTP request
+    SubscribeToEvent("Update", "HandleUpdate")
+end
+
+function HandleUpdate(eventType, eventData)
+    -- Create HTTP request
+    if httpRequest == nil then
+        httpRequest = network:MakeHttpRequest("http://httpbin.org/ip")
+    else
+        -- Initializing HTTP request
+        if httpRequest.state == HTTP_INITIALIZING then
+            return
+        -- An error has occured
+        elseif httpRequest.state == HTTP_ERROR then
+            text.text = "An error has occured."
+            UnsubscribeFromEvent("Update")
+        -- Get message data
+        else
+            if httpRequest.availableSize > 0 then
+                message = message .. httpRequest:ReadLine()
+            else
+                text.text = "Processing..."
+
+                local json = JSONFile:new()
+                json:FromString(message)
+
+                local val = json:GetRoot():Get("origin")
+
+                if val.isNull then
+                    text.text = "Invalid string."
+                else
+                    text.text =  "Your IP is: " .. val:GetString()
+                end
+
+                json:delete()
+                httpRequest:delete()
+
+                UnsubscribeFromEvent("Update")
+            end       
+        end
+    end
+end
+
+-- Create XML patch instructions for screen joystick layout specific to this sample app
+function GetScreenJoystickPatchString()
+    return
+        "<patch>" ..
+        "    <add sel=\"/element/element[./attribute[@name='Name' and @value='Hat0']]\">" ..
+        "        <attribute name=\"Is Visible\" value=\"false\" />" ..
+        "    </add>" ..
+        "</patch>"
+end

+ 97 - 0
bin/Data/Scripts/43_HttpRequestDemo.as

@@ -0,0 +1,97 @@
+// Http request example.
+// This example demonstrates:
+//     - How to use Http request API
+
+#include "Scripts/Utilities/Sample.as"
+
+String message;
+Text@ text;
+HttpRequest@ httpRequest;
+
+void Start()
+{
+    // Execute the common startup for samples
+    SampleStart();
+
+    // Create the user interface
+    CreateUI();
+
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE);
+
+    // Subscribe to basic events such as update
+    SubscribeToEvents();
+}
+
+void CreateUI()
+{
+    // Construct new Text object
+    text = Text();
+
+    // Set font and text color
+    text.SetFont(cache.GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15);
+    text.color = Color(1.0f, 1.0f, 0.0f);
+
+    // Align Text center-screen
+    text.horizontalAlignment = HA_CENTER;
+    text.verticalAlignment = VA_CENTER;
+
+    // Add Text instance to the UI root element
+    ui.root.AddChild(text);
+}
+
+void SubscribeToEvents()
+{
+    // Subscribe HandleUpdate() function for processing HTTP request
+    SubscribeToEvent("Update", "HandleUpdate");
+}
+
+void HandleUpdate(StringHash eventType, VariantMap& eventData)
+{
+    // Create HTTP request
+    if (httpRequest is null)
+        httpRequest = network.MakeHttpRequest("http://httpbin.org/ip");
+    else
+    {
+        // Initializing HTTP request
+        if (httpRequest.state == HTTP_INITIALIZING)
+            return;
+        // An error has occured
+        else if (httpRequest.state == HTTP_ERROR)
+        {
+            text.text = "An error has occured.";
+            UnsubscribeFromEvent("Update");
+        }
+        // Get message data
+        else
+        {
+            if (httpRequest.availableSize > 0)
+                message += httpRequest.ReadLine();
+            else
+            {
+                text.text = "Processing...";
+
+                JSONFile@ json = JSONFile();
+                json.FromString(message);
+
+                JSONValue val = json.GetRoot().Get("origin");
+
+                if (val.isNull)
+                    text.text = "Invalid string.";
+                else
+                    text.text =  "Your IP is: " + val.GetString();
+
+                UnsubscribeFromEvent("Update");
+            }
+        }
+    }
+}
+
+// Create XML patch instructions for screen joystick layout specific to this sample app
+String patchInstructions =
+        "<patch>" +
+        "    <add sel=\"/element/element[./attribute[@name='Name' and @value='Hat0']]\">" +
+        "        <attribute name=\"Is Visible\" value=\"false\" />" +
+        "    </add>" +
+        "</patch>";
+

+ 28 - 0
bin/Data/Scripts/Editor/EditorImport.as

@@ -34,6 +34,34 @@ int ExecuteAssetImporter(Array<String>@ args)
     return fileSystem.SystemRun(assetImporterPath, args);
     return fileSystem.SystemRun(assetImporterPath, args);
 }
 }
 
 
+void ImportAnimation(const String&in fileName)
+{
+  if (fileName.empty)
+      return;
+
+  ui.cursor.shape = CS_BUSY;
+
+  String modelName = "Models/" + GetFileName(fileName) + ".ani";
+  String outFileName = sceneResourcePath + modelName;
+  fileSystem.CreateDir(sceneResourcePath + "Models");
+
+  Array<String> args;
+  args.Push("anim");
+  args.Push("\"" + fileName + "\"");
+  args.Push("\"" + outFileName + "\"");
+  args.Push("-p \"" + sceneResourcePath + "\"");
+  Array<String> options = importOptions.Trimmed().Split(' ');
+  for (uint i = 0; i < options.length; ++i)
+      args.Push(options[i]);
+
+  if (ExecuteAssetImporter(args) == 0)
+  {
+
+  }
+  else
+      log.Error("Failed to execute AssetImporter to import model");
+}
+
 void ImportModel(const String&in fileName)
 void ImportModel(const String&in fileName)
 {
 {
     if (fileName.empty)
     if (fileName.empty)

+ 24 - 1
bin/Data/Scripts/Editor/EditorParticleEffect.as

@@ -128,8 +128,9 @@ void CreateParticleEffectEditor()
     SubscribeToEvent(particleEffectWindow.GetChild("Scaled", true), "Toggled", "EditParticleEffectScaled");
     SubscribeToEvent(particleEffectWindow.GetChild("Scaled", true), "Toggled", "EditParticleEffectScaled");
     SubscribeToEvent(particleEffectWindow.GetChild("Sorted", true), "Toggled", "EditParticleEffectSorted");
     SubscribeToEvent(particleEffectWindow.GetChild("Sorted", true), "Toggled", "EditParticleEffectSorted");
     SubscribeToEvent(particleEffectWindow.GetChild("Relative", true), "Toggled", "EditParticleEffectRelative");
     SubscribeToEvent(particleEffectWindow.GetChild("Relative", true), "Toggled", "EditParticleEffectRelative");
+    SubscribeToEvent(particleEffectWindow.GetChild("FixedScreenSize", true), "Toggled", "EditParticleEffectFixedScreenSize");
     SubscribeToEvent(particleEffectWindow.GetChild("FaceCameraMode", true), "ItemSelected", "EditParticleEffectFaceCameraMode");
     SubscribeToEvent(particleEffectWindow.GetChild("FaceCameraMode", true), "ItemSelected", "EditParticleEffectFaceCameraMode");
-    
+
     SubscribeToEvent(particleEffectWindow.GetChild("ResetViewport", true), "Released", "ParticleEffectResetViewport");
     SubscribeToEvent(particleEffectWindow.GetChild("ResetViewport", true), "Released", "ParticleEffectResetViewport");
     SubscribeToEvent(particleEffectWindow.GetChild("ShowGrid", true), "Toggled", "ParticleEffectShowGrid");
     SubscribeToEvent(particleEffectWindow.GetChild("ShowGrid", true), "Toggled", "ParticleEffectShowGrid");
 }
 }
@@ -866,6 +867,27 @@ void EditParticleEffectRelative(StringHash eventType, VariantMap& eventData)
     EndParticleEffectEdit();
     EndParticleEffectEdit();
 }
 }
 
 
+void EditParticleEffectFixedScreenSize(StringHash eventType, VariantMap& eventData)
+{
+    if (inParticleEffectRefresh)
+        return;
+
+    if (editParticleEffect is null)
+        return;
+
+    if (particleEffectEmitter is null)
+        return;
+
+    BeginParticleEffectEdit();
+
+    CheckBox@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.fixedScreenSize = element.checked;
+    particleEffectEmitter.ApplyEffect();
+
+    EndParticleEffectEdit();
+}
+
 bool ToggleParticleEffectEditor()
 bool ToggleParticleEffectEditor()
 {
 {
     if (particleEffectWindow.visible == false)
     if (particleEffectWindow.visible == false)
@@ -1480,6 +1502,7 @@ void RefreshParticleEffectBasicAttributes()
     cast<CheckBox>(particleEffectWindow.GetChild("Scaled", true)).checked = editParticleEffect.scaled;
     cast<CheckBox>(particleEffectWindow.GetChild("Scaled", true)).checked = editParticleEffect.scaled;
     cast<CheckBox>(particleEffectWindow.GetChild("Sorted", true)).checked = editParticleEffect.sorted;
     cast<CheckBox>(particleEffectWindow.GetChild("Sorted", true)).checked = editParticleEffect.sorted;
     cast<CheckBox>(particleEffectWindow.GetChild("Relative", true)).checked = editParticleEffect.relative;
     cast<CheckBox>(particleEffectWindow.GetChild("Relative", true)).checked = editParticleEffect.relative;
+    cast<CheckBox>(particleEffectWindow.GetChild("FixedScreenSize", true)).checked = editParticleEffect.fixedScreenSize;
 }
 }
 
 
 void RefreshParticleEffectMaterial()
 void RefreshParticleEffectMaterial()

+ 155 - 144
bin/Data/Scripts/Editor/EditorUI.as

@@ -98,7 +98,7 @@ void CreateUI()
     SubscribeToEvent("ScreenMode", "ResizeUI");
     SubscribeToEvent("ScreenMode", "ResizeUI");
     SubscribeToEvent("MenuSelected", "HandleMenuSelected");
     SubscribeToEvent("MenuSelected", "HandleMenuSelected");
     SubscribeToEvent("ChangeLanguage", "HandleChangeLanguage");
     SubscribeToEvent("ChangeLanguage", "HandleChangeLanguage");
-    
+
     SubscribeToEvent("WheelChangeColor", "HandleWheelChangeColor");
     SubscribeToEvent("WheelChangeColor", "HandleWheelChangeColor");
     SubscribeToEvent("WheelSelectColor", "HandleWheelSelectColor");
     SubscribeToEvent("WheelSelectColor", "HandleWheelSelectColor");
     SubscribeToEvent("WheelDiscardColor", "HandleWheelDiscardColor");
     SubscribeToEvent("WheelDiscardColor", "HandleWheelDiscardColor");
@@ -125,7 +125,7 @@ void ResizeUI()
 
 
     // Relayout root UI element
     // Relayout root UI element
     editorUIElement.SetSize(graphics.width, graphics.height);
     editorUIElement.SetSize(graphics.width, graphics.height);
-    
+
     // Set new viewport area and reset the viewport layout
     // Set new viewport area and reset the viewport layout
     viewportArea = IntRect(0, 0, graphics.width, graphics.height);
     viewportArea = IntRect(0, 0, graphics.width, graphics.height);
     SetViewportMode(viewportMode);
     SetViewportMode(viewportMode);
@@ -172,7 +172,7 @@ void HandleQuickSearchFinish(StringHash eventType, VariantMap& eventData)
     Menu@ menu = quickMenu.GetChild("ResultsMenu", true);
     Menu@ menu = quickMenu.GetChild("ResultsMenu", true);
     if (menu is null)
     if (menu is null)
         return;
         return;
-        
+
     String query = eventData["Text"].GetString();
     String query = eventData["Text"].GetString();
     if (query.length <= 0)
     if (query.length <= 0)
         return;
         return;
@@ -279,7 +279,7 @@ void CreateQuickMenu()
     quickMenu.enabled = false;
     quickMenu.enabled = false;
     quickMenu.visible = false;
     quickMenu.visible = false;
     quickMenu.opacity = uiMaxOpacity;
     quickMenu.opacity = uiMaxOpacity;
-    
+
     // Handle a dummy search in the quick menu to finalize its initial size to empty
     // Handle a dummy search in the quick menu to finalize its initial size to empty
     PerformQuickMenuSearch("");
     PerformQuickMenuSearch("");
 
 
@@ -338,6 +338,7 @@ void CreateMenuBar()
         CreateChildDivider(popup);
         CreateChildDivider(popup);
         popup.AddChild(CreateMenuItem("Import model...", @PickFile));
         popup.AddChild(CreateMenuItem("Import model...", @PickFile));
         popup.AddChild(CreateMenuItem("Import scene...", @PickFile));
         popup.AddChild(CreateMenuItem("Import scene...", @PickFile));
+        popup.AddChild(CreateMenuItem("Import animation...", @PickFile));
         CreateChildDivider(popup);
         CreateChildDivider(popup);
         popup.AddChild(CreateMenuItem("Export scene to OBJ...", @PickFile));
         popup.AddChild(CreateMenuItem("Export scene to OBJ...", @PickFile));
         popup.AddChild(CreateMenuItem("Export selected to OBJ...", @PickFile));
         popup.AddChild(CreateMenuItem("Export selected to OBJ...", @PickFile));
@@ -357,28 +358,28 @@ void CreateMenuBar()
         popup.AddChild(CreateMenuItem("Redo", @Redo, 'Y', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Redo", @Redo, 'Y', QUAL_CTRL));
         CreateChildDivider(popup);
         CreateChildDivider(popup);
         popup.AddChild(CreateMenuItem("Cut", @Cut, 'X', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Cut", @Cut, 'X', QUAL_CTRL));
-        
+
         if (hotKeyMode == HOTKEYS_MODE_STANDARD)
         if (hotKeyMode == HOTKEYS_MODE_STANDARD)
             popup.AddChild(CreateMenuItem("Duplicate", @Duplicate, 'D', QUAL_CTRL));
             popup.AddChild(CreateMenuItem("Duplicate", @Duplicate, 'D', QUAL_CTRL));
         else if (hotKeyMode == HOTKEYS_MODE_BLENDER)
         else if (hotKeyMode == HOTKEYS_MODE_BLENDER)
             popup.AddChild(CreateMenuItem("Duplicate", @Duplicate, 'D', QUAL_SHIFT));
             popup.AddChild(CreateMenuItem("Duplicate", @Duplicate, 'D', QUAL_SHIFT));
-        
+
         popup.AddChild(CreateMenuItem("Copy", @Copy, 'C', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Copy", @Copy, 'C', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Paste", @Paste, 'V', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Paste", @Paste, 'V', QUAL_CTRL));
-        
+
         if (hotKeyMode == HOTKEYS_MODE_STANDARD)
         if (hotKeyMode == HOTKEYS_MODE_STANDARD)
             popup.AddChild(CreateMenuItem("Delete", @Delete, KEY_DELETE, QUAL_ANY));
             popup.AddChild(CreateMenuItem("Delete", @Delete, KEY_DELETE, QUAL_ANY));
         else if (hotKeyMode == HOTKEYS_MODE_BLENDER)
         else if (hotKeyMode == HOTKEYS_MODE_BLENDER)
             popup.AddChild(CreateMenuItem("Delete", @BlenderModeDelete, 'X', QUAL_ANY));
             popup.AddChild(CreateMenuItem("Delete", @BlenderModeDelete, 'X', QUAL_ANY));
-        
+
         popup.AddChild(CreateMenuItem("Select all", @SelectAll, 'A', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Select all", @SelectAll, 'A', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Deselect all", @DeselectAll, 'A', QUAL_SHIFT | QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Deselect all", @DeselectAll, 'A', QUAL_SHIFT | QUAL_CTRL));
-        
+
         CreateChildDivider(popup);
         CreateChildDivider(popup);
         popup.AddChild(CreateMenuItem("Reset to default", @ResetToDefault));
         popup.AddChild(CreateMenuItem("Reset to default", @ResetToDefault));
         CreateChildDivider(popup);
         CreateChildDivider(popup);
-        
-        if (hotKeyMode == HOTKEYS_MODE_STANDARD)    
+
+        if (hotKeyMode == HOTKEYS_MODE_STANDARD)
         {
         {
             popup.AddChild(CreateMenuItem("Reset position", @SceneResetPosition, '1' , QUAL_ALT));
             popup.AddChild(CreateMenuItem("Reset position", @SceneResetPosition, '1' , QUAL_ALT));
             popup.AddChild(CreateMenuItem("Reset rotation", @SceneResetRotation, '2' , QUAL_ALT));
             popup.AddChild(CreateMenuItem("Reset rotation", @SceneResetRotation, '2' , QUAL_ALT));
@@ -390,7 +391,7 @@ void CreateMenuBar()
             popup.AddChild(CreateMenuItem("Reset position", @SceneResetPosition, 'G' , QUAL_ALT));
             popup.AddChild(CreateMenuItem("Reset position", @SceneResetPosition, 'G' , QUAL_ALT));
             popup.AddChild(CreateMenuItem("Reset rotation", @SceneResetRotation, 'R', QUAL_ALT));
             popup.AddChild(CreateMenuItem("Reset rotation", @SceneResetRotation, 'R', QUAL_ALT));
             popup.AddChild(CreateMenuItem("Reset scale", @SceneResetScale, 'S', QUAL_ALT));
             popup.AddChild(CreateMenuItem("Reset scale", @SceneResetScale, 'S', QUAL_ALT));
-            popup.AddChild(CreateMenuItem("Reset transform", @SceneResetTransform, 'Q' , QUAL_ALT));            
+            popup.AddChild(CreateMenuItem("Reset transform", @SceneResetTransform, 'Q' , QUAL_ALT));
         }
         }
 
 
         if (hotKeyMode == HOTKEYS_MODE_STANDARD)
         if (hotKeyMode == HOTKEYS_MODE_STANDARD)
@@ -415,13 +416,13 @@ void CreateMenuBar()
             popup.AddChild(CreateMenuItem("Parent to last", @NodesParentToLastSelected, 'P', QUAL_CTRL));
             popup.AddChild(CreateMenuItem("Parent to last", @NodesParentToLastSelected, 'P', QUAL_CTRL));
 
 
         CreateChildDivider(popup);
         CreateChildDivider(popup);
-        
+
         if (hotKeyMode == HOTKEYS_MODE_STANDARD)
         if (hotKeyMode == HOTKEYS_MODE_STANDARD)
             popup.AddChild(CreateMenuItem("Toggle update", @ToggleSceneUpdate, 'P', QUAL_CTRL));
             popup.AddChild(CreateMenuItem("Toggle update", @ToggleSceneUpdate, 'P', QUAL_CTRL));
         //else if (hotKeyMode == HOT_KEYS_MODE_BLENDER)
         //else if (hotKeyMode == HOT_KEYS_MODE_BLENDER)
         //    popup.AddChild(CreateMenuItem("Toggle update", @ToggleSceneUpdate, 'P', QUAL_CTRL));
         //    popup.AddChild(CreateMenuItem("Toggle update", @ToggleSceneUpdate, 'P', QUAL_CTRL));
-        
-        if (hotKeyMode == HOTKEYS_MODE_BLENDER) 
+
+        if (hotKeyMode == HOTKEYS_MODE_BLENDER)
         {
         {
              popup.AddChild(CreateMenuItem("Move to layer", @ShowLayerMover, 'M'));
              popup.AddChild(CreateMenuItem("Move to layer", @ShowLayerMover, 'M'));
              popup.AddChild(CreateMenuItem("Smart Duplicate", @SceneSmartDuplicateNode, 'D', QUAL_ALT));
              popup.AddChild(CreateMenuItem("Smart Duplicate", @SceneSmartDuplicateNode, 'D', QUAL_ALT));
@@ -431,7 +432,7 @@ void CreateMenuBar()
         popup.AddChild(CreateMenuItem("Show components icons", @ViewDebugIcons, 'I', QUAL_ALT));
         popup.AddChild(CreateMenuItem("Show components icons", @ViewDebugIcons, 'I', QUAL_ALT));
 
 
         CreateChildDivider(popup);
         CreateChildDivider(popup);
-        
+
         popup.AddChild(CreateMenuItem("Stop test animation", @StopTestAnimation));
         popup.AddChild(CreateMenuItem("Stop test animation", @StopTestAnimation));
         CreateChildDivider(popup);
         CreateChildDivider(popup);
         popup.AddChild(CreateMenuItem("Rebuild navigation data", @SceneRebuildNavigation));
         popup.AddChild(CreateMenuItem("Rebuild navigation data", @SceneRebuildNavigation));
@@ -639,6 +640,11 @@ bool PickFile()
         CreateFileSelector("Import model", "Import", "Cancel", uiImportPath, uiAllFilters, uiImportFilter);
         CreateFileSelector("Import model", "Import", "Cancel", uiImportPath, uiAllFilters, uiImportFilter);
         SubscribeToEvent(uiFileSelector, "FileSelected", "HandleImportModel");
         SubscribeToEvent(uiFileSelector, "FileSelected", "HandleImportModel");
     }
     }
+    else if (action == "Import animation...")
+    {
+        CreateFileSelector("Import animation", "Import", "Cancel", uiImportPath, uiAllFilters, uiImportFilter);
+        SubscribeToEvent(uiFileSelector, "FileSelected", "HandleImportAnimation");
+    }
     else if (action == "Import scene...")
     else if (action == "Import scene...")
     {
     {
         CreateFileSelector("Import scene", "Import", "Cancel", uiImportPath, uiAllFilters, uiImportFilter);
         CreateFileSelector("Import scene", "Import", "Cancel", uiImportPath, uiAllFilters, uiImportFilter);
@@ -657,41 +663,41 @@ bool PickFile()
             CreateFileSelector("Export selected to OBJ", "Save", "Cancel", uiExportPath, uiExportPathFilters, uiExportFilter);
             CreateFileSelector("Export selected to OBJ", "Save", "Cancel", uiExportPath, uiExportPathFilters, uiExportFilter);
             SubscribeToEvent(uiFileSelector, "FileSelected", "HandleExportSelectedOBJ");
             SubscribeToEvent(uiFileSelector, "FileSelected", "HandleExportSelectedOBJ");
         }
         }
-        
+
         Window@ window = uiFileSelector.window;
         Window@ window = uiFileSelector.window;
-        
+
             UIElement@ optionsGroup = UIElement();
             UIElement@ optionsGroup = UIElement();
             optionsGroup.maxHeight = 30;
             optionsGroup.maxHeight = 30;
             optionsGroup.layoutMode = LM_HORIZONTAL;
             optionsGroup.layoutMode = LM_HORIZONTAL;
             window.defaultStyle = uiStyle;
             window.defaultStyle = uiStyle;
             window.style = AUTO_STYLE;
             window.style = AUTO_STYLE;
-            
+
                 CheckBox@ checkRightHanded = CheckBox();
                 CheckBox@ checkRightHanded = CheckBox();
                 checkRightHanded.checked = objExportRightHanded_;
                 checkRightHanded.checked = objExportRightHanded_;
                 checkRightHanded.defaultStyle = uiStyle;
                 checkRightHanded.defaultStyle = uiStyle;
                 checkRightHanded.style = AUTO_STYLE;
                 checkRightHanded.style = AUTO_STYLE;
                 SubscribeToEvent(checkRightHanded, "Toggled", "HandleOBJRightHandedChanged");
                 SubscribeToEvent(checkRightHanded, "Toggled", "HandleOBJRightHandedChanged");
                 optionsGroup.AddChild(checkRightHanded);
                 optionsGroup.AddChild(checkRightHanded);
-                
+
                     Text@ lblRightHanded = Text();
                     Text@ lblRightHanded = Text();
                     lblRightHanded.defaultStyle = uiStyle;
                     lblRightHanded.defaultStyle = uiStyle;
                     lblRightHanded.style = AUTO_STYLE;
                     lblRightHanded.style = AUTO_STYLE;
                     lblRightHanded.text = "  Right handed";
                     lblRightHanded.text = "  Right handed";
                     optionsGroup.AddChild(lblRightHanded);
                     optionsGroup.AddChild(lblRightHanded);
-                
+
                 CheckBox@ checkZUp = CheckBox();
                 CheckBox@ checkZUp = CheckBox();
                 checkZUp.checked = objExportZUp_;
                 checkZUp.checked = objExportZUp_;
                 checkZUp.defaultStyle = uiStyle;
                 checkZUp.defaultStyle = uiStyle;
                 checkZUp.style = AUTO_STYLE;
                 checkZUp.style = AUTO_STYLE;
                 SubscribeToEvent(checkZUp, "Toggled", "HandleOBJZUpChanged");
                 SubscribeToEvent(checkZUp, "Toggled", "HandleOBJZUpChanged");
                 optionsGroup.AddChild(checkZUp);
                 optionsGroup.AddChild(checkZUp);
-                
+
                     Text@ lblZUp = Text();
                     Text@ lblZUp = Text();
                     lblZUp.defaultStyle = uiStyle;
                     lblZUp.defaultStyle = uiStyle;
                     lblZUp.style = AUTO_STYLE;
                     lblZUp.style = AUTO_STYLE;
                     lblZUp.text = " Z Axis Up";
                     lblZUp.text = " Z Axis Up";
                     optionsGroup.AddChild(lblZUp);
                     optionsGroup.AddChild(lblZUp);
-                
+
             window.AddChild(optionsGroup);
             window.AddChild(optionsGroup);
     }
     }
     else if (action == "Run script...")
     else if (action == "Run script...")
@@ -1193,6 +1199,11 @@ void HandleImportModel(StringHash eventType, VariantMap& eventData)
     CloseFileSelector(uiImportFilter, uiImportPath);
     CloseFileSelector(uiImportFilter, uiImportPath);
     ImportModel(ExtractFileName(eventData));
     ImportModel(ExtractFileName(eventData));
 }
 }
+void HandleImportAnimation(StringHash eventType, VariantMap& eventData)
+{
+    CloseFileSelector(uiImportFilter, uiImportPath);
+    ImportAnimation(ExtractFileName(eventData));
+}
 
 
 void HandleImportScene(StringHash eventType, VariantMap& eventData)
 void HandleImportScene(StringHash eventType, VariantMap& eventData)
 {
 {
@@ -1275,11 +1286,11 @@ void HandleUIElementDefaultStyle(StringHash eventType, VariantMap& eventData)
     SetUIElementDefaultStyle(ExtractFileName(eventData));
     SetUIElementDefaultStyle(ExtractFileName(eventData));
 }
 }
 
 
-void HandleHotKeysBlender( VariantMap& eventData) 
+void HandleHotKeysBlender( VariantMap& eventData)
 {
 {
     int key = eventData["Key"].GetInt();
     int key = eventData["Key"].GetInt();
     int viewDirection = eventData["Qualifiers"].GetInt() == QUAL_CTRL ? -1 : 1;
     int viewDirection = eventData["Qualifiers"].GetInt() == QUAL_CTRL ? -1 : 1;
-    
+
     if (key == KEY_ESC)
     if (key == KEY_ESC)
     {
     {
         if (uiHidden)
         if (uiHidden)
@@ -1323,13 +1334,13 @@ void HandleHotKeysBlender( VariantMap& eventData)
             fileSystem.CreateDir(screenshotDir);
             fileSystem.CreateDir(screenshotDir);
         screenshot.SavePNG(screenshotDir + "/Screenshot_" +
         screenshot.SavePNG(screenshotDir + "/Screenshot_" +
                 time.timeStamp.Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png");
                 time.timeStamp.Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png");
-    }   
+    }
     else if (key == KEY_KP_1 && ui.focusElement is null) // Front view
     else if (key == KEY_KP_1 && ui.focusElement is null) // Front view
     {
     {
         Vector3 center = Vector3(0,0,0);
         Vector3 center = Vector3(0,0,0);
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
             center = SelectedNodesCenterPoint();
             center = SelectedNodesCenterPoint();
-            
+
         Vector3 pos = cameraNode.worldPosition - center;
         Vector3 pos = cameraNode.worldPosition - center;
         cameraNode.worldPosition = center - Vector3(0.0, 0.0, pos.length * viewDirection);
         cameraNode.worldPosition = center - Vector3(0.0, 0.0, pos.length * viewDirection);
         cameraNode.direction = Vector3(0, 0, viewDirection);
         cameraNode.direction = Vector3(0, 0, viewDirection);
@@ -1341,7 +1352,7 @@ void HandleHotKeysBlender( VariantMap& eventData)
         Vector3 center = Vector3(0,0,0);
         Vector3 center = Vector3(0,0,0);
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
             center = SelectedNodesCenterPoint();
             center = SelectedNodesCenterPoint();
-            
+
         Vector3 pos = cameraNode.worldPosition - center;
         Vector3 pos = cameraNode.worldPosition - center;
         cameraNode.worldPosition = center - Vector3(pos.length * -viewDirection, 0.0, 0.0);
         cameraNode.worldPosition = center - Vector3(pos.length * -viewDirection, 0.0, 0.0);
         cameraNode.direction = Vector3(-viewDirection, 0, 0);
         cameraNode.direction = Vector3(-viewDirection, 0, 0);
@@ -1353,7 +1364,7 @@ void HandleHotKeysBlender( VariantMap& eventData)
         Vector3 center = Vector3(0,0,0);
         Vector3 center = Vector3(0,0,0);
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
             center = SelectedNodesCenterPoint();
             center = SelectedNodesCenterPoint();
-            
+
         Vector3 pos = cameraNode.worldPosition - center;
         Vector3 pos = cameraNode.worldPosition - center;
         cameraNode.worldPosition = center - Vector3(0.0, pos.length * -viewDirection, 0.0);
         cameraNode.worldPosition = center - Vector3(0.0, pos.length * -viewDirection, 0.0);
         cameraNode.direction = Vector3(0, -viewDirection, 0);
         cameraNode.direction = Vector3(0, -viewDirection, 0);
@@ -1382,7 +1393,7 @@ void HandleHotKeysBlender( VariantMap& eventData)
     }
     }
     else if (key == 'Z' && eventData["Qualifiers"].GetInt() != QUAL_CTRL)
     else if (key == 'Z' && eventData["Qualifiers"].GetInt() != QUAL_CTRL)
     {
     {
-        if (ui.focusElement is null) 
+        if (ui.focusElement is null)
         {
         {
             fillMode = FillMode(fillMode + 1);
             fillMode = FillMode(fillMode + 1);
             if (fillMode > FILL_POINT)
             if (fillMode > FILL_POINT)
@@ -1397,12 +1408,12 @@ void HandleHotKeysBlender( VariantMap& eventData)
         if (ui.cursor.visible && ui.focusElement is null)
         if (ui.cursor.visible && ui.focusElement is null)
             ToggleQuickMenu();
             ToggleQuickMenu();
     }
     }
-    else 
+    else
     {
     {
         SteppedObjectManipulation(key);
         SteppedObjectManipulation(key);
     }
     }
-        
-    if ((ui.focusElement is null) && (selectedNodes.length > 0) && !cameraFlyMode) 
+
+    if ((ui.focusElement is null) && (selectedNodes.length > 0) && !cameraFlyMode)
     {
     {
          if (eventData["Qualifiers"].GetInt() == QUAL_ALT) // reset transformations
          if (eventData["Qualifiers"].GetInt() == QUAL_ALT) // reset transformations
          {
          {
@@ -1412,56 +1423,56 @@ void HandleHotKeysBlender( VariantMap& eventData)
                 SceneResetRotation();
                 SceneResetRotation();
             else if (key == KEY_S)
             else if (key == KEY_S)
                 SceneResetScale();
                 SceneResetScale();
-            else if (key == KEY_F) 
+            else if (key == KEY_F)
             {
             {
                  Vector3 center = Vector3(0,0,0);
                  Vector3 center = Vector3(0,0,0);
-                 
+
                  if (selectedNodes.length > 0)
                  if (selectedNodes.length > 0)
                     center = SelectedNodesCenterPoint();
                     center = SelectedNodesCenterPoint();
-                 
-                 cameraNode.LookAt(center);  
+
+                 cameraNode.LookAt(center);
                  ReacquireCameraYawPitch();
                  ReacquireCameraYawPitch();
-            } 
+            }
          }
          }
          else if (eventData["Qualifiers"].GetInt() != QUAL_CTRL) // set transformations
          else if (eventData["Qualifiers"].GetInt() != QUAL_CTRL) // set transformations
          {
          {
-                if (key == KEY_G) 
+                if (key == KEY_G)
                 {
                 {
-                    editMode = EDIT_MOVE; 
+                    editMode = EDIT_MOVE;
                     axisMode = AxisMode(axisMode ^ AXIS_LOCAL);
                     axisMode = AxisMode(axisMode ^ AXIS_LOCAL);
-                
+
                 }
                 }
-                else if (key == KEY_R) 
+                else if (key == KEY_R)
                 {
                 {
                     editMode = EDIT_ROTATE;
                     editMode = EDIT_ROTATE;
                     axisMode = AxisMode(axisMode ^ AXIS_LOCAL);
                     axisMode = AxisMode(axisMode ^ AXIS_LOCAL);
-                
+
                 }
                 }
-                else if (key == KEY_S) 
+                else if (key == KEY_S)
                 {
                 {
                     editMode = EDIT_SCALE;
                     editMode = EDIT_SCALE;
-                    axisMode = AxisMode(axisMode ^ AXIS_LOCAL); 
+                    axisMode = AxisMode(axisMode ^ AXIS_LOCAL);
                 }
                 }
-                else if (key == KEY_F) 
+                else if (key == KEY_F)
                 {
                 {
-                    if (camera.orthographic) 
+                    if (camera.orthographic)
                     {
                     {
                         viewCloser = true;
                         viewCloser = true;
                     }
                     }
                     else
                     else
                     {
                     {
                         Vector3 center = Vector3(0,0,0);
                         Vector3 center = Vector3(0,0,0);
-                        
+
                         if (selectedNodes.length > 0)
                         if (selectedNodes.length > 0)
-                            center = SelectedNodesCenterPoint(); 
-                        
+                            center = SelectedNodesCenterPoint();
+
                         cameraNode.LookAt(center);
                         cameraNode.LookAt(center);
                         ReacquireCameraYawPitch();
                         ReacquireCameraYawPitch();
-                    } 
+                    }
                 }
                 }
-         }  
+         }
     }
     }
-    
+
     toolBarDirty = true;
     toolBarDirty = true;
 }
 }
 
 
@@ -1469,7 +1480,7 @@ void HandleHotKeysStandard(VariantMap& eventData)
 {
 {
     int key = eventData["Key"].GetInt();
     int key = eventData["Key"].GetInt();
     int viewDirection = eventData["Qualifiers"].GetInt() == QUAL_CTRL ? -1 : 1;
     int viewDirection = eventData["Qualifiers"].GetInt() == QUAL_CTRL ? -1 : 1;
-    
+
     if (key == KEY_ESC)
     if (key == KEY_ESC)
     {
     {
         if (uiHidden)
         if (uiHidden)
@@ -1514,13 +1525,13 @@ void HandleHotKeysStandard(VariantMap& eventData)
             fileSystem.CreateDir(screenshotDir);
             fileSystem.CreateDir(screenshotDir);
         screenshot.SavePNG(screenshotDir + "/Screenshot_" +
         screenshot.SavePNG(screenshotDir + "/Screenshot_" +
                 time.timeStamp.Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png");
                 time.timeStamp.Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png");
-    }   
+    }
     else if (key == KEY_KP_1 && ui.focusElement is null) // Front view
     else if (key == KEY_KP_1 && ui.focusElement is null) // Front view
     {
     {
         Vector3 center = Vector3(0,0,0);
         Vector3 center = Vector3(0,0,0);
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
             center = SelectedNodesCenterPoint();
             center = SelectedNodesCenterPoint();
-            
+
         Vector3 pos = cameraNode.worldPosition - center;
         Vector3 pos = cameraNode.worldPosition - center;
         cameraNode.worldPosition = center - Vector3(0.0, 0.0, pos.length * viewDirection);
         cameraNode.worldPosition = center - Vector3(0.0, 0.0, pos.length * viewDirection);
         cameraNode.direction = Vector3(0, 0, viewDirection);
         cameraNode.direction = Vector3(0, 0, viewDirection);
@@ -1532,7 +1543,7 @@ void HandleHotKeysStandard(VariantMap& eventData)
         Vector3 center = Vector3(0,0,0);
         Vector3 center = Vector3(0,0,0);
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
             center = SelectedNodesCenterPoint();
             center = SelectedNodesCenterPoint();
-            
+
         Vector3 pos = cameraNode.worldPosition - center;
         Vector3 pos = cameraNode.worldPosition - center;
         cameraNode.worldPosition = center - Vector3(pos.length * -viewDirection, 0.0, 0.0);
         cameraNode.worldPosition = center - Vector3(pos.length * -viewDirection, 0.0, 0.0);
         cameraNode.direction = Vector3(-viewDirection, 0, 0);
         cameraNode.direction = Vector3(-viewDirection, 0, 0);
@@ -1544,7 +1555,7 @@ void HandleHotKeysStandard(VariantMap& eventData)
         Vector3 center = Vector3(0,0,0);
         Vector3 center = Vector3(0,0,0);
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
         if (selectedNodes.length > 0 || selectedComponents.length > 0)
             center = SelectedNodesCenterPoint();
             center = SelectedNodesCenterPoint();
-            
+
         Vector3 pos = cameraNode.worldPosition - center;
         Vector3 pos = cameraNode.worldPosition - center;
         cameraNode.worldPosition = center - Vector3(0.0, pos.length * -viewDirection, 0.0);
         cameraNode.worldPosition = center - Vector3(0.0, pos.length * -viewDirection, 0.0);
         cameraNode.direction = Vector3(0, -viewDirection, 0);
         cameraNode.direction = Vector3(0, -viewDirection, 0);
@@ -1555,13 +1566,13 @@ void HandleHotKeysStandard(VariantMap& eventData)
     {
     {
         activeViewport.ToggleOrthographic();
         activeViewport.ToggleOrthographic();
     }
     }
-    else if (eventData["Qualifiers"].GetInt() == QUAL_CTRL) 
+    else if (eventData["Qualifiers"].GetInt() == QUAL_CTRL)
     {
     {
-        if (key == '1') 
-            editMode = EDIT_MOVE; 
-        else if (key == '2') 
+        if (key == '1')
+            editMode = EDIT_MOVE;
+        else if (key == '2')
             editMode = EDIT_ROTATE;
             editMode = EDIT_ROTATE;
-        else if (key == '3') 
+        else if (key == '3')
             editMode = EDIT_SCALE;
             editMode = EDIT_SCALE;
         else if (key == '4')
         else if (key == '4')
             editMode = EDIT_SELECT;
             editMode = EDIT_SELECT;
@@ -1595,7 +1606,7 @@ void HandleHotKeysStandard(VariantMap& eventData)
         }
         }
         else
         else
             SteppedObjectManipulation(key);
             SteppedObjectManipulation(key);
-            
+
         toolBarDirty = true;
         toolBarDirty = true;
     }
     }
 }
 }
@@ -1613,7 +1624,7 @@ void HandleKeyDown(StringHash eventType, VariantMap& eventData)
 }
 }
 
 
 void UnfadeUI()
 void UnfadeUI()
-{    
+{
     FadeUI(false);
     FadeUI(false);
 }
 }
 
 
@@ -1883,68 +1894,68 @@ bool SetSplinePath()
     return SceneSetChildrenSplinePath(menu.name == "Cyclic");
     return SceneSetChildrenSplinePath(menu.name == "Cyclic");
 }
 }
 
 
-bool ColorWheelBuildMenuSelectTypeColor() 
+bool ColorWheelBuildMenuSelectTypeColor()
 {
 {
     if (selectedNodes.empty && selectedComponents.empty) return false;
     if (selectedNodes.empty && selectedComponents.empty) return false;
     editMode = EDIT_SELECT;
     editMode = EDIT_SELECT;
-    
+
     // do coloring only for single selected object
     // do coloring only for single selected object
     // start with trying to find single component
     // start with trying to find single component
-    if (selectedComponents.length == 1) 
+    if (selectedComponents.length == 1)
     {
     {
-        coloringComponent = selectedComponents[0];    
+        coloringComponent = selectedComponents[0];
     }
     }
     // else try to get first component from selected node
     // else try to get first component from selected node
-    else if (selectedNodes.length == 1) 
+    else if (selectedNodes.length == 1)
     {
     {
         Array<Component@> components = selectedNodes[0].GetComponents();
         Array<Component@> components = selectedNodes[0].GetComponents();
-        if (components.length > 0) 
+        if (components.length > 0)
         {
         {
             coloringComponent = components[0];
             coloringComponent = components[0];
         }
         }
     }
     }
     else
     else
         return false;
         return false;
-        
+
     if (coloringComponent is null) return false;
     if (coloringComponent is null) return false;
-    
+
     Array<UIElement@> actions;
     Array<UIElement@> actions;
-           
-    if (coloringComponent.typeName == "Light") 
+
+    if (coloringComponent.typeName == "Light")
     {
     {
         actions.Push(CreateContextMenuItem("Light color", "HandleColorWheelMenu", "menuLightColor"));
         actions.Push(CreateContextMenuItem("Light color", "HandleColorWheelMenu", "menuLightColor"));
         actions.Push(CreateContextMenuItem("Specular intensity", "HandleColorWheelMenu", "menuSpecularIntensity"));
         actions.Push(CreateContextMenuItem("Specular intensity", "HandleColorWheelMenu", "menuSpecularIntensity"));
         actions.Push(CreateContextMenuItem("Brightness multiplier", "HandleColorWheelMenu", "menuBrightnessMultiplier"));
         actions.Push(CreateContextMenuItem("Brightness multiplier", "HandleColorWheelMenu", "menuBrightnessMultiplier"));
-        
+
         actions.Push(CreateContextMenuItem("Cancel", "HandleColorWheelMenu", "menuCancel"));
         actions.Push(CreateContextMenuItem("Cancel", "HandleColorWheelMenu", "menuCancel"));
-        
+
     }
     }
-    else if (coloringComponent.typeName == "StaticModel") 
+    else if (coloringComponent.typeName == "StaticModel")
     {
     {
         actions.Push(CreateContextMenuItem("Diffuse color", "HandleColorWheelMenu", "menuDiffuseColor"));
         actions.Push(CreateContextMenuItem("Diffuse color", "HandleColorWheelMenu", "menuDiffuseColor"));
         actions.Push(CreateContextMenuItem("Specular color", "HandleColorWheelMenu", "menuSpecularColor"));
         actions.Push(CreateContextMenuItem("Specular color", "HandleColorWheelMenu", "menuSpecularColor"));
         actions.Push(CreateContextMenuItem("Emissive color", "HandleColorWheelMenu", "menuEmissiveColor"));
         actions.Push(CreateContextMenuItem("Emissive color", "HandleColorWheelMenu", "menuEmissiveColor"));
         actions.Push(CreateContextMenuItem("Environment map color", "HandleColorWheelMenu", "menuEnvironmentMapColor"));
         actions.Push(CreateContextMenuItem("Environment map color", "HandleColorWheelMenu", "menuEnvironmentMapColor"));
-        
+
         actions.Push(CreateContextMenuItem("Cancel", "HandleColorWheelMenu", "menuCancel"));
         actions.Push(CreateContextMenuItem("Cancel", "HandleColorWheelMenu", "menuCancel"));
     }
     }
-    else if (coloringComponent.typeName == "Zone")        
+    else if (coloringComponent.typeName == "Zone")
     {
     {
         actions.Push(CreateContextMenuItem("Ambient color", "HandleColorWheelMenu", "menuAmbientColor"));
         actions.Push(CreateContextMenuItem("Ambient color", "HandleColorWheelMenu", "menuAmbientColor"));
         actions.Push(CreateContextMenuItem("Fog color", "HandleColorWheelMenu", "menuFogColor"));
         actions.Push(CreateContextMenuItem("Fog color", "HandleColorWheelMenu", "menuFogColor"));
-        
+
         actions.Push(CreateContextMenuItem("Cancel", "HandleColorWheelMenu", "menuCancel"));
         actions.Push(CreateContextMenuItem("Cancel", "HandleColorWheelMenu", "menuCancel"));
     }
     }
-    
+
     if (actions.length > 0) {
     if (actions.length > 0) {
         ActivateContextMenu(actions);
         ActivateContextMenu(actions);
         return true;
         return true;
     }
     }
-        
+
     return false;
     return false;
 }
 }
 
 
-void HandleColorWheelMenu() 
+void HandleColorWheelMenu()
 {
 {
     ColorWheelSetupBehaviorForColoring();
     ColorWheelSetupBehaviorForColoring();
 }
 }
@@ -1956,42 +1967,42 @@ void HandleWheelChangeColor(StringHash eventType, VariantMap& eventData)
 
 
     if (coloringComponent !is null)
     if (coloringComponent !is null)
     {
     {
-        Color c = eventData["Color"].GetColor();  // current ColorWheel   
+        Color c = eventData["Color"].GetColor();  // current ColorWheel
         // preview new color
         // preview new color
-        if (coloringComponent.typeName == "Light") 
+        if (coloringComponent.typeName == "Light")
         {
         {
             Light@ light = cast<Light>(coloringComponent);
             Light@ light = cast<Light>(coloringComponent);
-            if (light !is null) 
-            {          
+            if (light !is null)
+            {
                 if (coloringPropertyName == "menuLightColor")
                 if (coloringPropertyName == "menuLightColor")
                 {
                 {
                     light.color = c;
                     light.color = c;
                 }
                 }
                 else if (coloringPropertyName == "menuSpecularIntensity")
                 else if (coloringPropertyName == "menuSpecularIntensity")
                 {
                 {
-                   // multiply out 
+                   // multiply out
                    light.specularIntensity = c.Value() * 10.0f;
                    light.specularIntensity = c.Value() * 10.0f;
 
 
                 }
                 }
                 else if (coloringPropertyName == "menuBrightnessMultiplier")
                 else if (coloringPropertyName == "menuBrightnessMultiplier")
                 {
                 {
                    light.brightness = c.Value() * 10.0f;
                    light.brightness = c.Value() * 10.0f;
-                   
+
                 }
                 }
-                
-                attributesDirty = true;   
-            }      
+
+                attributesDirty = true;
+            }
         }
         }
-        else if (coloringComponent.typeName == "StaticModel") 
+        else if (coloringComponent.typeName == "StaticModel")
         {
         {
             StaticModel@ model  = cast<StaticModel>(coloringComponent);
             StaticModel@ model  = cast<StaticModel>(coloringComponent);
-            if (model !is null) 
-            {            
+            if (model !is null)
+            {
                 Material@ mat = model.materials[0];
                 Material@ mat = model.materials[0];
-                if (mat !is null) 
-                { 
+                if (mat !is null)
+                {
                     if (coloringPropertyName == "menuDiffuseColor")
                     if (coloringPropertyName == "menuDiffuseColor")
-                    {   
+                    {
                         Variant oldValue = mat.shaderParameters["MatDiffColor"];
                         Variant oldValue = mat.shaderParameters["MatDiffColor"];
                         Variant newValue;
                         Variant newValue;
                         String valueString;
                         String valueString;
@@ -2002,14 +2013,14 @@ void HandleWheelChangeColor(StringHash eventType, VariantMap& eventData)
                         valueString += String(c.b).Substring(0,5);
                         valueString += String(c.b).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(c.a).Substring(0,5);
                         valueString += String(c.a).Substring(0,5);
-                        newValue.FromString(oldValue.type, valueString);    
+                        newValue.FromString(oldValue.type, valueString);
                         mat.shaderParameters["MatDiffColor"] = newValue;
                         mat.shaderParameters["MatDiffColor"] = newValue;
                     }
                     }
                     else if (coloringPropertyName == "menuSpecularColor")
                     else if (coloringPropertyName == "menuSpecularColor")
-                    { 
+                    {
                         Variant oldValue = mat.shaderParameters["MatSpecColor"];
                         Variant oldValue = mat.shaderParameters["MatSpecColor"];
                         Variant newValue;
                         Variant newValue;
-                        String valueString;                        
+                        String valueString;
                         valueString += String(c.r).Substring(0,5);
                         valueString += String(c.r).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(c.g).Substring(0,5);
                         valueString += String(c.g).Substring(0,5);
@@ -2017,7 +2028,7 @@ void HandleWheelChangeColor(StringHash eventType, VariantMap& eventData)
                         valueString += String(c.b).Substring(0,5);
                         valueString += String(c.b).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(c.a * 128).Substring(0,5);
                         valueString += String(c.a * 128).Substring(0,5);
-                        newValue.FromString(oldValue.type, valueString);    
+                        newValue.FromString(oldValue.type, valueString);
                         mat.shaderParameters["MatSpecColor"] = newValue;
                         mat.shaderParameters["MatSpecColor"] = newValue;
                     }
                     }
                     else if (coloringPropertyName == "menuEmissiveColor")
                     else if (coloringPropertyName == "menuEmissiveColor")
@@ -2032,7 +2043,7 @@ void HandleWheelChangeColor(StringHash eventType, VariantMap& eventData)
                         valueString += String(c.b).Substring(0,5);
                         valueString += String(c.b).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(c.a).Substring(0,5);
                         valueString += String(c.a).Substring(0,5);
-                        newValue.FromString(oldValue.type, valueString);    
+                        newValue.FromString(oldValue.type, valueString);
                         mat.shaderParameters["MatEmissiveColor"] = newValue;
                         mat.shaderParameters["MatEmissiveColor"] = newValue;
                     }
                     }
                     else if (coloringPropertyName == "menuEnvironmentMapColor")
                     else if (coloringPropertyName == "menuEnvironmentMapColor")
@@ -2047,29 +2058,29 @@ void HandleWheelChangeColor(StringHash eventType, VariantMap& eventData)
                         valueString += String(c.b).Substring(0,5);
                         valueString += String(c.b).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(c.a).Substring(0,5);
                         valueString += String(c.a).Substring(0,5);
-                        newValue.FromString(oldValue.type, valueString);    
+                        newValue.FromString(oldValue.type, valueString);
                         mat.shaderParameters["MatEnvMapColor"] = newValue;
                         mat.shaderParameters["MatEnvMapColor"] = newValue;
-                    }                    
+                    }
                 }
                 }
             }
             }
         }
         }
-        else if (coloringComponent.typeName == "Zone") 
+        else if (coloringComponent.typeName == "Zone")
         {
         {
             Zone@ zone  = cast<Zone>(coloringComponent);
             Zone@ zone  = cast<Zone>(coloringComponent);
-            if (zone !is null) 
+            if (zone !is null)
             {
             {
                 if (coloringPropertyName == "menuAmbientColor")
                 if (coloringPropertyName == "menuAmbientColor")
                 {
                 {
                     zone.ambientColor = c;
                     zone.ambientColor = c;
                 }
                 }
-                else if (coloringPropertyName == "menuFogColor") 
+                else if (coloringPropertyName == "menuFogColor")
                 {
                 {
                     zone.fogColor = c;
                     zone.fogColor = c;
                 }
                 }
-                
+
                 attributesDirty = true;
                 attributesDirty = true;
             }
             }
-        }        
+        }
     }
     }
 
 
     timeToNextColoringGroupUpdate = time.systemTime + stepColoringGroupUpdate;
     timeToNextColoringGroupUpdate = time.systemTime + stepColoringGroupUpdate;
@@ -2080,15 +2091,15 @@ void HandleWheelDiscardColor(StringHash eventType, VariantMap& eventData)
 {
 {
     if (coloringComponent !is null)
     if (coloringComponent !is null)
     {
     {
-        //Color oldColor = eventData["Color"].GetColor(); //Old color from ColorWheel from ShowColorWheelWithColor(old)     
+        //Color oldColor = eventData["Color"].GetColor(); //Old color from ColorWheel from ShowColorWheelWithColor(old)
         Color oldColor = coloringOldColor;
         Color oldColor = coloringOldColor;
-        
+
         // preview new color
         // preview new color
-        if (coloringComponent.typeName == "Light") 
+        if (coloringComponent.typeName == "Light")
         {
         {
             Light@ light = cast<Light>(coloringComponent);
             Light@ light = cast<Light>(coloringComponent);
-            if (light !is null) 
-            {          
+            if (light !is null)
+            {
                 if (coloringPropertyName == "menuLightColor")
                 if (coloringPropertyName == "menuLightColor")
                 {
                 {
                     light.color = oldColor;
                     light.color = oldColor;
@@ -2101,22 +2112,22 @@ void HandleWheelDiscardColor(StringHash eventType, VariantMap& eventData)
                 else if (coloringPropertyName == "menuBrightnessMultiplier")
                 else if (coloringPropertyName == "menuBrightnessMultiplier")
                 {
                 {
                    light.brightness = coloringOldScalar * 10.0f;
                    light.brightness = coloringOldScalar * 10.0f;
-                   
+
                 }
                 }
-                
-                attributesDirty = true;   
-            }      
+
+                attributesDirty = true;
+            }
         }
         }
-        else if (coloringComponent.typeName == "StaticModel") 
+        else if (coloringComponent.typeName == "StaticModel")
         {
         {
             StaticModel@ model  = cast<StaticModel>(coloringComponent);
             StaticModel@ model  = cast<StaticModel>(coloringComponent);
-            if (model !is null) 
-            {            
+            if (model !is null)
+            {
                 Material@ mat = model.materials[0];
                 Material@ mat = model.materials[0];
-                if (mat !is null) 
-                {                 
+                if (mat !is null)
+                {
                     if (coloringPropertyName == "menuDiffuseColor")
                     if (coloringPropertyName == "menuDiffuseColor")
-                    {   
+                    {
                         Variant oldValue = mat.shaderParameters["MatDiffColor"];
                         Variant oldValue = mat.shaderParameters["MatDiffColor"];
                         Variant newValue;
                         Variant newValue;
                         String valueString;
                         String valueString;
@@ -2127,14 +2138,14 @@ void HandleWheelDiscardColor(StringHash eventType, VariantMap& eventData)
                         valueString += String(oldColor.b).Substring(0,5);
                         valueString += String(oldColor.b).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(oldColor.a).Substring(0,5);
                         valueString += String(oldColor.a).Substring(0,5);
-                        newValue.FromString(oldValue.type, valueString);    
+                        newValue.FromString(oldValue.type, valueString);
                         mat.shaderParameters["MatDiffColor"] = newValue;
                         mat.shaderParameters["MatDiffColor"] = newValue;
                     }
                     }
                     else if (coloringPropertyName == "menuSpecularColor")
                     else if (coloringPropertyName == "menuSpecularColor")
-                    { 
+                    {
                         Variant oldValue = mat.shaderParameters["MatSpecColor"];
                         Variant oldValue = mat.shaderParameters["MatSpecColor"];
                         Variant newValue;
                         Variant newValue;
-                        String valueString;                        
+                        String valueString;
                         valueString += String(oldColor.r).Substring(0,5);
                         valueString += String(oldColor.r).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(oldColor.g).Substring(0,5);
                         valueString += String(oldColor.g).Substring(0,5);
@@ -2142,7 +2153,7 @@ void HandleWheelDiscardColor(StringHash eventType, VariantMap& eventData)
                         valueString += String(oldColor.b).Substring(0,5);
                         valueString += String(oldColor.b).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(coloringOldScalar).Substring(0,5);
                         valueString += String(coloringOldScalar).Substring(0,5);
-                        newValue.FromString(oldValue.type, valueString);    
+                        newValue.FromString(oldValue.type, valueString);
                         mat.shaderParameters["MatSpecColor"] = newValue;
                         mat.shaderParameters["MatSpecColor"] = newValue;
                     }
                     }
                     else if (coloringPropertyName == "menuEmissiveColor")
                     else if (coloringPropertyName == "menuEmissiveColor")
@@ -2157,7 +2168,7 @@ void HandleWheelDiscardColor(StringHash eventType, VariantMap& eventData)
                         valueString += String(oldColor.b).Substring(0,5);
                         valueString += String(oldColor.b).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(oldColor.a).Substring(0,5);
                         valueString += String(oldColor.a).Substring(0,5);
-                        newValue.FromString(oldValue.type, valueString);    
+                        newValue.FromString(oldValue.type, valueString);
                         mat.shaderParameters["MatEmissiveColor"] = newValue;
                         mat.shaderParameters["MatEmissiveColor"] = newValue;
                     }
                     }
                     else if (coloringPropertyName == "menuEnvironmentMapColor")
                     else if (coloringPropertyName == "menuEnvironmentMapColor")
@@ -2172,53 +2183,53 @@ void HandleWheelDiscardColor(StringHash eventType, VariantMap& eventData)
                         valueString += String(oldColor.b).Substring(0,5);
                         valueString += String(oldColor.b).Substring(0,5);
                         valueString += " ";
                         valueString += " ";
                         valueString += String(oldColor.a).Substring(0,5);
                         valueString += String(oldColor.a).Substring(0,5);
-                        newValue.FromString(oldValue.type, valueString);    
+                        newValue.FromString(oldValue.type, valueString);
                         mat.shaderParameters["MatEnvMapColor"] = newValue;
                         mat.shaderParameters["MatEnvMapColor"] = newValue;
-                    }                                        
+                    }
                 }
                 }
             }
             }
         }
         }
-        else if (coloringComponent.typeName == "Zone") 
+        else if (coloringComponent.typeName == "Zone")
         {
         {
             Zone@ zone  = cast<Zone>(coloringComponent);
             Zone@ zone  = cast<Zone>(coloringComponent);
-            if (zone !is null) 
+            if (zone !is null)
             {
             {
                 if (coloringPropertyName == "menuAmbientColor")
                 if (coloringPropertyName == "menuAmbientColor")
                 {
                 {
                     zone.ambientColor = oldColor;
                     zone.ambientColor = oldColor;
                 }
                 }
-                else if (coloringPropertyName == "menuFogColor") 
+                else if (coloringPropertyName == "menuFogColor")
                 {
                 {
                     zone.fogColor = oldColor;
                     zone.fogColor = oldColor;
                 }
                 }
-                
+
                 attributesDirty = true;
                 attributesDirty = true;
             }
             }
-        }        
+        }
     }
     }
 }
 }
 
 
 // Applying color wheel changes to material
 // Applying color wheel changes to material
 void HandleWheelSelectColor(StringHash eventType, VariantMap& eventData)
 void HandleWheelSelectColor(StringHash eventType, VariantMap& eventData)
-{  
+{
     if (coloringComponent !is null)
     if (coloringComponent !is null)
-    if (coloringComponent.typeName == "StaticModel") 
+    if (coloringComponent.typeName == "StaticModel")
     {
     {
         Color c = eventData["Color"].GetColor(); //Selected color from ColorWheel
         Color c = eventData["Color"].GetColor(); //Selected color from ColorWheel
         StaticModel@ model  = cast<StaticModel>(coloringComponent);
         StaticModel@ model  = cast<StaticModel>(coloringComponent);
-        if (model !is null) 
+        if (model !is null)
         {
         {
             Material@ mat = model.materials[0];
             Material@ mat = model.materials[0];
-            if (mat !is null) 
+            if (mat !is null)
             {
             {
                 editMaterial = mat;
                 editMaterial = mat;
-                SaveMaterial();                       
+                SaveMaterial();
             }
             }
         }
         }
     }
     }
 }
 }
 
 
-bool ViewDebugIcons() 
+bool ViewDebugIcons()
 {
 {
     debugIconsShow = !debugIconsShow;
     debugIconsShow = !debugIconsShow;
     return true;
     return true;

+ 11 - 0
bin/Data/Scripts/NinjaSnowWar.as

@@ -489,6 +489,17 @@ void HandleKeyDown(StringHash eventType, VariantMap& eventData)
     if (key == KEY_F4)
     if (key == KEY_F4)
         drawOctreeDebug = !drawOctreeDebug;
         drawOctreeDebug = !drawOctreeDebug;
 
 
+    if (key == KEY_F5)
+        debugHud.Toggle(DEBUGHUD_SHOW_EVENTPROFILER);
+                // Take screenshot
+    if (key == KEY_F6)
+    {
+        Image@ screenshot = Image();
+        graphics.TakeScreenShot(screenshot);
+        // Here we save in the Data folder with date and time appended
+        screenshot.SavePNG(fileSystem.programDir + "Data/Screenshot_" +
+                time.timeStamp.Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png");
+    }
     // Allow pause only in singleplayer
     // Allow pause only in singleplayer
     if (key == 'P' && singlePlayer && !console.visible && gameOn)
     if (key == 'P' && singlePlayer && !console.visible && gameOn)
     {
     {

+ 22 - 3
bin/Data/UI/EditorParticleEffectWindow.xml

@@ -656,6 +656,25 @@
                                     <attribute name="Layout Spacing" value="1" />
                                     <attribute name="Layout Spacing" value="1" />
                                 </element>
                                 </element>
                             </element>
                             </element>
+                            <element>
+                                <!-- Relative -->
+                                <attribute name="Min Size" value="0 16" />
+                                <attribute name="Max Size" value="2147483647 16" />
+                                <attribute name="Layout Mode" value="Horizontal" />
+                                <attribute name="Layout Spacing" value="10" />
+                                <element type="Text" style="EditorAttributeText">
+                                    <attribute name="Text" value="Relative Transform" />
+                                </element>
+                                <element>
+                                    <attribute name="Min Size" value="0 16" />
+                                    <attribute name="Max Size" value="2147483647 16" />
+                                    <attribute name="Layout Mode" value="Horizontal" />
+                                    <attribute name="Layout Spacing" value="1" />
+                                    <element type="CheckBox">
+                                        <attribute name="Name" value="Relative" />
+                                    </element>
+                                </element>
+                            </element>
                             <element>
                             <element>
                                 <!-- Scaled -->
                                 <!-- Scaled -->
                                 <attribute name="Min Size" value="0 16" />
                                 <attribute name="Min Size" value="0 16" />
@@ -695,13 +714,13 @@
                                 </element>
                                 </element>
                             </element>
                             </element>
                             <element>
                             <element>
-                                <!-- Relative -->
+                                <!-- Fixed screen size -->
                                 <attribute name="Min Size" value="0 16" />
                                 <attribute name="Min Size" value="0 16" />
                                 <attribute name="Max Size" value="2147483647 16" />
                                 <attribute name="Max Size" value="2147483647 16" />
                                 <attribute name="Layout Mode" value="Horizontal" />
                                 <attribute name="Layout Mode" value="Horizontal" />
                                 <attribute name="Layout Spacing" value="10" />
                                 <attribute name="Layout Spacing" value="10" />
                                 <element type="Text" style="EditorAttributeText">
                                 <element type="Text" style="EditorAttributeText">
-                                    <attribute name="Text" value="Relative Transform" />
+                                    <attribute name="Text" value="Fixed Screen Size" />
                                 </element>
                                 </element>
                                 <element>
                                 <element>
                                     <attribute name="Min Size" value="0 16" />
                                     <attribute name="Min Size" value="0 16" />
@@ -709,7 +728,7 @@
                                     <attribute name="Layout Mode" value="Horizontal" />
                                     <attribute name="Layout Mode" value="Horizontal" />
                                     <attribute name="Layout Spacing" value="1" />
                                     <attribute name="Layout Spacing" value="1" />
                                     <element type="CheckBox">
                                     <element type="CheckBox">
-                                        <attribute name="Name" value="Relative" />
+                                        <attribute name="Name" value="FixedScreenSize" />
                                     </element>
                                     </element>
                                 </element>
                                 </element>
                             </element>
                             </element>

Some files were not shown because too many files changed in this diff