// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "SceneObject.h" #include "Engine/Core/Log.h" #include "Engine/Physics/Joints/Joint.h" #include "Engine/Content/Content.h" #include "Engine/Level/Prefabs/Prefab.h" #include "Engine/Scripting/BinaryModule.h" #include "Engine/Scripting/ManagedSerialization.h" #include "Engine/Serialization/ISerializeModifier.h" #include "Engine/Serialization/Serialization.h" void SceneBeginData::OnDone() { for (int32 i = 0; i < JointsToCreate.Count(); i++) { JointsToCreate[i]->Create(); } JointsToCreate.Clear(); } SceneObject::SceneObject(const SpawnParams& params) : Base(params) , _parent(nullptr) , _prefabID(Guid::Empty) , _prefabObjectID(Guid::Empty) { } SceneObject::~SceneObject() { } void SceneObject::LinkPrefab(const Guid& prefabId, const Guid& prefabObjectId) { ASSERT(prefabId.IsValid()); // Link _prefabID = prefabId; _prefabObjectID = prefabObjectId; if (_prefabID.IsValid() && _prefabObjectID.IsValid()) { auto prefab = Content::LoadAsync(_prefabID); if (prefab == nullptr || prefab->WaitForLoaded()) { _prefabID = Guid::Empty; _prefabObjectID = Guid::Empty; LOG(Warning, "Failed to load prefab linked to the actor."); } } } void SceneObject::BreakPrefabLink() { // Invalidate link _prefabID = Guid::Empty; _prefabObjectID = Guid::Empty; } String SceneObject::GetNamePath(Char separatorChar) const { Array names; const Actor* a = dynamic_cast(this); if (!a) a = GetParent(); while (a) { names.Add(a->GetName()); a = a->GetParent(); } if (names.IsEmpty()) return String::Empty; int32 length = names.Count() - 1; for (int32 i = 0; i < names.Count(); i++) length += names[i].Length(); String result; result.ReserveSpace(length); Char* ptr = result.Get(); for (int32 i = names.Count() - 1; i >= 0; i--) { const String& name = names[i]; Platform::MemoryCopy(ptr, name.Get(), name.Length() * sizeof(Char)); ptr += name.Length(); if (i != 0) *ptr++ = separatorChar; } *ptr = 0; return result.ToString(); } void SceneObject::Serialize(SerializeStream& stream, const void* otherObj) { SERIALIZE_GET_OTHER_OBJ(SceneObject); stream.JKEY("ID"); stream.Guid(_id); if (other && HasPrefabLink()) { stream.JKEY("PrefabID"); stream.Guid(_prefabID); stream.JKEY("PrefabObjectID"); stream.Guid(_prefabObjectID); } else { stream.JKEY("TypeName"); stream.String(GetType().Fullname); } if (_parent) { stream.JKEY("ParentID"); stream.Guid(_parent->GetID()); } // Handle C# objects data serialization if (Flags & ObjectFlags::IsManagedType) { stream.JKEY("V"); if (other) { ManagedSerialization::SerializeDiff(stream, GetOrCreateManagedInstance(), other->GetOrCreateManagedInstance()); } else { ManagedSerialization::Serialize(stream, GetOrCreateManagedInstance()); } } // Handle custom scripting objects data serialization if (Flags & ObjectFlags::IsCustomScriptingType) { stream.JKEY("D"); _type.Module->SerializeObject(stream, this, other); } } void SceneObject::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) { // _id is deserialized by Actor/Script impl // _parent is deserialized by Actor/Script impl // _prefabID is deserialized by Actor/Script impl DESERIALIZE_MEMBER(PrefabObjectID, _prefabObjectID); // Handle C# objects data serialization if (Flags & ObjectFlags::IsManagedType) { auto* const v = SERIALIZE_FIND_MEMBER(stream, "V"); if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0) { ManagedSerialization::Deserialize(v->value, GetOrCreateManagedInstance()); } } // Handle custom scripting objects data serialization if (Flags & ObjectFlags::IsCustomScriptingType) { auto* const v = SERIALIZE_FIND_MEMBER(stream, "D"); if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0) { _type.Module->DeserializeObject(v->value, this, modifier); } } }