Browse Source

Merge branch 'master' of github.com:urho3d/Urho3D into p2p-multiplayer

Arnis Lielturks 6 years ago
parent
commit
c89e98c3eb
37 changed files with 380 additions and 497 deletions
  1. 2 7
      .travis.yml
  2. 20 8
      Docs/AngelScriptAPI.h
  3. 9 5
      Docs/LuaScriptAPI.dox
  4. 34 8
      Docs/ScriptAPI.dox
  5. 3 0
      Docs/Urho3D.dox
  6. 3 0
      README.md
  7. 1 0
      Source/Samples/Utilities2D/Sample2D.cpp
  8. 26 0
      Source/ThirdParty/SLikeNet/CMakeLists.txt
  9. 18 9
      Source/ThirdParty/SLikeNet/Source/include/slikenet/linux_adapter.h
  10. 0 60
      Source/ThirdParty/SLikeNet/Source/include/slikenet/osx_adapter.h
  11. 33 31
      Source/ThirdParty/SLikeNet/Source/src/linux_adapter.cpp
  12. 0 303
      Source/ThirdParty/SLikeNet/Source/src/osx_adapter.cpp
  13. 3 2
      Source/ThirdParty/StanHull/hull.cpp
  14. 1 1
      Source/ThirdParty/ik/src/util.c
  15. 1 1
      Source/Urho3D/.soversion
  16. 2 0
      Source/Urho3D/AngelScript/APITemplates.h
  17. 8 8
      Source/Urho3D/AngelScript/ResourceAPI.cpp
  18. 2 0
      Source/Urho3D/AngelScript/UIAPI.cpp
  19. 5 0
      Source/Urho3D/CMakeLists.txt
  20. 1 1
      Source/Urho3D/Core/Context.cpp
  21. 1 1
      Source/Urho3D/IO/Log.h
  22. 2 1
      Source/Urho3D/LuaScript/pkgs/Graphics/AnimationState.pkg
  23. 6 6
      Source/Urho3D/LuaScript/pkgs/Resource/JSONValue.pkg
  24. 4 0
      Source/Urho3D/LuaScript/pkgs/UI/ToolTip.pkg
  25. 17 7
      Source/Urho3D/Network/Network.cpp
  26. 5 0
      Source/Urho3D/Network/NetworkEvents.h
  27. 7 7
      Source/Urho3D/Resource/JSONValue.h
  28. 26 0
      Source/Urho3D/UI/BorderImage.cpp
  29. 11 0
      Source/Urho3D/UI/BorderImage.h
  30. 37 12
      Source/Urho3D/UI/ToolTip.cpp
  31. 10 2
      Source/Urho3D/UI/ToolTip.h
  32. 68 14
      Source/Urho3D/UI/UI.cpp
  33. 3 0
      Source/Urho3D/UI/UIBatch.h
  34. 1 1
      bin/Data/LuaScripts/50_Urho2DPlatformer.lua
  35. 1 0
      bin/Data/LuaScripts/Utilities/2D/Sample2D.lua
  36. 1 0
      bin/Data/Scripts/Utilities/2D/Sample2D.as
  37. 8 2
      script/dockerized.sh

+ 2 - 7
.travis.yml

@@ -23,7 +23,6 @@
 ---
 
 dist: trusty
-sudo: required
 addons: {apt: {packages: docker-ce}}
 cache: {directories: $HOME/urho3d_home_dir/.ccache}
 env:
@@ -168,7 +167,6 @@ language: cpp
 compiler: gcc
 cache: ccache
 dist: trusty
-sudo: false
 addons:
   apt:
     packages: libpulse-dev
@@ -201,6 +199,7 @@ branch: {name: Annotate, active: no}
 language: cpp
 compiler: gcc
 cache: ccache
+dist: trusty
 addons: {apt: {packages: libpulse-dev}}
 env:
   global:
@@ -221,7 +220,6 @@ after_script: rake ci_delete_mirror
 
 branch: {name: Android-CI, active: yes}
 dist: trusty
-sudo: required
 addons: {apt: {packages: docker-ce}}
 cache:
   directories:
@@ -260,7 +258,6 @@ matrix:
 
 branch: {name: RPI-CI, active: yes}
 dist: trusty
-sudo: required
 addons: {apt: {packages: docker-ce}}
 cache: {directories: $HOME/urho3d_home_dir/.ccache}
 env:
@@ -293,7 +290,6 @@ matrix:
 
 branch: {name: ARM-CI, active: yes}
 dist: trusty
-sudo: required
 addons: {apt: {packages: docker-ce}}
 cache: {directories: $HOME/urho3d_home_dir/.ccache}
 env:
@@ -326,7 +322,6 @@ matrix:
 
 branch: {name: Web-CI, active: yes}
 dist: trusty
-sudo: required
 addons: {apt: {packages: docker-ce}}
 cache:
   directories:
@@ -382,7 +377,7 @@ cache:
   directories:
     - $HOME/.ccache
     - $HOME/initial-build-tree
-osx_image: xcode9.4
+osx_image: xcode10.2
 env:
   global:
     - secure: SLJCjkjDsTMbCIV9Wecz5JATnhk0fuzlnLMeZdvvFDv+8NL8cXyutkU0VfyRSLf3HSD1Js79a6fRMROyVGWj/w/BRrjqGnZzsB6+ZeJNnadiVIF5Gh+w90We5ccvSp2G4DyYgwkNnkKlJK7zNEWGu/K+bHL1EOCA+EIVrFMyA44=

+ 20 - 8
Docs/AngelScriptAPI.h

@@ -1008,6 +1008,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;
@@ -1279,6 +1280,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;
@@ -1626,6 +1628,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;
@@ -3954,6 +3957,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;
@@ -4875,6 +4879,7 @@ LayoutMode layoutMode;
 int layoutSpacing;
 /* readonly */
 ListView listView;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;
@@ -6138,13 +6143,13 @@ void Clear();
 bool Contains(const String&) const;
 void Erase(const String&);
 void Erase(uint, uint = 1);
-bool GetBool() const;
-double GetDouble() const;
-float GetFloat() const;
-int GetInt() const;
-uint GetUInt() const;
-Variant GetVariant() const;
-VariantMap GetVariantMap() const;
+bool GetBool(bool = false) const;
+double GetDouble(double = 0) const;
+float GetFloat(float = 0) const;
+int GetInt(int = 0) const;
+uint GetUInt(uint = 0) const;
+Variant GetVariant(Variant = Variant ( )) const;
+VariantMap GetVariantMap(VariantMap = VariantMap ( )) const;
 void Insert(uint, const JSONValue&);
 const JSONValue& Get(const String&) const;
 void Pop();
@@ -6153,7 +6158,7 @@ void Resize(uint);
 void Set(const String&, const JSONValue&);
 void SetVariant(const Variant&);
 void SetVariantMap(const VariantMap&);
-const String& GetString() const;
+const String& GetString(const String& = String ( "" )) const;
 
 // Properties:
 /* readonly */
@@ -6498,6 +6503,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 uint maxLength;
@@ -7267,6 +7273,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;
@@ -11219,6 +11226,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;
@@ -14011,6 +14019,7 @@ void RemoveChild(uint);
 void RemoveInstanceDefault();
 void RemoveObjectAnimation();
 bool RemoveTag(const String&);
+void Reset();
 void ResetDeepEnabled();
 void ResetToDefault();
 bool Save(File) const;
@@ -14048,6 +14057,7 @@ bool SetStyle(const XMLElement&);
 bool SetStyleAuto(XMLFile = null);
 void UpdateLayout();
 const Variant& GetVar(const StringHash&);
+void add_altTarget(UIElement);
 
 // Properties:
 bool animationEnabled;
@@ -15319,6 +15329,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;
@@ -15603,6 +15614,7 @@ IntRect layoutBorder;
 Vector2 layoutFlexScale;
 LayoutMode layoutMode;
 int layoutSpacing;
+Material material;
 Vector2 maxAnchor;
 int maxHeight;
 IntVector2 maxOffset;

+ 9 - 5
Docs/LuaScriptAPI.dox

@@ -469,6 +469,7 @@ Methods:
 - void AddTime(float delta)
 - void SetLayer(char layer)
 - void SetBlendMode(AnimationBlendMode mode)
+- void Apply()
 - Animation* GetAnimation() const
 - Bone* GetStartBone() const
 - float GetBoneWeight(const String name) const
@@ -3161,12 +3162,13 @@ Methods:
 - bool IsString() const
 - bool IsArray() const
 - bool IsObject() const
-- bool GetBool() const
-- int GetInt() const
-- unsigned GetUInt() const
-- float GetFloat() const
-- double GetDouble() const
+- bool GetBool(bool defaultValue = false) const
+- int GetInt(int defaultValue = 0) const
+- unsigned GetUInt(unsigned defaultValue = 0) const
+- float GetFloat(float defaultValue = 0) const
+- double GetDouble(double defaultValue = 0) const
 - const String GetString() const
+- const String GetString(const String defaultValue) const
 - const JSONArray& GetArray() const
 - const JSONObject& GetObject() const
 - Variant GetVariant() const
@@ -7093,6 +7095,8 @@ Methods:
 - ToolTip() (GC)
 - ToolTip* new()
 - void delete()
+- void Reset()
+- void AddAltTarget(UIElement* target)
 - void SetDelay(float delay)
 - float GetDelay() const
 

+ 34 - 8
Docs/ScriptAPI.dox

@@ -404,6 +404,8 @@ namespace Urho3D
 
 ### ConnectFailed
 
+### ConnectionInProgress
+
 ### ClientConnected
 - %Connection : Connection pointer
 
@@ -1084,6 +1086,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 
 ### Button
 - %Name : String
@@ -1132,6 +1135,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Pressed %Image %Offset : IntVector2
 - %Disabled %Image %Offset : IntVector2
 - %Pressed %Child %Offset : IntVector2
@@ -1205,6 +1209,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Is %Checked : bool
 - %Checked %Image %Offset : IntVector2
 
@@ -1467,6 +1472,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Use %System %Shapes : bool
 - %Shapes : VariantVector
 
@@ -1550,6 +1556,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Pressed %Image %Offset : IntVector2
 - %Disabled %Image %Offset : IntVector2
 - %Pressed %Child %Offset : IntVector2
@@ -1691,6 +1698,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Max %Length : int
 - %Is %Cursor %Movable : bool
 - %Is %Text %Selectable : bool
@@ -1805,6 +1813,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Pressed %Image %Offset : IntVector2
 - %Disabled %Image %Offset : IntVector2
 - %Pressed %Child %Offset : IntVector2
@@ -1971,6 +1980,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Orientation : int
 - %Range : float
 - %Value : float
@@ -2108,6 +2118,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Orientation : int
 - %Range : float
 - %Value : float
@@ -2231,6 +2242,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Orientation : int
 - %Range : float
 - %Value : float
@@ -2654,6 +2666,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Resize %Border : IntRect
 - %Is %Movable : bool
 - %Is %Resizable : bool
@@ -2711,6 +2724,7 @@ namespace Urho3D
 - %Hover %Image %Offset : IntVector2
 - %Tiled : bool
 - %Blend %Mode : int
+- %Material : ResourceRef
 - %Resize %Border : IntRect
 - %Is %Movable : bool
 - %Is %Resizable : bool
@@ -3833,6 +3847,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset
@@ -4066,6 +4081,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset
@@ -4364,6 +4380,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset
@@ -6354,6 +6371,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset
@@ -7141,6 +7159,7 @@ Properties:
 - LayoutMode layoutMode
 - int layoutSpacing
 - ListView@ listView // readonly
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset
@@ -8169,13 +8188,13 @@ Methods:
 - bool Contains(const String&) const
 - void Erase(const String&)
 - void Erase(uint, uint = 1)
-- bool GetBool() const
-- double GetDouble() const
-- float GetFloat() const
-- int GetInt() const
-- uint GetUInt() const
-- Variant GetVariant() const
-- VariantMap GetVariantMap() const
+- bool GetBool(bool = false) const
+- double GetDouble(double = 0) const
+- float GetFloat(float = 0) const
+- int GetInt(int = 0) const
+- uint GetUInt(uint = 0) const
+- Variant GetVariant(Variant = Variant ( )) const
+- VariantMap GetVariantMap(VariantMap = VariantMap ( )) const
 - void Insert(uint, const JSONValue&)
 - const JSONValue& Get(const String&) const
 - void Pop()
@@ -8184,7 +8203,7 @@ Methods:
 - void Set(const String&, const JSONValue&)
 - void SetVariant(const Variant&)
 - void SetVariantMap(const VariantMap&)
-- const String& GetString() const
+- const String& GetString(const String& = String ( "" )) const
 
 Properties:
 
@@ -8472,6 +8491,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - uint maxLength
@@ -9142,6 +9162,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset
@@ -12549,6 +12570,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset
@@ -14858,6 +14880,7 @@ Methods:
 - void RemoveInstanceDefault()
 - void RemoveObjectAnimation()
 - bool RemoveTag(const String&)
+- void Reset()
 - void ResetDeepEnabled()
 - void ResetToDefault()
 - bool Save(File@) const
@@ -14895,6 +14918,7 @@ Methods:
 - bool SetStyleAuto(XMLFile@ = null)
 - void UpdateLayout()
 - const Variant& GetVar(const StringHash&)
+- void add_altTarget(UIElement@)
 
 Properties:
 
@@ -15956,6 +15980,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset
@@ -16197,6 +16222,7 @@ Properties:
 - Vector2 layoutFlexScale
 - LayoutMode layoutMode
 - int layoutSpacing
+- Material@ material
 - Vector2 maxAnchor
 - int maxHeight
 - IntVector2 maxOffset

+ 3 - 0
Docs/Urho3D.dox

@@ -162,6 +162,7 @@ Urho3D development, contributions and bugfixes by:
 - Ner'zhul
 - Newb I the Newbd
 - OvermindDL1
+- Polynominal
 - PredatorMF
 - Scellow
 - Skrylar
@@ -190,6 +191,7 @@ Urho3D development, contributions and bugfixes by:
 - marynate
 - meshonline
 - mightyCelu
+- MystMagus
 - neat3d
 - nemerle
 - ninjastone
@@ -202,6 +204,7 @@ Urho3D development, contributions and bugfixes by:
 - rifai
 - rikorin
 - skaiware
+- smortex
 - ssinai1
 - sssooonnnggg
 - svifylabs

+ 3 - 0
README.md

@@ -116,6 +116,7 @@ Urho3D development, contributions and bugfixes by:
 - Ner'zhul
 - Newb I the Newbd
 - OvermindDL1
+- Polynominal
 - PredatorMF
 - Scellow
 - Skrylar
@@ -145,6 +146,7 @@ Urho3D development, contributions and bugfixes by:
 - marynate
 - meshonline
 - mightyCelu
+- MystMagus
 - neat3d
 - nemerle
 - ninjastone
@@ -157,6 +159,7 @@ Urho3D development, contributions and bugfixes by:
 - rifai
 - rikorin
 - skaiware
+- smortex
 - ssinai1
 - sssooonnnggg
 - svifylabs

+ 1 - 0
Source/Samples/Utilities2D/Sample2D.cpp

@@ -506,6 +506,7 @@ void Sample2D::CreateBackgroundSprite(TileMapInfo2D info, float scale, const Str
     sprite->SetSprite(cache->GetResource<Sprite2D>(texture));
     SetRandomSeed(Time::GetSystemTime()); // Randomize from system clock
     sprite->SetColor(Color(Random(0.0f, 1.0f), Random(0.0f, 1.0f), Random(0.0f, 1.0f), 1.0f));
+    sprite->SetLayer(-99);
 
     // Create rotation animation
     if (animate)

+ 26 - 0
Source/ThirdParty/SLikeNet/CMakeLists.txt

@@ -32,6 +32,32 @@ add_definitions (-D_RAKNET_SUPPORT_FullyConnectedMesh2=1)
 add_definitions (-D_RAKNET_SUPPORT_ReplicaManager3=1)
 add_definitions (-D_RAKNET_SUPPORT_ReadyEvent=1)
 
+# Check specific function availability which may be missing from different MinGW versions
+check_cxx_source_compiles ("#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\nint main() {\n    struct sockaddr_in sa;\n    char str[INET_ADDRSTRLEN];\n    inet_pton(AF_INET, \"192.0.2.33\", &(sa.sin_addr));\n    inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);\n}" INET_FUNCTIONS_EXISTS_1)
+
+set (ORIG_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ws2_32)
+check_cxx_source_compiles ("#include <winsock2.h>\n#include <ws2tcpip.h>\nint main() {\n    struct sockaddr_in sa;\n    char str[INET_ADDRSTRLEN];\n    inet_pton(AF_INET, \"192.0.2.33\", &(sa.sin_addr));\n    inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);\n}" INET_FUNCTIONS_EXISTS_2)
+set (CMAKE_REQUIRED_LIBRARIES ${ORIG_CMAKE_REQUIRED_LIBRARIES})
+
+if (NOT INET_FUNCTIONS_EXISTS_1 AND NOT INET_FUNCTIONS_EXISTS_2 AND NOT HAVE_INET_NTOP)
+    add_definitions(-DINET_FUNCTIONS_MISSING=1)
+endif()
+
+# Check specific function availability which may be missing from different MinGW versions
+check_cxx_source_compiles ("#include <stdio.h>\nint main() { char s[80];\nint x = 1;\nsprintf_s(s, 80, \"Test:%d\", x); }" SPRINTFS_FUNCTION_EXISTS)
+
+if (NOT SPRINTFS_FUNCTION_EXISTS)
+    add_definitions(-DSPRINTFS_FUNCTION_MISSING=1)
+endif()
+
+# Check specific function availability which may be missing from different MinGW versions
+check_cxx_source_compiles ("#include <stdio.h>\nint main() {\nchar s[80];\nint x = 1;\nva_list args = {};\nvsnprintf_s(s, 80, \"Test:%d\", args);}" VSNPRINTFS_FUNCTION_EXISTS)
+
+if (NOT VSNPRINTFS_FUNCTION_EXISTS)
+    add_definitions(-DVSNPRINTFS_FUNCTION_MISSING=1)
+endif()
+
 if (URHO3D_LIB_TYPE STREQUAL SHARED)
     add_definitions(-D_RAKNET_DLL=1)
 endif ()

+ 18 - 9
Source/ThirdParty/SLikeNet/Source/include/slikenet/linux_adapter.h

@@ -9,7 +9,7 @@
  */
 #pragma once
 
-#ifdef __MINGW32__
+#ifdef INET_FUNCTIONS_MISSING
 #include <cstdarg>  // for va_start, va_end, va_list
 #include <cstdio>   // for FILE
 #include <ctime>    // for time_t
@@ -28,14 +28,29 @@ int inet_pton(int af, const char *src, unsigned long *dst);
 
 #endif
 
-#ifdef __linux__
+#if defined(SPRINTFS_FUNCTION_MISSING) || defined(VSNPRINTFS_FUNCTION_MISSING)
+
 #define _TRUNCATE ((size_t)-1)
 typedef int errno_t;
-
 #include <cstdarg>  // for va_start, va_end, va_list
 #include <cstdio>   // for FILE
 #include <ctime>    // for time_t
 
+#endif
+
+#ifdef VSNPRINTFS_FUNCTION_MISSING
+int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr);
+#endif
+
+#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
+template<size_t BufferSize> int vsnprintf_s(char (&buffer)[BufferSize], size_t count, const char *format, va_list argptr)
+{
+    return vsnprintf_s(buffer, BufferSize, count, format, argptr);
+}
+#endif
+
+#ifdef SPRINTFS_FUNCTION_MISSING
+
 // MS specific security enhanced functions
 errno_t fopen_s(FILE **pfile, const char *filename, const char *mode);
 errno_t localtime_s(struct tm* _tm, const time_t *time);
@@ -45,7 +60,6 @@ errno_t strcat_s(char *strDestination, size_t numberOfElements, const char *strS
 errno_t strcpy_s(char* strDestination, size_t numberOfElements, const char *strSource);
 errno_t strncat_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count);
 errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count);
-int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr);
 errno_t wcscat_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource);
 errno_t wcscpy_s(wchar_t* strDestination, size_t numberOfElements, const wchar_t *strSource);
 
@@ -85,11 +99,6 @@ template<size_t BufferSize> errno_t strncpy_s(char(&strDest)[BufferSize], const
     return strncpy_s(strDest, BufferSize, strSource, count);
 }
 
-template<size_t BufferSize> int vsnprintf_s(char (&buffer)[BufferSize], size_t count, const char *format, va_list argptr)
-{
-    return vsnprintf_s(buffer, BufferSize, count, format, argptr);
-}
-
 #endif
 
 

+ 0 - 60
Source/ThirdParty/SLikeNet/Source/include/slikenet/osx_adapter.h

@@ -10,65 +10,5 @@
 #pragma once
 
 #ifdef __APPLE__
-#define _TRUNCATE ((size_t)-1)
-typedef int errno_t;
-
-#include <cstdarg>	// for va_start, va_end, va_list
-#include <cstdio>	// for FILE
-#include <ctime>	// for time_t
-
-// MS specific security enhanced functions
-errno_t fopen_s(FILE **pfile, const char *filename, const char *mode);
-errno_t localtime_s(struct tm* _tm, const time_t *time);
-errno_t mbstowcs_s(size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count);
-int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...);
-errno_t strcat_s(char *strDestination, size_t numberOfElements, const char *strSource);
-errno_t strcpy_s(char* strDestination, size_t numberOfElements, const char *strSource);
-errno_t strncat_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count);
-errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count);
-int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr);
-errno_t wcscat_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource);
-errno_t wcscpy_s(wchar_t* strDestination, size_t numberOfElements, const wchar_t *strSource);
-
-// corresponding template overloads
-template<size_t BufferSize> errno_t mbstowcs_s(size_t *pReturnValue, wchar_t(&wcstr)[BufferSize], const char *mbstr, size_t count)
-{
-	return mbstowcs_s(pReturnValue, wcstr, BufferSize, mbstr, count);
-}
-
-template<size_t BufferSize> int sprintf_s(char (&buffer)[BufferSize], const char* format, ...)
-{
-	va_list arglist;
-	va_start(arglist, format);
-	int numCharsWritten = vsnprintf_s(buffer, BufferSize, BufferSize - 1, format, arglist);
-	va_end(arglist);
-
-	return numCharsWritten;
-}
-
-template<size_t BufferSize> errno_t strcat_s(char (&strDestination)[BufferSize], const char* strSource)
-{
-	return strcat_s(strDestination, BufferSize, strSource);
-}
-
-template<size_t BufferSize> errno_t strcpy_s(char (&strDestination)[BufferSize], const char* strSource)
-{
-	return strcpy_s(strDestination, BufferSize, strSource);
-}
-
-template<size_t BufferSize> errno_t strncat_s(char(&strDest)[BufferSize], const char *strSource, size_t count)
-{
-	return strncat_s(strDest, BufferSize, strSource, count);
-}
-
-template<size_t BufferSize> errno_t strncpy_s(char(&strDest)[BufferSize], const char *strSource, size_t count)
-{
-	return strncpy_s(strDest, BufferSize, strSource, count);
-}
-
-template<size_t BufferSize> int vsnprintf_s(char (&buffer)[BufferSize], size_t count, const char *format, va_list argptr)
-{
-	return vsnprintf_s(buffer, BufferSize, count, format, argptr);
-}
 
 #endif

+ 33 - 31
Source/ThirdParty/SLikeNet/Source/src/linux_adapter.cpp

@@ -8,9 +8,10 @@
  *  This file defines adapters for all MS-specific functions used throughout SLikeNet.
  */
 
-#ifdef __linux__
 #include "slikenet/linux_adapter.h"
 
+#ifdef SPRINTFS_FUNCTION_MISSING
+
 #include <algorithm>	// for std::max, std::min
 #include <cerrno>		// for errno
 #include <cstdio>		// for FILE, fopen, vsnprintf
@@ -242,35 +243,6 @@ errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource,
 	return truncated ? 80 : 0; // STRUNCATE, if we truncated the string, 0 otherwise
 }
 
-int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr)
-{
-	if ((buffer == nullptr) || (format == nullptr) || (sizeOfBuffer == 0)) {
-		return -1;
-	}
-
-	size_t maxChars = sizeOfBuffer;
-	if (count != _TRUNCATE) {
-		if (count >= sizeOfBuffer) {
-			buffer[0] = '\0'; // ensure trailing \0 is written
-			return -1;
-		}
-		maxChars = count;
-	}
-
-	int numCharsWritten = vsnprintf(buffer, maxChars, format, argptr);
-	if (numCharsWritten >= maxChars) {
-		if (count != _TRUNCATE) {
-			buffer[0] = '\0'; // buffer set to empty string
-			return -1;
-		}
-
-		// truncation occurred, add terminating \0
-		buffer[sizeOfBuffer] = '\0';
-	}
-
-	return numCharsWritten;
-}
-
 errno_t wcscat_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource)
 {
 	if ((strDestination == nullptr) || (strSource == nullptr)) {
@@ -316,8 +288,38 @@ errno_t wcscpy_s(wchar_t* strDestination, size_t numberOfElements, const wchar_t
 
 #endif
 
+#ifdef VSNPRINTFS_FUNCTION_MISSING
+int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr)
+{
+	if ((buffer == nullptr) || (format == nullptr) || (sizeOfBuffer == 0)) {
+		return -1;
+	}
+
+	size_t maxChars = sizeOfBuffer;
+	if (count != _TRUNCATE) {
+		if (count >= sizeOfBuffer) {
+			buffer[0] = '\0'; // ensure trailing \0 is written
+			return -1;
+		}
+		maxChars = count;
+	}
+
+	int numCharsWritten = vsnprintf(buffer, maxChars, format, argptr);
+	if (numCharsWritten >= maxChars) {
+		if (count != _TRUNCATE) {
+			buffer[0] = '\0'; // buffer set to empty string
+			return -1;
+		}
+
+		// truncation occurred, add terminating \0
+		buffer[sizeOfBuffer] = '\0';
+	}
+
+	return numCharsWritten;
+}
+#endif
 
-#ifdef __MINGW32__
+#ifdef INET_FUNCTIONS_MISSING
 #include <cstdarg>  // for va_start, va_end, va_list
 #include <cstdio>   // for FILE
 #include <ctime>    // for time_t

+ 0 - 303
Source/ThirdParty/SLikeNet/Source/src/osx_adapter.cpp

@@ -11,307 +11,4 @@
 #ifdef __APPLE__
 #include "slikenet/osx_adapter.h"
 
-#include <algorithm>	// for std::max, std::min
-#include <cerrno>		// for errno
-#include <cstdio>		// for FILE, fopen, vsnprintf
-#include <cstdlib>		// for mbstowcs
-#include <cstring>		// for strcat, strcpy, strncat, strncpy
-#include <cstdarg>		// for va_start, va_end, va_list
-#include <ctime>		// for localtime, time_t
-#include <cwchar>		// for wcscat, wcscpy, wcslen
-
-errno_t fopen_s(FILE **pfile, const char *filename, const char *mode)
-{
-	if ((pfile == nullptr) || (filename == nullptr) || (mode == nullptr)) {
-		return 22; // error: EINVAL
-	}
-
-	FILE *file = fopen(filename, mode);
-	if (file == nullptr) {
-		return errno;
-	}
-
-	*pfile = file;
-	return 0;
-}
-
-errno_t localtime_s(struct tm *_tm, const time_t *time)
-{
-	// #med - should actually also check for _*time > _MAX_TIME64_T according to MSDN, but can't seem to find the
-	// definition of _MAX_TIME64_T
-	if ((_tm == nullptr) || (time == nullptr) || (*time == 0)) {
-		if (_tm != nullptr) {
-			_tm->tm_hour  = -1;
-			_tm->tm_isdst = -1;
-			_tm->tm_mday  = -1;
-			_tm->tm_min   = -1;
-			_tm->tm_mon   = -1;
-			_tm->tm_sec   = -1;
-			_tm->tm_wday  = -1;
-			_tm->tm_yday  = -1;
-			_tm->tm_year  = -1;
-		}
-		return 22; // error: EINVAL
-	}
-
-	struct tm *curTime = localtime(time);
-	*_tm = *curTime;
-
-	return 0;
-}
-
-errno_t mbstowcs_s(size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count)
-{
-	if ((mbstr == nullptr) || ((wcstr == nullptr) && (sizeInWords > 0)) || ((wcstr != nullptr) && (sizeInWords != 0))) {
-		if (wcstr != nullptr) {
-			wcstr[0] = L'\0'; // ensure 0-termination
-		}
-		return 22; // error: EINVAL
-	}
-
-	size_t numMaxChars = sizeInWords;
-	if (count != _TRUNCATE) {
-		numMaxChars = std::min(numMaxChars, count);
-	}
-
-	size_t numCharsWritten = mbstowcs(wcstr, mbstr, numMaxChars);
-	if (numCharsWritten == (size_t)-1) {
-		// invalid multibyte character encountered
-		if (pReturnValue != nullptr) {
-			*pReturnValue = 0;
-		}
-		if (wcstr != nullptr) {
-			wcstr[0] = L'\0'; // ensure 0-termination
-		}
-		return 42; // error: EILSEQ
-	}
-
-	if (numCharsWritten == numMaxChars) {
-		if (wcstr != nullptr) {
-			wcstr[0] = L'\0'; // ensure 0-termination
-		}
-		return 34; // error: ERANGE
-	}
-
-	if (pReturnValue != nullptr) {
-		*pReturnValue = numCharsWritten + 1; // chars written, including terminating null character
-	}
-
-	// ensure we write a terminating null character (in case there was none in the original converted string)
-	if (wcstr != nullptr) {
-		wcstr[numCharsWritten] = L'\0'; // ensure 0-termination
-	}
-
-	return 0;
-}
-
-int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
-{
-	if ((buffer == nullptr) || (sizeOfBuffer == 0) || (format == nullptr)) {
-		return -1;
-	}
-
-	va_list arglist;
-	va_start(arglist, format);
-	int numCharsWritten = vsnprintf(buffer, sizeOfBuffer, format, arglist);
-	va_end(arglist);
-
-	if (numCharsWritten == -1) {
-		buffer[0] = '\0'; // error occurred ensure terminating \0-character
-		return -1;
-	}
-
-	if (numCharsWritten >= sizeOfBuffer) {
-		buffer[0] = '\0'; // buffer too small, write empty string to ensure terminating \0-char
-	}
-
-	return numCharsWritten;
-}
-
-errno_t strcat_s(char *strDestination, size_t numberOfElements, const char *strSource)
-{
-	if ((strDestination == nullptr) || (strSource == nullptr)) {
-		if (strDestination != nullptr) {
-			strDestination[0] = '\0'; // ensure trailing \0 is written
-		}
-		return 22; // error: EINVAL
-	}
-
-	if (numberOfElements == 0) {
-		strDestination[0] = '\0'; // ensure trailing \0 is written
-		return 34; // error: ERANGE
-	}
-
-	const size_t destLen = strlen(strDestination);
-	const size_t sourceLen = strlen(strSource);
-	if ((destLen > numberOfElements - 1) || ((sourceLen > 0) && (destLen == numberOfElements - 1)) || (sourceLen > numberOfElements - destLen - 1)) {
-		strDestination[0] = '\0'; // ensure trailing \0 is written
-		return 34; // error: ERANGE
-	}
-
-	(void)strcat(strDestination, strSource);
-	return 0;
-}
-
-errno_t strcpy_s(char* strDestination, size_t numberOfElements, const char *strSource)
-{
-	if ((strDestination == nullptr) || (strSource == nullptr)) {
-		if (strDestination != nullptr) {
-			strDestination[0] = '\0'; // ensure trailing \0 is written
-		}
-		return 22; // error: EINVAL
-	}
-
-	if ((numberOfElements == 0) || (strlen(strSource) >= numberOfElements)) {
-		strDestination[0] = '\0'; // ensure trailing \0 is written
-		return 34; // error: ERANGE
-	}
-
-	(void)strcpy(strDestination, strSource);
-	return 0;
-}
-
-errno_t strncat_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
-{
-	// check valid parameters
-	if ((strDest == nullptr) || (strSource == nullptr)) {
-		return 22; // error: EINVAL
-	}
-
-	if (numberOfElements == 0) {
-		return 34; // error: ERANGE
-	}
-
-	size_t charsToWrite;
-	const size_t sourceLen = strlen(strSource);
-	if (count == _TRUNCATE) {
-		charsToWrite = sourceLen;
-	}
-	else {
-		charsToWrite = std::min(count, sourceLen);
-	}
-
-	const size_t destLen = strlen(strDest);
-	const size_t sizeLeft = numberOfElements - destLen;
-
-	if (((count != _TRUNCATE) && (charsToWrite > sizeLeft - 1)) || ((sourceLen > 0) && (destLen == numberOfElements - 1))) {
-		strDest[0] = '\0'; // ensure trailing \0 is written
-		return 34; // error: ERANGE
-	}
-
-	(void)strncat(strDest, strSource, charsToWrite);
-	return 0;
-}
-
-errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
-{
-	// check valid parameters
-	if ((numberOfElements == 0) || (strDest == nullptr) || (strSource == nullptr)) {
-		if (strDest != nullptr) {
-			strDest[0] = '\0'; // ensure trailing \0 is written
-		}
-		return 22; // error: EINVAL
-	}
-
-	size_t numChars;
-	bool truncated = false;
-	if (count == _TRUNCATE) {
-		// if count == _TRUNCATE use the length of the source string
-		numChars = strlen(strSource);
-
-		// ensure we are not exceeding numberOfElements
-		if (numChars >= numberOfElements) {
-			numChars = numberOfElements - 1;
-			truncated = true; // we are going to truncate the copied string
-		}
-	}
-	else {
-		// otherwise we use count, but have to check that the destination buffer is of sufficient size
-		if ((count > numberOfElements) || ((count == numberOfElements) && (strSource[count] != '\0'))) {
-			strDest[0] = '\0'; // ensure trailing \0 is written
-			return 34; // error: ERANGE
-		}
-		numChars = count;
-	}
-
-	(void)strncpy(strDest, strSource, numChars);
-
-	// enforce the trailing \0
-	strDest[numChars] = '\0';
-
-	return truncated ? 80 : 0; // STRUNCATE, if we truncated the string, 0 otherwise
-}
-
-int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr)
-{
-	if ((buffer == nullptr) || (format == nullptr) || (sizeOfBuffer == 0)) {
-		return -1;
-	}
-
-	size_t maxChars = sizeOfBuffer;
-	if (count != _TRUNCATE) {
-		if (count >= sizeOfBuffer) {
-			buffer[0] = '\0'; // ensure trailing \0 is written
-			return -1;
-		}
-		maxChars = count;
-	}
-
-	int numCharsWritten = vsnprintf(buffer, maxChars, format, argptr);
-	if (numCharsWritten >= maxChars) {
-		if (count != _TRUNCATE) {
-			buffer[0] = '\0'; // buffer set to empty string
-			return -1;
-		}
-
-		// truncation occurred, add terminating \0
-		buffer[sizeOfBuffer] = '\0';
-	}
-
-	return numCharsWritten;
-}
-
-errno_t wcscat_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource)
-{
-	if ((strDestination == nullptr) || (strSource == nullptr)) {
-		if (strDestination != nullptr) {
-			strDestination[0] = L'\0'; // ensure trailing \0 is written
-		}
-		return 22; // error: EINVAL
-	}
-
-	if (numberOfElements == 0) {
-		strDestination[0] = L'\0'; // ensure trailing \0 is written
-		return 34; // error: ERANGE
-	}
-
-	const size_t destLen = wcslen(strDestination);
-	const size_t sourceLen = wcslen(strSource);
-	if ((destLen > numberOfElements - 1) || ((sourceLen > 0) && (destLen == numberOfElements)) || (sourceLen > numberOfElements - destLen - 1)) {
-		strDestination[0] = L'\0'; // ensure trailing \0 is written
-		return 34; // error: ERANGE
-	}
-
-	(void)wcscat(strDestination, strSource);
-	return 0;
-}
-
-errno_t wcscpy_s(wchar_t* strDestination, size_t numberOfElements, const wchar_t *strSource)
-{
-	if ((strDestination == nullptr) || (strSource == nullptr)) {
-		if (strDestination != nullptr) {
-			strDestination[0] = L'\0'; // ensure trailing \0 is written
-		}
-		return 22; // error: EINVAL
-	}
-
-	if ((numberOfElements == 0) || (wcslen(strSource) >= numberOfElements)) {
-		strDestination[0] = L'\0'; // ensure trailing \0 is written
-		return 34; // error: ERANGE
-	}
-
-	(void)wcscpy(strDestination, strSource);
-	return 0;
-}
-
 #endif

+ 3 - 2
Source/ThirdParty/StanHull/hull.cpp

@@ -34,7 +34,7 @@
 		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -----------------------------------------------------------------------*/
 
-// Modified by Lasse Oorni for Urho3D
+// Modified by Lasse Oorni and Romain Tartière for Urho3D
 
 // Urho3D: use a namespace to not clash with Urho3D's inbuilt math types
 namespace StanHull
@@ -2587,7 +2587,8 @@ int overhull(Plane *planes,int planes_count,float3 *verts, int verts_count,int m
 			 float3 *&verts_out, int &verts_count_out,  int *&faces_out, int &faces_count_out ,float inflate)
 {
 	int i,j;
-	if(verts_count <4) return NULL;
+	// Urho3D: Return 0, not NULL, in function returning an int
+	if(verts_count <4) return 0;
 	maxplanes = Min(maxplanes,planes_count);
 	float3 bmin(verts[0]),bmax(verts[0]);
 	for(i=0;i<verts_count;i++) 

+ 1 - 1
Source/ThirdParty/ik/src/util.c

@@ -16,7 +16,7 @@ calculate_rotation_weight_decays_recursive(chain_t* chain)
 {
     int average_count;
     int node_idx, node_count;
-    effector_data_t effector_data;
+    effector_data_t effector_data = {0.0, 0.0};
 
     /*
      * Find the rotation weight of this chain's last node by averaging the

+ 1 - 1
Source/Urho3D/.soversion

@@ -1 +1 @@
-0.1.120
+0.1.124

+ 2 - 0
Source/Urho3D/AngelScript/APITemplates.h

@@ -1311,6 +1311,8 @@ template <class T> void RegisterBorderImage(asIScriptEngine* engine, const char*
     engine->RegisterObjectMethod(className, "void SetHoverOffset(int, int)", asMETHODPR(T, SetHoverOffset, (int, int), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_texture(Texture@+)", asMETHOD(T, SetTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "Texture@+ get_texture() const", asMETHOD(T, GetTexture), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_material(Material@+)", asMETHOD(T, SetMaterial), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "Material@+ get_material() const", asMETHOD(T, GetMaterial), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_imageRect(const IntRect&in)", asMETHODPR(T, SetImageRect, (const IntRect&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "const IntRect& get_imageRect() const", asMETHOD(T, GetImageRect), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_border(const IntRect&in)", asMETHODPR(T, SetBorder, (const IntRect&), void), asCALL_THISCALL);

+ 8 - 8
Source/Urho3D/AngelScript/ResourceAPI.cpp

@@ -396,14 +396,14 @@ static void RegisterJSONValue(asIScriptEngine* engine)
     engine->RegisterObjectMethod("JSONValue", "bool get_isArray() const", asMETHOD(JSONValue, IsArray), asCALL_THISCALL);
     engine->RegisterObjectMethod("JSONValue", "bool get_isObject() const", asMETHOD(JSONValue, IsObject), asCALL_THISCALL);
 
-    engine->RegisterObjectMethod("JSONValue", "bool GetBool() const", asMETHOD(JSONValue, GetBool), asCALL_THISCALL);
-    engine->RegisterObjectMethod("JSONValue", "int GetInt() const", asMETHOD(JSONValue, GetInt), asCALL_THISCALL);
-    engine->RegisterObjectMethod("JSONValue", "uint GetUInt() const", asMETHOD(JSONValue, GetUInt), asCALL_THISCALL);
-    engine->RegisterObjectMethod("JSONValue", "float GetFloat() const", asMETHOD(JSONValue, GetFloat), asCALL_THISCALL);
-    engine->RegisterObjectMethod("JSONValue", "double GetDouble() const", asMETHOD(JSONValue, GetDouble), asCALL_THISCALL);
-    engine->RegisterObjectMethod("JSONValue", "const String& GetString() const", asMETHOD(JSONValue, GetString), asCALL_THISCALL);
-    engine->RegisterObjectMethod("JSONValue", "Variant GetVariant() const", asMETHOD(JSONValue, GetVariant), asCALL_THISCALL);
-    engine->RegisterObjectMethod("JSONValue", "VariantMap GetVariantMap() const", asMETHOD(JSONValue, GetVariantMap), asCALL_THISCALL);
+    engine->RegisterObjectMethod("JSONValue", "bool GetBool(bool defaultValue = false) const", asMETHOD(JSONValue, GetBool), asCALL_THISCALL);
+    engine->RegisterObjectMethod("JSONValue", "int GetInt(int defaultValue = 0) const", asMETHOD(JSONValue, GetInt), asCALL_THISCALL);
+    engine->RegisterObjectMethod("JSONValue", "uint GetUInt(uint defaultValue = 0) const", asMETHOD(JSONValue, GetUInt), asCALL_THISCALL);
+    engine->RegisterObjectMethod("JSONValue", "float GetFloat(float defaultValue = 0) const", asMETHOD(JSONValue, GetFloat), asCALL_THISCALL);
+    engine->RegisterObjectMethod("JSONValue", "double GetDouble(double defaultValue = 0) const", asMETHOD(JSONValue, GetDouble), asCALL_THISCALL);
+    engine->RegisterObjectMethod("JSONValue", "const String& GetString(const String& defaultValue = String(\"\")) const", asMETHOD(JSONValue, GetString), asCALL_THISCALL);
+    engine->RegisterObjectMethod("JSONValue", "Variant GetVariant(Variant defaultValue = Variant()) const", asMETHOD(JSONValue, GetVariant), asCALL_THISCALL);
+    engine->RegisterObjectMethod("JSONValue", "VariantMap GetVariantMap(VariantMap defaultValue = VariantMap()) const", asMETHOD(JSONValue, GetVariantMap), asCALL_THISCALL);
 
     engine->RegisterObjectMethod("JSONValue", "JSONValue& opIndex(uint)", asFUNCTION(JSONValueAtPosition), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("JSONValue", "const JSONValue& opIndex(uint) const", asFUNCTION(JSONValueAtPosition), asCALL_CDECL_OBJLAST);

+ 2 - 0
Source/Urho3D/AngelScript/UIAPI.cpp

@@ -654,6 +654,8 @@ static void RegisterFileSelector(asIScriptEngine* engine)
 static void RegisterToolTip(asIScriptEngine* engine)
 {
     RegisterUIElement<ToolTip>(engine, "ToolTip");
+    engine->RegisterObjectMethod("ToolTip", "void Reset()", asMETHOD(ToolTip, Reset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ToolTip", "void add_altTarget(UIElement@+)", asMETHOD(ToolTip, AddAltTarget), asCALL_THISCALL);
     engine->RegisterObjectMethod("ToolTip", "void set_delay(float)", asMETHOD(ToolTip, SetDelay), asCALL_THISCALL);
     engine->RegisterObjectMethod("ToolTip", "float get_delay() const", asMETHOD(ToolTip, GetDelay), asCALL_THISCALL);
 }

+ 5 - 0
Source/Urho3D/CMakeLists.txt

@@ -31,6 +31,11 @@ if (MINGW AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.1 AND NOT URHO3D_64BIT
     set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mpreferred-stack-boundary=2")
 endif ()
 
+check_include_files (stdint.h HAVE_STDINT_H)
+if (HAVE_STDINT_H)
+  add_definitions (-DHAVE_STDINT_H)
+endif ()
+
 # Generate JSON compilation database format specification
 if (URHO3D_CLANG_TOOLS OR URHO3D_BINDINGS)
     set (CMAKE_EXPORT_COMPILE_COMMANDS 1)

+ 1 - 1
Source/Urho3D/Core/Context.cpp

@@ -298,7 +298,7 @@ void Context::ReleaseSDL()
 #ifdef URHO3D_IK
 void Context::RequireIK()
 {
-    // Always increment, the caller must match with ReleaseSDL(), regardless of
+    // Always increment, the caller must match with ReleaseIK(), regardless of
     // what happens.
     ++ikInitCounter;
 

+ 1 - 1
Source/Urho3D/IO/Log.h

@@ -150,7 +150,7 @@ private:
 #define URHO3D_LOGWARNING(message) ((void)0)
 #define URHO3D_LOGERROR(message) ((void)0)
 #define URHO3D_LOGRAW(message) ((void)0)
-#define URHO3D_LOGTRACEF(message) ((void)0)
+#define URHO3D_LOGTRACEF(...) ((void)0)
 #define URHO3D_LOGDEBUGF(...) ((void)0)
 #define URHO3D_LOGINFOF(...) ((void)0)
 #define URHO3D_LOGWARNINGF(...) ((void)0)

+ 2 - 1
Source/Urho3D/LuaScript/pkgs/Graphics/AnimationState.pkg

@@ -23,7 +23,8 @@ class AnimationState
     void AddTime(float delta);
     void SetLayer(unsigned char layer);
     void SetBlendMode(AnimationBlendMode mode);
-
+    void Apply();
+    
     Animation* GetAnimation() const;
     Bone* GetStartBone() const;
     float GetBoneWeight(const String name) const;

+ 6 - 6
Source/Urho3D/LuaScript/pkgs/Resource/JSONValue.pkg

@@ -51,12 +51,12 @@ class JSONValue
     bool IsArray() const;
     bool IsObject() const;
 
-    bool GetBool() const;
-    int GetInt() const;
-    unsigned GetUInt() const;
-    float GetFloat() const;
-    double GetDouble() const;
-    const String GetString() const;
+    bool GetBool(bool defaultValue = false) const;
+    int GetInt(int defaultValue = 0) const;
+    unsigned GetUInt(unsigned defaultValue = 0) const;
+    float GetFloat(float defaultValue = 0) const;
+    double GetDouble(double defaultValue = 0) const;
+    const String GetString(const String& defaultValue = String("")) const;
     const JSONArray& GetArray() const;
     const JSONObject& GetObject() const;
     Variant GetVariant() const;

+ 4 - 0
Source/Urho3D/LuaScript/pkgs/UI/ToolTip.pkg

@@ -5,6 +5,10 @@ class ToolTip : public UIElement
     ToolTip();
     virtual ~ToolTip();
 
+    void Reset();
+
+    void AddAltTarget(UIElement* target);
+
     void SetDelay(float delay);
     
     float GetDelay() const;

+ 17 - 7
Source/Urho3D/Network/Network.cpp

@@ -486,13 +486,7 @@ bool Network::Connect(const String& address, unsigned short port, Scene* scene,
 
     //isServer_ = false;
     SLNet::ConnectionAttemptResult connectResult = rakPeerClient_->Connect(address.CString(), port, password_.CString(), password_.Length());
-    if (connectResult != SLNet::CONNECTION_ATTEMPT_STARTED)
-    {
-        URHO3D_LOGERROR("Failed to connect to server " + address + ":" + String(port) + ", error code: " + String((int)connectResult));
-        SendEvent(E_CONNECTFAILED);
-        return false;
-    }
-    else
+    if (connectResult == SLNet::CONNECTION_ATTEMPT_STARTED)
     {
         serverConnection_ = new Connection(context_, false, rakPeerClient_->GetMyGUID(), rakPeerClient_);
         serverConnection_->SetScene(scene);
@@ -503,6 +497,22 @@ bool Network::Connect(const String& address, unsigned short port, Scene* scene,
         URHO3D_LOGINFO("Connecting to server " + address + ":" + String(port) + ", Client: " + serverConnection_->ToString());
         return true;
     }
+    else if (connectResult == SLNet::ALREADY_CONNECTED_TO_ENDPOINT) {
+        URHO3D_LOGWARNING("Already connected to server!");
+        SendEvent(E_CONNECTIONINPROGRESS);
+        return false;
+    }
+    else if (connectResult == SLNet::CONNECTION_ATTEMPT_ALREADY_IN_PROGRESS) {
+        URHO3D_LOGWARNING("Connection attempt already in progress!");
+        SendEvent(E_CONNECTIONINPROGRESS);
+        return false;
+    }
+    else
+    {
+        URHO3D_LOGERROR("Failed to connect to server " + address + ":" + String(port) + ", error code: " + String((int)connectResult));
+        SendEvent(E_CONNECTFAILED);
+        return false;
+    }
 }
 
 bool Network::ConnectNAT(const String& address, unsigned short port)

+ 5 - 0
Source/Urho3D/Network/NetworkEvents.h

@@ -42,6 +42,11 @@ URHO3D_EVENT(E_CONNECTFAILED, ConnectFailed)
 {
 }
 
+/// Server connection failed because its already connected or tries to connect already.
+URHO3D_EVENT(E_CONNECTIONINPROGRESS, ConnectionInProgress)
+{
+}
+
 /// New client connection established.
 URHO3D_EVENT(E_CLIENTCONNECTED, ClientConnected)
 {

+ 7 - 7
Source/Urho3D/Resource/JSONValue.h

@@ -187,19 +187,19 @@ public:
     bool IsObject() const { return GetValueType() == JSON_OBJECT; }
 
     /// Return boolean value.
-    bool GetBool() const { return IsBool() ? boolValue_ : false;}
+    bool GetBool(bool defaultValue = false) const { return IsBool() ? boolValue_ : defaultValue;}
     /// Return integer value.
-    int GetInt() const { return IsNumber() ? (int)numberValue_ : 0; }
+    int GetInt(int defaultValue = 0) const { return IsNumber() ? (int)numberValue_ : defaultValue; }
     /// Return unsigned integer value.
-    unsigned GetUInt() const { return IsNumber() ? (unsigned)numberValue_ : 0; }
+    unsigned GetUInt(unsigned defaultValue = 0) const { return IsNumber() ? (unsigned)numberValue_ : defaultValue; }
     /// Return float value.
-    float GetFloat() const { return IsNumber() ? (float)numberValue_ : 0.0f; }
+    float GetFloat(float defaultValue = 0.0f) const { return IsNumber() ? (float)numberValue_ : defaultValue; }
     /// Return double value.
-    double GetDouble() const { return IsNumber() ? numberValue_ : 0.0; }
+    double GetDouble(double defaultValue = 0.0) const { return IsNumber() ? numberValue_ : defaultValue; }
     /// Return string value.
-    const String& GetString() const { return IsString() ? *stringValue_ : String::EMPTY;}
+    const String& GetString(String defaultValue = String::EMPTY) const { return IsString() ? *stringValue_ : defaultValue;}
     /// Return C string value.
-    const char* GetCString() const { return IsString() ? stringValue_->CString() : nullptr;}
+    const char* GetCString(const char* defaultValue = nullptr) const { return IsString() ? stringValue_->CString() : defaultValue;}
     /// Return JSON array value.
     const JSONArray& GetArray() const { return IsArray() ? *arrayValue_ : emptyArray; }
     /// Return JSON object value.

+ 26 - 0
Source/Urho3D/UI/BorderImage.cpp

@@ -61,6 +61,8 @@ void BorderImage::RegisterObject(Context* context)
     URHO3D_ACCESSOR_ATTRIBUTE("Hover Image Offset", GetHoverOffset, SetHoverOffset, IntVector2, IntVector2::ZERO, AM_FILE);
     URHO3D_ACCESSOR_ATTRIBUTE("Tiled", IsTiled, SetTiled, bool, false, AM_FILE);
     URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, 0, AM_FILE);
+    URHO3D_MIXED_ACCESSOR_ATTRIBUTE("Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()),
+        AM_FILE);
 }
 
 void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
@@ -134,6 +136,9 @@ void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vert
     UIBatch
         batch(this, blendMode_ == BLEND_REPLACE && !allOpaque ? BLEND_ALPHA : blendMode_, currentScissor, texture_, &vertexData);
 
+    if (material_)
+        batch.custom_material_ = material_;
+
     // Calculate size of the inner rect, and texture dimensions of the inner rect
     const IntRect& uvBorder = (imageBorder_ == IntRect::ZERO) ? border_ : imageBorder_;
     int x = GetIndentWidth();
@@ -208,4 +213,25 @@ ResourceRef BorderImage::GetTextureAttr() const
     return GetResourceRef(texture_, Texture2D::GetTypeStatic());
 }
 
+void BorderImage::SetMaterialAttr(const ResourceRef& value)
+{
+    auto* cache = GetSubsystem<ResourceCache>();
+    SetMaterial(cache->GetResource<Material>(value.name_));
+}
+
+ResourceRef BorderImage::GetMaterialAttr() const
+{
+    return GetResourceRef(material_, Material::GetTypeStatic());
+}
+
+void BorderImage::SetMaterial(Material* material)
+{
+    material_ = material;
+}
+
+Material* BorderImage::GetMaterial() const
+{
+    return material_;
+}
+
 }

+ 11 - 0
Source/Urho3D/UI/BorderImage.h

@@ -65,6 +65,8 @@ public:
     void SetBlendMode(BlendMode mode);
     /// Set tiled mode.
     void SetTiled(bool enable);
+    /// Set material for custom rendering.
+    void SetMaterial(Material* material);
 
     /// Return texture.
     Texture* GetTexture() const { return texture_; }
@@ -87,11 +89,18 @@ public:
     /// Return whether is tiled.
     bool IsTiled() const { return tiled_; }
 
+    /// Get material used for custom rendering.
+    Material* GetMaterial() const;
+
     /// Set texture attribute.
     void SetTextureAttr(const ResourceRef& value);
     /// Return texture attribute.
     ResourceRef GetTextureAttr() const;
 
+    /// Set material attribute.
+    void SetMaterialAttr(const ResourceRef& value);
+    /// Get material attribute.
+    ResourceRef GetMaterialAttr() const;
 protected:
     /// Return UI rendering batches with offset to image rectangle.
     void GetBatches
@@ -111,6 +120,8 @@ protected:
     BlendMode blendMode_;
     /// Tiled flag.
     bool tiled_;
+    /// Material used for custom rendering.
+    SharedPtr<Material> material_;
 };
 
 }

+ 37 - 12
Source/Urho3D/UI/ToolTip.cpp

@@ -34,7 +34,7 @@ extern const char* UI_CATEGORY;
 ToolTip::ToolTip(Context* context) :
     UIElement(context),
     delay_(0.0f),
-    parentHovered_(false)
+    hovered_(false)
 {
     SetVisible(false);
 }
@@ -66,13 +66,28 @@ void ToolTip::Update(float timeStep)
         return;
     }
 
-    if (target_->IsHovering() && target_->IsVisibleEffective())
+    bool hovering = target_->IsHovering() && target_->IsVisibleEffective();
+    if (!hovering)
+    {
+        for (auto it = altTargets_.Begin(); it != altTargets_.End();)
+        {
+            SharedPtr<UIElement> target = it->Lock();
+            if (!target)
+                it = altTargets_.Erase(it);
+            else if (hovering = target->IsHovering() && target->IsVisibleEffective())
+                break;
+            else
+                ++it;
+        }
+    }
+
+    if (hovering)
     {
         float effectiveDelay = delay_ > 0.0f ? delay_ : GetSubsystem<UI>()->GetDefaultToolTipDelay();
 
-        if (!parentHovered_)
+        if (!hovered_)
         {
-            parentHovered_ = true;
+            hovered_ = true;
             displayAt_.Reset();
         }
         else if (displayAt_.GetMSec(false) >= (unsigned)(effectiveDelay * 1000.0f) && parent_ == target_)
@@ -89,17 +104,27 @@ void ToolTip::Update(float timeStep)
     }
     else
     {
-        if (IsVisible() && parent_ == root)
-        {
-            SetParent(target_);
-            SetPosition(originalPosition_);
-            SetVisible(false);
-        }
-        parentHovered_ = false;
-        displayAt_.Reset();
+        Reset();
     }
 }
 
+void ToolTip::Reset()
+{
+    if (IsVisible() && parent_ == GetRoot())
+    {
+        SetParent(target_);
+        SetPosition(originalPosition_);
+        SetVisible(false);
+    }
+    hovered_ = false;
+    displayAt_.Reset();
+}
+
+void ToolTip::AddAltTarget(UIElement* target)
+{
+    altTargets_.Push(WeakPtr<UIElement>(target));
+}
+
 void ToolTip::SetDelay(float delay)
 {
     delay_ = delay;

+ 10 - 2
Source/Urho3D/UI/ToolTip.h

@@ -44,6 +44,12 @@ public:
     /// Perform UI element update.
     void Update(float timeStep) override;
 
+    /// Hide tooltip if visible and reset parentage.
+    void Reset();
+
+    /// Add an alternative hover target.
+    void AddAltTarget(UIElement* target);
+
     /// Set the delay in seconds until the tooltip shows once hovering. Set zero to use the default from the UI subsystem.
     void SetDelay(float delay);
 
@@ -53,10 +59,12 @@ public:
 private:
     /// The element that is being tracked for hovering. Normally the parent element.
     WeakPtr<UIElement> target_;
+    /// Alternative targets. Primarily targets parent.
+    Vector<WeakPtr<UIElement> > altTargets_;
     /// Delay from hover start to displaying the tooltip.
     float delay_;
-    /// Point at which the parent was hovered.
-    bool parentHovered_;
+    /// Hover countdown has started.
+    bool hovered_;
     /// Point at which the tooltip was set visible.
     Timer displayAt_;
     /// Original offset position to the parent.

+ 68 - 14
Source/Urho3D/UI/UI.cpp

@@ -35,6 +35,7 @@
 #include "../Graphics/Octree.h"
 #include "../Graphics/Viewport.h"
 #include "../Graphics/Camera.h"
+#include "../Graphics/Technique.h"
 #include "../Scene/Scene.h"
 #include "../Input/Input.h"
 #include "../Input/InputEvents.h"
@@ -1040,22 +1041,44 @@ void UI::Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigne
         ShaderVariation* ps;
         ShaderVariation* vs;
 
-        if (!batch.texture_)
+        if (!batch.custom_material_)
         {
-            ps = noTexturePS;
-            vs = noTextureVS;
-        }
-        else
+            if (!batch.texture_)
+            {
+                ps = noTexturePS;
+                vs = noTextureVS;
+            } else
+            {
+                // If texture contains only an alpha channel, use alpha shader (for fonts)
+                vs = diffTextureVS;
+
+                if (batch.texture_->GetFormat() == alphaFormat)
+                    ps = alphaTexturePS;
+                else if (batch.blendMode_ != BLEND_ALPHA && batch.blendMode_ != BLEND_ADDALPHA && batch.blendMode_ != BLEND_PREMULALPHA)
+                    ps = diffMaskTexturePS;
+                else
+                    ps = diffTexturePS;
+            }
+        } else
         {
-            // If texture contains only an alpha channel, use alpha shader (for fonts)
-            vs = diffTextureVS;
+            vs = diffTextureVS;
+            ps = diffTexturePS;
 
-            if (batch.texture_->GetFormat() == alphaFormat)
-                ps = alphaTexturePS;
-            else if (batch.blendMode_ != BLEND_ALPHA && batch.blendMode_ != BLEND_ADDALPHA && batch.blendMode_ != BLEND_PREMULALPHA)
-                ps = diffMaskTexturePS;
-            else
-                ps = diffTexturePS;
+            Technique* technique = batch.custom_material_->GetTechnique(0);
+            if (technique)
+            {
+                Pass* pass = nullptr;
+                for (int i = 0; i < technique->GetNumPasses(); ++i)
+                {
+                    pass = technique->GetPass(i);
+                    if (pass)
+                    {
+                        vs = graphics_->GetShader(VS, pass->GetVertexShader(), batch.custom_material_->GetVertexShaderDefines());
+                        ps = graphics_->GetShader(PS, pass->GetPixelShader(), batch.custom_material_->GetPixelShaderDefines());
+                        break;
+                    }
+                }
+            }
         }
 
         graphics_->SetShaders(vs, ps);
@@ -1089,9 +1112,40 @@ void UI::Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigne
 
         graphics_->SetBlendMode(batch.blendMode_);
         graphics_->SetScissorTest(true, scissor);
-        graphics_->SetTexture(0, batch.texture_);
+        if (!batch.custom_material_)
+        {
+            graphics_->SetTexture(0, batch.texture_);
+        } else
+        {
+            // Update custom shader parameters if needed
+            if (graphics_->NeedParameterUpdate(SP_MATERIAL, reinterpret_cast<const void*>(batch.custom_material_->GetShaderParameterHash())))
+            {
+                auto shader_parameters = batch.custom_material_->GetShaderParameters();
+                for (auto it = shader_parameters.Begin(); it != shader_parameters.End(); ++it)
+                {
+                    graphics_->SetShaderParameter(it->second_.name_, it->second_.value_);
+                }
+            }
+            // Apply custom shader textures
+            auto textures = batch.custom_material_->GetTextures();
+            for (auto it = textures.Begin(); it != textures.End(); ++it)
+            {
+                graphics_->SetTexture(it->first_, it->second_);
+            }
+        }
+
         graphics_->Draw(TRIANGLE_LIST, batch.vertexStart_ / UI_VERTEX_SIZE,
             (batch.vertexEnd_ - batch.vertexStart_) / UI_VERTEX_SIZE);
+
+        if (batch.custom_material_)
+        {
+            // Reset textures used by the batch custom material
+            auto textures = batch.custom_material_->GetTextures();
+            for (auto it = textures.Begin(); it != textures.End(); ++it)
+            {
+                graphics_->SetTexture(it->first_, 0);
+            }
+        }
     }
 }
 

+ 3 - 0
Source/Urho3D/UI/UIBatch.h

@@ -25,6 +25,7 @@
 #include "../Math/Color.h"
 #include "../Math/Rect.h"
 #include "../Graphics/GraphicsDefs.h"
+#include "../Graphics/Material.h"
 
 namespace Urho3D
 {
@@ -92,6 +93,8 @@ public:
     unsigned color_{};
     /// Gradient flag.
     bool useGradient_{};
+    /// Custom material
+    Material* custom_material_{};
 
     /// Position adjustment vector for pixel-perfect rendering. Initialized by UI.
     static Vector3 posAdjust;

+ 1 - 1
bin/Data/LuaScripts/50_Urho2DPlatformer.lua

@@ -355,7 +355,7 @@ function Character2D:Update(timeStep)
         if self.onSlope then
             body:ApplyForceToCenter(moveDir * MOVE_SPEED / 2, true) -- When climbing a slope, apply force (todo: replace by setting linear velocity to zero when will work)
         else
-            node:Translate(moveDir * timeStep * 1.8)
+            node:Translate(Vector3(moveDir.x, moveDir.y, 0) * timeStep * 1.8)
         end
         if jump then
             body:ApplyLinearImpulse(Vector2(0, 0.17) * MOVE_SPEED, body.massCenter, true)

+ 1 - 0
bin/Data/LuaScripts/Utilities/2D/Sample2D.lua

@@ -461,6 +461,7 @@ function CreateBackgroundSprite(info, scale, texture, animate)
     sprite.sprite = cache:GetResource("Sprite2D", texture)
     SetRandomSeed(time:GetSystemTime()) -- Randomize from system clock
     sprite.color = Color(Random(0, 1), Random(0, 1), Random(0, 1), 1)
+    sprite.layer = -99
 
     -- Create rotation animation
     if animate then

+ 1 - 0
bin/Data/Scripts/Utilities/2D/Sample2D.as

@@ -534,6 +534,7 @@ void CreateBackgroundSprite(TileMapInfo2D@ info, float scale, String texture, bo
     sprite.sprite = cache.GetResource("Sprite2D", texture);
     SetRandomSeed(time.systemTime); // Randomize from system clock
     sprite.color = Color(Random(0.0f, 1.0f), Random(0.0f, 1.0f), Random(0.0f, 1.0f), 1.0f);
+    sprite.layer = -99;
 
     // Create rotation animation
     if (animate)

+ 8 - 2
script/dockerized.sh

@@ -25,6 +25,12 @@ if [[ $# -eq 0 ]]; then echo "Usage: dockerized.sh native|mingw|android|rpi|arm|
 
 PROJECT_DIR=$(cd ${0%/*}/..; pwd)
 
+if [[ ! $DBE_TAG ]]; then
+    DBE_TAG=$(git describe --exact-match 2>/dev/null)
+    # If the command failed or not on a tag then use ':master' by default
+    if [[ $? -ne 0 ]]; then DBE_TAG=:master; fi
+fi
+
 BuildEnvironment=-$1; shift
 BuildEnvironment=${BuildEnvironment/-base}
 
@@ -38,7 +44,7 @@ if [[ $(docker version -f {{.Client.Version}}) =~ ^([0-9]+)\.0*([0-9]+)\. ]] &&
         --mount type=bind,source=$PROJECT_DIR,target=$PROJECT_DIR \
         --mount source=$(id -u).urho3d_home_dir,target=/home/urho3d \
         --name dockerized$BuildEnvironment \
-        urho3d/dockerized$BuildEnvironment $@
+        urho3d/dockerized$BuildEnvironment$DBE_TAG $@
 else
     # Fallback workaround on older Docker CLI version
     docker run -it --rm -h fishtank \
@@ -47,7 +53,7 @@ else
         --mount type=bind,source=$PROJECT_DIR,target=$PROJECT_DIR \
         --mount source=$(id -u).urho3d_home_dir,target=/home/urho3d \
         --name dockerized$BuildEnvironment \
-        urho3d/dockerized$BuildEnvironment $@
+        urho3d/dockerized$BuildEnvironment$DBE_TAG $@
 fi
 
 # vi: set ts=4 sw=4 expandtab: