Pārlūkot izejas kodu

Merge branch 'preview'
(Last couple of commits incorrectly went to the preview branch)

BearishSun 9 gadi atpakaļ
vecāks
revīzija
e3ebefc413
75 mainītis faili ar 299 papildinājumiem un 59 dzēšanām
  1. BIN
      Data/Editor/GUISkin.asset
  2. BIN
      Data/Editor/Icons/Sprites/sprite_AnimationClipIcon.psd16.asset
  3. BIN
      Data/Editor/Icons/Sprites/sprite_AnimationClipIcon.psd32.asset
  4. BIN
      Data/Editor/Icons/Sprites/sprite_AnimationClipIcon.psd48.asset
  5. BIN
      Data/Editor/Icons/Sprites/sprite_AudioClipIcon.psd16.asset
  6. BIN
      Data/Editor/Icons/Sprites/sprite_AudioClipIcon.psd32.asset
  7. BIN
      Data/Editor/Icons/Sprites/sprite_AudioClipIcon.psd48.asset
  8. BIN
      Data/Editor/Icons/Sprites/sprite_CSharpIcon.psd16.asset
  9. BIN
      Data/Editor/Icons/Sprites/sprite_CSharpIcon.psd32.asset
  10. BIN
      Data/Editor/Icons/Sprites/sprite_CSharpIcon.psd48.asset
  11. BIN
      Data/Editor/Icons/Sprites/sprite_FolderIcon.psd16.asset
  12. BIN
      Data/Editor/Icons/Sprites/sprite_FolderIcon.psd32.asset
  13. BIN
      Data/Editor/Icons/Sprites/sprite_FolderIcon.psd48.asset
  14. BIN
      Data/Editor/Icons/Sprites/sprite_FontIcon.psd16.asset
  15. BIN
      Data/Editor/Icons/Sprites/sprite_FontIcon.psd32.asset
  16. BIN
      Data/Editor/Icons/Sprites/sprite_FontIcon.psd48.asset
  17. BIN
      Data/Editor/Icons/Sprites/sprite_GUISkinIcon.psd16.asset
  18. BIN
      Data/Editor/Icons/Sprites/sprite_GUISkinIcon.psd32.asset
  19. BIN
      Data/Editor/Icons/Sprites/sprite_GUISkinIcon.psd48.asset
  20. BIN
      Data/Editor/Icons/Sprites/sprite_MaterialIcon.psd16.asset
  21. BIN
      Data/Editor/Icons/Sprites/sprite_MaterialIcon.psd32.asset
  22. BIN
      Data/Editor/Icons/Sprites/sprite_MaterialIcon.psd48.asset
  23. BIN
      Data/Editor/Icons/Sprites/sprite_MeshIcon.psd16.asset
  24. BIN
      Data/Editor/Icons/Sprites/sprite_MeshIcon.psd32.asset
  25. BIN
      Data/Editor/Icons/Sprites/sprite_MeshIcon.psd48.asset
  26. BIN
      Data/Editor/Icons/Sprites/sprite_PhysicsMaterialIcon.psd16.asset
  27. BIN
      Data/Editor/Icons/Sprites/sprite_PhysicsMaterialIcon.psd32.asset
  28. BIN
      Data/Editor/Icons/Sprites/sprite_PhysicsMaterialIcon.psd48.asset
  29. BIN
      Data/Editor/Icons/Sprites/sprite_PhysicsMeshIcon.psd16.asset
  30. BIN
      Data/Editor/Icons/Sprites/sprite_PhysicsMeshIcon.psd32.asset
  31. BIN
      Data/Editor/Icons/Sprites/sprite_PhysicsMeshIcon.psd48.asset
  32. BIN
      Data/Editor/Icons/Sprites/sprite_PrefabIcon.psd16.asset
  33. BIN
      Data/Editor/Icons/Sprites/sprite_PrefabIcon.psd32.asset
  34. BIN
      Data/Editor/Icons/Sprites/sprite_PrefabIcon.psd48.asset
  35. BIN
      Data/Editor/Icons/Sprites/sprite_ShaderIcon.psd16.asset
  36. BIN
      Data/Editor/Icons/Sprites/sprite_ShaderIcon.psd32.asset
  37. BIN
      Data/Editor/Icons/Sprites/sprite_ShaderIcon.psd48.asset
  38. BIN
      Data/Editor/Icons/Sprites/sprite_ShaderIncludeIcon.psd16.asset
  39. BIN
      Data/Editor/Icons/Sprites/sprite_ShaderIncludeIcon.psd32.asset
  40. BIN
      Data/Editor/Icons/Sprites/sprite_ShaderIncludeIcon.psd48.asset
  41. BIN
      Data/Editor/Icons/Sprites/sprite_SpriteIcon.psd16.asset
  42. BIN
      Data/Editor/Icons/Sprites/sprite_SpriteIcon.psd32.asset
  43. BIN
      Data/Editor/Icons/Sprites/sprite_SpriteIcon.psd48.asset
  44. BIN
      Data/Editor/Icons/Sprites/sprite_TextIcon.psd16.asset
  45. BIN
      Data/Editor/Icons/Sprites/sprite_TextIcon.psd32.asset
  46. BIN
      Data/Editor/Icons/Sprites/sprite_TextIcon.psd48.asset
  47. BIN
      Data/Editor/Icons/Sprites/sprite_TextureIcon.psd16.asset
  48. BIN
      Data/Editor/Icons/Sprites/sprite_TextureIcon.psd32.asset
  49. BIN
      Data/Editor/Icons/Sprites/sprite_TextureIcon.psd48.asset
  50. BIN
      Data/Editor/ResourceManifest.asset
  51. BIN
      Data/Editor/Timestamp.asset
  52. BIN
      Data/Editor/arial.ttf.asset
  53. BIN
      Data/Editor/arialAA.ttf.asset
  54. BIN
      Data/Engine/GUISkin.asset
  55. BIN
      Data/Engine/ResourceManifest.asset
  56. BIN
      Data/Engine/Timestamp.asset
  57. BIN
      Data/Engine/arial.ttf.asset
  58. 4 2
      Source/BansheeEditor/Include/BsCmdInputFieldValueChange.h
  59. 0 3
      Source/BansheeEditor/Include/BsEditorCommand.h
  60. 5 5
      Source/BansheeEditor/Include/BsUndoRedo.h
  61. 4 2
      Source/BansheeEditor/Source/BsCmdBreakPrefab.cpp
  62. 11 7
      Source/BansheeEditor/Source/BsCmdCloneSO.cpp
  63. 5 3
      Source/BansheeEditor/Source/BsCmdCreateSO.cpp
  64. 4 2
      Source/BansheeEditor/Source/BsCmdDeleteSO.cpp
  65. 5 3
      Source/BansheeEditor/Source/BsCmdInstantiateSO.cpp
  66. 4 2
      Source/BansheeEditor/Source/BsCmdRecordSO.cpp
  67. 8 4
      Source/BansheeEditor/Source/BsCmdReparentSO.cpp
  68. 1 6
      Source/BansheeEditor/Source/BsEditorCommand.cpp
  69. 13 17
      Source/BansheeEditor/Source/BsUndoRedo.cpp
  70. 1 0
      Source/MBansheeEditor/MBansheeEditor.csproj
  71. 3 3
      Source/MBansheeEditor/Utility/SerializedObject.cs
  72. 32 0
      Source/MBansheeEditor/Utility/UndoableCommand.cs
  73. 2 0
      Source/SBansheeEditor/CMakeSources.cmake
  74. 87 0
      Source/SBansheeEditor/Include/BsManagedEditorCommand.h
  75. 110 0
      Source/SBansheeEditor/Source/BsManagedEditorCommand.cpp

BIN
Data/Editor/GUISkin.asset


BIN
Data/Editor/Icons/Sprites/sprite_AnimationClipIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_AnimationClipIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_AnimationClipIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_AudioClipIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_AudioClipIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_AudioClipIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_CSharpIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_CSharpIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_CSharpIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_FolderIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_FolderIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_FolderIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_FontIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_FontIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_FontIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_GUISkinIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_GUISkinIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_GUISkinIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_MaterialIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_MaterialIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_MaterialIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_MeshIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_MeshIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_MeshIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_PhysicsMaterialIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_PhysicsMaterialIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_PhysicsMaterialIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_PhysicsMeshIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_PhysicsMeshIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_PhysicsMeshIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_PrefabIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_PrefabIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_PrefabIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_ShaderIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_ShaderIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_ShaderIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_ShaderIncludeIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_ShaderIncludeIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_ShaderIncludeIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_SpriteIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_SpriteIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_SpriteIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_TextIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_TextIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_TextIcon.psd48.asset


BIN
Data/Editor/Icons/Sprites/sprite_TextureIcon.psd16.asset


BIN
Data/Editor/Icons/Sprites/sprite_TextureIcon.psd32.asset


BIN
Data/Editor/Icons/Sprites/sprite_TextureIcon.psd48.asset


BIN
Data/Editor/ResourceManifest.asset


BIN
Data/Editor/Timestamp.asset


BIN
Data/Editor/arial.ttf.asset


BIN
Data/Editor/arialAA.ttf.asset


BIN
Data/Engine/GUISkin.asset


BIN
Data/Engine/ResourceManifest.asset


BIN
Data/Engine/Timestamp.asset


BIN
Data/Engine/arial.ttf.asset


+ 4 - 2
Source/BansheeEditor/Include/BsCmdInputFieldValueChange.h

@@ -33,8 +33,10 @@ namespace BansheeEngine
 		{
 		{
 			CmdInputFieldValueChange* command = 
 			CmdInputFieldValueChange* command = 
 				new (bs_alloc<CmdInputFieldValueChange>()) CmdInputFieldValueChange(description, inputField, value);
 				new (bs_alloc<CmdInputFieldValueChange>()) CmdInputFieldValueChange(description, inputField, value);
-			UndoRedo::instance().registerCommand(command);
-			command->commit();
+			SPtr<CmdInputFieldValueChange> commandPtr = bs_shared_ptr(command);
+
+			UndoRedo::instance().registerCommand(commandPtr);
+			commandPtr->commit();
 		}
 		}
 
 
 		/** @copydoc EditorCommand::commit */
 		/** @copydoc EditorCommand::commit */

+ 0 - 3
Source/BansheeEditor/Include/BsEditorCommand.h

@@ -26,9 +26,6 @@ namespace BansheeEngine
 		/** Reverts the command, reverting the change previously done with commit(). */
 		/** Reverts the command, reverting the change previously done with commit(). */
 		virtual void revert() { }
 		virtual void revert() { }
 
 
-		/**	Deletes the command. */
-		static void destroy(EditorCommand* command);
-
 	private:
 	private:
 		friend class UndoRedo;
 		friend class UndoRedo;
 
 

+ 5 - 5
Source/BansheeEditor/Include/BsUndoRedo.h

@@ -53,7 +53,7 @@ namespace BansheeEngine
 		void popGroup(const String& name);
 		void popGroup(const String& name);
 
 
 		/**	Registers a new undo command. */
 		/**	Registers a new undo command. */
-		void registerCommand(EditorCommand* command);
+		void registerCommand(const SPtr<EditorCommand>& command);
 
 
 		/**	Returns the unique identifier for the command on top of the undo stack. */
 		/**	Returns the unique identifier for the command on top of the undo stack. */
 		UINT32 getTopCommandId() const;
 		UINT32 getTopCommandId() const;
@@ -70,10 +70,10 @@ namespace BansheeEngine
 
 
 	private:
 	private:
 		/**	Removes the last undo command from the undo stack, and returns it. */
 		/**	Removes the last undo command from the undo stack, and returns it. */
-		EditorCommand* removeLastFromUndoStack();
+		SPtr<EditorCommand> removeLastFromUndoStack();
 
 
 		/**	Adds a new command to the undo stack. */
 		/**	Adds a new command to the undo stack. */
-		void addToUndoStack(EditorCommand* command);
+		void addToUndoStack(const SPtr<EditorCommand>& command);
 
 
 		/**	Removes all entries from the undo stack. */
 		/**	Removes all entries from the undo stack. */
 		void clearUndoStack();
 		void clearUndoStack();
@@ -83,8 +83,8 @@ namespace BansheeEngine
 
 
 		static const UINT32 MAX_STACK_ELEMENTS;
 		static const UINT32 MAX_STACK_ELEMENTS;
 
 
-		EditorCommand** mUndoStack;
-		EditorCommand** mRedoStack;
+		SPtr<EditorCommand>* mUndoStack;
+		SPtr<EditorCommand>* mRedoStack;
 
 
 		UINT32 mUndoStackPtr;
 		UINT32 mUndoStackPtr;
 		UINT32 mUndoNumElements;
 		UINT32 mUndoNumElements;

+ 4 - 2
Source/BansheeEditor/Source/BsCmdBreakPrefab.cpp

@@ -21,8 +21,10 @@ namespace BansheeEngine
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdBreakPrefab* command = new (bs_alloc<CmdBreakPrefab>()) CmdBreakPrefab(description, sceneObject);
 		CmdBreakPrefab* command = new (bs_alloc<CmdBreakPrefab>()) CmdBreakPrefab(description, sceneObject);
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdBreakPrefab> commandPtr = bs_shared_ptr(command);
+
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
 	}
 	}
 
 
 	void CmdBreakPrefab::commit()
 	void CmdBreakPrefab::commit()

+ 11 - 7
Source/BansheeEditor/Source/BsCmdCloneSO.cpp

@@ -20,11 +20,13 @@ namespace BansheeEngine
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdCloneSO* command = new (bs_alloc<CmdCloneSO>()) CmdCloneSO(description, { sceneObject });
 		CmdCloneSO* command = new (bs_alloc<CmdCloneSO>()) CmdCloneSO(description, { sceneObject });
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdCloneSO> commandPtr = bs_shared_ptr(command);
 
 
-		if (command->mClones.size() > 0)
-			return command->mClones[0];
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
+
+		if (commandPtr->mClones.size() > 0)
+			return commandPtr->mClones[0];
 
 
 		return HSceneObject();
 		return HSceneObject();
 	}
 	}
@@ -33,10 +35,12 @@ namespace BansheeEngine
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdCloneSO* command = new (bs_alloc<CmdCloneSO>()) CmdCloneSO(description, sceneObjects);
 		CmdCloneSO* command = new (bs_alloc<CmdCloneSO>()) CmdCloneSO(description, sceneObjects);
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdCloneSO> commandPtr = bs_shared_ptr(command);
+
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
 
 
-		return command->mClones;
+		return commandPtr->mClones;
 	}
 	}
 
 
 	void CmdCloneSO::commit()
 	void CmdCloneSO::commit()

+ 5 - 3
Source/BansheeEditor/Source/BsCmdCreateSO.cpp

@@ -20,10 +20,12 @@ namespace BansheeEngine
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdCreateSO* command = new (bs_alloc<CmdCreateSO>()) CmdCreateSO(description, name, flags);
 		CmdCreateSO* command = new (bs_alloc<CmdCreateSO>()) CmdCreateSO(description, name, flags);
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdCreateSO> commandPtr = bs_shared_ptr(command);
 
 
-		return command->mSceneObject;
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
+
+		return commandPtr->mSceneObject;
 	}
 	}
 
 
 	void CmdCreateSO::commit()
 	void CmdCreateSO::commit()

+ 4 - 2
Source/BansheeEditor/Source/BsCmdDeleteSO.cpp

@@ -36,8 +36,10 @@ namespace BansheeEngine
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdDeleteSO* command = new (bs_alloc<CmdDeleteSO>()) CmdDeleteSO(description, sceneObject);
 		CmdDeleteSO* command = new (bs_alloc<CmdDeleteSO>()) CmdDeleteSO(description, sceneObject);
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdDeleteSO> commandPtr = bs_shared_ptr(command);
+
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
 	}
 	}
 
 
 	void CmdDeleteSO::commit()
 	void CmdDeleteSO::commit()

+ 5 - 3
Source/BansheeEditor/Source/BsCmdInstantiateSO.cpp

@@ -21,10 +21,12 @@ namespace BansheeEngine
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdInstantiateSO* command = new (bs_alloc<CmdInstantiateSO>()) CmdInstantiateSO(description, prefab);
 		CmdInstantiateSO* command = new (bs_alloc<CmdInstantiateSO>()) CmdInstantiateSO(description, prefab);
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdInstantiateSO> commandPtr = bs_shared_ptr(command);
 
 
-		return command->mSceneObject;
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
+
+		return commandPtr->mSceneObject;
 	}
 	}
 
 
 	void CmdInstantiateSO::commit()
 	void CmdInstantiateSO::commit()

+ 4 - 2
Source/BansheeEditor/Source/BsCmdRecordSO.cpp

@@ -35,8 +35,10 @@ namespace BansheeEngine
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdRecordSO* command = new (bs_alloc<CmdRecordSO>()) CmdRecordSO(description, sceneObject, recordHierarchy);
 		CmdRecordSO* command = new (bs_alloc<CmdRecordSO>()) CmdRecordSO(description, sceneObject, recordHierarchy);
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdRecordSO> commandPtr = bs_shared_ptr(command);
+
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
 	}
 	}
 
 
 	void CmdRecordSO::commit()
 	void CmdRecordSO::commit()

+ 8 - 4
Source/BansheeEditor/Source/BsCmdReparentSO.cpp

@@ -19,16 +19,20 @@ namespace BansheeEngine
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdReparentSO* command = new (bs_alloc<CmdReparentSO>()) CmdReparentSO(description, sceneObjects, newParent);
 		CmdReparentSO* command = new (bs_alloc<CmdReparentSO>()) CmdReparentSO(description, sceneObjects, newParent);
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdReparentSO> commandPtr = bs_shared_ptr(command);
+
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
 	}
 	}
 
 
 	void CmdReparentSO::execute(HSceneObject& sceneObject, const HSceneObject& newParent, const WString& description)
 	void CmdReparentSO::execute(HSceneObject& sceneObject, const HSceneObject& newParent, const WString& description)
 	{
 	{
 		// Register command and commit it
 		// Register command and commit it
 		CmdReparentSO* command = new (bs_alloc<CmdReparentSO>()) CmdReparentSO(description, { sceneObject }, newParent);
 		CmdReparentSO* command = new (bs_alloc<CmdReparentSO>()) CmdReparentSO(description, { sceneObject }, newParent);
-		UndoRedo::instance().registerCommand(command);
-		command->commit();
+		SPtr<CmdReparentSO> commandPtr = bs_shared_ptr(command);
+
+		UndoRedo::instance().registerCommand(commandPtr);
+		commandPtr->commit();
 	}
 	}
 
 
 	void CmdReparentSO::commit()
 	void CmdReparentSO::commit()

+ 1 - 6
Source/BansheeEditor/Source/BsEditorCommand.cpp

@@ -5,11 +5,6 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	EditorCommand::EditorCommand(const WString& description)
 	EditorCommand::EditorCommand(const WString& description)
-		:mDescription(description)
+		:mDescription(description), mId(0)
 	{ }
 	{ }
-
-	void EditorCommand::destroy(EditorCommand* command)
-	{
-		bs_delete(command);
-	}
 }
 }

+ 13 - 17
Source/BansheeEditor/Source/BsUndoRedo.cpp

@@ -11,8 +11,8 @@ namespace BansheeEngine
 		: mUndoStack(nullptr), mRedoStack(nullptr), mUndoStackPtr(0), mUndoNumElements(0), mRedoStackPtr(0)
 		: mUndoStack(nullptr), mRedoStack(nullptr), mUndoStackPtr(0), mUndoNumElements(0), mRedoStackPtr(0)
 		, mRedoNumElements(0), mNextCommandId(0)
 		, mRedoNumElements(0), mNextCommandId(0)
 	{
 	{
-		mUndoStack = bs_newN<EditorCommand*>(MAX_STACK_ELEMENTS);
-		mRedoStack = bs_newN<EditorCommand*>(MAX_STACK_ELEMENTS);
+		mUndoStack = bs_newN<SPtr<EditorCommand>>(MAX_STACK_ELEMENTS);
+		mRedoStack = bs_newN<SPtr<EditorCommand>>(MAX_STACK_ELEMENTS);
 	}
 	}
 
 
 	UndoRedo::~UndoRedo()
 	UndoRedo::~UndoRedo()
@@ -28,7 +28,7 @@ namespace BansheeEngine
 		if(mUndoNumElements == 0)
 		if(mUndoNumElements == 0)
 			return;
 			return;
 
 
-		EditorCommand* command = removeLastFromUndoStack();
+		SPtr<EditorCommand> command = removeLastFromUndoStack();
 		
 		
 		mRedoStackPtr = (mRedoStackPtr + 1) % MAX_STACK_ELEMENTS;
 		mRedoStackPtr = (mRedoStackPtr + 1) % MAX_STACK_ELEMENTS;
 		mRedoStack[mRedoStackPtr] = command;
 		mRedoStack[mRedoStackPtr] = command;
@@ -42,7 +42,7 @@ namespace BansheeEngine
 		if(mRedoNumElements == 0)
 		if(mRedoNumElements == 0)
 			return;
 			return;
 
 
-		EditorCommand* command = mRedoStack[mRedoStackPtr];
+		SPtr<EditorCommand> command = mRedoStack[mRedoStackPtr];
 		mRedoStackPtr = (mRedoStackPtr - 1) % MAX_STACK_ELEMENTS;
 		mRedoStackPtr = (mRedoStackPtr - 1) % MAX_STACK_ELEMENTS;
 		mRedoNumElements--;
 		mRedoNumElements--;
 
 
@@ -73,18 +73,16 @@ namespace BansheeEngine
 
 
 		for(UINT32 i = 0; i < topGroup.numEntries; i++)
 		for(UINT32 i = 0; i < topGroup.numEntries; i++)
 		{
 		{
-			EditorCommand* command = mUndoStack[mUndoStackPtr];
+			mUndoStack[mUndoStackPtr] = SPtr<EditorCommand>();
 			mUndoStackPtr = (mUndoStackPtr - 1) % MAX_STACK_ELEMENTS;
 			mUndoStackPtr = (mUndoStackPtr - 1) % MAX_STACK_ELEMENTS;
 			mUndoNumElements--;
 			mUndoNumElements--;
-
-			EditorCommand::destroy(command);
 		}
 		}
 
 
 		mGroups.pop();
 		mGroups.pop();
 		clearRedoStack();
 		clearRedoStack();
 	}
 	}
 
 
-	void UndoRedo::registerCommand(EditorCommand* command)
+	void UndoRedo::registerCommand(const SPtr<EditorCommand>& command)
 	{
 	{
 		command->mId = mNextCommandId++;
 		command->mId = mNextCommandId++;
 		addToUndoStack(command);
 		addToUndoStack(command);
@@ -151,9 +149,11 @@ namespace BansheeEngine
 		clearRedoStack();
 		clearRedoStack();
 	}
 	}
 
 
-	EditorCommand* UndoRedo::removeLastFromUndoStack()
+	SPtr<EditorCommand> UndoRedo::removeLastFromUndoStack()
 	{
 	{
-		EditorCommand* command = mUndoStack[mUndoStackPtr];
+		SPtr<EditorCommand> command = mUndoStack[mUndoStackPtr];
+
+		mUndoStack[mUndoStackPtr] = SPtr<EditorCommand>();
 		mUndoStackPtr = (mUndoStackPtr - 1) % MAX_STACK_ELEMENTS;
 		mUndoStackPtr = (mUndoStackPtr - 1) % MAX_STACK_ELEMENTS;
 		mUndoNumElements--;
 		mUndoNumElements--;
 
 
@@ -173,7 +173,7 @@ namespace BansheeEngine
 		return command;
 		return command;
 	}
 	}
 
 
-	void UndoRedo::addToUndoStack(EditorCommand* command)
+	void UndoRedo::addToUndoStack(const SPtr<EditorCommand>& command)
 	{
 	{
 		mUndoStackPtr = (mUndoStackPtr + 1) % MAX_STACK_ELEMENTS;
 		mUndoStackPtr = (mUndoStackPtr + 1) % MAX_STACK_ELEMENTS;
 		mUndoStack[mUndoStackPtr] = command;
 		mUndoStack[mUndoStackPtr] = command;
@@ -190,11 +190,9 @@ namespace BansheeEngine
 	{
 	{
 		while(mUndoNumElements > 0)
 		while(mUndoNumElements > 0)
 		{
 		{
-			EditorCommand* command = mUndoStack[mUndoStackPtr];
+			mUndoStack[mUndoStackPtr] = SPtr<EditorCommand>();
 			mUndoStackPtr = (mUndoStackPtr - 1) % MAX_STACK_ELEMENTS;
 			mUndoStackPtr = (mUndoStackPtr - 1) % MAX_STACK_ELEMENTS;
 			mUndoNumElements--;
 			mUndoNumElements--;
-
-			EditorCommand::destroy(command);
 		}
 		}
 
 
 		while(!mGroups.empty())
 		while(!mGroups.empty())
@@ -205,11 +203,9 @@ namespace BansheeEngine
 	{
 	{
 		while(mRedoNumElements > 0)
 		while(mRedoNumElements > 0)
 		{
 		{
-			EditorCommand* command = mRedoStack[mRedoStackPtr];
+			mRedoStack[mRedoStackPtr] = SPtr<EditorCommand>();
 			mRedoStackPtr = (mRedoStackPtr - 1) % MAX_STACK_ELEMENTS;
 			mRedoStackPtr = (mRedoStackPtr - 1) % MAX_STACK_ELEMENTS;
 			mRedoNumElements--;
 			mRedoNumElements--;
-
-			EditorCommand::destroy(command);
 		}
 		}
 	}
 	}
 }
 }

+ 1 - 0
Source/MBansheeEditor/MBansheeEditor.csproj

@@ -51,6 +51,7 @@
     <Compile Include="Utility\SerializedSceneObject.cs" />
     <Compile Include="Utility\SerializedSceneObject.cs" />
     <Compile Include="Utility\SerializedDiff.cs" />
     <Compile Include="Utility\SerializedDiff.cs" />
     <Compile Include="Utility\SerializedObject.cs" />
     <Compile Include="Utility\SerializedObject.cs" />
+    <Compile Include="Utility\UndoableCommand.cs" />
     <Compile Include="Windows\AboutBox.cs" />
     <Compile Include="Windows\AboutBox.cs" />
     <Compile Include="Windows\AnimationWindow.cs" />
     <Compile Include="Windows\AnimationWindow.cs" />
     <Compile Include="Windows\Animation\AnimationGizmo.cs" />
     <Compile Include="Windows\Animation\AnimationGizmo.cs" />

+ 3 - 3
Source/MBansheeEditor/Utility/SerializedObject.cs

@@ -26,7 +26,7 @@ namespace BansheeEditor
         /// <summary>
         /// <summary>
         /// Serializes all data within the provided component.
         /// Serializes all data within the provided component.
         /// </summary>
         /// </summary>
-        /// <param name="obj">Component to deserialize.</param>
+        /// <param name="obj">Component to serialize.</param>
         /// <returns>Object containing serialized data.</returns>
         /// <returns>Object containing serialized data.</returns>
         public static SerializedObject Create(Component obj)
         public static SerializedObject Create(Component obj)
         {
         {
@@ -40,7 +40,7 @@ namespace BansheeEditor
         /// <summary>
         /// <summary>
         /// Serializes all data within the provided resources.
         /// Serializes all data within the provided resources.
         /// </summary>
         /// </summary>
-        /// <param name="obj">Resource to deserialize.</param>
+        /// <param name="obj">Resource to serialize.</param>
         /// <returns>Object containing serialized data.</returns>
         /// <returns>Object containing serialized data.</returns>
         public static SerializedObject Create(ManagedResource obj)
         public static SerializedObject Create(ManagedResource obj)
         {
         {
@@ -54,7 +54,7 @@ namespace BansheeEditor
         /// <summary>
         /// <summary>
         /// Serializes all data within the provided object.
         /// Serializes all data within the provided object.
         /// </summary>
         /// </summary>
-        /// <param name="obj">Object to deserialize.</param>
+        /// <param name="obj">Object to serialize.</param>
         /// <returns>Object containing serialized data.</returns>
         /// <returns>Object containing serialized data.</returns>
         public static SerializedObject Create(object obj)
         public static SerializedObject Create(object obj)
         {
         {

+ 32 - 0
Source/MBansheeEditor/Utility/UndoableCommand.cs

@@ -0,0 +1,32 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Base class for implementation of commands that can be recorded in the UndoRedo system.
+    /// </summary>
+    public abstract class UndoableCommand : ScriptObject
+    {
+        public UndoableCommand()
+        {
+            Internal_CreateInstance(this);
+        }
+
+        /// <summary>
+        /// Applies the command, committing the change.
+        /// </summary>
+        protected abstract void Commit();
+
+        /// <summary>
+        /// Reverts the command, reverting the change previously done with <see cref="Commit"/>.
+        /// </summary>
+        protected abstract void Revert();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(UndoableCommand instance);
+    }
+}

+ 2 - 0
Source/SBansheeEditor/CMakeSources.cmake

@@ -11,6 +11,7 @@ set(BS_SBANSHEEEDITOR_INC_NOFILTER
 	"Include/BsEditorScriptLibrary.h"
 	"Include/BsEditorScriptLibrary.h"
 	"Include/BsToolbarItemManager.h"
 	"Include/BsToolbarItemManager.h"
 	"Include/BsScriptGizmoManager.h"
 	"Include/BsScriptGizmoManager.h"
+	"Include/BsManagedEditorCommand.h"
 )
 )
 
 
 set(BS_SBANSHEEEDITOR_SRC_WRAPPERS_GUI
 set(BS_SBANSHEEEDITOR_SRC_WRAPPERS_GUI
@@ -85,6 +86,7 @@ set(BS_SBANSHEEEDITOR_SRC_NOFILTER
 	"Source/BsEditorResourceLoader.cpp"
 	"Source/BsEditorResourceLoader.cpp"
 	"Source/BsEditorScriptLibrary.cpp"
 	"Source/BsEditorScriptLibrary.cpp"
 	"Source/BsToolbarItemManager.cpp"
 	"Source/BsToolbarItemManager.cpp"
+	"Source/BsManagedEditorCommand.cpp"
 )
 )
 
 
 set(BS_SBANSHEEEDITOR_INC_WRAPPERS
 set(BS_SBANSHEEEDITOR_INC_WRAPPERS

+ 87 - 0
Source/SBansheeEditor/Include/BsManagedEditorCommand.h

@@ -0,0 +1,87 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+#include "BsEditorCommand.h"
+
+namespace BansheeEngine
+{
+	class CmdManaged;
+
+	/** @addtogroup ScriptInteropEditor
+	 *  @{
+	 */
+
+	/**	Interop class between C++ & CLR for CmdManaged. */
+	class BS_SCR_BED_EXPORT ScriptCmdManaged : public ScriptObject <ScriptCmdManaged>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "UndoableCommand")
+
+		~ScriptCmdManaged();
+
+	private:
+		friend class CmdManaged;
+
+		ScriptCmdManaged(MonoObject* instance);
+
+		/** Triggers the Commit() method on the managed object instance. */
+		void triggerCommit();
+
+		/** Triggers the Revert() method on the managed object instance. */
+		void triggerRevert();
+
+		/** Notifies the script instance that the underlying managed command was destroyed. */
+		void notifyCommandDestroyed();
+
+		CmdManaged* mManagedCommand;
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static void internal_CreateInstance(MonoObject* instance);
+
+		static MonoMethod* sCommitMethod;
+		static MonoMethod* sRevertMethod;
+	};
+
+	/** @} */
+
+	/** @addtogroup SBansheeEditor
+	 *  @{
+	 */
+
+	/** 
+	 * A command used for undo/redo purposes. This particular implementation provides a generic overridable base to be
+	 * implemented by script classes. 
+	 */
+	class BS_SCR_BED_EXPORT CmdManaged : public EditorCommand
+	{
+	public:
+		~CmdManaged();
+
+		/** @copydoc EditorCommand::commit */
+		void commit() override;
+
+		/** @copydoc EditorCommand::revert */
+		void revert() override;
+
+	private:
+		friend class UndoRedo;
+		friend class ScriptCmdManaged;
+
+		CmdManaged(ScriptCmdManaged* scriptObj);
+
+		/** 
+		 * Notifies the command the managed script object instance it is referencing has been destroyed. Normally when this
+		 * happens the command should already be outside of the undo/redo stack, but we clear the instance just in case.
+		 */
+		void notifyScriptInstanceDestroyed();
+
+		ScriptCmdManaged* mScriptObj;
+	};
+
+	/** @} */
+}

+ 110 - 0
Source/SBansheeEditor/Source/BsManagedEditorCommand.cpp

@@ -0,0 +1,110 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsManagedEditorCommand.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoMethod.h"
+#include "BsMonoManager.h"
+
+namespace BansheeEngine
+{
+	MonoMethod* ScriptCmdManaged::sCommitMethod = nullptr;
+	MonoMethod* ScriptCmdManaged::sRevertMethod = nullptr;
+
+	ScriptCmdManaged::ScriptCmdManaged(MonoObject* managedInstance)
+		:ScriptObject(managedInstance), mManagedCommand(nullptr)
+	{
+		mManagedCommand = new (bs_alloc<CmdManaged>()) CmdManaged(this);
+	}
+
+	ScriptCmdManaged::~ScriptCmdManaged()
+	{
+		if(mManagedCommand != nullptr)
+		{
+			mManagedCommand->notifyScriptInstanceDestroyed();
+			mManagedCommand = nullptr;
+		}
+	}
+
+	void ScriptCmdManaged::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptCmdManaged::internal_CreateInstance);
+
+		sCommitMethod = metaData.scriptClass->getMethod("Commit");
+		sRevertMethod = metaData.scriptClass->getMethod("Revert");
+	}
+
+	void ScriptCmdManaged::internal_CreateInstance(MonoObject* managedInstance)
+	{
+		new (bs_alloc<ScriptCmdManaged>()) ScriptCmdManaged(managedInstance);
+	}
+
+	void ScriptCmdManaged::triggerCommit()
+	{
+		if (sCommitMethod == nullptr)
+			return;
+
+		sCommitMethod->invokeVirtual(mManagedInstance, nullptr);
+	}
+
+	void ScriptCmdManaged::triggerRevert()
+	{
+		if (sRevertMethod == nullptr)
+			return;
+
+		sRevertMethod->invokeVirtual(mManagedInstance, nullptr);
+	}
+
+	void ScriptCmdManaged::notifyCommandDestroyed()
+	{
+		mManagedCommand = nullptr;
+	}
+
+	CmdManaged::CmdManaged(ScriptCmdManaged* scriptObj)
+		: EditorCommand(L""), mScriptObj(scriptObj)
+	{
+
+	}
+
+	CmdManaged::~CmdManaged()
+	{
+		if (mScriptObj != nullptr)
+			mScriptObj->notifyCommandDestroyed();
+	}
+
+	void CmdManaged::commit()
+	{
+		if(mScriptObj == nullptr)
+		{
+			LOGWRN("Trying to execute a managed undo/redo command whose managed object has been destroyed, ignoring.");
+			// Note: This can most likely happen if managed undo commands are queued on a global undo/redo stack. When
+			// assembly refresh happens those commands will be destroyed but not removed from the stack. To fix the issue
+			// implement assembly refresh handling for such commands.
+
+			return;
+		}
+
+		mScriptObj->triggerCommit();
+	}
+
+	void CmdManaged::revert()
+	{
+		if (mScriptObj == nullptr)
+		{
+			LOGWRN("Trying to execute a managed undo/redo command whose managed object has been destroyed, ignoring.");
+			// Note: This can most likely happen if managed undo commands are queued on a global undo/redo stack. When
+			// assembly refresh happens those commands will be destroyed but not removed from the stack. To fix the issue
+			// implement assembly refresh handling for such commands.
+
+			return;
+		}
+
+		mScriptObj->triggerRevert();
+	}
+
+	void CmdManaged::notifyScriptInstanceDestroyed()
+	{
+		mScriptObj = nullptr;
+	}
+}