Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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;
            }
        }
Пример #3
0
        /// <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);
        }