/// <summary> /// Saves the surface to bytes. Performs also modified child surfaces saving before. /// </summary> /// <remarks> /// Assume this method does not throw exceptions but uses return value as a error code. /// </remarks> /// <returns>True if failed, otherwise false.</returns> public bool Save() { // Save all children modified before saving the current surface for (int i = 0; i < Children.Count; i++) { if (Children[i].IsModified && Children[i].Save()) { return(true); } } Saving?.Invoke(this); // Save surface meta _meta.AddEntry(10, Utils.StructureToByteArray(ref CachedSurfaceMeta)); // Save all nodes meta VisjectSurface.Meta11 meta11; for (int i = 0; i < Nodes.Count; i++) { var node = Nodes[i]; meta11.Position = node.Location; meta11.Selected = false; // don't save selection to prevent stupid binary diffs on asset // TODO: reuse byte[] array for all nodes to reduce dynamic memory allocations node.Meta.AddEntry(11, Utils.StructureToByteArray(ref meta11)); } // Save graph try { // Save graph using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { // Save graph to bytes SaveGraph(writer); var bytes = stream.ToArray(); // Send data to the container Context.SurfaceData = bytes; Saved?.Invoke(this); // Clear modification flag _isModified = false; } } catch (Exception ex) { // Error Editor.LogWarning("Saving Visject Surface data failed."); Editor.LogWarning(ex); return(true); } return(false); }
internal static void WriteVariant(this BinaryWriter stream, object value) { if (value == null) { stream.Write((byte)0); stream.Write(0); return; } var type = value.GetType(); var variantType = ToVariantType(type); stream.Write((byte)variantType); switch (variantType) { case VariantType.Object: if (type != typeof(FlaxEngine.Object)) { stream.Write(int.MaxValue); stream.WriteStrAnsi(type.FullName, 77); } else { stream.Write(0); } break; case VariantType.Asset: if (type != typeof(Asset)) { stream.Write(int.MaxValue); stream.WriteStrAnsi(type.FullName, 77); } else { stream.Write(0); } break; case VariantType.Enum: case VariantType.Structure: stream.Write(int.MaxValue); stream.WriteStrAnsi(type.FullName, 77); break; default: stream.Write(0); break; } Guid id; switch (variantType) { case VariantType.Bool: stream.Write((byte)((bool)value ? 1 : 0)); break; case VariantType.Int16: stream.Write((short)value); break; case VariantType.Uint16: stream.Write((ushort)value); break; case VariantType.Int: stream.Write((int)value); break; case VariantType.Uint: stream.Write((uint)value); break; case VariantType.Int64: stream.Write((long)value); break; case VariantType.Uint64: stream.Write((ulong)value); break; case VariantType.Float: stream.Write((float)value); break; case VariantType.Double: stream.Write((double)value); break; case VariantType.Pointer: stream.Write((ulong)(IntPtr)value); break; case VariantType.String: stream.WriteStr((string)value, -14); break; case VariantType.Object: id = ((FlaxEngine.Object)value).ID; stream.WriteGuid(ref id); break; case VariantType.Structure: { var data = Utils.StructureToByteArray(value, type); stream.Write(data.Length); stream.Write(data); break; } case VariantType.Asset: id = ((Asset)value).ID; stream.WriteGuid(ref id); break; case VariantType.Blob: stream.Write(((byte[])value).Length); stream.Write((byte[])value); break; case VariantType.Enum: stream.Write(Convert.ToUInt64(value)); break; case VariantType.Vector2: stream.Write((Vector2)value); break; case VariantType.Vector3: stream.Write((Vector3)value); break; case VariantType.Vector4: stream.Write((Vector4)value); break; case VariantType.Int2: stream.Write((Int2)value); break; case VariantType.Int3: stream.Write((Int3)value); break; case VariantType.Int4: stream.Write((Int4)value); break; case VariantType.Color: stream.Write((Color)value); break; case VariantType.Guid: id = (Guid)value; stream.WriteGuid(ref id); break; case VariantType.BoundingBox: stream.Write((BoundingBox)value); break; case VariantType.BoundingSphere: stream.Write((BoundingSphere)value); break; case VariantType.Quaternion: stream.Write((Quaternion)value); break; case VariantType.Transform: stream.Write((Transform)value); break; case VariantType.Rectangle: stream.Write((Rectangle)value); break; case VariantType.Ray: stream.Write((Ray)value); break; case VariantType.Matrix: stream.Write((Matrix)value); break; case VariantType.Array: stream.Write(((object[])value).Length); foreach (var e in (object[])value) { stream.WriteVariant(e); } break; case VariantType.Dictionary: stream.Write(((Dictionary <object, object>)value).Count); foreach (var e in (Dictionary <object, object>)value) { stream.WriteVariant(e.Key); stream.WriteVariant(e.Value); } break; case VariantType.Typename: if (value is Type) { stream.WriteStrAnsi(((Type)value).FullName, -14); } else if (value is ScriptType) { stream.WriteStrAnsi(((ScriptType)value).TypeName, -14); } break; } }