/// <summary> /// Called when node gets loaded and should be added to the surface. Creates node elements from the archetype. /// </summary> /// <param name="node">The node.</param> public virtual void OnNodeLoaded(SurfaceNode node) { // Create child elements of the node based on it's archetype int elementsCount = node.Archetype.Elements?.Length ?? 0; for (int i = 0; i < elementsCount; i++) { // ReSharper disable once PossibleNullReferenceException node.AddElement(node.Archetype.Elements[i]); } // Load metadata var meta = node.Meta.GetEntry(11); if (meta.Data != null) { var meta11 = Utils.ByteArrayToStructure <VisjectSurface.Meta11>(meta.Data); node.Location = meta11.Position; //node.IsSelected = meta11.Selected; } }
internal static unsafe object ReadVariant(this BinaryReader stream) { Type type = null; var variantType = (VariantType)stream.ReadByte(); var typeNameLength = stream.ReadInt32(); if (typeNameLength == int.MaxValue) { typeNameLength = stream.ReadInt32(); var data = new byte[typeNameLength]; for (int i = 0; i < typeNameLength; i++) { var c = stream.ReadByte(); data[i] = (byte)(c ^ 77); } var typeName = System.Text.Encoding.ASCII.GetString(data); type = TypeUtils.GetManagedType(typeName); } else if (typeNameLength > 0) { // [Deprecated on 27.08.2020, expires on 27.08.2021] var data = new char[typeNameLength]; for (int i = 0; i < typeNameLength; i++) { var c = stream.ReadUInt16(); data[i] = (char)(c ^ 77); } var typeName = new string(data); type = TypeUtils.GetManagedType(typeName); } switch (variantType) { case VariantType.Null: case VariantType.ManagedObject: case VariantType.Void: return(null); case VariantType.Bool: return(stream.ReadByte() != 0); case VariantType.Int16: return(stream.ReadInt16()); case VariantType.Uint16: return(stream.ReadUInt16()); case VariantType.Int: return(stream.ReadInt32()); case VariantType.Uint: return(stream.ReadUInt32()); case VariantType.Int64: return(stream.ReadInt64()); case VariantType.Uint64: return(stream.ReadUInt64()); case VariantType.Float: return(stream.ReadSingle()); case VariantType.Double: return(stream.ReadDouble()); case VariantType.Pointer: return(new IntPtr((void *)stream.ReadUInt64())); case VariantType.String: { typeNameLength = stream.ReadInt32(); var data = new char[typeNameLength]; for (int i = 0; i < typeNameLength; i++) { var c = stream.ReadUInt16(); data[i] = (char)(c ^ -14); } return(new string(data)); } case VariantType.Object: { var id = stream.ReadGuid(); return(FlaxEngine.Object.Find(ref id, type ?? typeof(FlaxEngine.Object))); } case VariantType.Structure: { if (type == null) { throw new Exception("Missing structure type of the Variant."); } var data = stream.ReadBytes(stream.ReadInt32()); return(Utils.ByteArrayToStructure(data, type)); } case VariantType.Asset: { var id = stream.ReadGuid(); return(FlaxEngine.Object.Find(ref id, type ?? typeof(Asset))); } case VariantType.Blob: return(stream.ReadBytes(stream.ReadInt32())); case VariantType.Enum: { if (type == null) { throw new Exception("Missing enum type of the Variant."); } return(Enum.ToObject(type, stream.ReadUInt64())); } case VariantType.Vector2: return(stream.ReadVector2()); case VariantType.Vector3: return(stream.ReadVector3()); case VariantType.Vector4: return(stream.ReadVector4()); case VariantType.Int2: return(stream.ReadInt2()); case VariantType.Int3: return(stream.ReadInt3()); case VariantType.Int4: return(stream.ReadInt4()); case VariantType.Color: return(stream.ReadColor()); case VariantType.Guid: return(stream.ReadGuid()); case VariantType.BoundingBox: return(stream.ReadBoundingBox()); case VariantType.BoundingSphere: return(stream.ReadBoundingSphere()); case VariantType.Quaternion: return(stream.ReadQuaternion()); case VariantType.Transform: return(stream.ReadTransform()); case VariantType.Rectangle: return(stream.ReadRectangle()); case VariantType.Ray: return(stream.ReadRay()); case VariantType.Matrix: return(stream.ReadMatrix()); case VariantType.Array: { var count = stream.ReadInt32(); var result = new object[count]; for (int i = 0; i < count; i++) { result[i] = stream.ReadVariant(); } return(result); } case VariantType.Dictionary: { var count = stream.ReadInt32(); var result = new Dictionary <object, object>(); for (int i = 0; i < count; i++) { result.Add(stream.ReadVariant(), stream.ReadVariant()); } return(result); } case VariantType.Typename: { typeNameLength = stream.ReadInt32(); var data = new byte[typeNameLength]; for (int i = 0; i < typeNameLength; i++) { var c = stream.ReadByte(); data[i] = (byte)(c ^ -14); } var typeName = System.Text.Encoding.ASCII.GetString(data); return(TypeUtils.GetType(typeName)); } default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType}." + (type != null ? $" Type: {type.FullName}" : string.Empty)); } }
/// <summary> /// Loads the surface from bytes. Clears the surface before and uses context source data as a surface bytes source. /// </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 Load() { Surface._isUpdatingBoxTypes++; try { // Prepare Clear(); Loading?.Invoke(this); // Load bytes var bytes = Context.SurfaceData; if (bytes == null) { throw new Exception("Failed to load surface data."); } // Load graph (empty bytes data means empty graph for simplicity when using subgraphs) if (bytes.Length > 0) { using (var stream = new MemoryStream(bytes)) using (var reader = new BinaryReader(stream)) { LoadGraph(reader); } } // Load surface meta var meta = _meta.GetEntry(10); if (meta.Data != null) { Utils.ByteArrayToStructure(meta.Data, out CachedSurfaceMeta); } else { // Reset view CachedSurfaceMeta.ViewCenterPosition = Vector2.Zero; CachedSurfaceMeta.Scale = 1.0f; } // [Deprecated on 04.07.2019] Load surface comments var commentsData = _meta.GetEntry(666); if (commentsData.Data != null) { using (var stream = new MemoryStream(commentsData.Data)) using (var reader = new BinaryReader(stream)) { var commentsCount = reader.ReadInt32(); for (int i = 0; i < commentsCount; i++) { var title = reader.ReadStr(71); var color = new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); var bounds = new Rectangle(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); var comment = SpawnComment(ref bounds, title, color); if (comment == null) { throw new InvalidOperationException("Failed to create comment."); } OnControlLoaded(comment); } } } // Post load for (int i = 0; i < RootControl.Children.Count; i++) { if (RootControl.Children[i] is SurfaceControl control) { control.OnSurfaceLoaded(); } } RootControl.UnlockChildrenRecursive(); // Update boxes types for nodes that dependant box types based on incoming connections { bool keepUpdating = false; int updateLimit = 100; do { for (int i = 0; i < RootControl.Children.Count; i++) { if (RootControl.Children[i] is SurfaceNode node && !node.HasDependentBoxesSetup) { node.UpdateBoxesTypes(); keepUpdating = true; } } } while (keepUpdating && updateLimit-- > 0); } Loaded?.Invoke(this); // Clear modification flag _isModified = false; } catch (Exception ex) { // Error Editor.LogWarning("Loading Visject Surface data failed."); Editor.LogWarning(ex); return(true); } finally { Surface._isUpdatingBoxTypes--; } return(false); }