1 //
2 // Copyright (c) 2008-2017 the Urho3D project.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 //
22
23 #include "../Precompiled.h"
24
25 #include "../Core/Context.h"
26 #include "../Core/Profiler.h"
27 #include "../IO/Log.h"
28 #include "../IO/MemoryBuffer.h"
29 #include "../Resource/XMLFile.h"
30 #include "../Resource/JSONFile.h"
31 #include "../Scene/Component.h"
32 #include "../Scene/ObjectAnimation.h"
33 #include "../Scene/ReplicationState.h"
34 #include "../Scene/Scene.h"
35 #include "../Scene/SceneEvents.h"
36 #include "../Scene/SmoothedTransform.h"
37 #include "../Scene/UnknownComponent.h"
38
39 #include "../DebugNew.h"
40
41 #ifdef _MSC_VER
42 #pragma warning(disable:6293)
43 #endif
44
45 namespace Urho3D
46 {
47
Node(Context * context)48 Node::Node(Context* context) :
49 Animatable(context),
50 worldTransform_(Matrix3x4::IDENTITY),
51 dirty_(false),
52 enabled_(true),
53 enabledPrev_(true),
54 networkUpdate_(false),
55 parent_(0),
56 scene_(0),
57 id_(0),
58 position_(Vector3::ZERO),
59 rotation_(Quaternion::IDENTITY),
60 scale_(Vector3::ONE),
61 worldRotation_(Quaternion::IDENTITY)
62 {
63 impl_ = new NodeImpl();
64 impl_->owner_ = 0;
65 }
66
~Node()67 Node::~Node()
68 {
69 RemoveAllChildren();
70 RemoveAllComponents();
71
72 // Remove from the scene
73 if (scene_)
74 scene_->NodeRemoved(this);
75 }
76
RegisterObject(Context * context)77 void Node::RegisterObject(Context* context)
78 {
79 context->RegisterFactory<Node>();
80
81 URHO3D_ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
82 URHO3D_ACCESSOR_ATTRIBUTE("Name", GetName, SetName, String, String::EMPTY, AM_DEFAULT);
83 URHO3D_ACCESSOR_ATTRIBUTE("Tags", GetTags, SetTags, StringVector, Variant::emptyStringVector, AM_DEFAULT);
84 URHO3D_ACCESSOR_ATTRIBUTE("Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_FILE);
85 URHO3D_ACCESSOR_ATTRIBUTE("Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE);
86 URHO3D_ACCESSOR_ATTRIBUTE("Scale", GetScale, SetScale, Vector3, Vector3::ONE, AM_DEFAULT);
87 URHO3D_ATTRIBUTE("Variables", VariantMap, vars_, Variant::emptyVariantMap, AM_FILE); // Network replication of vars uses custom data
88 URHO3D_ACCESSOR_ATTRIBUTE("Network Position", GetNetPositionAttr, SetNetPositionAttr, Vector3, Vector3::ZERO,
89 AM_NET | AM_LATESTDATA | AM_NOEDIT);
90 URHO3D_ACCESSOR_ATTRIBUTE("Network Rotation", GetNetRotationAttr, SetNetRotationAttr, PODVector<unsigned char>, Variant::emptyBuffer,
91 AM_NET | AM_LATESTDATA | AM_NOEDIT);
92 URHO3D_ACCESSOR_ATTRIBUTE("Network Parent Node", GetNetParentAttr, SetNetParentAttr, PODVector<unsigned char>, Variant::emptyBuffer,
93 AM_NET | AM_NOEDIT);
94 }
95
Load(Deserializer & source,bool setInstanceDefault)96 bool Node::Load(Deserializer& source, bool setInstanceDefault)
97 {
98 SceneResolver resolver;
99
100 // Read own ID. Will not be applied, only stored for resolving possible references
101 unsigned nodeID = source.ReadUInt();
102 resolver.AddNode(nodeID, this);
103
104 // Read attributes, components and child nodes
105 bool success = Load(source, resolver);
106 if (success)
107 {
108 resolver.Resolve();
109 ApplyAttributes();
110 }
111
112 return success;
113 }
114
Save(Serializer & dest) const115 bool Node::Save(Serializer& dest) const
116 {
117 // Write node ID
118 if (!dest.WriteUInt(id_))
119 return false;
120
121 // Write attributes
122 if (!Animatable::Save(dest))
123 return false;
124
125 // Write components
126 dest.WriteVLE(GetNumPersistentComponents());
127 for (unsigned i = 0; i < components_.Size(); ++i)
128 {
129 Component* component = components_[i];
130 if (component->IsTemporary())
131 continue;
132
133 // Create a separate buffer to be able to skip failing components during deserialization
134 VectorBuffer compBuffer;
135 if (!component->Save(compBuffer))
136 return false;
137 dest.WriteVLE(compBuffer.GetSize());
138 dest.Write(compBuffer.GetData(), compBuffer.GetSize());
139 }
140
141 // Write child nodes
142 dest.WriteVLE(GetNumPersistentChildren());
143 for (unsigned i = 0; i < children_.Size(); ++i)
144 {
145 Node* node = children_[i];
146 if (node->IsTemporary())
147 continue;
148
149 if (!node->Save(dest))
150 return false;
151 }
152
153 return true;
154 }
155
LoadXML(const XMLElement & source,bool setInstanceDefault)156 bool Node::LoadXML(const XMLElement& source, bool setInstanceDefault)
157 {
158 SceneResolver resolver;
159
160 // Read own ID. Will not be applied, only stored for resolving possible references
161 unsigned nodeID = source.GetUInt("id");
162 resolver.AddNode(nodeID, this);
163
164 // Read attributes, components and child nodes
165 bool success = LoadXML(source, resolver);
166 if (success)
167 {
168 resolver.Resolve();
169 ApplyAttributes();
170 }
171
172 return success;
173 }
174
LoadJSON(const JSONValue & source,bool setInstanceDefault)175 bool Node::LoadJSON(const JSONValue& source, bool setInstanceDefault)
176 {
177 SceneResolver resolver;
178
179 // Read own ID. Will not be applied, only stored for resolving possible references
180 unsigned nodeID = source.Get("id").GetUInt();
181 resolver.AddNode(nodeID, this);
182
183 // Read attributes, components and child nodes
184 bool success = LoadJSON(source, resolver);
185 if (success)
186 {
187 resolver.Resolve();
188 ApplyAttributes();
189 }
190
191 return success;
192 }
193
SaveXML(XMLElement & dest) const194 bool Node::SaveXML(XMLElement& dest) const
195 {
196 // Write node ID
197 if (!dest.SetUInt("id", id_))
198 return false;
199
200 // Write attributes
201 if (!Animatable::SaveXML(dest))
202 return false;
203
204 // Write components
205 for (unsigned i = 0; i < components_.Size(); ++i)
206 {
207 Component* component = components_[i];
208 if (component->IsTemporary())
209 continue;
210
211 XMLElement compElem = dest.CreateChild("component");
212 if (!component->SaveXML(compElem))
213 return false;
214 }
215
216 // Write child nodes
217 for (unsigned i = 0; i < children_.Size(); ++i)
218 {
219 Node* node = children_[i];
220 if (node->IsTemporary())
221 continue;
222
223 XMLElement childElem = dest.CreateChild("node");
224 if (!node->SaveXML(childElem))
225 return false;
226 }
227
228 return true;
229 }
230
SaveJSON(JSONValue & dest) const231 bool Node::SaveJSON(JSONValue& dest) const
232 {
233 // Write node ID
234 dest.Set("id", id_);
235
236 // Write attributes
237 if (!Animatable::SaveJSON(dest))
238 return false;
239
240 // Write components
241 JSONArray componentsArray;
242 componentsArray.Reserve(components_.Size());
243 for (unsigned i = 0; i < components_.Size(); ++i)
244 {
245 Component* component = components_[i];
246 if (component->IsTemporary())
247 continue;
248
249 JSONValue compVal;
250 if (!component->SaveJSON(compVal))
251 return false;
252 componentsArray.Push(compVal);
253 }
254 dest.Set("components", componentsArray);
255
256 // Write child nodes
257 JSONArray childrenArray;
258 childrenArray.Reserve(children_.Size());
259 for (unsigned i = 0; i < children_.Size(); ++i)
260 {
261 Node* node = children_[i];
262 if (node->IsTemporary())
263 continue;
264
265 JSONValue childVal;
266 if (!node->SaveJSON(childVal))
267 return false;
268 childrenArray.Push(childVal);
269 }
270 dest.Set("children", childrenArray);
271
272 return true;
273 }
274
ApplyAttributes()275 void Node::ApplyAttributes()
276 {
277 for (unsigned i = 0; i < components_.Size(); ++i)
278 components_[i]->ApplyAttributes();
279
280 for (unsigned i = 0; i < children_.Size(); ++i)
281 children_[i]->ApplyAttributes();
282 }
283
MarkNetworkUpdate()284 void Node::MarkNetworkUpdate()
285 {
286 if (!networkUpdate_ && scene_ && id_ < FIRST_LOCAL_ID)
287 {
288 scene_->MarkNetworkUpdate(this);
289 networkUpdate_ = true;
290 }
291 }
292
AddReplicationState(NodeReplicationState * state)293 void Node::AddReplicationState(NodeReplicationState* state)
294 {
295 if (!networkState_)
296 AllocateNetworkState();
297
298 networkState_->replicationStates_.Push(state);
299 }
300
SaveXML(Serializer & dest,const String & indentation) const301 bool Node::SaveXML(Serializer& dest, const String& indentation) const
302 {
303 SharedPtr<XMLFile> xml(new XMLFile(context_));
304 XMLElement rootElem = xml->CreateRoot("node");
305 if (!SaveXML(rootElem))
306 return false;
307
308 return xml->Save(dest, indentation);
309 }
310
SaveJSON(Serializer & dest,const String & indentation) const311 bool Node::SaveJSON(Serializer& dest, const String& indentation) const
312 {
313 SharedPtr<JSONFile> json(new JSONFile(context_));
314 JSONValue& rootElem = json->GetRoot();
315
316 if (!SaveJSON(rootElem))
317 return false;
318
319 return json->Save(dest, indentation);
320 }
321
SetName(const String & name)322 void Node::SetName(const String& name)
323 {
324 if (name != impl_->name_)
325 {
326 impl_->name_ = name;
327 impl_->nameHash_ = name;
328
329 MarkNetworkUpdate();
330
331 // Send change event
332 if (scene_)
333 {
334 using namespace NodeNameChanged;
335
336 VariantMap& eventData = GetEventDataMap();
337 eventData[P_SCENE] = scene_;
338 eventData[P_NODE] = this;
339
340 scene_->SendEvent(E_NODENAMECHANGED, eventData);
341 }
342 }
343 }
344
SetTags(const StringVector & tags)345 void Node::SetTags(const StringVector& tags)
346 {
347 RemoveAllTags();
348 AddTags(tags);
349 // MarkNetworkUpdate() already called in RemoveAllTags() / AddTags()
350 }
351
AddTag(const String & tag)352 void Node::AddTag(const String& tag)
353 {
354 // Check if tag empty or already added
355 if (tag.Empty() || HasTag(tag))
356 return;
357
358 // Add tag
359 impl_->tags_.Push(tag);
360
361 // Cache
362 scene_->NodeTagAdded(this, tag);
363
364 // Send event
365 using namespace NodeTagAdded;
366 VariantMap& eventData = GetEventDataMap();
367 eventData[P_SCENE] = scene_;
368 eventData[P_NODE] = this;
369 eventData[P_TAG] = tag;
370 scene_->SendEvent(E_NODETAGADDED, eventData);
371
372 // Sync
373 MarkNetworkUpdate();
374 }
375
AddTags(const String & tags,char separator)376 void Node::AddTags(const String& tags, char separator)
377 {
378 StringVector tagVector = tags.Split(separator);
379 AddTags(tagVector);
380 }
381
AddTags(const StringVector & tags)382 void Node::AddTags(const StringVector& tags)
383 {
384 // This is OK, as MarkNetworkUpdate() early-outs when called multiple times
385 for (unsigned i = 0; i < tags.Size(); ++i)
386 AddTag(tags[i]);
387 }
388
RemoveTag(const String & tag)389 bool Node::RemoveTag(const String& tag)
390 {
391 bool removed = impl_->tags_.Remove(tag);
392
393 // Nothing to do
394 if (!removed)
395 return false;
396
397 // Scene cache update
398 if (scene_)
399 {
400 scene_->NodeTagRemoved(this, tag);
401 // Send event
402 using namespace NodeTagRemoved;
403 VariantMap& eventData = GetEventDataMap();
404 eventData[P_SCENE] = scene_;
405 eventData[P_NODE] = this;
406 eventData[P_TAG] = tag;
407 scene_->SendEvent(E_NODETAGREMOVED, eventData);
408 }
409
410 // Sync
411 MarkNetworkUpdate();
412 return true;
413 }
414
RemoveAllTags()415 void Node::RemoveAllTags()
416 {
417 // Clear old scene cache
418 if (scene_)
419 {
420 for (unsigned i = 0; i < impl_->tags_.Size(); ++i)
421 {
422 scene_->NodeTagRemoved(this, impl_->tags_[i]);
423
424 // Send event
425 using namespace NodeTagRemoved;
426 VariantMap& eventData = GetEventDataMap();
427 eventData[P_SCENE] = scene_;
428 eventData[P_NODE] = this;
429 eventData[P_TAG] = impl_->tags_[i];
430 scene_->SendEvent(E_NODETAGREMOVED, eventData);
431 }
432 }
433
434 impl_->tags_.Clear();
435
436 // Sync
437 MarkNetworkUpdate();
438 }
439
SetPosition(const Vector3 & position)440 void Node::SetPosition(const Vector3& position)
441 {
442 position_ = position;
443 MarkDirty();
444
445 MarkNetworkUpdate();
446 }
447
SetRotation(const Quaternion & rotation)448 void Node::SetRotation(const Quaternion& rotation)
449 {
450 rotation_ = rotation;
451 MarkDirty();
452
453 MarkNetworkUpdate();
454 }
455
SetDirection(const Vector3 & direction)456 void Node::SetDirection(const Vector3& direction)
457 {
458 SetRotation(Quaternion(Vector3::FORWARD, direction));
459 }
460
SetScale(float scale)461 void Node::SetScale(float scale)
462 {
463 SetScale(Vector3(scale, scale, scale));
464 }
465
SetScale(const Vector3 & scale)466 void Node::SetScale(const Vector3& scale)
467 {
468 scale_ = scale;
469 // Prevent exact zero scale e.g. from momentary edits as this may cause division by zero
470 // when decomposing the world transform matrix
471 if (scale_.x_ == 0.0f)
472 scale_.x_ = M_EPSILON;
473 if (scale_.y_ == 0.0f)
474 scale_.y_ = M_EPSILON;
475 if (scale_.z_ == 0.0f)
476 scale_.z_ = M_EPSILON;
477
478 MarkDirty();
479 MarkNetworkUpdate();
480 }
481
SetTransform(const Vector3 & position,const Quaternion & rotation)482 void Node::SetTransform(const Vector3& position, const Quaternion& rotation)
483 {
484 position_ = position;
485 rotation_ = rotation;
486 MarkDirty();
487
488 MarkNetworkUpdate();
489 }
490
SetTransform(const Vector3 & position,const Quaternion & rotation,float scale)491 void Node::SetTransform(const Vector3& position, const Quaternion& rotation, float scale)
492 {
493 SetTransform(position, rotation, Vector3(scale, scale, scale));
494 }
495
SetTransform(const Vector3 & position,const Quaternion & rotation,const Vector3 & scale)496 void Node::SetTransform(const Vector3& position, const Quaternion& rotation, const Vector3& scale)
497 {
498 position_ = position;
499 rotation_ = rotation;
500 scale_ = scale;
501 MarkDirty();
502
503 MarkNetworkUpdate();
504 }
505
SetTransform(const Matrix3x4 & matrix)506 void Node::SetTransform(const Matrix3x4& matrix)
507 {
508 SetTransform(matrix.Translation(), matrix.Rotation(), matrix.Scale());
509 }
510
SetWorldPosition(const Vector3 & position)511 void Node::SetWorldPosition(const Vector3& position)
512 {
513 SetPosition((parent_ == scene_ || !parent_) ? position : parent_->GetWorldTransform().Inverse() * position);
514 }
515
SetWorldRotation(const Quaternion & rotation)516 void Node::SetWorldRotation(const Quaternion& rotation)
517 {
518 SetRotation((parent_ == scene_ || !parent_) ? rotation : parent_->GetWorldRotation().Inverse() * rotation);
519 }
520
SetWorldDirection(const Vector3 & direction)521 void Node::SetWorldDirection(const Vector3& direction)
522 {
523 Vector3 localDirection = (parent_ == scene_ || !parent_) ? direction : parent_->GetWorldRotation().Inverse() * direction;
524 SetRotation(Quaternion(Vector3::FORWARD, localDirection));
525 }
526
SetWorldScale(float scale)527 void Node::SetWorldScale(float scale)
528 {
529 SetWorldScale(Vector3(scale, scale, scale));
530 }
531
SetWorldScale(const Vector3 & scale)532 void Node::SetWorldScale(const Vector3& scale)
533 {
534 SetScale((parent_ == scene_ || !parent_) ? scale : scale / parent_->GetWorldScale());
535 }
536
SetWorldTransform(const Vector3 & position,const Quaternion & rotation)537 void Node::SetWorldTransform(const Vector3& position, const Quaternion& rotation)
538 {
539 SetWorldPosition(position);
540 SetWorldRotation(rotation);
541 }
542
SetWorldTransform(const Vector3 & position,const Quaternion & rotation,float scale)543 void Node::SetWorldTransform(const Vector3& position, const Quaternion& rotation, float scale)
544 {
545 SetWorldPosition(position);
546 SetWorldRotation(rotation);
547 SetWorldScale(scale);
548 }
549
SetWorldTransform(const Vector3 & position,const Quaternion & rotation,const Vector3 & scale)550 void Node::SetWorldTransform(const Vector3& position, const Quaternion& rotation, const Vector3& scale)
551 {
552 SetWorldPosition(position);
553 SetWorldRotation(rotation);
554 SetWorldScale(scale);
555 }
556
Translate(const Vector3 & delta,TransformSpace space)557 void Node::Translate(const Vector3& delta, TransformSpace space)
558 {
559 switch (space)
560 {
561 case TS_LOCAL:
562 // Note: local space translation disregards local scale for scale-independent movement speed
563 position_ += rotation_ * delta;
564 break;
565
566 case TS_PARENT:
567 position_ += delta;
568 break;
569
570 case TS_WORLD:
571 position_ += (parent_ == scene_ || !parent_) ? delta : parent_->GetWorldTransform().Inverse() * Vector4(delta, 0.0f);
572 break;
573 }
574
575 MarkDirty();
576
577 MarkNetworkUpdate();
578 }
579
Rotate(const Quaternion & delta,TransformSpace space)580 void Node::Rotate(const Quaternion& delta, TransformSpace space)
581 {
582 switch (space)
583 {
584 case TS_LOCAL:
585 rotation_ = (rotation_ * delta).Normalized();
586 break;
587
588 case TS_PARENT:
589 rotation_ = (delta * rotation_).Normalized();
590 break;
591
592 case TS_WORLD:
593 if (parent_ == scene_ || !parent_)
594 rotation_ = (delta * rotation_).Normalized();
595 else
596 {
597 Quaternion worldRotation = GetWorldRotation();
598 rotation_ = rotation_ * worldRotation.Inverse() * delta * worldRotation;
599 }
600 break;
601 }
602
603 MarkDirty();
604
605 MarkNetworkUpdate();
606 }
607
RotateAround(const Vector3 & point,const Quaternion & delta,TransformSpace space)608 void Node::RotateAround(const Vector3& point, const Quaternion& delta, TransformSpace space)
609 {
610 Vector3 parentSpacePoint;
611 Quaternion oldRotation = rotation_;
612
613 switch (space)
614 {
615 case TS_LOCAL:
616 parentSpacePoint = GetTransform() * point;
617 rotation_ = (rotation_ * delta).Normalized();
618 break;
619
620 case TS_PARENT:
621 parentSpacePoint = point;
622 rotation_ = (delta * rotation_).Normalized();
623 break;
624
625 case TS_WORLD:
626 if (parent_ == scene_ || !parent_)
627 {
628 parentSpacePoint = point;
629 rotation_ = (delta * rotation_).Normalized();
630 }
631 else
632 {
633 parentSpacePoint = parent_->GetWorldTransform().Inverse() * point;
634 Quaternion worldRotation = GetWorldRotation();
635 rotation_ = rotation_ * worldRotation.Inverse() * delta * worldRotation;
636 }
637 break;
638 }
639
640 Vector3 oldRelativePos = oldRotation.Inverse() * (position_ - parentSpacePoint);
641 position_ = rotation_ * oldRelativePos + parentSpacePoint;
642
643 MarkDirty();
644
645 MarkNetworkUpdate();
646 }
647
Yaw(float angle,TransformSpace space)648 void Node::Yaw(float angle, TransformSpace space)
649 {
650 Rotate(Quaternion(angle, Vector3::UP), space);
651 }
652
Pitch(float angle,TransformSpace space)653 void Node::Pitch(float angle, TransformSpace space)
654 {
655 Rotate(Quaternion(angle, Vector3::RIGHT), space);
656 }
657
Roll(float angle,TransformSpace space)658 void Node::Roll(float angle, TransformSpace space)
659 {
660 Rotate(Quaternion(angle, Vector3::FORWARD), space);
661 }
662
LookAt(const Vector3 & target,const Vector3 & up,TransformSpace space)663 bool Node::LookAt(const Vector3& target, const Vector3& up, TransformSpace space)
664 {
665 Vector3 worldSpaceTarget;
666
667 switch (space)
668 {
669 case TS_LOCAL:
670 worldSpaceTarget = GetWorldTransform() * target;
671 break;
672
673 case TS_PARENT:
674 worldSpaceTarget = (parent_ == scene_ || !parent_) ? target : parent_->GetWorldTransform() * target;
675 break;
676
677 case TS_WORLD:
678 worldSpaceTarget = target;
679 break;
680 }
681
682 Vector3 lookDir = worldSpaceTarget - GetWorldPosition();
683 // Check if target is very close, in that case can not reliably calculate lookat direction
684 if (lookDir.Equals(Vector3::ZERO))
685 return false;
686 Quaternion newRotation;
687 // Do nothing if setting look rotation failed
688 if (!newRotation.FromLookRotation(lookDir, up))
689 return false;
690
691 SetWorldRotation(newRotation);
692 return true;
693 }
694
Scale(float scale)695 void Node::Scale(float scale)
696 {
697 Scale(Vector3(scale, scale, scale));
698 }
699
Scale(const Vector3 & scale)700 void Node::Scale(const Vector3& scale)
701 {
702 scale_ *= scale;
703 MarkDirty();
704
705 MarkNetworkUpdate();
706 }
707
SetEnabled(bool enable)708 void Node::SetEnabled(bool enable)
709 {
710 SetEnabled(enable, false, true);
711 }
712
SetDeepEnabled(bool enable)713 void Node::SetDeepEnabled(bool enable)
714 {
715 SetEnabled(enable, true, false);
716 }
717
ResetDeepEnabled()718 void Node::ResetDeepEnabled()
719 {
720 SetEnabled(enabledPrev_, false, false);
721
722 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
723 (*i)->ResetDeepEnabled();
724 }
725
SetEnabledRecursive(bool enable)726 void Node::SetEnabledRecursive(bool enable)
727 {
728 SetEnabled(enable, true, true);
729 }
730
SetOwner(Connection * owner)731 void Node::SetOwner(Connection* owner)
732 {
733 impl_->owner_ = owner;
734 }
735
MarkDirty()736 void Node::MarkDirty()
737 {
738 Node *cur = this;
739 for (;;)
740 {
741 // Precondition:
742 // a) whenever a node is marked dirty, all its children are marked dirty as well.
743 // b) whenever a node is cleared from being dirty, all its parents must have been
744 // cleared as well.
745 // Therefore if we are recursing here to mark this node dirty, and it already was,
746 // then all children of this node must also be already dirty, and we don't need to
747 // reflag them again.
748 if (cur->dirty_)
749 return;
750 cur->dirty_ = true;
751
752 // Notify listener components first, then mark child nodes
753 for (Vector<WeakPtr<Component> >::Iterator i = cur->listeners_.Begin(); i != cur->listeners_.End();)
754 {
755 Component *c = *i;
756 if (c)
757 {
758 c->OnMarkedDirty(cur);
759 ++i;
760 }
761 // If listener has expired, erase from list (swap with the last element to avoid O(n^2) behavior)
762 else
763 {
764 *i = cur->listeners_.Back();
765 cur->listeners_.Pop();
766 }
767 }
768
769 // Tail call optimization: Don't recurse to mark the first child dirty, but
770 // instead process it in the context of the current function. If there are more
771 // than one child, then recurse to the excess children.
772 Vector<SharedPtr<Node> >::Iterator i = cur->children_.Begin();
773 if (i != cur->children_.End())
774 {
775 Node *next = *i;
776 for (++i; i != cur->children_.End(); ++i)
777 (*i)->MarkDirty();
778 cur = next;
779 }
780 else
781 return;
782 }
783 }
784
CreateChild(const String & name,CreateMode mode,unsigned id,bool temporary)785 Node* Node::CreateChild(const String& name, CreateMode mode, unsigned id, bool temporary)
786 {
787 Node* newNode = CreateChild(id, mode, temporary);
788 newNode->SetName(name);
789 return newNode;
790 }
791
CreateTemporaryChild(const String & name,CreateMode mode,unsigned id)792 Node* Node::CreateTemporaryChild(const String& name, CreateMode mode, unsigned id)
793 {
794 return CreateChild(name, mode, id, true);
795 }
796
AddChild(Node * node,unsigned index)797 void Node::AddChild(Node* node, unsigned index)
798 {
799 // Check for illegal or redundant parent assignment
800 if (!node || node == this || node->parent_ == this)
801 return;
802 // Check for possible cyclic parent assignment
803 if (IsChildOf(node))
804 return;
805
806 // Keep a shared ptr to the node while transferring
807 SharedPtr<Node> nodeShared(node);
808 Node* oldParent = node->parent_;
809 if (oldParent)
810 {
811 // If old parent is in different scene, perform the full removal
812 if (oldParent->GetScene() != scene_)
813 oldParent->RemoveChild(node);
814 else
815 {
816 if (scene_)
817 {
818 // Otherwise do not remove from the scene during reparenting, just send the necessary change event
819 using namespace NodeRemoved;
820
821 VariantMap& eventData = GetEventDataMap();
822 eventData[P_SCENE] = scene_;
823 eventData[P_PARENT] = oldParent;
824 eventData[P_NODE] = node;
825
826 scene_->SendEvent(E_NODEREMOVED, eventData);
827 }
828
829 oldParent->children_.Remove(nodeShared);
830 }
831 }
832
833 // Add to the child vector, then add to the scene if not added yet
834 children_.Insert(index, nodeShared);
835 if (scene_ && node->GetScene() != scene_)
836 scene_->NodeAdded(node);
837
838 node->parent_ = this;
839 node->MarkDirty();
840 node->MarkNetworkUpdate();
841 // If the child node has components, also mark network update on them to ensure they have a valid NetworkState
842 for (Vector<SharedPtr<Component> >::Iterator i = node->components_.Begin(); i != node->components_.End(); ++i)
843 (*i)->MarkNetworkUpdate();
844
845 // Send change event
846 if (scene_)
847 {
848 using namespace NodeAdded;
849
850 VariantMap& eventData = GetEventDataMap();
851 eventData[P_SCENE] = scene_;
852 eventData[P_PARENT] = this;
853 eventData[P_NODE] = node;
854
855 scene_->SendEvent(E_NODEADDED, eventData);
856 }
857 }
858
RemoveChild(Node * node)859 void Node::RemoveChild(Node* node)
860 {
861 if (!node)
862 return;
863
864 for (Vector<SharedPtr<Node> >::Iterator i = children_.Begin(); i != children_.End(); ++i)
865 {
866 if (*i == node)
867 {
868 RemoveChild(i);
869 return;
870 }
871 }
872 }
873
RemoveAllChildren()874 void Node::RemoveAllChildren()
875 {
876 RemoveChildren(true, true, true);
877 }
878
RemoveChildren(bool removeReplicated,bool removeLocal,bool recursive)879 void Node::RemoveChildren(bool removeReplicated, bool removeLocal, bool recursive)
880 {
881 unsigned numRemoved = 0;
882
883 for (unsigned i = children_.Size() - 1; i < children_.Size(); --i)
884 {
885 bool remove = false;
886 Node* childNode = children_[i];
887
888 if (recursive)
889 childNode->RemoveChildren(removeReplicated, removeLocal, true);
890 if (childNode->GetID() < FIRST_LOCAL_ID && removeReplicated)
891 remove = true;
892 else if (childNode->GetID() >= FIRST_LOCAL_ID && removeLocal)
893 remove = true;
894
895 if (remove)
896 {
897 RemoveChild(children_.Begin() + i);
898 ++numRemoved;
899 }
900 }
901
902 // Mark node dirty in all replication states
903 if (numRemoved)
904 MarkReplicationDirty();
905 }
906
CreateComponent(StringHash type,CreateMode mode,unsigned id)907 Component* Node::CreateComponent(StringHash type, CreateMode mode, unsigned id)
908 {
909 // Do not attempt to create replicated components to local nodes, as that may lead to component ID overwrite
910 // as replicated components are synced over
911 if (id_ >= FIRST_LOCAL_ID && mode == REPLICATED)
912 mode = LOCAL;
913
914 // Check that creation succeeds and that the object in fact is a component
915 SharedPtr<Component> newComponent = DynamicCast<Component>(context_->CreateObject(type));
916 if (!newComponent)
917 {
918 URHO3D_LOGERROR("Could not create unknown component type " + type.ToString());
919 return 0;
920 }
921
922 AddComponent(newComponent, id, mode);
923 return newComponent;
924 }
925
GetOrCreateComponent(StringHash type,CreateMode mode,unsigned id)926 Component* Node::GetOrCreateComponent(StringHash type, CreateMode mode, unsigned id)
927 {
928 Component* oldComponent = GetComponent(type);
929 if (oldComponent)
930 return oldComponent;
931 else
932 return CreateComponent(type, mode, id);
933 }
934
CloneComponent(Component * component,unsigned id)935 Component* Node::CloneComponent(Component* component, unsigned id)
936 {
937 if (!component)
938 {
939 URHO3D_LOGERROR("Null source component given for CloneComponent");
940 return 0;
941 }
942
943 return CloneComponent(component, component->GetID() < FIRST_LOCAL_ID ? REPLICATED : LOCAL, id);
944 }
945
CloneComponent(Component * component,CreateMode mode,unsigned id)946 Component* Node::CloneComponent(Component* component, CreateMode mode, unsigned id)
947 {
948 if (!component)
949 {
950 URHO3D_LOGERROR("Null source component given for CloneComponent");
951 return 0;
952 }
953
954 Component* cloneComponent = SafeCreateComponent(component->GetTypeName(), component->GetType(), mode, 0);
955 if (!cloneComponent)
956 {
957 URHO3D_LOGERROR("Could not clone component " + component->GetTypeName());
958 return 0;
959 }
960
961 const Vector<AttributeInfo>* compAttributes = component->GetAttributes();
962 const Vector<AttributeInfo>* cloneAttributes = cloneComponent->GetAttributes();
963
964 if (compAttributes)
965 {
966 for (unsigned i = 0; i < compAttributes->Size() && i < cloneAttributes->Size(); ++i)
967 {
968 const AttributeInfo& attr = compAttributes->At(i);
969 const AttributeInfo& cloneAttr = cloneAttributes->At(i);
970 if (attr.mode_ & AM_FILE)
971 {
972 Variant value;
973 component->OnGetAttribute(attr, value);
974 // Note: when eg. a ScriptInstance component is cloned, its script object attributes are unique and therefore we
975 // can not simply refer to the source component's AttributeInfo
976 cloneComponent->OnSetAttribute(cloneAttr, value);
977 }
978 }
979 cloneComponent->ApplyAttributes();
980 }
981
982 {
983 using namespace ComponentCloned;
984
985 VariantMap& eventData = GetEventDataMap();
986 eventData[P_SCENE] = scene_;
987 eventData[P_COMPONENT] = component;
988 eventData[P_CLONECOMPONENT] = cloneComponent;
989
990 scene_->SendEvent(E_COMPONENTCLONED, eventData);
991 }
992
993 return cloneComponent;
994 }
995
RemoveComponent(Component * component)996 void Node::RemoveComponent(Component* component)
997 {
998 for (Vector<SharedPtr<Component> >::Iterator i = components_.Begin(); i != components_.End(); ++i)
999 {
1000 if (*i == component)
1001 {
1002 RemoveComponent(i);
1003
1004 // Mark node dirty in all replication states
1005 MarkReplicationDirty();
1006 return;
1007 }
1008 }
1009 }
1010
RemoveComponent(StringHash type)1011 void Node::RemoveComponent(StringHash type)
1012 {
1013 for (Vector<SharedPtr<Component> >::Iterator i = components_.Begin(); i != components_.End(); ++i)
1014 {
1015 if ((*i)->GetType() == type)
1016 {
1017 RemoveComponent(i);
1018
1019 // Mark node dirty in all replication states
1020 MarkReplicationDirty();
1021 return;
1022 }
1023 }
1024 }
1025
RemoveComponents(bool removeReplicated,bool removeLocal)1026 void Node::RemoveComponents(bool removeReplicated, bool removeLocal)
1027 {
1028 unsigned numRemoved = 0;
1029
1030 for (unsigned i = components_.Size() - 1; i < components_.Size(); --i)
1031 {
1032 bool remove = false;
1033 Component* component = components_[i];
1034
1035 if (component->GetID() < FIRST_LOCAL_ID && removeReplicated)
1036 remove = true;
1037 else if (component->GetID() >= FIRST_LOCAL_ID && removeLocal)
1038 remove = true;
1039
1040 if (remove)
1041 {
1042 RemoveComponent(components_.Begin() + i);
1043 ++numRemoved;
1044 }
1045 }
1046
1047 // Mark node dirty in all replication states
1048 if (numRemoved)
1049 MarkReplicationDirty();
1050 }
1051
RemoveComponents(StringHash type)1052 void Node::RemoveComponents(StringHash type)
1053 {
1054 unsigned numRemoved = 0;
1055
1056 for (unsigned i = components_.Size() - 1; i < components_.Size(); --i)
1057 {
1058 if (components_[i]->GetType() == type)
1059 {
1060 RemoveComponent(components_.Begin() + i);
1061 ++numRemoved;
1062 }
1063 }
1064
1065 // Mark node dirty in all replication states
1066 if (numRemoved)
1067 MarkReplicationDirty();
1068 }
1069
RemoveAllComponents()1070 void Node::RemoveAllComponents()
1071 {
1072 RemoveComponents(true, true);
1073 }
1074
ReorderComponent(Component * component,unsigned index)1075 void Node::ReorderComponent(Component* component, unsigned index)
1076 {
1077 if (!component || component->GetNode() != this)
1078 return;
1079
1080 for (Vector<SharedPtr<Component> >::Iterator i = components_.Begin(); i != components_.End(); ++i)
1081 {
1082 if (*i == component)
1083 {
1084 // Need shared ptr to insert. Also, prevent destruction when removing first
1085 SharedPtr<Component> componentShared(component);
1086 components_.Erase(i);
1087 components_.Insert(index, componentShared);
1088 return;
1089 }
1090 }
1091 }
1092
Clone(CreateMode mode)1093 Node* Node::Clone(CreateMode mode)
1094 {
1095 // The scene itself can not be cloned
1096 if (this == scene_ || !parent_)
1097 {
1098 URHO3D_LOGERROR("Can not clone node without a parent");
1099 return 0;
1100 }
1101
1102 URHO3D_PROFILE(CloneNode);
1103
1104 SceneResolver resolver;
1105 Node* clone = CloneRecursive(parent_, resolver, mode);
1106 resolver.Resolve();
1107 clone->ApplyAttributes();
1108 return clone;
1109 }
1110
Remove()1111 void Node::Remove()
1112 {
1113 if (parent_)
1114 parent_->RemoveChild(this);
1115 }
1116
SetParent(Node * parent)1117 void Node::SetParent(Node* parent)
1118 {
1119 if (parent)
1120 {
1121 Matrix3x4 oldWorldTransform = GetWorldTransform();
1122
1123 parent->AddChild(this);
1124
1125 if (parent != scene_)
1126 {
1127 Matrix3x4 newTransform = parent->GetWorldTransform().Inverse() * oldWorldTransform;
1128 SetTransform(newTransform.Translation(), newTransform.Rotation(), newTransform.Scale());
1129 }
1130 else
1131 {
1132 // The root node is assumed to have identity transform, so can disregard it
1133 SetTransform(oldWorldTransform.Translation(), oldWorldTransform.Rotation(), oldWorldTransform.Scale());
1134 }
1135 }
1136 }
1137
SetVar(StringHash key,const Variant & value)1138 void Node::SetVar(StringHash key, const Variant& value)
1139 {
1140 vars_[key] = value;
1141 MarkNetworkUpdate();
1142 }
1143
AddListener(Component * component)1144 void Node::AddListener(Component* component)
1145 {
1146 if (!component)
1147 return;
1148
1149 // Check for not adding twice
1150 for (Vector<WeakPtr<Component> >::Iterator i = listeners_.Begin(); i != listeners_.End(); ++i)
1151 {
1152 if (*i == component)
1153 return;
1154 }
1155
1156 listeners_.Push(WeakPtr<Component>(component));
1157 // If the node is currently dirty, notify immediately
1158 if (dirty_)
1159 component->OnMarkedDirty(this);
1160 }
1161
RemoveListener(Component * component)1162 void Node::RemoveListener(Component* component)
1163 {
1164 for (Vector<WeakPtr<Component> >::Iterator i = listeners_.Begin(); i != listeners_.End(); ++i)
1165 {
1166 if (*i == component)
1167 {
1168 listeners_.Erase(i);
1169 return;
1170 }
1171 }
1172 }
1173
GetSignedWorldScale() const1174 Vector3 Node::GetSignedWorldScale() const
1175 {
1176 if (dirty_)
1177 UpdateWorldTransform();
1178
1179 return worldTransform_.SignedScale(worldRotation_.RotationMatrix());
1180 }
1181
LocalToWorld(const Vector3 & position) const1182 Vector3 Node::LocalToWorld(const Vector3& position) const
1183 {
1184 return GetWorldTransform() * position;
1185 }
1186
LocalToWorld(const Vector4 & vector) const1187 Vector3 Node::LocalToWorld(const Vector4& vector) const
1188 {
1189 return GetWorldTransform() * vector;
1190 }
1191
LocalToWorld2D(const Vector2 & vector) const1192 Vector2 Node::LocalToWorld2D(const Vector2& vector) const
1193 {
1194 Vector3 result = LocalToWorld(Vector3(vector));
1195 return Vector2(result.x_, result.y_);
1196 }
1197
WorldToLocal(const Vector3 & position) const1198 Vector3 Node::WorldToLocal(const Vector3& position) const
1199 {
1200 return GetWorldTransform().Inverse() * position;
1201 }
1202
WorldToLocal(const Vector4 & vector) const1203 Vector3 Node::WorldToLocal(const Vector4& vector) const
1204 {
1205 return GetWorldTransform().Inverse() * vector;
1206 }
1207
WorldToLocal2D(const Vector2 & vector) const1208 Vector2 Node::WorldToLocal2D(const Vector2& vector) const
1209 {
1210 Vector3 result = WorldToLocal(Vector3(vector));
1211 return Vector2(result.x_, result.y_);
1212 }
1213
GetNumChildren(bool recursive) const1214 unsigned Node::GetNumChildren(bool recursive) const
1215 {
1216 if (!recursive)
1217 return children_.Size();
1218 else
1219 {
1220 unsigned allChildren = children_.Size();
1221 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
1222 allChildren += (*i)->GetNumChildren(true);
1223
1224 return allChildren;
1225 }
1226 }
1227
GetChildren(PODVector<Node * > & dest,bool recursive) const1228 void Node::GetChildren(PODVector<Node*>& dest, bool recursive) const
1229 {
1230 dest.Clear();
1231
1232 if (!recursive)
1233 {
1234 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
1235 dest.Push(*i);
1236 }
1237 else
1238 GetChildrenRecursive(dest);
1239 }
1240
GetChildren(bool recursive) const1241 PODVector<Node*> Node::GetChildren(bool recursive) const
1242 {
1243 PODVector<Node*> dest;
1244 GetChildren(dest, recursive);
1245 return dest;
1246 }
1247
GetChildrenWithComponent(PODVector<Node * > & dest,StringHash type,bool recursive) const1248 void Node::GetChildrenWithComponent(PODVector<Node*>& dest, StringHash type, bool recursive) const
1249 {
1250 dest.Clear();
1251
1252 if (!recursive)
1253 {
1254 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
1255 {
1256 if ((*i)->HasComponent(type))
1257 dest.Push(*i);
1258 }
1259 }
1260 else
1261 GetChildrenWithComponentRecursive(dest, type);
1262 }
1263
GetChildrenWithComponent(StringHash type,bool recursive) const1264 PODVector<Node*> Node::GetChildrenWithComponent(StringHash type, bool recursive) const
1265 {
1266 PODVector<Node*> dest;
1267 GetChildrenWithComponent(dest, type, recursive);
1268 return dest;
1269 }
1270
GetChildrenWithTag(PODVector<Node * > & dest,const String & tag,bool recursive) const1271 void Node::GetChildrenWithTag(PODVector<Node*>& dest, const String& tag, bool recursive /*= true*/) const
1272 {
1273 dest.Clear();
1274
1275 if (!recursive)
1276 {
1277 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
1278 {
1279 if ((*i)->HasTag(tag))
1280 dest.Push(*i);
1281 }
1282 }
1283 else
1284 GetChildrenWithTagRecursive(dest, tag);
1285 }
1286
GetChildrenWithTag(const String & tag,bool recursive) const1287 PODVector<Node*> Node::GetChildrenWithTag(const String& tag, bool recursive) const
1288 {
1289 PODVector<Node*> dest;
1290 GetChildrenWithTag(dest, tag, recursive);
1291 return dest;
1292 }
1293
GetChild(unsigned index) const1294 Node* Node::GetChild(unsigned index) const
1295 {
1296 return index < children_.Size() ? children_[index].Get() : 0;
1297 }
1298
GetChild(const String & name,bool recursive) const1299 Node* Node::GetChild(const String& name, bool recursive) const
1300 {
1301 return GetChild(StringHash(name), recursive);
1302 }
1303
GetChild(const char * name,bool recursive) const1304 Node* Node::GetChild(const char* name, bool recursive) const
1305 {
1306 return GetChild(StringHash(name), recursive);
1307 }
1308
GetChild(StringHash nameHash,bool recursive) const1309 Node* Node::GetChild(StringHash nameHash, bool recursive) const
1310 {
1311 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
1312 {
1313 if ((*i)->GetNameHash() == nameHash)
1314 return *i;
1315
1316 if (recursive)
1317 {
1318 Node* node = (*i)->GetChild(nameHash, true);
1319 if (node)
1320 return node;
1321 }
1322 }
1323
1324 return 0;
1325 }
1326
GetNumNetworkComponents() const1327 unsigned Node::GetNumNetworkComponents() const
1328 {
1329 unsigned num = 0;
1330 for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
1331 {
1332 if ((*i)->GetID() < FIRST_LOCAL_ID)
1333 ++num;
1334 }
1335
1336 return num;
1337 }
1338
GetComponents(PODVector<Component * > & dest,StringHash type,bool recursive) const1339 void Node::GetComponents(PODVector<Component*>& dest, StringHash type, bool recursive) const
1340 {
1341 dest.Clear();
1342
1343 if (!recursive)
1344 {
1345 for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
1346 {
1347 if ((*i)->GetType() == type)
1348 dest.Push(*i);
1349 }
1350 }
1351 else
1352 GetComponentsRecursive(dest, type);
1353 }
1354
HasComponent(StringHash type) const1355 bool Node::HasComponent(StringHash type) const
1356 {
1357 for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
1358 {
1359 if ((*i)->GetType() == type)
1360 return true;
1361 }
1362 return false;
1363 }
1364
HasTag(const String & tag) const1365 bool Node::HasTag(const String& tag) const
1366 {
1367 return impl_->tags_.Contains(tag);
1368 }
1369
IsChildOf(Node * node) const1370 bool Node::IsChildOf(Node* node) const
1371 {
1372 Node* parent = parent_;
1373 while (parent)
1374 {
1375 if (parent == node)
1376 return true;
1377 parent = parent->parent_;
1378 }
1379 return false;
1380 }
1381
GetVar(StringHash key) const1382 const Variant& Node::GetVar(StringHash key) const
1383 {
1384 VariantMap::ConstIterator i = vars_.Find(key);
1385 return i != vars_.End() ? i->second_ : Variant::EMPTY;
1386 }
1387
GetComponent(StringHash type,bool recursive) const1388 Component* Node::GetComponent(StringHash type, bool recursive) const
1389 {
1390 for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
1391 {
1392 if ((*i)->GetType() == type)
1393 return *i;
1394 }
1395
1396 if (recursive)
1397 {
1398 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
1399 {
1400 Component* component = (*i)->GetComponent(type, true);
1401 if (component)
1402 return component;
1403 }
1404 }
1405
1406 return 0;
1407 }
1408
GetParentComponent(StringHash type,bool fullTraversal) const1409 Component* Node::GetParentComponent(StringHash type, bool fullTraversal) const
1410 {
1411 Node* current = GetParent();
1412 while (current)
1413 {
1414 Component* soughtComponent = current->GetComponent(type);
1415 if (soughtComponent)
1416 return soughtComponent;
1417
1418 if (fullTraversal)
1419 current = current->GetParent();
1420 else
1421 break;
1422 }
1423 return 0;
1424 }
1425
SetID(unsigned id)1426 void Node::SetID(unsigned id)
1427 {
1428 id_ = id;
1429 }
1430
SetScene(Scene * scene)1431 void Node::SetScene(Scene* scene)
1432 {
1433 scene_ = scene;
1434 }
1435
ResetScene()1436 void Node::ResetScene()
1437 {
1438 SetID(0);
1439 SetScene(0);
1440 SetOwner(0);
1441 }
1442
SetNetPositionAttr(const Vector3 & value)1443 void Node::SetNetPositionAttr(const Vector3& value)
1444 {
1445 SmoothedTransform* transform = GetComponent<SmoothedTransform>();
1446 if (transform)
1447 transform->SetTargetPosition(value);
1448 else
1449 SetPosition(value);
1450 }
1451
SetNetRotationAttr(const PODVector<unsigned char> & value)1452 void Node::SetNetRotationAttr(const PODVector<unsigned char>& value)
1453 {
1454 MemoryBuffer buf(value);
1455 SmoothedTransform* transform = GetComponent<SmoothedTransform>();
1456 if (transform)
1457 transform->SetTargetRotation(buf.ReadPackedQuaternion());
1458 else
1459 SetRotation(buf.ReadPackedQuaternion());
1460 }
1461
SetNetParentAttr(const PODVector<unsigned char> & value)1462 void Node::SetNetParentAttr(const PODVector<unsigned char>& value)
1463 {
1464 Scene* scene = GetScene();
1465 if (!scene)
1466 return;
1467
1468 MemoryBuffer buf(value);
1469 // If nothing in the buffer, parent is the root node
1470 if (buf.IsEof())
1471 {
1472 scene->AddChild(this);
1473 return;
1474 }
1475
1476 unsigned baseNodeID = buf.ReadNetID();
1477 Node* baseNode = scene->GetNode(baseNodeID);
1478 if (!baseNode)
1479 {
1480 URHO3D_LOGWARNING("Failed to find parent node " + String(baseNodeID));
1481 return;
1482 }
1483
1484 // If buffer contains just an ID, the parent is replicated and we are done
1485 if (buf.IsEof())
1486 baseNode->AddChild(this);
1487 else
1488 {
1489 // Else the parent is local and we must find it recursively by name hash
1490 StringHash nameHash = buf.ReadStringHash();
1491 Node* parentNode = baseNode->GetChild(nameHash, true);
1492 if (!parentNode)
1493 URHO3D_LOGWARNING("Failed to find parent node with name hash " + nameHash.ToString());
1494 else
1495 parentNode->AddChild(this);
1496 }
1497 }
1498
GetNetPositionAttr() const1499 const Vector3& Node::GetNetPositionAttr() const
1500 {
1501 return position_;
1502 }
1503
GetNetRotationAttr() const1504 const PODVector<unsigned char>& Node::GetNetRotationAttr() const
1505 {
1506 impl_->attrBuffer_.Clear();
1507 impl_->attrBuffer_.WritePackedQuaternion(rotation_);
1508 return impl_->attrBuffer_.GetBuffer();
1509 }
1510
GetNetParentAttr() const1511 const PODVector<unsigned char>& Node::GetNetParentAttr() const
1512 {
1513 impl_->attrBuffer_.Clear();
1514 Scene* scene = GetScene();
1515 if (scene && parent_ && parent_ != scene)
1516 {
1517 // If parent is replicated, can write the ID directly
1518 unsigned parentID = parent_->GetID();
1519 if (parentID < FIRST_LOCAL_ID)
1520 impl_->attrBuffer_.WriteNetID(parentID);
1521 else
1522 {
1523 // Parent is local: traverse hierarchy to find a non-local base node
1524 // This iteration always stops due to the scene (root) being non-local
1525 Node* current = parent_;
1526 while (current->GetID() >= FIRST_LOCAL_ID)
1527 current = current->GetParent();
1528
1529 // Then write the base node ID and the parent's name hash
1530 impl_->attrBuffer_.WriteNetID(current->GetID());
1531 impl_->attrBuffer_.WriteStringHash(parent_->GetNameHash());
1532 }
1533 }
1534
1535 return impl_->attrBuffer_.GetBuffer();
1536 }
1537
Load(Deserializer & source,SceneResolver & resolver,bool readChildren,bool rewriteIDs,CreateMode mode)1538 bool Node::Load(Deserializer& source, SceneResolver& resolver, bool readChildren, bool rewriteIDs, CreateMode mode)
1539 {
1540 // Remove all children and components first in case this is not a fresh load
1541 RemoveAllChildren();
1542 RemoveAllComponents();
1543
1544 // ID has been read at the parent level
1545 if (!Animatable::Load(source))
1546 return false;
1547
1548 unsigned numComponents = source.ReadVLE();
1549 for (unsigned i = 0; i < numComponents; ++i)
1550 {
1551 VectorBuffer compBuffer(source, source.ReadVLE());
1552 StringHash compType = compBuffer.ReadStringHash();
1553 unsigned compID = compBuffer.ReadUInt();
1554
1555 Component* newComponent = SafeCreateComponent(String::EMPTY, compType,
1556 (mode == REPLICATED && compID < FIRST_LOCAL_ID) ? REPLICATED : LOCAL, rewriteIDs ? 0 : compID);
1557 if (newComponent)
1558 {
1559 resolver.AddComponent(compID, newComponent);
1560 // Do not abort if component fails to load, as the component buffer is nested and we can skip to the next
1561 newComponent->Load(compBuffer);
1562 }
1563 }
1564
1565 if (!readChildren)
1566 return true;
1567
1568 unsigned numChildren = source.ReadVLE();
1569 for (unsigned i = 0; i < numChildren; ++i)
1570 {
1571 unsigned nodeID = source.ReadUInt();
1572 Node* newNode = CreateChild(rewriteIDs ? 0 : nodeID, (mode == REPLICATED && nodeID < FIRST_LOCAL_ID) ? REPLICATED :
1573 LOCAL);
1574 resolver.AddNode(nodeID, newNode);
1575 if (!newNode->Load(source, resolver, readChildren, rewriteIDs, mode))
1576 return false;
1577 }
1578
1579 return true;
1580 }
1581
LoadXML(const XMLElement & source,SceneResolver & resolver,bool readChildren,bool rewriteIDs,CreateMode mode)1582 bool Node::LoadXML(const XMLElement& source, SceneResolver& resolver, bool readChildren, bool rewriteIDs, CreateMode mode)
1583 {
1584 // Remove all children and components first in case this is not a fresh load
1585 RemoveAllChildren();
1586 RemoveAllComponents();
1587
1588 if (!Animatable::LoadXML(source))
1589 return false;
1590
1591 XMLElement compElem = source.GetChild("component");
1592 while (compElem)
1593 {
1594 String typeName = compElem.GetAttribute("type");
1595 unsigned compID = compElem.GetUInt("id");
1596 Component* newComponent = SafeCreateComponent(typeName, StringHash(typeName),
1597 (mode == REPLICATED && compID < FIRST_LOCAL_ID) ? REPLICATED : LOCAL, rewriteIDs ? 0 : compID);
1598 if (newComponent)
1599 {
1600 resolver.AddComponent(compID, newComponent);
1601 if (!newComponent->LoadXML(compElem))
1602 return false;
1603 }
1604
1605 compElem = compElem.GetNext("component");
1606 }
1607
1608 if (!readChildren)
1609 return true;
1610
1611 XMLElement childElem = source.GetChild("node");
1612 while (childElem)
1613 {
1614 unsigned nodeID = childElem.GetUInt("id");
1615 Node* newNode = CreateChild(rewriteIDs ? 0 : nodeID, (mode == REPLICATED && nodeID < FIRST_LOCAL_ID) ? REPLICATED :
1616 LOCAL);
1617 resolver.AddNode(nodeID, newNode);
1618 if (!newNode->LoadXML(childElem, resolver, readChildren, rewriteIDs, mode))
1619 return false;
1620
1621 childElem = childElem.GetNext("node");
1622 }
1623
1624 return true;
1625 }
1626
LoadJSON(const JSONValue & source,SceneResolver & resolver,bool readChildren,bool rewriteIDs,CreateMode mode)1627 bool Node::LoadJSON(const JSONValue& source, SceneResolver& resolver, bool readChildren, bool rewriteIDs, CreateMode mode)
1628 {
1629 // Remove all children and components first in case this is not a fresh load
1630 RemoveAllChildren();
1631 RemoveAllComponents();
1632
1633 if (!Animatable::LoadJSON(source))
1634 return false;
1635
1636 const JSONArray& componentsArray = source.Get("components").GetArray();
1637
1638 for (unsigned i = 0; i < componentsArray.Size(); i++)
1639 {
1640 const JSONValue& compVal = componentsArray.At(i);
1641 String typeName = compVal.Get("type").GetString();
1642 unsigned compID = compVal.Get("id").GetUInt();
1643 Component* newComponent = SafeCreateComponent(typeName, StringHash(typeName),
1644 (mode == REPLICATED && compID < FIRST_LOCAL_ID) ? REPLICATED : LOCAL, rewriteIDs ? 0 : compID);
1645 if (newComponent)
1646 {
1647 resolver.AddComponent(compID, newComponent);
1648 if (!newComponent->LoadJSON(compVal))
1649 return false;
1650 }
1651 }
1652
1653 if (!readChildren)
1654 return true;
1655
1656 const JSONArray& childrenArray = source.Get("children").GetArray();
1657 for (unsigned i = 0; i < childrenArray.Size(); i++)
1658 {
1659 const JSONValue& childVal = childrenArray.At(i);
1660
1661 unsigned nodeID = childVal.Get("id").GetUInt();
1662 Node* newNode = CreateChild(rewriteIDs ? 0 : nodeID, (mode == REPLICATED && nodeID < FIRST_LOCAL_ID) ? REPLICATED :
1663 LOCAL);
1664 resolver.AddNode(nodeID, newNode);
1665 if (!newNode->LoadJSON(childVal, resolver, readChildren, rewriteIDs, mode))
1666 return false;
1667 }
1668
1669 return true;
1670 }
1671
PrepareNetworkUpdate()1672 void Node::PrepareNetworkUpdate()
1673 {
1674 // Update dependency nodes list first
1675 impl_->dependencyNodes_.Clear();
1676
1677 // Add the parent node, but if it is local, traverse to the first non-local node
1678 if (parent_ && parent_ != scene_)
1679 {
1680 Node* current = parent_;
1681 while (current->id_ >= FIRST_LOCAL_ID)
1682 current = current->parent_;
1683 if (current && current != scene_)
1684 impl_->dependencyNodes_.Push(current);
1685 }
1686
1687 // Let the components add their dependencies
1688 for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
1689 {
1690 Component* component = *i;
1691 if (component->GetID() < FIRST_LOCAL_ID)
1692 component->GetDependencyNodes(impl_->dependencyNodes_);
1693 }
1694
1695 // Then check for node attribute changes
1696 if (!networkState_)
1697 AllocateNetworkState();
1698
1699 const Vector<AttributeInfo>* attributes = networkState_->attributes_;
1700 unsigned numAttributes = attributes->Size();
1701
1702 // Check for attribute changes
1703 for (unsigned i = 0; i < numAttributes; ++i)
1704 {
1705 const AttributeInfo& attr = attributes->At(i);
1706
1707 if (animationEnabled_ && IsAnimatedNetworkAttribute(attr))
1708 continue;
1709
1710 OnGetAttribute(attr, networkState_->currentValues_[i]);
1711
1712 if (networkState_->currentValues_[i] != networkState_->previousValues_[i])
1713 {
1714 networkState_->previousValues_[i] = networkState_->currentValues_[i];
1715
1716 // Mark the attribute dirty in all replication states that are tracking this node
1717 for (PODVector<ReplicationState*>::Iterator j = networkState_->replicationStates_.Begin();
1718 j != networkState_->replicationStates_.End(); ++j)
1719 {
1720 NodeReplicationState* nodeState = static_cast<NodeReplicationState*>(*j);
1721 nodeState->dirtyAttributes_.Set(i);
1722
1723 // Add node to the dirty set if not added yet
1724 if (!nodeState->markedDirty_)
1725 {
1726 nodeState->markedDirty_ = true;
1727 nodeState->sceneState_->dirtyNodes_.Insert(id_);
1728 }
1729 }
1730 }
1731 }
1732
1733 // Finally check for user var changes
1734 for (VariantMap::ConstIterator i = vars_.Begin(); i != vars_.End(); ++i)
1735 {
1736 VariantMap::ConstIterator j = networkState_->previousVars_.Find(i->first_);
1737 if (j == networkState_->previousVars_.End() || j->second_ != i->second_)
1738 {
1739 networkState_->previousVars_[i->first_] = i->second_;
1740
1741 // Mark the var dirty in all replication states that are tracking this node
1742 for (PODVector<ReplicationState*>::Iterator j = networkState_->replicationStates_.Begin();
1743 j != networkState_->replicationStates_.End(); ++j)
1744 {
1745 NodeReplicationState* nodeState = static_cast<NodeReplicationState*>(*j);
1746 nodeState->dirtyVars_.Insert(i->first_);
1747
1748 if (!nodeState->markedDirty_)
1749 {
1750 nodeState->markedDirty_ = true;
1751 nodeState->sceneState_->dirtyNodes_.Insert(id_);
1752 }
1753 }
1754 }
1755 }
1756
1757 networkUpdate_ = false;
1758 }
1759
CleanupConnection(Connection * connection)1760 void Node::CleanupConnection(Connection* connection)
1761 {
1762 if (impl_->owner_ == connection)
1763 impl_->owner_ = 0;
1764
1765 if (networkState_)
1766 {
1767 for (unsigned i = networkState_->replicationStates_.Size() - 1; i < networkState_->replicationStates_.Size(); --i)
1768 {
1769 if (networkState_->replicationStates_[i]->connection_ == connection)
1770 networkState_->replicationStates_.Erase(i);
1771 }
1772 }
1773 }
1774
MarkReplicationDirty()1775 void Node::MarkReplicationDirty()
1776 {
1777 if (networkState_)
1778 {
1779 for (PODVector<ReplicationState*>::Iterator j = networkState_->replicationStates_.Begin();
1780 j != networkState_->replicationStates_.End(); ++j)
1781 {
1782 NodeReplicationState* nodeState = static_cast<NodeReplicationState*>(*j);
1783 if (!nodeState->markedDirty_)
1784 {
1785 nodeState->markedDirty_ = true;
1786 nodeState->sceneState_->dirtyNodes_.Insert(id_);
1787 }
1788 }
1789 }
1790 }
1791
CreateChild(unsigned id,CreateMode mode,bool temporary)1792 Node* Node::CreateChild(unsigned id, CreateMode mode, bool temporary)
1793 {
1794 SharedPtr<Node> newNode(new Node(context_));
1795 newNode->SetTemporary(temporary);
1796
1797 // If zero ID specified, or the ID is already taken, let the scene assign
1798 if (scene_)
1799 {
1800 if (!id || scene_->GetNode(id))
1801 id = scene_->GetFreeNodeID(mode);
1802 newNode->SetID(id);
1803 }
1804 else
1805 newNode->SetID(id);
1806
1807 AddChild(newNode);
1808 return newNode;
1809 }
1810
AddComponent(Component * component,unsigned id,CreateMode mode)1811 void Node::AddComponent(Component* component, unsigned id, CreateMode mode)
1812 {
1813 if (!component)
1814 return;
1815
1816 components_.Push(SharedPtr<Component>(component));
1817
1818 if (component->GetNode())
1819 URHO3D_LOGWARNING("Component " + component->GetTypeName() + " already belongs to a node!");
1820
1821 component->SetNode(this);
1822
1823 // If zero ID specified, or the ID is already taken, let the scene assign
1824 if (scene_)
1825 {
1826 if (!id || scene_->GetComponent(id))
1827 id = scene_->GetFreeComponentID(mode);
1828 component->SetID(id);
1829 scene_->ComponentAdded(component);
1830 }
1831 else
1832 component->SetID(id);
1833
1834 component->OnMarkedDirty(this);
1835
1836 // Check attributes of the new component on next network update, and mark node dirty in all replication states
1837 component->MarkNetworkUpdate();
1838 MarkNetworkUpdate();
1839 MarkReplicationDirty();
1840
1841 // Send change event
1842 if (scene_)
1843 {
1844 using namespace ComponentAdded;
1845
1846 VariantMap& eventData = GetEventDataMap();
1847 eventData[P_SCENE] = scene_;
1848 eventData[P_NODE] = this;
1849 eventData[P_COMPONENT] = component;
1850
1851 scene_->SendEvent(E_COMPONENTADDED, eventData);
1852 }
1853 }
1854
GetNumPersistentChildren() const1855 unsigned Node::GetNumPersistentChildren() const
1856 {
1857 unsigned ret = 0;
1858
1859 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
1860 {
1861 if (!(*i)->IsTemporary())
1862 ++ret;
1863 }
1864
1865 return ret;
1866 }
1867
GetNumPersistentComponents() const1868 unsigned Node::GetNumPersistentComponents() const
1869 {
1870 unsigned ret = 0;
1871
1872 for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
1873 {
1874 if (!(*i)->IsTemporary())
1875 ++ret;
1876 }
1877
1878 return ret;
1879 }
1880
SetTransformSilent(const Vector3 & position,const Quaternion & rotation,const Vector3 & scale)1881 void Node::SetTransformSilent(const Vector3& position, const Quaternion& rotation, const Vector3& scale)
1882 {
1883 position_ = position;
1884 rotation_ = rotation;
1885 scale_ = scale;
1886 }
1887
OnAttributeAnimationAdded()1888 void Node::OnAttributeAnimationAdded()
1889 {
1890 if (attributeAnimationInfos_.Size() == 1)
1891 SubscribeToEvent(GetScene(), E_ATTRIBUTEANIMATIONUPDATE, URHO3D_HANDLER(Node, HandleAttributeAnimationUpdate));
1892 }
1893
OnAttributeAnimationRemoved()1894 void Node::OnAttributeAnimationRemoved()
1895 {
1896 if (attributeAnimationInfos_.Empty())
1897 UnsubscribeFromEvent(GetScene(), E_ATTRIBUTEANIMATIONUPDATE);
1898 }
1899
FindAttributeAnimationTarget(const String & name,String & outName)1900 Animatable* Node::FindAttributeAnimationTarget(const String& name, String& outName)
1901 {
1902 Vector<String> names = name.Split('/');
1903 // Only attribute name
1904 if (names.Size() == 1)
1905 {
1906 outName = name;
1907 return this;
1908 }
1909 else
1910 {
1911 // Name must in following format: "#0/#1/@component#0/attribute"
1912 Node* node = this;
1913 unsigned i = 0;
1914 for (; i < names.Size() - 1; ++i)
1915 {
1916 if (names[i].Front() != '#')
1917 break;
1918
1919 String name = names[i].Substring(1, names[i].Length() - 1);
1920 char s = name.Front();
1921 if (s >= '0' && s <= '9')
1922 {
1923 unsigned index = ToUInt(name);
1924 node = node->GetChild(index);
1925 }
1926 else
1927 {
1928 node = node->GetChild(name, true);
1929 }
1930
1931 if (!node)
1932 {
1933 URHO3D_LOGERROR("Could not find node by name " + name);
1934 return 0;
1935 }
1936 }
1937
1938 if (i == names.Size() - 1)
1939 {
1940 outName = names.Back();
1941 return node;
1942 }
1943
1944 if (i != names.Size() - 2 || names[i].Front() != '@')
1945 {
1946 URHO3D_LOGERROR("Invalid name " + name);
1947 return 0;
1948 }
1949
1950 String componentName = names[i].Substring(1, names[i].Length() - 1);
1951 Vector<String> componentNames = componentName.Split('#');
1952 if (componentNames.Size() == 1)
1953 {
1954 Component* component = node->GetComponent(StringHash(componentNames.Front()));
1955 if (!component)
1956 {
1957 URHO3D_LOGERROR("Could not find component by name " + name);
1958 return 0;
1959 }
1960
1961 outName = names.Back();
1962 return component;
1963 }
1964 else
1965 {
1966 unsigned index = ToUInt(componentNames[1]);
1967 PODVector<Component*> components;
1968 node->GetComponents(components, StringHash(componentNames.Front()));
1969 if (index >= components.Size())
1970 {
1971 URHO3D_LOGERROR("Could not find component by name " + name);
1972 return 0;
1973 }
1974
1975 outName = names.Back();
1976 return components[index];
1977 }
1978 }
1979 }
1980
SetEnabled(bool enable,bool recursive,bool storeSelf)1981 void Node::SetEnabled(bool enable, bool recursive, bool storeSelf)
1982 {
1983 // The enabled state of the whole scene can not be changed. SetUpdateEnabled() is used instead to start/stop updates.
1984 if (GetType() == Scene::GetTypeStatic())
1985 {
1986 URHO3D_LOGERROR("Can not change enabled state of the Scene");
1987 return;
1988 }
1989
1990 if (storeSelf)
1991 enabledPrev_ = enable;
1992
1993 if (enable != enabled_)
1994 {
1995 enabled_ = enable;
1996 MarkNetworkUpdate();
1997
1998 // Notify listener components of the state change
1999 for (Vector<WeakPtr<Component> >::Iterator i = listeners_.Begin(); i != listeners_.End();)
2000 {
2001 if (*i)
2002 {
2003 (*i)->OnNodeSetEnabled(this);
2004 ++i;
2005 }
2006 // If listener has expired, erase from list
2007 else
2008 i = listeners_.Erase(i);
2009 }
2010
2011 // Send change event
2012 if (scene_)
2013 {
2014 using namespace NodeEnabledChanged;
2015
2016 VariantMap& eventData = GetEventDataMap();
2017 eventData[P_SCENE] = scene_;
2018 eventData[P_NODE] = this;
2019
2020 scene_->SendEvent(E_NODEENABLEDCHANGED, eventData);
2021 }
2022
2023 for (Vector<SharedPtr<Component> >::Iterator i = components_.Begin(); i != components_.End(); ++i)
2024 {
2025 (*i)->OnSetEnabled();
2026
2027 // Send change event for the component
2028 if (scene_)
2029 {
2030 using namespace ComponentEnabledChanged;
2031
2032 VariantMap& eventData = GetEventDataMap();
2033 eventData[P_SCENE] = scene_;
2034 eventData[P_NODE] = this;
2035 eventData[P_COMPONENT] = (*i);
2036
2037 scene_->SendEvent(E_COMPONENTENABLEDCHANGED, eventData);
2038 }
2039 }
2040 }
2041
2042 if (recursive)
2043 {
2044 for (Vector<SharedPtr<Node> >::Iterator i = children_.Begin(); i != children_.End(); ++i)
2045 (*i)->SetEnabled(enable, recursive, storeSelf);
2046 }
2047 }
2048
SafeCreateComponent(const String & typeName,StringHash type,CreateMode mode,unsigned id)2049 Component* Node::SafeCreateComponent(const String& typeName, StringHash type, CreateMode mode, unsigned id)
2050 {
2051 // Do not attempt to create replicated components to local nodes, as that may lead to component ID overwrite
2052 // as replicated components are synced over
2053 if (id_ >= FIRST_LOCAL_ID && mode == REPLICATED)
2054 mode = LOCAL;
2055
2056 // First check if factory for type exists
2057 if (!context_->GetTypeName(type).Empty())
2058 return CreateComponent(type, mode, id);
2059 else
2060 {
2061 URHO3D_LOGWARNING("Component type " + type.ToString() + " not known, creating UnknownComponent as placeholder");
2062 // Else create as UnknownComponent
2063 SharedPtr<UnknownComponent> newComponent(new UnknownComponent(context_));
2064 if (typeName.Empty() || typeName.StartsWith("Unknown", false))
2065 newComponent->SetType(type);
2066 else
2067 newComponent->SetTypeName(typeName);
2068
2069 AddComponent(newComponent, id, mode);
2070 return newComponent;
2071 }
2072 }
2073
UpdateWorldTransform() const2074 void Node::UpdateWorldTransform() const
2075 {
2076 Matrix3x4 transform = GetTransform();
2077
2078 // Assume the root node (scene) has identity transform
2079 if (parent_ == scene_ || !parent_)
2080 {
2081 worldTransform_ = transform;
2082 worldRotation_ = rotation_;
2083 }
2084 else
2085 {
2086 worldTransform_ = parent_->GetWorldTransform() * transform;
2087 worldRotation_ = parent_->GetWorldRotation() * rotation_;
2088 }
2089
2090 dirty_ = false;
2091 }
2092
RemoveChild(Vector<SharedPtr<Node>>::Iterator i)2093 void Node::RemoveChild(Vector<SharedPtr<Node> >::Iterator i)
2094 {
2095 // Keep a shared pointer to the child about to be removed, to make sure the erase from container completes first. Otherwise
2096 // it would be possible that other child nodes get removed as part of the node's components' cleanup, causing a re-entrant
2097 // erase and a crash
2098 SharedPtr<Node> child(*i);
2099
2100 // Send change event. Do not send when this node is already being destroyed
2101 if (Refs() > 0 && scene_)
2102 {
2103 using namespace NodeRemoved;
2104
2105 VariantMap& eventData = GetEventDataMap();
2106 eventData[P_SCENE] = scene_;
2107 eventData[P_PARENT] = this;
2108 eventData[P_NODE] = child;
2109
2110 scene_->SendEvent(E_NODEREMOVED, eventData);
2111 }
2112
2113 child->parent_ = 0;
2114 child->MarkDirty();
2115 child->MarkNetworkUpdate();
2116 if (scene_)
2117 scene_->NodeRemoved(child);
2118
2119 children_.Erase(i);
2120 }
2121
GetChildrenRecursive(PODVector<Node * > & dest) const2122 void Node::GetChildrenRecursive(PODVector<Node*>& dest) const
2123 {
2124 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
2125 {
2126 Node* node = *i;
2127 dest.Push(node);
2128 if (!node->children_.Empty())
2129 node->GetChildrenRecursive(dest);
2130 }
2131 }
2132
GetChildrenWithComponentRecursive(PODVector<Node * > & dest,StringHash type) const2133 void Node::GetChildrenWithComponentRecursive(PODVector<Node*>& dest, StringHash type) const
2134 {
2135 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
2136 {
2137 Node* node = *i;
2138 if (node->HasComponent(type))
2139 dest.Push(node);
2140 if (!node->children_.Empty())
2141 node->GetChildrenWithComponentRecursive(dest, type);
2142 }
2143 }
2144
GetComponentsRecursive(PODVector<Component * > & dest,StringHash type) const2145 void Node::GetComponentsRecursive(PODVector<Component*>& dest, StringHash type) const
2146 {
2147 for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
2148 {
2149 if ((*i)->GetType() == type)
2150 dest.Push(*i);
2151 }
2152 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
2153 (*i)->GetComponentsRecursive(dest, type);
2154 }
2155
GetChildrenWithTagRecursive(PODVector<Node * > & dest,const String & tag) const2156 void Node::GetChildrenWithTagRecursive(PODVector<Node*>& dest, const String& tag) const
2157 {
2158 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
2159 {
2160 Node* node = *i;
2161 if (node->HasTag(tag))
2162 dest.Push(node);
2163 if (!node->children_.Empty())
2164 node->GetChildrenWithTagRecursive(dest, tag);
2165 }
2166 }
2167
CloneRecursive(Node * parent,SceneResolver & resolver,CreateMode mode)2168 Node* Node::CloneRecursive(Node* parent, SceneResolver& resolver, CreateMode mode)
2169 {
2170 // Create clone node
2171 Node* cloneNode = parent->CreateChild(0, (mode == REPLICATED && id_ < FIRST_LOCAL_ID) ? REPLICATED : LOCAL);
2172 resolver.AddNode(id_, cloneNode);
2173
2174 // Copy attributes
2175 const Vector<AttributeInfo>* attributes = GetAttributes();
2176 for (unsigned j = 0; j < attributes->Size(); ++j)
2177 {
2178 const AttributeInfo& attr = attributes->At(j);
2179 // Do not copy network-only attributes, as they may have unintended side effects
2180 if (attr.mode_ & AM_FILE)
2181 {
2182 Variant value;
2183 OnGetAttribute(attr, value);
2184 cloneNode->OnSetAttribute(attr, value);
2185 }
2186 }
2187
2188 // Clone components
2189 for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
2190 {
2191 Component* component = *i;
2192 if (component->IsTemporary())
2193 continue;
2194
2195 Component* cloneComponent = cloneNode->CloneComponent(component,
2196 (mode == REPLICATED && component->GetID() < FIRST_LOCAL_ID) ? REPLICATED : LOCAL, 0);
2197 if (cloneComponent)
2198 resolver.AddComponent(component->GetID(), cloneComponent);
2199 }
2200
2201 // Clone child nodes recursively
2202 for (Vector<SharedPtr<Node> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
2203 {
2204 Node* node = *i;
2205 if (node->IsTemporary())
2206 continue;
2207
2208 node->CloneRecursive(cloneNode, resolver, mode);
2209 }
2210
2211 {
2212 using namespace NodeCloned;
2213
2214 VariantMap& eventData = GetEventDataMap();
2215 eventData[P_SCENE] = scene_;
2216 eventData[P_NODE] = this;
2217 eventData[P_CLONENODE] = cloneNode;
2218
2219 scene_->SendEvent(E_NODECLONED, eventData);
2220 }
2221
2222 return cloneNode;
2223 }
2224
RemoveComponent(Vector<SharedPtr<Component>>::Iterator i)2225 void Node::RemoveComponent(Vector<SharedPtr<Component> >::Iterator i)
2226 {
2227 // Send node change event. Do not send when already being destroyed
2228 if (Refs() > 0 && scene_)
2229 {
2230 using namespace ComponentRemoved;
2231
2232 VariantMap& eventData = GetEventDataMap();
2233 eventData[P_SCENE] = scene_;
2234 eventData[P_NODE] = this;
2235 eventData[P_COMPONENT] = (*i).Get();
2236
2237 scene_->SendEvent(E_COMPONENTREMOVED, eventData);
2238 }
2239
2240 RemoveListener(*i);
2241 if (scene_)
2242 scene_->ComponentRemoved(*i);
2243 (*i)->SetNode(0);
2244 components_.Erase(i);
2245 }
2246
HandleAttributeAnimationUpdate(StringHash eventType,VariantMap & eventData)2247 void Node::HandleAttributeAnimationUpdate(StringHash eventType, VariantMap& eventData)
2248 {
2249 using namespace AttributeAnimationUpdate;
2250
2251 UpdateAttributeAnimations(eventData[P_TIMESTEP].GetFloat());
2252 }
2253
2254 }
2255