Browse Source

Rearranged Octant variables for more optimal access.
Slimmed down Object, Serializable & Node for better cache performance by storing event handlers in a Map instead of HashMap and abstracting per-object network replication state into a separately allocated structure NetworkState.

Lasse Öörni 13 years ago
parent
commit
da921892b2

+ 11 - 11
Engine/Core/Object.cpp

@@ -44,7 +44,7 @@ void Object::OnEvent(Object* sender, bool broadcast, StringHash eventType, Varia
     Context* context = context_;
     Context* context = context_;
     
     
     // Check first the specific event handlers, which have priority
     // Check first the specific event handlers, which have priority
-    HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::ConstIterator i = eventHandlers_.Find(
+    Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::ConstIterator i = eventHandlers_.Find(
         MakePair(sender, eventType));
         MakePair(sender, eventType));
     if (i != eventHandlers_.End())
     if (i != eventHandlers_.End())
     {
     {
@@ -88,10 +88,10 @@ void Object::SubscribeToEvent(Object* sender, StringHash eventType, EventHandler
 
 
 void Object::UnsubscribeFromEvent(StringHash eventType)
 void Object::UnsubscribeFromEvent(StringHash eventType)
 {
 {
-    for (HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
+    for (Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
         i != eventHandlers_.End();)
         i != eventHandlers_.End();)
     {
     {
-        HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator current = i++;
+        Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator current = i++;
         if (current->first_.second_ == eventType)
         if (current->first_.second_ == eventType)
         {
         {
             if (current->first_.first_)
             if (current->first_.first_)
@@ -107,7 +107,7 @@ void Object::UnsubscribeFromEvent(Object* sender, StringHash eventType)
 {
 {
     Pair<Object*, StringHash> combination(sender, eventType);
     Pair<Object*, StringHash> combination(sender, eventType);
     
     
-    HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Find(combination);
+    Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Find(combination);
     if (i != eventHandlers_.End())
     if (i != eventHandlers_.End())
     {
     {
         context_->RemoveEventReceiver(this, i->first_.first_, i->first_.second_);
         context_->RemoveEventReceiver(this, i->first_.first_, i->first_.second_);
@@ -120,10 +120,10 @@ void Object::UnsubscribeFromEvents(Object* sender)
     if (!sender)
     if (!sender)
         return;
         return;
     
     
-    for (HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
+    for (Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
         i != eventHandlers_.End();)
         i != eventHandlers_.End();)
     {
     {
-        HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator current = i++;
+        Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator current = i++;
         if (current->first_.first_ == sender)
         if (current->first_.first_ == sender)
         {
         {
             context_->RemoveEventReceiver(this, current->first_.first_, current->first_.second_);
             context_->RemoveEventReceiver(this, current->first_.first_, current->first_.second_);
@@ -134,7 +134,7 @@ void Object::UnsubscribeFromEvents(Object* sender)
 
 
 void Object::UnsubscribeFromAllEvents()
 void Object::UnsubscribeFromAllEvents()
 {
 {
-    for (HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
+    for (Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
         i != eventHandlers_.End(); ++i)
         i != eventHandlers_.End(); ++i)
     {
     {
         if (i->first_.first_)
         if (i->first_.first_)
@@ -148,12 +148,12 @@ void Object::UnsubscribeFromAllEvents()
 
 
 void Object::UnsubscribeFromAllEventsWithUserData()
 void Object::UnsubscribeFromAllEventsWithUserData()
 {
 {
-    for (HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
+    for (Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
         i != eventHandlers_.End(); )
         i != eventHandlers_.End(); )
     {
     {
         if (i->second_->GetUserData())
         if (i->second_->GetUserData())
         {
         {
-            HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator current = i++;
+            Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator current = i++;
             if (current->first_.first_)
             if (current->first_.first_)
                 context_->RemoveEventReceiver(this, current->first_.first_, current->first_.second_);
                 context_->RemoveEventReceiver(this, current->first_.first_, current->first_.second_);
             else
             else
@@ -323,10 +323,10 @@ bool Object::HasSubscribedToEvent(Object* sender, StringHash eventType) const
 
 
 void Object::RemoveEventSender(Object* sender)
 void Object::RemoveEventSender(Object* sender)
 {
 {
-    for (HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
+    for (Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator i = eventHandlers_.Begin();
         i != eventHandlers_.End();)
         i != eventHandlers_.End();)
     {
     {
-        HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator current = i++;
+        Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> >::Iterator current = i++;
         if (current->first_.first_ == sender)
         if (current->first_.first_ == sender)
             eventHandlers_.Erase(current);
             eventHandlers_.Erase(current);
     }
     }

+ 2 - 1
Engine/Core/Object.h

@@ -24,6 +24,7 @@
 #pragma once
 #pragma once
 
 
 #include "HashMap.h"
 #include "HashMap.h"
+#include "Map.h"
 #include "Ptr.h"
 #include "Ptr.h"
 #include "Variant.h"
 #include "Variant.h"
 
 
@@ -95,7 +96,7 @@ private:
     void RemoveEventSender(Object* sender);
     void RemoveEventSender(Object* sender);
     
     
     /// Event handlers. Sender is null for non-specific handlers.
     /// Event handlers. Sender is null for non-specific handlers.
-    HashMap<Pair<Object*, StringHash>, SharedPtr<EventHandler> > eventHandlers_;
+    Map<Pair<Object*, StringHash>, SharedPtr<EventHandler> > eventHandlers_;
 };
 };
 
 
 template <class T> T* Object::GetSubsystem() const { return static_cast<T*>(GetSubsystem(T::GetTypeStatic())); }
 template <class T> T* Object::GetSubsystem() const { return static_cast<T*>(GetSubsystem(T::GetTypeStatic())); }

+ 0 - 1
Engine/Graphics/Model.h

@@ -25,7 +25,6 @@
 
 
 #include "ArrayPtr.h"
 #include "ArrayPtr.h"
 #include "BoundingBox.h"
 #include "BoundingBox.h"
-#include "Map.h"
 #include "Skeleton.h"
 #include "Skeleton.h"
 #include "Resource.h"
 #include "Resource.h"
 #include "Ptr.h"
 #include "Ptr.h"

+ 2 - 8
Engine/Graphics/Octree.cpp

@@ -82,9 +82,9 @@ inline bool CompareRayQueryResults(const RayQueryResult& lhs, const RayQueryResu
 Octant::Octant(const BoundingBox& box, unsigned level, Octant* parent, Octree* root) :
 Octant::Octant(const BoundingBox& box, unsigned level, Octant* parent, Octree* root) :
     worldBoundingBox_(box),
     worldBoundingBox_(box),
     level_(level),
     level_(level),
+    numDrawables_(0),
     parent_(parent),
     parent_(parent),
-    root_(root),
-    numDrawables_(0)
+    root_(root)
 {
 {
     center_ = worldBoundingBox_.Center();
     center_ = worldBoundingBox_.Center();
     halfSize_ = worldBoundingBox_.Size() * 0.5f;
     halfSize_ = worldBoundingBox_.Size() * 0.5f;
@@ -234,9 +234,6 @@ void Octant::GetDrawablesInternal(OctreeQuery& query, bool inside) const
 
 
 void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
 void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
 {
 {
-    if (!numDrawables_)
-        return;
-    
     float octantDist = query.ray_.HitDistance(cullingBox_);
     float octantDist = query.ray_.HitDistance(cullingBox_);
     if (octantDist > query.maxDistance_)
     if (octantDist > query.maxDistance_)
         return;
         return;
@@ -267,9 +264,6 @@ void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
 
 
 void Octant::GetDrawablesOnlyInternal(RayOctreeQuery& query, PODVector<Drawable*>& drawables) const
 void Octant::GetDrawablesOnlyInternal(RayOctreeQuery& query, PODVector<Drawable*>& drawables) const
 {
 {
-    if (!numDrawables_)
-        return;
-    
     float octantDist = query.ray_.HitDistance(cullingBox_);
     float octantDist = query.ray_.HitDistance(cullingBox_);
     if (octantDist > query.maxDistance_)
     if (octantDist > query.maxDistance_)
         return;
         return;

+ 6 - 6
Engine/Graphics/Octree.h

@@ -131,22 +131,22 @@ protected:
     BoundingBox worldBoundingBox_;
     BoundingBox worldBoundingBox_;
     /// Bounding box used for drawable object fitting.
     /// Bounding box used for drawable object fitting.
     BoundingBox cullingBox_;
     BoundingBox cullingBox_;
+    /// Drawable objects.
+    PODVector<Drawable*> drawables_;
+    /// Child octants.
+    Octant* children_[NUM_OCTANTS];
     /// World bounding box center.
     /// World bounding box center.
     Vector3 center_;
     Vector3 center_;
     /// World bounding box half size.
     /// World bounding box half size.
     Vector3 halfSize_;
     Vector3 halfSize_;
     /// Subdivision level.
     /// Subdivision level.
     unsigned level_;
     unsigned level_;
+    /// Number of drawable objects in this octant and child octants.
+    unsigned numDrawables_;
     /// Parent octant.
     /// Parent octant.
     Octant* parent_;
     Octant* parent_;
-    /// Child octants.
-    Octant* children_[NUM_OCTANTS];
     /// Octree root.
     /// Octree root.
     Octree* root_;
     Octree* root_;
-    /// Drawable objects.
-    PODVector<Drawable*> drawables_;
-    /// Number of drawable objects in this octant and child octants.
-    unsigned numDrawables_;
 };
 };
 
 
 /// %Octree component. Should be added only to the root scene node
 /// %Octree component. Should be added only to the root scene node

+ 0 - 1
Engine/Network/Network.h

@@ -25,7 +25,6 @@
 
 
 #include "Connection.h"
 #include "Connection.h"
 #include "HashSet.h"
 #include "HashSet.h"
-#include "Map.h"
 #include "Object.h"
 #include "Object.h"
 #include "VectorBuffer.h"
 #include "VectorBuffer.h"
 
 

+ 28 - 16
Engine/Scene/Component.cpp

@@ -91,7 +91,10 @@ const Matrix3x4& Component::GetWorldTransform() const
 
 
 void Component::AddReplicationState(ComponentReplicationState* state)
 void Component::AddReplicationState(ComponentReplicationState* state)
 {
 {
-    replicationStates_.Push(state);
+    if (!netState_)
+        netState_ = new NetworkState();
+    
+    netState_->replicationStates_.Push(state);
 }
 }
 
 
 void Component::PrepareNetworkUpdate()
 void Component::PrepareNetworkUpdate()
@@ -102,36 +105,42 @@ void Component::PrepareNetworkUpdate()
     
     
     unsigned numAttributes = attributes->Size();
     unsigned numAttributes = attributes->Size();
     
     
-    if (currentState_.Size() != numAttributes)
+    if (!netState_)
+        netState_ = new NetworkState();
+    
+    if (netState_->attributes_.Size() != numAttributes)
     {
     {
-        currentState_.Resize(numAttributes);
-        previousState_.Resize(numAttributes);
+        netState_->attributes_.Resize(numAttributes);
+        netState_->previousAttributes_.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)
-            previousState_[i] = attributes->At(i).defaultValue_;
+            netState_->previousAttributes_[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, currentState_[i]);
+        OnGetAttribute(attr, netState_->attributes_[i]);
         
         
-        if (currentState_[i] != previousState_[i])
+        if (netState_->attributes_[i] != netState_->previousAttributes_[i])
         {
         {
-            previousState_[i] = currentState_[i];
+            netState_->previousAttributes_[i] = netState_->attributes_[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<ComponentReplicationState*>::Iterator j = replicationStates_.Begin(); j != replicationStates_.End(); ++j)
+            for (PODVector<ReplicationState*>::Iterator j = netState_->replicationStates_.Begin(); j !=
+                netState_->replicationStates_.End(); ++j)
             {
             {
-                (*j)->dirtyAttributes_.Set(i);
+                ComponentReplicationState* compState = static_cast<ComponentReplicationState*>(*j);
+                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
-                if (!(*j)->nodeState_->markedDirty_)
+                NodeReplicationState* nodeState = compState->nodeState_;
+                if (!nodeState->markedDirty_)
                 {
                 {
-                    (*j)->nodeState_->markedDirty_ = true;
-                    (*j)->nodeState_->sceneState_->dirtyNodes_.Insert(node_->GetID());
+                    nodeState->markedDirty_ = true;
+                    nodeState->sceneState_->dirtyNodes_.Insert(node_->GetID());
                 }
                 }
             }
             }
         }
         }
@@ -140,10 +149,13 @@ void Component::PrepareNetworkUpdate()
 
 
 void Component::CleanupConnection(Connection* connection)
 void Component::CleanupConnection(Connection* connection)
 {
 {
-    for (unsigned i = replicationStates_.Size() - 1; i < replicationStates_.Size(); --i)
+    if (netState_)
     {
     {
-        if (replicationStates_[i]->connection_ == connection)
-            replicationStates_.Erase(i);
+        for (unsigned i = netState_->replicationStates_.Size() - 1; i < netState_->replicationStates_.Size(); --i)
+        {
+            if (netState_->replicationStates_[i]->connection_ == connection)
+                netState_->replicationStates_.Erase(i);
+        }
     }
     }
 }
 }
 
 

+ 0 - 2
Engine/Scene/Component.h

@@ -103,8 +103,6 @@ protected:
     Node* node_;
     Node* node_;
     /// Unique ID within the scene.
     /// Unique ID within the scene.
     unsigned id_;
     unsigned id_;
-    /// Per-user network replication states.
-    PODVector<ComponentReplicationState*> replicationStates_;
 };
 };
 
 
 template <class T> T* Component::GetComponent() const { return static_cast<T*>(GetComponent(T::GetTypeStatic())); }
 template <class T> T* Component::GetComponent() const { return static_cast<T*>(GetComponent(T::GetTypeStatic())); }

+ 64 - 49
Engine/Scene/Node.cpp

@@ -43,7 +43,7 @@ Node::Node(Context* context) :
     Serializable(context),
     Serializable(context),
     worldTransform_(Matrix3x4::IDENTITY),
     worldTransform_(Matrix3x4::IDENTITY),
     dirty_(false),
     dirty_(false),
-    networkUpdate_(false),
+    netUpdate_(false),
     rotateCount_(0),
     rotateCount_(0),
     parent_(0),
     parent_(0),
     scene_(0),
     scene_(0),
@@ -220,7 +220,10 @@ void Node::ApplyAttributes()
 
 
 void Node::AddReplicationState(NodeReplicationState* state)
 void Node::AddReplicationState(NodeReplicationState* state)
 {
 {
-    replicationStates_.Push(state);
+    if (!netState_)
+        netState_ = new NetworkState();
+    
+    netState_->replicationStates_.Push(state);
 }
 }
 
 
 bool Node::SaveXML(Serializer& dest)
 bool Node::SaveXML(Serializer& dest)
@@ -858,70 +861,74 @@ void Node::PrepareNetworkUpdate()
     
     
     // Then check for node attribute changes
     // Then check for node attribute changes
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
-    if (attributes)
+    unsigned numAttributes = attributes->Size();
+    
+    if (!netState_)
+        netState_ = new NetworkState();
+    
+    if (netState_->attributes_.Size() != numAttributes)
     {
     {
-        unsigned numAttributes = attributes->Size();
+        netState_->attributes_.Resize(numAttributes);
+        netState_->previousAttributes_.Resize(numAttributes);
         
         
-        if (currentState_.Size() != numAttributes)
-        {
-            currentState_.Resize(numAttributes);
-            previousState_.Resize(numAttributes);
-            
-            // Copy the default attribute values to the previous state as a starting point
-            for (unsigned i = 0; i < numAttributes; ++i)
-                previousState_[i] = attributes->At(i).defaultValue_;
-        }
-        
-        // Check for attribute changes
+        // 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)
+            netState_->previousAttributes_[i] = attributes->At(i).defaultValue_;
+    }
+    
+    // Check for attribute changes
+    for (unsigned i = 0; i < numAttributes; ++i)
+    {
+        const AttributeInfo& attr = attributes->At(i);
+        OnGetAttribute(attr, netState_->attributes_[i]);
+        
+        if (netState_->attributes_[i] != netState_->previousAttributes_[i])
         {
         {
-            const AttributeInfo& attr = attributes->At(i);
-            OnGetAttribute(attr, currentState_[i]);
+            netState_->previousAttributes_[i] = netState_->attributes_[i];
             
             
-            if (currentState_[i] != previousState_[i])
+            // Mark the attribute dirty in all replication states that are tracking this node
+            for (PODVector<ReplicationState*>::Iterator j = netState_->replicationStates_.Begin(); j !=
+                netState_->replicationStates_.End();
+                ++j)
             {
             {
-                previousState_[i] = currentState_[i];
+                NodeReplicationState* nodeState = static_cast<NodeReplicationState*>(*j);
+                nodeState->dirtyAttributes_.Set(i);
                 
                 
-                // Mark the attribute dirty in all replication states that are tracking this node
-                for (PODVector<NodeReplicationState*>::Iterator j = replicationStates_.Begin(); j != replicationStates_.End();
-                    ++j)
+                // Add node to the dirty set if not added yet
+                if (!nodeState->markedDirty_)
                 {
                 {
-                    (*j)->dirtyAttributes_.Set(i);
-                    
-                    // Add node to the dirty set if not added yet
-                    if (!(*j)->markedDirty_)
-                    {
-                        (*j)->markedDirty_ = true;
-                        (*j)->sceneState_->dirtyNodes_.Insert(id_);
-                    }
+                    nodeState->markedDirty_ = true;
+                    nodeState->sceneState_->dirtyNodes_.Insert(id_);
                 }
                 }
             }
             }
         }
         }
     }
     }
-    
+
     // Finally check for user var changes
     // Finally check for user var changes
     for (VariantMap::ConstIterator i = vars_.Begin(); i != vars_.End(); ++i)
     for (VariantMap::ConstIterator i = vars_.Begin(); i != vars_.End(); ++i)
     {
     {
-        VariantMap::ConstIterator j = previousVars_.Find(i->first_);
-        if (j == previousVars_.End() || j->second_ != i->second_)
+        VariantMap::ConstIterator j = netState_->previousVars_.Find(i->first_);
+        if (j == netState_->previousVars_.End() || j->second_ != i->second_)
         {
         {
-            previousVars_[i->first_] = i->second_;
+            netState_->previousVars_[i->first_] = i->second_;
             
             
             // Mark the var dirty in all replication states that are tracking this node
             // Mark the var dirty in all replication states that are tracking this node
-            for (PODVector<NodeReplicationState*>::Iterator j = replicationStates_.Begin(); j != replicationStates_.End(); ++j)
+            for (PODVector<ReplicationState*>::Iterator j = netState_->replicationStates_.Begin(); j !=
+                netState_->replicationStates_.End(); ++j)
             {
             {
-                (*j)->dirtyVars_.Insert(i->first_);
+                NodeReplicationState* nodeState = static_cast<NodeReplicationState*>(*j);
+                nodeState->dirtyVars_.Insert(i->first_);
                 
                 
-                if (!(*j)->markedDirty_)
+                if (!nodeState->markedDirty_)
                 {
                 {
-                    (*j)->markedDirty_ = true;
-                    (*j)->sceneState_->dirtyNodes_.Insert(id_);
+                    nodeState->markedDirty_ = true;
+                    nodeState->sceneState_->dirtyNodes_.Insert(id_);
                 }
                 }
             }
             }
         }
         }
     }
     }
     
     
-    networkUpdate_ = false;
+    netUpdate_ = false;
 }
 }
 
 
 void Node::CleanupConnection(Connection* connection)
 void Node::CleanupConnection(Connection* connection)
@@ -929,30 +936,38 @@ void Node::CleanupConnection(Connection* connection)
     if (owner_ == connection)
     if (owner_ == connection)
         owner_ = 0;
         owner_ = 0;
     
     
-    for (unsigned i = replicationStates_.Size() - 1; i < replicationStates_.Size(); --i)
+    if (netState_)
     {
     {
-        if (replicationStates_[i]->connection_ == connection)
-            replicationStates_.Erase(i);
+        for (unsigned i = netState_->replicationStates_.Size() - 1; i < netState_->replicationStates_.Size(); --i)
+        {
+            if (netState_->replicationStates_[i]->connection_ == connection)
+                netState_->replicationStates_.Erase(i);
+        }
     }
     }
 }
 }
 
 
 void Node::MarkNetworkUpdate()
 void Node::MarkNetworkUpdate()
 {
 {
-    if (id_ < FIRST_LOCAL_ID && !networkUpdate_ && scene_)
+    if (id_ < FIRST_LOCAL_ID && !netUpdate_ && scene_)
     {
     {
         scene_->MarkNetworkUpdate(this);
         scene_->MarkNetworkUpdate(this);
-        networkUpdate_ = true;
+        netUpdate_ = true;
     }
     }
 }
 }
 
 
 void Node::MarkReplicationDirty()
 void Node::MarkReplicationDirty()
 {
 {
-    for (PODVector<NodeReplicationState*>::Iterator j = replicationStates_.Begin(); j != replicationStates_.End(); ++j)
+    if (netState_)
     {
     {
-        if (!(*j)->markedDirty_)
+        for (PODVector<ReplicationState*>::Iterator j = netState_->replicationStates_.Begin(); j !=
+            netState_->replicationStates_.End(); ++j)
         {
         {
-            (*j)->markedDirty_ = true;
-            (*j)->sceneState_->dirtyNodes_.Insert(id_);
+            NodeReplicationState* nodeState = static_cast<NodeReplicationState*>(*j);
+            if (!nodeState->markedDirty_)
+            {
+                nodeState->markedDirty_ = true;
+                nodeState->sceneState_->dirtyNodes_.Insert(id_);
+            }
         }
         }
     }
     }
 }
 }

+ 1 - 5
Engine/Scene/Node.h

@@ -341,7 +341,7 @@ private:
     /// World transform needs update flag.
     /// World transform needs update flag.
     mutable bool dirty_;
     mutable bool dirty_;
     /// Network update queued flag.
     /// Network update queued flag.
-    bool networkUpdate_;
+    bool netUpdate_;
     /// Consecutive rotation count for rotation renormalization.
     /// Consecutive rotation count for rotation renormalization.
     unsigned short rotateCount_;
     unsigned short rotateCount_;
     /// Parent scene node.
     /// Parent scene node.
@@ -376,10 +376,6 @@ private:
 protected:
 protected:
     /// User variables.
     /// User variables.
     VariantMap vars_;
     VariantMap vars_;
-    /// Previous user variables for network updates.
-    VariantMap previousVars_;
-    /// Per-user network replication states.
-    PODVector<NodeReplicationState*> replicationStates_;
 };
 };
 
 
 template <class T> T* Node::CreateComponent(CreateMode mode) { return static_cast<T*>(CreateComponent(T::GetTypeStatic(), mode)); }
 template <class T> T* Node::CreateComponent(CreateMode mode) { return static_cast<T*>(CreateComponent(T::GetTypeStatic(), mode)); }

+ 25 - 9
Engine/Scene/ReplicationState.h

@@ -37,6 +37,7 @@ class Connection;
 class Node;
 class Node;
 class Scene;
 class Scene;
 
 
+struct ReplicationState;
 struct ComponentReplicationState;
 struct ComponentReplicationState;
 struct NodeReplicationState;
 struct NodeReplicationState;
 struct SceneReplicationState;
 struct SceneReplicationState;
@@ -117,11 +118,29 @@ struct DirtyBits
     unsigned char count_;
     unsigned char count_;
 };
 };
 
 
-/// Per-user component network replication state.
-struct ComponentReplicationState
+/// Per-object attribute state for network replication, allocated on demand.
+struct NetworkState
+{
+    /// Current network attributes.
+    Vector<Variant> attributes_;
+    /// Previous network attributes.
+    Vector<Variant> previousAttributes_;
+    /// Replication states that are tracking this object.
+    PODVector<ReplicationState*> replicationStates_;
+    /// Previous user variables.
+    VariantMap previousVars_;
+};
+
+/// Base class for per-user network replication states.
+struct ReplicationState
 {
 {
     /// Parent network connection.
     /// Parent network connection.
     Connection* connection_;
     Connection* connection_;
+};
+
+/// Per-user component network replication state.
+struct ComponentReplicationState : ReplicationState
+{
     /// Parent node replication state.
     /// Parent node replication state.
     NodeReplicationState* nodeState_;
     NodeReplicationState* nodeState_;
     /// Link to the actual component.
     /// Link to the actual component.
@@ -130,18 +149,17 @@ struct ComponentReplicationState
     DirtyBits dirtyAttributes_;
     DirtyBits dirtyAttributes_;
 };
 };
 
 
-/// Last sent state of a node for network replication.
-struct NodeReplicationState
+/// Per-user node network replication state.
+struct NodeReplicationState : ReplicationState
 {
 {
     /// Construct.
     /// Construct.
     NodeReplicationState() :
     NodeReplicationState() :
+        ReplicationState(),
         priorityAcc_(0.0f),
         priorityAcc_(0.0f),
         markedDirty_(false)
         markedDirty_(false)
     {
     {
     }
     }
     
     
-    /// Parent network connection.
-    Connection* connection_;
     /// Parent scene replication state.
     /// Parent scene replication state.
     SceneReplicationState* sceneState_;
     SceneReplicationState* sceneState_;
     /// Link to the actual node.
     /// Link to the actual node.
@@ -159,10 +177,8 @@ struct NodeReplicationState
 };
 };
 
 
 /// Per-user scene network replication state.
 /// Per-user scene network replication state.
-struct SceneReplicationState
+struct SceneReplicationState : ReplicationState
 {
 {
-    /// Parent network connection.
-    Connection* connection_;
     /// Nodes by ID.
     /// Nodes by ID.
     HashMap<unsigned, NodeReplicationState> nodeStates_;
     HashMap<unsigned, NodeReplicationState> nodeStates_;
     /// Dirty node IDs.
     /// Dirty node IDs.

+ 9 - 4
Engine/Scene/Scene.cpp

@@ -160,7 +160,7 @@ bool Scene::LoadXML(const XMLElement& source)
 
 
 void Scene::AddReplicationState(NodeReplicationState* state)
 void Scene::AddReplicationState(NodeReplicationState* state)
 {
 {
-    replicationStates_.Push(state);
+    Node::AddReplicationState(state);
     
     
     // This is the first update for a new connection. Mark all replicated nodes dirty
     // This is the first update for a new connection. Mark all replicated nodes dirty
     for (HashMap<unsigned, Node*>::ConstIterator i = replicatedNodes_.Begin(); i != replicatedNodes_.End(); ++i)
     for (HashMap<unsigned, Node*>::ConstIterator i = replicatedNodes_.Begin(); i != replicatedNodes_.End(); ++i)
@@ -745,10 +745,15 @@ void Scene::MarkNetworkUpdate(Node* node)
 void Scene::MarkReplicationDirty(Node* node)
 void Scene::MarkReplicationDirty(Node* node)
 {
 {
     unsigned id = node->GetID();
     unsigned id = node->GetID();
-    if (id < FIRST_LOCAL_ID)
+    
+    if (id < FIRST_LOCAL_ID && netState_)
     {
     {
-        for (PODVector<NodeReplicationState*>::Iterator i = replicationStates_.Begin(); i != replicationStates_.End(); ++i)
-            (*i)->sceneState_->dirtyNodes_.Insert(id);
+        for (PODVector<ReplicationState*>::Iterator i = netState_->replicationStates_.Begin(); i !=
+            netState_->replicationStates_.End(); ++i)
+        {
+            NodeReplicationState* nodeState = static_cast<NodeReplicationState*>(*i);
+            nodeState->sceneState_->dirtyNodes_.Insert(id);
+        }
     }
     }
 }
 }
 
 

+ 10 - 7
Engine/Scene/Serializable.cpp

@@ -36,12 +36,15 @@ OBJECTTYPESTATIC(Serializable);
 
 
 Serializable::Serializable(Context* context) :
 Serializable::Serializable(Context* context) :
     Object(context),
     Object(context),
+    netState_(0),
     loading_(false)
     loading_(false)
 {
 {
 }
 }
 
 
 Serializable::~Serializable()
 Serializable::~Serializable()
 {
 {
+    delete netState_;
+    netState_ = 0;
 }
 }
 
 
 void Serializable::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 void Serializable::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
@@ -423,7 +426,7 @@ bool Serializable::SetAttribute(const String& name, const Variant& value)
 void Serializable::WriteInitialDeltaUpdate(Serializer& dest)
 void Serializable::WriteInitialDeltaUpdate(Serializer& dest)
 {
 {
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
-    if (!attributes)
+    if (!attributes || !netState_)
         return;
         return;
     
     
     unsigned numAttributes = attributes->Size();
     unsigned numAttributes = attributes->Size();
@@ -433,7 +436,7 @@ void Serializable::WriteInitialDeltaUpdate(Serializer& dest)
     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);
-        if (currentState_[i] != attr.defaultValue_)
+        if (netState_->attributes_[i] != attr.defaultValue_)
             attributeBits.Set(i);
             attributeBits.Set(i);
     }
     }
     
     
@@ -443,14 +446,14 @@ void Serializable::WriteInitialDeltaUpdate(Serializer& dest)
     for (unsigned i = 0; i < numAttributes; ++i)
     for (unsigned i = 0; i < numAttributes; ++i)
     {
     {
         if (attributeBits.IsSet(i))
         if (attributeBits.IsSet(i))
-            dest.WriteVariantData(currentState_[i]);
+            dest.WriteVariantData(netState_->attributes_[i]);
     }
     }
 }
 }
 
 
 void Serializable::WriteDeltaUpdate(Serializer& dest, const DirtyBits& attributeBits)
 void Serializable::WriteDeltaUpdate(Serializer& dest, const DirtyBits& attributeBits)
 {
 {
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
-    if (!attributes)
+    if (!attributes || !netState_)
         return;
         return;
     
     
     unsigned numAttributes = attributes->Size();
     unsigned numAttributes = attributes->Size();
@@ -462,14 +465,14 @@ void Serializable::WriteDeltaUpdate(Serializer& dest, const DirtyBits& attribute
     for (unsigned i = 0; i < numAttributes; ++i)
     for (unsigned i = 0; i < numAttributes; ++i)
     {
     {
         if (attributeBits.IsSet(i))
         if (attributeBits.IsSet(i))
-            dest.WriteVariantData(currentState_[i]);
+            dest.WriteVariantData(netState_->attributes_[i]);
     }
     }
 }
 }
 
 
 void Serializable::WriteLatestDataUpdate(Serializer& dest)
 void Serializable::WriteLatestDataUpdate(Serializer& dest)
 {
 {
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
-    if (!attributes)
+    if (!attributes || !netState_)
         return;
         return;
     
     
     unsigned numAttributes = attributes->Size();
     unsigned numAttributes = attributes->Size();
@@ -477,7 +480,7 @@ void Serializable::WriteLatestDataUpdate(Serializer& dest)
     for (unsigned i = 0; i < numAttributes; ++i)
     for (unsigned i = 0; i < numAttributes; ++i)
     {
     {
         if (attributes->At(i).mode_ & AM_LATESTDATA)
         if (attributes->At(i).mode_ & AM_LATESTDATA)
-            dest.WriteVariantData(currentState_[i]);
+            dest.WriteVariantData(netState_->attributes_[i]);
     }
     }
 }
 }
 
 

+ 4 - 4
Engine/Scene/Serializable.h

@@ -34,6 +34,8 @@ class Serializer;
 class XMLElement;
 class XMLElement;
 
 
 struct DirtyBits;
 struct DirtyBits;
+struct NetworkState;
+struct ReplicationState;
 
 
 /// Base class for objects with automatic serialization through attributes.
 /// Base class for objects with automatic serialization through attributes.
 class Serializable : public Object
 class Serializable : public Object
@@ -92,10 +94,8 @@ public:
     bool IsLoading() const { return loading_; }
     bool IsLoading() const { return loading_; }
     
     
 protected:
 protected:
-    /// Current attributes for sending network updates.
-    Vector<Variant> currentState_;
-    /// Previous attributes for sending network updates.
-    Vector<Variant> previousState_;
+    /// Network attribute state.
+    NetworkState* netState_;
     /// Is loading flag.
     /// Is loading flag.
     bool loading_;
     bool loading_;
 };
 };

+ 0 - 1
Tools/AssetImporter/AssetImporter.cpp

@@ -47,7 +47,6 @@
 #include "Zone.h"
 #include "Zone.h"
 
 
 #include "Sort.h"
 #include "Sort.h"
-#include "Map.h"
 #include "Set.h"
 #include "Set.h"
 
 
 #ifdef WIN32
 #ifdef WIN32

+ 0 - 1
Tools/OgreImporter/OgreImporterUtils.h

@@ -26,7 +26,6 @@
 #include "Animation.h"
 #include "Animation.h"
 #include "BoundingBox.h"
 #include "BoundingBox.h"
 #include "Graphics.h"
 #include "Graphics.h"
-#include "Map.h"
 #include "Serializer.h"
 #include "Serializer.h"
 #include "Matrix3x4.h"
 #include "Matrix3x4.h"
 
 

+ 0 - 1
Tools/ShaderCompiler/ShaderCompiler.cpp

@@ -25,7 +25,6 @@
 #include "File.h"
 #include "File.h"
 #include "FileSystem.h"
 #include "FileSystem.h"
 #include "List.h"
 #include "List.h"
-#include "Map.h"
 #include "Mutex.h"
 #include "Mutex.h"
 #include "ProcessUtils.h"
 #include "ProcessUtils.h"
 #include "Set.h"
 #include "Set.h"