//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #include "UndoRedo/BsCmdRecordSO.h" #include "Scene/BsSceneObject.h" #include "Scene/BsComponent.h" #include "Serialization/BsMemorySerializer.h" namespace bs { CmdRecordSO::CmdRecordSO(const WString& description, const HSceneObject& sceneObject, bool recordHierarchy) : EditorCommand(description), mSceneObject(sceneObject), mRecordHierarchy(recordHierarchy) , mSerializedObject(nullptr), mSerializedObjectSize(0) { } 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); SPtr commandPtr = bs_shared_ptr(command); UndoRedo::instance().registerCommand(commandPtr); commandPtr->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; SPtr restored = std::static_pointer_cast(serializer.decode(mSerializedObject, mSerializedObjectSize)); EditorUtility::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); } restored->_instantiate(); } 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()); } } bool isInstantiated = !mSceneObject->hasFlag(SOF_DontInstantiate); mSceneObject->_setFlags(SOF_DontInstantiate); MemorySerializer serializer; mSerializedObject = serializer.encode(mSceneObject.get(), mSerializedObjectSize); if (isInstantiated) mSceneObject->_unsetFlags(SOF_DontInstantiate); mSceneObjectProxy = EditorUtility::createProxy(mSceneObject); if (!mRecordHierarchy) { for (UINT32 i = 0; i < numChildren; i++) children[i]->setParent(sceneObject->getHandle()); bs_stack_delete(children, numChildren); } } }