PrefabComponent.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include <Atomic/Core/Context.h>
  2. #include <Atomic/Scene/Node.h>
  3. #include <Atomic/Resource/XMLFile.h>
  4. #include <Atomic/Resource/ResourceCache.h>
  5. #include <Atomic/Resource/ResourceEvents.h>
  6. #include <Atomic/Physics/RigidBody.h>
  7. #include <Atomic/Atomic2D/AnimatedSprite2D.h>
  8. #include "PrefabEvents.h"
  9. #include "PrefabComponent.h"
  10. namespace Atomic
  11. {
  12. PrefabComponent::PrefabComponent(Context* context) :
  13. Component(context)
  14. {
  15. SubscribeToEvent(E_PREFABCHANGED, HANDLER(PrefabComponent, HandlePrefabChanged));
  16. }
  17. PrefabComponent::~PrefabComponent()
  18. {
  19. }
  20. bool PrefabComponent::SavePrefab()
  21. {
  22. using namespace PrefabSave;
  23. VariantMap eventData;
  24. eventData[P_PREFABCOMPONENT] = this;
  25. SendEvent(E_PREFABSAVE, eventData);
  26. return true;
  27. }
  28. void PrefabComponent::UndoPrefab()
  29. {
  30. LoadPrefabNode();
  31. }
  32. void PrefabComponent::RegisterObject(Context* context)
  33. {
  34. context->RegisterFactory<PrefabComponent>();
  35. ACCESSOR_ATTRIBUTE("PrefabGUID", GetPrefabGUID, SetPrefabGUID, String, String::EMPTY, AM_FILE | AM_NOEDIT);
  36. }
  37. void PrefabComponent::LoadPrefabNode()
  38. {
  39. ResourceCache* cache = GetSubsystem<ResourceCache>();
  40. // first look in cache
  41. XMLFile* xmlfile = cache->GetResource<XMLFile>("Cache/" + prefabGUID_, false);
  42. // if not found, could be loading a specific prefab
  43. if (!xmlfile)
  44. xmlfile = cache->GetResource<XMLFile>(prefabGUID_, false);
  45. if (!xmlfile || !node_)
  46. return;
  47. bool temporary = IsTemporary();
  48. unsigned id = GetID();
  49. // We're going to be removed, so keep ourselves alive and
  50. // a reference to node_ as we'll readd
  51. SharedPtr<PrefabComponent> keepAlive(this);
  52. SharedPtr<Node> node(node_);
  53. // store original transform
  54. Vector3 pos = node->GetPosition();
  55. Quaternion rot = node->GetRotation();
  56. Vector3 scale = node->GetScale();
  57. node->LoadXML(xmlfile->GetRoot());
  58. node->SetPosition(pos);
  59. node->SetRotation(rot);
  60. node->SetScale(scale);
  61. // Get the root components of the load node
  62. const Vector<SharedPtr<Component>>& rootComponents = node->GetComponents();
  63. // set all loaded components to be temporary, set all loaded root components and
  64. // direct children to temporary
  65. for (unsigned i = 0; i < rootComponents.Size(); i++)
  66. {
  67. rootComponents.At(i)->SetTemporary(true);
  68. }
  69. const Vector<SharedPtr<Node> >& children = node->GetChildren();
  70. for (unsigned i = 0; i < children.Size(); i++)
  71. {
  72. children.At(i)->SetTemporary(true);
  73. }
  74. // readd via stored node, which is the same as node_ after this add
  75. this->SetTemporary(temporary);
  76. node->AddComponent(this, id, REPLICATED);
  77. #ifdef ATOMIC_3D
  78. // Get all the rigid bodies of the load node
  79. PODVector<RigidBody*> bodies;
  80. node_->GetComponents<RigidBody>(bodies, true);
  81. for (unsigned i = 0; i < bodies.Size(); i++)
  82. {
  83. RigidBody* body = bodies[i];
  84. body->SetTransform(body->GetNode()->GetWorldPosition(), body->GetNode()->GetWorldRotation());
  85. }
  86. #endif
  87. }
  88. void PrefabComponent::BreakPrefab()
  89. {
  90. if (!node_ || !node_->GetScene())
  91. return;
  92. // flip temporary root children and components to break prefab
  93. const Vector<SharedPtr<Component>>& rootComponents = node_->GetComponents();
  94. const Vector<SharedPtr<Node> >& children = node_->GetChildren();
  95. PODVector<Node*> filterNodes;
  96. for (unsigned i = 0; i < rootComponents.Size(); i++)
  97. {
  98. if (rootComponents[i]->IsTemporary())
  99. {
  100. rootComponents[i]->SetTemporary(false);
  101. // Animated sprites contain a temporary node we don't want to save in the prefab
  102. // it would be nice if this was general purpose because have to test this when
  103. // saving a prefab as well
  104. if (rootComponents[i]->GetType() == AnimatedSprite2D::GetTypeStatic())
  105. {
  106. AnimatedSprite2D* asprite = (AnimatedSprite2D*) rootComponents[i].Get();
  107. if (asprite->GetRootNode())
  108. filterNodes.Push(asprite->GetRootNode());
  109. }
  110. }
  111. }
  112. for (unsigned i = 0; i < children.Size(); i++)
  113. {
  114. if (children[i]->IsTemporary() && !filterNodes.Contains(children[i].Get()))
  115. {
  116. children[i]->SetTemporary(false);
  117. }
  118. }
  119. node_->RemoveComponent(this);
  120. }
  121. void PrefabComponent::HandlePrefabChanged(StringHash eventType, VariantMap& eventData)
  122. {
  123. using namespace PrefabChanged;
  124. if (prefabGUID_ != eventData[P_GUID].GetString())
  125. return;
  126. LoadPrefabNode();
  127. }
  128. void PrefabComponent::SetPrefabGUID(const String& guid)
  129. {
  130. prefabGUID_ = guid;
  131. if (prefabGUID_.Length())
  132. {
  133. LoadPrefabNode();
  134. }
  135. }
  136. void PrefabComponent::OnNodeSet(Node* node)
  137. {
  138. Component::OnNodeSet(node);
  139. }
  140. }