Browse Source

Add IsReplicated() method for Node and Component classes.
Close #2211.

Yao Wei Tjong 姚伟忠 8 years ago
parent
commit
23a696676d

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

@@ -511,6 +511,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_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, "bool get_replicated()", asMETHOD(T, IsReplicated), asCALL_THISCALL);
     if (nodeRegistered)
         engine->RegisterObjectMethod(className, "Node@+ get_node() const", asMETHODPR(T, GetNode, () const, Node*), asCALL_THISCALL);
     if (debugRendererRegistered)
@@ -783,6 +784,7 @@ template <class T> void RegisterNode(asIScriptEngine* engine, const char* classN
     engine->RegisterObjectMethod(className, "const Matrix3x4& get_worldTransform() const", asMETHOD(T, GetWorldTransform), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_id(uint)", asMETHOD(T, SetID), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "uint get_id()", asMETHOD(T, GetID), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_replicated()", asMETHOD(T, IsReplicated), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "uint get_numChildren() const", asFUNCTION(NodeGetNumChildrenNonRecursive), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "uint get_numAllChildren() const", asFUNCTION(NodeGetNumChildrenRecursive), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "Node@+ get_children(uint) const", asFUNCTION(NodeGetChild), asCALL_CDECL_OBJLAST);

+ 2 - 0
Source/Urho3D/LuaScript/pkgs/Scene/Component.pkg

@@ -14,6 +14,7 @@ class Component : public Animatable
     void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
 
     unsigned GetID() const;
+    bool IsReplicated() const;
     Node* GetNode() const;
     Scene* GetScene() const;
     bool IsEnabled() const;
@@ -23,6 +24,7 @@ class Component : public Animatable
     Component* GetComponent(const String type) const;
 
     tolua_readonly tolua_property__get_set unsigned ID;
+    tolua_readonly tolua_property__is_set bool replicated;
     tolua_property__is_set bool enabled;
     tolua_readonly tolua_property__is_set bool enabledEffective;
     tolua_readonly tolua_property__get_set Node* node;

+ 3 - 1
Source/Urho3D/LuaScript/pkgs/Scene/Node.pkg

@@ -128,6 +128,7 @@ class Node : public Animatable
     int GetScriptObject(const String scriptObjectType) const;
 
     unsigned GetID() const;
+    bool IsReplicated() const;
     const String GetName() const;
     StringHash GetNameHash() const;
     Node* GetParent() const;
@@ -205,11 +206,12 @@ class Node : public Animatable
     const StringVector& GetTags() const;
 
     // void GetChildrenWithTag(PODVector<Node*>& dest, const String& tag, bool recursive = false) const;
-    tolua_outside const PODVector<Node*>& NodeGetChildrenWithTag @ GetChildrenWithTag(const String& tag, bool recursive = false) const; 
+    tolua_outside const PODVector<Node*>& NodeGetChildrenWithTag @ GetChildrenWithTag(const String& tag, bool recursive = false) const;
 
     void SetID(unsigned id);
 
     tolua_readonly tolua_property__get_set unsigned ID;
+    tolua_readonly tolua_property__is_set bool replicated;
     tolua_property__get_set String name;
     tolua_readonly tolua_property__get_set StringHash nameHash;
     tolua_property__get_set Node* parent;

+ 3 - 3
Source/Urho3D/Network/Connection.cpp

@@ -146,7 +146,7 @@ void Connection::SendRemoteEvent(Node* node, StringHash eventType, bool inOrder,
         URHO3D_LOGERROR("Sender node is not in the connection's scene, can not send remote node event");
         return;
     }
-    if (node->GetID() >= FIRST_LOCAL_ID)
+    if (!node->IsReplicated())
     {
         URHO3D_LOGERROR("Sender node has a local ID, can not send remote node event");
         return;
@@ -1180,7 +1180,7 @@ void Connection::ProcessNewNode(Node* node)
     {
         Component* component = components[i];
         // Check if component is not to be replicated
-        if (component->GetID() >= FIRST_LOCAL_ID)
+        if (!component->IsReplicated())
             continue;
 
         ComponentReplicationState& componentState = nodeState.componentStates_[component->GetID()];
@@ -1348,7 +1348,7 @@ void Connection::ProcessExistingNode(Node* node, NodeReplicationState& nodeState
         {
             Component* component = components[i];
             // Check if component is not to be replicated
-            if (component->GetID() >= FIRST_LOCAL_ID)
+            if (!component->IsReplicated())
                 continue;
 
             HashMap<unsigned, ComponentReplicationState>::Iterator j = nodeState.componentStates_.Find(component->GetID());

+ 1 - 1
Source/Urho3D/Network/Network.cpp

@@ -317,7 +317,7 @@ void Network::BroadcastRemoteEvent(Node* node, StringHash eventType, bool inOrde
         URHO3D_LOGERROR("Null sender node for remote node event");
         return;
     }
-    if (node->GetID() >= FIRST_LOCAL_ID)
+    if (!node->IsReplicated())
     {
         URHO3D_LOGERROR("Sender node has a local ID, can not send remote node event");
         return;

+ 6 - 1
Source/Urho3D/Scene/Component.cpp

@@ -98,7 +98,7 @@ bool Component::SaveJSON(JSONValue& dest) const
 
 void Component::MarkNetworkUpdate()
 {
-    if (!networkUpdate_ && id_ < FIRST_LOCAL_ID)
+    if (!networkUpdate_ && IsReplicated())
     {
         Scene* scene = GetScene();
         if (scene)
@@ -147,6 +147,11 @@ void Component::Remove()
         node_->RemoveComponent(this);
 }
 
+bool Component::IsReplicated() const
+{
+    return id_ < FIRST_LOCAL_ID;
+}
+
 Scene* Component::GetScene() const
 {
     return node_ ? node_->GetScene() : nullptr;

+ 4 - 2
Source/Urho3D/Scene/Component.h

@@ -78,6 +78,8 @@ public:
 
     /// Return ID.
     unsigned GetID() const { return id_; }
+    /// Return whether the component is replicated or local to a scene.
+    bool IsReplicated() const;
 
     /// Return scene node.
     Node* GetNode() const { return node_; }
@@ -87,9 +89,9 @@ public:
 
     /// Return whether is enabled.
     bool IsEnabled() const { return enabled_; }
-
-    /// Return whether is effectively enabled (node is also enabled.)
+    /// Return whether is effectively enabled (node is also enabled).
     bool IsEnabledEffective() const;
+
     /// Return component in the same scene node by type. If there are several, returns the first.
     Component* GetComponent(StringHash type) const;
     /// Return components in the same scene node by type.

+ 19 - 14
Source/Urho3D/Scene/Node.cpp

@@ -283,7 +283,7 @@ void Node::ApplyAttributes()
 
 void Node::MarkNetworkUpdate()
 {
-    if (!networkUpdate_ && scene_ && id_ < FIRST_LOCAL_ID)
+    if (!networkUpdate_ && scene_ && IsReplicated())
     {
         scene_->MarkNetworkUpdate(this);
         networkUpdate_ = true;
@@ -887,9 +887,9 @@ void Node::RemoveChildren(bool removeReplicated, bool removeLocal, bool recursiv
 
         if (recursive)
             childNode->RemoveChildren(removeReplicated, removeLocal, true);
-        if (childNode->GetID() < FIRST_LOCAL_ID && removeReplicated)
+        if (childNode->IsReplicated() && removeReplicated)
             remove = true;
-        else if (childNode->GetID() >= FIRST_LOCAL_ID && removeLocal)
+        else if (!childNode->IsReplicated() && removeLocal)
             remove = true;
 
         if (remove)
@@ -908,7 +908,7 @@ Component* Node::CreateComponent(StringHash type, CreateMode mode, unsigned id)
 {
     // Do not attempt to create replicated components to local nodes, as that may lead to component ID overwrite
     // as replicated components are synced over
-    if (id_ >= FIRST_LOCAL_ID && mode == REPLICATED)
+    if (mode == REPLICATED && !IsReplicated())
         mode = LOCAL;
 
     // Check that creation succeeds and that the object in fact is a component
@@ -940,7 +940,7 @@ Component* Node::CloneComponent(Component* component, unsigned id)
         return nullptr;
     }
 
-    return CloneComponent(component, component->GetID() < FIRST_LOCAL_ID ? REPLICATED : LOCAL, id);
+    return CloneComponent(component, component->IsReplicated() ? REPLICATED : LOCAL, id);
 }
 
 Component* Node::CloneComponent(Component* component, CreateMode mode, unsigned id)
@@ -1033,9 +1033,9 @@ void Node::RemoveComponents(bool removeReplicated, bool removeLocal)
         bool remove = false;
         Component* component = components_[i];
 
-        if (component->GetID() < FIRST_LOCAL_ID && removeReplicated)
+        if (component->IsReplicated() && removeReplicated)
             remove = true;
-        else if (component->GetID() >= FIRST_LOCAL_ID && removeLocal)
+        else if (!component->IsReplicated() && removeLocal)
             remove = true;
 
         if (remove)
@@ -1330,7 +1330,7 @@ unsigned Node::GetNumNetworkComponents() const
     unsigned num = 0;
     for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
     {
-        if ((*i)->GetID() < FIRST_LOCAL_ID)
+        if ((*i)->IsReplicated())
             ++num;
     }
 
@@ -1363,6 +1363,11 @@ bool Node::HasComponent(StringHash type) const
     return false;
 }
 
+bool Node::IsReplicated() const
+{
+    return id_ < FIRST_LOCAL_ID;
+}
+
 bool Node::HasTag(const String& tag) const
 {
     return impl_->tags_.Contains(tag);
@@ -1524,7 +1529,7 @@ const PODVector<unsigned char>& Node::GetNetParentAttr() const
             // Parent is local: traverse hierarchy to find a non-local base node
             // This iteration always stops due to the scene (root) being non-local
             Node* current = parent_;
-            while (current->GetID() >= FIRST_LOCAL_ID)
+            while (!current->IsReplicated())
                 current = current->GetParent();
 
             // Then write the base node ID and the parent's name hash
@@ -1679,7 +1684,7 @@ void Node::PrepareNetworkUpdate()
     if (parent_ && parent_ != scene_)
     {
         Node* current = parent_;
-        while (current->id_ >= FIRST_LOCAL_ID)
+        while (!current->IsReplicated())
             current = current->parent_;
         if (current && current != scene_)
             impl_->dependencyNodes_.Push(current);
@@ -1689,7 +1694,7 @@ void Node::PrepareNetworkUpdate()
     for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
     {
         Component* component = *i;
-        if (component->GetID() < FIRST_LOCAL_ID)
+        if (component->IsReplicated())
             component->GetDependencyNodes(impl_->dependencyNodes_);
     }
 
@@ -2051,7 +2056,7 @@ Component* Node::SafeCreateComponent(const String& typeName, StringHash type, Cr
 {
     // Do not attempt to create replicated components to local nodes, as that may lead to component ID overwrite
     // as replicated components are synced over
-    if (id_ >= FIRST_LOCAL_ID && mode == REPLICATED)
+    if (mode == REPLICATED && !IsReplicated())
         mode = LOCAL;
 
     // First check if factory for type exists
@@ -2169,7 +2174,7 @@ void Node::GetChildrenWithTagRecursive(PODVector<Node*>& dest, const String& tag
 Node* Node::CloneRecursive(Node* parent, SceneResolver& resolver, CreateMode mode)
 {
     // Create clone node
-    Node* cloneNode = parent->CreateChild(0, (mode == REPLICATED && id_ < FIRST_LOCAL_ID) ? REPLICATED : LOCAL);
+    Node* cloneNode = parent->CreateChild(0, (mode == REPLICATED && IsReplicated()) ? REPLICATED : LOCAL);
     resolver.AddNode(id_, cloneNode);
 
     // Copy attributes
@@ -2194,7 +2199,7 @@ Node* Node::CloneRecursive(Node* parent, SceneResolver& resolver, CreateMode mod
             continue;
 
         Component* cloneComponent = cloneNode->CloneComponent(component,
-            (mode == REPLICATED && component->GetID() < FIRST_LOCAL_ID) ? REPLICATED : LOCAL, 0);
+            (mode == REPLICATED && component->IsReplicated()) ? REPLICATED : LOCAL, 0);
         if (cloneComponent)
             resolver.AddComponent(component->GetID(), cloneComponent);
     }

+ 2 - 0
Source/Urho3D/Scene/Node.h

@@ -336,6 +336,8 @@ public:
 
     /// Return ID.
     unsigned GetID() const { return id_; }
+    /// Return whether the node is replicated or local to a scene.
+    bool IsReplicated() const;
 
     /// Return name.
     const String& GetName() const { return impl_->name_; }

+ 4 - 5
Source/Urho3D/Scene/Scene.cpp

@@ -982,7 +982,7 @@ void Scene::NodeRemoved(Node* node)
         return;
 
     unsigned id = node->GetID();
-    if (id < FIRST_LOCAL_ID)
+    if (node->IsReplicated())
     {
         replicatedNodes_.Erase(id);
         MarkReplicationDirty(node);
@@ -1055,7 +1055,7 @@ void Scene::ComponentRemoved(Component* component)
         return;
 
     unsigned id = component->GetID();
-    if (id < FIRST_LOCAL_ID)
+    if (component->IsReplicated())
         replicatedComponents_.Erase(id);
     else
         localComponents_.Erase(id);
@@ -1149,10 +1149,9 @@ void Scene::MarkNetworkUpdate(Component* component)
 
 void Scene::MarkReplicationDirty(Node* node)
 {
-    unsigned id = node->GetID();
-
-    if (id < FIRST_LOCAL_ID && networkState_)
+    if (networkState_ && node->IsReplicated())
     {
+        unsigned id = node->GetID();
         for (PODVector<ReplicationState*>::Iterator i = networkState_->replicationStates_.Begin();
              i != networkState_->replicationStates_.End(); ++i)
         {

+ 24 - 24
bin/Data/Scripts/Editor/EditorHierarchyWindow.as

@@ -476,25 +476,25 @@ String GetNodeTitle(Node@ node)
 
     if (showID)
     {
-        if (node.id >= FIRST_LOCAL_ID)
-            ret += " (Local " + String(node.id) + ")";
-        else
+        if (node.replicated)
             ret += " (" + String(node.id) + ")";
+        else
+            ret += " (Local " + String(node.id) + ")";
 
         if (node.temporary)
             ret += " (Temp)";
     }
-    
+
     return ret;
 }
 
 String GetComponentTitle(Component@ component)
 {
     String ret = component.typeName;
-    
+
     if (showID)
     {
-        if (component.id >= FIRST_LOCAL_ID)
+        if (!component.replicated)
             ret += " (Local)";
 
         if (component.temporary)
@@ -650,7 +650,7 @@ Model@ FindFirstSelectedModel()
                 return sm.model;
         }
     }
-    
+
     return null;
 }
 
@@ -661,16 +661,16 @@ void UpdateModelInfo(Model@ model)
         modelInfoText.text = "";
         return;
     }
-    
+
     String infoStr = "Model: " + model.name;
 
     infoStr += "\n  Morphs: " + model.numMorphs;
-    
+
     for (uint g = 0; g < model.numGeometries; ++g)
     {
         infoStr += "\n  Geometry " + g + "\n    Lods: " + model.numGeometryLodLevels[g];
     }
-    
+
     modelInfoText.text = infoStr;
 }
 
@@ -701,7 +701,7 @@ void HandleHierarchyListSelectionChange()
         else if (type == ITEM_NODE)
         {
             Node@ node = GetListNode(index);
-            if (node !is null) 
+            if (node !is null)
                 selectedNodes.Push(node);
         }
         else if (type == ITEM_UI_ELEMENT)
@@ -711,7 +711,7 @@ void HandleHierarchyListSelectionChange()
                 selectedUIElements.Push(element);
         }
     }
-    
+
     // If only one node/UIElement selected, use it for editing
     if (selectedNodes.length == 1)
         editNode = selectedNodes[0];
@@ -734,7 +734,7 @@ void HandleHierarchyListSelectionChange()
         }
         editNode = commonNode;
     }
-    
+
     UpdateModelInfo(FindFirstSelectedModel());
 
     // Now check if the component(s) can be edited. If many selected, must have same type or have same edit node
@@ -834,10 +834,10 @@ void HandleHierarchyListDoubleClick(StringHash eventType, VariantMap& eventData)
 
     bool isExpanded = hierarchyList.IsExpanded(hierarchyList.selection);
 
-    if (!isExpanded && eventData["Button"].GetInt() == MOUSEB_LEFT) 
+    if (!isExpanded && eventData["Button"].GetInt() == MOUSEB_LEFT)
     {
-        isExpanded = !isExpanded;  
-        hierarchyList.Expand(hierarchyList.selection, isExpanded, false); 
+        isExpanded = !isExpanded;
+        hierarchyList.Expand(hierarchyList.selection, isExpanded, false);
     }
 }
 
@@ -873,7 +873,7 @@ void HandleHierarchyItemClick(StringHash eventType, VariantMap& eventData)
         actions.Push(CreateContextMenuItem("Copy", "HandleHierarchyContextCopy"));
         actions.Push(CreateContextMenuItem("Cut", "HandleHierarchyContextCut"));
         actions.Push(CreateContextMenuItem("Delete", "HandleHierarchyContextDelete"));
-        actions.Push(CreateContextMenuItem("Paste", "HandleHierarchyContextPaste")); 
+        actions.Push(CreateContextMenuItem("Paste", "HandleHierarchyContextPaste"));
         actions.Push(CreateContextMenuItem("Enable/disable", "HandleHierarchyContextEnableDisable"));
 
         /* actions.Push(CreateBrowserFileActionMenu("Edit", "HandleBrowserEditResource", file)); */
@@ -886,7 +886,7 @@ void HandleHierarchyItemClick(StringHash eventType, VariantMap& eventData)
         actions.Push(CreateContextMenuItem("Copy", "HandleHierarchyContextCopy"));
         actions.Push(CreateContextMenuItem("Cut", "HandleHierarchyContextCut"));
         actions.Push(CreateContextMenuItem("Delete", "HandleHierarchyContextDelete"));
-        actions.Push(CreateContextMenuItem("Paste", "HandleHierarchyContextPaste")); 
+        actions.Push(CreateContextMenuItem("Paste", "HandleHierarchyContextPaste"));
         actions.Push(CreateContextMenuItem("Reset to default", "HandleHierarchyContextResetToDefault"));
         actions.Push(CreateContextMenuItem("Reset position", "HandleHierarchyContextResetPosition"));
         actions.Push(CreateContextMenuItem("Reset rotation", "HandleHierarchyContextResetRotation"));
@@ -1030,7 +1030,7 @@ void HandleDragDropFinish(StringHash eventType, VariantMap& eventData)
     {
         Node@ targetNode = editorScene.GetNode(target.vars[NODE_ID_VAR].GetUInt());
         Array<Node@> sourceNodes = GetMultipleSourceNodes(source);
-        
+
         if (sourceNodes.length > 0)
         {
             if (input.qualifierDown[QUAL_CTRL] && sourceNodes.length == 1)
@@ -1707,7 +1707,7 @@ bool BlenderModeDelete()
         actions.Push(CreateContextMenuItem("Delete?", "HandleBlenderModeDelete"));
         actions.Push(CreateContextMenuItem("Cancel", "HandleEmpty"));
 
-        if (actions.length > 0) 
+        if (actions.length > 0)
         {
             ActivateContextMenu(actions);
             return true;
@@ -1853,12 +1853,12 @@ void HandleHierarchyContextDelete()
     Delete();
 }
 
-void HandleBlenderModeDelete() 
+void HandleBlenderModeDelete()
 {
     Delete();
 }
 
-void HandleEmpty() 
+void HandleEmpty()
 {
     //just doing nothing
 }
@@ -1920,7 +1920,7 @@ void CollapseHierarchy()
 
     // only scene's scope expand by default
     hierarchyList.Expand(0, true, false);
-    
+
     hierarchyList.SetSelections(oldSelections);
 }
 
@@ -1929,7 +1929,7 @@ void CollapseHierarchy(StringHash eventType, VariantMap& eventData)
     CollapseHierarchy();
 }
 
-void HandleShowID(StringHash eventType, VariantMap& eventData) 
+void HandleShowID(StringHash eventType, VariantMap& eventData)
 {
     CheckBox@ checkBox = eventData["Element"].GetPtr();
     showID = checkBox.checked;

+ 18 - 18
bin/Data/Scripts/Editor/EditorInspectorWindow.as

@@ -266,10 +266,10 @@ void UpdateAttributeInspector(bool fullUpdate = true)
         if (editNode !is null)
         {
             String idStr;
-            if (editNode.id >= FIRST_LOCAL_ID)
-                idStr = " (Local ID " + String(editNode.id) + ")";
-            else
+            if (editNode.replicated)
                 idStr = " (ID " + String(editNode.id) + ")";
+            else
+                idStr = " (Local ID " + String(editNode.id) + ")";
             nodeType = editNode.typeName;
             nodeTitle.text = nodeType + idStr;
             LineEdit@ tagEdit = parentContainer.GetChild("TagsEdit", true);
@@ -447,7 +447,7 @@ void UpdateAttributeInspectorIcons()
             SetIconEnabledColor(componentTitle, enabledEffective, !hasSameEnabledState);
         }
     }
-    
+
     if (!editUIElements.empty)
     {
         Text@ elementTitle = GetUIElementContainer().GetChild("TitleText");
@@ -478,7 +478,7 @@ bool PreEditAttribute(Array<Serializable@>@ serializables, uint index)
     return true;
 }
 
-/// Call after the attribute values in the target serializables have been edited. 
+/// Call after the attribute values in the target serializables have been edited.
 void PostEditAttribute(Array<Serializable@>@ serializables, uint index, const Array<Variant>& oldValues)
 {
     // Create undo actions for the edits
@@ -507,7 +507,7 @@ void PostEditAttribute(Array<Serializable@>@ serializables, uint index, const Ar
         SetSceneModified();
 }
 
-/// Call after the attribute values in the target serializables have been edited. 
+/// Call after the attribute values in the target serializables have been edited.
 void PostEditAttribute(Serializable@ serializable, uint index)
 {
     // If a StaticModel/AnimatedModel/Skybox model was changed, apply a possibly different material list
@@ -517,7 +517,7 @@ void PostEditAttribute(Serializable@ serializable, uint index)
         if (staticModel !is null)
             staticModel.ApplyMaterialList();
     }
-    
+
     // If a CollisionShape changed the shape type to trimesh or convex, and a collision model is not set,
     // try to get it from a StaticModel in the same node
     if (serializable.typeName == "CollisionShape" && serializable.attributeInfos[index].name == "Shape Type")
@@ -625,7 +625,7 @@ void HandleTagsEdit(StringHash eventType, VariantMap& eventData)
 {
     LineEdit@ lineEdit = eventData["Element"].GetPtr();
     Array<String> tags = lineEdit.text.Split(';');
-    
+
     if (editUIElement !is null)
     {
         editUIElement.RemoveAllTags();
@@ -650,7 +650,7 @@ void HandleTagsSelect(StringHash eventType, VariantMap& eventData)
     {
         // 1. Add established tags from current editable UIElement to menu
         Array<String> elementTags = editUIElement.tags;
-        for (uint i = 0; i < elementTags.length; i++) 
+        for (uint i = 0; i < elementTags.length; i++)
         {
             bool isHasTag = editUIElement.HasTag(elementTags[i]);
             String taggedIndicator = (isHasTag ? Indicator : "");
@@ -659,7 +659,7 @@ void HandleTagsSelect(StringHash eventType, VariantMap& eventData)
 
         // 2. Add default tags
         Array<String> stdTags = defaultTags.Split(';');
-        for (uint i= 0; i < stdTags.length; i++) 
+        for (uint i= 0; i < stdTags.length; i++)
         {
             bool isHasTag = editUIElement.HasTag(stdTags[i]);
             // Add this tag into menu if only Node not tadded with it yet, otherwise it showed on step 1.
@@ -674,7 +674,7 @@ void HandleTagsSelect(StringHash eventType, VariantMap& eventData)
     {
         // 1. Add established tags from Node to menu
         Array<String> nodeTags = editNode.tags;
-        for (uint i = 0; i < nodeTags.length; i++) 
+        for (uint i = 0; i < nodeTags.length; i++)
         {
             bool isHasTag = editNode.HasTag(nodeTags[i]);
             String taggedIndicator = (isHasTag ? Indicator : "");
@@ -707,7 +707,7 @@ void HandleTagsSelect(StringHash eventType, VariantMap& eventData)
             }
         }
     }
-    
+
     // if any action has been added, add also Reset and Cancel and show menu
     if (actions.length > 0)
     {
@@ -715,13 +715,13 @@ void HandleTagsSelect(StringHash eventType, VariantMap& eventData)
         actions.Push(CreateContextMenuItem("Cancel", "HandleTagsMenuSelectionDivisor"));
         ActivateContextMenu(actions);
     }
-    
+
 }
 void HandleTagsMenuSelectionDivisor()
 {
     //do nothing
 }
-void HandleTagsMenuSelection() 
+void HandleTagsMenuSelection()
 {
     Menu@ menu = GetEventSender();
     if (menu is null)
@@ -738,7 +738,7 @@ void HandleTagsMenuSelection()
             UpdateAttributeInspector();
             return;
         }
-        
+
         if (!editUIElement.HasTag(menuSelectedTag))
         {
             editUIElement.AddTag(menuSelectedTag.Trimmed());
@@ -809,7 +809,7 @@ void HandleResetToDefault(StringHash eventType, VariantMap& eventData)
     attributesFullDirty = true;
 }
 
-/// Handle create new user-defined variable event for node target. 
+/// Handle create new user-defined variable event for node target.
 void CreateNodeVariable(StringHash eventType, VariantMap& eventData)
 {
     if (editNodes.empty)
@@ -872,7 +872,7 @@ void DeleteNodeVariable(StringHash eventType, VariantMap& eventData)
                 break;
             }
         }
-        
+
         if (!inUse)
             editorScene.UnregisterVar(delName);
     }
@@ -971,7 +971,7 @@ String GetVarName(StringHash hash)
 
 bool inSetStyleListSelection = false;
 
-/// Select/highlight the matching style in the style drop-down-list based on specified style. 
+/// Select/highlight the matching style in the style drop-down-list based on specified style.
 void SetStyleListSelection(DropDownList@ styleList, const String&in style)
 {
     // Prevent infinite loop upon initial style selection

+ 75 - 75
bin/Data/Scripts/Editor/EditorScene.as

@@ -325,7 +325,7 @@ void CreateComponent(const String&in componentType)
     /// \todo Allow to specify the createmode
     for (uint i = 0; i < editNodes.length; ++i)
     {
-        Component@ newComponent = editNodes[i].CreateComponent(componentType, editNodes[i].id < FIRST_LOCAL_ID ? REPLICATED : LOCAL);
+        Component@ newComponent = editNodes[i].CreateComponent(componentType, editNodes[i].replicated ? REPLICATED : LOCAL);
         if (newComponent !is null)
         {
             // Some components such as CollisionShape do not create their internal object before the first call to ApplyAttributes()
@@ -409,11 +409,11 @@ Node@ InstantiateNodeFromFile(File@ file, const Vector3& position, const Quatern
 
     if (parent !is null)
         newNode.parent = parent;
-        
+
     if (newNode !is null)
     {
         newNode.scale = newNode.scale * scaleMod;
-        
+
         AdjustNodePositionByAABB(newNode);
 
         // Create an undo action for the load
@@ -641,7 +641,7 @@ bool SceneCopy()
             XMLFile@ xml = XMLFile();
             XMLElement rootElem = xml.CreateRoot("component");
             selectedComponents[i].SaveXML(rootElem);
-            rootElem.SetBool("local", selectedComponents[i].id >= FIRST_LOCAL_ID);
+            rootElem.SetBool("local", !selectedComponents[i].replicated);
             sceneCopyBuffer.Push(xml);
         }
     }
@@ -657,7 +657,7 @@ bool SceneCopy()
             XMLFile@ xml = XMLFile();
             XMLElement rootElem = xml.CreateRoot("node");
             selectedNodes[i].SaveXML(rootElem);
-            rootElem.SetBool("local", selectedNodes[i].id >= FIRST_LOCAL_ID);
+            rootElem.SetBool("local", !selectedNodes[i].replicated);
             sceneCopyBuffer.Push(xml);
         }
     }
@@ -794,7 +794,7 @@ bool NodesParentToLastSelected()
 {
     if (lastSelectedNode.Get() is null)
         return false;
-        
+
     if (!CheckHierarchyWindowFocus() || !selectedComponents.empty || selectedNodes.empty)
         return false;
 
@@ -805,17 +805,17 @@ bool NodesParentToLastSelected()
 
     // Parent selected nodes to root
     Array<Node@> changedNodes;
-    
+
     // Find new parent node it selected last
     Node@ lastNode = lastSelectedNode.Get(); //GetListNode(hierarchyList.selection);
-    
+
     for (uint i = 0; i < selectedNodes.length; ++i)
     {
-        
+
         Node@ sourceNode = selectedNodes[i];
         if ( sourceNode.id == lastNode.id)
             continue; // Skip last node it is parent
-        
+
         if (sourceNode.parent.id == lastNode.id)
             continue; // Root or already parented to root
 
@@ -838,20 +838,20 @@ bool NodesParentToLastSelected()
     return true;
 }
 
-bool SceneSmartDuplicateNode() 
-{       
+bool SceneSmartDuplicateNode()
+{
     const float minOffset = 0.1;
-    
-    if (!CheckHierarchyWindowFocus() || !selectedComponents.empty 
+
+    if (!CheckHierarchyWindowFocus() || !selectedComponents.empty
         || selectedNodes.empty || lastSelectedNode.Get() is null)
         return false;
-    
-    
+
+
     Node@ node = lastSelectedNode.Get();
     Node@ parent = node.parent;
     Vector3 offset = Vector3(1,0,0); // default offset
-    
-    if (parent is editorScene) // if parent of selected node is Scene make empty parent for it and place in same position; 
+
+    if (parent is editorScene) // if parent of selected node is Scene make empty parent for it and place in same position;
     {
         parent = CreateNode(LOCAL);
         SceneChangeParent(parent, editorScene, false);
@@ -861,20 +861,20 @@ bool SceneSmartDuplicateNode()
         SceneChangeParent(node, parent, false);
         parent = node.parent;
         SelectNode(node, false);
-    } 
-    
+    }
+
     Vector3 size;
     BoundingBox bb;
-    
-    // get bb for offset  
+
+    // get bb for offset
     Drawable@ drawable = GetFirstDrawable(node);
     if (drawable !is null)
     {
         bb = drawable.boundingBox;
         size =  bb.size * drawable.node.worldScale;
-        offset = Vector3(size.x, 0, 0); 
-    } 
-    
+        offset = Vector3(size.x, 0, 0);
+    }
+
     // make offset on axis that select user by mouse
     if (gizmoAxisX.selected)
     {
@@ -892,10 +892,10 @@ bool SceneSmartDuplicateNode()
         offset = node.worldRotation * Vector3(0,0,size.z);
     }
     else
-        offset = lastOffsetForSmartDuplicate;    
-    
+        offset = lastOffsetForSmartDuplicate;
+
     Vector3 lastInstancePosition = node.worldPosition;
-    
+
     SelectNode(node, false);
     SceneDuplicate();
     Node@ newInstance = parent.children[parent.numChildren-1];
@@ -903,7 +903,7 @@ bool SceneSmartDuplicateNode()
     newInstance.worldPosition = lastInstancePosition;
     newInstance.Translate(offset, TS_WORLD);
     newInstance.name = parent.name + "Instance" + String(parent.numChildren-1);
-    
+
     lastOffsetForSmartDuplicate = offset;
     UpdateNodeAttributes();
     return true;
@@ -913,7 +913,7 @@ bool ViewCloser()
 {
     if (selectedNodes.length > 0 || selectedNodes.length > 0)
         LocateNodesAndComponents(selectedNodes, selectedComponents);
-    
+
     return true;
 }
 
@@ -976,7 +976,7 @@ bool SceneEnableAllNodes()
     // Toggle enabled state of nodes recursively
     Array<Node@> allNodes;
     allNodes = editorScene.GetChildren(true);
-    
+
     for (uint i = 0; i < allNodes.length; ++i)
     {
         // Do not attempt to disable the Scene
@@ -992,10 +992,10 @@ bool SceneEnableAllNodes()
             group.actions.Push(action);
         }
     }
-    
+
     Array<Component@> allComponents;
     allComponents = editorScene.GetComponents();
-    
+
     for (uint i = 0; i < allComponents.length; ++i)
     {
         // Some components purposefully do not expose the Enabled attribute, and it does not affect them in any way
@@ -1135,7 +1135,7 @@ uint SceneFindChildIndex(Node@ parent, Node@ child)
         if (parent.children[i] is child)
             return i;
     }
-    
+
     return -1;
 }
 
@@ -1146,7 +1146,7 @@ uint SceneFindComponentIndex(Node@ node, Component@ component)
         if (node.components[i] is component)
             return i;
     }
-    
+
     return -1;
 }
 
@@ -1333,7 +1333,7 @@ bool SceneRenderZoneCubemaps()
     bool success = false;
     Array<Zone@> capturedThisCall;
     bool alreadyCapturing = activeCubeCapture.length > 0; // May have managed to quickly queue up a second round of zones to render cubemaps for
-    
+
     for (uint i = 0; i < selectedNodes.length; ++i)
     {
         Array<Component@>@ zones = selectedNodes[i].GetComponents("Zone", true);
@@ -1347,7 +1347,7 @@ bool SceneRenderZoneCubemaps()
             }
         }
     }
-    
+
     for (uint i = 0; i < selectedComponents.length; ++i)
     {
         Zone@ zone = cast<Zone>(selectedComponents[i]);
@@ -1360,7 +1360,7 @@ bool SceneRenderZoneCubemaps()
             }
         }
     }
-    
+
     // Start rendering cubemaps if there are any to render and the queue isn't already running
     if (activeCubeCapture.length > 0 && !alreadyCapturing)
         activeCubeCapture[0].Start();
@@ -1396,7 +1396,7 @@ bool SceneAddChildrenStaticModelGroup()
     SaveEditAction(action);
     SetSceneModified();
     FocusComponent(smg);
-    
+
     return true;
 }
 
@@ -1436,7 +1436,7 @@ bool SceneSetChildrenSplinePath(bool makeCycle)
     SaveEditAction(action);
     SetSceneModified();
     FocusComponent(sp);
-    
+
     return true;
 }
 
@@ -1488,7 +1488,7 @@ Drawable@ GetFirstDrawable(Node@ node)
                 return drawable;
         }
     }
-    
+
     return null;
 }
 
@@ -1505,7 +1505,7 @@ void AssignModel(StaticModel@ assignee, String modelPath)
     action.Define(assignee, oldModel, model);
     SaveEditAction(action);
     SetSceneModified();
-    FocusComponent(assignee); 
+    FocusComponent(assignee);
 }
 
 void CreateModelWithStaticModel(String filepath, Node@ parent)
@@ -1547,20 +1547,20 @@ void CreateModelWithAnimatedModel(String filepath, Node@ parent)
 }
 
 bool ColorWheelSetupBehaviorForColoring()
-{    
+{
     Menu@ menu = GetEventSender();
     if (menu is null)
         return false;
-    
+
     coloringPropertyName = menu.name;
-    
+
     if (coloringPropertyName == "menuCancel") return false;
-    
-    if (coloringComponent.typeName == "Light") 
+
+    if (coloringComponent.typeName == "Light")
     {
         Light@ light = cast<Light>(coloringComponent);
-        if (light !is null) 
-        {          
+        if (light !is null)
+        {
             if (coloringPropertyName == "menuLightColor")
             {
                 coloringOldColor = light.color;
@@ -1568,28 +1568,28 @@ bool ColorWheelSetupBehaviorForColoring()
             }
             else if (coloringPropertyName == "menuSpecularIntensity")
             {
-               // ColorWheel have only 0-1 range output of V-value(BW), and for huge-range values we divide in and multiply out 
-               float scaledSpecular = light.specularIntensity * 0.1f; 
+               // ColorWheel have only 0-1 range output of V-value(BW), and for huge-range values we divide in and multiply out
+               float scaledSpecular = light.specularIntensity * 0.1f;
                coloringOldScalar = scaledSpecular;
                ShowColorWheelWithColor(Color(scaledSpecular,scaledSpecular,scaledSpecular));
 
             }
             else if (coloringPropertyName == "menuBrightnessMultiplier")
-            { 
+            {
                float scaledBrightness = light.brightness * 0.1f;
                coloringOldScalar = scaledBrightness;
                ShowColorWheelWithColor(Color(scaledBrightness,scaledBrightness,scaledBrightness));
-            }   
-        }      
+            }
+        }
     }
-    else if (coloringComponent.typeName == "StaticModel") 
+    else if (coloringComponent.typeName == "StaticModel")
     {
         StaticModel@ model  = cast<StaticModel>(coloringComponent);
-        if (model !is null) 
-        {            
+        if (model !is null)
+        {
             Material@ mat = model.materials[0];
-            if (mat !is null) 
-            { 
+            if (mat !is null)
+            {
                 if (coloringPropertyName == "menuDiffuseColor")
                 {
                     Variant oldValue = mat.shaderParameters["MatDiffColor"];
@@ -1610,55 +1610,55 @@ bool ColorWheelSetupBehaviorForColoring()
                     Variant oldValue = mat.shaderParameters["MatEmissiveColor"];
                     Array<String> values = oldValue.ToString().Split(' ');
                     coloringOldColor = Color(values[0].ToFloat(),values[1].ToFloat(),values[2].ToFloat()); // RGB
-                    
-                    
+
+
                     ShowColorWheelWithColor(coloringOldColor);
                 }
                 else if (coloringPropertyName == "menuEnvironmentMapColor")
-                {   
+                {
                     Variant oldValue = mat.shaderParameters["MatEnvMapColor"];
                     Array<String> values = oldValue.ToString().Split(' ');
                     coloringOldColor = Color(values[0].ToFloat(),values[1].ToFloat(),values[2].ToFloat()); //RGB
-                    
+
                     ShowColorWheelWithColor(coloringOldColor);
-                }      
+                }
             }
         }
     }
-    else if (coloringComponent.typeName == "Zone") 
+    else if (coloringComponent.typeName == "Zone")
     {
         Zone@ zone  = cast<Zone>(coloringComponent);
-        if (zone !is null) 
+        if (zone !is null)
         {
             if (coloringPropertyName == "menuAmbientColor")
             {
                 coloringOldColor = zone.ambientColor;
             }
-            else if (coloringPropertyName == "menuFogColor") 
+            else if (coloringPropertyName == "menuFogColor")
             {
                 coloringOldColor = zone.fogColor;
             }
-            
+
             ShowColorWheelWithColor(coloringOldColor);
         }
     }
-    else if (coloringComponent.typeName == "Text3D") 
+    else if (coloringComponent.typeName == "Text3D")
     {
         Text3D@ txt = cast<Text3D>(coloringComponent);
-        if (txt !is null) 
+        if (txt !is null)
         {
             if (coloringPropertyName == "c" || coloringPropertyName == "tl")
                 coloringOldColor = txt.colors[C_TOPLEFT];
-            else if (coloringPropertyName == "tr") 
+            else if (coloringPropertyName == "tr")
                 coloringOldColor = txt.colors[C_TOPRIGHT];
-            else if (coloringPropertyName == "bl") 
+            else if (coloringPropertyName == "bl")
                 coloringOldColor = txt.colors[C_BOTTOMLEFT];
-            else if (coloringPropertyName == "br") 
+            else if (coloringPropertyName == "br")
                 coloringOldColor = txt.colors[C_BOTTOMRIGHT];
-            
+
             ShowColorWheelWithColor(coloringOldColor);
         }
-    }          
+    }
     return true;
 }