Browse Source

Updates to terrain, PugiXML, FreeType rendering, and 2D rendering

Josh Engebretson 10 years ago
parent
commit
f39b4d7630
32 changed files with 1118 additions and 520 deletions
  1. 3 0
      Source/Atomic/Atomic2D/AnimatedSprite2D.cpp
  2. 1 1
      Source/Atomic/Atomic2D/Renderer2D.cpp
  3. 2 3
      Source/Atomic/Audio/Sound.cpp
  4. 4 3
      Source/Atomic/Audio/Sound.h
  5. 1 31
      Source/Atomic/Container/ForEach.h
  6. 10 0
      Source/Atomic/Container/HashMap.h
  7. 11 1
      Source/Atomic/Container/HashSet.h
  8. 11 1
      Source/Atomic/Container/List.h
  9. 15 0
      Source/Atomic/Container/Vector.h
  10. 8 9
      Source/Atomic/Core/ProcessUtils.cpp
  11. 1 2
      Source/Atomic/Engine/Application.cpp
  12. 1 6
      Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp
  13. 45 40
      Source/Atomic/Graphics/Terrain.cpp
  14. 1 3
      Source/Atomic/Graphics/Terrain.h
  15. 8 3
      Source/Atomic/Graphics/View.cpp
  16. 35 32
      Source/Atomic/Input/Input.cpp
  17. 10 1
      Source/Atomic/Scene/Node.cpp
  18. 13 17
      Source/Atomic/UI/Cursor.cpp
  19. 37 33
      Source/Atomic/UI/FontFaceFreeType.cpp
  20. 6 4
      Source/Atomic/UI/FontFaceFreeType.h
  21. 5 2
      Source/ThirdParty/Assimp/code/ASELoader.cpp
  22. 5 1
      Source/ThirdParty/Assimp/code/BlenderLoader.cpp
  23. 4 1
      Source/ThirdParty/Assimp/code/ColladaLoader.cpp
  24. 3 3
      Source/ThirdParty/PugiXml/readme.txt
  25. 15 5
      Source/ThirdParty/PugiXml/src/pugiconfig.hpp
  26. 430 141
      Source/ThirdParty/PugiXml/src/pugixml.cpp
  27. 386 167
      Source/ThirdParty/PugiXml/src/pugixml.hpp
  28. 4 0
      Source/ThirdParty/SDL/src/video/windows/SDL_windowsevents.c
  29. 5 2
      Source/ThirdParty/kNet/include/kNet/MessageConnection.h
  30. 3 2
      Source/ThirdParty/kNet/include/kNet/Thread.h
  31. 3 1
      Source/ThirdParty/kNet/src/NetworkSimulator.cpp
  32. 32 5
      Source/Tools/AssetImporter/AssetImporter.cpp

+ 3 - 0
Source/Atomic/Atomic2D/AnimatedSprite2D.cpp

@@ -328,7 +328,10 @@ void AnimatedSprite2D::SetAnimation(Animation2D* animation, LoopMode2D loopMode)
 
             // Create StaticSprite2D component
             if (track.hasSprite_)
+            {
                 staticSprite = trackNode->CreateComponent<StaticSprite2D>();
+                staticSprite->SetEnabled(IsEnabledEffective());
+            }
         }
 
         if (staticSprite)

+ 1 - 1
Source/Atomic/Atomic2D/Renderer2D.cpp

@@ -79,7 +79,7 @@ static inline bool CompareDrawable2Ds(Drawable2D* lhs, Drawable2D* rhs)
 
     Material* lhsUsedMaterial = lhs->GetMaterial();
     Material* rhsUsedMaterial = rhs->GetMaterial();
-    if (lhsUsedMaterial != rhsUsedMaterial)
+    if (lhsUsedMaterial && rhsUsedMaterial && lhsUsedMaterial != rhsUsedMaterial)
         return lhsUsedMaterial->GetNameHash() < rhsUsedMaterial->GetNameHash();
 
     return lhs->GetID() < rhs->GetID();

+ 2 - 3
Source/Atomic/Audio/Sound.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../Core/Context.h"
 #include "../IO/FileSystem.h"
 #include "../IO/Log.h"
@@ -294,7 +293,7 @@ void Sound::SetLoop(unsigned repeatOffset, unsigned endOffset)
 
 void Sound::FixInterpolation()
 {
-    if (!data_)
+    if (!data_ || compressed_)
         return;
     
     // If looped, copy loop start to loop end. If oneshot, insert silence to end

+ 4 - 3
Source/Atomic/Audio/Sound.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -62,8 +62,6 @@ public:
     void SetLooped(bool enable);
     /// Define loop.
     void SetLoop(unsigned repeatOffset, unsigned endOffset);
-    /// Fix interpolation by copying data from loop start to loop end (looped), or adding silence (oneshot.)
-    void FixInterpolation();
     
     /// Return a new instance of a decoder sound stream. Used by compressed sounds.
     SharedPtr<SoundStream> GetDecoderStream() const;
@@ -94,6 +92,9 @@ public:
     /// Return whether is compressed.
     bool IsCompressed() const { return compressed_; }
     
+    /// Fix interpolation by copying data from loop start to loop end (looped), or adding silence (oneshot.) Called internally, does not normally need to be called, unless the sound data is modified manually on the fly.
+    void FixInterpolation();
+
 private:
     /// Load optional parameters from an XML file.
     void LoadParameters();

+ 1 - 31
Source/Atomic/Container/ForEach.h

@@ -29,42 +29,12 @@
 
 #include <algorithm>
 
-namespace std
-{
-
-template <class T> typename Atomic::Vector<T>::ConstIterator begin(const Atomic::Vector<T>& v) { return v.Begin(); }
-template <class T> typename Atomic::Vector<T>::ConstIterator end(const Atomic::Vector<T>& v) { return v.End(); }
-template <class T> typename Atomic::Vector<T>::Iterator begin(Atomic::Vector<T>& v) { return v.Begin(); }
-template <class T> typename Atomic::Vector<T>::Iterator end(Atomic::Vector<T>& v) { return v.End(); }
-
-template <class T> typename Atomic::PODVector<T>::ConstIterator begin(const Atomic::PODVector<T>& v) { return v.Begin(); }
-template <class T> typename Atomic::PODVector<T>::ConstIterator end(const Atomic::PODVector<T>& v) { return v.End(); }
-template <class T> typename Atomic::PODVector<T>::Iterator begin(Atomic::PODVector<T>& v) { return v.Begin(); }
-template <class T> typename Atomic::PODVector<T>::Iterator end(Atomic::PODVector<T>& v) { return v.End(); }
-
-template <class T> typename Atomic::List<T>::ConstIterator begin(const Atomic::List<T>& v) { return v.Begin(); }
-template <class T> typename Atomic::List<T>::ConstIterator end(const Atomic::List<T>& v) { return v.End(); }
-template <class T> typename Atomic::List<T>::Iterator begin(Atomic::List<T>& v) { return v.Begin(); }
-template <class T> typename Atomic::List<T>::Iterator end(Atomic::List<T>& v) { return v.End(); }
-
-template <class T, class U> typename Atomic::HashMap<T, U>::ConstIterator begin(const Atomic::HashMap<T, U>& v) { return v.Begin(); }
-template <class T, class U> typename Atomic::HashMap<T, U>::ConstIterator end(const Atomic::HashMap<T, U>& v) { return v.End(); }
-template <class T, class U> typename Atomic::HashMap<T, U>::Iterator begin(Atomic::HashMap<T, U>& v) { return v.Begin(); }
-template <class T, class U> typename Atomic::HashMap<T, U>::Iterator end(Atomic::HashMap<T, U>& v) { return v.End(); }
-
-template <class T> typename Atomic::HashSet<T>::ConstIterator begin(const Atomic::HashSet<T>& v) { return v.Begin(); }
-template <class T> typename Atomic::HashSet<T>::ConstIterator end(const Atomic::HashSet<T>& v) { return v.End(); }
-template <class T> typename Atomic::HashSet<T>::Iterator begin(Atomic::HashSet<T>& v) { return v.Begin(); }
-template <class T> typename Atomic::HashSet<T>::Iterator end(Atomic::HashSet<T>& v) { return v.End(); }
-
-}
-
 // VS2010+ and other compilers: use std::begin(), std::end() & range based for
 // C++11 features need to be enabled
 #if !defined(_MSC_VER) || _MSC_VER > 1600
 #define foreach(VAL, VALS) for (VAL : VALS)
 // Fallback solution for VS2010. Will have problem with break statement.
-// See https://github.com/urho3d/Atomic/issues/561
+// See https://github.com/urho3d/Urho3D/issues/561
 #else
 
 namespace Atomic

+ 10 - 0
Source/Atomic/Container/HashMap.h

@@ -652,3 +652,13 @@ private:
 };
 
 }
+
+namespace std
+{
+
+template <class T, class U> typename Atomic::HashMap<T, U>::ConstIterator begin(const Atomic::HashMap<T, U>& v) { return v.Begin(); }
+template <class T, class U> typename Atomic::HashMap<T, U>::ConstIterator end(const Atomic::HashMap<T, U>& v) { return v.End(); }
+template <class T, class U> typename Atomic::HashMap<T, U>::Iterator begin(Atomic::HashMap<T, U>& v) { return v.Begin(); }
+template <class T, class U> typename Atomic::HashMap<T, U>::Iterator end(Atomic::HashMap<T, U>& v) { return v.End(); }
+
+}

+ 11 - 1
Source/Atomic/Container/HashSet.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -550,3 +550,13 @@ private:
 };
 
 }
+
+namespace std
+{
+
+template <class T> typename Atomic::HashSet<T>::ConstIterator begin(const Atomic::HashSet<T>& v) { return v.Begin(); }
+template <class T> typename Atomic::HashSet<T>::ConstIterator end(const Atomic::HashSet<T>& v) { return v.End(); }
+template <class T> typename Atomic::HashSet<T>::Iterator begin(Atomic::HashSet<T>& v) { return v.Begin(); }
+template <class T> typename Atomic::HashSet<T>::Iterator end(Atomic::HashSet<T>& v) { return v.End(); }
+
+}

+ 11 - 1
Source/Atomic/Container/List.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -412,3 +412,13 @@ private:
 };
 
 }
+
+namespace std
+{
+
+template <class T> typename Atomic::List<T>::ConstIterator begin(const Atomic::List<T>& v) { return v.Begin(); }
+template <class T> typename Atomic::List<T>::ConstIterator end(const Atomic::List<T>& v) { return v.End(); }
+template <class T> typename Atomic::List<T>::Iterator begin(Atomic::List<T>& v) { return v.Begin(); }
+template <class T> typename Atomic::List<T>::Iterator end(Atomic::List<T>& v) { return v.End(); }
+
+}

+ 15 - 0
Source/Atomic/Container/Vector.h

@@ -842,3 +842,18 @@ private:
 };
 
 }
+
+namespace std
+{
+
+template <class T> typename Atomic::Vector<T>::ConstIterator begin(const Atomic::Vector<T>& v) { return v.Begin(); }
+template <class T> typename Atomic::Vector<T>::ConstIterator end(const Atomic::Vector<T>& v) { return v.End(); }
+template <class T> typename Atomic::Vector<T>::Iterator begin(Atomic::Vector<T>& v) { return v.Begin(); }
+template <class T> typename Atomic::Vector<T>::Iterator end(Atomic::Vector<T>& v) { return v.End(); }
+
+template <class T> typename Atomic::PODVector<T>::ConstIterator begin(const Atomic::PODVector<T>& v) { return v.Begin(); }
+template <class T> typename Atomic::PODVector<T>::ConstIterator end(const Atomic::PODVector<T>& v) { return v.End(); }
+template <class T> typename Atomic::PODVector<T>::Iterator begin(Atomic::PODVector<T>& v) { return v.Begin(); }
+template <class T> typename Atomic::PODVector<T>::Iterator end(Atomic::PODVector<T>& v) { return v.End(); }
+
+}

+ 8 - 9
Source/Atomic/Core/ProcessUtils.cpp

@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../Core/Mutex.h"
 #include "../Core/ProcessUtils.h"
 #include "../Math/MathDefs.h"
@@ -358,8 +357,8 @@ String GetPlatform()
     #endif
 }
 
-#ifdef ANDROID
-static unsigned GetAndroidCPUCount()
+#if defined(ANDROID) || defined(RPI)
+static unsigned GetArmCPUCount()
 {
     FILE* fp;
     int res, i = -1, j = -1;
@@ -393,9 +392,9 @@ unsigned GetNumPhysicalCPUs()
     #else
     return data.physical_cpu;
     #endif
-    #elif defined(ANDROID)
-    return GetAndroidCPUCount();
-    #elif !defined(RPI) && !defined(EMSCRIPTEN)
+    #elif defined(ANDROID) || defined(RPI)
+    return GetArmCPUCount();
+    #elif !defined(EMSCRIPTEN)
     struct cpu_id_t data;
     GetCPUData(&data);
     return data.num_cores;
@@ -415,9 +414,9 @@ unsigned GetNumLogicalCPUs()
     #else
     return data.logical_cpu;
     #endif
-    #elif defined(ANDROID)
-    return GetAndroidCPUCount();
-    #elif !defined(RPI) && !defined(EMSCRIPTEN)
+    #elif defined(ANDROID) || defined (RPI)
+    return GetArmCPUCount();
+    #elif !defined(EMSCRIPTEN)
     struct cpu_id_t data;
     GetCPUData(&data);
     return data.num_logical_cpus;

+ 1 - 2
Source/Atomic/Engine/Application.cpp

@@ -45,8 +45,7 @@ namespace Atomic
 #endif
 void RunFrame(void* data)
 {
-    Engine* engine = reinterpret_cast<Engine*>(data);
-    engine->RunFrame();
+    static_cast<Engine*>(data)->RunFrame();
 }
 #endif
 

+ 1 - 6
Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp

@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../../Graphics/AnimatedModel.h"
 #include "../../Graphics/Animation.h"
 #include "../../Graphics/AnimationController.h"
@@ -356,12 +355,8 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
         fullscreen = false;
 
     multiSample = Clamp(multiSample, 1, 16);
-    bool isInitialized = IsInitialized();
-    LOGINFO(isInitialized ? "isInitialized == true" : "isInitialized == false");
-
     
-    //if (IsInitialized() && width == width_ && height == height_ && fullscreen == fullscreen_ && borderless == borderless_ && resizable == resizable_ &&
-    if (isInitialized && width == width_ && height == height_ && fullscreen == fullscreen_ && borderless == borderless_ && resizable == resizable_ &&
+    if (IsInitialized() && width == width_ && height == height_ && fullscreen == fullscreen_ && borderless == borderless_ && resizable == resizable_ &&
         vsync == vsync_ && tripleBuffer == tripleBuffer_ && multiSample == multiSample_)
         return true;
     

+ 45 - 40
Source/Atomic/Graphics/Terrain.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../Core/Context.h"
 #include "../Graphics/DrawableEvents.h"
 #include "../Graphics/Geometry.h"
@@ -55,6 +54,26 @@ static const unsigned STITCH_SOUTH = 2;
 static const unsigned STITCH_WEST = 4;
 static const unsigned STITCH_EAST = 8;
 
+inline void GrowUpdateRegion(IntRect& updateRegion, int x, int y)
+{
+    if (updateRegion.left_ < 0)
+    {
+        updateRegion.left_ = updateRegion.right_ = x;
+        updateRegion.top_ = updateRegion.bottom_ = y;
+    }
+    else
+    {
+        if (x < updateRegion.left_)
+            updateRegion.left_ = x;
+        if (x > updateRegion.right_)
+            updateRegion.right_ = x;
+        if (y < updateRegion.top_)
+            updateRegion.top_ = y;
+        if (y > updateRegion.bottom_)
+            updateRegion.bottom_ = y;
+    }
+}
+
 Terrain::Terrain(Context* context) :
     Component(context),
     indexBuffer_(new IndexBuffer(context)),
@@ -685,6 +704,7 @@ void Terrain::CreateGeometry()
         float* dest = smoothing_ ? sourceHeightData_ : heightData_;
         unsigned imgComps = heightMap_->GetComponents();
         unsigned imgRow = heightMap_->GetWidth() * imgComps;
+        IntRect updateRegion(-1, -1, -1, -1);
 
         if (imgComps == 1)
         {
@@ -702,16 +722,8 @@ void Terrain::CreateGeometry()
                     {
                         if (*dest != newHeight)
                         {
-                            if (!smoothing_)
-                                MarkPatchesDirty(dirtyPatches, x, z);
-                            else
-                            {
-                                for (int z1 = z - 1; z1 <= z + 1; ++z1)
-                                    for (int x1 = x - 1; x1 <= z + 1; ++x1)
-                                        MarkPatchesDirty(dirtyPatches, x1, z1);
-                            }
-
                             *dest = newHeight;
+                            GrowUpdateRegion(updateRegion, x, z);
                         }
                     }
 
@@ -737,16 +749,8 @@ void Terrain::CreateGeometry()
                     {
                         if (*dest != newHeight)
                         {
-                            if (!smoothing_)
-                                MarkPatchesDirty(dirtyPatches, x, z);
-                            else
-                            {
-                                for (int z1 = z - 1; z1 <= z + 1; ++z1)
-                                    for (int x1 = x - 1; x1 <= z + 1; ++x1)
-                                        MarkPatchesDirty(dirtyPatches, x1, z1);
-                            }
-
                             *dest = newHeight;
+                            GrowUpdateRegion(updateRegion, x, z);
                         }
                     }
 
@@ -755,6 +759,27 @@ void Terrain::CreateGeometry()
             }
         }
 
+        // If updating a region of the heightmap, check which patches change
+        if (!updateAll)
+        {
+            int lodExpand = 1 << (numLodLevels_ - 1);
+            // Expand the right & bottom 1 pixel more, as patches share vertices at the edge
+            updateRegion.left_ -= lodExpand;
+            updateRegion.right_ += lodExpand + 1;
+            updateRegion.top_ -= lodExpand;
+            updateRegion.bottom_ += lodExpand + 1;
+            
+            int sX = Max(updateRegion.left_ / patchSize_, 0);
+            int eX = Min(updateRegion.right_ / patchSize_, numPatches_.x_ - 1);
+            int sY = Max(updateRegion.top_ / patchSize_, 0);
+            int eY = Min(updateRegion.bottom_ / patchSize_, numPatches_.y_ - 1);
+            for (int y = sY; y <= eY; ++y)
+            {
+                for (int x = sX; x <= eX; ++x)
+                    dirtyPatches[y * numPatches_.x_ + x] = true;
+            }
+        }
+
         patches_.Reserve(numPatches_.x_ * numPatches_.y_);
 
         bool enabled = IsEnabledEffective();
@@ -1177,24 +1202,4 @@ void Terrain::HandleHeightMapReloadFinished(StringHash eventType, VariantMap& ev
     CreateGeometry();
 }
 
-void Terrain::MarkPatchesDirty(PODVector<bool>& dirtyPatches, int x, int z)
-{
-    x = Clamp(x, 0, numVertices_.x_);
-    z = Clamp(z, 0, numVertices_.y_);
-
-    // A point on the heightmap can potentially belong to multiple patches; dirty all that are applicable
-    int pZ = z / patchSize_;
-    int vZ = z % patchSize_;
-    int pX = x / patchSize_;
-    int vX = x % patchSize_;
-    if (pZ < numPatches_.y_ && pX < numPatches_.x_)
-        dirtyPatches[pZ * numPatches_.x_ + pX] = true;
-    if (vX == 0 && pX > 0 && pZ < numPatches_.y_)
-        dirtyPatches[pZ * numPatches_.x_ + pX - 1] = true;
-    if (vZ == 0 && pZ > 0 && pX < numPatches_.y_)
-        dirtyPatches[(pZ - 1) * numPatches_.x_ + pX] = true;
-    if (vX == 0 && vZ == 0 && pX > 0 && pZ > 0)
-        dirtyPatches[(pZ - 1) * numPatches_.x_ + pX - 1] = true;
-}
-
 }

+ 1 - 3
Source/Atomic/Graphics/Terrain.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -175,8 +175,6 @@ private:
     bool SetHeightMapInternal(Image* image, bool recreateNow);
     /// Handle heightmap image reload finished.
     void HandleHeightMapReloadFinished(StringHash eventType, VariantMap& eventData);
-    /// Mark patch(es) dirty based on location. Used when checking the heightmap image for changes.
-    void MarkPatchesDirty(PODVector<bool>& dirtyPatches, int x, int z);
 
     /// Shared index buffer.
     SharedPtr<IndexBuffer> indexBuffer_;

+ 8 - 3
Source/Atomic/Graphics/View.cpp

@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../Graphics/Camera.h"
 #include "../Graphics/DebugRenderer.h"
 #include "../IO/FileSystem.h"
@@ -1484,7 +1483,13 @@ void View::ExecuteRenderPathCommands()
                 {
                     currentRenderTarget_ = viewportTextures_[1]->GetRenderSurface();
                     // If the render path ends into a quad, it can be redirected to the final render target
+                    // However, on OpenGL we can not reliably do this in case the final target is the backbuffer, and we want to
+                    // render depth buffer sensitive debug geometry afterward (backbuffer and textures can not share depth)
+                    #ifndef ATOMIC_OPENGL
                     if (i == lastCommandIndex && command.type_ == CMD_QUAD)
+                    #else
+                    if (i == lastCommandIndex && command.type_ == CMD_QUAD && renderTarget_)
+                    #endif
                         currentRenderTarget_ = renderTarget_;
                 }
                 else
@@ -1635,8 +1640,8 @@ void View::SetRenderTargets(RenderPathCommand& command)
             {
                 Texture2D* texture = renderTargets_[nameHash];
                 // Check for depth only rendering (by specifying a depth texture as the sole output)
-                if (!index && command.outputNames_.Size() == 1 && texture && texture->GetFormat() == 
-                    Graphics::GetReadableDepthFormat() || texture->GetFormat() == Graphics::GetDepthStencilFormat())
+                if (!index && command.outputNames_.Size() == 1 && texture && (texture->GetFormat() ==
+                    Graphics::GetReadableDepthFormat() || texture->GetFormat() == Graphics::GetDepthStencilFormat()))
                 {
                     useColorWrite = false;
                     useCustomDepth = true;

+ 35 - 32
Source/Atomic/Input/Input.cpp

@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../Core/Context.h"
 #include "../Core/CoreEvents.h"
 #include "../IO/FileSystem.h"
@@ -94,8 +93,6 @@ UIElement* TouchState::GetTouchedElement()
  * - The user can press 'escape' key and browser will force user out of pointer lock. Urho will send the E_MOUSEMODECHANGED event.
  * - SetMouseMode(MM_ABSOLUTE) will leave pointer lock.
  * - MM_WRAP is unsupported.
- *
- * Touch Input:
  */
 /// % Emscripten Input glue. Intended to be used by the Input subsystem only.
 class EmscriptenInput
@@ -105,11 +102,9 @@ public:
     EmscriptenInput(Input* inputInst);
 
     /// Static callback method for Pointer Lock API. Handles change in Pointer Lock state and sends events for mouse mode change.
-    static EM_BOOL PointerLockCallback(int eventType, const EmscriptenPointerlockChangeEvent* keyEvent, void* userData);
-    /// Static callback method for tracking lose focus event.
-    static EM_BOOL LoseFocus(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData);
-    /// Static callback method for tracking gain focus event.
-    static EM_BOOL GainFocus(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData);
+    static EM_BOOL HandlePointerLockChange(int eventType, const EmscriptenPointerlockChangeEvent* keyEvent, void* userData);
+    /// Static callback method for tracking focus change events.
+    static EM_BOOL HandleFocusChange(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData);
 
     /// Send request to user to gain pointer lock. This requires a user-browser interaction on the first call.
     void RequestPointerLock();
@@ -126,11 +121,12 @@ private:
 EmscriptenInput::EmscriptenInput(Input* inputInst)
 {
     inputInst_ = inputInst;
-    emscripten_set_pointerlockchange_callback(NULL, (void*)inputInst, false, EmscriptenInput::PointerLockCallback);
+    void* vInputInst = (void*)inputInst;
+    emscripten_set_pointerlockchange_callback(NULL, vInputInst, false, EmscriptenInput::HandlePointerLockChange);
 
     // Handle focus changes:
-    emscripten_set_blur_callback(NULL, (void*)inputInst, false, EmscriptenInput::LoseFocus);
-    emscripten_set_focus_callback(NULL, (void*)inputInst, false, EmscriptenInput::GainFocus);
+    emscripten_set_blur_callback(NULL, vInputInst, false, EmscriptenInput::HandleFocusChange);
+    emscripten_set_focus_callback(NULL, vInputInst, false, EmscriptenInput::HandleFocusChange);
 }
 
 void EmscriptenInput::RequestPointerLock()
@@ -155,7 +151,7 @@ bool EmscriptenInput::IsVisible()
     return true;
 }
 
-EM_BOOL EmscriptenInput::PointerLockCallback(int eventType, const EmscriptenPointerlockChangeEvent* keyEvent, void* userData)
+EM_BOOL EmscriptenInput::HandlePointerLockChange(int eventType, const EmscriptenPointerlockChangeEvent* keyEvent, void* userData)
 {
     Input* inputInst = (Input*)userData;
     if (keyEvent->isActive >= EM_TRUE)
@@ -172,18 +168,12 @@ EM_BOOL EmscriptenInput::PointerLockCallback(int eventType, const EmscriptenPoin
     return EM_TRUE;
 }
 
-EM_BOOL EmscriptenInput::LoseFocus(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData)
+EM_BOOL EmscriptenInput::HandleFocusChange(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData)
 {
     Input* inputInst = (Input*)userData;
     if (eventType == EMSCRIPTEN_EVENT_BLUR)
         inputInst->LoseFocus();
-    return EM_TRUE;
-}
-
-EM_BOOL EmscriptenInput::GainFocus(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData)
-{
-    Input* inputInst = (Input*)userData;
-    if (eventType == EMSCRIPTEN_EVENT_FOCUS)
+    else if (eventType == EMSCRIPTEN_EVENT_FOCUS)
         inputInst->GainFocus();
     return EM_TRUE;
 }
@@ -425,18 +415,18 @@ void Input::Update()
         }
     }
 
-#ifndef EMSCRIPTEN
-   if (mouseMode_ == MM_RELATIVE)
-   {
-       IntVector2 mousePosition = GetMousePosition();
-       IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
-       if (mousePosition != center)
-       {
-           SetMousePosition(center);
-           lastMousePosition_ = center;
-       }
-   }
-   #endif
+    #ifndef EMSCRIPTEN
+    if (mouseMode_ == MM_RELATIVE)
+    {
+        IntVector2 mousePosition = GetMousePosition();
+        IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
+        if (mousePosition != center)
+        {
+            SetMousePosition(center);
+            lastMousePosition_ = center;
+        }
+    }
+    #endif
 }
 
 void Input::SetMouseVisible(bool enable, bool suppressEvent)
@@ -1641,8 +1631,12 @@ void Input::HandleSDLEvent(void* sdlEvent)
             int touchID = GetTouchIndexFromID(evt.tfinger.fingerId & 0x7ffffff);
             TouchState& state = touches_[touchID];
             state.touchID_ = touchID;
+            #ifndef EMSCRIPTEN
             state.lastPosition_ = state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
                 (int)(evt.tfinger.y * graphics_->GetHeight()));
+            #else
+            state.position_ = IntVector2((int)(evt.tfinger.x), (int)(evt.tfinger.y));
+            #endif
             state.delta_ = IntVector2::ZERO;
             state.pressure_ = evt.tfinger.pressure;
 
@@ -1689,8 +1683,12 @@ void Input::HandleSDLEvent(void* sdlEvent)
                 break;
             TouchState& state = touches_[touchID];
             state.touchID_ = touchID;
+            #ifndef EMSCRIPTEN
             state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
                 (int)(evt.tfinger.y * graphics_->GetHeight()));
+            #else
+            state.position_ = IntVector2((int)(evt.tfinger.x), (int)(evt.tfinger.y));
+            #endif
             state.delta_ = state.position_ - state.lastPosition_;
             state.pressure_ = evt.tfinger.pressure;
 
@@ -1700,8 +1698,13 @@ void Input::HandleSDLEvent(void* sdlEvent)
             eventData[P_TOUCHID] = touchID;
             eventData[P_X] = state.position_.x_;
             eventData[P_Y] = state.position_.y_;
+            #ifndef EMSCRIPTEN
             eventData[P_DX] = (int)(evt.tfinger.dx * graphics_->GetWidth());
             eventData[P_DY] = (int)(evt.tfinger.dy * graphics_->GetHeight());
+            #else
+            eventData[P_DX] = (int)(evt.tfinger.dx);
+            eventData[P_DY] = (int)(evt.tfinger.dy);
+            #endif
             eventData[P_PRESSURE] = state.pressure_;
             SendEvent(E_TOUCHMOVE, eventData);
         }

+ 10 - 1
Source/Atomic/Scene/Node.cpp

@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../Scene/Component.h"
 #include "../Core/Context.h"
 #include "../IO/Log.h"
@@ -682,6 +681,11 @@ void Node::RemoveChildren(bool removeReplicated, bool removeLocal, bool recursiv
 
 Component* Node::CreateComponent(StringHash type, CreateMode mode, unsigned id)
 {
+    // Do not attempt to create replicated components to local nodes, as that may lead to component ID overwrite
+    // as replicated components are synced over
+    if (id_ >= FIRST_LOCAL_ID && mode == REPLICATED)
+        mode = LOCAL;
+
     // Check that creation succeeds and that the object in fact is a component
     SharedPtr<Component> newComponent = DynamicCast<Component>(context_->CreateObject(type));
     if (!newComponent)
@@ -1632,6 +1636,11 @@ void Node::SetEnabled(bool enable, bool recursive, bool storeSelf)
 
 Component* Node::SafeCreateComponent(const String& typeName, StringHash type, CreateMode mode, unsigned id)
 {
+    // Do not attempt to create replicated components to local nodes, as that may lead to component ID overwrite
+    // as replicated components are synced over
+    if (id_ >= FIRST_LOCAL_ID && mode == REPLICATED)
+        mode = LOCAL;
+
     // First check if factory for type exists
     if (!context_->GetTypeName(type).Empty())
         return CreateComponent(type, mode, id);

+ 13 - 17
Source/Atomic/UI/Cursor.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../Core/Context.h"
 #include "../UI/Cursor.h"
 #include "../Input/Input.h"
@@ -87,13 +86,12 @@ Cursor::Cursor(Context* context) :
 
 Cursor::~Cursor()
 {
-    HashMap<String, CursorShapeInfo>::Iterator iter = shapeInfos_.Begin();
-    for (iter; iter != shapeInfos_.End(); iter++)
+    for (HashMap<String, CursorShapeInfo>::Iterator i = shapeInfos_.Begin(); i != shapeInfos_.End(); ++i)
     {
-        if (iter->second_.osCursor_)
+        if (i->second_.osCursor_)
         {
-            SDL_FreeCursor(iter->second_.osCursor_);
-            iter->second_.osCursor_ = 0;
+            SDL_FreeCursor(i->second_.osCursor_);
+            i->second_.osCursor_ = 0;
         }
     }
 }
@@ -217,10 +215,9 @@ void Cursor::SetShapesAttr(const VariantVector& value)
     if (!value.Size())
         return;
 
-    VariantVector::ConstIterator iter = value.Begin();
-    for (iter; iter != value.End(); iter++)
+    for (VariantVector::ConstIterator i = value.Begin(); i != value.End(); ++i)
     {
-        VariantVector shapeVector = iter->GetVariantVector();
+        VariantVector shapeVector = i->GetVariantVector();
         if (shapeVector.Size() >= 4)
         {
             String shape = shapeVector[0].GetString();
@@ -237,17 +234,16 @@ VariantVector Cursor::GetShapesAttr() const
 {
     VariantVector ret;
 
-    HashMap<String, CursorShapeInfo>::ConstIterator iter = shapeInfos_.Begin();
-    for (iter; iter != shapeInfos_.End(); iter++)
+    for (HashMap<String, CursorShapeInfo>::ConstIterator i = shapeInfos_.Begin(); i != shapeInfos_.End(); ++i)
     {
-        if (iter->second_.imageRect_ != IntRect::ZERO)
+        if (i->second_.imageRect_ != IntRect::ZERO)
         {
             // Could use a map but this simplifies the UI xml.
             VariantVector shape;
-            shape.Push(iter->first_);
-            shape.Push(GetResourceRef(iter->second_.texture_, Texture2D::GetTypeStatic()));
-            shape.Push(iter->second_.imageRect_);
-            shape.Push(iter->second_.hotSpot_);
+            shape.Push(i->first_);
+            shape.Push(GetResourceRef(i->second_.texture_, Texture2D::GetTypeStatic()));
+            shape.Push(i->second_.imageRect_);
+            shape.Push(i->second_.hotSpot_);
             ret.Push(shape);
         }
     }

+ 37 - 33
Source/Atomic/UI/FontFaceFreeType.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -20,7 +20,6 @@
 // THE SOFTWARE.
 //
 
-#include "Precompiled.h"
 #include "../Core/Context.h"
 #include "../IO/FileSystem.h"
 #include "../UI/Font.h"
@@ -71,9 +70,9 @@ private:
 
 FontFaceFreeType::FontFaceFreeType(Font* font) :
 FontFace(font),
-    face_(0)
+    face_(0), 
+    loadMode_(FT_LOAD_DEFAULT)
 {
-
 }
 
 FontFaceFreeType::~FontFaceFreeType()
@@ -88,10 +87,12 @@ FontFaceFreeType::~FontFaceFreeType()
 bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize, int pointSize)
 {
     Context* context = font_->GetContext();
+
     // Create & initialize FreeType library if it does not exist yet
     FreeTypeLibrary* freeType = font_->GetSubsystem<FreeTypeLibrary>();
     if (!freeType)
         context->RegisterSubsystem(freeType = new FreeTypeLibrary(context));
+
     // Ensure the FreeType library is kept alive as long as TTF font resources exist
     freeType_ = freeType;
 
@@ -130,22 +131,25 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
 
     face_ = face;
 
-    FT_UInt glyphIndex;
-    unsigned numGlyphs = 0;
-    HashMap<unsigned, unsigned> indexToCharMapping;
+    unsigned numGlyphs = face->num_glyphs;
+    LOGDEBUGF("Font face %s (%dpt) has %d glyphs", GetFileName(font_->GetName()).CString(), pointSize, numGlyphs);
+    
+    PODVector<unsigned> charCodes(numGlyphs);
+    for (unsigned i = 0; i < numGlyphs; ++i)
+        charCodes[i] = 0;
 
+    FT_UInt glyphIndex;
     FT_ULong charCode = FT_Get_First_Char(face, &glyphIndex);
     while (glyphIndex != 0)
     {
-        numGlyphs = Max((int)glyphIndex + 1, (int)numGlyphs);
-        indexToCharMapping[glyphIndex] = charCode;
+        if (glyphIndex < numGlyphs)
+            charCodes[glyphIndex] = charCode;
+
         charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
     }
 
-    LOGDEBUGF("Font face %s (%dpt) has %d glyphs", GetFileName(font_->GetName()).CString(), pointSize, numGlyphs);
-
     // Load each of the glyphs to see the sizes & store other information
-    int loadMode = ui->GetForceAutoHint() ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT;
+    loadMode_ = ui->GetForceAutoHint() ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT;
     ascender_ = face->size->metrics.ascender >> 6;
     int descender = face->size->metrics.descender >> 6;
 
@@ -165,7 +169,7 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
 
     int textureWidth = maxTextureSize;
     int textureHeight = maxTextureSize;
-    bool loadAllGlyphs = CanLoadAllGlyphs(numGlyphs, loadMode, textureWidth, textureHeight);
+    bool loadAllGlyphs = CanLoadAllGlyphs(charCodes, textureWidth, textureHeight);
 
     SharedPtr<Image> image(new Image(font_->GetContext()));
     image->SetSize(textureWidth, textureHeight, 1);
@@ -175,7 +179,10 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
 
     for (unsigned i = 0; i < numGlyphs; ++i)
     {
-        unsigned charCode = indexToCharMapping[i];
+        unsigned charCode = charCodes[i];
+        if (charCode == 0)
+            continue;
+        
         if (!loadAllGlyphs && (charCode > 0xff))
             break;
 
@@ -195,9 +202,9 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
     {
         // Read kerning manually to be more efficient and avoid out of memory crash when use large font file, for example there
         // are 29354 glyphs in msyh.ttf
-        FT_ULong tag = FT_MAKE_TAG('k', 'e', 'r', 'n');
+        FT_ULong tagKern = FT_MAKE_TAG('k', 'e', 'r', 'n');
         FT_ULong kerningTableSize = 0;
-        FT_Error error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &kerningTableSize);
+        FT_Error error = FT_Load_Sfnt_Table(face, tagKern, 0, NULL, &kerningTableSize);
         if (error)
         {
             LOGERROR("Could not get kerning table length");
@@ -205,7 +212,7 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
         }
 
         SharedArrayPtr<unsigned char> kerningTable(new unsigned char[kerningTableSize]);
-        error = FT_Load_Sfnt_Table(face, tag, 0, kerningTable, &kerningTableSize);
+        error = FT_Load_Sfnt_Table(face, tagKern, 0, kerningTable, &kerningTableSize);
         if (error)
         {
             LOGERROR("Could not load kerning table");
@@ -239,15 +246,13 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
                         unsigned rightIndex = deserializer.ReadUShort();
                         short amount = (short)(deserializer.ReadShort() >> 6);
 
-                        HashMap<unsigned, unsigned>::ConstIterator leftIter = indexToCharMapping.Find(leftIndex);
-                        HashMap<unsigned, unsigned>::ConstIterator rightIter = indexToCharMapping.Find(rightIndex);
-                        if (leftIter != indexToCharMapping.End() && rightIter != indexToCharMapping.End())
+                        unsigned leftCharCode = leftIndex < numGlyphs ? charCodes[leftIndex] : 0;
+                        unsigned rightCharCode = rightIndex < numGlyphs ? charCodes[rightIndex] : 0;
+                        if (leftCharCode != 0 && rightCharCode != 0)
                         {
-                            unsigned value = (leftIter->second_ << 16) + rightIter->second_;
+                            unsigned value = (leftCharCode << 16) + rightCharCode;
                             kerningMapping_[value] = amount;
                         }
-                        else
-                            LOGWARNING("Out of range glyph index in kerning information");
                     }
                 }
                 else
@@ -297,15 +302,20 @@ const FontGlyph* FontFaceFreeType::GetGlyph(unsigned c)
     return 0;
 }
 
-bool FontFaceFreeType::CanLoadAllGlyphs(unsigned numGlyphs, int loadMode, int& textureWidth, int& textureHeight) const
+bool FontFaceFreeType::CanLoadAllGlyphs(const PODVector<unsigned>& charCodes, int& textureWidth, int& textureHeight) const
 {
     FT_Face face = (FT_Face)face_;
     FT_GlyphSlot slot = face->glyph;
     AreaAllocator allocator(FONT_TEXTURE_MIN_SIZE, FONT_TEXTURE_MIN_SIZE, textureWidth, textureHeight);
 
+    unsigned numGlyphs = charCodes.Size();
     for (unsigned i = 0; i < numGlyphs; ++i)
     {
-        FT_Error error = FT_Load_Glyph(face, i, loadMode);
+        unsigned charCode = charCodes[i];
+        if (charCode == 0)
+            continue;
+
+        FT_Error error = FT_Load_Char(face, charCode, loadMode_);
         if (!error)
         {
             int width = Max(slot->metrics.width >> 6, slot->bitmap.width);
@@ -348,11 +358,8 @@ bool FontFaceFreeType::LoadCharGlyph(unsigned charCode, Image* image)
     FT_Face face = (FT_Face)face_;
     FT_GlyphSlot slot = face->glyph;
 
-    UI* ui = font_->GetSubsystem<UI>();
-    int loadMode = ui->GetForceAutoHint() ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT;
-
     FontGlyph fontGlyph;
-    FT_Error error = FT_Load_Char(face, charCode, loadMode);
+    FT_Error error = FT_Load_Char(face, charCode, loadMode_);
     if (!error)
     {
         // Note: position within texture will be filled later
@@ -367,8 +374,7 @@ bool FontFaceFreeType::LoadCharGlyph(unsigned charCode, Image* image)
             int x, y;
             if (!allocator_.Allocate(fontGlyph.width_ + 1, fontGlyph.height_ + 1, x, y))
             {
-                int textureSize = ui->GetMaxFontTextureSize();
-                if (!SetupNextTexture(textureSize, textureSize))
+                if (!SetupNextTexture(allocator_.GetWidth(), allocator_.GetHeight()))
                     return false;
 
                 if (!allocator_.Allocate(fontGlyph.width_ + 1, fontGlyph.height_ + 1, x, y))
@@ -445,6 +451,4 @@ bool FontFaceFreeType::LoadCharGlyph(unsigned charCode, Image* image)
     return true;
 }
 
-
-
 }

+ 6 - 4
Source/Atomic/UI/FontFaceFreeType.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -48,7 +48,7 @@ public:
 
 private:
     /// Check can load all glyph in one texture, return true and texture size if can load.
-    bool CanLoadAllGlyphs(unsigned numGlyphs, int loadMode, int& textureWidth, int& textureHeight) const;
+    bool CanLoadAllGlyphs(const PODVector<unsigned>& charCodes, int& textureWidth, int& textureHeight) const;
     /// Setup next texture.
     bool SetupNextTexture(int textureWidth, int textureHeight);
     /// Load char glyph.
@@ -58,10 +58,12 @@ private:
     SharedPtr<FreeTypeLibrary> freeType_;
     /// FreeType face. Non-null after creation only in dynamic mode.
     void* face_;
-    /// Has mutable glyph.
-    bool hasMutableGlyph_;
+    /// Load mode.
+    int loadMode_;
     /// Ascender.
     int ascender_;
+    /// Has mutable glyph.
+    bool hasMutableGlyph_;
     /// Glyph area allocator.
     AreaAllocator allocator_;
 };

+ 5 - 2
Source/ThirdParty/Assimp/code/ASELoader.cpp

@@ -43,6 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the ASE importer class
  */
 
+// Modified by Lasse Oorni for Urho3D
+
 #include "AssimpPCH.h"
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 
@@ -449,8 +451,9 @@ void ASEImporter::BuildLights()
 
 			// The direction is encoded in the transformation matrix of the node. 
 			// In 3DS MAX the light source points into negative Z direction if 
-			// the node transformation is the identity. 
-			out->mDirection = aiVector3D(0.f,0.f,-1.f);
+			// the node transformation is the identity.
+            // Urho3D: lights should use positive Z as local direction
+			out->mDirection = aiVector3D(0.f,0.f,1.f);
 
 			out->mName.Set(in.mName);
 			switch (in.mLightType)

+ 5 - 1
Source/ThirdParty/Assimp/code/BlenderLoader.cpp

@@ -42,6 +42,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  BlenderLoader.cpp
  *  @brief Implementation of the Blender3D importer class.
  */
+
+// Modified by Lasse Oorni for Urho3D
+
 #include "AssimpPCH.h"
 
 //#define ASSIMP_BUILD_NO_COMPRESSED_BLEND
@@ -1024,7 +1027,8 @@ aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const
 	        out->mType = aiLightSource_DIRECTIONAL;
 
 	        // blender orients directional lights as facing toward -z
-	        out->mDirection = aiVector3D(0.f, 0.f, -1.f);
+            // Urho3D: lights should use positive Z as local direction
+	        out->mDirection = aiVector3D(0.f, 0.f, 1.f);
 	        break;
 	    default:
 	        break;

+ 4 - 1
Source/ThirdParty/Assimp/code/ColladaLoader.cpp

@@ -41,6 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /** @file Implementation of the Collada loader */
 
+// Modified by Lasse Oorni for Urho3D
+
 #include "AssimpPCH.h"
 #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
 
@@ -318,7 +320,8 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
 		out->mType = (aiLightSourceType)srcLight->mType;
 
 		// collada lights point in -Z by default, rest is specified in node transform
-		out->mDirection = aiVector3D(0.f,0.f,-1.f);
+        // Urho3D: lights should use positive Z as local direction
+        out->mDirection = aiVector3D(0.f, 0.f,1.f);
 
 		out->mAttenuationConstant = srcLight->mAttConstant;
 		out->mAttenuationLinear = srcLight->mAttLinear;

+ 3 - 3
Source/ThirdParty/PugiXml/readme.txt

@@ -1,6 +1,6 @@
-pugixml 1.0 - an XML processing library
+pugixml 1.5 - an XML processing library
 
-Copyright (C) 2006-2010, by Arseny Kapoulkine ([email protected])
+Copyright (C) 2006-2014, by Arseny Kapoulkine ([email protected])
 Report bugs and download new versions at http://pugixml.org/
 
 This is the distribution of pugixml, which is a C++ XML processing library,
@@ -28,7 +28,7 @@ The distribution contains the following folders:
 
 This library is distributed under the MIT License:
 
-Copyright (c) 2006-2010 Arseny Kapoulkine
+Copyright (c) 2006-2014 Arseny Kapoulkine
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation

+ 15 - 5
Source/ThirdParty/PugiXml/src/pugiconfig.hpp

@@ -1,7 +1,7 @@
 /**
- * pugixml parser - version 1.0
+ * pugixml parser - version 1.5
  * --------------------------------------------------------
- * Copyright (C) 2006-2010, by Arseny Kapoulkine ([email protected])
+ * Copyright (C) 2006-2014, by Arseny Kapoulkine ([email protected])
  * Report bugs and download new versions at http://pugixml.org/
  *
  * This library is distributed under the MIT License. See notice at the end
@@ -21,11 +21,9 @@
 // #define PUGIXML_NO_XPATH
 
 // Uncomment this to disable STL
-// Note: you can't use XPath with PUGIXML_NO_STL
 #define PUGIXML_NO_STL
 
 // Uncomment this to disable exceptions
-// Note: you can't use XPath with PUGIXML_NO_EXCEPTIONS
 #define PUGIXML_NO_EXCEPTIONS
 
 // Set this to control attributes for public classes/functions, i.e.:
@@ -34,10 +32,22 @@
 // #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
 // In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
 
+// Tune these constants to adjust memory-related behavior
+// #define PUGIXML_MEMORY_PAGE_SIZE 32768
+// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
+// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
+
+// Uncomment this to switch to header-only version
+// #define PUGIXML_HEADER_ONLY
+// #include "pugixml.cpp"
+
+// Uncomment this to enable long long support
+// #define PUGIXML_HAS_LONG_LONG
+
 #endif
 
 /**
- * Copyright (c) 2006-2010 Arseny Kapoulkine
+ * Copyright (c) 2006-2014 Arseny Kapoulkine
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation

File diff suppressed because it is too large
+ 430 - 141
Source/ThirdParty/PugiXml/src/pugixml.cpp


File diff suppressed because it is too large
+ 386 - 167
Source/ThirdParty/PugiXml/src/pugixml.hpp


+ 4 - 0
Source/ThirdParty/SDL/src/video/windows/SDL_windowsevents.c

@@ -783,6 +783,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
                     return (0);
                 }
             }
+
+            // Urho3D: prevent alert bell sounds from Alt key combinations
+            if ((wParam & 0xFFF0) == SC_KEYMENU)
+                returnCode = 1;            
         }
         break;
 #endif /* System has screensaver support */

+ 5 - 2
Source/ThirdParty/kNet/include/kNet/MessageConnection.h

@@ -16,17 +16,20 @@
 /** @file MessageConnection.h
 	@brief The MessageConnection and ConnectionStatistics classes. */
 
+// Modified by Lasse Oorni for Urho3D
+
 #include <vector>
 #include <map>
 #include <utility>
 #include <set>
 
 #include "kNetBuildConfig.h"
+// Urho3D: include Socket.h first to make sure WS2Include.h is included before windows.h / winsock.h
+#include "Socket.h"
 #include "WaitFreeQueue.h"
-#include "NetworkSimulator.h"
 #include "LockFreePoolAllocator.h"
 #include "Lockable.h"
-#include "Socket.h"
+#include "NetworkSimulator.h"
 #include "IMessageHandler.h"
 #include "BasicSerializedDataTypes.h"
 #include "Datagram.h"

+ 3 - 2
Source/ThirdParty/kNet/include/kNet/Thread.h

@@ -24,6 +24,9 @@
 #include <boost/thread.hpp>
 #else
 
+// Urho3D: include Event.h first to make sure WS2Include.h is included before windows.h / winsock.h
+#include "Event.h"
+
 #ifdef WIN32
 // Urho3D: windows.h in lowercase to fix MinGW cross-compiling on a case-sensitive system
 #include <windows.h>
@@ -31,8 +34,6 @@
 #include <pthread.h>
 #endif
 
-#include "Event.h"
-
 namespace kNet
 {
 typedef void (*ThreadEntryFunc)(void *threadStartData);

+ 3 - 1
Source/ThirdParty/kNet/src/NetworkSimulator.cpp

@@ -12,7 +12,9 @@
    See the License for the specific language governing permissions and
    limitations under the License. */
 
-#include "kNet/NetworkSimulator.h"
+// Modified by Lasse Oorni for Urho3D
+
+// Urho3D: MessageConnection.h already includes NetworkSimulator.h, make sure WS2Include.h is included before windows.h / winsock.h
 #include "kNet/MessageConnection.h"
 
 namespace kNet

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

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -113,6 +113,7 @@ bool noHierarchy_ = false;
 bool noMaterials_ = false;
 bool noTextures_ = false;
 bool noMaterialDiffuseColor_ = false;
+bool noEmptyNodes_ = false;
 bool saveMaterialList_ = false;
 bool includeNonSkinningBones_ = false;
 bool verboseLog_ = false;
@@ -144,6 +145,7 @@ void BuildAndSaveAnimations(OutModel* model = 0);
 
 void ExportScene(const String& outName, bool asPrefab);
 void CollectSceneModels(OutScene& scene, aiNode* node);
+void CreateHierarchy(Scene* scene, aiNode* srcNode, HashMap<aiNode*, Node*>& nodeMapping);
 Node* CreateSceneNode(Scene* scene, aiNode* srcNode, HashMap<aiNode*, Node*>& nodeMapping);
 void BuildAndSaveScene(OutScene& scene, bool asPrefab);
 
@@ -212,7 +214,7 @@ void Run(const Vector<String>& arguments)
             "scene      Output a scene\n"
             "node       Output a node and its children (prefab)\n"
             "dump       Dump scene node structure. No output file is generated\n"
-            "lod        Combine several Atomic models as LOD levels of the output model\n"
+            "lod        Combine several Urho3D models as LOD levels of the output model\n"
             "           Syntax: lod <dist0> <mdl0> <dist1 <mdl1> ... <output file>\n"
             "\n"
             "Options:\n"
@@ -228,6 +230,7 @@ void Run(const Vector<String>& arguments)
             "-ns         Do not create subdirectories for resources\n"
             "-nz         Do not create a zone and a directional light (scene mode only)\n"
             "-nf         Do not fix infacing normals\n"
+            "-ne         Do not save empty nodes (scene mode only)\n"
             "-p <path>   Set path for scene resources. Default is output file path\n"
             "-r <name>   Use the named scene node as root node\n"
             "-f <freq>   Animation tick frequency to use if unspecified. Default 4800\n"
@@ -314,6 +317,10 @@ void Run(const Vector<String>& arguments)
                     noHierarchy_ = true;
                     break;
 
+                case 'e':
+                    noEmptyNodes_ = true;
+                    break;
+
                 case 's':
                     useSubdirs_ = false;
                     break;
@@ -1258,6 +1265,13 @@ void CollectSceneModels(OutScene& scene, aiNode* node)
         CollectSceneModels(scene, node->mChildren[i]);
 }
 
+void CreateHierarchy(Scene* scene, aiNode* srcNode, HashMap<aiNode*, Node*>& nodeMapping)
+{
+    CreateSceneNode(scene, srcNode, nodeMapping);
+    for (unsigned i = 0; i < srcNode->mNumChildren; ++i)
+        CreateHierarchy(scene, srcNode->mChildren[i], nodeMapping);
+}
+
 Node* CreateSceneNode(Scene* scene, aiNode* srcNode, HashMap<aiNode*, Node*>& nodeMapping)
 {
     if (nodeMapping.Contains(srcNode))
@@ -1346,10 +1360,23 @@ void BuildAndSaveScene(OutScene& scene, bool asPrefab)
     ResourceCache* cache = context_->GetSubsystem<ResourceCache>();
 
     HashMap<aiNode*, Node*> nodeMapping;
+
     Node* outRootNode = 0;
-    if (asPrefab || !noHierarchy_)
+    if (asPrefab)
         outRootNode = CreateSceneNode(outScene, rootNode_, nodeMapping);
-    
+    else
+    {
+        // If not saving as a prefab, associate the root node with the scene first to prevent unnecessary creation of a root
+        // However do not do that if the root node does not have an identity matrix, or itself contains a model
+        // (models at the Urho scene root are not preferable)
+        if (ToMatrix3x4(rootNode_->mTransformation).Equals(Matrix3x4::IDENTITY) && !scene.nodes_.Contains(rootNode_))
+           nodeMapping[rootNode_] = outScene;
+    }
+
+    // If is allowed to export empty nodes, export the full Assimp node hierarchy first
+    if (!noHierarchy_ && !noEmptyNodes_)
+        CreateHierarchy(outScene, rootNode_, nodeMapping);
+
     // Create geometry nodes
     for (unsigned i = 0; i < scene.nodes_.Size(); ++i)
     {
@@ -1415,7 +1442,7 @@ void BuildAndSaveScene(OutScene& scene, bool asPrefab)
                 break;
             case aiLightSource_SPOT:
                 outLight->SetLightType(LIGHT_SPOT);
-                outLight->SetFov(light->mAngleOuterCone * M_RADTODEG);
+                outLight->SetFov(light->mAngleOuterCone * 0.5f * M_RADTODEG);
                 break;
             case aiLightSource_POINT:
                 outLight->SetLightType(LIGHT_POINT);

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