/// <summary> /// Recursively writes the <see cref="IUndoAction"/>s to the output stream /// </summary> /// <param name="bw"></param> /// <param name="action"></param> private void WriteAction(BinaryWriter bw, IUndoAction action) { if (action is MultiUndoAction multiUndoAction) { bw.Write(true); // It's a MultiUndoAction int actionCount = multiUndoAction.Actions.Length; bw.Write(actionCount); // bw.Write(multiUndoAction.ActionString) // TODO: Action string foreach (var subAction in multiUndoAction.Actions) { WriteAction(bw, subAction); } } else if (action is UndoActionObject undoActionObject) { bw.Write(false); bw.Write(this.ObjectDiffPacket); bw.Write(UndoActionObjectSerializer.ToJson(undoActionObject)); } else { bw.Write(false); string typeName = action.GetType().AssemblyQualifiedName; string data = FlaxEngine.Json.JsonSerializer.Serialize(action); bw.Write(typeName); bw.Write(data); } }
public IUndoAction DeserializeUndoAction(string typeName, string data) { // Handle object modifications, special case if (typeName == this.ObjectDiffPacket) { return(UndoActionObjectSerializer.FromJson(data)); } // Otherwise, generically deserialize it object undoAction = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type.GetType(typeName)); FlaxEngine.Json.JsonSerializer.Deserialize(undoAction, data); // Special deserialisation cases for a few undo actions /*if (undoAction is DeleteActorsAction deleteAction) * { * // Get node parents * FieldInfo nodeParentsField = typeof(DeleteActorsAction).GetField("_nodeParents", BindingFlags.NonPublic | BindingFlags.Instance); * List<ActorNode> nodeParents = nodeParentsField.GetValue(deleteAction) as List<ActorNode>; * if (nodeParents == null || nodeParents.Count <= 0) * { * // Deleting * // Get the actor Guids * FieldInfo actorDataField = typeof(DeleteActorsAction).GetField("_data", BindingFlags.NonPublic | BindingFlags.Instance); * byte[] actorData = actorDataField.GetValue(deleteAction) as byte[]; * Guid[] deletedActorGuids = Actor.TryGetSerializedObjectsIds(actorData); * * // Get the nodes in the scene graph * var actorNodes = new List<ActorNode>(deletedActorGuids.Length); * for (int i = 0; i < deletedActorGuids.Length; i++) * { * var foundNode = SceneGraphFactory.FindNode(deletedActorGuids[i]); * if (foundNode is ActorNode node) * { * actorNodes.Add(node); * } * } * * // Set the node parents field (used internally when deleting actors) * actorNodes.BuildNodesParents(nodeParents); * } * } * else*/ if (undoAction is SelectionChangeAction selectionChangeAction) { // Selection change action custom handling var callbackProp = typeof(SelectionChangeAction).GetField("_callback", BindingFlags.NonPublic | BindingFlags.Instance); var callbackMethod = typeof(SceneEditingModule).GetMethod("OnSelectionUndo", BindingFlags.NonPublic | BindingFlags.Instance); Action <SceneGraphNode[]> callbackLambda = (param) => callbackMethod.Invoke(Editor.Instance.SceneEditing, new object[] { param }); callbackProp.SetValue(selectionChangeAction, callbackLambda); } return(undoAction as IUndoAction); }