Browse Source

Group components into categories. In the Editor app, dynamically create the menu structure based on the component categories. Added new GetCategory() method in Component class and exposed it to script. Reviewed and fixed as necessary the default attributes registration of Component's descendant classes. Removed 'Attenuation' and 'Panning' attributes from SoundSource3D as they are updated constantly in this class. Enhanced Context class to 'register' component category during the component factory registration.

Wei Tjong Yao 12 years ago
parent
commit
8d1c28bc3e
50 changed files with 775 additions and 627 deletions
  1. 13 3
      Bin/Data/Scripts/Editor/EditorUI.as
  2. 33 1
      Docs/ScriptAPI.dox
  3. 2 0
      Engine/Audio/Audio.cpp
  4. 9 7
      Engine/Audio/Audio.h
  5. 4 2
      Engine/Audio/SoundListener.cpp
  6. 73 73
      Engine/Audio/SoundSource.cpp
  7. 8 5
      Engine/Audio/SoundSource3D.cpp
  8. 6 0
      Engine/Core/Context.cpp
  9. 18 9
      Engine/Core/Context.h
  10. 1 0
      Engine/Engine/APITemplates.h
  11. 32 18
      Engine/Engine/SceneAPI.cpp
  12. 1 1
      Engine/Graphics/AnimatedModel.cpp
  13. 2 0
      Engine/Graphics/Animation.cpp
  14. 2 0
      Engine/Graphics/Animation.h
  15. 1 1
      Engine/Graphics/AnimationController.cpp
  16. 3 1
      Engine/Graphics/BillboardSet.cpp
  17. 31 29
      Engine/Graphics/Camera.cpp
  18. 3 1
      Engine/Graphics/CustomGeometry.cpp
  19. 48 46
      Engine/Graphics/DebugRenderer.cpp
  20. 1 1
      Engine/Graphics/DecalSet.cpp
  21. 28 26
      Engine/Graphics/Light.cpp
  22. 67 67
      Engine/Graphics/Octree.cpp
  23. 1 1
      Engine/Graphics/ParticleEmitter.cpp
  24. 6 4
      Engine/Graphics/Skybox.cpp
  25. 3 1
      Engine/Graphics/StaticModel.cpp
  26. 92 90
      Engine/Graphics/Terrain.cpp
  27. 9 7
      Engine/Graphics/Terrain.h
  28. 1 1
      Engine/Graphics/TerrainPatch.cpp
  29. 1 1
      Engine/Graphics/Zone.cpp
  30. 4 2
      Engine/Navigation/Navigable.cpp
  31. 3 3
      Engine/Navigation/Navigable.h
  32. 2 0
      Engine/Navigation/Navigation.cpp
  33. 2 0
      Engine/Navigation/Navigation.h
  34. 3 1
      Engine/Navigation/NavigationMesh.cpp
  35. 3 1
      Engine/Navigation/OffMeshConnection.cpp
  36. 3 1
      Engine/Network/NetworkPriority.cpp
  37. 1 1
      Engine/Physics/CollisionShape.cpp
  38. 1 1
      Engine/Physics/Constraint.cpp
  39. 86 84
      Engine/Physics/PhysicsWorld.cpp
  40. 12 10
      Engine/Physics/PhysicsWorld.h
  41. 47 47
      Engine/Physics/RigidBody.cpp
  42. 27 15
      Engine/Scene/Component.cpp
  43. 3 0
      Engine/Scene/Component.h
  44. 3 0
      Engine/Scene/Scene.cpp
  45. 3 0
      Engine/Scene/Scene.h
  46. 14 12
      Engine/Scene/SmoothedTransform.cpp
  47. 47 45
      Engine/Script/Script.cpp
  48. 8 6
      Engine/Script/Script.h
  49. 1 1
      Engine/Script/ScriptInstance.cpp
  50. 3 1
      Engine/UI/Text3D.cpp

+ 13 - 3
Bin/Data/Scripts/Editor/EditorUI.as

@@ -192,9 +192,17 @@ void CreateMenuBar()
 
 
         Menu@ childMenu = CreateMenuItem("Component", null, SHOW_POPUP_INDICATOR);
         Menu@ childMenu = CreateMenuItem("Component", null, SHOW_POPUP_INDICATOR);
         Window@ childPopup = CreatePopup(childMenu);
         Window@ childPopup = CreatePopup(childMenu);
-        String[] componentTypes = GetAvailableComponents();
-        for (uint i = 0; i < componentTypes.length; ++i)
-            childPopup.AddChild(CreateIconizedMenuItem(componentTypes[i], @PickComponent));
+        String[] componentCategories = GetComponentCategories();
+        for (uint i = 0; i < componentCategories.length; ++i)
+        {
+            Menu@ menu = CreateMenuItem(componentCategories[i], null, SHOW_POPUP_INDICATOR);
+            Window@ popup = CreatePopup(menu);
+            String[] componentTypes = GetComponentsByCategory(componentCategories[i]);
+            for (uint j = 0; j < componentTypes.length; ++j)
+                popup.AddChild(CreateIconizedMenuItem(componentTypes[j], @PickComponent));
+            childPopup.AddChild(menu);
+        }
+        FinalizedPopupMenu(childPopup);
         popup.AddChild(childMenu);
         popup.AddChild(childMenu);
 
 
         childMenu = CreateMenuItem("Builtin object", null, SHOW_POPUP_INDICATOR);
         childMenu = CreateMenuItem("Builtin object", null, SHOW_POPUP_INDICATOR);
@@ -467,8 +475,10 @@ Menu@ CreateMenuItem(const String&in title, MENU_CALLBACK@ callback = null, int
 
 
     if (accelKey != 0)
     if (accelKey != 0)
     {
     {
+        int minWidth = menuText.minWidth;
         menuText.layoutMode = LM_HORIZONTAL;
         menuText.layoutMode = LM_HORIZONTAL;
         menuText.AddChild(CreateAccelKeyText(accelKey, accelQual));
         menuText.AddChild(CreateAccelKeyText(accelKey, accelQual));
+        menuText.minWidth = minWidth;
     }
     }
 
 
     return menu;
     return menu;

+ 33 - 1
Docs/ScriptAPI.dox

@@ -66,7 +66,8 @@ namespace Urho3D
 - String RemoveTrailingSlash(const String&)
 - String RemoveTrailingSlash(const String&)
 - String GetParentPath(const String&)
 - String GetParentPath(const String&)
 - String GetInternalPath(const String&)
 - String GetInternalPath(const String&)
-- String[]@ GetAvailableComponents()
+- String[]@ GetComponentCategories()
+- String[]@ GetComponentsByCategory(const String&)
 - uint GetAlphaFormat()
 - uint GetAlphaFormat()
 - uint GetLuminanceFormat()
 - uint GetLuminanceFormat()
 - uint GetLuminanceAlphaFormat()
 - uint GetLuminanceAlphaFormat()
@@ -1375,6 +1376,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 
 
 
 
@@ -1503,6 +1505,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - Vector3 targetPosition
 - Vector3 targetPosition
 - Quaternion targetRotation
 - Quaternion targetRotation
@@ -1688,6 +1691,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 
 
 
 
@@ -1728,6 +1732,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - float nearClip
 - float nearClip
 - float farClip
 - float farClip
@@ -2117,6 +2122,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2184,6 +2190,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2248,6 +2255,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2305,6 +2313,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2358,6 +2367,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2440,6 +2450,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2526,6 +2537,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 
 
 
 
@@ -2571,6 +2583,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2626,6 +2639,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2689,6 +2703,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2743,6 +2758,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2796,6 +2812,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -2845,6 +2862,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - Material@ material
 - Material@ material
 - Image@ heightMap
 - Image@ heightMap
@@ -2915,6 +2933,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - BoundingBox worldBoundingBox (readonly)
 - BoundingBox worldBoundingBox (readonly)
 - uint numLevels (readonly)
 - uint numLevels (readonly)
@@ -3114,6 +3133,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 
 
 
 
@@ -3152,6 +3172,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - SoundType soundType
 - SoundType soundType
 - float frequency
 - float frequency
@@ -3200,6 +3221,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - SoundType soundType
 - SoundType soundType
 - float frequency
 - float frequency
@@ -4741,6 +4763,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool inView (readonly)
 - bool inView (readonly)
 - bool castShadows
 - bool castShadows
@@ -5455,6 +5478,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - float basePriority
 - float basePriority
 - float distanceFactor
 - float distanceFactor
@@ -5561,6 +5585,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - ShapeType shapeType
 - ShapeType shapeType
 - Vector3 size
 - Vector3 size
@@ -5612,6 +5637,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - float mass
 - float mass
 - Vector3 position
 - Vector3 position
@@ -5670,6 +5696,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - ConstraintType constraintType
 - ConstraintType constraintType
 - Vector3 position
 - Vector3 position
@@ -5734,6 +5761,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - Vector3 gravity
 - Vector3 gravity
 - int fps
 - int fps
@@ -5770,6 +5798,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - bool recursive
 - bool recursive
 
 
@@ -5811,6 +5840,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - int tileSize
 - int tileSize
 - float cellSize
 - float cellSize
@@ -5862,6 +5892,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - Node@ endPoint
 - Node@ endPoint
 - float radius
 - float radius
@@ -5926,6 +5957,7 @@ Properties:<br>
 - bool enabled
 - bool enabled
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
+- String category (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
 - int fixedUpdateFps
 - int fixedUpdateFps
 - ScriptFile@ scriptFile
 - ScriptFile@ scriptFile

+ 2 - 0
Engine/Audio/Audio.cpp

@@ -39,6 +39,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* AUDIO_CATEGORY = "Audio";
+
 static const int MIN_BUFFERLENGTH = 20;
 static const int MIN_BUFFERLENGTH = 20;
 static const int MIN_MIXRATE = 11025;
 static const int MIN_MIXRATE = 11025;
 static const int MAX_MIXRATE = 48000;
 static const int MAX_MIXRATE = 48000;

+ 9 - 7
Engine/Audio/Audio.h

@@ -30,6 +30,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* AUDIO_CATEGORY;
+
 class AudioImpl;
 class AudioImpl;
 class Sound;
 class Sound;
 class SoundListener;
 class SoundListener;
@@ -39,13 +41,13 @@ class SoundSource;
 class Audio : public Object
 class Audio : public Object
 {
 {
     OBJECT(Audio);
     OBJECT(Audio);
-    
+
 public:
 public:
     /// Construct.
     /// Construct.
     Audio(Context* context);
     Audio(Context* context);
     /// Destruct. Terminate the audio thread and free the audio buffer.
     /// Destruct. Terminate the audio thread and free the audio buffer.
     virtual ~Audio();
     virtual ~Audio();
-    
+
     /// Initialize sound output with specified buffer length and output mode.
     /// Initialize sound output with specified buffer length and output mode.
     bool SetMode(int bufferLengthMSec, int mixRate, bool stereo, bool interpolation = true);
     bool SetMode(int bufferLengthMSec, int mixRate, bool stereo, bool interpolation = true);
     /// Run update on sound sources. Not required for continued playback, but frees unused sound sources & sounds and updates 3D positions.
     /// Run update on sound sources. Not required for continued playback, but frees unused sound sources & sounds and updates 3D positions.
@@ -60,7 +62,7 @@ public:
     void SetListener(SoundListener* listener);
     void SetListener(SoundListener* listener);
     /// Stop any sound source playing a certain sound clip.
     /// Stop any sound source playing a certain sound clip.
     void StopSound(Sound* sound);
     void StopSound(Sound* sound);
-    
+
     /// Return byte size of one sample.
     /// Return byte size of one sample.
     unsigned GetSampleSize() const { return sampleSize_; }
     unsigned GetSampleSize() const { return sampleSize_; }
     /// Return mixing rate.
     /// Return mixing rate.
@@ -79,7 +81,7 @@ public:
     SoundListener* GetListener() const;
     SoundListener* GetListener() const;
     /// Return all sound sources.
     /// Return all sound sources.
     const PODVector<SoundSource*>& GetSoundSources() const { return soundSources_; }
     const PODVector<SoundSource*>& GetSoundSources() const { return soundSources_; }
-    
+
     /// Add a sound source to keep track of. Called by SoundSource.
     /// Add a sound source to keep track of. Called by SoundSource.
     void AddSoundSource(SoundSource* soundSource);
     void AddSoundSource(SoundSource* soundSource);
     /// Remove a sound source. Called by SoundSource.
     /// Remove a sound source. Called by SoundSource.
@@ -88,16 +90,16 @@ public:
     Mutex& GetMutex() { return audioMutex_; }
     Mutex& GetMutex() { return audioMutex_; }
     /// Return sound type specific gain multiplied by master gain.
     /// Return sound type specific gain multiplied by master gain.
     float GetSoundSourceMasterGain(SoundType type) const { return masterGain_[SOUND_MASTER] * masterGain_[type]; }
     float GetSoundSourceMasterGain(SoundType type) const { return masterGain_[SOUND_MASTER] * masterGain_[type]; }
-    
+
     /// Mix sound sources into the buffer.
     /// Mix sound sources into the buffer.
     void MixOutput(void *dest, unsigned samples);
     void MixOutput(void *dest, unsigned samples);
-    
+
 private:
 private:
     /// Handle render update event.
     /// Handle render update event.
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
     /// Stop sound output and release the sound buffer.
     /// Stop sound output and release the sound buffer.
     void Release();
     void Release();
-    
+
     /// Clipping buffer for mixing.
     /// Clipping buffer for mixing.
     SharedArrayPtr<int> clipBuffer_;
     SharedArrayPtr<int> clipBuffer_;
     /// Audio thread mutex.
     /// Audio thread mutex.

+ 4 - 2
Engine/Audio/SoundListener.cpp

@@ -29,6 +29,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* AUDIO_CATEGORY;
+
 OBJECTTYPESTATIC(SoundListener);
 OBJECTTYPESTATIC(SoundListener);
 
 
 SoundListener::SoundListener(Context* context) :
 SoundListener::SoundListener(Context* context) :
@@ -42,8 +44,8 @@ SoundListener::~SoundListener()
 
 
 void SoundListener::RegisterObject(Context* context)
 void SoundListener::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<SoundListener>();
-    
+    context->RegisterComponentFactory<SoundListener>(AUDIO_CATEGORY);
+
     ACCESSOR_ATTRIBUTE(SoundListener, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(SoundListener, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
 }
 }
 
 

+ 73 - 73
Engine/Audio/SoundSource.cpp

@@ -119,7 +119,7 @@ SoundSource::SoundSource(Context* context) :
     decodePosition_(0)
     decodePosition_(0)
 {
 {
     audio_ = GetSubsystem<Audio>();
     audio_ = GetSubsystem<Audio>();
-    
+
     if (audio_)
     if (audio_)
         audio_->AddSoundSource(this);
         audio_->AddSoundSource(this);
 }
 }
@@ -128,14 +128,14 @@ SoundSource::~SoundSource()
 {
 {
     if (audio_)
     if (audio_)
         audio_->RemoveSoundSource(this);
         audio_->RemoveSoundSource(this);
-    
+
     FreeDecoder();
     FreeDecoder();
 }
 }
 
 
 void SoundSource::RegisterObject(Context* context)
 void SoundSource::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<SoundSource>();
-    
+    context->RegisterComponentFactory<SoundSource>(AUDIO_CATEGORY);
+
     ACCESSOR_ATTRIBUTE(SoundSource, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(SoundSource, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ENUM_ATTRIBUTE(SoundSource, "Sound Type", soundType_, typeNames, SOUND_EFFECT, AM_DEFAULT);
     ENUM_ATTRIBUTE(SoundSource, "Sound Type", soundType_, typeNames, SOUND_EFFECT, AM_DEFAULT);
     ATTRIBUTE(SoundSource, VAR_FLOAT, "Frequency", frequency_, 0.0f, AM_DEFAULT);
     ATTRIBUTE(SoundSource, VAR_FLOAT, "Frequency", frequency_, 0.0f, AM_DEFAULT);
@@ -151,11 +151,11 @@ void SoundSource::Play(Sound* sound)
 {
 {
     if (!audio_)
     if (!audio_)
         return;
         return;
-    
+
     // If no frequency set yet, set from the sound's default
     // If no frequency set yet, set from the sound's default
     if (frequency_ == 0.0f && sound)
     if (frequency_ == 0.0f && sound)
         SetFrequency(sound->GetFrequency());
         SetFrequency(sound->GetFrequency());
-    
+
     // If sound source is currently playing, have to lock the audio mutex
     // If sound source is currently playing, have to lock the audio mutex
     if (position_)
     if (position_)
     {
     {
@@ -164,7 +164,7 @@ void SoundSource::Play(Sound* sound)
     }
     }
     else
     else
         PlayLockless(sound);
         PlayLockless(sound);
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -193,18 +193,18 @@ void SoundSource::Stop()
 {
 {
     if (!audio_)
     if (!audio_)
         return;
         return;
-    
+
     // If sound source is currently playing, have to lock the audio mutex
     // If sound source is currently playing, have to lock the audio mutex
     if (position_)
     if (position_)
     {
     {
         MutexLock lock(audio_->GetMutex());
         MutexLock lock(audio_->GetMutex());
         StopLockless();
         StopLockless();
     }
     }
-    
+
     // Free the compressed sound decoder now if any
     // Free the compressed sound decoder now if any
     FreeDecoder();
     FreeDecoder();
     sound_.Reset();
     sound_.Reset();
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -212,7 +212,7 @@ void SoundSource::SetSoundType(SoundType type)
 {
 {
     if (type == SOUND_MASTER || type >= MAX_SOUND_TYPES)
     if (type == SOUND_MASTER || type >= MAX_SOUND_TYPES)
         return;
         return;
-    
+
     soundType_ = type;
     soundType_ = type;
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
@@ -255,7 +255,7 @@ void SoundSource::SetPlayPosition(signed char* pos)
 {
 {
     if (!audio_ || !sound_)
     if (!audio_ || !sound_)
         return;
         return;
-    
+
     MutexLock lock(audio_->GetMutex());
     MutexLock lock(audio_->GetMutex());
     SetPlayPositionLockless(pos);
     SetPlayPositionLockless(pos);
 }
 }
@@ -264,7 +264,7 @@ void SoundSource::PlayLockless(Sound* sound)
 {
 {
     // Reset the time position in any case
     // Reset the time position in any case
     timePosition_ = 0.0f;
     timePosition_ = 0.0f;
-    
+
     if (sound)
     if (sound)
     {
     {
         if (!sound->IsCompressed())
         if (!sound->IsCompressed())
@@ -300,7 +300,7 @@ void SoundSource::PlayLockless(Sound* sound)
             }
             }
         }
         }
     }
     }
-    
+
     // If sound pointer is null or if sound has no data, stop playback
     // If sound pointer is null or if sound has no data, stop playback
     FreeDecoder();
     FreeDecoder();
     sound_.Reset();
     sound_.Reset();
@@ -318,7 +318,7 @@ void SoundSource::SetPlayPositionLockless(signed char* pos)
     // Setting position on a compressed sound is not supported
     // Setting position on a compressed sound is not supported
     if (!sound_ || sound_->IsCompressed())
     if (!sound_ || sound_->IsCompressed())
         return;
         return;
-    
+
     signed char* start = sound_->GetStart();
     signed char* start = sound_->GetStart();
     signed char* end = sound_->GetEnd();
     signed char* end = sound_->GetEnd();
     if (pos < start)
     if (pos < start)
@@ -327,7 +327,7 @@ void SoundSource::SetPlayPositionLockless(signed char* pos)
         ++pos;
         ++pos;
     if (pos > end)
     if (pos > end)
         pos = end;
         pos = end;
-    
+
     position_ = pos;
     position_ = pos;
     timePosition_ = ((float)(int)(size_t)(pos - sound_->GetStart())) / (sound_->GetSampleSize() * sound_->GetFrequency());
     timePosition_ = ((float)(int)(size_t)(pos - sound_->GetStart())) / (sound_->GetSampleSize() * sound_->GetFrequency());
 }
 }
@@ -336,18 +336,18 @@ void SoundSource::Update(float timeStep)
 {
 {
     if (!audio_ || !IsEnabledEffective())
     if (!audio_ || !IsEnabledEffective())
         return;
         return;
-    
+
     // If there is no actual audio output, perform fake mixing into a nonexistent buffer to check stopping/looping
     // If there is no actual audio output, perform fake mixing into a nonexistent buffer to check stopping/looping
     if (!audio_->IsInitialized())
     if (!audio_->IsInitialized())
         MixNull(timeStep);
         MixNull(timeStep);
-    
+
     // Free the sound if playback has stopped
     // Free the sound if playback has stopped
     if (sound_ && !position_)
     if (sound_ && !position_)
     {
     {
         FreeDecoder();
         FreeDecoder();
         sound_.Reset();
         sound_.Reset();
     }
     }
-    
+
     // Check for autoremove
     // Check for autoremove
     if (autoRemove_)
     if (autoRemove_)
     {
     {
@@ -370,7 +370,7 @@ void SoundSource::Mix(int* dest, unsigned samples, int mixRate, bool stereo, boo
 {
 {
     if (!position_ || !sound_ || !IsEnabledEffective())
     if (!position_ || !sound_ || !IsEnabledEffective())
         return;
         return;
-    
+
     if (sound_->IsCompressed())
     if (sound_->IsCompressed())
     {
     {
         if (decoder_)
         if (decoder_)
@@ -404,13 +404,13 @@ void SoundSource::Mix(int* dest, unsigned samples, int mixRate, bool stereo, boo
                         if (sound_->IsLooped())
                         if (sound_->IsLooped())
                             eof = true;
                             eof = true;
                     }
                     }
-                    
+
                     // If wrote to buffer start, correct interpolation wraparound
                     // If wrote to buffer start, correct interpolation wraparound
                     if (!decodePosition_)
                     if (!decodePosition_)
                         decodeBuffer_->FixInterpolation();
                         decodeBuffer_->FixInterpolation();
                 }
                 }
             }
             }
-            
+
             // If end of stream encountered, check whether we should rewind or stop
             // If end of stream encountered, check whether we should rewind or stop
             if (eof)
             if (eof)
             {
             {
@@ -422,7 +422,7 @@ void SoundSource::Mix(int* dest, unsigned samples, int mixRate, bool stereo, boo
                 else
                 else
                     decodeBuffer_->SetLooped(false); // Stop after the current decode buffer has been played
                     decodeBuffer_->SetLooped(false); // Stop after the current decode buffer has been played
             }
             }
-            
+
             decodePosition_ = currentPos;
             decodePosition_ = currentPos;
         }
         }
         else
         else
@@ -434,24 +434,24 @@ void SoundSource::Mix(int* dest, unsigned samples, int mixRate, bool stereo, boo
             decodeBuffer_ = new Sound(context_);
             decodeBuffer_ = new Sound(context_);
             decodeBuffer_->SetSize(DecodeBufferSize);
             decodeBuffer_->SetSize(DecodeBufferSize);
             decodeBuffer_->SetFormat(sound_->GetIntFrequency(), true, sound_->IsStereo());
             decodeBuffer_->SetFormat(sound_->GetIntFrequency(), true, sound_->IsStereo());
-            
+
             // Clear the decode buffer, then fill with initial audio data and set it to loop
             // Clear the decode buffer, then fill with initial audio data and set it to loop
             memset(decodeBuffer_->GetStart(), 0, DecodeBufferSize);
             memset(decodeBuffer_->GetStart(), 0, DecodeBufferSize);
             sound_->Decode(decoder_, decodeBuffer_->GetStart(), DecodeBufferSize);
             sound_->Decode(decoder_, decodeBuffer_->GetStart(), DecodeBufferSize);
             decodeBuffer_->SetLooped(true);
             decodeBuffer_->SetLooped(true);
             decodePosition_ = 0;
             decodePosition_ = 0;
-            
+
             // Start playing the decode buffer
             // Start playing the decode buffer
             position_ = decodeBuffer_->GetStart();
             position_ = decodeBuffer_->GetStart();
             fractPosition_ = 0;
             fractPosition_ = 0;
         }
         }
     }
     }
-    
+
     // If compressed, play the decode buffer. Otherwise play the original sound
     // If compressed, play the decode buffer. Otherwise play the original sound
     Sound* sound = sound_->IsCompressed() ? decodeBuffer_ : sound_;
     Sound* sound = sound_->IsCompressed() ? decodeBuffer_ : sound_;
     if (!sound)
     if (!sound)
         return;
         return;
-    
+
     // Choose the correct mixing routine
     // Choose the correct mixing routine
     if (!sound->IsStereo())
     if (!sound->IsStereo())
     {
     {
@@ -487,7 +487,7 @@ void SoundSource::Mix(int* dest, unsigned samples, int mixRate, bool stereo, boo
                 MixStereoToMono(sound, dest, samples, mixRate);
                 MixStereoToMono(sound, dest, samples, mixRate);
         }
         }
     }
     }
-    
+
     // Update the time position
     // Update the time position
     if (!sound_->IsCompressed())
     if (!sound_->IsCompressed())
         timePosition_ = ((float)(int)(size_t)(position_ - sound_->GetStart())) / (sound_->GetSampleSize() * sound_->GetFrequency());
         timePosition_ = ((float)(int)(size_t)(position_ - sound_->GetStart())) / (sound_->GetSampleSize() * sound_->GetFrequency());
@@ -529,18 +529,18 @@ void SoundSource::MixMonoToMono(Sound* sound, int* dest, unsigned samples, int m
         MixZeroVolume(sound, samples, mixRate);
         MixZeroVolume(sound, samples, mixRate);
         return;
         return;
     }
     }
-    
+
     float add = frequency_ / (float)mixRate;
     float add = frequency_ / (float)mixRate;
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractPos = fractPosition_;
     int fractPos = fractPosition_;
-    
+
     if (sound->IsSixteenBit())
     if (sound->IsSixteenBit())
     {
     {
         short* pos = (short*)position_;
         short* pos = (short*)position_;
         short* end = (short*)sound->GetEnd();
         short* end = (short*)sound->GetEnd();
         short* repeat = (short*)sound->GetRepeat();
         short* repeat = (short*)sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -567,7 +567,7 @@ void SoundSource::MixMonoToMono(Sound* sound, int* dest, unsigned samples, int m
         signed char* pos = (signed char*)position_;
         signed char* pos = (signed char*)position_;
         signed char* end = sound->GetEnd();
         signed char* end = sound->GetEnd();
         signed char* repeat = sound->GetRepeat();
         signed char* repeat = sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -589,7 +589,7 @@ void SoundSource::MixMonoToMono(Sound* sound, int* dest, unsigned samples, int m
             position_ = pos;
             position_ = pos;
         }
         }
     }
     }
-    
+
     fractPosition_ = fractPos;
     fractPosition_ = fractPos;
 }
 }
 
 
@@ -603,18 +603,18 @@ void SoundSource::MixMonoToStereo(Sound* sound, int* dest, unsigned samples, int
         MixZeroVolume(sound, samples, mixRate);
         MixZeroVolume(sound, samples, mixRate);
         return;
         return;
     }
     }
-    
+
     float add = frequency_ / (float)mixRate;
     float add = frequency_ / (float)mixRate;
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractPos = fractPosition_;
     int fractPos = fractPosition_;
-    
+
     if (sound->IsSixteenBit())
     if (sound->IsSixteenBit())
     {
     {
         short* pos = (short*)position_;
         short* pos = (short*)position_;
         short* end = (short*)sound->GetEnd();
         short* end = (short*)sound->GetEnd();
         short* repeat = (short*)sound->GetRepeat();
         short* repeat = (short*)sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -645,7 +645,7 @@ void SoundSource::MixMonoToStereo(Sound* sound, int* dest, unsigned samples, int
         signed char* pos = (signed char*)position_;
         signed char* pos = (signed char*)position_;
         signed char* end = sound->GetEnd();
         signed char* end = sound->GetEnd();
         signed char* repeat = sound->GetRepeat();
         signed char* repeat = sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -671,7 +671,7 @@ void SoundSource::MixMonoToStereo(Sound* sound, int* dest, unsigned samples, int
             position_ = pos;
             position_ = pos;
         }
         }
     }
     }
-    
+
     fractPosition_ = fractPos;
     fractPosition_ = fractPos;
 }
 }
 
 
@@ -684,18 +684,18 @@ void SoundSource::MixMonoToMonoIP(Sound* sound, int* dest, unsigned samples, int
         MixZeroVolume(sound, samples, mixRate);
         MixZeroVolume(sound, samples, mixRate);
         return;
         return;
     }
     }
-    
+
     float add = frequency_ / (float)mixRate;
     float add = frequency_ / (float)mixRate;
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractPos = fractPosition_;
     int fractPos = fractPosition_;
-    
+
     if (sound->IsSixteenBit())
     if (sound->IsSixteenBit())
     {
     {
         short* pos = (short*)position_;
         short* pos = (short*)position_;
         short* end = (short*)sound->GetEnd();
         short* end = (short*)sound->GetEnd();
         short* repeat = (short*)sound->GetRepeat();
         short* repeat = (short*)sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -722,7 +722,7 @@ void SoundSource::MixMonoToMonoIP(Sound* sound, int* dest, unsigned samples, int
         signed char* pos = (signed char*)position_;
         signed char* pos = (signed char*)position_;
         signed char* end = sound->GetEnd();
         signed char* end = sound->GetEnd();
         signed char* repeat = sound->GetRepeat();
         signed char* repeat = sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -744,7 +744,7 @@ void SoundSource::MixMonoToMonoIP(Sound* sound, int* dest, unsigned samples, int
             position_ = pos;
             position_ = pos;
         }
         }
     }
     }
-    
+
     fractPosition_ = fractPos;
     fractPosition_ = fractPos;
 }
 }
 
 
@@ -758,18 +758,18 @@ void SoundSource::MixMonoToStereoIP(Sound* sound, int* dest, unsigned samples, i
         MixZeroVolume(sound, samples, mixRate);
         MixZeroVolume(sound, samples, mixRate);
         return;
         return;
     }
     }
-    
+
     float add = frequency_ / (float)mixRate;
     float add = frequency_ / (float)mixRate;
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractPos = fractPosition_;
     int fractPos = fractPosition_;
-    
+
     if (sound->IsSixteenBit())
     if (sound->IsSixteenBit())
     {
     {
         short* pos = (short*)position_;
         short* pos = (short*)position_;
         short* end = (short*)sound->GetEnd();
         short* end = (short*)sound->GetEnd();
         short* repeat = (short*)sound->GetRepeat();
         short* repeat = (short*)sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -802,7 +802,7 @@ void SoundSource::MixMonoToStereoIP(Sound* sound, int* dest, unsigned samples, i
         signed char* pos = (signed char*)position_;
         signed char* pos = (signed char*)position_;
         signed char* end = sound->GetEnd();
         signed char* end = sound->GetEnd();
         signed char* repeat = sound->GetRepeat();
         signed char* repeat = sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -830,7 +830,7 @@ void SoundSource::MixMonoToStereoIP(Sound* sound, int* dest, unsigned samples, i
             position_ = pos;
             position_ = pos;
         }
         }
     }
     }
-    
+
     fractPosition_ = fractPos;
     fractPosition_ = fractPos;
 }
 }
 
 
@@ -843,18 +843,18 @@ void SoundSource::MixStereoToMono(Sound* sound, int* dest, unsigned samples, int
         MixZeroVolume(sound, samples, mixRate);
         MixZeroVolume(sound, samples, mixRate);
         return;
         return;
     }
     }
-    
+
     float add = frequency_ / (float)mixRate;
     float add = frequency_ / (float)mixRate;
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractPos = fractPosition_;
     int fractPos = fractPosition_;
-    
+
     if (sound->IsSixteenBit())
     if (sound->IsSixteenBit())
     {
     {
         short* pos = (short*)position_;
         short* pos = (short*)position_;
         short* end = (short*)sound->GetEnd();
         short* end = (short*)sound->GetEnd();
         short* repeat = (short*)sound->GetRepeat();
         short* repeat = (short*)sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -883,7 +883,7 @@ void SoundSource::MixStereoToMono(Sound* sound, int* dest, unsigned samples, int
         signed char* pos = (signed char*)position_;
         signed char* pos = (signed char*)position_;
         signed char* end = sound->GetEnd();
         signed char* end = sound->GetEnd();
         signed char* repeat = sound->GetRepeat();
         signed char* repeat = sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -907,7 +907,7 @@ void SoundSource::MixStereoToMono(Sound* sound, int* dest, unsigned samples, int
             position_ = pos;
             position_ = pos;
         }
         }
     }
     }
-    
+
     fractPosition_ = fractPos;
     fractPosition_ = fractPos;
 }
 }
 
 
@@ -920,18 +920,18 @@ void SoundSource::MixStereoToStereo(Sound* sound, int* dest, unsigned samples, i
         MixZeroVolume(sound, samples, mixRate);
         MixZeroVolume(sound, samples, mixRate);
         return;
         return;
     }
     }
-    
+
     float add = frequency_ / (float)mixRate;
     float add = frequency_ / (float)mixRate;
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractPos = fractPosition_;
     int fractPos = fractPosition_;
-    
+
     if (sound->IsSixteenBit())
     if (sound->IsSixteenBit())
     {
     {
         short* pos = (short*)position_;
         short* pos = (short*)position_;
         short* end = (short*)sound->GetEnd();
         short* end = (short*)sound->GetEnd();
         short* repeat = (short*)sound->GetRepeat();
         short* repeat = (short*)sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -962,7 +962,7 @@ void SoundSource::MixStereoToStereo(Sound* sound, int* dest, unsigned samples, i
         signed char* pos = (signed char*)position_;
         signed char* pos = (signed char*)position_;
         signed char* end = sound->GetEnd();
         signed char* end = sound->GetEnd();
         signed char* repeat = sound->GetRepeat();
         signed char* repeat = sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -988,7 +988,7 @@ void SoundSource::MixStereoToStereo(Sound* sound, int* dest, unsigned samples, i
             position_ = pos;
             position_ = pos;
         }
         }
     }
     }
-    
+
     fractPosition_ = fractPos;
     fractPosition_ = fractPos;
 }
 }
 
 
@@ -1001,18 +1001,18 @@ void SoundSource::MixStereoToMonoIP(Sound* sound, int* dest, unsigned samples, i
         MixZeroVolume(sound, samples, mixRate);
         MixZeroVolume(sound, samples, mixRate);
         return;
         return;
     }
     }
-    
+
     float add = frequency_ / (float)mixRate;
     float add = frequency_ / (float)mixRate;
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractPos = fractPosition_;
     int fractPos = fractPosition_;
-    
+
     if (sound->IsSixteenBit())
     if (sound->IsSixteenBit())
     {
     {
         short* pos = (short*)position_;
         short* pos = (short*)position_;
         short* end = (short*)sound->GetEnd();
         short* end = (short*)sound->GetEnd();
         short* repeat = (short*)sound->GetRepeat();
         short* repeat = (short*)sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -1041,7 +1041,7 @@ void SoundSource::MixStereoToMonoIP(Sound* sound, int* dest, unsigned samples, i
         signed char* pos = (signed char*)position_;
         signed char* pos = (signed char*)position_;
         signed char* end = sound->GetEnd();
         signed char* end = sound->GetEnd();
         signed char* repeat = sound->GetRepeat();
         signed char* repeat = sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -1065,7 +1065,7 @@ void SoundSource::MixStereoToMonoIP(Sound* sound, int* dest, unsigned samples, i
             position_ = pos;
             position_ = pos;
         }
         }
     }
     }
-    
+
     fractPosition_ = fractPos;
     fractPosition_ = fractPos;
 }
 }
 
 
@@ -1078,18 +1078,18 @@ void SoundSource::MixStereoToStereoIP(Sound* sound, int* dest, unsigned samples,
         MixZeroVolume(sound, samples, mixRate);
         MixZeroVolume(sound, samples, mixRate);
         return;
         return;
     }
     }
-    
+
     float add = frequency_ / (float)mixRate;
     float add = frequency_ / (float)mixRate;
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractPos = fractPosition_;
     int fractPos = fractPosition_;
-    
+
     if (sound->IsSixteenBit())
     if (sound->IsSixteenBit())
     {
     {
         short* pos = (short*)position_;
         short* pos = (short*)position_;
         short* end = (short*)sound->GetEnd();
         short* end = (short*)sound->GetEnd();
         short* repeat = (short*)sound->GetRepeat();
         short* repeat = (short*)sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -1120,7 +1120,7 @@ void SoundSource::MixStereoToStereoIP(Sound* sound, int* dest, unsigned samples,
         signed char* pos = (signed char*)position_;
         signed char* pos = (signed char*)position_;
         signed char* end = sound->GetEnd();
         signed char* end = sound->GetEnd();
         signed char* repeat = sound->GetRepeat();
         signed char* repeat = sound->GetRepeat();
-        
+
         if (sound->IsLooped())
         if (sound->IsLooped())
         {
         {
             while (--samples)
             while (--samples)
@@ -1146,7 +1146,7 @@ void SoundSource::MixStereoToStereoIP(Sound* sound, int* dest, unsigned samples,
             position_ = pos;
             position_ = pos;
         }
         }
     }
     }
-    
+
     fractPosition_ = fractPos;
     fractPosition_ = fractPos;
 }
 }
 
 
@@ -1156,7 +1156,7 @@ void SoundSource::MixZeroVolume(Sound* sound, unsigned samples, int mixRate)
     int intAdd = (int)add;
     int intAdd = (int)add;
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     int fractAdd = (int)((add - floorf(add)) * 65536.0f);
     unsigned sampleSize = sound->GetSampleSize();
     unsigned sampleSize = sound->GetSampleSize();
-    
+
     fractPosition_ += fractAdd;
     fractPosition_ += fractAdd;
     if (fractPosition_ > 65535)
     if (fractPosition_ > 65535)
     {
     {
@@ -1164,7 +1164,7 @@ void SoundSource::MixZeroVolume(Sound* sound, unsigned samples, int mixRate)
         position_ += sampleSize;
         position_ += sampleSize;
     }
     }
     position_ += intAdd * sampleSize;
     position_ += intAdd * sampleSize;
-    
+
     if (position_ > sound->GetEnd())
     if (position_ > sound->GetEnd())
     {
     {
         if (sound->IsLooped())
         if (sound->IsLooped())
@@ -1183,10 +1183,10 @@ void SoundSource::MixNull(float timeStep)
 {
 {
     if (!position_ || !sound_ || !IsEnabledEffective())
     if (!position_ || !sound_ || !IsEnabledEffective())
         return;
         return;
-    
+
     // Advance only the time position
     // Advance only the time position
     timePosition_ += timeStep * frequency_ / sound_->GetFrequency();
     timePosition_ += timeStep * frequency_ / sound_->GetFrequency();
-    
+
     if (sound_->IsLooped())
     if (sound_->IsLooped())
     {
     {
         // For simulated playback, simply reset the time position to zero when the sound loops
         // For simulated playback, simply reset the time position to zero when the sound loops
@@ -1210,7 +1210,7 @@ void SoundSource::FreeDecoder()
         sound_->FreeDecoder(decoder_);
         sound_->FreeDecoder(decoder_);
         decoder_ = 0;
         decoder_ = 0;
     }
     }
-    
+
     decodeBuffer_.Reset();
     decodeBuffer_.Reset();
 }
 }
 
 

+ 8 - 5
Engine/Audio/SoundSource3D.cpp

@@ -52,9 +52,12 @@ SoundSource3D::SoundSource3D(Context* context) :
 
 
 void SoundSource3D::RegisterObject(Context* context)
 void SoundSource3D::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<SoundSource3D>();
-    
+    context->RegisterComponentFactory<SoundSource3D>(AUDIO_CATEGORY);
+
     COPY_BASE_ATTRIBUTES(SoundSource3D, SoundSource);
     COPY_BASE_ATTRIBUTES(SoundSource3D, SoundSource);
+    // Remove Attenuation and Panning as attribute as they are constantly being updated
+    REMOVE_ATTRIBUTE(SoundSource3D, "Attenuation");
+    REMOVE_ATTRIBUTE(SoundSource3D, "Panning");
     ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Near Distance", nearDistance_, DEFAULT_NEARDISTANCE, AM_DEFAULT);
     ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Near Distance", nearDistance_, DEFAULT_NEARDISTANCE, AM_DEFAULT);
     ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Far Distance", farDistance_, DEFAULT_FARDISTANCE, AM_DEFAULT);
     ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Far Distance", farDistance_, DEFAULT_FARDISTANCE, AM_DEFAULT);
     ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Rolloff Factor", rolloffFactor_, DEFAULT_ROLLOFF, AM_DEFAULT);
     ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Rolloff Factor", rolloffFactor_, DEFAULT_ROLLOFF, AM_DEFAULT);
@@ -96,12 +99,12 @@ void SoundSource3D::CalculateAttenuation()
 {
 {
     if (!audio_)
     if (!audio_)
         return;
         return;
-    
+
     float interval = farDistance_ - nearDistance_;
     float interval = farDistance_ - nearDistance_;
     if (interval > 0.0f && node_)
     if (interval > 0.0f && node_)
     {
     {
         SoundListener* listener = audio_->GetListener();
         SoundListener* listener = audio_->GetListener();
-        
+
         // Listener must either be sceneless or in the same scene, else attenuate sound to silence
         // Listener must either be sceneless or in the same scene, else attenuate sound to silence
         if (listener && listener->IsEnabledEffective() && (!listener->GetScene() || listener->GetScene() == GetScene()))
         if (listener && listener->IsEnabledEffective() && (!listener->GetScene() || listener->GetScene() == GetScene()))
         {
         {
@@ -110,7 +113,7 @@ void SoundSource3D::CalculateAttenuation()
             float distance = Clamp(relativePos.Length() - nearDistance_, 0.0f, interval);
             float distance = Clamp(relativePos.Length() - nearDistance_, 0.0f, interval);
             float attenuation = powf(1.0f - distance / interval, rolloffFactor_);
             float attenuation = powf(1.0f - distance / interval, rolloffFactor_);
             float panning = relativePos.Normalized().x_;
             float panning = relativePos.Normalized().x_;
-            
+
             attenuation_ = attenuation;
             attenuation_ = attenuation;
             panning_ = panning;
             panning_ = panning;
         }
         }

+ 6 - 0
Engine/Core/Context.cpp

@@ -82,6 +82,12 @@ void Context::RegisterFactory(ObjectFactory* factory)
     factories_[factory->GetType()] = factory;
     factories_[factory->GetType()] = factory;
 }
 }
 
 
+void Context::RegisterComponentFactory(ObjectFactory* factory, const char* category)
+{
+    RegisterFactory(factory);
+    componentCategories_[category].Push(factory->GetType());
+}
+
 void Context::RegisterSubsystem(Object* object)
 void Context::RegisterSubsystem(Object* object)
 {
 {
     if (!object)
     if (!object)

+ 18 - 9
Engine/Core/Context.h

@@ -33,17 +33,19 @@ namespace Urho3D
 class Context : public RefCounted
 class Context : public RefCounted
 {
 {
     friend class Object;
     friend class Object;
-    
+
 public:
 public:
     /// Construct.
     /// Construct.
     Context();
     Context();
     /// Destruct.
     /// Destruct.
     ~Context();
     ~Context();
-    
+
     /// Create an object by type hash. Return pointer to it or null if no factory found.
     /// Create an object by type hash. Return pointer to it or null if no factory found.
     SharedPtr<Object> CreateObject(ShortStringHash objectType);
     SharedPtr<Object> CreateObject(ShortStringHash objectType);
     /// Register a factory for an object type.
     /// Register a factory for an object type.
     void RegisterFactory(ObjectFactory* factory);
     void RegisterFactory(ObjectFactory* factory);
+    /// Register a factory for a component type.
+    void RegisterComponentFactory(ObjectFactory* factory, const char* category);
     /// Register a subsystem.
     /// Register a subsystem.
     void RegisterSubsystem(Object* subsystem);
     void RegisterSubsystem(Object* subsystem);
     /// Remove a subsystem.
     /// Remove a subsystem.
@@ -54,11 +56,13 @@ public:
     void RemoveAttribute(ShortStringHash objectType, const char* name);
     void RemoveAttribute(ShortStringHash objectType, const char* name);
     /// Update object attribute's default value.
     /// Update object attribute's default value.
     void UpdateAttributeDefaultValue(ShortStringHash objectType, const char* name, const Variant& defaultValue);
     void UpdateAttributeDefaultValue(ShortStringHash objectType, const char* name, const Variant& defaultValue);
-    
+
     /// Copy base class attributes to derived class.
     /// Copy base class attributes to derived class.
     void CopyBaseAttributes(ShortStringHash baseType, ShortStringHash derivedType);
     void CopyBaseAttributes(ShortStringHash baseType, ShortStringHash derivedType);
     /// Template version of registering an object factory.
     /// Template version of registering an object factory.
     template <class T> void RegisterFactory();
     template <class T> void RegisterFactory();
+    /// Template version of registering a component factory.
+    template <class T> void RegisterComponentFactory(const char* category);
     /// Template version of removing a subsystem.
     /// Template version of removing a subsystem.
     template <class T> void RemoveSubsystem();
     template <class T> void RemoveSubsystem();
     /// Template version of registering an object attribute.
     /// Template version of registering an object attribute.
@@ -69,13 +73,15 @@ public:
     template <class T, class U> void CopyBaseAttributes();
     template <class T, class U> void CopyBaseAttributes();
     /// Template version of updating an object attribute's default value.
     /// Template version of updating an object attribute's default value.
     template <class T> void UpdateAttributeDefaultValue(const char* name, const Variant& defaultValue);
     template <class T> void UpdateAttributeDefaultValue(const char* name, const Variant& defaultValue);
-    
+
     /// Return subsystem by type.
     /// Return subsystem by type.
     Object* GetSubsystem(ShortStringHash type) const;
     Object* GetSubsystem(ShortStringHash type) const;
     /// Return all subsystems.
     /// Return all subsystems.
     const HashMap<ShortStringHash, SharedPtr<Object> >& GetSubsystems() const { return subsystems_; }
     const HashMap<ShortStringHash, SharedPtr<Object> >& GetSubsystems() const { return subsystems_; }
     /// Return all object factories.
     /// Return all object factories.
     const HashMap<ShortStringHash, SharedPtr<ObjectFactory> >& GetObjectFactories() const { return factories_; }
     const HashMap<ShortStringHash, SharedPtr<ObjectFactory> >& GetObjectFactories() const { return factories_; }
+    /// Return all component categories.
+    const HashMap<String, Vector<ShortStringHash> >& GetComponentCategories() const { return componentCategories_; }
     /// Return active event sender. Null outside event handling.
     /// Return active event sender. Null outside event handling.
     Object* GetEventSender() const;
     Object* GetEventSender() const;
     /// Return active event handler. Set by Object. Null outside event handling.
     /// Return active event handler. Set by Object. Null outside event handling.
@@ -88,21 +94,21 @@ public:
     template <class T> T* GetSubsystem() const;
     template <class T> T* GetSubsystem() const;
     /// Template version of returning a specific attribute description.
     /// Template version of returning a specific attribute description.
     template <class T> AttributeInfo* GetAttribute(const char* name);
     template <class T> AttributeInfo* GetAttribute(const char* name);
-    
+
     /// Return attribute descriptions for an object type, or null if none defined.
     /// Return attribute descriptions for an object type, or null if none defined.
     const Vector<AttributeInfo>* GetAttributes(ShortStringHash type) const
     const Vector<AttributeInfo>* GetAttributes(ShortStringHash type) const
     {
     {
         HashMap<ShortStringHash, Vector<AttributeInfo> >::ConstIterator i = attributes_.Find(type);
         HashMap<ShortStringHash, Vector<AttributeInfo> >::ConstIterator i = attributes_.Find(type);
         return i != attributes_.End() ? &i->second_ : 0;
         return i != attributes_.End() ? &i->second_ : 0;
     }
     }
-    
+
     /// Return network replication attribute descriptions for an object type, or null if none defined.
     /// Return network replication attribute descriptions for an object type, or null if none defined.
     const Vector<AttributeInfo>* GetNetworkAttributes(ShortStringHash type) const
     const Vector<AttributeInfo>* GetNetworkAttributes(ShortStringHash type) const
     {
     {
         HashMap<ShortStringHash, Vector<AttributeInfo> >::ConstIterator i = networkAttributes_.Find(type);
         HashMap<ShortStringHash, Vector<AttributeInfo> >::ConstIterator i = networkAttributes_.Find(type);
         return i != networkAttributes_.End() ? &i->second_ : 0;
         return i != networkAttributes_.End() ? &i->second_ : 0;
     }
     }
-    
+
     /// Return event receivers for a sender and event type, or null if they do not exist.
     /// Return event receivers for a sender and event type, or null if they do not exist.
     HashSet<Object*>* GetEventReceivers(Object* sender, StringHash eventType)
     HashSet<Object*>* GetEventReceivers(Object* sender, StringHash eventType)
     {
     {
@@ -115,14 +121,14 @@ public:
         else
         else
             return 0;
             return 0;
     }
     }
-    
+
     /// Return event receivers for an event type, or null if they do not exist.
     /// Return event receivers for an event type, or null if they do not exist.
     HashSet<Object*>* GetEventReceivers(StringHash eventType)
     HashSet<Object*>* GetEventReceivers(StringHash eventType)
     {
     {
         HashMap<StringHash, HashSet<Object*> >::Iterator i = eventReceivers_.Find(eventType);
         HashMap<StringHash, HashSet<Object*> >::Iterator i = eventReceivers_.Find(eventType);
         return i != eventReceivers_.End() ? &i->second_ : 0;
         return i != eventReceivers_.End() ? &i->second_ : 0;
     }
     }
-    
+
 private:
 private:
     /// Add event receiver.
     /// Add event receiver.
     void AddEventReceiver(Object* receiver, StringHash eventType);
     void AddEventReceiver(Object* receiver, StringHash eventType);
@@ -157,9 +163,12 @@ private:
     PODVector<Object*> eventSenders_;
     PODVector<Object*> eventSenders_;
     /// Active event handler. Not stored in a stack for performance reasons; is needed only in esoteric cases.
     /// Active event handler. Not stored in a stack for performance reasons; is needed only in esoteric cases.
     EventHandler* eventHandler_;
     EventHandler* eventHandler_;
+    /// Component categories.
+    HashMap<String, Vector<ShortStringHash> > componentCategories_;
 };
 };
 
 
 template <class T> void Context::RegisterFactory() { RegisterFactory(new ObjectFactoryImpl<T>(this)); }
 template <class T> void Context::RegisterFactory() { RegisterFactory(new ObjectFactoryImpl<T>(this)); }
+template <class T> void Context::RegisterComponentFactory(const char* category) { RegisterComponentFactory(new ObjectFactoryImpl<T>(this), category); }
 template <class T> void Context::RemoveSubsystem() { RemoveSubsystem(T::GetTypeStatic()); }
 template <class T> void Context::RemoveSubsystem() { RemoveSubsystem(T::GetTypeStatic()); }
 template <class T> void Context::RegisterAttribute(const AttributeInfo& attr) { RegisterAttribute(T::GetTypeStatic(), attr); }
 template <class T> void Context::RegisterAttribute(const AttributeInfo& attr) { RegisterAttribute(T::GetTypeStatic(), attr); }
 template <class T> void Context::RemoveAttribute(const char* name) { RemoveAttribute(T::GetTypeStatic(), name); }
 template <class T> void Context::RemoveAttribute(const char* name) { RemoveAttribute(T::GetTypeStatic(), name); }

+ 1 - 0
Engine/Engine/APITemplates.h

@@ -399,6 +399,7 @@ template <class T> void RegisterComponent(asIScriptEngine* engine, const char* c
     engine->RegisterObjectMethod(className, "bool get_enabled() const", asMETHODPR(T, IsEnabled, () const, bool), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_enabled() const", asMETHODPR(T, IsEnabled, () const, bool), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_enabledEffective() const", asMETHODPR(T, IsEnabledEffective, () const, bool), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_enabledEffective() const", asMETHODPR(T, IsEnabledEffective, () const, bool), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "uint get_id()", asMETHODPR(T, GetID, () const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "uint get_id()", asMETHODPR(T, GetID, () const, unsigned), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "const String& get_category() const", asMETHOD(T, GetCategory), asCALL_THISCALL);
     if (nodeRegistered)
     if (nodeRegistered)
         engine->RegisterObjectMethod(className, "Node@+ get_node() const", asMETHODPR(T, GetNode, () const, Node*), asCALL_THISCALL);
         engine->RegisterObjectMethod(className, "Node@+ get_node() const", asMETHODPR(T, GetNode, () const, Node*), asCALL_THISCALL);
     if (debugRendererRegistered)
     if (debugRendererRegistered)

+ 32 - 18
Engine/Engine/SceneAPI.cpp

@@ -39,7 +39,7 @@ static void RegisterSerializable(asIScriptEngine* engine)
     engine->RegisterGlobalProperty("const uint AM_NOEDIT", (void*)&AM_NOEDIT);
     engine->RegisterGlobalProperty("const uint AM_NOEDIT", (void*)&AM_NOEDIT);
     engine->RegisterGlobalProperty("const uint AM_NODEID", (void*)&AM_NODEID);
     engine->RegisterGlobalProperty("const uint AM_NODEID", (void*)&AM_NODEID);
     engine->RegisterGlobalProperty("const uint AM_COMPONENTID", (void*)&AM_COMPONENTID);
     engine->RegisterGlobalProperty("const uint AM_COMPONENTID", (void*)&AM_COMPONENTID);
-    
+
     RegisterSerializable<Serializable>(engine, "Serializable");
     RegisterSerializable<Serializable>(engine, "Serializable");
 }
 }
 
 
@@ -56,7 +56,7 @@ static void RegisterNode(asIScriptEngine* engine)
     engine->RegisterEnum("CreateMode");
     engine->RegisterEnum("CreateMode");
     engine->RegisterEnumValue("CreateMode", "REPLICATED", REPLICATED);
     engine->RegisterEnumValue("CreateMode", "REPLICATED", REPLICATED);
     engine->RegisterEnumValue("CreateMode", "LOCAL", LOCAL);
     engine->RegisterEnumValue("CreateMode", "LOCAL", LOCAL);
-    
+
     // Register Component first. At this point Node is not yet registered, so can not register GetNode for Component
     // Register Component first. At this point Node is not yet registered, so can not register GetNode for Component
     RegisterComponent<Component>(engine, "Component", false, false);
     RegisterComponent<Component>(engine, "Component", false, false);
     RegisterNode<Node>(engine, "Node");
     RegisterNode<Node>(engine, "Node");
@@ -68,10 +68,10 @@ static void RegisterNode(asIScriptEngine* engine)
     RegisterObjectConstructor<Node>(engine, "Node");
     RegisterObjectConstructor<Node>(engine, "Node");
     RegisterNamedObjectConstructor<Node>(engine, "Node");
     RegisterNamedObjectConstructor<Node>(engine, "Node");
     engine->RegisterGlobalFunction("Node@+ get_node()", asFUNCTION(GetScriptContextNode), asCALL_CDECL);
     engine->RegisterGlobalFunction("Node@+ get_node()", asFUNCTION(GetScriptContextNode), asCALL_CDECL);
-    
+
     // Now GetNode can be registered
     // Now GetNode can be registered
     engine->RegisterObjectMethod("Component", "Node@+ get_node() const", asMETHOD(Component, GetNode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Component", "Node@+ get_node() const", asMETHOD(Component, GetNode), asCALL_THISCALL);
-    
+
     // Register Variant GetPtr() for Node & Component
     // Register Variant GetPtr() for Node & Component
     engine->RegisterObjectMethod("Variant", "Node@+ GetNode() const", asFUNCTION(GetVariantPtr<Node>), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Variant", "Node@+ GetNode() const", asFUNCTION(GetVariantPtr<Node>), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Variant", "Component@+ GetComponent() const", asFUNCTION(GetVariantPtr<Component>), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Variant", "Component@+ GetComponent() const", asFUNCTION(GetVariantPtr<Component>), asCALL_CDECL_OBJLAST);
@@ -122,20 +122,33 @@ static CScriptArray* SceneGetRequiredPackageFiles(Scene* ptr)
     return VectorToHandleArray<PackageFile>(ptr->GetRequiredPackageFiles(), "Array<PackageFile@>");
     return VectorToHandleArray<PackageFile>(ptr->GetRequiredPackageFiles(), "Array<PackageFile@>");
 }
 }
 
 
-static CScriptArray* GetAvailableComponents(Scene* ptr)
+static CScriptArray* GetComponentCategories()
+{
+    Vector<String> categories = GetScriptContext()->GetComponentCategories().Keys();
+    Sort(categories.Begin(), categories.End());
+    return VectorToArray<String>(categories, "Array<String>");
+}
+
+static CScriptArray* GetComponentsByCategory(const String& category)
 {
 {
-    const HashMap<ShortStringHash, SharedPtr<ObjectFactory> >& factories = GetScriptContext()->GetObjectFactories();
+    const HashMap<String, Vector<ShortStringHash> >& categories = GetScriptContext()->GetComponentCategories();
     Vector<String> components;
     Vector<String> components;
-    
-    // Simply try to create each of the objects, and check which derive from Component.
-    // This assumes that creating any of them does not have harmful side-effects
-    for (HashMap<ShortStringHash, SharedPtr<ObjectFactory> >::ConstIterator i = factories.Begin(); i != factories.End(); ++i)
+
+    HashMap<String, Vector<ShortStringHash> >::ConstIterator i = categories.Find(category);
+    if (i != categories.End())
     {
     {
-        SharedPtr<Object> object = i->second_->CreateObject();
-        if (dynamic_cast<Component*>(object.Get()))
-            components.Push(object->GetTypeName());
+        const HashMap<ShortStringHash, SharedPtr<ObjectFactory> >& factories = GetScriptContext()->GetObjectFactories();
+        const Vector<ShortStringHash>& factoryHashes = i->second_;
+        components.Reserve(factoryHashes.Size());
+
+        for (unsigned j = 0; j < factoryHashes.Size(); ++j)
+        {
+            HashMap<ShortStringHash, SharedPtr<ObjectFactory> >::ConstIterator k = factories.Find(factoryHashes[j]);
+            if (k != factories.End())
+                components.Push(k->second_->GetTypeName());
+        }
     }
     }
-    
+
     Sort(components.Begin(), components.End());
     Sort(components.Begin(), components.End());
     return VectorToArray<String>(components, "Array<String>");
     return VectorToArray<String>(components, "Array<String>");
 }
 }
@@ -161,7 +174,7 @@ static void RegisterScene(asIScriptEngine* engine)
     engine->RegisterGlobalProperty("const uint LAST_REPLICATED_ID", (void*)&LAST_REPLICATED_ID);
     engine->RegisterGlobalProperty("const uint LAST_REPLICATED_ID", (void*)&LAST_REPLICATED_ID);
     engine->RegisterGlobalProperty("const uint FIRST_LOCAL_ID", (void*)&FIRST_LOCAL_ID);
     engine->RegisterGlobalProperty("const uint FIRST_LOCAL_ID", (void*)&FIRST_LOCAL_ID);
     engine->RegisterGlobalProperty("const uint LAST_LOCAL_ID", (void*)&LAST_LOCAL_ID);
     engine->RegisterGlobalProperty("const uint LAST_LOCAL_ID", (void*)&LAST_LOCAL_ID);
-    
+
     RegisterNode<Scene>(engine, "Scene");
     RegisterNode<Scene>(engine, "Scene");
     RegisterObjectConstructor<Scene>(engine, "Scene");
     RegisterObjectConstructor<Scene>(engine, "Scene");
     RegisterNamedObjectConstructor<Scene>(engine, "Scene");
     RegisterNamedObjectConstructor<Scene>(engine, "Scene");
@@ -201,11 +214,12 @@ static void RegisterScene(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Scene", "Array<PackageFile@>@ get_requiredPackageFiles() const", asFUNCTION(SceneGetRequiredPackageFiles), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "Array<PackageFile@>@ get_requiredPackageFiles() const", asFUNCTION(SceneGetRequiredPackageFiles), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Node", "Scene@+ get_scene() const", asMETHOD(Node, GetScene), asCALL_THISCALL);
     engine->RegisterObjectMethod("Node", "Scene@+ get_scene() const", asMETHOD(Node, GetScene), asCALL_THISCALL);
     engine->RegisterGlobalFunction("Scene@+ get_scene()", asFUNCTION(GetScriptContextScene), asCALL_CDECL);
     engine->RegisterGlobalFunction("Scene@+ get_scene()", asFUNCTION(GetScriptContextScene), asCALL_CDECL);
-    
+
     // Register Variant GetPtr() for Scene
     // Register Variant GetPtr() for Scene
     engine->RegisterObjectMethod("Variant", "Scene@+ GetScene() const", asFUNCTION(GetVariantPtr<Scene>), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Variant", "Scene@+ GetScene() const", asFUNCTION(GetVariantPtr<Scene>), asCALL_CDECL_OBJLAST);
-    
-    engine->RegisterGlobalFunction("Array<String>@ GetAvailableComponents()", asFUNCTION(GetAvailableComponents), asCALL_CDECL);
+
+    engine->RegisterGlobalFunction("Array<String>@ GetComponentCategories()", asFUNCTION(GetComponentCategories), asCALL_CDECL);
+    engine->RegisterGlobalFunction("Array<String>@ GetComponentsByCategory(const String&in)", asFUNCTION(GetComponentsByCategory), asCALL_CDECL);
 }
 }
 
 
 void RegisterSceneAPI(asIScriptEngine* engine)
 void RegisterSceneAPI(asIScriptEngine* engine)

+ 1 - 1
Engine/Graphics/AnimatedModel.cpp

@@ -78,7 +78,7 @@ AnimatedModel::~AnimatedModel()
 
 
 void AnimatedModel::RegisterObject(Context* context)
 void AnimatedModel::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<AnimatedModel>();
+    context->RegisterComponentFactory<AnimatedModel>(ANIMATION_CATEGORY);
 
 
     ACCESSOR_ATTRIBUTE(AnimatedModel, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(AnimatedModel, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(AnimatedModel, VAR_RESOURCEREF, "Model", GetModelAttr, SetModelAttr, ResourceRef, ResourceRef(Model::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(AnimatedModel, VAR_RESOURCEREF, "Model", GetModelAttr, SetModelAttr, ResourceRef, ResourceRef(Model::GetTypeStatic()), AM_DEFAULT);

+ 2 - 0
Engine/Graphics/Animation.cpp

@@ -36,6 +36,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* ANIMATION_CATEGORY = "Animation";
+
 inline bool CompareTriggers(AnimationTriggerPoint& lhs, AnimationTriggerPoint& rhs)
 inline bool CompareTriggers(AnimationTriggerPoint& lhs, AnimationTriggerPoint& rhs)
 {
 {
     return lhs.time_ < rhs.time_;
     return lhs.time_ < rhs.time_;

+ 2 - 0
Engine/Graphics/Animation.h

@@ -30,6 +30,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* ANIMATION_CATEGORY;
+
 /// Skeletal animation keyframe.
 /// Skeletal animation keyframe.
 struct AnimationKeyFrame
 struct AnimationKeyFrame
 {
 {

+ 1 - 1
Engine/Graphics/AnimationController.cpp

@@ -59,7 +59,7 @@ AnimationController::~AnimationController()
 
 
 void AnimationController::RegisterObject(Context* context)
 void AnimationController::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<AnimationController>();
+    context->RegisterComponentFactory<AnimationController>(ANIMATION_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(AnimationController, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(AnimationController, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(AnimationController, VAR_VARIANTVECTOR, "Animations", GetAnimationsAttr, SetAnimationsAttr, VariantVector, Variant::emptyVariantVector, AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE(AnimationController, VAR_VARIANTVECTOR, "Animations", GetAnimationsAttr, SetAnimationsAttr, VariantVector, Variant::emptyVariantVector, AM_FILE | AM_NOEDIT);

+ 3 - 1
Engine/Graphics/BillboardSet.cpp

@@ -41,6 +41,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* EFFECT_CATEGORY;
+
 static const float INV_SQRT_TWO = 1.0f / sqrtf(2.0f);
 static const float INV_SQRT_TWO = 1.0f / sqrtf(2.0f);
 
 
 inline bool CompareBillboards(Billboard* lhs, Billboard* rhs)
 inline bool CompareBillboards(Billboard* lhs, Billboard* rhs)
@@ -80,7 +82,7 @@ BillboardSet::~BillboardSet()
 
 
 void BillboardSet::RegisterObject(Context* context)
 void BillboardSet::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<BillboardSet>();
+    context->RegisterComponentFactory<BillboardSet>(EFFECT_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(BillboardSet, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(BillboardSet, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(BillboardSet, VAR_RESOURCEREF, "Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(BillboardSet, VAR_RESOURCEREF, "Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);

+ 31 - 29
Engine/Graphics/Camera.cpp

@@ -31,6 +31,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* SCENE_CATEGORY;
+
 static const float DEFAULT_NEARCLIP = 0.1f;
 static const float DEFAULT_NEARCLIP = 0.1f;
 static const float DEFAULT_FARCLIP = 1000.0f;
 static const float DEFAULT_FARCLIP = 1000.0f;
 static const float DEFAULT_FOV = 45.0f;
 static const float DEFAULT_FOV = 45.0f;
@@ -81,8 +83,8 @@ Camera::~Camera()
 
 
 void Camera::RegisterObject(Context* context)
 void Camera::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Camera>();
-    
+    context->RegisterComponentFactory<Camera>(SCENE_CATEGORY);
+
     ACCESSOR_ATTRIBUTE(Camera, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Camera, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Camera, VAR_FLOAT, "Near Clip", GetNearClip, SetNearClip, float, DEFAULT_NEARCLIP, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Camera, VAR_FLOAT, "Near Clip", GetNearClip, SetNearClip, float, DEFAULT_NEARCLIP, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Camera, VAR_FLOAT, "Far Clip", GetFarClip, SetFarClip, float, DEFAULT_FARCLIP, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Camera, VAR_FLOAT, "Far Clip", GetFarClip, SetFarClip, float, DEFAULT_FARCLIP, AM_DEFAULT);
@@ -222,54 +224,54 @@ float Camera::GetNearClip() const
 Frustum Camera::GetSplitFrustum(float nearClip, float farClip) const
 Frustum Camera::GetSplitFrustum(float nearClip, float farClip) const
 {
 {
     Frustum ret;
     Frustum ret;
-    
+
     const Matrix3x4& worldTransform = node_ ? node_->GetWorldTransform() : Matrix3x4::IDENTITY;
     const Matrix3x4& worldTransform = node_ ? node_->GetWorldTransform() : Matrix3x4::IDENTITY;
     nearClip = Max(nearClip, GetNearClip());
     nearClip = Max(nearClip, GetNearClip());
     farClip = Min(farClip, farClip_);
     farClip = Min(farClip, farClip_);
     if (farClip < nearClip)
     if (farClip < nearClip)
         farClip = nearClip;
         farClip = nearClip;
-    
+
     if (!orthographic_)
     if (!orthographic_)
         ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip, worldTransform);
         ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip, worldTransform);
     else
     else
         ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip, worldTransform);
         ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip, worldTransform);
-    
+
     return ret;
     return ret;
 }
 }
 
 
 Frustum Camera::GetViewSpaceFrustum() const
 Frustum Camera::GetViewSpaceFrustum() const
 {
 {
     Frustum ret;
     Frustum ret;
-    
+
     if (!orthographic_)
     if (!orthographic_)
         ret.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_);
         ret.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_);
     else
     else
         ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), farClip_);
         ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), farClip_);
-    
+
     return ret;
     return ret;
 }
 }
 
 
 Frustum Camera::GetViewSpaceSplitFrustum(float nearClip, float farClip) const
 Frustum Camera::GetViewSpaceSplitFrustum(float nearClip, float farClip) const
 {
 {
     Frustum ret;
     Frustum ret;
-    
+
     nearClip = Max(nearClip, GetNearClip());
     nearClip = Max(nearClip, GetNearClip());
     farClip = Min(farClip, farClip_);
     farClip = Min(farClip, farClip_);
     if (farClip < nearClip)
     if (farClip < nearClip)
         farClip = nearClip;
         farClip = nearClip;
-    
+
     if (!orthographic_)
     if (!orthographic_)
         ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip);
         ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip);
     else
     else
         ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip);
         ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip);
-    
+
     return ret;
     return ret;
 }
 }
 
 
 Ray Camera::GetScreenRay(float x, float y) const
 Ray Camera::GetScreenRay(float x, float y) const
 {
 {
     Ray ret;
     Ray ret;
-    
+
     // If projection is invalid, just return a ray pointing forward
     // If projection is invalid, just return a ray pointing forward
     if (!IsProjectionValid())
     if (!IsProjectionValid())
     {
     {
@@ -277,15 +279,15 @@ Ray Camera::GetScreenRay(float x, float y) const
         ret.direction_ = GetForwardVector();
         ret.direction_ = GetForwardVector();
         return ret;
         return ret;
     }
     }
-    
+
     Matrix4 viewProjInverse = (GetProjection(false) * GetInverseWorldTransform()).Inverse();
     Matrix4 viewProjInverse = (GetProjection(false) * GetInverseWorldTransform()).Inverse();
-    
+
     // The parameters range from 0.0 to 1.0. Expand to normalized device coordinates (-1.0 to 1.0) & flip Y axis
     // The parameters range from 0.0 to 1.0. Expand to normalized device coordinates (-1.0 to 1.0) & flip Y axis
     x = 2.0f * x - 1.0f;
     x = 2.0f * x - 1.0f;
     y = 1.0f - 2.0f * y;
     y = 1.0f - 2.0f * y;
     Vector3 near(x, y, 0.0f);
     Vector3 near(x, y, 0.0f);
     Vector3 far(x, y, 1.0f);
     Vector3 far(x, y, 1.0f);
-    
+
     ret.origin_ = viewProjInverse * near;
     ret.origin_ = viewProjInverse * near;
     ret.direction_ = ((viewProjInverse * far) - ret.origin_).Normalized();
     ret.direction_ = ((viewProjInverse * far) - ret.origin_).Normalized();
     return ret;
     return ret;
@@ -295,7 +297,7 @@ Vector2 Camera::WorldToScreenPoint(const Vector3& worldPos) const
 {
 {
     Vector3 eyeSpacePos = GetInverseWorldTransform() * worldPos;
     Vector3 eyeSpacePos = GetInverseWorldTransform() * worldPos;
     Vector2 ret;
     Vector2 ret;
-    
+
     if(eyeSpacePos.z_ > 0.0f)
     if(eyeSpacePos.z_ > 0.0f)
     {
     {
         Vector3 screenSpacePos = GetProjection(false) * eyeSpacePos;
         Vector3 screenSpacePos = GetProjection(false) * eyeSpacePos;
@@ -307,7 +309,7 @@ Vector2 Camera::WorldToScreenPoint(const Vector3& worldPos) const
         ret.x_ = (-eyeSpacePos.x_ > 0.0f) ? -1.0f : 1.0f;
         ret.x_ = (-eyeSpacePos.x_ > 0.0f) ? -1.0f : 1.0f;
         ret.y_ = (-eyeSpacePos.y_ > 0.0f) ? -1.0f : 1.0f;
         ret.y_ = (-eyeSpacePos.y_ > 0.0f) ? -1.0f : 1.0f;
     }
     }
-    
+
     ret.x_ = (ret.x_ / 2.0f) + 0.5f;
     ret.x_ = (ret.x_ / 2.0f) + 0.5f;
     ret.y_ = 1.0f - ((ret.y_ / 2.0f) + 0.5f);
     ret.y_ = 1.0f - ((ret.y_ / 2.0f) + 0.5f);
     return ret;
     return ret;
@@ -328,10 +330,10 @@ const Frustum& Camera::GetFrustum() const
             frustum_.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);
             frustum_.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);
         else
         else
             frustum_.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);
             frustum_.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);
-        
+
         frustumDirty_ = false;
         frustumDirty_ = false;
     }
     }
-    
+
     return frustum_;
     return frustum_;
 }
 }
 
 
@@ -342,21 +344,21 @@ const Matrix4& Camera::GetProjection() const
         projection_ = GetProjection(true);
         projection_ = GetProjection(true);
         projectionDirty_ = false;
         projectionDirty_ = false;
     }
     }
-    
+
     return projection_;
     return projection_;
 }
 }
 
 
 Matrix4 Camera::GetProjection(bool apiSpecific) const
 Matrix4 Camera::GetProjection(bool apiSpecific) const
 {
 {
     Matrix4 ret(Matrix4::ZERO);
     Matrix4 ret(Matrix4::ZERO);
-    
+
     if (!orthographic_)
     if (!orthographic_)
     {
     {
         float nearClip = GetNearClip();
         float nearClip = GetNearClip();
         float h = (1.0f / tanf(fov_ * M_DEGTORAD * 0.5f)) * zoom_;
         float h = (1.0f / tanf(fov_ * M_DEGTORAD * 0.5f)) * zoom_;
         float w = h / aspectRatio_;
         float w = h / aspectRatio_;
         float q, r;
         float q, r;
-        
+
         if (apiSpecific)
         if (apiSpecific)
         {
         {
             #ifdef USE_OPENGL
             #ifdef USE_OPENGL
@@ -372,7 +374,7 @@ Matrix4 Camera::GetProjection(bool apiSpecific) const
             q = farClip_ / (farClip_ - nearClip);
             q = farClip_ / (farClip_ - nearClip);
             r = -q * nearClip;
             r = -q * nearClip;
         }
         }
-        
+
         ret.m00_ = w;
         ret.m00_ = w;
         ret.m02_ = projectionOffset_.x_ * 2.0f;
         ret.m02_ = projectionOffset_.x_ * 2.0f;
         ret.m11_ = h;
         ret.m11_ = h;
@@ -387,7 +389,7 @@ Matrix4 Camera::GetProjection(bool apiSpecific) const
         float h = (1.0f / (orthoSize_ * 0.5f)) * zoom_;
         float h = (1.0f / (orthoSize_ * 0.5f)) * zoom_;
         float w = h / aspectRatio_;
         float w = h / aspectRatio_;
         float q, r;
         float q, r;
-        
+
         if (apiSpecific)
         if (apiSpecific)
         {
         {
             #ifdef USE_OPENGL
             #ifdef USE_OPENGL
@@ -403,7 +405,7 @@ Matrix4 Camera::GetProjection(bool apiSpecific) const
             q = 1.0f / farClip_;
             q = 1.0f / farClip_;
             r = 0.0f;
             r = 0.0f;
         }
         }
-        
+
         ret.m00_ = w;
         ret.m00_ = w;
         ret.m03_ = projectionOffset_.x_ * 2.0f;
         ret.m03_ = projectionOffset_.x_ * 2.0f;
         ret.m11_ = h;
         ret.m11_ = h;
@@ -412,10 +414,10 @@ Matrix4 Camera::GetProjection(bool apiSpecific) const
         ret.m23_ = r;
         ret.m23_ = r;
         ret.m33_ = 1.0f;
         ret.m33_ = 1.0f;
     }
     }
-    
+
     if (flipVertical_)
     if (flipVertical_)
         ret = flipMatrix * ret;
         ret = flipMatrix * ret;
-    
+
     return ret;
     return ret;
 }
 }
 
 
@@ -423,7 +425,7 @@ void Camera::GetFrustumSize(Vector3& near, Vector3& far) const
 {
 {
     near.z_ = GetNearClip();
     near.z_ = GetNearClip();
     far.z_ = farClip_;
     far.z_ = farClip_;
-    
+
     if (!orthographic_)
     if (!orthographic_)
     {
     {
         float halfViewSize = tanf(fov_ * M_DEGTORAD * 0.5f) / zoom_;
         float halfViewSize = tanf(fov_ * M_DEGTORAD * 0.5f) / zoom_;
@@ -438,7 +440,7 @@ void Camera::GetFrustumSize(Vector3& near, Vector3& far) const
         near.y_ = far.y_ = halfViewSize;
         near.y_ = far.y_ = halfViewSize;
         near.x_ = far.x_ = near.y_ * aspectRatio_;
         near.x_ = far.x_ = near.y_ * aspectRatio_;
     }
     }
-    
+
     if (flipVertical_)
     if (flipVertical_)
     {
     {
         near.y_ = -near.y_;
         near.y_ = -near.y_;
@@ -516,7 +518,7 @@ const Matrix3x4& Camera::GetInverseWorldTransform() const
         inverseWorld_ = worldTransform.Inverse();
         inverseWorld_ = worldTransform.Inverse();
         inverseWorldDirty_ = false;
         inverseWorldDirty_ = false;
     }
     }
-    
+
     return inverseWorld_;
     return inverseWorld_;
 }
 }
 
 

+ 3 - 1
Engine/Graphics/CustomGeometry.cpp

@@ -39,6 +39,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* STATIC_CATEGORY;
+
 OBJECTTYPESTATIC(CustomGeometry);
 OBJECTTYPESTATIC(CustomGeometry);
 
 
 CustomGeometry::CustomGeometry(Context* context) :
 CustomGeometry::CustomGeometry(Context* context) :
@@ -57,7 +59,7 @@ CustomGeometry::~CustomGeometry()
 
 
 void CustomGeometry::RegisterObject(Context* context)
 void CustomGeometry::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<CustomGeometry>();
+    context->RegisterComponentFactory<CustomGeometry>(STATIC_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(CustomGeometry, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CustomGeometry, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ATTRIBUTE(CustomGeometry, VAR_BOOL, "Is Occluder", occluder_, false, AM_DEFAULT);
     ATTRIBUTE(CustomGeometry, VAR_BOOL, "Is Occluder", occluder_, false, AM_DEFAULT);

+ 48 - 46
Engine/Graphics/DebugRenderer.cpp

@@ -41,6 +41,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* SCENE_CATEGORY;
+
 // Cap the amount of lines to prevent crash when eg. debug rendering large heightfields
 // Cap the amount of lines to prevent crash when eg. debug rendering large heightfields
 static const unsigned MAX_LINES = 1000000;
 static const unsigned MAX_LINES = 1000000;
 
 
@@ -50,7 +52,7 @@ DebugRenderer::DebugRenderer(Context* context) :
     Component(context)
     Component(context)
 {
 {
     vertexBuffer_ = new VertexBuffer(context_);
     vertexBuffer_ = new VertexBuffer(context_);
-    
+
     SubscribeToEvent(E_ENDFRAME, HANDLER(DebugRenderer, HandleEndFrame));
     SubscribeToEvent(E_ENDFRAME, HANDLER(DebugRenderer, HandleEndFrame));
 }
 }
 
 
@@ -60,14 +62,14 @@ DebugRenderer::~DebugRenderer()
 
 
 void DebugRenderer::RegisterObject(Context* context)
 void DebugRenderer::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<DebugRenderer>();
+    context->RegisterComponentFactory<DebugRenderer>(SCENE_CATEGORY);
 }
 }
 
 
 void DebugRenderer::SetView(Camera* camera)
 void DebugRenderer::SetView(Camera* camera)
 {
 {
     if (!camera)
     if (!camera)
         return;
         return;
-    
+
     view_ = camera->GetInverseWorldTransform();
     view_ = camera->GetInverseWorldTransform();
     projection_ = camera->GetProjection();
     projection_ = camera->GetProjection();
     frustum_ = camera->GetFrustum();
     frustum_ = camera->GetFrustum();
@@ -82,7 +84,7 @@ void DebugRenderer::AddLine(const Vector3& start, const Vector3& end, unsigned c
 {
 {
     if (lines_.Size() + noDepthLines_.Size() >= MAX_LINES)
     if (lines_.Size() + noDepthLines_.Size() >= MAX_LINES)
         return;
         return;
-    
+
     if (depthTest)
     if (depthTest)
         lines_.Push(DebugLine(start, end, color));
         lines_.Push(DebugLine(start, end, color));
     else
     else
@@ -93,10 +95,10 @@ void DebugRenderer::AddNode(Node* node, float scale, bool depthTest)
 {
 {
     if (!node)
     if (!node)
         return;
         return;
-    
+
     Vector3 start = node->GetWorldPosition();
     Vector3 start = node->GetWorldPosition();
     Quaternion rotation = node->GetWorldRotation();
     Quaternion rotation = node->GetWorldRotation();
-    
+
     AddLine(start, start + rotation * (scale * Vector3::RIGHT), Color::RED.ToUInt(), depthTest);
     AddLine(start, start + rotation * (scale * Vector3::RIGHT), Color::RED.ToUInt(), depthTest);
     AddLine(start, start + rotation * (scale * Vector3::UP), Color::GREEN.ToUInt(), depthTest);
     AddLine(start, start + rotation * (scale * Vector3::UP), Color::GREEN.ToUInt(), depthTest);
     AddLine(start, start + rotation * (scale * Vector3::FORWARD), Color::BLUE.ToUInt(), depthTest);
     AddLine(start, start + rotation * (scale * Vector3::FORWARD), Color::BLUE.ToUInt(), depthTest);
@@ -106,16 +108,16 @@ void DebugRenderer::AddBoundingBox(const BoundingBox& box, const Color& color, b
 {
 {
     const Vector3& min = box.min_;
     const Vector3& min = box.min_;
     const Vector3& max = box.max_;
     const Vector3& max = box.max_;
-    
+
     Vector3 v1(max.x_, min.y_, min.z_);
     Vector3 v1(max.x_, min.y_, min.z_);
     Vector3 v2(max.x_, max.y_, min.z_);
     Vector3 v2(max.x_, max.y_, min.z_);
     Vector3 v3(min.x_, max.y_, min.z_);
     Vector3 v3(min.x_, max.y_, min.z_);
     Vector3 v4(min.x_, min.y_, max.z_);
     Vector3 v4(min.x_, min.y_, max.z_);
     Vector3 v5(max.x_, min.y_, max.z_);
     Vector3 v5(max.x_, min.y_, max.z_);
     Vector3 v6(min.x_, max.y_, max.z_);
     Vector3 v6(min.x_, max.y_, max.z_);
-    
+
     unsigned uintColor = color.ToUInt();
     unsigned uintColor = color.ToUInt();
-    
+
     AddLine(min, v1, uintColor, depthTest);
     AddLine(min, v1, uintColor, depthTest);
     AddLine(v1, v2, uintColor, depthTest);
     AddLine(v1, v2, uintColor, depthTest);
     AddLine(v2, v3, uintColor, depthTest);
     AddLine(v2, v3, uintColor, depthTest);
@@ -134,7 +136,7 @@ void DebugRenderer::AddBoundingBox(const BoundingBox& box, const Matrix3x4& tran
 {
 {
     const Vector3& min = box.min_;
     const Vector3& min = box.min_;
     const Vector3& max = box.max_;
     const Vector3& max = box.max_;
-    
+
     Vector3 v0(transform * min);
     Vector3 v0(transform * min);
     Vector3 v1(transform * Vector3(max.x_, min.y_, min.z_));
     Vector3 v1(transform * Vector3(max.x_, min.y_, min.z_));
     Vector3 v2(transform * Vector3(max.x_, max.y_, min.z_));
     Vector3 v2(transform * Vector3(max.x_, max.y_, min.z_));
@@ -143,9 +145,9 @@ void DebugRenderer::AddBoundingBox(const BoundingBox& box, const Matrix3x4& tran
     Vector3 v5(transform * Vector3(max.x_, min.y_, max.z_));
     Vector3 v5(transform * Vector3(max.x_, min.y_, max.z_));
     Vector3 v6(transform * Vector3(min.x_, max.y_, max.z_));
     Vector3 v6(transform * Vector3(min.x_, max.y_, max.z_));
     Vector3 v7(transform * max);
     Vector3 v7(transform * max);
-    
+
     unsigned uintColor = color.ToUInt();
     unsigned uintColor = color.ToUInt();
-    
+
     AddLine(v0, v1, uintColor, depthTest);
     AddLine(v0, v1, uintColor, depthTest);
     AddLine(v1, v2, uintColor, depthTest);
     AddLine(v1, v2, uintColor, depthTest);
     AddLine(v2, v3, uintColor, depthTest);
     AddLine(v2, v3, uintColor, depthTest);
@@ -165,7 +167,7 @@ void DebugRenderer::AddFrustum(const Frustum& frustum, const Color& color, bool
 {
 {
     const Vector3* vertices = frustum.vertices_;
     const Vector3* vertices = frustum.vertices_;
     unsigned uintColor = color.ToUInt();
     unsigned uintColor = color.ToUInt();
-    
+
     AddLine(vertices[0], vertices[1], uintColor, depthTest);
     AddLine(vertices[0], vertices[1], uintColor, depthTest);
     AddLine(vertices[1], vertices[2], uintColor, depthTest);
     AddLine(vertices[1], vertices[2], uintColor, depthTest);
     AddLine(vertices[2], vertices[3], uintColor, depthTest);
     AddLine(vertices[2], vertices[3], uintColor, depthTest);
@@ -183,7 +185,7 @@ void DebugRenderer::AddFrustum(const Frustum& frustum, const Color& color, bool
 void DebugRenderer::AddPolyhedron(const Polyhedron& poly, const Color& color, bool depthTest)
 void DebugRenderer::AddPolyhedron(const Polyhedron& poly, const Color& color, bool depthTest)
 {
 {
     unsigned uintColor = color.ToUInt();
     unsigned uintColor = color.ToUInt();
-    
+
     for (unsigned i = 0; i < poly.faces_.Size(); ++i)
     for (unsigned i = 0; i < poly.faces_.Size(); ++i)
     {
     {
         const PODVector<Vector3>& face = poly.faces_[i];
         const PODVector<Vector3>& face = poly.faces_[i];
@@ -200,7 +202,7 @@ void DebugRenderer::AddSphere(const Sphere& sphere, const Color& color, bool dep
     const Vector3& center = sphere.center_;
     const Vector3& center = sphere.center_;
     float radius = sphere.radius_;
     float radius = sphere.radius_;
     unsigned uintColor = color.ToUInt();
     unsigned uintColor = color.ToUInt();
-    
+
     for (unsigned i = 0; i < 360; i += 45)
     for (unsigned i = 0; i < 360; i += 45)
     {
     {
         unsigned j = i + 45;
         unsigned j = i + 45;
@@ -209,7 +211,7 @@ void DebugRenderer::AddSphere(const Sphere& sphere, const Color& color, bool dep
         float c = radius * sinf(j * M_DEGTORAD);
         float c = radius * sinf(j * M_DEGTORAD);
         float d = radius * cosf(j * M_DEGTORAD);
         float d = radius * cosf(j * M_DEGTORAD);
         Vector3 start, end;
         Vector3 start, end;
-        
+
         start = center + Vector3(a, b, 0.0f);
         start = center + Vector3(a, b, 0.0f);
         end = center + Vector3(c, d, 0.0f);
         end = center + Vector3(c, d, 0.0f);
         AddLine(start, end, uintColor, depthTest);
         AddLine(start, end, uintColor, depthTest);
@@ -227,31 +229,31 @@ void DebugRenderer::AddSkeleton(const Skeleton& skeleton, const Color& color, bo
     const Vector<Bone>& bones = skeleton.GetBones();
     const Vector<Bone>& bones = skeleton.GetBones();
     if (!bones.Size())
     if (!bones.Size())
         return;
         return;
-    
+
     unsigned uintColor = color.ToUInt();
     unsigned uintColor = color.ToUInt();
-    
+
     for (unsigned i = 0; i < bones.Size(); ++i)
     for (unsigned i = 0; i < bones.Size(); ++i)
     {
     {
         // Skip if bone contains no skinned geometry
         // Skip if bone contains no skinned geometry
         if (bones[i].radius_ < M_EPSILON && bones[i].boundingBox_.Size().LengthSquared() < M_EPSILON)
         if (bones[i].radius_ < M_EPSILON && bones[i].boundingBox_.Size().LengthSquared() < M_EPSILON)
             continue;
             continue;
-        
+
         Node* boneNode = bones[i].node_;
         Node* boneNode = bones[i].node_;
         if (!boneNode)
         if (!boneNode)
             continue;
             continue;
-        
+
         Vector3 start = boneNode->GetWorldPosition();
         Vector3 start = boneNode->GetWorldPosition();
         Vector3 end;
         Vector3 end;
-        
+
         unsigned j = bones[i].parentIndex_;
         unsigned j = bones[i].parentIndex_;
         Node* parentNode = boneNode->GetParent();
         Node* parentNode = boneNode->GetParent();
-        
+
         // If bone has a parent defined, and it also skins geometry, draw a line to it. Else draw the bone as a point
         // If bone has a parent defined, and it also skins geometry, draw a line to it. Else draw the bone as a point
         if (parentNode && (bones[j].radius_ >= M_EPSILON || bones[j].boundingBox_.Size().LengthSquared() >= M_EPSILON))
         if (parentNode && (bones[j].radius_ >= M_EPSILON || bones[j].boundingBox_.Size().LengthSquared() >= M_EPSILON))
             end = parentNode->GetWorldPosition();
             end = parentNode->GetWorldPosition();
         else
         else
             end = start;
             end = start;
-        
+
         AddLine(start, end, uintColor, depthTest);
         AddLine(start, end, uintColor, depthTest);
     }
     }
 }
 }
@@ -261,23 +263,23 @@ void DebugRenderer::AddTriangleMesh(const void* vertexData, unsigned vertexSize,
 {
 {
     unsigned uintColor = color.ToUInt();
     unsigned uintColor = color.ToUInt();
     const unsigned char* srcData = (const unsigned char*)vertexData;
     const unsigned char* srcData = (const unsigned char*)vertexData;
-    
+
     // 16-bit indices
     // 16-bit indices
     if (indexSize == sizeof(unsigned short))
     if (indexSize == sizeof(unsigned short))
     {
     {
         const unsigned short* indices = ((const unsigned short*)indexData) + indexStart;
         const unsigned short* indices = ((const unsigned short*)indexData) + indexStart;
         const unsigned short* indicesEnd = indices + indexCount;
         const unsigned short* indicesEnd = indices + indexCount;
-        
+
         while (indices < indicesEnd)
         while (indices < indicesEnd)
         {
         {
             Vector3 v0 = transform * *((const Vector3*)(&srcData[indices[0] * vertexSize]));
             Vector3 v0 = transform * *((const Vector3*)(&srcData[indices[0] * vertexSize]));
             Vector3 v1 = transform * *((const Vector3*)(&srcData[indices[1] * vertexSize]));
             Vector3 v1 = transform * *((const Vector3*)(&srcData[indices[1] * vertexSize]));
             Vector3 v2 = transform * *((const Vector3*)(&srcData[indices[2] * vertexSize]));
             Vector3 v2 = transform * *((const Vector3*)(&srcData[indices[2] * vertexSize]));
-            
+
             AddLine(v0, v1, uintColor, depthTest);
             AddLine(v0, v1, uintColor, depthTest);
             AddLine(v1, v2, uintColor, depthTest);
             AddLine(v1, v2, uintColor, depthTest);
             AddLine(v2, v0, uintColor, depthTest);
             AddLine(v2, v0, uintColor, depthTest);
-            
+
             indices += 3;
             indices += 3;
         }
         }
     }
     }
@@ -285,17 +287,17 @@ void DebugRenderer::AddTriangleMesh(const void* vertexData, unsigned vertexSize,
     {
     {
         const unsigned* indices = ((const unsigned*)indexData) + indexStart;
         const unsigned* indices = ((const unsigned*)indexData) + indexStart;
         const unsigned* indicesEnd = indices + indexCount;
         const unsigned* indicesEnd = indices + indexCount;
-        
+
         while (indices < indicesEnd)
         while (indices < indicesEnd)
         {
         {
             Vector3 v0 = transform * *((const Vector3*)(&srcData[indices[0] * vertexSize]));
             Vector3 v0 = transform * *((const Vector3*)(&srcData[indices[0] * vertexSize]));
             Vector3 v1 = transform * *((const Vector3*)(&srcData[indices[1] * vertexSize]));
             Vector3 v1 = transform * *((const Vector3*)(&srcData[indices[1] * vertexSize]));
             Vector3 v2 = transform * *((const Vector3*)(&srcData[indices[2] * vertexSize]));
             Vector3 v2 = transform * *((const Vector3*)(&srcData[indices[2] * vertexSize]));
-            
+
             AddLine(v0, v1, uintColor, depthTest);
             AddLine(v0, v1, uintColor, depthTest);
             AddLine(v1, v2, uintColor, depthTest);
             AddLine(v1, v2, uintColor, depthTest);
             AddLine(v2, v0, uintColor, depthTest);
             AddLine(v2, v0, uintColor, depthTest);
-            
+
             indices += 3;
             indices += 3;
         }
         }
     }
     }
@@ -305,48 +307,48 @@ void DebugRenderer::Render()
 {
 {
     if (lines_.Empty() && noDepthLines_.Empty())
     if (lines_.Empty() && noDepthLines_.Empty())
         return;
         return;
-    
+
     Graphics* graphics = GetSubsystem<Graphics>();
     Graphics* graphics = GetSubsystem<Graphics>();
     Renderer* renderer = GetSubsystem<Renderer>();
     Renderer* renderer = GetSubsystem<Renderer>();
-    
+
     if (!graphics || graphics->IsDeviceLost())
     if (!graphics || graphics->IsDeviceLost())
         return;
         return;
-    
+
     PROFILE(RenderDebugGeometry);
     PROFILE(RenderDebugGeometry);
-    
+
     unsigned numVertices = (lines_.Size() + noDepthLines_.Size()) * 2;
     unsigned numVertices = (lines_.Size() + noDepthLines_.Size()) * 2;
     // Resize the vertex buffer if too small or much too large
     // Resize the vertex buffer if too small or much too large
     if (vertexBuffer_->GetVertexCount() < numVertices || vertexBuffer_->GetVertexCount() > numVertices * 2)
     if (vertexBuffer_->GetVertexCount() < numVertices || vertexBuffer_->GetVertexCount() > numVertices * 2)
         vertexBuffer_->SetSize(numVertices, MASK_POSITION | MASK_COLOR, true);
         vertexBuffer_->SetSize(numVertices, MASK_POSITION | MASK_COLOR, true);
-    
+
     float* dest = (float*)vertexBuffer_->Lock(0, numVertices, true);
     float* dest = (float*)vertexBuffer_->Lock(0, numVertices, true);
     if (!dest)
     if (!dest)
         return;
         return;
-    
+
     for (unsigned i = 0; i < lines_.Size(); ++i)
     for (unsigned i = 0; i < lines_.Size(); ++i)
     {
     {
         const DebugLine& line = lines_[i];
         const DebugLine& line = lines_[i];
-        
+
         *dest++ = line.start_.x_; *dest++ = line.start_.y_; *dest++ = line.start_.z_;
         *dest++ = line.start_.x_; *dest++ = line.start_.y_; *dest++ = line.start_.z_;
         *((unsigned*)dest) = line.color_; dest++;
         *((unsigned*)dest) = line.color_; dest++;
-        
+
         *dest++ = line.end_.x_; *dest++ = line.end_.y_; *dest++ = line.end_.z_;
         *dest++ = line.end_.x_; *dest++ = line.end_.y_; *dest++ = line.end_.z_;
         *((unsigned*)dest) = line.color_; dest++;
         *((unsigned*)dest) = line.color_; dest++;
     }
     }
-    
+
     for (unsigned i = 0; i < noDepthLines_.Size(); ++i)
     for (unsigned i = 0; i < noDepthLines_.Size(); ++i)
     {
     {
         const DebugLine& line = noDepthLines_[i];
         const DebugLine& line = noDepthLines_[i];
-        
+
         *dest++ = line.start_.x_; *dest++ = line.start_.y_; *dest++ = line.start_.z_;
         *dest++ = line.start_.x_; *dest++ = line.start_.y_; *dest++ = line.start_.z_;
         *((unsigned*)dest) = line.color_; dest++;
         *((unsigned*)dest) = line.color_; dest++;
-        
+
         *dest++ = line.end_.x_; *dest++ = line.end_.y_; *dest++ = line.end_.z_;
         *dest++ = line.end_.x_; *dest++ = line.end_.y_; *dest++ = line.end_.z_;
         *((unsigned*)dest) = line.color_; dest++;
         *((unsigned*)dest) = line.color_; dest++;
     }
     }
-    
+
     vertexBuffer_->Unlock();
     vertexBuffer_->Unlock();
-    
+
     graphics->SetBlendMode(BLEND_REPLACE);
     graphics->SetBlendMode(BLEND_REPLACE);
     graphics->SetColorWrite(true);
     graphics->SetColorWrite(true);
     graphics->SetCullMode(CULL_NONE);
     graphics->SetCullMode(CULL_NONE);
@@ -358,7 +360,7 @@ void DebugRenderer::Render()
     graphics->SetShaderParameter(VSP_VIEWPROJ, projection_ * view_);
     graphics->SetShaderParameter(VSP_VIEWPROJ, projection_ * view_);
     graphics->SetShaderParameter(PSP_MATDIFFCOLOR, Color(1.0f, 1.0f, 1.0f, 1.0f));
     graphics->SetShaderParameter(PSP_MATDIFFCOLOR, Color(1.0f, 1.0f, 1.0f, 1.0f));
     graphics->SetVertexBuffer(vertexBuffer_);
     graphics->SetVertexBuffer(vertexBuffer_);
-    
+
     if (lines_.Size())
     if (lines_.Size())
     {
     {
         graphics->SetDepthTest(CMP_LESSEQUAL);
         graphics->SetDepthTest(CMP_LESSEQUAL);
@@ -381,10 +383,10 @@ void DebugRenderer::HandleEndFrame(StringHash eventType, VariantMap& eventData)
     // When the amount of debug geometry is reduced, release memory
     // When the amount of debug geometry is reduced, release memory
     unsigned linesSize = lines_.Size();
     unsigned linesSize = lines_.Size();
     unsigned noDepthLinesSize = noDepthLines_.Size();
     unsigned noDepthLinesSize = noDepthLines_.Size();
-    
+
     lines_.Clear();
     lines_.Clear();
     noDepthLines_.Clear();
     noDepthLines_.Clear();
-    
+
     if (lines_.Capacity() > linesSize * 2)
     if (lines_.Capacity() > linesSize * 2)
         lines_.Reserve(linesSize);
         lines_.Reserve(linesSize);
     if (noDepthLines_.Capacity() > noDepthLinesSize * 2)
     if (noDepthLines_.Capacity() > noDepthLinesSize * 2)

+ 1 - 1
Engine/Graphics/DecalSet.cpp

@@ -178,7 +178,7 @@ DecalSet::~DecalSet()
 
 
 void DecalSet::RegisterObject(Context* context)
 void DecalSet::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<DecalSet>();
+    context->RegisterComponentFactory<DecalSet>(EFFECT_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(DecalSet, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(DecalSet, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(DecalSet, VAR_RESOURCEREF, "Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(DecalSet, VAR_RESOURCEREF, "Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);

+ 28 - 26
Engine/Graphics/Light.cpp

@@ -37,6 +37,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* SCENE_CATEGORY;
+
 static const LightType DEFAULT_LIGHTTYPE = LIGHT_POINT;
 static const LightType DEFAULT_LIGHTTYPE = LIGHT_POINT;
 static const float DEFAULT_RANGE = 10.0f;
 static const float DEFAULT_RANGE = 10.0f;
 static const float DEFAULT_FOV = 30.0f;
 static const float DEFAULT_FOV = 30.0f;
@@ -110,11 +112,11 @@ Light::~Light()
 
 
 void Light::RegisterObject(Context* context)
 void Light::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Light>();
-    
+    context->RegisterComponentFactory<Light>(SCENE_CATEGORY);
+
     ACCESSOR_ATTRIBUTE(Light, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Light, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ENUM_ACCESSOR_ATTRIBUTE(Light, "Light Type", GetLightType, SetLightType, LightType, typeNames, DEFAULT_LIGHTTYPE, AM_DEFAULT);
     ENUM_ACCESSOR_ATTRIBUTE(Light, "Light Type", GetLightType, SetLightType, LightType, typeNames, DEFAULT_LIGHTTYPE, AM_DEFAULT);
-    REF_ACCESSOR_ATTRIBUTE(Light, VAR_COLOR, "Color", GetColor, SetColor, Color, Color(), AM_DEFAULT);
+    REF_ACCESSOR_ATTRIBUTE(Light, VAR_COLOR, "Color", GetColor, SetColor, Color, Color::WHITE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Light, VAR_FLOAT, "Specular Intensity", GetSpecularIntensity, SetSpecularIntensity, float, DEFAULT_SPECULARINTENSITY, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Light, VAR_FLOAT, "Specular Intensity", GetSpecularIntensity, SetSpecularIntensity, float, DEFAULT_SPECULARINTENSITY, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Light, VAR_FLOAT, "Range", GetRange, SetRange, float, DEFAULT_RANGE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Light, VAR_FLOAT, "Range", GetRange, SetRange, float, DEFAULT_RANGE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Light, VAR_FLOAT, "Spot FOV", GetFov, SetFov, float, DEFAULT_FOV, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Light, VAR_FLOAT, "Spot FOV", GetFov, SetFov, float, DEFAULT_FOV, AM_DEFAULT);
@@ -148,7 +150,7 @@ void Light::RegisterObject(Context* context)
 void Light::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 void Light::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
 {
     Component::OnSetAttribute(attr, src);
     Component::OnSetAttribute(attr, src);
-    
+
     // Validate the bias, cascade & focus parameters
     // Validate the bias, cascade & focus parameters
     if (attr.offset_ >= offsetof(Light, shadowBias_) && attr.offset_ < (offsetof(Light, shadowBias_) + sizeof(BiasParameters)))
     if (attr.offset_ >= offsetof(Light, shadowBias_) && attr.offset_ < (offsetof(Light, shadowBias_) + sizeof(BiasParameters)))
         shadowBias_.Validate();
         shadowBias_.Validate();
@@ -163,7 +165,7 @@ void Light::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResul
     // Do not record a raycast result for a directional light, as it would block all other results
     // Do not record a raycast result for a directional light, as it would block all other results
     if (lightType_ == LIGHT_DIRECTIONAL)
     if (lightType_ == LIGHT_DIRECTIONAL)
         return;
         return;
-    
+
     float distance;
     float distance;
     switch (query.level_)
     switch (query.level_)
     {
     {
@@ -171,7 +173,7 @@ void Light::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResul
     case RAY_AABB:
     case RAY_AABB:
         Drawable::ProcessRayQuery(query, results);
         Drawable::ProcessRayQuery(query, results);
         return;
         return;
-        
+
     case RAY_OBB:
     case RAY_OBB:
         {
         {
             Matrix3x4 inverse(node_->GetWorldTransform().Inverse());
             Matrix3x4 inverse(node_->GetWorldTransform().Inverse());
@@ -181,7 +183,7 @@ void Light::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResul
                 return;
                 return;
         }
         }
         break;
         break;
-        
+
     case RAY_TRIANGLE:
     case RAY_TRIANGLE:
         if (lightType_ == LIGHT_SPOT)
         if (lightType_ == LIGHT_SPOT)
         {
         {
@@ -215,7 +217,7 @@ void Light::UpdateBatches(const FrameInfo& frame)
         // Directional light affects the whole scene, so it is always "closest"
         // Directional light affects the whole scene, so it is always "closest"
         distance_ = 0.0f;
         distance_ = 0.0f;
         break;
         break;
-        
+
     default:
     default:
         distance_ = frame.camera_->GetDistance(node_->GetWorldPosition());
         distance_ = frame.camera_->GetDistance(node_->GetWorldPosition());
         break;
         break;
@@ -241,11 +243,11 @@ void Light::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
                     }
                     }
             }
             }
             break;
             break;
-            
+
         case LIGHT_SPOT:
         case LIGHT_SPOT:
             debug->AddFrustum(GetFrustum(), color_, depthTest);
             debug->AddFrustum(GetFrustum(), color_, depthTest);
             break;
             break;
-            
+
         case LIGHT_POINT:
         case LIGHT_POINT:
             debug->AddSphere(Sphere(node_->GetWorldPosition(), range_), color_, depthTest);
             debug->AddSphere(Sphere(node_->GetWorldPosition(), range_), color_, depthTest);
             break;
             break;
@@ -377,35 +379,35 @@ Matrix3x4 Light::GetDirLightTransform(Camera* camera, bool getNearQuad)
 {
 {
     if (!camera)
     if (!camera)
         return Matrix3x4::IDENTITY;
         return Matrix3x4::IDENTITY;
-    
+
     Vector3 nearVector, farVector;
     Vector3 nearVector, farVector;
     camera->GetFrustumSize(nearVector, farVector);
     camera->GetFrustumSize(nearVector, farVector);
     float nearClip = camera->GetNearClip();
     float nearClip = camera->GetNearClip();
     float farClip = camera->GetFarClip();
     float farClip = camera->GetFarClip();
-    
+
     float distance = getNearQuad ? nearClip : farClip;
     float distance = getNearQuad ? nearClip : farClip;
     if (!camera->IsOrthographic())
     if (!camera->IsOrthographic())
         farVector *= (distance / farClip);
         farVector *= (distance / farClip);
     else
     else
         farVector.z_ *= (distance / farClip);
         farVector.z_ *= (distance / farClip);
-    
+
     // Set an epsilon from clip planes due to possible inaccuracy
     // Set an epsilon from clip planes due to possible inaccuracy
     /// \todo Rather set an identity projection matrix
     /// \todo Rather set an identity projection matrix
     farVector.z_ = Clamp(farVector.z_, (1.0f + M_LARGE_EPSILON) * nearClip, (1.0f - M_LARGE_EPSILON) * farClip);
     farVector.z_ = Clamp(farVector.z_, (1.0f + M_LARGE_EPSILON) * nearClip, (1.0f - M_LARGE_EPSILON) * farClip);
-    
+
     return  Matrix3x4(Vector3(0.0f, 0.0f, farVector.z_), Quaternion::IDENTITY, Vector3(farVector.x_, farVector.y_, 1.0f));
     return  Matrix3x4(Vector3(0.0f, 0.0f, farVector.z_), Quaternion::IDENTITY, Vector3(farVector.x_, farVector.y_, 1.0f));
 }
 }
 
 
 const Matrix3x4& Light::GetVolumeTransform(Camera* camera)
 const Matrix3x4& Light::GetVolumeTransform(Camera* camera)
 {
 {
     const Matrix3x4& transform = node_->GetWorldTransform();
     const Matrix3x4& transform = node_->GetWorldTransform();
-    
+
     switch (lightType_)
     switch (lightType_)
     {
     {
     case LIGHT_DIRECTIONAL:
     case LIGHT_DIRECTIONAL:
         volumeTransform_ = GetDirLightTransform(camera);
         volumeTransform_ = GetDirLightTransform(camera);
         break;
         break;
-        
+
     case LIGHT_SPOT:
     case LIGHT_SPOT:
         {
         {
             float yScale = tanf(fov_ * M_DEGTORAD * 0.5f) * range_;
             float yScale = tanf(fov_ * M_DEGTORAD * 0.5f) * range_;
@@ -413,12 +415,12 @@ const Matrix3x4& Light::GetVolumeTransform(Camera* camera)
             volumeTransform_ = Matrix3x4(transform.Translation(), transform.Rotation(), Vector3(xScale, yScale, range_));
             volumeTransform_ = Matrix3x4(transform.Translation(), transform.Rotation(), Vector3(xScale, yScale, range_));
         }
         }
         break;
         break;
-        
+
     case LIGHT_POINT:
     case LIGHT_POINT:
         volumeTransform_ = Matrix3x4(transform.Translation(), Quaternion::IDENTITY, range_);
         volumeTransform_ = Matrix3x4(transform.Translation(), Quaternion::IDENTITY, range_);
         break;
         break;
     }
     }
-    
+
     return volumeTransform_;
     return volumeTransform_;
 }
 }
 
 
@@ -452,12 +454,12 @@ void Light::OnWorldBoundingBoxUpdate()
         // Directional light always sets humongous bounding box not affected by transform
         // Directional light always sets humongous bounding box not affected by transform
         worldBoundingBox_.Define(-M_LARGE_VALUE, M_LARGE_VALUE);
         worldBoundingBox_.Define(-M_LARGE_VALUE, M_LARGE_VALUE);
         break;
         break;
-            
+
     case LIGHT_SPOT:
     case LIGHT_SPOT:
         // Frustum is already transformed into world space
         // Frustum is already transformed into world space
         worldBoundingBox_.Define(GetFrustum());
         worldBoundingBox_.Define(GetFrustum());
         break;
         break;
-        
+
     case LIGHT_POINT:
     case LIGHT_POINT:
         {
         {
             const Vector3& center = node_->GetWorldPosition();
             const Vector3& center = node_->GetWorldPosition();
@@ -475,7 +477,7 @@ void Light::SetIntensitySortValue(float distance)
         sortValue_ = Max(distance, M_MIN_NEARCLIP) / (color_.Intensity() + M_EPSILON);
         sortValue_ = Max(distance, M_MIN_NEARCLIP) / (color_.Intensity() + M_EPSILON);
     else
     else
         sortValue_ = M_EPSILON / (color_.Intensity() + M_EPSILON);
         sortValue_ = M_EPSILON / (color_.Intensity() + M_EPSILON);
-    
+
     // Additionally, give priority to vertex lights so that vertex light base passes can be determined before per pixel lights
     // Additionally, give priority to vertex lights so that vertex light base passes can be determined before per pixel lights
     if (perVertex_)
     if (perVertex_)
         sortValue_ -= M_LARGE_VALUE;
         sortValue_ -= M_LARGE_VALUE;
@@ -489,26 +491,26 @@ void Light::SetIntensitySortValue(const BoundingBox& box)
     case LIGHT_DIRECTIONAL:
     case LIGHT_DIRECTIONAL:
         sortValue_ = 1.0f / (color_.Intensity() + M_EPSILON);
         sortValue_ = 1.0f / (color_.Intensity() + M_EPSILON);
         break;
         break;
-        
+
     case LIGHT_SPOT:
     case LIGHT_SPOT:
         {
         {
             Vector3 centerPos = box.Center();
             Vector3 centerPos = box.Center();
             Vector3 lightPos = node_->GetWorldPosition();
             Vector3 lightPos = node_->GetWorldPosition();
             Vector3 lightDir = node_->GetWorldDirection();
             Vector3 lightDir = node_->GetWorldDirection();
             Ray lightRay(lightPos, lightDir);
             Ray lightRay(lightPos, lightDir);
-            
+
             Vector3 centerProj = lightRay.Project(centerPos);
             Vector3 centerProj = lightRay.Project(centerPos);
             float centerDistance = (centerProj - lightPos).Length();
             float centerDistance = (centerProj - lightPos).Length();
             Ray centerRay(centerProj, (centerPos - centerProj).Normalized());
             Ray centerRay(centerProj, (centerPos - centerProj).Normalized());
             float centerAngle = centerRay.HitDistance(box) / centerDistance;
             float centerAngle = centerRay.HitDistance(box) / centerDistance;
-            
+
             // Check if a corner of the bounding box is closer to the light ray than the center, use its angle in that case
             // Check if a corner of the bounding box is closer to the light ray than the center, use its angle in that case
             Vector3 cornerPos = centerPos + box.HalfSize() * Vector3(centerPos.x_ < centerProj.x_ ? 1.0f : -1.0f,
             Vector3 cornerPos = centerPos + box.HalfSize() * Vector3(centerPos.x_ < centerProj.x_ ? 1.0f : -1.0f,
                 centerPos.y_ < centerProj.y_ ? 1.0f : -1.0f, centerPos.z_ < centerProj.z_ ? 1.0f : -1.0f);
                 centerPos.y_ < centerProj.y_ ? 1.0f : -1.0f, centerPos.z_ < centerProj.z_ ? 1.0f : -1.0f);
             Vector3 cornerProj = lightRay.Project(cornerPos);
             Vector3 cornerProj = lightRay.Project(cornerPos);
             float cornerDistance = (cornerProj - lightPos).Length();
             float cornerDistance = (cornerProj - lightPos).Length();
             float cornerAngle = (cornerPos - cornerProj).Length() / cornerDistance;
             float cornerAngle = (cornerPos - cornerProj).Length() / cornerDistance;
-            
+
             float spotAngle = Min(centerAngle, cornerAngle);
             float spotAngle = Min(centerAngle, cornerAngle);
             float maxAngle = tanf(fov_ * M_DEGTORAD * 0.5f);
             float maxAngle = tanf(fov_ * M_DEGTORAD * 0.5f);
             float spotFactor = Min(spotAngle / maxAngle, 1.0f);
             float spotFactor = Min(spotAngle / maxAngle, 1.0f);
@@ -517,7 +519,7 @@ void Light::SetIntensitySortValue(const BoundingBox& box)
             sortValue_ = 1.0f / (color_.Intensity() * att + M_EPSILON);
             sortValue_ = 1.0f / (color_.Intensity() * att + M_EPSILON);
         }
         }
         break;
         break;
-            
+
     case LIGHT_POINT:
     case LIGHT_POINT:
         {
         {
             Vector3 centerPos = box.Center();
             Vector3 centerPos = box.Center();

+ 67 - 67
Engine/Graphics/Octree.cpp

@@ -52,7 +52,7 @@ void RaycastDrawablesWork(const WorkItem* item, unsigned threadIndex)
     Drawable** end = reinterpret_cast<Drawable**>(item->end_);
     Drawable** end = reinterpret_cast<Drawable**>(item->end_);
     const RayOctreeQuery& query = *octree->rayQuery_;
     const RayOctreeQuery& query = *octree->rayQuery_;
     PODVector<RayQueryResult>& results = octree->rayQueryResults_[threadIndex];
     PODVector<RayQueryResult>& results = octree->rayQueryResults_[threadIndex];
-    
+
     while (start != end)
     while (start != end)
     {
     {
         Drawable* drawable = *start;
         Drawable* drawable = *start;
@@ -66,7 +66,7 @@ void UpdateDrawablesWork(const WorkItem* item, unsigned threadIndex)
     const FrameInfo& frame = *(reinterpret_cast<FrameInfo*>(item->aux_));
     const FrameInfo& frame = *(reinterpret_cast<FrameInfo*>(item->aux_));
     WeakPtr<Drawable>* start = reinterpret_cast<WeakPtr<Drawable>*>(item->start_);
     WeakPtr<Drawable>* start = reinterpret_cast<WeakPtr<Drawable>*>(item->start_);
     WeakPtr<Drawable>* end = reinterpret_cast<WeakPtr<Drawable>*>(item->end_);
     WeakPtr<Drawable>* end = reinterpret_cast<WeakPtr<Drawable>*>(item->end_);
-    
+
     while (start != end)
     while (start != end)
     {
     {
         Drawable* drawable = *start;
         Drawable* drawable = *start;
@@ -92,7 +92,7 @@ Octant::Octant(const BoundingBox& box, unsigned level, Octant* parent, Octree* r
     index_(index)
     index_(index)
 {
 {
     Initialize(box);
     Initialize(box);
-    
+
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
         children_[i] = 0;
         children_[i] = 0;
 }
 }
@@ -111,7 +111,7 @@ Octant::~Octant()
         drawables_.Clear();
         drawables_.Clear();
         numDrawables_ = 0;
         numDrawables_ = 0;
     }
     }
-    
+
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
         DeleteChild(i);
         DeleteChild(i);
 }
 }
@@ -120,26 +120,26 @@ Octant* Octant::GetOrCreateChild(unsigned index)
 {
 {
     if (children_[index])
     if (children_[index])
         return children_[index];
         return children_[index];
-    
+
     Vector3 newMin = worldBoundingBox_.min_;
     Vector3 newMin = worldBoundingBox_.min_;
     Vector3 newMax = worldBoundingBox_.max_;
     Vector3 newMax = worldBoundingBox_.max_;
     Vector3 oldCenter = worldBoundingBox_.Center();
     Vector3 oldCenter = worldBoundingBox_.Center();
-    
+
     if (index & 1)
     if (index & 1)
         newMin.x_ = oldCenter.x_;
         newMin.x_ = oldCenter.x_;
     else
     else
         newMax.x_ = oldCenter.x_;
         newMax.x_ = oldCenter.x_;
-    
+
     if (index & 2)
     if (index & 2)
         newMin.y_ = oldCenter.y_;
         newMin.y_ = oldCenter.y_;
     else
     else
         newMax.y_ = oldCenter.y_;
         newMax.y_ = oldCenter.y_;
-    
+
     if (index & 4)
     if (index & 4)
         newMin.z_ = oldCenter.z_;
         newMin.z_ = oldCenter.z_;
     else
     else
         newMax.z_ = oldCenter.z_;
         newMax.z_ = oldCenter.z_;
-    
+
     children_[index] = new Octant(BoundingBox(newMin, newMax), level_ + 1, this, root_, index);
     children_[index] = new Octant(BoundingBox(newMin, newMax), level_ + 1, this, root_, index);
     return children_[index];
     return children_[index];
 }
 }
@@ -154,7 +154,7 @@ void Octant::DeleteChild(unsigned index)
 void Octant::InsertDrawable(Drawable* drawable)
 void Octant::InsertDrawable(Drawable* drawable)
 {
 {
     const BoundingBox& box = drawable->GetWorldBoundingBox();
     const BoundingBox& box = drawable->GetWorldBoundingBox();
-    
+
     // If root octant, insert all non-occludees here, so that octant occlusion does not hide the drawable.
     // If root octant, insert all non-occludees here, so that octant occlusion does not hide the drawable.
     // Also if drawable is outside the root octant bounds, insert to root
     // Also if drawable is outside the root octant bounds, insert to root
     bool insertHere;
     bool insertHere;
@@ -162,7 +162,7 @@ void Octant::InsertDrawable(Drawable* drawable)
         insertHere = !drawable->IsOccludee() || cullingBox_.IsInside(box) != INSIDE || CheckDrawableFit(box);
         insertHere = !drawable->IsOccludee() || cullingBox_.IsInside(box) != INSIDE || CheckDrawableFit(box);
     else
     else
         insertHere = CheckDrawableFit(box);
         insertHere = CheckDrawableFit(box);
-    
+
     if (insertHere)
     if (insertHere)
     {
     {
         Octant* oldOctant = drawable->octant_;
         Octant* oldOctant = drawable->octant_;
@@ -180,7 +180,7 @@ void Octant::InsertDrawable(Drawable* drawable)
         unsigned x = boxCenter.x_ < center_.x_ ? 0 : 1;
         unsigned x = boxCenter.x_ < center_.x_ ? 0 : 1;
         unsigned y = boxCenter.y_ < center_.y_ ? 0 : 2;
         unsigned y = boxCenter.y_ < center_.y_ ? 0 : 2;
         unsigned z = boxCenter.z_ < center_.z_ ? 0 : 4;
         unsigned z = boxCenter.z_ < center_.z_ ? 0 : 4;
-        
+
         GetOrCreateChild(x + y + z)->InsertDrawable(drawable);
         GetOrCreateChild(x + y + z)->InsertDrawable(drawable);
     }
     }
 }
 }
@@ -188,7 +188,7 @@ void Octant::InsertDrawable(Drawable* drawable)
 bool Octant::CheckDrawableFit(const BoundingBox& box) const
 bool Octant::CheckDrawableFit(const BoundingBox& box) const
 {
 {
     Vector3 boxSize = box.Size();
     Vector3 boxSize = box.Size();
-    
+
     // If max split level, size always OK, otherwise check that box is at least half size of octant
     // If max split level, size always OK, otherwise check that box is at least half size of octant
     if (level_ >= root_->GetNumLevels() || boxSize.x_ >= halfSize_.x_ || boxSize.y_ >= halfSize_.y_ ||
     if (level_ >= root_->GetNumLevels() || boxSize.x_ >= halfSize_.x_ || boxSize.y_ >= halfSize_.y_ ||
         boxSize.z_ >= halfSize_.z_)
         boxSize.z_ >= halfSize_.z_)
@@ -204,7 +204,7 @@ bool Octant::CheckDrawableFit(const BoundingBox& box) const
             box.max_.z_ >= worldBoundingBox_.max_.z_ + 0.5f * halfSize_.z_)
             box.max_.z_ >= worldBoundingBox_.max_.z_ + 0.5f * halfSize_.z_)
             return true;
             return true;
     }
     }
-    
+
     // Bounding box too small, should create a child octant
     // Bounding box too small, should create a child octant
     return false;
     return false;
 }
 }
@@ -212,7 +212,7 @@ bool Octant::CheckDrawableFit(const BoundingBox& box) const
 void Octant::ResetRoot()
 void Octant::ResetRoot()
 {
 {
     root_ = 0;
     root_ = 0;
-    
+
     // The whole octree is being destroyed, just detach the drawables
     // The whole octree is being destroyed, just detach the drawables
     for (PODVector<Drawable*>::Iterator i = drawables_.Begin(); i != drawables_.End(); ++i)
     for (PODVector<Drawable*>::Iterator i = drawables_.Begin(); i != drawables_.End(); ++i)
         (*i)->SetOctant(0);
         (*i)->SetOctant(0);
@@ -229,7 +229,7 @@ void Octant::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
     if (debug && debug->IsInside(worldBoundingBox_))
     if (debug && debug->IsInside(worldBoundingBox_))
     {
     {
         debug->AddBoundingBox(worldBoundingBox_, Color(0.25f, 0.25f, 0.25f), depthTest);
         debug->AddBoundingBox(worldBoundingBox_, Color(0.25f, 0.25f, 0.25f), depthTest);
-        
+
         for (unsigned i = 0; i < NUM_OCTANTS; ++i)
         for (unsigned i = 0; i < NUM_OCTANTS; ++i)
         {
         {
             if (children_[i])
             if (children_[i])
@@ -259,14 +259,14 @@ void Octant::GetDrawablesInternal(OctreeQuery& query, bool inside) const
             return;
             return;
         }
         }
     }
     }
-    
+
     if (drawables_.Size())
     if (drawables_.Size())
     {
     {
         Drawable** start = const_cast<Drawable**>(&drawables_[0]);
         Drawable** start = const_cast<Drawable**>(&drawables_[0]);
         Drawable** end = start + drawables_.Size();
         Drawable** end = start + drawables_.Size();
         query.TestDrawables(start, end, inside);
         query.TestDrawables(start, end, inside);
     }
     }
-    
+
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     {
     {
         if (children_[i])
         if (children_[i])
@@ -279,21 +279,21 @@ void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
     float octantDist = query.ray_.HitDistance(cullingBox_);
     float octantDist = query.ray_.HitDistance(cullingBox_);
     if (octantDist >= query.maxDistance_)
     if (octantDist >= query.maxDistance_)
         return;
         return;
-    
+
     if (drawables_.Size())
     if (drawables_.Size())
     {
     {
         Drawable** start = const_cast<Drawable**>(&drawables_[0]);
         Drawable** start = const_cast<Drawable**>(&drawables_[0]);
         Drawable** end = start + drawables_.Size();
         Drawable** end = start + drawables_.Size();
-       
+
         while (start != end)
         while (start != end)
         {
         {
             Drawable* drawable = *start++;
             Drawable* drawable = *start++;
-            
+
             if ((drawable->GetDrawableFlags() & query.drawableFlags_) && (drawable->GetViewMask() & query.viewMask_))
             if ((drawable->GetDrawableFlags() & query.drawableFlags_) && (drawable->GetViewMask() & query.viewMask_))
                 drawable->ProcessRayQuery(query, query.result_);
                 drawable->ProcessRayQuery(query, query.result_);
         }
         }
     }
     }
-    
+
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     {
     {
         if (children_[i])
         if (children_[i])
@@ -306,21 +306,21 @@ void Octant::GetDrawablesOnlyInternal(RayOctreeQuery& query, PODVector<Drawable*
     float octantDist = query.ray_.HitDistance(cullingBox_);
     float octantDist = query.ray_.HitDistance(cullingBox_);
     if (octantDist >= query.maxDistance_)
     if (octantDist >= query.maxDistance_)
         return;
         return;
-    
+
     if (drawables_.Size())
     if (drawables_.Size())
     {
     {
         Drawable** start = const_cast<Drawable**>(&drawables_[0]);
         Drawable** start = const_cast<Drawable**>(&drawables_[0]);
         Drawable** end = start + drawables_.Size();
         Drawable** end = start + drawables_.Size();
-        
+
         while (start != end)
         while (start != end)
         {
         {
             Drawable* drawable = *start++;
             Drawable* drawable = *start++;
-            
+
             if ((drawable->GetDrawableFlags() & query.drawableFlags_) && (drawable->GetViewMask() & query.viewMask_))
             if ((drawable->GetDrawableFlags() & query.drawableFlags_) && (drawable->GetViewMask() & query.viewMask_))
                 drawables.Push(drawable);
                 drawables.Push(drawable);
         }
         }
     }
     }
-    
+
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     {
     {
         if (children_[i])
         if (children_[i])
@@ -348,11 +348,11 @@ Octree::~Octree()
 
 
 void Octree::RegisterObject(Context* context)
 void Octree::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Octree>();
-    
+    context->RegisterComponentFactory<Octree>(SCENE_CATEGORY);
+
     Vector3 defaultBoundsMin = -Vector3::ONE * DEFAULT_OCTREE_SIZE;
     Vector3 defaultBoundsMin = -Vector3::ONE * DEFAULT_OCTREE_SIZE;
     Vector3 defaultBoundsMax = Vector3::ONE * DEFAULT_OCTREE_SIZE;
     Vector3 defaultBoundsMax = Vector3::ONE * DEFAULT_OCTREE_SIZE;
-    
+
     ATTRIBUTE(Octree, VAR_VECTOR3, "Bounding Box Min", worldBoundingBox_.min_, defaultBoundsMin, AM_DEFAULT);
     ATTRIBUTE(Octree, VAR_VECTOR3, "Bounding Box Min", worldBoundingBox_.min_, defaultBoundsMin, AM_DEFAULT);
     ATTRIBUTE(Octree, VAR_VECTOR3, "Bounding Box Max", worldBoundingBox_.max_, defaultBoundsMax, AM_DEFAULT);
     ATTRIBUTE(Octree, VAR_VECTOR3, "Bounding Box Max", worldBoundingBox_.max_, defaultBoundsMax, AM_DEFAULT);
     ATTRIBUTE(Octree, VAR_INT, "Number of Levels", numLevels_, DEFAULT_OCTREE_LEVELS, AM_DEFAULT);
     ATTRIBUTE(Octree, VAR_INT, "Number of Levels", numLevels_, DEFAULT_OCTREE_LEVELS, AM_DEFAULT);
@@ -370,7 +370,7 @@ void Octree::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
     if (debug)
     if (debug)
     {
     {
         PROFILE(OctreeDrawDebug);
         PROFILE(OctreeDrawDebug);
-        
+
         Octant::DrawDebugGeometry(debug, depthTest);
         Octant::DrawDebugGeometry(debug, depthTest);
     }
     }
 }
 }
@@ -378,11 +378,11 @@ void Octree::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void Octree::Resize(const BoundingBox& box, unsigned numLevels)
 void Octree::Resize(const BoundingBox& box, unsigned numLevels)
 {
 {
     PROFILE(ResizeOctree);
     PROFILE(ResizeOctree);
-    
+
     // If drawables exist, they are temporarily moved to the root
     // If drawables exist, they are temporarily moved to the root
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
     for (unsigned i = 0; i < NUM_OCTANTS; ++i)
         DeleteChild(i);
         DeleteChild(i);
-    
+
     Initialize(box);
     Initialize(box);
     numDrawables_ = drawables_.Size();
     numDrawables_ = drawables_.Size();
     numLevels_ = Max((int)numLevels, 1);
     numLevels_ = Max((int)numLevels, 1);
@@ -391,19 +391,19 @@ void Octree::Resize(const BoundingBox& box, unsigned numLevels)
 void Octree::Update(const FrameInfo& frame)
 void Octree::Update(const FrameInfo& frame)
 {
 {
     UpdateDrawables(frame);
     UpdateDrawables(frame);
-    
+
     // Notify drawable update being finished. Custom animation (eg. IK) can be done at this point
     // Notify drawable update being finished. Custom animation (eg. IK) can be done at this point
     Scene* scene = GetScene();
     Scene* scene = GetScene();
     if (scene)
     if (scene)
     {
     {
         using namespace SceneDrawableUpdateFinished;
         using namespace SceneDrawableUpdateFinished;
-        
+
         VariantMap eventData;
         VariantMap eventData;
         eventData[P_SCENE] = (void*)scene;
         eventData[P_SCENE] = (void*)scene;
         eventData[P_TIMESTEP] = frame.timeStep_;
         eventData[P_TIMESTEP] = frame.timeStep_;
         scene->SendEvent(E_SCENEDRAWABLEUPDATEFINISHED, eventData);
         scene->SendEvent(E_SCENEDRAWABLEUPDATEFINISHED, eventData);
     }
     }
-    
+
     ReinsertDrawables(frame);
     ReinsertDrawables(frame);
 }
 }
 
 
@@ -411,7 +411,7 @@ void Octree::AddManualDrawable(Drawable* drawable)
 {
 {
     if (!drawable || drawable->GetOctant())
     if (!drawable || drawable->GetOctant())
         return;
         return;
-    
+
     AddDrawable(drawable);
     AddDrawable(drawable);
 }
 }
 
 
@@ -419,7 +419,7 @@ void Octree::RemoveManualDrawable(Drawable* drawable)
 {
 {
     if (!drawable)
     if (!drawable)
         return;
         return;
-    
+
     Octant* octant = drawable->GetOctant();
     Octant* octant = drawable->GetOctant();
     if (octant && octant->GetRoot() == this)
     if (octant && octant->GetRoot() == this)
         octant->RemoveDrawable(drawable);
         octant->RemoveDrawable(drawable);
@@ -434,11 +434,11 @@ void Octree::GetDrawables(OctreeQuery& query) const
 void Octree::Raycast(RayOctreeQuery& query) const
 void Octree::Raycast(RayOctreeQuery& query) const
 {
 {
     PROFILE(Raycast);
     PROFILE(Raycast);
-    
+
     query.result_.Clear();
     query.result_.Clear();
-    
+
     WorkQueue* queue = GetSubsystem<WorkQueue>();
     WorkQueue* queue = GetSubsystem<WorkQueue>();
-    
+
     // If no worker threads or no triangle-level testing, do not create work items
     // If no worker threads or no triangle-level testing, do not create work items
     if (!queue->GetNumThreads() || query.level_ < RAY_TRIANGLE)
     if (!queue->GetNumThreads() || query.level_ < RAY_TRIANGLE)
         GetDrawablesInternal(query);
         GetDrawablesInternal(query);
@@ -448,31 +448,31 @@ void Octree::Raycast(RayOctreeQuery& query) const
         rayQuery_ = &query;
         rayQuery_ = &query;
         rayQueryDrawables_.Clear();
         rayQueryDrawables_.Clear();
         GetDrawablesOnlyInternal(query, rayQueryDrawables_);
         GetDrawablesOnlyInternal(query, rayQueryDrawables_);
-        
+
         // Check that amount of drawables is large enough to justify threading
         // Check that amount of drawables is large enough to justify threading
         if (rayQueryDrawables_.Size() > RAYCASTS_PER_WORK_ITEM)
         if (rayQueryDrawables_.Size() > RAYCASTS_PER_WORK_ITEM)
         {
         {
             for (unsigned i = 0; i < rayQueryResults_.Size(); ++i)
             for (unsigned i = 0; i < rayQueryResults_.Size(); ++i)
                 rayQueryResults_[i].Clear();
                 rayQueryResults_[i].Clear();
-            
+
             WorkItem item;
             WorkItem item;
             item.workFunction_ = RaycastDrawablesWork;
             item.workFunction_ = RaycastDrawablesWork;
             item.aux_ = const_cast<Octree*>(this);
             item.aux_ = const_cast<Octree*>(this);
-            
+
             PODVector<Drawable*>::Iterator start = rayQueryDrawables_.Begin();
             PODVector<Drawable*>::Iterator start = rayQueryDrawables_.Begin();
             while (start != rayQueryDrawables_.End())
             while (start != rayQueryDrawables_.End())
             {
             {
                 PODVector<Drawable*>::Iterator end = rayQueryDrawables_.End();
                 PODVector<Drawable*>::Iterator end = rayQueryDrawables_.End();
                 if (end - start > RAYCASTS_PER_WORK_ITEM)
                 if (end - start > RAYCASTS_PER_WORK_ITEM)
                     end = start + RAYCASTS_PER_WORK_ITEM;
                     end = start + RAYCASTS_PER_WORK_ITEM;
-                
+
                 item.start_ = &(*start);
                 item.start_ = &(*start);
                 item.end_ = &(*end);
                 item.end_ = &(*end);
                 queue->AddWorkItem(item);
                 queue->AddWorkItem(item);
-                
+
                 start = end;
                 start = end;
             }
             }
-            
+
             // Merge per-thread results
             // Merge per-thread results
             queue->Complete(M_MAX_UNSIGNED);
             queue->Complete(M_MAX_UNSIGNED);
             for (unsigned i = 0; i < rayQueryResults_.Size(); ++i)
             for (unsigned i = 0; i < rayQueryResults_.Size(); ++i)
@@ -484,27 +484,27 @@ void Octree::Raycast(RayOctreeQuery& query) const
                 (*i)->ProcessRayQuery(query, query.result_);
                 (*i)->ProcessRayQuery(query, query.result_);
         }
         }
     }
     }
-    
+
     Sort(query.result_.Begin(), query.result_.End(), CompareRayQueryResults);
     Sort(query.result_.Begin(), query.result_.End(), CompareRayQueryResults);
 }
 }
 
 
 void Octree::RaycastSingle(RayOctreeQuery& query) const
 void Octree::RaycastSingle(RayOctreeQuery& query) const
 {
 {
     PROFILE(Raycast);
     PROFILE(Raycast);
-    
+
     query.result_.Clear();
     query.result_.Clear();
     rayQueryDrawables_.Clear();
     rayQueryDrawables_.Clear();
     GetDrawablesOnlyInternal(query, rayQueryDrawables_);
     GetDrawablesOnlyInternal(query, rayQueryDrawables_);
-    
+
     // Sort by increasing hit distance to AABB
     // Sort by increasing hit distance to AABB
     for (PODVector<Drawable*>::Iterator i = rayQueryDrawables_.Begin(); i != rayQueryDrawables_.End(); ++i)
     for (PODVector<Drawable*>::Iterator i = rayQueryDrawables_.Begin(); i != rayQueryDrawables_.End(); ++i)
     {
     {
         Drawable* drawable = *i;
         Drawable* drawable = *i;
         drawable->SetSortValue(query.ray_.HitDistance(drawable->GetWorldBoundingBox()));
         drawable->SetSortValue(query.ray_.HitDistance(drawable->GetWorldBoundingBox()));
     }
     }
-    
+
     Sort(rayQueryDrawables_.Begin(), rayQueryDrawables_.End(), CompareDrawables);
     Sort(rayQueryDrawables_.Begin(), rayQueryDrawables_.End(), CompareDrawables);
-    
+
     // Then do the actual test according to the query, and early-out as possible
     // Then do the actual test according to the query, and early-out as possible
     float closestHit = M_INFINITY;
     float closestHit = M_INFINITY;
     for (PODVector<Drawable*>::Iterator i = rayQueryDrawables_.Begin(); i != rayQueryDrawables_.End(); ++i)
     for (PODVector<Drawable*>::Iterator i = rayQueryDrawables_.Begin(); i != rayQueryDrawables_.End(); ++i)
@@ -520,7 +520,7 @@ void Octree::RaycastSingle(RayOctreeQuery& query) const
         else
         else
             break;
             break;
     }
     }
-    
+
     if (query.result_.Size() > 1)
     if (query.result_.Size() > 1)
     {
     {
         Sort(query.result_.Begin(), query.result_.End(), CompareRayQueryResults);
         Sort(query.result_.Begin(), query.result_.End(), CompareRayQueryResults);
@@ -544,7 +544,7 @@ void Octree::QueueReinsertion(Drawable* drawable)
     }
     }
     else
     else
         drawableReinsertions_.Push(WeakPtr<Drawable>(drawable));
         drawableReinsertions_.Push(WeakPtr<Drawable>(drawable));
-    
+
     drawable->reinsertionQueued_ = true;
     drawable->reinsertionQueued_ = true;
 }
 }
 
 
@@ -559,31 +559,31 @@ void Octree::UpdateDrawables(const FrameInfo& frame)
     // Let drawables update themselves before reinsertion. This can be used for animation
     // Let drawables update themselves before reinsertion. This can be used for animation
     if (drawableUpdates_.Empty())
     if (drawableUpdates_.Empty())
         return;
         return;
-    
+
     PROFILE(UpdateDrawables);
     PROFILE(UpdateDrawables);
-    
+
     Scene* scene = GetScene();
     Scene* scene = GetScene();
     WorkQueue* queue = GetSubsystem<WorkQueue>();
     WorkQueue* queue = GetSubsystem<WorkQueue>();
     scene->BeginThreadedUpdate();
     scene->BeginThreadedUpdate();
-    
+
     WorkItem item;
     WorkItem item;
     item.workFunction_ = UpdateDrawablesWork;
     item.workFunction_ = UpdateDrawablesWork;
     item.aux_ = const_cast<FrameInfo*>(&frame);
     item.aux_ = const_cast<FrameInfo*>(&frame);
-    
+
     Vector<WeakPtr<Drawable> >::Iterator start = drawableUpdates_.Begin();
     Vector<WeakPtr<Drawable> >::Iterator start = drawableUpdates_.Begin();
     while (start != drawableUpdates_.End())
     while (start != drawableUpdates_.End())
     {
     {
         Vector<WeakPtr<Drawable> >::Iterator end = drawableUpdates_.End();
         Vector<WeakPtr<Drawable> >::Iterator end = drawableUpdates_.End();
         if (end - start > DRAWABLES_PER_WORK_ITEM)
         if (end - start > DRAWABLES_PER_WORK_ITEM)
             end = start + DRAWABLES_PER_WORK_ITEM;
             end = start + DRAWABLES_PER_WORK_ITEM;
-        
+
         item.start_ = &(*start);
         item.start_ = &(*start);
         item.end_ = &(*end);
         item.end_ = &(*end);
         queue->AddWorkItem(item);
         queue->AddWorkItem(item);
-        
+
         start = end;
         start = end;
     }
     }
-    
+
     queue->Complete(M_MAX_UNSIGNED);
     queue->Complete(M_MAX_UNSIGNED);
     scene->EndThreadedUpdate();
     scene->EndThreadedUpdate();
     drawableUpdates_.Clear();
     drawableUpdates_.Clear();
@@ -595,28 +595,28 @@ void Octree::ReinsertDrawables(const FrameInfo& frame)
     // the proper octant yet
     // the proper octant yet
     if (drawableReinsertions_.Empty())
     if (drawableReinsertions_.Empty())
         return;
         return;
-    
+
     PROFILE(ReinsertToOctree);
     PROFILE(ReinsertToOctree);
-    
+
     for (Vector<WeakPtr<Drawable> >::Iterator i = drawableReinsertions_.Begin(); i != drawableReinsertions_.End(); ++i)
     for (Vector<WeakPtr<Drawable> >::Iterator i = drawableReinsertions_.Begin(); i != drawableReinsertions_.End(); ++i)
     {
     {
         Drawable* drawable = *i;
         Drawable* drawable = *i;
         if (!drawable)
         if (!drawable)
             continue;
             continue;
-        
+
         drawable->reinsertionQueued_ = false;
         drawable->reinsertionQueued_ = false;
         Octant* octant = drawable->GetOctant();
         Octant* octant = drawable->GetOctant();
         const BoundingBox& box = drawable->GetWorldBoundingBox();
         const BoundingBox& box = drawable->GetWorldBoundingBox();
-        
+
         // Skip if no octant or does not belong to this octree anymore
         // Skip if no octant or does not belong to this octree anymore
         if (!octant || octant->GetRoot() != this)
         if (!octant || octant->GetRoot() != this)
             continue;
             continue;
         // Skip if still fits the current octant
         // Skip if still fits the current octant
         if (drawable->IsOccludee() && octant->GetCullingBox().IsInside(box) == INSIDE && octant->CheckDrawableFit(box))
         if (drawable->IsOccludee() && octant->GetCullingBox().IsInside(box) == INSIDE && octant->CheckDrawableFit(box))
             continue;
             continue;
-        
+
         InsertDrawable(drawable);
         InsertDrawable(drawable);
-        
+
         #ifdef _DEBUG
         #ifdef _DEBUG
         // Verify that the drawable will be culled correctly
         // Verify that the drawable will be culled correctly
         octant = drawable->GetOctant();
         octant = drawable->GetOctant();
@@ -625,7 +625,7 @@ void Octree::ReinsertDrawables(const FrameInfo& frame)
                 octant->GetCullingBox().ToString());
                 octant->GetCullingBox().ToString());
         #endif
         #endif
     }
     }
-    
+
     drawableReinsertions_.Clear();
     drawableReinsertions_.Clear();
 }
 }
 
 

+ 1 - 1
Engine/Graphics/ParticleEmitter.cpp

@@ -79,7 +79,7 @@ ParticleEmitter::~ParticleEmitter()
 
 
 void ParticleEmitter::RegisterObject(Context* context)
 void ParticleEmitter::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<ParticleEmitter>();
+    context->RegisterComponentFactory<ParticleEmitter>(EFFECT_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(ParticleEmitter, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(ParticleEmitter, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(ParticleEmitter, VAR_RESOURCEREF, "Parameter Source", GetParameterSourceAttr, SetParameterSourceAttr, ResourceRef, ResourceRef(XMLFile::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(ParticleEmitter, VAR_RESOURCEREF, "Parameter Source", GetParameterSourceAttr, SetParameterSourceAttr, ResourceRef, ResourceRef(XMLFile::GetTypeStatic()), AM_DEFAULT);

+ 6 - 4
Engine/Graphics/Skybox.cpp

@@ -32,6 +32,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+static const char* SKY_CATEGORY = "Sky";
+
 OBJECTTYPESTATIC(Skybox);
 OBJECTTYPESTATIC(Skybox);
 
 
 Skybox::Skybox(Context* context) :
 Skybox::Skybox(Context* context) :
@@ -46,8 +48,8 @@ Skybox::~Skybox()
 
 
 void Skybox::RegisterObject(Context* context)
 void Skybox::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Skybox>();
-    
+    context->RegisterComponentFactory<Skybox>(SKY_CATEGORY);
+
     COPY_BASE_ATTRIBUTES(Skybox, StaticModel);
     COPY_BASE_ATTRIBUTES(Skybox, StaticModel);
 }
 }
 
 
@@ -59,11 +61,11 @@ void Skybox::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResu
 void Skybox::UpdateBatches(const FrameInfo& frame)
 void Skybox::UpdateBatches(const FrameInfo& frame)
 {
 {
     distance_ = 0.0f;
     distance_ = 0.0f;
-    
+
     // Follow only the camera rotation, not position
     // Follow only the camera rotation, not position
     Matrix3x4 customView(Vector3::ZERO, frame.camera_->GetNode()->GetWorldRotation().Inverse(), Vector3::ONE);
     Matrix3x4 customView(Vector3::ZERO, frame.camera_->GetNode()->GetWorldRotation().Inverse(), Vector3::ONE);
     customWorldTransform_ = customView * node_->GetWorldTransform();
     customWorldTransform_ = customView * node_->GetWorldTransform();
-    
+
     for (unsigned i = 0; i < batches_.Size(); ++i)
     for (unsigned i = 0; i < batches_.Size(); ++i)
     {
     {
         batches_[i].worldTransform_ = &customWorldTransform_;
         batches_[i].worldTransform_ = &customWorldTransform_;

+ 3 - 1
Engine/Graphics/StaticModel.cpp

@@ -40,6 +40,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* STATIC_CATEGORY = "Static";
+
 OBJECTTYPESTATIC(StaticModel);
 OBJECTTYPESTATIC(StaticModel);
 
 
 StaticModel::StaticModel(Context* context) :
 StaticModel::StaticModel(Context* context) :
@@ -55,7 +57,7 @@ StaticModel::~StaticModel()
 
 
 void StaticModel::RegisterObject(Context* context)
 void StaticModel::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<StaticModel>();
+    context->RegisterComponentFactory<StaticModel>(STATIC_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(StaticModel, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(StaticModel, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(StaticModel, VAR_RESOURCEREF, "Model", GetModelAttr, SetModelAttr, ResourceRef, ResourceRef(Model::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(StaticModel, VAR_RESOURCEREF, "Model", GetModelAttr, SetModelAttr, ResourceRef, ResourceRef(Model::GetTypeStatic()), AM_DEFAULT);

+ 92 - 90
Engine/Graphics/Terrain.cpp

@@ -44,6 +44,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* TERRAIN_CATEGORY = "Terrain";
+
 OBJECTTYPESTATIC(Terrain);
 OBJECTTYPESTATIC(Terrain);
 
 
 static const Vector3 DEFAULT_SPACING(1.0f, 0.25f, 1.0f);
 static const Vector3 DEFAULT_SPACING(1.0f, 0.25f, 1.0f);
@@ -89,8 +91,8 @@ Terrain::~Terrain()
 
 
 void Terrain::RegisterObject(Context* context)
 void Terrain::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Terrain>();
-    
+    context->RegisterComponentFactory<Terrain>(TERRAIN_CATEGORY);
+
     ACCESSOR_ATTRIBUTE(Terrain, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_RESOURCEREF, "Height Map", GetHeightMapAttr, SetHeightMapAttr, ResourceRef, ResourceRef(Image::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_RESOURCEREF, "Height Map", GetHeightMapAttr, SetHeightMapAttr, ResourceRef, ResourceRef(Image::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_RESOURCEREF, "Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_RESOURCEREF, "Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);
@@ -106,13 +108,13 @@ void Terrain::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(Terrain, VAR_INT, "View Mask", GetViewMask, SetViewMask, unsigned, DEFAULT_VIEWMASK, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_INT, "View Mask", GetViewMask, SetViewMask, unsigned, DEFAULT_VIEWMASK, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_INT, "Light Mask", GetLightMask, SetLightMask, unsigned, DEFAULT_LIGHTMASK, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_INT, "Light Mask", GetLightMask, SetLightMask, unsigned, DEFAULT_LIGHTMASK, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_INT, "Shadow Mask", GetShadowMask, SetShadowMask, unsigned, DEFAULT_SHADOWMASK, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Terrain, VAR_INT, "Shadow Mask", GetShadowMask, SetShadowMask, unsigned, DEFAULT_SHADOWMASK, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(Terrain, VAR_INT, "Zone Mask", GetZoneMask, SetZoneMask, unsigned, DEFAULT_SHADOWMASK, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(Terrain, VAR_INT, "Zone Mask", GetZoneMask, SetZoneMask, unsigned, DEFAULT_ZONEMASK, AM_DEFAULT);
 }
 }
 
 
 void Terrain::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 void Terrain::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
 {
     Component::OnSetAttribute(attr, src);
     Component::OnSetAttribute(attr, src);
-    
+
     // Change of any non-accessor attribute requires recreation of the terrain
     // Change of any non-accessor attribute requires recreation of the terrain
     if (!attr.accessor_)
     if (!attr.accessor_)
         recreateTerrain_ = true;
         recreateTerrain_ = true;
@@ -127,7 +129,7 @@ void Terrain::ApplyAttributes()
 void Terrain::OnSetEnabled()
 void Terrain::OnSetEnabled()
 {
 {
     bool enabled = IsEnabledEffective();
     bool enabled = IsEnabledEffective();
-    
+
     for (unsigned i = 0; i < patches_.Size(); ++i)
     for (unsigned i = 0; i < patches_.Size(); ++i)
     {
     {
         if (patches_[i])
         if (patches_[i])
@@ -140,7 +142,7 @@ void Terrain::SetSpacing(const Vector3& spacing)
     if (spacing != spacing_)
     if (spacing != spacing_)
     {
     {
         spacing_ = spacing;
         spacing_ = spacing;
-        
+
         CreateGeometry();
         CreateGeometry();
         MarkNetworkUpdate();
         MarkNetworkUpdate();
     }
     }
@@ -150,11 +152,11 @@ void Terrain::SetPatchSize(int size)
 {
 {
     if (size < MIN_PATCH_SIZE || size > MAX_PATCH_SIZE || !IsPowerOfTwo(size))
     if (size < MIN_PATCH_SIZE || size > MAX_PATCH_SIZE || !IsPowerOfTwo(size))
         return;
         return;
-    
+
     if (size != patchSize_)
     if (size != patchSize_)
     {
     {
         patchSize_ = size;
         patchSize_ = size;
-        
+
         CreateGeometry();
         CreateGeometry();
         MarkNetworkUpdate();
         MarkNetworkUpdate();
     }
     }
@@ -163,7 +165,7 @@ void Terrain::SetPatchSize(int size)
 bool Terrain::SetHeightMap(Image* image)
 bool Terrain::SetHeightMap(Image* image)
 {
 {
     bool success = SetHeightMapInternal(image, true);
     bool success = SetHeightMapInternal(image, true);
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
     return success;
     return success;
 }
 }
@@ -176,7 +178,7 @@ void Terrain::SetMaterial(Material* material)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetMaterial(material);
             patches_[i]->SetMaterial(material);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -188,7 +190,7 @@ void Terrain::SetDrawDistance(float distance)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetDrawDistance(distance);
             patches_[i]->SetDrawDistance(distance);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -200,7 +202,7 @@ void Terrain::SetShadowDistance(float distance)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetShadowDistance(distance);
             patches_[i]->SetShadowDistance(distance);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -212,7 +214,7 @@ void Terrain::SetLodBias(float bias)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetLodBias(bias);
             patches_[i]->SetLodBias(bias);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -224,7 +226,7 @@ void Terrain::SetViewMask(unsigned mask)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetViewMask(mask);
             patches_[i]->SetViewMask(mask);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -236,7 +238,7 @@ void Terrain::SetLightMask(unsigned mask)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetLightMask(mask);
             patches_[i]->SetLightMask(mask);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -248,7 +250,7 @@ void Terrain::SetShadowMask(unsigned mask)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetShadowMask(mask);
             patches_[i]->SetShadowMask(mask);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -260,7 +262,7 @@ void Terrain::SetZoneMask(unsigned mask)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetZoneMask(mask);
             patches_[i]->SetZoneMask(mask);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -272,7 +274,7 @@ void Terrain::SetMaxLights(unsigned num)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetMaxLights(num);
             patches_[i]->SetMaxLights(num);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -284,7 +286,7 @@ void Terrain::SetCastShadows(bool enable)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetCastShadows(enable);
             patches_[i]->SetCastShadows(enable);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -296,7 +298,7 @@ void Terrain::SetOccluder(bool enable)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetOccluder(enable);
             patches_[i]->SetOccluder(enable);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -308,7 +310,7 @@ void Terrain::SetOccludee(bool enable)
         if (patches_[i])
         if (patches_[i])
             patches_[i]->SetOccludee(enable);
             patches_[i]->SetOccludee(enable);
     }
     }
-    
+
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -345,7 +347,7 @@ float Terrain::GetHeight(const Vector3& worldPosition) const
         float xFrac = xPos - floorf(xPos);
         float xFrac = xPos - floorf(xPos);
         float zFrac = zPos - floorf(zPos);
         float zFrac = zPos - floorf(zPos);
         float h1, h2, h3;
         float h1, h2, h3;
-        
+
         if (xFrac + zFrac >= 1.0f)
         if (xFrac + zFrac >= 1.0f)
         {
         {
             h1 = GetRawHeight((unsigned)xPos + 1, (unsigned)zPos + 1);
             h1 = GetRawHeight((unsigned)xPos + 1, (unsigned)zPos + 1);
@@ -360,7 +362,7 @@ float Terrain::GetHeight(const Vector3& worldPosition) const
             h2 = GetRawHeight((unsigned)xPos + 1, (unsigned)zPos);
             h2 = GetRawHeight((unsigned)xPos + 1, (unsigned)zPos);
             h3 = GetRawHeight((unsigned)xPos, (unsigned)zPos + 1);
             h3 = GetRawHeight((unsigned)xPos, (unsigned)zPos + 1);
         }
         }
-        
+
         float h = h1 * (1.0f - xFrac - zFrac) + h2 * xFrac + h3 * zFrac;
         float h = h1 * (1.0f - xFrac - zFrac) + h2 * xFrac + h3 * zFrac;
         /// \todo This assumes that the terrain scene node is upright
         /// \todo This assumes that the terrain scene node is upright
         return node_->GetWorldScale().y_ * h + node_->GetWorldPosition().y_;
         return node_->GetWorldScale().y_ * h + node_->GetWorldPosition().y_;
@@ -379,7 +381,7 @@ Vector3 Terrain::GetNormal(const Vector3& worldPosition) const
         float xFrac = xPos - floorf(xPos);
         float xFrac = xPos - floorf(xPos);
         float zFrac = zPos - floorf(zPos);
         float zFrac = zPos - floorf(zPos);
         Vector3 n1, n2, n3;
         Vector3 n1, n2, n3;
-        
+
         if (xFrac + zFrac >= 1.0f)
         if (xFrac + zFrac >= 1.0f)
         {
         {
             n1 = GetRawNormal((unsigned)xPos + 1, (unsigned)zPos + 1);
             n1 = GetRawNormal((unsigned)xPos + 1, (unsigned)zPos + 1);
@@ -394,7 +396,7 @@ Vector3 Terrain::GetNormal(const Vector3& worldPosition) const
             n2 = GetRawNormal((unsigned)xPos + 1, (unsigned)zPos);
             n2 = GetRawNormal((unsigned)xPos + 1, (unsigned)zPos);
             n3 = GetRawNormal((unsigned)xPos, (unsigned)zPos + 1);
             n3 = GetRawNormal((unsigned)xPos, (unsigned)zPos + 1);
         }
         }
-        
+
         Vector3 n = (n1 * (1.0f - xFrac - zFrac) + n2 * xFrac + n3 * zFrac).Normalized();
         Vector3 n = (n1 * (1.0f - xFrac - zFrac) + n2 * xFrac + n3 * zFrac).Normalized();
         return node_->GetWorldRotation() * n;
         return node_->GetWorldRotation() * n;
     }
     }
@@ -405,33 +407,33 @@ Vector3 Terrain::GetNormal(const Vector3& worldPosition) const
 void Terrain::CreatePatchGeometry(TerrainPatch* patch)
 void Terrain::CreatePatchGeometry(TerrainPatch* patch)
 {
 {
     PROFILE(CreatePatchGeometry);
     PROFILE(CreatePatchGeometry);
-    
+
     unsigned row = patchSize_ + 1;
     unsigned row = patchSize_ + 1;
     VertexBuffer* vertexBuffer = patch->GetVertexBuffer();
     VertexBuffer* vertexBuffer = patch->GetVertexBuffer();
     Geometry* geometry = patch->GetGeometry();
     Geometry* geometry = patch->GetGeometry();
     Geometry* maxLodGeometry = patch->GetMaxLodGeometry();
     Geometry* maxLodGeometry = patch->GetMaxLodGeometry();
     Geometry* minLodGeometry = patch->GetMinLodGeometry();
     Geometry* minLodGeometry = patch->GetMinLodGeometry();
-    
+
     if (vertexBuffer->GetVertexCount() != row * row)
     if (vertexBuffer->GetVertexCount() != row * row)
         vertexBuffer->SetSize(row * row, MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT);
         vertexBuffer->SetSize(row * row, MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT);
-    
+
     SharedArrayPtr<unsigned char> cpuVertexData(new unsigned char[row * row * sizeof(Vector3)]);
     SharedArrayPtr<unsigned char> cpuVertexData(new unsigned char[row * row * sizeof(Vector3)]);
-    
+
     float* vertexData = (float*)vertexBuffer->Lock(0, vertexBuffer->GetVertexCount());
     float* vertexData = (float*)vertexBuffer->Lock(0, vertexBuffer->GetVertexCount());
     float* positionData = (float*)cpuVertexData.Get();
     float* positionData = (float*)cpuVertexData.Get();
     BoundingBox box;
     BoundingBox box;
-    
+
     if (vertexData)
     if (vertexData)
     {
     {
         const IntVector2& coords = patch->GetCoordinates();
         const IntVector2& coords = patch->GetCoordinates();
-        
+
         for (int z1 = 0; z1 <= patchSize_; ++z1)
         for (int z1 = 0; z1 <= patchSize_; ++z1)
         {
         {
             for (int x1 = 0; x1 <= patchSize_; ++x1)
             for (int x1 = 0; x1 <= patchSize_; ++x1)
             {
             {
                 int xPos = coords.x_ * patchSize_ + x1;
                 int xPos = coords.x_ * patchSize_ + x1;
                 int zPos = coords.y_ * patchSize_ + z1;
                 int zPos = coords.y_ * patchSize_ + z1;
-                
+
                 // Position
                 // Position
                 Vector3 position((float)x1 * spacing_.x_, GetRawHeight(xPos, zPos), (float)z1 * spacing_.z_);
                 Vector3 position((float)x1 * spacing_.x_, GetRawHeight(xPos, zPos), (float)z1 * spacing_.z_);
                 *vertexData++ = position.x_;
                 *vertexData++ = position.x_;
@@ -440,20 +442,20 @@ void Terrain::CreatePatchGeometry(TerrainPatch* patch)
                 *positionData++ = position.x_;
                 *positionData++ = position.x_;
                 *positionData++ = position.y_;
                 *positionData++ = position.y_;
                 *positionData++ = position.z_;
                 *positionData++ = position.z_;
-                
+
                 box.Merge(position);
                 box.Merge(position);
-                
+
                 // Normal
                 // Normal
                 Vector3 normal = GetRawNormal(xPos, zPos);
                 Vector3 normal = GetRawNormal(xPos, zPos);
                 *vertexData++ = normal.x_;
                 *vertexData++ = normal.x_;
                 *vertexData++ = normal.y_;
                 *vertexData++ = normal.y_;
                 *vertexData++ = normal.z_;
                 *vertexData++ = normal.z_;
-                
+
                 // Texture coordinate
                 // Texture coordinate
                 Vector2 texCoord((float)xPos / (float)numVertices_.x_, 1.0f - (float)zPos / (float)numVertices_.y_);
                 Vector2 texCoord((float)xPos / (float)numVertices_.x_, 1.0f - (float)zPos / (float)numVertices_.y_);
                 *vertexData++ = texCoord.x_;
                 *vertexData++ = texCoord.x_;
                 *vertexData++ = texCoord.y_;
                 *vertexData++ = texCoord.y_;
-                
+
                 // Tangent
                 // Tangent
                 Vector3 xyz = (Vector3::RIGHT - normal * normal.DotProduct(Vector3::RIGHT)).Normalized();
                 Vector3 xyz = (Vector3::RIGHT - normal * normal.DotProduct(Vector3::RIGHT)).Normalized();
                 *vertexData++ = xyz.x_;
                 *vertexData++ = xyz.x_;
@@ -462,17 +464,17 @@ void Terrain::CreatePatchGeometry(TerrainPatch* patch)
                 *vertexData++ = 1.0f;
                 *vertexData++ = 1.0f;
             }
             }
         }
         }
-        
+
         vertexBuffer->Unlock();
         vertexBuffer->Unlock();
         vertexBuffer->ClearDataLost();
         vertexBuffer->ClearDataLost();
     }
     }
-    
+
     patch->SetBoundingBox(box);
     patch->SetBoundingBox(box);
-    
+
     if (drawRanges_.Size())
     if (drawRanges_.Size())
     {
     {
         unsigned lastDrawRange = drawRanges_.Size() - 1;
         unsigned lastDrawRange = drawRanges_.Size() - 1;
-        
+
         geometry->SetIndexBuffer(indexBuffer_);
         geometry->SetIndexBuffer(indexBuffer_);
         geometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[0].first_, drawRanges_[0].second_, false);
         geometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[0].first_, drawRanges_[0].second_, false);
         geometry->SetRawVertexData(cpuVertexData, sizeof(Vector3), MASK_POSITION);
         geometry->SetRawVertexData(cpuVertexData, sizeof(Vector3), MASK_POSITION);
@@ -483,7 +485,7 @@ void Terrain::CreatePatchGeometry(TerrainPatch* patch)
         minLodGeometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[lastDrawRange].first_, drawRanges_[lastDrawRange].second_, false);
         minLodGeometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[lastDrawRange].first_, drawRanges_[lastDrawRange].second_, false);
         minLodGeometry->SetRawVertexData(cpuVertexData, sizeof(Vector3), MASK_POSITION);
         minLodGeometry->SetRawVertexData(cpuVertexData, sizeof(Vector3), MASK_POSITION);
     }
     }
-    
+
     // Offset the occlusion geometry by vertex spacing to reduce possibility of over-aggressive occlusion
     // Offset the occlusion geometry by vertex spacing to reduce possibility of over-aggressive occlusion
     patch->SetOcclusionOffset(-0.5f * (spacing_.x_ + spacing_.z_));
     patch->SetOcclusionOffset(-0.5f * (spacing_.x_ + spacing_.z_));
     patch->ResetLod();
     patch->ResetLod();
@@ -492,7 +494,7 @@ void Terrain::CreatePatchGeometry(TerrainPatch* patch)
 void Terrain::UpdatePatchLod(TerrainPatch* patch)
 void Terrain::UpdatePatchLod(TerrainPatch* patch)
 {
 {
     Geometry* geometry = patch->GetGeometry();
     Geometry* geometry = patch->GetGeometry();
-    
+
     // All LOD levels except the coarsest have 16 versions for stitching
     // All LOD levels except the coarsest have 16 versions for stitching
     unsigned lodLevel = patch->GetLodLevel();
     unsigned lodLevel = patch->GetLodLevel();
     unsigned drawRangeIndex = lodLevel << 4;
     unsigned drawRangeIndex = lodLevel << 4;
@@ -502,7 +504,7 @@ void Terrain::UpdatePatchLod(TerrainPatch* patch)
         TerrainPatch* south = patch->GetSouthPatch();
         TerrainPatch* south = patch->GetSouthPatch();
         TerrainPatch* west = patch->GetWestPatch();
         TerrainPatch* west = patch->GetWestPatch();
         TerrainPatch* east = patch->GetEastPatch();
         TerrainPatch* east = patch->GetEastPatch();
-        
+
         if (north && north->GetLodLevel() > lodLevel)
         if (north && north->GetLodLevel() > lodLevel)
             drawRangeIndex |= STITCH_NORTH;
             drawRangeIndex |= STITCH_NORTH;
         if (south && south->GetLodLevel() > lodLevel)
         if (south && south->GetLodLevel() > lodLevel)
@@ -512,7 +514,7 @@ void Terrain::UpdatePatchLod(TerrainPatch* patch)
         if (east && east->GetLodLevel() > lodLevel)
         if (east && east->GetLodLevel() > lodLevel)
             drawRangeIndex |= STITCH_EAST;
             drawRangeIndex |= STITCH_EAST;
     }
     }
-    
+
     if (drawRangeIndex < drawRanges_.Size())
     if (drawRangeIndex < drawRanges_.Size())
         geometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[drawRangeIndex].first_, drawRanges_[drawRangeIndex].second_, false);
         geometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[drawRangeIndex].first_, drawRanges_[drawRangeIndex].second_, false);
 }
 }
@@ -534,7 +536,7 @@ void Terrain::SetPatchSizeAttr(int value)
 {
 {
     if (value < MIN_PATCH_SIZE || value > MAX_PATCH_SIZE || !IsPowerOfTwo(value))
     if (value < MIN_PATCH_SIZE || value > MAX_PATCH_SIZE || !IsPowerOfTwo(value))
         return;
         return;
-    
+
     if (value != patchSize_)
     if (value != patchSize_)
     {
     {
         patchSize_ = value;
         patchSize_ = value;
@@ -555,14 +557,14 @@ ResourceRef Terrain::GetHeightMapAttr() const
 void Terrain::CreateGeometry()
 void Terrain::CreateGeometry()
 {
 {
     recreateTerrain_ = false;
     recreateTerrain_ = false;
-    
+
     if (!node_)
     if (!node_)
         return;
         return;
-    
+
     PROFILE(CreateTerrainGeometry);
     PROFILE(CreateTerrainGeometry);
-    
+
     unsigned prevNumPatches = patches_.Size();
     unsigned prevNumPatches = patches_.Size();
-    
+
     // Determine number of LOD levels
     // Determine number of LOD levels
     unsigned lodSize = patchSize_;
     unsigned lodSize = patchSize_;
     numLodLevels_ = 1;
     numLodLevels_ = 1;
@@ -571,7 +573,7 @@ void Terrain::CreateGeometry()
         lodSize >>= 1;
         lodSize >>= 1;
         ++numLodLevels_;
         ++numLodLevels_;
     }
     }
-    
+
     // Determine total terrain size
     // Determine total terrain size
     patchWorldSize_ = Vector2(spacing_.x_ * (float)patchSize_, spacing_.z_ * (float)patchSize_);
     patchWorldSize_ = Vector2(spacing_.x_ * (float)patchSize_, spacing_.z_ * (float)patchSize_);
     if (heightMap_)
     if (heightMap_)
@@ -589,7 +591,7 @@ void Terrain::CreateGeometry()
         patchWorldOrigin_ = Vector2::ZERO;
         patchWorldOrigin_ = Vector2::ZERO;
         heightData_.Reset();
         heightData_.Reset();
     }
     }
-    
+
     // Remove old patch nodes which are not needed
     // Remove old patch nodes which are not needed
     PODVector<Node*> oldPatchNodes;
     PODVector<Node*> oldPatchNodes;
     node_->GetChildrenWithComponent<TerrainPatch>(oldPatchNodes);
     node_->GetChildrenWithComponent<TerrainPatch>(oldPatchNodes);
@@ -604,13 +606,13 @@ void Terrain::CreateGeometry()
             if (x < numPatches_.x_ && z < numPatches_.y_)
             if (x < numPatches_.x_ && z < numPatches_.y_)
                 nodeOk = true;
                 nodeOk = true;
         }
         }
-        
+
         if (!nodeOk)
         if (!nodeOk)
             node_->RemoveChild(*i);
             node_->RemoveChild(*i);
     }
     }
-    
+
     patches_.Clear();
     patches_.Clear();
-    
+
     if (heightMap_)
     if (heightMap_)
     {
     {
         // Copy heightmap data
         // Copy heightmap data
@@ -618,7 +620,7 @@ void Terrain::CreateGeometry()
         float* dest = heightData_;
         float* dest = heightData_;
         unsigned imgComps = heightMap_->GetComponents();
         unsigned imgComps = heightMap_->GetComponents();
         unsigned imgRow = heightMap_->GetWidth() * imgComps;
         unsigned imgRow = heightMap_->GetWidth() * imgComps;
-        
+
         if (imgComps == 1)
         if (imgComps == 1)
         {
         {
             for (int z = 0; z < numVertices_.y_; ++z)
             for (int z = 0; z < numVertices_.y_; ++z)
@@ -651,14 +653,14 @@ void Terrain::CreateGeometry()
                 Node* patchNode = node_->GetChild(nodeName);
                 Node* patchNode = node_->GetChild(nodeName);
                 if (!patchNode)
                 if (!patchNode)
                     patchNode = node_->CreateChild(nodeName, LOCAL);
                     patchNode = node_->CreateChild(nodeName, LOCAL);
-                
+
                 patchNode->SetPosition(Vector3(patchWorldOrigin_.x_ + (float)x * patchWorldSize_.x_, 0.0f, patchWorldOrigin_.y_ +
                 patchNode->SetPosition(Vector3(patchWorldOrigin_.x_ + (float)x * patchWorldSize_.x_, 0.0f, patchWorldOrigin_.y_ +
                     (float)z * patchWorldSize_.y_));
                     (float)z * patchWorldSize_.y_));
-                
+
                 TerrainPatch* patch = patchNode->GetOrCreateComponent<TerrainPatch>();
                 TerrainPatch* patch = patchNode->GetOrCreateComponent<TerrainPatch>();
                 patch->SetOwner(this);
                 patch->SetOwner(this);
                 patch->SetCoordinates(IntVector2(x, z));
                 patch->SetCoordinates(IntVector2(x, z));
-                
+
                 // Copy initial drawable parameters
                 // Copy initial drawable parameters
                 patch->SetEnabled(enabled);
                 patch->SetEnabled(enabled);
                 patch->SetMaterial(material_);
                 patch->SetMaterial(material_);
@@ -673,14 +675,14 @@ void Terrain::CreateGeometry()
                 patch->SetCastShadows(castShadows_);
                 patch->SetCastShadows(castShadows_);
                 patch->SetOccluder(occluder_);
                 patch->SetOccluder(occluder_);
                 patch->SetOccludee(occludee_);
                 patch->SetOccludee(occludee_);
-                
+
                 patches_.Push(WeakPtr<TerrainPatch>(patch));
                 patches_.Push(WeakPtr<TerrainPatch>(patch));
             }
             }
         }
         }
-        
+
         // Create the shared index data
         // Create the shared index data
         CreateIndexData();
         CreateIndexData();
-        
+
         // Create vertex data for patches
         // Create vertex data for patches
         for (Vector<WeakPtr<TerrainPatch> >::Iterator i = patches_.Begin(); i != patches_.End(); ++i)
         for (Vector<WeakPtr<TerrainPatch> >::Iterator i = patches_.Begin(); i != patches_.End(); ++i)
         {
         {
@@ -689,12 +691,12 @@ void Terrain::CreateGeometry()
             SetNeighbors(*i);
             SetNeighbors(*i);
         }
         }
     }
     }
-    
+
     // Send event only if new geometry was generated, or the old was cleared
     // Send event only if new geometry was generated, or the old was cleared
     if (patches_.Size() || prevNumPatches)
     if (patches_.Size() || prevNumPatches)
     {
     {
         using namespace TerrainCreated;
         using namespace TerrainCreated;
-        
+
         VariantMap eventData;
         VariantMap eventData;
         eventData[P_NODE] = (void*)node_;
         eventData[P_NODE] = (void*)node_;
         node_->SendEvent(E_TERRAINCREATED, eventData);
         node_->SendEvent(E_TERRAINCREATED, eventData);
@@ -704,25 +706,25 @@ void Terrain::CreateGeometry()
 void Terrain::CreateIndexData()
 void Terrain::CreateIndexData()
 {
 {
     PROFILE(CreateIndexData);
     PROFILE(CreateIndexData);
-    
+
     PODVector<unsigned short> indices;
     PODVector<unsigned short> indices;
     drawRanges_.Clear();
     drawRanges_.Clear();
     unsigned row = patchSize_ + 1;
     unsigned row = patchSize_ + 1;
-    
+
     for (unsigned i = 0; i < numLodLevels_; ++i)
     for (unsigned i = 0; i < numLodLevels_; ++i)
     {
     {
         unsigned combinations = (i < numLodLevels_ - 1) ? 16 : 1;
         unsigned combinations = (i < numLodLevels_ - 1) ? 16 : 1;
         int skip = 1 << i;
         int skip = 1 << i;
-        
+
         for (unsigned j = 0; j < combinations; ++j)
         for (unsigned j = 0; j < combinations; ++j)
         {
         {
             unsigned indexStart = indices.Size();
             unsigned indexStart = indices.Size();
-            
+
             int zStart = 0;
             int zStart = 0;
             int xStart = 0;
             int xStart = 0;
             int zEnd = patchSize_;
             int zEnd = patchSize_;
             int xEnd = patchSize_;
             int xEnd = patchSize_;
-            
+
             if (j & STITCH_NORTH)
             if (j & STITCH_NORTH)
                 zEnd -= skip;
                 zEnd -= skip;
             if (j & STITCH_SOUTH)
             if (j & STITCH_SOUTH)
@@ -731,7 +733,7 @@ void Terrain::CreateIndexData()
                 xStart += skip;
                 xStart += skip;
             if (j & STITCH_EAST)
             if (j & STITCH_EAST)
                 xEnd -= skip;
                 xEnd -= skip;
-            
+
             // Build the main grid
             // Build the main grid
             for (int z = zStart; z < zEnd; z += skip)
             for (int z = zStart; z < zEnd; z += skip)
             {
             {
@@ -745,7 +747,7 @@ void Terrain::CreateIndexData()
                     indices.Push(z * row + x + skip);
                     indices.Push(z * row + x + skip);
                 }
                 }
             }
             }
-            
+
             // Build the north edge
             // Build the north edge
             if (j & STITCH_NORTH)
             if (j & STITCH_NORTH)
             {
             {
@@ -769,7 +771,7 @@ void Terrain::CreateIndexData()
                     }
                     }
                 }
                 }
             }
             }
-            
+
             // Build the south edge
             // Build the south edge
             if (j & STITCH_SOUTH)
             if (j & STITCH_SOUTH)
             {
             {
@@ -793,7 +795,7 @@ void Terrain::CreateIndexData()
                     }
                     }
                 }
                 }
             }
             }
-            
+
             // Build the west edge
             // Build the west edge
             if (j & STITCH_WEST)
             if (j & STITCH_WEST)
             {
             {
@@ -817,7 +819,7 @@ void Terrain::CreateIndexData()
                     }
                     }
                 }
                 }
             }
             }
-            
+
             // Build the east edge
             // Build the east edge
             if (j & STITCH_EAST)
             if (j & STITCH_EAST)
             {
             {
@@ -841,11 +843,11 @@ void Terrain::CreateIndexData()
                     }
                     }
                 }
                 }
             }
             }
-            
+
             drawRanges_.Push(MakePair(indexStart, indices.Size() - indexStart));
             drawRanges_.Push(MakePair(indexStart, indices.Size() - indexStart));
         }
         }
     }
     }
-    
+
     indexBuffer_->SetSize(indices.Size(), false);
     indexBuffer_->SetSize(indices.Size(), false);
     unsigned short* indexData = (unsigned short*)indexBuffer_->Lock(0, indices.Size());
     unsigned short* indexData = (unsigned short*)indexBuffer_->Lock(0, indices.Size());
     if (indexData)
     if (indexData)
@@ -859,7 +861,7 @@ float Terrain::GetRawHeight(int x, int z) const
 {
 {
     if (!heightData_)
     if (!heightData_)
         return 0.0f;
         return 0.0f;
-    
+
     x = Clamp(x, 0, numVertices_.x_ - 1);
     x = Clamp(x, 0, numVertices_.x_ - 1);
     z = Clamp(z, 0, numVertices_.y_ - 1);
     z = Clamp(z, 0, numVertices_.y_ - 1);
     return heightData_[z * numVertices_.x_ + x];
     return heightData_[z * numVertices_.x_ + x];
@@ -872,7 +874,7 @@ float Terrain::GetLodHeight(int x, int z, unsigned lodLevel) const
     float xFrac = (float)(x % offset) / divisor;
     float xFrac = (float)(x % offset) / divisor;
     float zFrac = (float)(z % offset) / divisor;
     float zFrac = (float)(z % offset) / divisor;
     float h1, h2, h3;
     float h1, h2, h3;
-    
+
     if (xFrac + zFrac >= 1.0f)
     if (xFrac + zFrac >= 1.0f)
     {
     {
         h1 = GetRawHeight(x + offset, z + offset);
         h1 = GetRawHeight(x + offset, z + offset);
@@ -887,7 +889,7 @@ float Terrain::GetLodHeight(int x, int z, unsigned lodLevel) const
         h2 = GetRawHeight(x + offset, z);
         h2 = GetRawHeight(x + offset, z);
         h3 = GetRawHeight(x, z + offset);
         h3 = GetRawHeight(x, z + offset);
     }
     }
-    
+
     return h1 * (1.0f - xFrac - zFrac) + h2 * xFrac + h3 * zFrac;
     return h1 * (1.0f - xFrac - zFrac) + h2 * xFrac + h3 * zFrac;
 }
 }
 
 
@@ -903,13 +905,13 @@ Vector3 Terrain::GetRawNormal(int x, int z) const
     float wSlope = GetRawHeight(x - 1, z) - baseHeight;
     float wSlope = GetRawHeight(x - 1, z) - baseHeight;
     float nwSlope = GetRawHeight(x - 1, z - 1) - baseHeight;
     float nwSlope = GetRawHeight(x - 1, z - 1) - baseHeight;
     float up = 0.5f * (spacing_.x_ + spacing_.z_);
     float up = 0.5f * (spacing_.x_ + spacing_.z_);
-    
+
     return (Vector3(0.0f, up, nSlope) +
     return (Vector3(0.0f, up, nSlope) +
         Vector3(-neSlope, up, neSlope) +
         Vector3(-neSlope, up, neSlope) +
         Vector3(-eSlope, up, 0.0f) +
         Vector3(-eSlope, up, 0.0f) +
         Vector3(-seSlope, up, -seSlope) +
         Vector3(-seSlope, up, -seSlope) +
         Vector3(0.0f, up, -sSlope) +
         Vector3(0.0f, up, -sSlope) +
-        Vector3(swSlope, up, -swSlope) + 
+        Vector3(swSlope, up, -swSlope) +
         Vector3(wSlope, up, 0.0f) +
         Vector3(wSlope, up, 0.0f) +
         Vector3(nwSlope, up, nwSlope)).Normalized();
         Vector3(nwSlope, up, nwSlope)).Normalized();
 }
 }
@@ -917,22 +919,22 @@ Vector3 Terrain::GetRawNormal(int x, int z) const
 void Terrain::CalculateLodErrors(TerrainPatch* patch)
 void Terrain::CalculateLodErrors(TerrainPatch* patch)
 {
 {
     PROFILE(CalculateLodErrors);
     PROFILE(CalculateLodErrors);
-    
+
     const IntVector2& coords = patch->GetCoordinates();
     const IntVector2& coords = patch->GetCoordinates();
     PODVector<float>& lodErrors = patch->GetLodErrors();
     PODVector<float>& lodErrors = patch->GetLodErrors();
     lodErrors.Clear();
     lodErrors.Clear();
     lodErrors.Reserve(numLodLevels_);
     lodErrors.Reserve(numLodLevels_);
-    
+
     int xStart = coords.x_ * patchSize_;
     int xStart = coords.x_ * patchSize_;
     int zStart = coords.y_ * patchSize_;
     int zStart = coords.y_ * patchSize_;
     int xEnd = xStart + patchSize_;
     int xEnd = xStart + patchSize_;
     int zEnd = zStart + patchSize_;
     int zEnd = zStart + patchSize_;
-    
+
     for (unsigned i = 0; i < numLodLevels_; ++i)
     for (unsigned i = 0; i < numLodLevels_; ++i)
     {
     {
         float maxError = 0.0f;
         float maxError = 0.0f;
         int divisor = 1 << i;
         int divisor = 1 << i;
-        
+
         if (i > 0)
         if (i > 0)
         {
         {
             for (int z = zStart; z <= zEnd; ++z)
             for (int z = zStart; z <= zEnd; ++z)
@@ -946,11 +948,11 @@ void Terrain::CalculateLodErrors(TerrainPatch* patch)
                     }
                     }
                 }
                 }
             }
             }
-            
+
             // Set error to be at least same as (half vertex spacing x LOD) to prevent horizontal stretches getting too inaccurate
             // Set error to be at least same as (half vertex spacing x LOD) to prevent horizontal stretches getting too inaccurate
             maxError = Max(maxError, 0.25f * (spacing_.x_ + spacing_.z_) * (float)(1 << i));
             maxError = Max(maxError, 0.25f * (spacing_.x_ + spacing_.z_) * (float)(1 << i));
         }
         }
-        
+
         lodErrors.Push(maxError);
         lodErrors.Push(maxError);
     }
     }
 }
 }
@@ -969,20 +971,20 @@ bool Terrain::SetHeightMapInternal(Image* image, bool recreateNow)
         LOGERROR("Can not use a compressed image as a terrain heightmap");
         LOGERROR("Can not use a compressed image as a terrain heightmap");
         return false;
         return false;
     }
     }
-    
+
     // Unsubscribe from the reload event of previous image (if any), then subscribe to the new
     // Unsubscribe from the reload event of previous image (if any), then subscribe to the new
     if (heightMap_)
     if (heightMap_)
         UnsubscribeFromEvent(heightMap_, E_RELOADFINISHED);
         UnsubscribeFromEvent(heightMap_, E_RELOADFINISHED);
     if (image)
     if (image)
         SubscribeToEvent(image, E_RELOADFINISHED, HANDLER(Terrain, HandleHeightMapReloadFinished));
         SubscribeToEvent(image, E_RELOADFINISHED, HANDLER(Terrain, HandleHeightMapReloadFinished));
-    
+
     heightMap_ = image;
     heightMap_ = image;
-    
+
     if (recreateNow)
     if (recreateNow)
         CreateGeometry();
         CreateGeometry();
     else
     else
         recreateTerrain_ = true;
         recreateTerrain_ = true;
-    
+
     return true;
     return true;
 }
 }
 
 

+ 9 - 7
Engine/Graphics/Terrain.h

@@ -27,6 +27,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* TERRAIN_CATEGORY;
+
 class Image;
 class Image;
 class Material;
 class Material;
 class Node;
 class Node;
@@ -36,7 +38,7 @@ class TerrainPatch;
 class Terrain : public Component
 class Terrain : public Component
 {
 {
     OBJECT(Terrain);
     OBJECT(Terrain);
-    
+
 public:
 public:
     /// Construct.
     /// Construct.
     Terrain(Context* context);
     Terrain(Context* context);
@@ -44,14 +46,14 @@ public:
     ~Terrain();
     ~Terrain();
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
-    
+
     /// Handle attribute write access.
     /// Handle attribute write access.
     virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
     virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
     /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
     /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
     virtual void ApplyAttributes();
     virtual void ApplyAttributes();
     /// Handle enabled/disabled state change.
     /// Handle enabled/disabled state change.
     virtual void OnSetEnabled();
     virtual void OnSetEnabled();
-    
+
     /// Set patch quads per side. Must be a power of two.
     /// Set patch quads per side. Must be a power of two.
     void SetPatchSize(int size);
     void SetPatchSize(int size);
     /// Set vertex (XZ) and height (Y) spacing.
     /// Set vertex (XZ) and height (Y) spacing.
@@ -82,7 +84,7 @@ public:
     void SetOccluder(bool enable);
     void SetOccluder(bool enable);
     /// Set occludee flag for patches.
     /// Set occludee flag for patches.
     void SetOccludee(bool enable);
     void SetOccludee(bool enable);
-    
+
     /// Return patch quads per side.
     /// Return patch quads per side.
     int GetPatchSize() const { return patchSize_; }
     int GetPatchSize() const { return patchSize_; }
     /// Return vertex and height spacing.
     /// Return vertex and height spacing.
@@ -129,7 +131,7 @@ public:
     bool IsOccluder() const { return occluder_; }
     bool IsOccluder() const { return occluder_; }
     /// Return occludee flag.
     /// Return occludee flag.
     bool IsOccludee() const { return occludee_; }
     bool IsOccludee() const { return occludee_; }
-    
+
     /// Regenerate patch geometry.
     /// Regenerate patch geometry.
     void CreatePatchGeometry(TerrainPatch* patch);
     void CreatePatchGeometry(TerrainPatch* patch);
     /// Update patch based on LOD and neighbor LOD.
     /// Update patch based on LOD and neighbor LOD.
@@ -144,7 +146,7 @@ public:
     ResourceRef GetHeightMapAttr() const;
     ResourceRef GetHeightMapAttr() const;
     /// Return material attribute.
     /// Return material attribute.
     ResourceRef GetMaterialAttr() const;
     ResourceRef GetMaterialAttr() const;
-    
+
 private:
 private:
     /// Fully regenerate terrain geometry.
     /// Fully regenerate terrain geometry.
     void CreateGeometry();
     void CreateGeometry();
@@ -164,7 +166,7 @@ private:
     bool SetHeightMapInternal(Image* image, bool recreateNow);
     bool SetHeightMapInternal(Image* image, bool recreateNow);
     /// Handle heightmap image reload finished.
     /// Handle heightmap image reload finished.
     void HandleHeightMapReloadFinished(StringHash eventType, VariantMap& eventData);
     void HandleHeightMapReloadFinished(StringHash eventType, VariantMap& eventData);
-    
+
     /// Shared index buffer.
     /// Shared index buffer.
     SharedPtr<IndexBuffer> indexBuffer_;
     SharedPtr<IndexBuffer> indexBuffer_;
     /// Heightmap image.
     /// Heightmap image.

+ 1 - 1
Engine/Graphics/TerrainPatch.cpp

@@ -68,7 +68,7 @@ TerrainPatch::~TerrainPatch()
 
 
 void TerrainPatch::RegisterObject(Context* context)
 void TerrainPatch::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<TerrainPatch>();
+    context->RegisterComponentFactory<TerrainPatch>(TERRAIN_CATEGORY);
 }
 }
 
 
 void TerrainPatch::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
 void TerrainPatch::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)

+ 1 - 1
Engine/Graphics/Zone.cpp

@@ -62,7 +62,7 @@ Zone::~Zone()
 
 
 void Zone::RegisterObject(Context* context)
 void Zone::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Zone>();
+    context->RegisterComponentFactory<Zone>(SCENE_CATEGORY);
 
 
     ACCESSOR_ATTRIBUTE(Zone, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Zone, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_VECTOR3, "Bounding Box Min", boundingBox_.min_, DEFAULT_BOUNDING_BOX_MIN, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_VECTOR3, "Bounding Box Min", boundingBox_.min_, DEFAULT_BOUNDING_BOX_MIN, AM_DEFAULT);

+ 4 - 2
Engine/Navigation/Navigable.cpp

@@ -29,6 +29,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* NAVIGATION_CATEGORY;
+
 OBJECTTYPESTATIC(Navigable);
 OBJECTTYPESTATIC(Navigable);
 
 
 Navigable::Navigable(Context* context) :
 Navigable::Navigable(Context* context) :
@@ -43,8 +45,8 @@ Navigable::~Navigable()
 
 
 void Navigable::RegisterObject(Context* context)
 void Navigable::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Navigable>();
-    
+    context->RegisterComponentFactory<Navigable>(NAVIGATION_CATEGORY);
+
     ACCESSOR_ATTRIBUTE(Navigable, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Navigable, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ATTRIBUTE(Navigable, VAR_BOOL, "Recursive", recursive_, true, AM_DEFAULT);
     ATTRIBUTE(Navigable, VAR_BOOL, "Recursive", recursive_, true, AM_DEFAULT);
 }
 }

+ 3 - 3
Engine/Navigation/Navigable.h

@@ -31,7 +31,7 @@ namespace Urho3D
 class Navigable : public Component
 class Navigable : public Component
 {
 {
     OBJECT(Navigable);
     OBJECT(Navigable);
-    
+
 public:
 public:
     /// Construct.
     /// Construct.
     Navigable(Context* context);
     Navigable(Context* context);
@@ -39,12 +39,12 @@ public:
     virtual ~Navigable();
     virtual ~Navigable();
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
-    
+
     /// Set whether geometry is automatically collected from child nodes. Default true.
     /// Set whether geometry is automatically collected from child nodes. Default true.
     void SetRecursive(bool enable);
     void SetRecursive(bool enable);
     /// Return whether geometry is automatically collected from child nodes.
     /// Return whether geometry is automatically collected from child nodes.
     bool IsRecursive() const { return recursive_; }
     bool IsRecursive() const { return recursive_; }
-    
+
 private:
 private:
     /// Recursive flag.
     /// Recursive flag.
     bool recursive_;
     bool recursive_;

+ 2 - 0
Engine/Navigation/Navigation.cpp

@@ -30,6 +30,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* NAVIGATION_CATEGORY = "Navigation";
+
 void RegisterNavigationLibrary(Context* context)
 void RegisterNavigationLibrary(Context* context)
 {
 {
     Navigable::RegisterObject(context);
     Navigable::RegisterObject(context);

+ 2 - 0
Engine/Navigation/Navigation.h

@@ -25,6 +25,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* NAVIGATION_CATEGORY;
+
 class Context;
 class Context;
 
 
 /// Register Navigation library objects.
 /// Register Navigation library objects.

+ 3 - 1
Engine/Navigation/NavigationMesh.cpp

@@ -49,6 +49,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* NAVIGATION_CATEGORY;
+
 static const int DEFAULT_TILE_SIZE = 128;
 static const int DEFAULT_TILE_SIZE = 128;
 static const float DEFAULT_CELL_SIZE = 0.3f;
 static const float DEFAULT_CELL_SIZE = 0.3f;
 static const float DEFAULT_CELL_HEIGHT = 0.2f;
 static const float DEFAULT_CELL_HEIGHT = 0.2f;
@@ -180,7 +182,7 @@ NavigationMesh::~NavigationMesh()
 
 
 void NavigationMesh::RegisterObject(Context* context)
 void NavigationMesh::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<NavigationMesh>();
+    context->RegisterComponentFactory<NavigationMesh>(NAVIGATION_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(NavigationMesh, VAR_INT, "Tile Size", GetTileSize, SetTileSize, int, DEFAULT_TILE_SIZE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(NavigationMesh, VAR_INT, "Tile Size", GetTileSize, SetTileSize, int, DEFAULT_TILE_SIZE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(NavigationMesh, VAR_FLOAT, "Cell Size", GetCellSize, SetCellSize, float, DEFAULT_CELL_SIZE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(NavigationMesh, VAR_FLOAT, "Cell Size", GetCellSize, SetCellSize, float, DEFAULT_CELL_SIZE, AM_DEFAULT);

+ 3 - 1
Engine/Navigation/OffMeshConnection.cpp

@@ -31,6 +31,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* NAVIGATION_CATEGORY;
+
 OBJECTTYPESTATIC(OffMeshConnection);
 OBJECTTYPESTATIC(OffMeshConnection);
 
 
 static const float DEFAULT_RADIUS = 1.0f;
 static const float DEFAULT_RADIUS = 1.0f;
@@ -50,7 +52,7 @@ OffMeshConnection::~OffMeshConnection()
 
 
 void OffMeshConnection::RegisterObject(Context* context)
 void OffMeshConnection::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<OffMeshConnection>();
+    context->RegisterComponentFactory<OffMeshConnection>(NAVIGATION_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(OffMeshConnection, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(OffMeshConnection, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ATTRIBUTE(OffMeshConnection, VAR_INT, "Endpoint NodeID", endPointID_, 0, AM_DEFAULT | AM_NODEID);
     ATTRIBUTE(OffMeshConnection, VAR_INT, "Endpoint NodeID", endPointID_, 0, AM_DEFAULT | AM_NODEID);

+ 3 - 1
Engine/Network/NetworkPriority.cpp

@@ -29,6 +29,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* NETWORK_CATEGORY = "Network";
+
 static const float DEFAULT_BASE_PRIORITY = 100.0f;
 static const float DEFAULT_BASE_PRIORITY = 100.0f;
 static const float DEFAULT_DISTANCE_FACTOR = 0.0f;
 static const float DEFAULT_DISTANCE_FACTOR = 0.0f;
 static const float DEFAULT_MIN_PRIORITY = 0.0f;
 static const float DEFAULT_MIN_PRIORITY = 0.0f;
@@ -51,7 +53,7 @@ NetworkPriority::~NetworkPriority()
 
 
 void NetworkPriority::RegisterObject(Context* context)
 void NetworkPriority::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<NetworkPriority>();
+    context->RegisterComponentFactory<NetworkPriority>(NETWORK_CATEGORY);
     
     
     ATTRIBUTE(NetworkPriority, VAR_FLOAT, "Base Priority", basePriority_, DEFAULT_BASE_PRIORITY, AM_DEFAULT);
     ATTRIBUTE(NetworkPriority, VAR_FLOAT, "Base Priority", basePriority_, DEFAULT_BASE_PRIORITY, AM_DEFAULT);
     ATTRIBUTE(NetworkPriority, VAR_FLOAT, "Distance Factor", distanceFactor_, DEFAULT_DISTANCE_FACTOR, AM_DEFAULT);
     ATTRIBUTE(NetworkPriority, VAR_FLOAT, "Distance Factor", distanceFactor_, DEFAULT_DISTANCE_FACTOR, AM_DEFAULT);

+ 1 - 1
Engine/Physics/CollisionShape.cpp

@@ -271,7 +271,7 @@ CollisionShape::~CollisionShape()
 
 
 void CollisionShape::RegisterObject(Context* context)
 void CollisionShape::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<CollisionShape>();
+    context->RegisterComponentFactory<CollisionShape>(PHYSICS_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ENUM_ATTRIBUTE(CollisionShape, "Shape Type", shapeType_, typeNames, SHAPE_BOX, AM_DEFAULT);
     ENUM_ATTRIBUTE(CollisionShape, "Shape Type", shapeType_, typeNames, SHAPE_BOX, AM_DEFAULT);

+ 1 - 1
Engine/Physics/Constraint.cpp

@@ -80,7 +80,7 @@ Constraint::~Constraint()
 
 
 void Constraint::RegisterObject(Context* context)
 void Constraint::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Constraint>();
+    context->RegisterComponentFactory<Constraint>(PHYSICS_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(Constraint, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Constraint, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ENUM_ATTRIBUTE(Constraint, "Constraint Type", constraintType_, typeNames, CONSTRAINT_POINT, AM_DEFAULT);
     ENUM_ATTRIBUTE(Constraint, "Constraint Type", constraintType_, typeNames, CONSTRAINT_POINT, AM_DEFAULT);

+ 86 - 84
Engine/Physics/PhysicsWorld.cpp

@@ -47,6 +47,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* PHYSICS_CATEGORY = "Physics";
+
 static const int DEFAULT_FPS = 60;
 static const int DEFAULT_FPS = 60;
 static const Vector3 DEFAULT_GRAVITY = Vector3(0.0f, -9.81f, 0.0f);
 static const Vector3 DEFAULT_GRAVITY = Vector3(0.0f, -9.81f, 0.0f);
 
 
@@ -72,7 +74,7 @@ struct PhysicsQueryCallback : public btCollisionWorld::ContactResultCallback
     PhysicsQueryCallback(PODVector<RigidBody*>& result) : result_(result)
     PhysicsQueryCallback(PODVector<RigidBody*>& result) : result_(result)
     {
     {
     }
     }
-    
+
     /// Add a contact result.
     /// Add a contact result.
     virtual btScalar addSingleResult(btManifoldPoint &, const btCollisionObject *colObj0, int, int, const btCollisionObject *colObj1, int, int)
     virtual btScalar addSingleResult(btManifoldPoint &, const btCollisionObject *colObj0, int, int, const btCollisionObject *colObj1, int, int)
     {
     {
@@ -84,7 +86,7 @@ struct PhysicsQueryCallback : public btCollisionWorld::ContactResultCallback
             result_.Push(body);
             result_.Push(body);
         return 0.0f;
         return 0.0f;
     }
     }
-    
+
     /// Found rigid bodies.
     /// Found rigid bodies.
     PODVector<RigidBody*>& result_;
     PODVector<RigidBody*>& result_;
 };
 };
@@ -111,7 +113,7 @@ PhysicsWorld::PhysicsWorld(Context* context) :
     broadphase_ = new btDbvtBroadphase();
     broadphase_ = new btDbvtBroadphase();
     solver_ = new btSequentialImpulseConstraintSolver();
     solver_ = new btSequentialImpulseConstraintSolver();
     world_ = new btDiscreteDynamicsWorld(collisionDispatcher_, broadphase_, solver_, collisionConfiguration_);
     world_ = new btDiscreteDynamicsWorld(collisionDispatcher_, broadphase_, solver_, collisionConfiguration_);
-    
+
     world_->setGravity(ToBtVector3(DEFAULT_GRAVITY));
     world_->setGravity(ToBtVector3(DEFAULT_GRAVITY));
     world_->getDispatchInfo().m_useContinuous = true;
     world_->getDispatchInfo().m_useContinuous = true;
     world_->setDebugDrawer(this);
     world_->setDebugDrawer(this);
@@ -126,34 +128,34 @@ PhysicsWorld::~PhysicsWorld()
         // Force all remaining constraints, rigid bodies and collision shapes to release themselves
         // Force all remaining constraints, rigid bodies and collision shapes to release themselves
         for (PODVector<Constraint*>::Iterator i = constraints_.Begin(); i != constraints_.End(); ++i)
         for (PODVector<Constraint*>::Iterator i = constraints_.Begin(); i != constraints_.End(); ++i)
             (*i)->ReleaseConstraint();
             (*i)->ReleaseConstraint();
-        
+
         for (PODVector<RigidBody*>::Iterator i = rigidBodies_.Begin(); i != rigidBodies_.End(); ++i)
         for (PODVector<RigidBody*>::Iterator i = rigidBodies_.Begin(); i != rigidBodies_.End(); ++i)
             (*i)->ReleaseBody();
             (*i)->ReleaseBody();
-        
+
         for (PODVector<CollisionShape*>::Iterator i = collisionShapes_.Begin(); i != collisionShapes_.End(); ++i)
         for (PODVector<CollisionShape*>::Iterator i = collisionShapes_.Begin(); i != collisionShapes_.End(); ++i)
             (*i)->ReleaseShape();
             (*i)->ReleaseShape();
     }
     }
-    
+
     delete world_;
     delete world_;
     world_ = 0;
     world_ = 0;
-    
+
     delete solver_;
     delete solver_;
     solver_ = 0;
     solver_ = 0;
-    
+
     delete broadphase_;
     delete broadphase_;
     broadphase_ = 0;
     broadphase_ = 0;
-    
+
     delete collisionDispatcher_;
     delete collisionDispatcher_;
     collisionDispatcher_ = 0;
     collisionDispatcher_ = 0;
-    
+
     delete collisionConfiguration_;
     delete collisionConfiguration_;
     collisionConfiguration_ = 0;
     collisionConfiguration_ = 0;
 }
 }
 
 
 void PhysicsWorld::RegisterObject(Context* context)
 void PhysicsWorld::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<PhysicsWorld>();
-    
+    context->RegisterComponentFactory<PhysicsWorld>(PHYSICS_CATEGORY);
+
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_VECTOR3, "Gravity", GetGravity, SetGravity, Vector3, DEFAULT_GRAVITY, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_VECTOR3, "Gravity", GetGravity, SetGravity, Vector3, DEFAULT_GRAVITY, AM_DEFAULT);
     ATTRIBUTE(PhysicsWorld, VAR_INT, "Physics FPS", fps_, DEFAULT_FPS, AM_DEFAULT);
     ATTRIBUTE(PhysicsWorld, VAR_INT, "Physics FPS", fps_, DEFAULT_FPS, AM_DEFAULT);
     ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Net Max Angular Vel.", maxNetworkAngularVelocity_, DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY, AM_DEFAULT);
     ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Net Max Angular Vel.", maxNetworkAngularVelocity_, DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY, AM_DEFAULT);
@@ -179,7 +181,7 @@ void PhysicsWorld::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
     if (debug)
     if (debug)
     {
     {
         PROFILE(PhysicsDrawDebug);
         PROFILE(PhysicsDrawDebug);
-        
+
         debugRenderer_ = debug;
         debugRenderer_ = debug;
         debugDepthTest_ = depthTest;
         debugDepthTest_ = depthTest;
         world_->debugDrawWorld();
         world_->debugDrawWorld();
@@ -195,10 +197,10 @@ void PhysicsWorld::reportErrorWarning(const char* warningString)
 void PhysicsWorld::Update(float timeStep)
 void PhysicsWorld::Update(float timeStep)
 {
 {
     PROFILE(UpdatePhysics);
     PROFILE(UpdatePhysics);
-    
+
     float internalTimeStep = 1.0f / fps_;
     float internalTimeStep = 1.0f / fps_;
     delayedWorldTransforms_.Clear();
     delayedWorldTransforms_.Clear();
-    
+
     if (interpolation_)
     if (interpolation_)
     {
     {
         int maxSubSteps = (int)(timeStep * fps_) + 1;
         int maxSubSteps = (int)(timeStep * fps_) + 1;
@@ -213,7 +215,7 @@ void PhysicsWorld::Update(float timeStep)
             timeAcc_ -= internalTimeStep;
             timeAcc_ -= internalTimeStep;
         }
         }
     }
     }
-    
+
     // Apply delayed (parented) world transforms now
     // Apply delayed (parented) world transforms now
     while (!delayedWorldTransforms_.Empty())
     while (!delayedWorldTransforms_.Empty())
     {
     {
@@ -221,7 +223,7 @@ void PhysicsWorld::Update(float timeStep)
             i != delayedWorldTransforms_.End(); ++i)
             i != delayedWorldTransforms_.End(); ++i)
         {
         {
             const DelayedWorldTransform& transform = i->second_;
             const DelayedWorldTransform& transform = i->second_;
-            
+
             // If parent's transform has already been assigned, can proceed
             // If parent's transform has already been assigned, can proceed
             if (!delayedWorldTransforms_.Contains(transform.parentRigidBody_))
             if (!delayedWorldTransforms_.Contains(transform.parentRigidBody_))
             {
             {
@@ -260,14 +262,14 @@ void PhysicsWorld::SetMaxNetworkAngularVelocity(float velocity)
 void PhysicsWorld::Raycast(PODVector<PhysicsRaycastResult>& result, const Ray& ray, float maxDistance, unsigned collisionMask)
 void PhysicsWorld::Raycast(PODVector<PhysicsRaycastResult>& result, const Ray& ray, float maxDistance, unsigned collisionMask)
 {
 {
     PROFILE(PhysicsRaycast);
     PROFILE(PhysicsRaycast);
-    
+
     btCollisionWorld::AllHitsRayResultCallback rayCallback(ToBtVector3(ray.origin_), ToBtVector3(ray.origin_ +
     btCollisionWorld::AllHitsRayResultCallback rayCallback(ToBtVector3(ray.origin_), ToBtVector3(ray.origin_ +
         maxDistance * ray.direction_));
         maxDistance * ray.direction_));
     rayCallback.m_collisionFilterGroup = (short)0xffff;
     rayCallback.m_collisionFilterGroup = (short)0xffff;
     rayCallback.m_collisionFilterMask = collisionMask;
     rayCallback.m_collisionFilterMask = collisionMask;
-    
+
     world_->rayTest(rayCallback.m_rayFromWorld, rayCallback.m_rayToWorld, rayCallback);
     world_->rayTest(rayCallback.m_rayFromWorld, rayCallback.m_rayToWorld, rayCallback);
-    
+
     for (int i = 0; i < rayCallback.m_collisionObjects.size(); ++i)
     for (int i = 0; i < rayCallback.m_collisionObjects.size(); ++i)
     {
     {
         PhysicsRaycastResult newResult;
         PhysicsRaycastResult newResult;
@@ -277,21 +279,21 @@ void PhysicsWorld::Raycast(PODVector<PhysicsRaycastResult>& result, const Ray& r
         newResult.distance_ = (newResult.position_ - ray.origin_).Length();
         newResult.distance_ = (newResult.position_ - ray.origin_).Length();
         result.Push(newResult);
         result.Push(newResult);
     }
     }
-    
+
     Sort(result.Begin(), result.End(), CompareRaycastResults);
     Sort(result.Begin(), result.End(), CompareRaycastResults);
 }
 }
 
 
 void PhysicsWorld::RaycastSingle(PhysicsRaycastResult& result, const Ray& ray, float maxDistance, unsigned collisionMask)
 void PhysicsWorld::RaycastSingle(PhysicsRaycastResult& result, const Ray& ray, float maxDistance, unsigned collisionMask)
 {
 {
     PROFILE(PhysicsRaycastSingle);
     PROFILE(PhysicsRaycastSingle);
-    
+
     btCollisionWorld::ClosestRayResultCallback rayCallback(ToBtVector3(ray.origin_), ToBtVector3(ray.origin_ +
     btCollisionWorld::ClosestRayResultCallback rayCallback(ToBtVector3(ray.origin_), ToBtVector3(ray.origin_ +
         maxDistance * ray.direction_));
         maxDistance * ray.direction_));
     rayCallback.m_collisionFilterGroup = (short)0xffff;
     rayCallback.m_collisionFilterGroup = (short)0xffff;
     rayCallback.m_collisionFilterMask = collisionMask;
     rayCallback.m_collisionFilterMask = collisionMask;
-    
+
     world_->rayTest(rayCallback.m_rayFromWorld, rayCallback.m_rayToWorld, rayCallback);
     world_->rayTest(rayCallback.m_rayFromWorld, rayCallback.m_rayToWorld, rayCallback);
-    
+
     if (rayCallback.hasHit())
     if (rayCallback.hasHit())
     {
     {
         result.body_ = static_cast<RigidBody*>(rayCallback.m_collisionObject->getUserPointer());
         result.body_ = static_cast<RigidBody*>(rayCallback.m_collisionObject->getUserPointer());
@@ -311,17 +313,17 @@ void PhysicsWorld::RaycastSingle(PhysicsRaycastResult& result, const Ray& ray, f
 void PhysicsWorld::SphereCast(PhysicsRaycastResult& result, const Ray& ray, float radius, float maxDistance, unsigned collisionMask)
 void PhysicsWorld::SphereCast(PhysicsRaycastResult& result, const Ray& ray, float radius, float maxDistance, unsigned collisionMask)
 {
 {
     PROFILE(PhysicsSphereCast);
     PROFILE(PhysicsSphereCast);
-    
+
     btSphereShape shape(radius);
     btSphereShape shape(radius);
-    
+
     btCollisionWorld::ClosestConvexResultCallback convexCallback(ToBtVector3(ray.origin_), ToBtVector3(ray.origin_ +
     btCollisionWorld::ClosestConvexResultCallback convexCallback(ToBtVector3(ray.origin_), ToBtVector3(ray.origin_ +
         maxDistance * ray.direction_));
         maxDistance * ray.direction_));
     convexCallback.m_collisionFilterGroup = (short)0xffff;
     convexCallback.m_collisionFilterGroup = (short)0xffff;
     convexCallback.m_collisionFilterMask = collisionMask;
     convexCallback.m_collisionFilterMask = collisionMask;
-    
+
     world_->convexSweepTest(&shape, btTransform(btQuaternion::getIdentity(), convexCallback.m_convexFromWorld),
     world_->convexSweepTest(&shape, btTransform(btQuaternion::getIdentity(), convexCallback.m_convexFromWorld),
         btTransform(btQuaternion::getIdentity(), convexCallback.m_convexToWorld), convexCallback);
         btTransform(btQuaternion::getIdentity(), convexCallback.m_convexToWorld), convexCallback);
-    
+
     if (convexCallback.hasHit())
     if (convexCallback.hasHit())
     {
     {
         result.body_ = static_cast<RigidBody*>(convexCallback.m_hitCollisionObject->getUserPointer());
         result.body_ = static_cast<RigidBody*>(convexCallback.m_hitCollisionObject->getUserPointer());
@@ -341,19 +343,19 @@ void PhysicsWorld::SphereCast(PhysicsRaycastResult& result, const Ray& ray, floa
 void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const Sphere& sphere, unsigned collisionMask)
 void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const Sphere& sphere, unsigned collisionMask)
 {
 {
     PROFILE(PhysicsSphereQuery);
     PROFILE(PhysicsSphereQuery);
-    
+
     result.Clear();
     result.Clear();
-    
+
     btSphereShape sphereShape(sphere.radius_);
     btSphereShape sphereShape(sphere.radius_);
     btRigidBody* tempRigidBody = new btRigidBody(1.0f, 0, &sphereShape);
     btRigidBody* tempRigidBody = new btRigidBody(1.0f, 0, &sphereShape);
     tempRigidBody->setWorldTransform(btTransform(btQuaternion::getIdentity(), ToBtVector3(sphere.center_)));
     tempRigidBody->setWorldTransform(btTransform(btQuaternion::getIdentity(), ToBtVector3(sphere.center_)));
     // Need to activate the temporary rigid body to get reliable results from static, sleeping objects
     // Need to activate the temporary rigid body to get reliable results from static, sleeping objects
     tempRigidBody->activate();
     tempRigidBody->activate();
     world_->addRigidBody(tempRigidBody, (short)0xffff, (short)collisionMask);
     world_->addRigidBody(tempRigidBody, (short)0xffff, (short)collisionMask);
-    
+
     PhysicsQueryCallback callback(result);
     PhysicsQueryCallback callback(result);
     world_->contactTest(tempRigidBody, callback);
     world_->contactTest(tempRigidBody, callback);
-    
+
     world_->removeRigidBody(tempRigidBody);
     world_->removeRigidBody(tempRigidBody);
     delete tempRigidBody;
     delete tempRigidBody;
 }
 }
@@ -361,18 +363,18 @@ void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const Sphere& s
 void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const BoundingBox& box, unsigned collisionMask)
 void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const BoundingBox& box, unsigned collisionMask)
 {
 {
     PROFILE(PhysicsBoxQuery);
     PROFILE(PhysicsBoxQuery);
-    
+
     result.Clear();
     result.Clear();
-    
+
     btBoxShape boxShape(ToBtVector3(box.HalfSize()));
     btBoxShape boxShape(ToBtVector3(box.HalfSize()));
     btRigidBody* tempRigidBody = new btRigidBody(1.0f, 0, &boxShape);
     btRigidBody* tempRigidBody = new btRigidBody(1.0f, 0, &boxShape);
     tempRigidBody->setWorldTransform(btTransform(btQuaternion::getIdentity(), ToBtVector3(box.Center())));
     tempRigidBody->setWorldTransform(btTransform(btQuaternion::getIdentity(), ToBtVector3(box.Center())));
     tempRigidBody->activate();
     tempRigidBody->activate();
     world_->addRigidBody(tempRigidBody, (short)0xffff, (short)collisionMask);
     world_->addRigidBody(tempRigidBody, (short)0xffff, (short)collisionMask);
-    
+
     PhysicsQueryCallback callback(result);
     PhysicsQueryCallback callback(result);
     world_->contactTest(tempRigidBody, callback);
     world_->contactTest(tempRigidBody, callback);
-    
+
     world_->removeRigidBody(tempRigidBody);
     world_->removeRigidBody(tempRigidBody);
     delete tempRigidBody;
     delete tempRigidBody;
 }
 }
@@ -380,9 +382,9 @@ void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const BoundingB
 void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const RigidBody* body)
 void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const RigidBody* body)
 {
 {
     PROFILE(GetCollidingBodies);
     PROFILE(GetCollidingBodies);
-    
+
     result.Clear();
     result.Clear();
-    
+
     for (HashMap<Pair<WeakPtr<RigidBody>, WeakPtr<RigidBody> >, btPersistentManifold*>::Iterator i = currentCollisions_.Begin();
     for (HashMap<Pair<WeakPtr<RigidBody>, WeakPtr<RigidBody> >, btPersistentManifold*>::Iterator i = currentCollisions_.Begin();
         i != currentCollisions_.End(); ++i)
         i != currentCollisions_.End(); ++i)
     {
     {
@@ -474,7 +476,7 @@ void PhysicsWorld::OnNodeSet(Node* node)
 void PhysicsWorld::HandleSceneSubsystemUpdate(StringHash eventType, VariantMap& eventData)
 void PhysicsWorld::HandleSceneSubsystemUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
     using namespace SceneSubsystemUpdate;
     using namespace SceneSubsystemUpdate;
-    
+
     Update(eventData[P_TIMESTEP].GetFloat());
     Update(eventData[P_TIMESTEP].GetFloat());
 }
 }
 
 
@@ -482,12 +484,12 @@ void PhysicsWorld::PreStep(float timeStep)
 {
 {
     // Send pre-step event
     // Send pre-step event
     using namespace PhysicsPreStep;
     using namespace PhysicsPreStep;
-    
+
     VariantMap eventData;
     VariantMap eventData;
     eventData[P_WORLD] = (void*)this;
     eventData[P_WORLD] = (void*)this;
     eventData[P_TIMESTEP] = timeStep;
     eventData[P_TIMESTEP] = timeStep;
     SendEvent(E_PHYSICSPRESTEP, eventData);
     SendEvent(E_PHYSICSPRESTEP, eventData);
-    
+
     // Start profiling block for the actual simulation step
     // Start profiling block for the actual simulation step
 #ifdef ENABLE_PROFILING
 #ifdef ENABLE_PROFILING
     Profiler* profiler = GetSubsystem<Profiler>();
     Profiler* profiler = GetSubsystem<Profiler>();
@@ -503,12 +505,12 @@ void PhysicsWorld::PostStep(float timeStep)
     if (profiler)
     if (profiler)
         profiler->EndBlock();
         profiler->EndBlock();
 #endif
 #endif
-    
+
     SendCollisionEvents();
     SendCollisionEvents();
-    
+
     // Send post-step event
     // Send post-step event
     using namespace PhysicsPreStep;
     using namespace PhysicsPreStep;
-    
+
     VariantMap eventData;
     VariantMap eventData;
     eventData[P_WORLD] = (void*)this;
     eventData[P_WORLD] = (void*)this;
     eventData[P_TIMESTEP] = timeStep;
     eventData[P_TIMESTEP] = timeStep;
@@ -518,18 +520,18 @@ void PhysicsWorld::PostStep(float timeStep)
 void PhysicsWorld::SendCollisionEvents()
 void PhysicsWorld::SendCollisionEvents()
 {
 {
     PROFILE(SendCollisionEvents);
     PROFILE(SendCollisionEvents);
-    
+
     currentCollisions_.Clear();
     currentCollisions_.Clear();
     int numManifolds = collisionDispatcher_->getNumManifolds();
     int numManifolds = collisionDispatcher_->getNumManifolds();
-    
+
     if (numManifolds)
     if (numManifolds)
     {
     {
         VariantMap physicsCollisionData;
         VariantMap physicsCollisionData;
         VariantMap nodeCollisionData;
         VariantMap nodeCollisionData;
         VectorBuffer contacts;
         VectorBuffer contacts;
-        
+
         physicsCollisionData[PhysicsCollision::P_WORLD] = (void*)this;
         physicsCollisionData[PhysicsCollision::P_WORLD] = (void*)this;
-        
+
         for (int i = 0; i < numManifolds; ++i)
         for (int i = 0; i < numManifolds; ++i)
         {
         {
             btPersistentManifold* contactManifold = collisionDispatcher_->getManifoldByIndexInternal(i);
             btPersistentManifold* contactManifold = collisionDispatcher_->getManifoldByIndexInternal(i);
@@ -537,16 +539,16 @@ void PhysicsWorld::SendCollisionEvents()
             // First check that there are actual contacts, as the manifold exists also when objects are close but not touching
             // First check that there are actual contacts, as the manifold exists also when objects are close but not touching
             if (!numContacts)
             if (!numContacts)
                 continue;
                 continue;
-            
+
             btCollisionObject* objectA = static_cast<btCollisionObject*>(contactManifold->getBody0());
             btCollisionObject* objectA = static_cast<btCollisionObject*>(contactManifold->getBody0());
             btCollisionObject* objectB = static_cast<btCollisionObject*>(contactManifold->getBody1());
             btCollisionObject* objectB = static_cast<btCollisionObject*>(contactManifold->getBody1());
-            
+
             RigidBody* bodyA = static_cast<RigidBody*>(objectA->getUserPointer());
             RigidBody* bodyA = static_cast<RigidBody*>(objectA->getUserPointer());
             RigidBody* bodyB = static_cast<RigidBody*>(objectB->getUserPointer());
             RigidBody* bodyB = static_cast<RigidBody*>(objectB->getUserPointer());
             // If it's not a rigidbody, maybe a ghost object
             // If it's not a rigidbody, maybe a ghost object
             if (!bodyA || !bodyB)
             if (!bodyA || !bodyB)
                 continue;
                 continue;
-            
+
             // Skip collision event signaling if both objects are static, or if collision event mode does not match
             // Skip collision event signaling if both objects are static, or if collision event mode does not match
             if (bodyA->GetMass() == 0.0f && bodyB->GetMass() == 0.0f)
             if (bodyA->GetMass() == 0.0f && bodyB->GetMass() == 0.0f)
                 continue;
                 continue;
@@ -555,21 +557,21 @@ void PhysicsWorld::SendCollisionEvents()
             if (bodyA->GetCollisionEventMode() == COLLISION_ACTIVE && bodyB->GetCollisionEventMode() == COLLISION_ACTIVE &&
             if (bodyA->GetCollisionEventMode() == COLLISION_ACTIVE && bodyB->GetCollisionEventMode() == COLLISION_ACTIVE &&
                 !bodyA->IsActive() && !bodyB->IsActive())
                 !bodyA->IsActive() && !bodyB->IsActive())
                 continue;
                 continue;
-            
+
             WeakPtr<RigidBody> bodyWeakA(bodyA);
             WeakPtr<RigidBody> bodyWeakA(bodyA);
             WeakPtr<RigidBody> bodyWeakB(bodyB);
             WeakPtr<RigidBody> bodyWeakB(bodyB);
-            
+
             Pair<WeakPtr<RigidBody>, WeakPtr<RigidBody> > bodyPair;
             Pair<WeakPtr<RigidBody>, WeakPtr<RigidBody> > bodyPair;
             if (bodyA < bodyB)
             if (bodyA < bodyB)
                 bodyPair = MakePair(bodyWeakA, bodyWeakB);
                 bodyPair = MakePair(bodyWeakA, bodyWeakB);
             else
             else
                 bodyPair = MakePair(bodyWeakB, bodyWeakA);
                 bodyPair = MakePair(bodyWeakB, bodyWeakA);
-            
+
             // First only store the collision pair as weak pointers and the manifold pointer, so user code can safely destroy
             // First only store the collision pair as weak pointers and the manifold pointer, so user code can safely destroy
             // objects during collision event handling
             // objects during collision event handling
             currentCollisions_[bodyPair] = contactManifold;
             currentCollisions_[bodyPair] = contactManifold;
         }
         }
-        
+
         for (HashMap<Pair<WeakPtr<RigidBody>, WeakPtr<RigidBody> >, btPersistentManifold*>::Iterator i = currentCollisions_.Begin();
         for (HashMap<Pair<WeakPtr<RigidBody>, WeakPtr<RigidBody> >, btPersistentManifold*>::Iterator i = currentCollisions_.Begin();
             i != currentCollisions_.End(); ++i)
             i != currentCollisions_.End(); ++i)
         {
         {
@@ -577,26 +579,26 @@ void PhysicsWorld::SendCollisionEvents()
             RigidBody* bodyB = i->first_.second_;
             RigidBody* bodyB = i->first_.second_;
             if (!bodyA || !bodyB)
             if (!bodyA || !bodyB)
                 continue;
                 continue;
-            
+
             btPersistentManifold* contactManifold = i->second_;
             btPersistentManifold* contactManifold = i->second_;
             int numContacts = contactManifold->getNumContacts();
             int numContacts = contactManifold->getNumContacts();
-            
+
             Node* nodeA = bodyA->GetNode();
             Node* nodeA = bodyA->GetNode();
             Node* nodeB = bodyB->GetNode();
             Node* nodeB = bodyB->GetNode();
             WeakPtr<Node> nodeWeakA(nodeA);
             WeakPtr<Node> nodeWeakA(nodeA);
             WeakPtr<Node> nodeWeakB(nodeB);
             WeakPtr<Node> nodeWeakB(nodeB);
-            
+
             bool phantom = bodyA->IsPhantom() || bodyB->IsPhantom();
             bool phantom = bodyA->IsPhantom() || bodyB->IsPhantom();
             bool newCollision = !previousCollisions_.Contains(i->first_);
             bool newCollision = !previousCollisions_.Contains(i->first_);
-            
+
             physicsCollisionData[PhysicsCollision::P_NODEA] = (void*)nodeA;
             physicsCollisionData[PhysicsCollision::P_NODEA] = (void*)nodeA;
             physicsCollisionData[PhysicsCollision::P_NODEB] = (void*)nodeB;
             physicsCollisionData[PhysicsCollision::P_NODEB] = (void*)nodeB;
             physicsCollisionData[PhysicsCollision::P_BODYA] = (void*)bodyA;
             physicsCollisionData[PhysicsCollision::P_BODYA] = (void*)bodyA;
             physicsCollisionData[PhysicsCollision::P_BODYB] = (void*)bodyB;
             physicsCollisionData[PhysicsCollision::P_BODYB] = (void*)bodyB;
             physicsCollisionData[PhysicsCollision::P_PHANTOM] = phantom;
             physicsCollisionData[PhysicsCollision::P_PHANTOM] = phantom;
-            
+
             contacts.Clear();
             contacts.Clear();
-            
+
             for (int j = 0; j < numContacts; ++j)
             for (int j = 0; j < numContacts; ++j)
             {
             {
                 btManifoldPoint& point = contactManifold->getContactPoint(j);
                 btManifoldPoint& point = contactManifold->getContactPoint(j);
@@ -605,9 +607,9 @@ void PhysicsWorld::SendCollisionEvents()
                 contacts.WriteFloat(point.m_distance1);
                 contacts.WriteFloat(point.m_distance1);
                 contacts.WriteFloat(point.m_appliedImpulse);
                 contacts.WriteFloat(point.m_appliedImpulse);
             }
             }
-            
+
             physicsCollisionData[PhysicsCollision::P_CONTACTS] = contacts.GetBuffer();
             physicsCollisionData[PhysicsCollision::P_CONTACTS] = contacts.GetBuffer();
-            
+
             // Send separate collision start event if collision is new
             // Send separate collision start event if collision is new
             if (newCollision)
             if (newCollision)
             {
             {
@@ -616,29 +618,29 @@ void PhysicsWorld::SendCollisionEvents()
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                     continue;
                     continue;
             }
             }
-            
+
             // Then send the ongoing collision event
             // Then send the ongoing collision event
             SendEvent(E_PHYSICSCOLLISION, physicsCollisionData);
             SendEvent(E_PHYSICSCOLLISION, physicsCollisionData);
             if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
             if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                 continue;
                 continue;
-            
+
             nodeCollisionData[NodeCollision::P_BODY] = (void*)bodyA;
             nodeCollisionData[NodeCollision::P_BODY] = (void*)bodyA;
             nodeCollisionData[NodeCollision::P_OTHERNODE] = (void*)nodeB;
             nodeCollisionData[NodeCollision::P_OTHERNODE] = (void*)nodeB;
             nodeCollisionData[NodeCollision::P_OTHERBODY] = (void*)bodyB;
             nodeCollisionData[NodeCollision::P_OTHERBODY] = (void*)bodyB;
             nodeCollisionData[NodeCollision::P_PHANTOM] = phantom;
             nodeCollisionData[NodeCollision::P_PHANTOM] = phantom;
             nodeCollisionData[NodeCollision::P_CONTACTS] = contacts.GetBuffer();
             nodeCollisionData[NodeCollision::P_CONTACTS] = contacts.GetBuffer();
-            
+
             if (newCollision)
             if (newCollision)
             {
             {
                 nodeA->SendEvent(E_NODECOLLISIONSTART, nodeCollisionData);
                 nodeA->SendEvent(E_NODECOLLISIONSTART, nodeCollisionData);
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                     continue;
                     continue;
             }
             }
-            
+
             nodeA->SendEvent(E_NODECOLLISION, nodeCollisionData);
             nodeA->SendEvent(E_NODECOLLISION, nodeCollisionData);
             if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
             if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                 continue;
                 continue;
-            
+
             contacts.Clear();
             contacts.Clear();
             for (int j = 0; j < numContacts; ++j)
             for (int j = 0; j < numContacts; ++j)
             {
             {
@@ -648,30 +650,30 @@ void PhysicsWorld::SendCollisionEvents()
                 contacts.WriteFloat(point.m_distance1);
                 contacts.WriteFloat(point.m_distance1);
                 contacts.WriteFloat(point.m_appliedImpulse);
                 contacts.WriteFloat(point.m_appliedImpulse);
             }
             }
-            
+
             nodeCollisionData[NodeCollision::P_BODY] = (void*)bodyB;
             nodeCollisionData[NodeCollision::P_BODY] = (void*)bodyB;
             nodeCollisionData[NodeCollision::P_OTHERNODE] = (void*)nodeA;
             nodeCollisionData[NodeCollision::P_OTHERNODE] = (void*)nodeA;
             nodeCollisionData[NodeCollision::P_OTHERBODY] = (void*)bodyA;
             nodeCollisionData[NodeCollision::P_OTHERBODY] = (void*)bodyA;
             nodeCollisionData[NodeCollision::P_CONTACTS] = contacts.GetBuffer();
             nodeCollisionData[NodeCollision::P_CONTACTS] = contacts.GetBuffer();
-            
+
             if (newCollision)
             if (newCollision)
             {
             {
                 nodeB->SendEvent(E_NODECOLLISIONSTART, nodeCollisionData);
                 nodeB->SendEvent(E_NODECOLLISIONSTART, nodeCollisionData);
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                     continue;
                     continue;
             }
             }
-            
+
             nodeB->SendEvent(E_NODECOLLISION, nodeCollisionData);
             nodeB->SendEvent(E_NODECOLLISION, nodeCollisionData);
         }
         }
     }
     }
-    
+
     // Send collision end events as applicable
     // Send collision end events as applicable
     {
     {
         VariantMap physicsCollisionData;
         VariantMap physicsCollisionData;
         VariantMap nodeCollisionData;
         VariantMap nodeCollisionData;
-        
+
         physicsCollisionData[PhysicsCollisionEnd::P_WORLD] = (void*)this;
         physicsCollisionData[PhysicsCollisionEnd::P_WORLD] = (void*)this;
-        
+
         for (HashMap<Pair<WeakPtr<RigidBody>, WeakPtr<RigidBody> >, btPersistentManifold*>::Iterator i = previousCollisions_.Begin(); i != previousCollisions_.End(); ++i)
         for (HashMap<Pair<WeakPtr<RigidBody>, WeakPtr<RigidBody> >, btPersistentManifold*>::Iterator i = previousCollisions_.Begin(); i != previousCollisions_.End(); ++i)
         {
         {
             if (!currentCollisions_.Contains(i->first_))
             if (!currentCollisions_.Contains(i->first_))
@@ -680,9 +682,9 @@ void PhysicsWorld::SendCollisionEvents()
                 RigidBody* bodyB = i->first_.second_;
                 RigidBody* bodyB = i->first_.second_;
                 if (!bodyA || !bodyB)
                 if (!bodyA || !bodyB)
                     continue;
                     continue;
-                
+
                 bool phantom = bodyA->IsPhantom() || bodyB->IsPhantom();
                 bool phantom = bodyA->IsPhantom() || bodyB->IsPhantom();
-                
+
                 // Skip collision event signaling if both objects are static, or if collision event mode does not match
                 // Skip collision event signaling if both objects are static, or if collision event mode does not match
                 if (bodyA->GetMass() == 0.0f && bodyB->GetMass() == 0.0f)
                 if (bodyA->GetMass() == 0.0f && bodyB->GetMass() == 0.0f)
                     continue;
                     continue;
@@ -691,41 +693,41 @@ void PhysicsWorld::SendCollisionEvents()
                 if (bodyA->GetCollisionEventMode() == COLLISION_ACTIVE && bodyB->GetCollisionEventMode() == COLLISION_ACTIVE &&
                 if (bodyA->GetCollisionEventMode() == COLLISION_ACTIVE && bodyB->GetCollisionEventMode() == COLLISION_ACTIVE &&
                     !bodyA->IsActive() && !bodyB->IsActive())
                     !bodyA->IsActive() && !bodyB->IsActive())
                     continue;
                     continue;
-                
+
                 Node* nodeA = bodyA->GetNode();
                 Node* nodeA = bodyA->GetNode();
                 Node* nodeB = bodyB->GetNode();
                 Node* nodeB = bodyB->GetNode();
                 WeakPtr<Node> nodeWeakA(nodeA);
                 WeakPtr<Node> nodeWeakA(nodeA);
                 WeakPtr<Node> nodeWeakB(nodeB);
                 WeakPtr<Node> nodeWeakB(nodeB);
-                
+
                 physicsCollisionData[PhysicsCollisionEnd::P_BODYA] = (void*)bodyA;
                 physicsCollisionData[PhysicsCollisionEnd::P_BODYA] = (void*)bodyA;
                 physicsCollisionData[PhysicsCollisionEnd::P_BODYB] = (void*)bodyB;
                 physicsCollisionData[PhysicsCollisionEnd::P_BODYB] = (void*)bodyB;
                 physicsCollisionData[PhysicsCollisionEnd::P_NODEA] = (void*)nodeA;
                 physicsCollisionData[PhysicsCollisionEnd::P_NODEA] = (void*)nodeA;
                 physicsCollisionData[PhysicsCollisionEnd::P_NODEB] = (void*)nodeB;
                 physicsCollisionData[PhysicsCollisionEnd::P_NODEB] = (void*)nodeB;
                 physicsCollisionData[PhysicsCollisionEnd::P_PHANTOM] = phantom;
                 physicsCollisionData[PhysicsCollisionEnd::P_PHANTOM] = phantom;
-                
+
                 SendEvent(E_PHYSICSCOLLISIONEND, physicsCollisionData);
                 SendEvent(E_PHYSICSCOLLISIONEND, physicsCollisionData);
                 // Skip rest of processing if either of the nodes or bodies is removed as a response to the event
                 // Skip rest of processing if either of the nodes or bodies is removed as a response to the event
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                     continue;
                     continue;
-                
+
                 nodeCollisionData[NodeCollisionEnd::P_BODY] = (void*)bodyA;
                 nodeCollisionData[NodeCollisionEnd::P_BODY] = (void*)bodyA;
                 nodeCollisionData[NodeCollisionEnd::P_OTHERNODE] = (void*)nodeB;
                 nodeCollisionData[NodeCollisionEnd::P_OTHERNODE] = (void*)nodeB;
                 nodeCollisionData[NodeCollisionEnd::P_OTHERBODY] = (void*)bodyB;
                 nodeCollisionData[NodeCollisionEnd::P_OTHERBODY] = (void*)bodyB;
                 nodeCollisionData[NodeCollisionEnd::P_PHANTOM] = phantom;
                 nodeCollisionData[NodeCollisionEnd::P_PHANTOM] = phantom;
-                
+
                 nodeA->SendEvent(E_NODECOLLISIONEND, nodeCollisionData);
                 nodeA->SendEvent(E_NODECOLLISIONEND, nodeCollisionData);
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                 if (!nodeWeakA || !nodeWeakB || !i->first_.first_ || !i->first_.second_)
                     continue;
                     continue;
-                
+
                 nodeCollisionData[NodeCollisionEnd::P_BODY] = (void*)bodyB;
                 nodeCollisionData[NodeCollisionEnd::P_BODY] = (void*)bodyB;
                 nodeCollisionData[NodeCollisionEnd::P_OTHERNODE] = (void*)nodeA;
                 nodeCollisionData[NodeCollisionEnd::P_OTHERNODE] = (void*)nodeA;
                 nodeCollisionData[NodeCollisionEnd::P_OTHERBODY] = (void*)bodyA;
                 nodeCollisionData[NodeCollisionEnd::P_OTHERBODY] = (void*)bodyA;
-                
+
                 nodeB->SendEvent(E_NODECOLLISIONEND, nodeCollisionData);
                 nodeB->SendEvent(E_NODECOLLISIONEND, nodeCollisionData);
             }
             }
         }
         }
     }
     }
-    
+
     previousCollisions_ = currentCollisions_;
     previousCollisions_ = currentCollisions_;
 }
 }
 
 

+ 12 - 10
Engine/Physics/PhysicsWorld.h

@@ -39,6 +39,8 @@ class btPersistentManifold;
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* PHYSICS_CATEGORY;
+
 class CollisionShape;
 class CollisionShape;
 class Deserializer;
 class Deserializer;
 class Constraint;
 class Constraint;
@@ -58,7 +60,7 @@ struct PhysicsRaycastResult
         body_(0)
         body_(0)
     {
     {
     }
     }
-    
+
     /// Hit position.
     /// Hit position.
     Vector3 position_;
     Vector3 position_;
     /// Hit normal.
     /// Hit normal.
@@ -89,9 +91,9 @@ class PhysicsWorld : public Component, public btIDebugDraw
 {
 {
     friend void InternalPreTickCallback(btDynamicsWorld *world, btScalar timeStep);
     friend void InternalPreTickCallback(btDynamicsWorld *world, btScalar timeStep);
     friend void InternalTickCallback(btDynamicsWorld *world, btScalar timeStep);
     friend void InternalTickCallback(btDynamicsWorld *world, btScalar timeStep);
-    
+
     OBJECT(PhysicsWorld);
     OBJECT(PhysicsWorld);
-    
+
 public:
 public:
     /// Construct.
     /// Construct.
     PhysicsWorld(Context* scontext);
     PhysicsWorld(Context* scontext);
@@ -99,7 +101,7 @@ public:
     virtual ~PhysicsWorld();
     virtual ~PhysicsWorld();
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
-    
+
     /// Check if an AABB is visible for debug drawing.
     /// Check if an AABB is visible for debug drawing.
     virtual bool isVisible(const btVector3& aabbMin, const btVector3& aabbMax);
     virtual bool isVisible(const btVector3& aabbMin, const btVector3& aabbMax);
     /// Draw a physics debug line.
     /// Draw a physics debug line.
@@ -116,7 +118,7 @@ public:
     virtual int getDebugMode() const { return debugMode_; }
     virtual int getDebugMode() const { return debugMode_; }
     /// Visualize the component as debug geometry.
     /// Visualize the component as debug geometry.
     virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
     virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
-    
+
     /// Step the simulation forward.
     /// Step the simulation forward.
     void Update(float timeStep);
     void Update(float timeStep);
     /// Refresh collisions only without updating dynamics.
     /// Refresh collisions only without updating dynamics.
@@ -149,7 +151,7 @@ public:
     int GetFps() const { return fps_; }
     int GetFps() const { return fps_; }
     /// Return maximum angular velocity for network replication.
     /// Return maximum angular velocity for network replication.
     float GetMaxNetworkAngularVelocity() const { return maxNetworkAngularVelocity_; }
     float GetMaxNetworkAngularVelocity() const { return maxNetworkAngularVelocity_; }
-    
+
     /// Add a rigid body to keep track of. Called by RigidBody.
     /// Add a rigid body to keep track of. Called by RigidBody.
     void AddRigidBody(RigidBody* body);
     void AddRigidBody(RigidBody* body);
     /// Remove a rigid body. Called by RigidBody.
     /// Remove a rigid body. Called by RigidBody.
@@ -170,7 +172,7 @@ public:
     void SetDebugRenderer(DebugRenderer* debug);
     void SetDebugRenderer(DebugRenderer* debug);
     /// Set debug geometry depth test mode. Called both by PhysicsWorld itself and physics components.
     /// Set debug geometry depth test mode. Called both by PhysicsWorld itself and physics components.
     void SetDebugDepthTest(bool enable);
     void SetDebugDepthTest(bool enable);
-    
+
     /// Return the Bullet physics world.
     /// Return the Bullet physics world.
     btDiscreteDynamicsWorld* GetWorld() { return world_; }
     btDiscreteDynamicsWorld* GetWorld() { return world_; }
     /// Clean up the geometry cache.
     /// Clean up the geometry cache.
@@ -181,11 +183,11 @@ public:
     void SetApplyingTransforms(bool enable) { applyingTransforms_ = enable; }
     void SetApplyingTransforms(bool enable) { applyingTransforms_ = enable; }
     /// Return whether node dirtying should be disregarded.
     /// Return whether node dirtying should be disregarded.
     bool IsApplyingTransforms() const { return applyingTransforms_; }
     bool IsApplyingTransforms() const { return applyingTransforms_; }
-    
+
 protected:
 protected:
     /// Handle node being assigned.
     /// Handle node being assigned.
     virtual void OnNodeSet(Node* node);
     virtual void OnNodeSet(Node* node);
-    
+
 private:
 private:
     /// Handle the scene subsystem update event, step simulation here.
     /// Handle the scene subsystem update event, step simulation here.
     void HandleSceneSubsystemUpdate(StringHash eventType, VariantMap& eventData);
     void HandleSceneSubsystemUpdate(StringHash eventType, VariantMap& eventData);
@@ -195,7 +197,7 @@ private:
     void PostStep(float timeStep);
     void PostStep(float timeStep);
     /// Send accumulated collision events.
     /// Send accumulated collision events.
     void SendCollisionEvents();
     void SendCollisionEvents();
-    
+
     /// Bullet collision configuration.
     /// Bullet collision configuration.
     btCollisionConfiguration* collisionConfiguration_;
     btCollisionConfiguration* collisionConfiguration_;
     /// Bullet collision dispatcher.
     /// Bullet collision dispatcher.

+ 47 - 47
Engine/Physics/RigidBody.cpp

@@ -49,7 +49,7 @@ static const float DEFAULT_RESTITUTION = 0.0f;
 static const unsigned DEFAULT_COLLISION_LAYER = 0x1;
 static const unsigned DEFAULT_COLLISION_LAYER = 0x1;
 static const unsigned DEFAULT_COLLISION_MASK = M_MAX_UNSIGNED;
 static const unsigned DEFAULT_COLLISION_MASK = M_MAX_UNSIGNED;
 
 
-static const char* collisionEventModeNames[] = 
+static const char* collisionEventModeNames[] =
 {
 {
     "Never",
     "Never",
     "When Active",
     "When Active",
@@ -83,18 +83,18 @@ RigidBody::RigidBody(Context* context) :
 RigidBody::~RigidBody()
 RigidBody::~RigidBody()
 {
 {
     ReleaseBody();
     ReleaseBody();
-    
+
     if (physicsWorld_)
     if (physicsWorld_)
         physicsWorld_->RemoveRigidBody(this);
         physicsWorld_->RemoveRigidBody(this);
-    
+
     delete compoundShape_;
     delete compoundShape_;
     compoundShape_ = 0;
     compoundShape_ = 0;
 }
 }
 
 
 void RigidBody::RegisterObject(Context* context)
 void RigidBody::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<RigidBody>();
-    
+    context->RegisterComponentFactory<RigidBody>(PHYSICS_CATEGORY);
+
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Physics Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Physics Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_QUATERNION, "Physics Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_QUATERNION, "Physics Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE | AM_NOEDIT);
@@ -106,9 +106,9 @@ void RigidBody::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Linear Factor", GetLinearFactor, SetLinearFactor, Vector3, Vector3::ONE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Linear Factor", GetLinearFactor, SetLinearFactor, Vector3, Vector3::ONE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Angular Factor", GetAngularFactor, SetAngularFactor, Vector3, Vector3::ONE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Angular Factor", GetAngularFactor, SetAngularFactor, Vector3, Vector3::ONE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Linear Damping", GetLinearDamping, SetLinearDamping, float, 0.0f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Linear Damping", GetLinearDamping, SetLinearDamping, float, 0.0f, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Damping", GetAngularDamping, SetAngularDamping, float, 0.01f, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Linear Rest Threshold", GetLinearRestThreshold, SetLinearRestThreshold, float, 0.01f, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Rest Threshold", GetAngularRestThreshold, SetAngularRestThreshold, float, 0.01f, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Damping", GetAngularDamping, SetAngularDamping, float, 0.0f, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Linear Rest Threshold", GetLinearRestThreshold, SetLinearRestThreshold, float, 0.8f, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Rest Threshold", GetAngularRestThreshold, SetAngularRestThreshold, float, 1.0f, AM_DEFAULT);
     ATTRIBUTE(RigidBody, VAR_INT, "Collision Layer", collisionLayer_, DEFAULT_COLLISION_LAYER, AM_DEFAULT);
     ATTRIBUTE(RigidBody, VAR_INT, "Collision Layer", collisionLayer_, DEFAULT_COLLISION_LAYER, AM_DEFAULT);
     ATTRIBUTE(RigidBody, VAR_INT, "Collision Mask", collisionMask_, DEFAULT_COLLISION_MASK, AM_DEFAULT);
     ATTRIBUTE(RigidBody, VAR_INT, "Collision Mask", collisionMask_, DEFAULT_COLLISION_MASK, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Contact Threshold", GetContactProcessingThreshold, SetContactProcessingThreshold, float, BT_LARGE_FLOAT, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Contact Threshold", GetContactProcessingThreshold, SetContactProcessingThreshold, float, BT_LARGE_FLOAT, AM_DEFAULT);
@@ -125,7 +125,7 @@ void RigidBody::RegisterObject(Context* context)
 void RigidBody::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 void RigidBody::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
 {
     Component::OnSetAttribute(attr, src);
     Component::OnSetAttribute(attr, src);
-    
+
     // Change of any non-accessor attribute requires the rigid body to be re-added to the physics world
     // Change of any non-accessor attribute requires the rigid body to be re-added to the physics world
     if (!attr.accessor_)
     if (!attr.accessor_)
         readdBody_ = true;
         readdBody_ = true;
@@ -140,7 +140,7 @@ void RigidBody::ApplyAttributes()
 void RigidBody::OnSetEnabled()
 void RigidBody::OnSetEnabled()
 {
 {
     bool enabled = IsEnabledEffective();
     bool enabled = IsEnabledEffective();
-    
+
     if (enabled && !inWorld_)
     if (enabled && !inWorld_)
         AddBodyToWorld();
         AddBodyToWorld();
     else if (!enabled && inWorld_)
     else if (!enabled && inWorld_)
@@ -165,7 +165,7 @@ void RigidBody::setWorldTransform(const btTransform &worldTrans)
     Vector3 newWorldPosition = ToVector3(worldTrans.getOrigin());
     Vector3 newWorldPosition = ToVector3(worldTrans.getOrigin());
     Quaternion newWorldRotation = ToQuaternion(worldTrans.getRotation());
     Quaternion newWorldRotation = ToQuaternion(worldTrans.getRotation());
     RigidBody* parentRigidBody = 0;
     RigidBody* parentRigidBody = 0;
-    
+
     // It is possible that the RigidBody component has been kept alive via a shared pointer,
     // It is possible that the RigidBody component has been kept alive via a shared pointer,
     // while its scene node has already been destroyed
     // while its scene node has already been destroyed
     if (node_)
     if (node_)
@@ -175,7 +175,7 @@ void RigidBody::setWorldTransform(const btTransform &worldTrans)
         Node* parent = node_->GetParent();
         Node* parent = node_->GetParent();
         if (parent && parent != GetScene())
         if (parent && parent != GetScene())
             parentRigidBody = parent->GetComponent<RigidBody>();
             parentRigidBody = parent->GetComponent<RigidBody>();
-        
+
         if (!parentRigidBody)
         if (!parentRigidBody)
             ApplyWorldTransform(newWorldPosition, newWorldRotation);
             ApplyWorldTransform(newWorldPosition, newWorldRotation);
         else
         else
@@ -187,7 +187,7 @@ void RigidBody::setWorldTransform(const btTransform &worldTrans)
             delayed.worldRotation_ = newWorldRotation;
             delayed.worldRotation_ = newWorldRotation;
             physicsWorld_->AddDelayedWorldTransform(delayed);
             physicsWorld_->AddDelayedWorldTransform(delayed);
         }
         }
-        
+
         MarkNetworkUpdate();
         MarkNetworkUpdate();
     }
     }
 }
 }
@@ -198,11 +198,11 @@ void RigidBody::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
     {
     {
         physicsWorld_->SetDebugRenderer(debug);
         physicsWorld_->SetDebugRenderer(debug);
         physicsWorld_->SetDebugDepthTest(depthTest);
         physicsWorld_->SetDebugDepthTest(depthTest);
-        
+
         btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
         btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
-        world->debugDrawObject(body_->getWorldTransform(), compoundShape_, IsActive() ? btVector3(1.0f, 1.0f, 1.0f) : 
+        world->debugDrawObject(body_->getWorldTransform(), compoundShape_, IsActive() ? btVector3(1.0f, 1.0f, 1.0f) :
             btVector3(0.0f, 1.0f, 0.0f));
             btVector3(0.0f, 1.0f, 0.0f));
-        
+
         physicsWorld_->SetDebugRenderer(0);
         physicsWorld_->SetDebugRenderer(0);
     }
     }
 }
 }
@@ -210,7 +210,7 @@ void RigidBody::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void RigidBody::SetMass(float mass)
 void RigidBody::SetMass(float mass)
 {
 {
     mass = Max(mass, 0.0f);
     mass = Max(mass, 0.0f);
-    
+
     if (mass != mass_)
     if (mass != mass_)
     {
     {
         mass_ = mass;
         mass_ = mass;
@@ -225,13 +225,13 @@ void RigidBody::SetPosition(Vector3 position)
     {
     {
         btTransform& worldTrans = body_->getWorldTransform();
         btTransform& worldTrans = body_->getWorldTransform();
         worldTrans.setOrigin(ToBtVector3(position));
         worldTrans.setOrigin(ToBtVector3(position));
-        
+
         // When forcing the physics position, set also interpolated position so that there is no jitter
         // When forcing the physics position, set also interpolated position so that there is no jitter
         btTransform interpTrans = body_->getInterpolationWorldTransform();
         btTransform interpTrans = body_->getInterpolationWorldTransform();
         interpTrans.setOrigin(worldTrans.getOrigin());
         interpTrans.setOrigin(worldTrans.getOrigin());
         body_->setInterpolationWorldTransform(interpTrans);
         body_->setInterpolationWorldTransform(interpTrans);
         body_->updateInertiaTensor();
         body_->updateInertiaTensor();
-        
+
         Activate();
         Activate();
         MarkNetworkUpdate();
         MarkNetworkUpdate();
     }
     }
@@ -243,13 +243,13 @@ void RigidBody::SetRotation(Quaternion rotation)
     {
     {
         btTransform& worldTrans = body_->getWorldTransform();
         btTransform& worldTrans = body_->getWorldTransform();
         worldTrans.setRotation(ToBtQuaternion(rotation));
         worldTrans.setRotation(ToBtQuaternion(rotation));
-        
+
         // When forcing the physics position, set also interpolated position so that there is no jitter
         // When forcing the physics position, set also interpolated position so that there is no jitter
         btTransform interpTrans = body_->getInterpolationWorldTransform();
         btTransform interpTrans = body_->getInterpolationWorldTransform();
         interpTrans.setRotation(worldTrans.getRotation());
         interpTrans.setRotation(worldTrans.getRotation());
         body_->setInterpolationWorldTransform(interpTrans);
         body_->setInterpolationWorldTransform(interpTrans);
         body_->updateInertiaTensor();
         body_->updateInertiaTensor();
-        
+
         Activate();
         Activate();
         MarkNetworkUpdate();
         MarkNetworkUpdate();
     }
     }
@@ -262,14 +262,14 @@ void RigidBody::SetTransform(const Vector3& position, const Quaternion& rotation
         btTransform& worldTrans = body_->getWorldTransform();
         btTransform& worldTrans = body_->getWorldTransform();
         worldTrans.setOrigin(ToBtVector3(position));
         worldTrans.setOrigin(ToBtVector3(position));
         worldTrans.setRotation(ToBtQuaternion(rotation));
         worldTrans.setRotation(ToBtQuaternion(rotation));
-        
+
         // When forcing the physics position, set also interpolated position so that there is no jitter
         // When forcing the physics position, set also interpolated position so that there is no jitter
         btTransform interpTrans = body_->getInterpolationWorldTransform();
         btTransform interpTrans = body_->getInterpolationWorldTransform();
         interpTrans.setOrigin(worldTrans.getOrigin());
         interpTrans.setOrigin(worldTrans.getOrigin());
         interpTrans.setRotation(worldTrans.getRotation());
         interpTrans.setRotation(worldTrans.getRotation());
         body_->setInterpolationWorldTransform(interpTrans);
         body_->setInterpolationWorldTransform(interpTrans);
         body_->updateInertiaTensor();
         body_->updateInertiaTensor();
-        
+
         Activate();
         Activate();
         MarkNetworkUpdate();
         MarkNetworkUpdate();
     }
     }
@@ -680,12 +680,12 @@ void RigidBody::GetCollidingBodies(PODVector<RigidBody*>& result) const
 void RigidBody::ApplyWorldTransform(const Vector3& newWorldPosition, const Quaternion& newWorldRotation)
 void RigidBody::ApplyWorldTransform(const Vector3& newWorldPosition, const Quaternion& newWorldRotation)
 {
 {
     physicsWorld_->SetApplyingTransforms(true);
     physicsWorld_->SetApplyingTransforms(true);
-    
+
     // Apply transform to the SmoothedTransform component instead of node transform if available
     // Apply transform to the SmoothedTransform component instead of node transform if available
     SmoothedTransform* transform = 0;
     SmoothedTransform* transform = 0;
     if (hasSmoothedTransform_)
     if (hasSmoothedTransform_)
         transform = GetComponent<SmoothedTransform>();
         transform = GetComponent<SmoothedTransform>();
-    
+
     if (transform)
     if (transform)
     {
     {
         transform->SetTargetWorldPosition(newWorldPosition);
         transform->SetTargetWorldPosition(newWorldPosition);
@@ -700,7 +700,7 @@ void RigidBody::ApplyWorldTransform(const Vector3& newWorldPosition, const Quate
         lastPosition_ = node_->GetWorldPosition();
         lastPosition_ = node_->GetWorldPosition();
         lastRotation_ = node_->GetWorldRotation();
         lastRotation_ = node_->GetWorldRotation();
     }
     }
-    
+
     physicsWorld_->SetApplyingTransforms(false);
     physicsWorld_->SetApplyingTransforms(false);
 }
 }
 
 
@@ -721,14 +721,14 @@ void RigidBody::UpdateGravity()
     if (physicsWorld_ && body_)
     if (physicsWorld_ && body_)
     {
     {
         btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
         btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
-        
+
         int flags = body_->getFlags();
         int flags = body_->getFlags();
         if (useGravity_ && gravityOverride_ == Vector3::ZERO)
         if (useGravity_ && gravityOverride_ == Vector3::ZERO)
             flags &= ~BT_DISABLE_WORLD_GRAVITY;
             flags &= ~BT_DISABLE_WORLD_GRAVITY;
         else
         else
             flags |= BT_DISABLE_WORLD_GRAVITY;
             flags |= BT_DISABLE_WORLD_GRAVITY;
         body_->setFlags(flags);
         body_->setFlags(flags);
-        
+
         if (useGravity_)
         if (useGravity_)
         {
         {
             // If override vector is zero, use world's gravity
             // If override vector is zero, use world's gravity
@@ -778,9 +778,9 @@ void RigidBody::ReleaseBody()
         PODVector<Constraint*> constraints = constraints_;
         PODVector<Constraint*> constraints = constraints_;
         for (PODVector<Constraint*>::Iterator i = constraints.Begin(); i != constraints.End(); ++i)
         for (PODVector<Constraint*>::Iterator i = constraints.Begin(); i != constraints.End(); ++i)
             (*i)->ReleaseConstraint();
             (*i)->ReleaseConstraint();
-        
+
         RemoveBodyFromWorld();
         RemoveBodyFromWorld();
-        
+
         delete body_;
         delete body_;
         body_ = 0;
         body_ = 0;
     }
     }
@@ -800,11 +800,11 @@ void RigidBody::OnMarkedDirty(Node* node)
             scene->DelayedMarkedDirty(this);
             scene->DelayedMarkedDirty(this);
             return;
             return;
         }
         }
-        
+
         // Check if transform has changed from the last one set in ApplyWorldTransform()
         // Check if transform has changed from the last one set in ApplyWorldTransform()
         Vector3 newPosition = node_->GetWorldPosition();
         Vector3 newPosition = node_->GetWorldPosition();
         Quaternion newRotation = node_->GetWorldRotation();
         Quaternion newRotation = node_->GetWorldRotation();
-        
+
         if (!newPosition.Equals(lastPosition_))
         if (!newPosition.Equals(lastPosition_))
         {
         {
             lastPosition_ = newPosition;
             lastPosition_ = newPosition;
@@ -827,13 +827,13 @@ void RigidBody::OnNodeSet(Node* node)
         {
         {
             if (scene == node)
             if (scene == node)
                 LOGWARNING(GetTypeName() + " should not be created to the root scene node");
                 LOGWARNING(GetTypeName() + " should not be created to the root scene node");
-            
+
             physicsWorld_ = scene->GetComponent<PhysicsWorld>();
             physicsWorld_ = scene->GetComponent<PhysicsWorld>();
             if (physicsWorld_)
             if (physicsWorld_)
                 physicsWorld_->AddRigidBody(this);
                 physicsWorld_->AddRigidBody(this);
             else
             else
                 LOGERROR("No physics world component in scene, can not create rigid body");
                 LOGERROR("No physics world component in scene, can not create rigid body");
-            
+
             AddBodyToWorld();
             AddBodyToWorld();
         }
         }
         node->AddListener(this);
         node->AddListener(this);
@@ -844,14 +844,14 @@ void RigidBody::AddBodyToWorld()
 {
 {
     if (!physicsWorld_)
     if (!physicsWorld_)
         return;
         return;
-    
+
     PROFILE(AddBodyToWorld);
     PROFILE(AddBodyToWorld);
-    
+
     if (mass_ < 0.0f)
     if (mass_ < 0.0f)
         mass_ = 0.0f;
         mass_ = 0.0f;
-    
+
     bool massUpdated = false;
     bool massUpdated = false;
-    
+
     if (body_)
     if (body_)
         RemoveBodyFromWorld();
         RemoveBodyFromWorld();
     else
     else
@@ -860,7 +860,7 @@ void RigidBody::AddBodyToWorld()
         btVector3 localInertia(0.0f, 0.0f, 0.0f);
         btVector3 localInertia(0.0f, 0.0f, 0.0f);
         body_ = new btRigidBody(mass_, this, compoundShape_, localInertia);
         body_ = new btRigidBody(mass_, this, compoundShape_, localInertia);
         body_->setUserPointer(this);
         body_->setUserPointer(this);
-        
+
         // Check for existence of the SmoothedTransform component, which should be created by now in network client mode.
         // Check for existence of the SmoothedTransform component, which should be created by now in network client mode.
         // If it exists, subscribe to its change events
         // If it exists, subscribe to its change events
         SmoothedTransform* transform = GetComponent<SmoothedTransform>();
         SmoothedTransform* transform = GetComponent<SmoothedTransform>();
@@ -870,7 +870,7 @@ void RigidBody::AddBodyToWorld()
             SubscribeToEvent(transform, E_TARGETPOSITION, HANDLER(RigidBody, HandleTargetPosition));
             SubscribeToEvent(transform, E_TARGETPOSITION, HANDLER(RigidBody, HandleTargetPosition));
             SubscribeToEvent(transform, E_TARGETROTATION, HANDLER(RigidBody, HandleTargetRotation));
             SubscribeToEvent(transform, E_TARGETROTATION, HANDLER(RigidBody, HandleTargetRotation));
         }
         }
-        
+
         // Check if CollisionShapes already exist in the node and add them to the compound shape.
         // Check if CollisionShapes already exist in the node and add them to the compound shape.
         // Note: NotifyRigidBody() will cause mass to be updated
         // Note: NotifyRigidBody() will cause mass to be updated
         PODVector<CollisionShape*> shapes;
         PODVector<CollisionShape*> shapes;
@@ -880,7 +880,7 @@ void RigidBody::AddBodyToWorld()
             massUpdated = true;
             massUpdated = true;
             (*i)->NotifyRigidBody();
             (*i)->NotifyRigidBody();
         }
         }
-        
+
         // Check if this node contains Constraint components that were waiting for the rigid body to be created, and signal them
         // Check if this node contains Constraint components that were waiting for the rigid body to be created, and signal them
         // to create themselves now
         // to create themselves now
         PODVector<Constraint*> constraints;
         PODVector<Constraint*> constraints;
@@ -888,12 +888,12 @@ void RigidBody::AddBodyToWorld()
         for (PODVector<Constraint*>::Iterator i = constraints.Begin(); i != constraints.End(); ++i)
         for (PODVector<Constraint*>::Iterator i = constraints.Begin(); i != constraints.End(); ++i)
             (*i)->CreateConstraint();
             (*i)->CreateConstraint();
     }
     }
-    
+
     if (!massUpdated)
     if (!massUpdated)
         UpdateMass();
         UpdateMass();
-    
+
     UpdateGravity();
     UpdateGravity();
-    
+
     int flags = body_->getCollisionFlags();
     int flags = body_->getCollisionFlags();
     if (phantom_)
     if (phantom_)
         flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
         flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
@@ -904,15 +904,15 @@ void RigidBody::AddBodyToWorld()
     else
     else
         flags &= ~btCollisionObject::CF_KINEMATIC_OBJECT;
         flags &= ~btCollisionObject::CF_KINEMATIC_OBJECT;
     body_->setCollisionFlags(flags);
     body_->setCollisionFlags(flags);
-    
+
     if (!IsEnabledEffective())
     if (!IsEnabledEffective())
         return;
         return;
-    
+
     btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
     btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
     world->addRigidBody(body_, collisionLayer_, collisionMask_);
     world->addRigidBody(body_, collisionLayer_, collisionMask_);
     inWorld_ = true;
     inWorld_ = true;
     readdBody_ = false;
     readdBody_ = false;
-    
+
     if (mass_ > 0.0f)
     if (mass_ > 0.0f)
         Activate();
         Activate();
     else
     else

+ 27 - 15
Engine/Scene/Component.cpp

@@ -60,7 +60,7 @@ bool Component::Save(Serializer& dest) const
         return false;
         return false;
     if (!dest.WriteUInt(id_))
     if (!dest.WriteUInt(id_))
         return false;
         return false;
-    
+
     // Write attributes
     // Write attributes
     return Serializable::Save(dest);
     return Serializable::Save(dest);
 }
 }
@@ -72,7 +72,7 @@ bool Component::SaveXML(XMLElement& dest) const
         return false;
         return false;
     if (!dest.SetInt("id", id_))
     if (!dest.SetInt("id", id_))
         return false;
         return false;
-    
+
     // Write attributes
     // Write attributes
     return Serializable::SaveXML(dest);
     return Serializable::SaveXML(dest);
 }
 }
@@ -84,18 +84,18 @@ void Component::SetEnabled(bool enable)
         enabled_ = enable;
         enabled_ = enable;
         OnSetEnabled();
         OnSetEnabled();
         MarkNetworkUpdate();
         MarkNetworkUpdate();
-        
+
         // Send change event for the component
         // Send change event for the component
         Scene* scene = GetScene();
         Scene* scene = GetScene();
         if (scene)
         if (scene)
         {
         {
             using namespace ComponentEnabledChanged;
             using namespace ComponentEnabledChanged;
-            
+
             VariantMap eventData;
             VariantMap eventData;
             eventData[P_SCENE] = (void*)scene;
             eventData[P_SCENE] = (void*)scene;
             eventData[P_NODE] = (void*)node_;
             eventData[P_NODE] = (void*)node_;
             eventData[P_COMPONENT] = (void*)this;
             eventData[P_COMPONENT] = (void*)this;
-            
+
             scene->SendEvent(E_COMPONENTENABLEDCHANGED, eventData);
             scene->SendEvent(E_COMPONENTENABLEDCHANGED, eventData);
         }
         }
     }
     }
@@ -116,7 +116,7 @@ void Component::AddReplicationState(ComponentReplicationState* state)
 {
 {
     if (!networkState_)
     if (!networkState_)
         AllocateNetworkState();
         AllocateNetworkState();
-    
+
     networkState_->replicationStates_.Push(state);
     networkState_->replicationStates_.Push(state);
 }
 }
 
 
@@ -124,40 +124,40 @@ void Component::PrepareNetworkUpdate()
 {
 {
     if (!networkState_)
     if (!networkState_)
         AllocateNetworkState();
         AllocateNetworkState();
-    
+
     const Vector<AttributeInfo>* attributes = networkState_->attributes_;
     const Vector<AttributeInfo>* attributes = networkState_->attributes_;
     if (!attributes)
     if (!attributes)
         return;
         return;
-    
+
     unsigned numAttributes = attributes->Size();
     unsigned numAttributes = attributes->Size();
-    
+
     if (networkState_->currentValues_.Size() != numAttributes)
     if (networkState_->currentValues_.Size() != numAttributes)
     {
     {
         networkState_->currentValues_.Resize(numAttributes);
         networkState_->currentValues_.Resize(numAttributes);
         networkState_->previousValues_.Resize(numAttributes);
         networkState_->previousValues_.Resize(numAttributes);
-        
+
         // Copy the default attribute values to the previous state as a starting point
         // Copy the default attribute values to the previous state as a starting point
         for (unsigned i = 0; i < numAttributes; ++i)
         for (unsigned i = 0; i < numAttributes; ++i)
             networkState_->previousValues_[i] = attributes->At(i).defaultValue_;
             networkState_->previousValues_[i] = attributes->At(i).defaultValue_;
     }
     }
-    
+
     // Check for attribute changes
     // Check for attribute changes
     for (unsigned i = 0; i < numAttributes; ++i)
     for (unsigned i = 0; i < numAttributes; ++i)
     {
     {
         const AttributeInfo& attr = attributes->At(i);
         const AttributeInfo& attr = attributes->At(i);
         OnGetAttribute(attr, networkState_->currentValues_[i]);
         OnGetAttribute(attr, networkState_->currentValues_[i]);
-        
+
         if (networkState_->currentValues_[i] != networkState_->previousValues_[i])
         if (networkState_->currentValues_[i] != networkState_->previousValues_[i])
         {
         {
             networkState_->previousValues_[i] = networkState_->currentValues_[i];
             networkState_->previousValues_[i] = networkState_->currentValues_[i];
-            
+
             // Mark the attribute dirty in all replication states that are tracking this component
             // Mark the attribute dirty in all replication states that are tracking this component
             for (PODVector<ReplicationState*>::Iterator j = networkState_->replicationStates_.Begin(); j !=
             for (PODVector<ReplicationState*>::Iterator j = networkState_->replicationStates_.Begin(); j !=
                 networkState_->replicationStates_.End(); ++j)
                 networkState_->replicationStates_.End(); ++j)
             {
             {
                 ComponentReplicationState* compState = static_cast<ComponentReplicationState*>(*j);
                 ComponentReplicationState* compState = static_cast<ComponentReplicationState*>(*j);
                 compState->dirtyAttributes_.Set(i);
                 compState->dirtyAttributes_.Set(i);
-                
+
                 // Add component's parent node to the dirty set if not added yet
                 // Add component's parent node to the dirty set if not added yet
                 NodeReplicationState* nodeState = compState->nodeState_;
                 NodeReplicationState* nodeState = compState->nodeState_;
                 if (!nodeState->markedDirty_)
                 if (!nodeState->markedDirty_)
@@ -168,7 +168,7 @@ void Component::PrepareNetworkUpdate()
             }
             }
         }
         }
     }
     }
-    
+
     networkUpdate_ = false;
     networkUpdate_ = false;
 }
 }
 
 
@@ -197,6 +197,18 @@ void Component::MarkNetworkUpdate()
     }
     }
 }
 }
 
 
+const String& Component::GetCategory() const
+{
+    const HashMap<String, Vector<ShortStringHash> >& componentCategories = context_->GetComponentCategories();
+    for (HashMap<String, Vector<ShortStringHash> >::ConstIterator i = componentCategories.Begin(); i != componentCategories.End(); ++i)
+    {
+        if (i->second_.Contains(GetType()))
+            return i->first_;
+    }
+
+    return String::EMPTY;
+}
+
 void Component::SetID(unsigned id)
 void Component::SetID(unsigned id)
 {
 {
     id_ = id;
     id_ = id;

+ 3 - 0
Engine/Scene/Component.h

@@ -93,6 +93,9 @@ public:
     /// Mark for attribute check on the next network update.
     /// Mark for attribute check on the next network update.
     void MarkNetworkUpdate();
     void MarkNetworkUpdate();
     
     
+    /// Return component category. Return an empty string if the component category is not registered.
+    const String& GetCategory() const;
+
 protected:
 protected:
     /// Handle scene node being assigned at creation.
     /// Handle scene node being assigned at creation.
     virtual void OnNodeSet(Node* node) {};
     virtual void OnNodeSet(Node* node) {};

+ 3 - 0
Engine/Scene/Scene.cpp

@@ -40,6 +40,9 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* SCENE_CATEGORY = "Scene";
+const char* EFFECT_CATEGORY = "Effect";
+
 static const int ASYNC_LOAD_MIN_FPS = 30;
 static const int ASYNC_LOAD_MIN_FPS = 30;
 static const int ASYNC_LOAD_MAX_MSEC = (int)(1000.0f / ASYNC_LOAD_MIN_FPS);
 static const int ASYNC_LOAD_MAX_MSEC = (int)(1000.0f / ASYNC_LOAD_MIN_FPS);
 static const float DEFAULT_SMOOTHING_CONSTANT = 50.0f;
 static const float DEFAULT_SMOOTHING_CONSTANT = 50.0f;

+ 3 - 0
Engine/Scene/Scene.h

@@ -31,6 +31,9 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* SCENE_CATEGORY;
+extern const char* EFFECT_CATEGORY;
+
 class File;
 class File;
 class PackageFile;
 class PackageFile;
 
 

+ 14 - 12
Engine/Scene/SmoothedTransform.cpp

@@ -31,6 +31,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+static const char* NETWORK_CATEGORY = "Network";
+
 OBJECTTYPESTATIC(SmoothedTransform);
 OBJECTTYPESTATIC(SmoothedTransform);
 
 
 SmoothedTransform::SmoothedTransform(Context* context) :
 SmoothedTransform::SmoothedTransform(Context* context) :
@@ -48,7 +50,7 @@ SmoothedTransform::~SmoothedTransform()
 
 
 void SmoothedTransform::RegisterObject(Context* context)
 void SmoothedTransform::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<SmoothedTransform>();
+    context->RegisterComponentFactory<SmoothedTransform>(NETWORK_CATEGORY);
 }
 }
 
 
 void SmoothedTransform::Update(float constant, float squaredSnapThreshold)
 void SmoothedTransform::Update(float constant, float squaredSnapThreshold)
@@ -57,14 +59,14 @@ void SmoothedTransform::Update(float constant, float squaredSnapThreshold)
     {
     {
         Vector3 position = node_->GetPosition();
         Vector3 position = node_->GetPosition();
         Quaternion rotation = node_->GetRotation();
         Quaternion rotation = node_->GetRotation();
-        
+
         if (smoothingMask_ & SMOOTH_POSITION)
         if (smoothingMask_ & SMOOTH_POSITION)
         {
         {
             // If position snaps, snap everything to the end
             // If position snaps, snap everything to the end
             float delta = (position - targetPosition_).LengthSquared();
             float delta = (position - targetPosition_).LengthSquared();
             if (delta > squaredSnapThreshold)
             if (delta > squaredSnapThreshold)
                 constant = 1.0f;
                 constant = 1.0f;
-            
+
             if (delta < M_EPSILON || constant >= 1.0f)
             if (delta < M_EPSILON || constant >= 1.0f)
             {
             {
                 position = targetPosition_;
                 position = targetPosition_;
@@ -72,10 +74,10 @@ void SmoothedTransform::Update(float constant, float squaredSnapThreshold)
             }
             }
             else
             else
                 position = position.Lerp(targetPosition_, constant);
                 position = position.Lerp(targetPosition_, constant);
-            
+
             node_->SetPosition(position);
             node_->SetPosition(position);
         }
         }
-        
+
         if (smoothingMask_ & SMOOTH_ROTATION)
         if (smoothingMask_ & SMOOTH_ROTATION)
         {
         {
             float delta = (rotation - targetRotation_).LengthSquared();
             float delta = (rotation - targetRotation_).LengthSquared();
@@ -86,11 +88,11 @@ void SmoothedTransform::Update(float constant, float squaredSnapThreshold)
             }
             }
             else
             else
                 rotation = rotation.Slerp(targetRotation_, constant);
                 rotation = rotation.Slerp(targetRotation_, constant);
-            
+
             node_->SetRotation(rotation);
             node_->SetRotation(rotation);
         }
         }
     }
     }
-    
+
     // If smoothing has completed, unsubscribe from the update event
     // If smoothing has completed, unsubscribe from the update event
     if (!smoothingMask_)
     if (!smoothingMask_)
     {
     {
@@ -103,14 +105,14 @@ void SmoothedTransform::SetTargetPosition(const Vector3& position)
 {
 {
     targetPosition_ = position;
     targetPosition_ = position;
     smoothingMask_ |= SMOOTH_POSITION;
     smoothingMask_ |= SMOOTH_POSITION;
-    
+
     // Subscribe to smoothing update if not yet subscribed
     // Subscribe to smoothing update if not yet subscribed
     if (!subscribed_)
     if (!subscribed_)
     {
     {
         SubscribeToEvent(GetScene(), E_UPDATESMOOTHING, HANDLER(SmoothedTransform, HandleUpdateSmoothing));
         SubscribeToEvent(GetScene(), E_UPDATESMOOTHING, HANDLER(SmoothedTransform, HandleUpdateSmoothing));
         subscribed_ = true;
         subscribed_ = true;
     }
     }
-    
+
     SendEvent(E_TARGETPOSITION);
     SendEvent(E_TARGETPOSITION);
 }
 }
 
 
@@ -118,13 +120,13 @@ void SmoothedTransform::SetTargetRotation(const Quaternion& rotation)
 {
 {
     targetRotation_ = rotation;
     targetRotation_ = rotation;
     smoothingMask_ |= SMOOTH_ROTATION;
     smoothingMask_ |= SMOOTH_ROTATION;
-    
+
     if (!subscribed_)
     if (!subscribed_)
     {
     {
         SubscribeToEvent(GetScene(), E_UPDATESMOOTHING, HANDLER(SmoothedTransform, HandleUpdateSmoothing));
         SubscribeToEvent(GetScene(), E_UPDATESMOOTHING, HANDLER(SmoothedTransform, HandleUpdateSmoothing));
         subscribed_ = true;
         subscribed_ = true;
     }
     }
-    
+
     SendEvent(E_TARGETROTATION);
     SendEvent(E_TARGETROTATION);
 }
 }
 
 
@@ -173,7 +175,7 @@ void SmoothedTransform::OnNodeSet(Node* node)
 void SmoothedTransform::HandleUpdateSmoothing(StringHash eventType, VariantMap& eventData)
 void SmoothedTransform::HandleUpdateSmoothing(StringHash eventType, VariantMap& eventData)
 {
 {
     using namespace UpdateSmoothing;
     using namespace UpdateSmoothing;
-    
+
     float constant = eventData[P_CONSTANT].GetFloat();
     float constant = eventData[P_CONSTANT].GetFloat();
     float squaredSnapThreshold = eventData[P_SQUAREDSNAPTHRESHOLD].GetFloat();
     float squaredSnapThreshold = eventData[P_SQUAREDSNAPTHRESHOLD].GetFloat();
     Update(constant, squaredSnapThreshold);
     Update(constant, squaredSnapThreshold);

+ 47 - 45
Engine/Script/Script.cpp

@@ -37,6 +37,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* SCRIPT_CATEGORY = "Script";
+
 /// %Object property info for scripting API dump.
 /// %Object property info for scripting API dump.
 struct PropertyInfo
 struct PropertyInfo
 {
 {
@@ -47,7 +49,7 @@ struct PropertyInfo
         indexed_(false)
         indexed_(false)
     {
     {
     }
     }
-    
+
     /// Property name.
     /// Property name.
     String name_;
     String name_;
     /// Property data type.
     /// Property data type.
@@ -96,7 +98,7 @@ void ExtractPropertyInfo(const String& functionName, const String& declaration,
             info->indexed_ = true;
             info->indexed_ = true;
             info->type_ += "[]";
             info->type_ += "[]";
         }
         }
-        
+
         // Sanitate the reference operator away
         // Sanitate the reference operator away
         info->type_.Replace("&", "");
         info->type_.Replace("&", "");
     }
     }
@@ -111,7 +113,7 @@ void ExtractPropertyInfo(const String& functionName, const String& declaration,
                 begin = declaration.Find('(');
                 begin = declaration.Find('(');
             else
             else
                 info->indexed_ = true;
                 info->indexed_ = true;
-            
+
             if (begin != String::NPOS)
             if (begin != String::NPOS)
             {
             {
                 ++begin;
                 ++begin;
@@ -144,18 +146,18 @@ Script::Script(Context* context) :
         LOGERROR("Could not create AngelScript engine");
         LOGERROR("Could not create AngelScript engine");
         return;
         return;
     }
     }
-    
+
     scriptEngine_->SetUserData(this);
     scriptEngine_->SetUserData(this);
     scriptEngine_->SetEngineProperty(asEP_USE_CHARACTER_LITERALS, true);
     scriptEngine_->SetEngineProperty(asEP_USE_CHARACTER_LITERALS, true);
     scriptEngine_->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, true);
     scriptEngine_->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, true);
     scriptEngine_->SetEngineProperty(asEP_ALLOW_IMPLICIT_HANDLE_TYPES, true);
     scriptEngine_->SetEngineProperty(asEP_ALLOW_IMPLICIT_HANDLE_TYPES, true);
     scriptEngine_->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, true);
     scriptEngine_->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, true);
     scriptEngine_->SetMessageCallback(asMETHOD(Script, MessageCallback), this, asCALL_THISCALL);
     scriptEngine_->SetMessageCallback(asMETHOD(Script, MessageCallback), this, asCALL_THISCALL);
-    
+
     // Create the context for immediate execution
     // Create the context for immediate execution
     immediateContext_ = scriptEngine_->CreateContext();
     immediateContext_ = scriptEngine_->CreateContext();
     immediateContext_->SetExceptionCallback(asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL);
     immediateContext_->SetExceptionCallback(asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL);
-    
+
     // Register the Array & String types
     // Register the Array & String types
     RegisterArray(scriptEngine_);
     RegisterArray(scriptEngine_);
     RegisterString(scriptEngine_);
     RegisterString(scriptEngine_);
@@ -168,10 +170,10 @@ Script::~Script()
         immediateContext_->Release();
         immediateContext_->Release();
         immediateContext_ = 0;
         immediateContext_ = 0;
     }
     }
-    
+
     for (unsigned i = 0 ; i < scriptFileContexts_.Size(); ++i)
     for (unsigned i = 0 ; i < scriptFileContexts_.Size(); ++i)
         scriptFileContexts_[i]->Release();
         scriptFileContexts_[i]->Release();
-    
+
     if (scriptEngine_)
     if (scriptEngine_)
     {
     {
         scriptEngine_->Release();
         scriptEngine_->Release();
@@ -183,11 +185,11 @@ bool Script::Execute(const String& line)
 {
 {
     // Note: compiling code each time is slow. Not to be used for performance-critical or repeating activity
     // Note: compiling code each time is slow. Not to be used for performance-critical or repeating activity
     PROFILE(ExecuteImmediate);
     PROFILE(ExecuteImmediate);
-    
+
     ClearObjectTypeCache();
     ClearObjectTypeCache();
-    
+
     String wrappedLine = "void f(){\n" + line + ";\n}";
     String wrappedLine = "void f(){\n" + line + ";\n}";
-    
+
     // If no immediate mode script file set, create a dummy module for compiling the line
     // If no immediate mode script file set, create a dummy module for compiling the line
     asIScriptModule* module = 0;
     asIScriptModule* module = 0;
     if (defaultScriptFile_)
     if (defaultScriptFile_)
@@ -196,21 +198,21 @@ bool Script::Execute(const String& line)
         module = scriptEngine_->GetModule("ExecuteImmediate", asGM_CREATE_IF_NOT_EXISTS);
         module = scriptEngine_->GetModule("ExecuteImmediate", asGM_CREATE_IF_NOT_EXISTS);
     if (!module)
     if (!module)
         return false;
         return false;
-    
+
     asIScriptFunction *function = 0;
     asIScriptFunction *function = 0;
     if (module->CompileFunction("", wrappedLine.CString(), -1, 0, &function) < 0)
     if (module->CompileFunction("", wrappedLine.CString(), -1, 0, &function) < 0)
         return false;
         return false;
-    
+
     if (immediateContext_->Prepare(function) < 0)
     if (immediateContext_->Prepare(function) < 0)
     {
     {
         function->Release();
         function->Release();
         return false;
         return false;
     }
     }
-    
+
     bool success = immediateContext_->Execute() >= 0;
     bool success = immediateContext_->Execute() >= 0;
     immediateContext_->Unprepare();
     immediateContext_->Unprepare();
     function->Release();
     function->Release();
-    
+
     return success;
     return success;
 }
 }
 
 
@@ -238,35 +240,35 @@ void Script::DumpAPI()
 {
 {
     // Does not use LOGRAW macro here to ensure the messages are always dumped regarless of ENABLE_LOGGING compiler directive and of Log subsystem availability
     // Does not use LOGRAW macro here to ensure the messages are always dumped regarless of ENABLE_LOGGING compiler directive and of Log subsystem availability
     Log::WriteRaw("namespace Urho3D\n{\n\n/**\n\\page ScriptAPI Scripting API\n\n");
     Log::WriteRaw("namespace Urho3D\n{\n\n/**\n\\page ScriptAPI Scripting API\n\n");
-    
+
     Vector<PropertyInfo> globalPropertyInfos;
     Vector<PropertyInfo> globalPropertyInfos;
     Vector<String> globalFunctions;
     Vector<String> globalFunctions;
-    
+
     unsigned functions = scriptEngine_->GetGlobalFunctionCount();
     unsigned functions = scriptEngine_->GetGlobalFunctionCount();
     for (unsigned i = 0; i < functions; ++i)
     for (unsigned i = 0; i < functions; ++i)
     {
     {
         asIScriptFunction* function = scriptEngine_->GetGlobalFunctionByIndex(i);
         asIScriptFunction* function = scriptEngine_->GetGlobalFunctionByIndex(i);
         String functionName(function->GetName());
         String functionName(function->GetName());
         String declaration(function->GetDeclaration());
         String declaration(function->GetDeclaration());
-        
+
         if (functionName.Contains("set_") || functionName.Contains("get_"))
         if (functionName.Contains("set_") || functionName.Contains("get_"))
             ExtractPropertyInfo(functionName, declaration, globalPropertyInfos);
             ExtractPropertyInfo(functionName, declaration, globalPropertyInfos);
         else
         else
             globalFunctions.Push(declaration);
             globalFunctions.Push(declaration);
     }
     }
-    
+
     Log::WriteRaw("\\section ScriptAPI_GlobalFunctions Global functions\n");
     Log::WriteRaw("\\section ScriptAPI_GlobalFunctions Global functions\n");
-    
+
     for (unsigned i = 0; i < globalFunctions.Size(); ++i)
     for (unsigned i = 0; i < globalFunctions.Size(); ++i)
         OutputAPIRow(globalFunctions[i]);
         OutputAPIRow(globalFunctions[i]);
-    
+
     Log::WriteRaw("\\section ScriptAPI_GlobalProperties Global properties\n");
     Log::WriteRaw("\\section ScriptAPI_GlobalProperties Global properties\n");
-    
+
     for (unsigned i = 0; i < globalPropertyInfos.Size(); ++i)
     for (unsigned i = 0; i < globalPropertyInfos.Size(); ++i)
         OutputAPIRow(globalPropertyInfos[i].type_ + " " + globalPropertyInfos[i].name_, true);
         OutputAPIRow(globalPropertyInfos[i].type_ + " " + globalPropertyInfos[i].name_, true);
-    
+
     Log::WriteRaw("\\section ScriptAPI_GlobalConstants Global constants\n");
     Log::WriteRaw("\\section ScriptAPI_GlobalConstants Global constants\n");
-    
+
     unsigned properties = scriptEngine_->GetGlobalPropertyCount();
     unsigned properties = scriptEngine_->GetGlobalPropertyCount();
     for (unsigned i = 0; i < properties; ++i)
     for (unsigned i = 0; i < properties; ++i)
     {
     {
@@ -275,13 +277,13 @@ void Script::DumpAPI()
         int typeId;
         int typeId;
         scriptEngine_->GetGlobalPropertyByIndex(i, &propertyName, 0, &typeId);
         scriptEngine_->GetGlobalPropertyByIndex(i, &propertyName, 0, &typeId);
         propertyDeclaration = scriptEngine_->GetTypeDeclaration(typeId);
         propertyDeclaration = scriptEngine_->GetTypeDeclaration(typeId);
-        
+
         String type(propertyDeclaration);
         String type(propertyDeclaration);
         OutputAPIRow(type + " " + String(propertyName), true);
         OutputAPIRow(type + " " + String(propertyName), true);
     }
     }
-    
+
     Log::WriteRaw("\\section ScriptAPI_Classes Classes\n");
     Log::WriteRaw("\\section ScriptAPI_Classes Classes\n");
-    
+
     unsigned types = scriptEngine_->GetObjectTypeCount();
     unsigned types = scriptEngine_->GetObjectTypeCount();
     for (unsigned i = 0; i < types; ++i)
     for (unsigned i = 0; i < types; ++i)
     {
     {
@@ -291,9 +293,9 @@ void Script::DumpAPI()
             String typeName(type->GetName());
             String typeName(type->GetName());
             Vector<String> methodDeclarations;
             Vector<String> methodDeclarations;
             Vector<PropertyInfo> propertyInfos;
             Vector<PropertyInfo> propertyInfos;
-            
+
             Log::WriteRaw("\n" + typeName + "\n");
             Log::WriteRaw("\n" + typeName + "\n");
-            
+
             unsigned methods = type->GetMethodCount();
             unsigned methods = type->GetMethodCount();
             for (unsigned j = 0; j < methods; ++j)
             for (unsigned j = 0; j < methods; ++j)
             {
             {
@@ -313,7 +315,7 @@ void Script::DumpAPI()
                     }
                     }
                 }
                 }
             }
             }
-            
+
             // Assume that the same property is never both an accessor property, and a direct one
             // Assume that the same property is never both an accessor property, and a direct one
             unsigned properties = type->GetPropertyCount();
             unsigned properties = type->GetPropertyCount();
             for (unsigned j = 0; j < properties; ++j)
             for (unsigned j = 0; j < properties; ++j)
@@ -321,24 +323,24 @@ void Script::DumpAPI()
                 const char* propertyName;
                 const char* propertyName;
                 const char* propertyDeclaration;
                 const char* propertyDeclaration;
                 int typeId;
                 int typeId;
-                
+
                 type->GetProperty(j, &propertyName, &typeId);
                 type->GetProperty(j, &propertyName, &typeId);
                 propertyDeclaration = scriptEngine_->GetTypeDeclaration(typeId);
                 propertyDeclaration = scriptEngine_->GetTypeDeclaration(typeId);
-                
+
                 PropertyInfo newInfo;
                 PropertyInfo newInfo;
                 newInfo.name_ = String(propertyName);
                 newInfo.name_ = String(propertyName);
                 newInfo.type_ = String(propertyDeclaration);
                 newInfo.type_ = String(propertyDeclaration);
                 newInfo.read_ = newInfo.write_ = true;
                 newInfo.read_ = newInfo.write_ = true;
                 propertyInfos.Push(newInfo);
                 propertyInfos.Push(newInfo);
             }
             }
-            
+
             if (!methodDeclarations.Empty())
             if (!methodDeclarations.Empty())
             {
             {
                 Log::WriteRaw("\nMethods:<br>\n");
                 Log::WriteRaw("\nMethods:<br>\n");
                 for (unsigned j = 0; j < methodDeclarations.Size(); ++j)
                 for (unsigned j = 0; j < methodDeclarations.Size(); ++j)
                     OutputAPIRow(methodDeclarations[j]);
                     OutputAPIRow(methodDeclarations[j]);
             }
             }
-            
+
             if (!propertyInfos.Empty())
             if (!propertyInfos.Empty())
             {
             {
                 Log::WriteRaw("\nProperties:<br>\n");
                 Log::WriteRaw("\nProperties:<br>\n");
@@ -349,15 +351,15 @@ void Script::DumpAPI()
                         remark = " (readonly)";
                         remark = " (readonly)";
                     else if (!propertyInfos[j].read_)
                     else if (!propertyInfos[j].read_)
                         remark = " (writeonly)";
                         remark = " (writeonly)";
-                    
+
                     OutputAPIRow(propertyInfos[j].type_ + " " + propertyInfos[j].name_ + remark);
                     OutputAPIRow(propertyInfos[j].type_ + " " + propertyInfos[j].name_ + remark);
                 }
                 }
             }
             }
-            
+
             Log::WriteRaw("\n");
             Log::WriteRaw("\n");
         }
         }
     }
     }
-    
+
     Log::WriteRaw("*/\n\n}\n");
     Log::WriteRaw("*/\n\n}\n");
 }
 }
 
 
@@ -365,7 +367,7 @@ void Script::MessageCallback(const asSMessageInfo* msg)
 {
 {
     String message;
     String message;
     message.AppendWithFormat("%s:%d,%d %s", msg->section, msg->row, msg->col, msg->message);
     message.AppendWithFormat("%s:%d,%d %s", msg->section, msg->row, msg->col, msg->message);
-    
+
     if (logMode_ == LOGMODE_IMMEDIATE)
     if (logMode_ == LOGMODE_IMMEDIATE)
     {
     {
         switch (msg->type)
         switch (msg->type)
@@ -373,11 +375,11 @@ void Script::MessageCallback(const asSMessageInfo* msg)
         case asMSGTYPE_ERROR:
         case asMSGTYPE_ERROR:
             LOGERROR(message);
             LOGERROR(message);
             break;
             break;
-            
+
         case asMSGTYPE_WARNING:
         case asMSGTYPE_WARNING:
             LOGWARNING(message);
             LOGWARNING(message);
             break;
             break;
-            
+
         default:
         default:
             LOGINFO(message);
             LOGINFO(message);
             break;
             break;
@@ -395,12 +397,12 @@ void Script::ExceptionCallback(asIScriptContext* context)
 {
 {
     String message;
     String message;
     message.AppendWithFormat("- Exception '%s' in '%s'\n%s", context->GetExceptionString(), context->GetExceptionFunction()->GetDeclaration(), GetCallStack(context).CString());
     message.AppendWithFormat("- Exception '%s' in '%s'\n%s", context->GetExceptionString(), context->GetExceptionFunction()->GetDeclaration(), GetCallStack(context).CString());
-    
+
     asSMessageInfo msg;
     asSMessageInfo msg;
     msg.row = context->GetExceptionLineNumber(&msg.col, &msg.section);
     msg.row = context->GetExceptionLineNumber(&msg.col, &msg.section);
     msg.type = asMSGTYPE_ERROR;
     msg.type = asMSGTYPE_ERROR;
     msg.message = message.CString();
     msg.message = message.CString();
-    
+
     MessageCallback(&msg);
     MessageCallback(&msg);
 }
 }
 
 
@@ -442,7 +444,7 @@ asIObjectType* Script::GetObjectType(const char* declaration)
     HashMap<const char*, asIObjectType*>::ConstIterator i = objectTypes_.Find(declaration);
     HashMap<const char*, asIObjectType*>::ConstIterator i = objectTypes_.Find(declaration);
     if (i != objectTypes_.End())
     if (i != objectTypes_.End())
         return i->second_;
         return i->second_;
-    
+
     asIObjectType* type = scriptEngine_->GetObjectTypeById(scriptEngine_->GetTypeIdByDecl(declaration));
     asIObjectType* type = scriptEngine_->GetObjectTypeById(scriptEngine_->GetTypeIdByDecl(declaration));
     objectTypes_[declaration] = type;
     objectTypes_[declaration] = type;
     return type;
     return type;
@@ -456,7 +458,7 @@ asIScriptContext* Script::GetScriptFileContext()
         newContext->SetExceptionCallback(asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL);
         newContext->SetExceptionCallback(asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL);
         scriptFileContexts_.Push(newContext);
         scriptFileContexts_.Push(newContext);
     }
     }
-    
+
     return scriptFileContexts_[scriptNestingLevel_];
     return scriptFileContexts_[scriptNestingLevel_];
 }
 }
 
 
@@ -471,7 +473,7 @@ void Script::OutputAPIRow(const String& row, bool removeReference)
     out.Replace("&out", "&");
     out.Replace("&out", "&");
     if (removeReference)
     if (removeReference)
         out.Replace("&", "");
         out.Replace("&", "");
-    
+
     Log::WriteRaw("- " + out + "\n");
     Log::WriteRaw("- " + out + "\n");
 }
 }
 
 

+ 8 - 6
Engine/Script/Script.h

@@ -34,6 +34,8 @@ struct asSMessageInfo;
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* SCRIPT_CATEGORY;
+
 class Scene;
 class Scene;
 class ScriptFile;
 class ScriptFile;
 class ScriptInstance;
 class ScriptInstance;
@@ -49,15 +51,15 @@ enum ScriptLogMode
 class Script : public Object
 class Script : public Object
 {
 {
     OBJECT(Script);
     OBJECT(Script);
-    
+
     friend class ScriptFile;
     friend class ScriptFile;
-    
+
 public:
 public:
     /// Construct.
     /// Construct.
     Script(Context* context);
     Script(Context* context);
     /// Destruct. Release the AngelScript engine.
     /// Destruct. Release the AngelScript engine.
     ~Script();
     ~Script();
-    
+
     /// Compile and execute a line of script in immediate mode.
     /// Compile and execute a line of script in immediate mode.
     bool Execute(const String& line);
     bool Execute(const String& line);
     /// Set immediate mode script file.
     /// Set immediate mode script file.
@@ -76,7 +78,7 @@ public:
     void ExceptionCallback(asIScriptContext* context);
     void ExceptionCallback(asIScriptContext* context);
     /// Get call stack.
     /// Get call stack.
     static String GetCallStack(asIScriptContext* context);
     static String GetCallStack(asIScriptContext* context);
-    
+
     /// Return the AngelScript engine.
     /// Return the AngelScript engine.
     asIScriptEngine* GetScriptEngine() const { return scriptEngine_; }
     asIScriptEngine* GetScriptEngine() const { return scriptEngine_; }
     /// Return immediate execution script context.
     /// Return immediate execution script context.
@@ -93,7 +95,7 @@ public:
     ScriptLogMode GetLogMode() const { return logMode_; }
     ScriptLogMode GetLogMode() const { return logMode_; }
     /// Return retained mode log messages.
     /// Return retained mode log messages.
     const String& GetLogMessages() const { return logMessages_; }
     const String& GetLogMessages() const { return logMessages_; }
-    
+
 private:
 private:
     /// Increase script nesting level.
     /// Increase script nesting level.
     void IncScriptNestingLevel() { ++scriptNestingLevel_; }
     void IncScriptNestingLevel() { ++scriptNestingLevel_; }
@@ -105,7 +107,7 @@ private:
     asIScriptContext* GetScriptFileContext();
     asIScriptContext* GetScriptFileContext();
     /// Output a sanitated row of script API. No-ops when ENABLE_LOGGING not defined.
     /// Output a sanitated row of script API. No-ops when ENABLE_LOGGING not defined.
     void OutputAPIRow(const String& row, bool removeReference = false);
     void OutputAPIRow(const String& row, bool removeReference = false);
-    
+
     /// AngelScript engine.
     /// AngelScript engine.
     asIScriptEngine* scriptEngine_;
     asIScriptEngine* scriptEngine_;
     /// Immediate execution script context.
     /// Immediate execution script context.

+ 1 - 1
Engine/Script/ScriptInstance.cpp

@@ -81,7 +81,7 @@ ScriptInstance::~ScriptInstance()
 
 
 void ScriptInstance::RegisterObject(Context* context)
 void ScriptInstance::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<ScriptInstance>();
+    context->RegisterComponentFactory<ScriptInstance>(SCRIPT_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(ScriptInstance, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(ScriptInstance, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(ScriptInstance, VAR_RESOURCEREF, "Script File", GetScriptFileAttr, SetScriptFileAttr, ResourceRef, ResourceRef(ScriptFile::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(ScriptInstance, VAR_RESOURCEREF, "Script File", GetScriptFileAttr, SetScriptFileAttr, ResourceRef, ResourceRef(ScriptFile::GetTypeStatic()), AM_DEFAULT);

+ 3 - 1
Engine/UI/Text3D.cpp

@@ -37,6 +37,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+static const char* EFFECT_CATEGORY = "Effect";
+
 extern const char* horizontalAlignments[];
 extern const char* horizontalAlignments[];
 extern const char* verticalAlignments[];
 extern const char* verticalAlignments[];
 
 
@@ -61,7 +63,7 @@ Text3D::~Text3D()
 
 
 void Text3D::RegisterObject(Context* context)
 void Text3D::RegisterObject(Context* context)
 {
 {
-    context->RegisterFactory<Text3D>();
+    context->RegisterComponentFactory<Text3D>(EFFECT_CATEGORY);
     
     
     ACCESSOR_ATTRIBUTE(Text3D, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Text3D, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Text3D, VAR_RESOURCEREF, "Font", GetFontAttr, SetFontAttr, ResourceRef, ResourceRef(Font::GetTypeStatic()), AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Text3D, VAR_RESOURCEREF, "Font", GetFontAttr, SetFontAttr, ResourceRef, ResourceRef(Font::GetTypeStatic()), AM_DEFAULT);