#include "BsCmdRecordSO.h" #include "BsSceneObject.h" #include "BsComponent.h" #include "BsMemorySerializer.h" namespace BansheeEngine { CmdRecordSO::CmdRecordSO(const WString& description, const HSceneObject& sceneObject, bool recordHierarchy) :EditorCommand(description), mSceneObject(sceneObject), mSerializedObject(nullptr), mSerializedObjectSize(0), mRecordHierarchy(recordHierarchy) { } CmdRecordSO::~CmdRecordSO() { mSceneObject = nullptr; clear(); } void CmdRecordSO::clear() { mSerializedObjectSize = 0; if (mSerializedObject != nullptr) { bs_free(mSerializedObject); mSerializedObject = nullptr; } } void CmdRecordSO::execute(const HSceneObject& sceneObject, bool recordHierarchy, const WString& description) { // Register command and commit it CmdRecordSO* command = new (bs_alloc()) CmdRecordSO(description, sceneObject, recordHierarchy); UndoRedo::instance().registerCommand(command); command->commit(); } void CmdRecordSO::commit() { clear(); if (mSceneObject == nullptr || mSceneObject.isDestroyed()) return; recordSO(mSceneObject); } void CmdRecordSO::revert() { if (mSceneObject == nullptr || mSceneObject.isDestroyed()) return; HSceneObject parent = mSceneObject->getParent(); UINT32 numChildren = mSceneObject->getNumChildren(); HSceneObject* children = nullptr; if (!mRecordHierarchy) { children = bs_stack_new(numChildren); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = mSceneObject->getChild(i); children[i] = child; child->setParent(HSceneObject()); } } mSceneObject->destroy(true); GameObjectManager::instance().setDeserializationMode(GODM_RestoreExternal | GODM_UseNewIds); MemorySerializer serializer; std::shared_ptr restored = std::static_pointer_cast(serializer.decode(mSerializedObject, mSerializedObjectSize)); CmdUtility::restoreIds(restored->getHandle(), mSceneObjectProxy); restored->setParent(parent); if (!mRecordHierarchy) { for (UINT32 i = 0; i < numChildren; i++) children[i]->setParent(restored->getHandle()); bs_stack_delete(children, numChildren); } } void CmdRecordSO::recordSO(const HSceneObject& sceneObject) { UINT32 numChildren = mSceneObject->getNumChildren(); HSceneObject* children = nullptr; if (!mRecordHierarchy) { children = bs_stack_new(numChildren); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = mSceneObject->getChild(i); children[i] = child; child->setParent(HSceneObject()); } } MemorySerializer serializer; mSerializedObject = serializer.encode(mSceneObject.get(), mSerializedObjectSize); mSceneObjectProxy = CmdUtility::createProxy(mSceneObject); if (!mRecordHierarchy) { for (UINT32 i = 0; i < numChildren; i++) children[i]->setParent(sceneObject->getHandle()); bs_stack_delete(children, numChildren); } } }