PrefabComponent.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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, 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. 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_);
  40. prefabNode_->LoadXML(xmlfile->GetRoot());
  41. prefabNode_->SetTemporary(true);
  42. prefabNode_->SetPosition(Vector3::ZERO);
  43. prefabNode_->SetRotation(Quaternion::IDENTITY);
  44. // prefabNode_->SetScale(Vector3::ONE);
  45. PODVector<RigidBody*> bodies;
  46. prefabNode_->GetComponents<RigidBody>(bodies, true);
  47. for (unsigned i = 0; i < bodies.Size(); i++)
  48. {
  49. RigidBody* body = bodies[i];
  50. body->SetTransform(body->GetNode()->GetWorldPosition(), body->GetNode()->GetWorldRotation());
  51. }
  52. }
  53. void PrefabComponent::BreakPrefab()
  54. {
  55. if (!node_ || !node_->GetScene())
  56. return;
  57. SharedPtr<PrefabComponent> keepAlive(this);
  58. if (prefabNode_.NotNull())
  59. prefabNode_->SetTemporary(false);
  60. node_->RemoveComponent(this);
  61. }
  62. void PrefabComponent::HandlePrefabChanged(StringHash eventType, VariantMap& eventData)
  63. {
  64. using namespace PrefabChanged;
  65. if (prefabGUID_ != eventData[P_GUID].GetString())
  66. return;
  67. LoadPrefabNode();
  68. }
  69. void PrefabComponent::SetPrefabGUID(const String& guid)
  70. {
  71. assert(prefabNode_.Null());
  72. // ensure to use node_->CreateChild() so in scene, this may be fixed
  73. // with update on https://github.com/urho3d/Urho3D/issues/748
  74. assert(node_);
  75. prefabGUID_ = guid;
  76. prefabNode_ = node_->CreateChild();
  77. if (prefabGUID_.Length())
  78. {
  79. LoadPrefabNode();
  80. }
  81. }
  82. void PrefabComponent::OnNodeSet(Node* node)
  83. {
  84. Component::OnNodeSet(node);
  85. if (!node && prefabNode_.NotNull())
  86. {
  87. // a prefab node might not be temporary is prefab is broken{
  88. if (prefabNode_->IsTemporary())
  89. prefabNode_->Remove();
  90. prefabNode_ = NULL;
  91. }
  92. }
  93. }