PrefabComponent.cpp 4.0 KB

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