Пример #1
0
        /// <summary>
        /// Creates the new parameter of the given type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public static SurfaceParameter Create(ParameterType type)
        {
            // Create new parameter with default values
            var param = new SurfaceParameter
            {
                ID           = Guid.NewGuid(),
                IsPublic     = true,
                IsStatic     = false,
                IsUIEditable = true,
                IsUIVisible  = true,
                Name         = "New parameter",
                Type         = type
            };

            // Initialize default value in a proper way
            switch (type)
            {
            case ParameterType.Bool:
                param.Value = false;
                break;

            case ParameterType.Inteager:
                param.Value = 0;
                break;

            case ParameterType.Float:
                param.Value = 0.0f;
                break;

            case ParameterType.Vector2:
                param.Value = Vector2.Zero;
                break;

            case ParameterType.Vector3:
                param.Value = Vector3.Zero;
                break;

            case ParameterType.Vector4:
                param.Value = Vector4.Zero;
                break;

            case ParameterType.Color:
                param.Value = Color.White;
                break;

            case ParameterType.CubeTexture:
            case ParameterType.Texture:
            case ParameterType.NormalMap:
            case ParameterType.RenderTarget:
                param.Value = Guid.Empty;
                break;

            default: throw new IndexOutOfRangeException();
            }

            return(param);
        }
Пример #2
0
 /// <inheritdoc />
 public void OnParamDeleted(SurfaceParameter param)
 {
     for (int i = 0; i < _nodes.Count; i++)
     {
         if (_nodes[i] is IParametersDependantNode node)
         {
             node.OnParamDeleted(param);
         }
     }
     MarkAsEdited();
 }
Пример #3
0
        /// <summary>
        /// Gets the parameter by the given name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns>Found parameter instance or null if missing.</returns>
        public SurfaceParameter GetParameter(string name)
        {
            SurfaceParameter result = null;

            for (int i = 0; i < Parameters.Count; i++)
            {
                var parameter = Parameters[i];
                if (parameter.Name == name)
                {
                    result = parameter;
                    break;
                }
            }
            return(result);
        }
Пример #4
0
        /// <summary>
        /// Gets the parameter by the given ID.
        /// </summary>
        /// <param name="id">The identifier.</param>
        /// <returns>Found parameter instance or null if missing.</returns>
        public SurfaceParameter GetParameter(Guid id)
        {
            SurfaceParameter result = null;

            for (int i = 0; i < Parameters.Count; i++)
            {
                var parameter = Parameters[i];
                if (parameter.ID == id)
                {
                    result = parameter;
                    break;
                }
            }
            return(result);
        }
Пример #5
0
        private void Add()
        {
            var type = Type;

            if (IsAdd && type.Type == typeof(NormalMap))
            {
                type = new ScriptType(typeof(Texture));
            }
            var param = SurfaceParameter.Create(type, Name);

            if (IsAdd && Type.Type == typeof(NormalMap))
            {
                param.Value = FlaxEngine.Content.LoadAsyncInternal <Texture>("Engine/Textures/NormalTexture");
            }
            Window.VisjectSurface.Parameters.Insert(Index, param);
            Window.VisjectSurface.OnParamCreated(param);
            Window.OnParamAddUndo();
        }
Пример #6
0
        /// <summary>
        /// Creates the new parameter of the given type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>The created parameter.</returns>
        public static SurfaceParameter Create(ParameterType type)
        {
            // Create new parameter with default values
            var param = new SurfaceParameter
            {
                ID           = Guid.NewGuid(),
                IsPublic     = true,
                IsStatic     = false,
                IsUIEditable = true,
                IsUIVisible  = true,
                Name         = "New parameter",
                Type         = type
            };

            // Initialize default value in a proper way
            switch (type)
            {
            case ParameterType.Bool:
                param.Value = false;
                break;

            case ParameterType.Integer:
                param.Value = 0;
                break;

            case ParameterType.Float:
                param.Value = 0.0f;
                break;

            case ParameterType.Vector2:
                param.Value = Vector2.Zero;
                break;

            case ParameterType.Vector3:
                param.Value = Vector3.Zero;
                break;

            case ParameterType.Vector4:
                param.Value = Vector4.Zero;
                break;

            case ParameterType.Color:
                param.Value = Color.White;
                break;

            case ParameterType.Matrix:
                param.Value = Matrix.Identity;
                break;

            case ParameterType.String:
                param.Value = string.Empty;
                break;

            case ParameterType.Box:
                param.Value = BoundingBox.Zero;
                break;

            case ParameterType.Rectangle:
                param.Value = Rectangle.Empty;
                break;

            case ParameterType.Rotation:
                param.Value = Quaternion.Identity;
                break;

            case ParameterType.Transform:
                param.Value = Transform.Identity;
                break;

            case ParameterType.SceneTexture:
                param.Value = 0;
                break;

            case ParameterType.Asset:
            case ParameterType.Actor:
            case ParameterType.CubeTexture:
            case ParameterType.Texture:
            case ParameterType.NormalMap:
            case ParameterType.RenderTarget:
            case ParameterType.RenderTargetArray:
            case ParameterType.RenderTargetCube:
            case ParameterType.RenderTargetVolume:
                param.Value = Guid.Empty;
                break;

            default: throw new IndexOutOfRangeException();
            }

            return(param);
        }
        private void LoadGraph(BinaryReader stream)
        {
            // IMPORTANT! This must match C++ Graph format

            // Magic Code
            int tmp = stream.ReadInt32();

            if (tmp != 1963542358)
            {
                // Error
                throw new Exception("Invalid Graph format version");
            }

            // Engine Build
            uint engineBuild = stream.ReadUInt32();

            // Load1
            {
                // Time saved (not used anymore to prevent binary diffs after saving unmodified surface)
                stream.ReadInt64();
                byte[] guidBytes = new byte[16];

                // Nodes count
                int nodesCount = stream.ReadInt32();
                if (Nodes.Capacity < nodesCount)
                {
                    Nodes.Capacity = nodesCount;
                }
                List <ConnectionHint> tmpHints = _cachedConnections.Value;
                tmpHints.Clear();
                tmpHints.Capacity = Mathf.Max(tmpHints.Capacity, nodesCount * 4);

                // Parameters count
                int parametersCount = stream.ReadInt32();
                if (Parameters.Capacity < parametersCount)
                {
                    Parameters.Capacity = parametersCount;
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    // ID
                    uint id = stream.ReadUInt32();

                    // Type
                    ushort typeId  = stream.ReadUInt16();
                    ushort groupId = stream.ReadUInt16();

                    // Create node
                    SurfaceNode node;
                    if (groupId == Archetypes.Custom.GroupID)
                    {
                        node = new Archetypes.Custom.DummyCustomNode(id, this);
                    }
                    else
                    {
                        node = NodeFactory.CreateNode(_surface.NodeArchetypes, id, this, groupId, typeId);
                    }
                    if (node == null)
                    {
                        // Error
                        throw new Exception("Cannot create graph node.");
                    }
                    Nodes.Add(node);
                }

                // For each param
                for (int i = 0; i < parametersCount; i++)
                {
                    // Create param
                    var param = new SurfaceParameter();
                    Parameters.Add(param);

                    // Properties
                    param.Type = (ParameterType)stream.ReadByte();
                    stream.Read(guidBytes, 0, 16);
                    param.ID           = new Guid(guidBytes);
                    param.Name         = Utils.ReadStr(stream, 97);
                    param.IsPublic     = stream.ReadByte() != 0;
                    param.IsStatic     = stream.ReadByte() != 0;
                    param.IsUIVisible  = stream.ReadByte() != 0;
                    param.IsUIEditable = stream.ReadByte() != 0;

                    // References
                    int refsCount = stream.ReadInt32();
                    param.ReferencedBy.Capacity = refsCount;
                    for (int j = 0; j < refsCount; j++)
                    {
                        uint refID = stream.ReadUInt32();
                        var  node  = FindNode(refID);
                        if (node == null)
                        {
                            // Error
                            Editor.LogWarning($"Invalid node reference id (param: {param.Name}, node ref: {refID})");
                        }
                        else
                        {
                            param.ReferencedBy.Add(node);
                        }
                    }

                    // Value
                    Utils.ReadCommonValue(stream, ref param.Value);

                    // Meta
                    param.Meta.Load(engineBuild, stream);
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    var node = Nodes[i];

                    int valuesCnt         = stream.ReadInt32();
                    int firstValueReadIdx = 0;

                    // Special case for custom nodes
                    if (node is Archetypes.Custom.DummyCustomNode dummyCustom)
                    {
                        // TODO: maybe reuse the same dummy node (static) because is only a placeholder

                        // Values check
                        if (valuesCnt < 2)
                        {
                            throw new Exception("Missing custom nodes data.");
                        }

                        // Node typename check
                        object typeName = null;
                        Utils.ReadCommonValue(stream, ref typeName);
                        firstValueReadIdx = 1;
                        if (string.IsNullOrEmpty(typeName as string))
                        {
                            throw new Exception("Missing custom node typename.");
                        }

                        // Find custom node archetype that matches this node type (it must be unique)
                        var customNodes = _surface.GetCustomNodes();
                        if (customNodes?.Archetypes == null)
                        {
                            throw new Exception("Cannot find any custom nodes archetype.");
                        }
                        NodeArchetype arch = null;
                        for (int j = 0; j < customNodes.Archetypes.Length; j++)
                        {
                            if (string.Equals(Archetypes.Custom.GetNodeTypeName(customNodes.Archetypes[j]), (string)typeName, StringComparison.OrdinalIgnoreCase))
                            {
                                arch = customNodes.Archetypes[j];
                                break;
                            }
                        }
                        if (arch == null)
                        {
                            throw new Exception("Missing custom node " + typeName);
                        }

                        // Create custom node and replace dummy placeholder
                        node = NodeFactory.CreateNode(dummyCustom.ID, this, customNodes, arch);
                        if (node == null)
                        {
                            throw new Exception("Failed to create custom node " + typeName);
                        }
                        Nodes[i] = node;

                        // Store node typename in values container
                        node.Values[0] = typeName;
                    }

                    // Values
                    int nodeValuesCnt = node.Values?.Length ?? 0;
                    if (valuesCnt == nodeValuesCnt)
                    {
                        for (int j = firstValueReadIdx; j < valuesCnt; j++)
                        {
                            // ReSharper disable once PossibleNullReferenceException
                            Utils.ReadCommonValue(stream, ref node.Values[j]);
                        }
                    }
                    else
                    {
                        Editor.LogWarning(String.Format("Invalid node values. Loaded: {0}, expected: {1}. Type: {2}, {3}", valuesCnt, nodeValuesCnt, node.Archetype.Title, node.Archetype.TypeID));

                        object dummy = null;
                        for (int j = firstValueReadIdx; j < valuesCnt; j++)
                        {
                            Utils.ReadCommonValue(stream, ref dummy);
                        }
                    }

                    // Boxes
                    ushort boxesCount = stream.ReadUInt16();
                    for (int j = 0; j < boxesCount; j++)
                    {
                        var    id             = stream.ReadByte();
                        uint   type           = stream.ReadUInt32();
                        ushort connectionsCnt = stream.ReadUInt16();

                        ConnectionHint hint;
                        hint.NodeB = node.ID;
                        hint.BoxB  = id;

                        for (int k = 0; k < connectionsCnt; k++)
                        {
                            uint targetNodeID = stream.ReadUInt32();
                            byte targetBoxID  = stream.ReadByte();

                            hint.NodeA = targetNodeID;
                            hint.BoxA  = targetBoxID;

                            tmpHints.Add(hint);
                        }
                    }

                    // Meta
                    node.Meta.Load(engineBuild, stream);

                    OnControlLoaded(node);
                }

                // Visject Meta
                _meta.Load(engineBuild, stream);

                // Setup connections
                for (int i = 0; i < tmpHints.Count; i++)
                {
                    var c = tmpHints[i];

                    var nodeA = FindNode(c.NodeA);
                    var nodeB = FindNode(c.NodeB);
                    if (nodeA == null || nodeB == null)
                    {
                        // Error
                        Editor.LogWarning("Invalid connected node id.");
                        continue;
                    }

                    var boxA = nodeA.GetBox(c.BoxA);
                    var boxB = nodeB.GetBox(c.BoxB);
                    if (boxA != null && boxB != null)
                    {
                        boxA.Connections.Add(boxB);
                    }
                }

                // Ending char
                byte end = stream.ReadByte();
                if (end != '\t')
                {
                    // Error
                    throw new Exception("Invalid data.");
                }
            }
        }
Пример #8
0
        internal static GraphParameterData[] InitGraphParameters(IEnumerable <MaterialParameter> parameters, Material material)
        {
            int count = parameters.Count();
            var data  = new GraphParameterData[count];
            int i     = 0;

            // Load material surface parameters meta to use it for material instance parameters editing
            SurfaceParameter[] surfaceParameters = null;
            try
            {
                Profiler.BeginEvent("Init Material Parameters UI Data");

                if (material != null && !material.WaitForLoaded())
                {
                    var surfaceData = material.LoadSurface(false);
                    if (surfaceData != null && surfaceData.Length > 0)
                    {
                        using (var memoryStream = new MemoryStream(surfaceData))
                            using (var stream = new BinaryReader(memoryStream))
                            {
                                // IMPORTANT! This must match C++ Graph format

                                // Magic Code
                                int tmp = stream.ReadInt32();
                                if (tmp != 1963542358)
                                {
                                    // Error
                                    throw new Exception("Invalid Graph format version");
                                }

                                // Version
                                var version   = stream.ReadUInt32();
                                var guidBytes = new byte[16];
                                if (version < 7000)
                                {
                                    // Time saved (not used anymore to prevent binary diffs after saving unmodified surface)
                                    stream.ReadInt64();

                                    // Nodes count
                                    int nodesCount = stream.ReadInt32();

                                    // Parameters count
                                    int parametersCount = stream.ReadInt32();

                                    // For each node
                                    for (int j = 0; j < nodesCount; j++)
                                    {
                                        // ID
                                        stream.ReadUInt32();

                                        // Type
                                        stream.ReadUInt16();
                                        stream.ReadUInt16();
                                    }

                                    // For each param
                                    surfaceParameters = new SurfaceParameter[parametersCount];
                                    for (int j = 0; j < parametersCount; j++)
                                    {
                                        // Create param
                                        var param = new SurfaceParameter();
                                        surfaceParameters[j] = param;

                                        // Properties
                                        param.Type = new ScriptType(VisjectSurfaceContext.GetGraphParameterValueType((VisjectSurfaceContext.GraphParamType_Deprecated)stream.ReadByte()));
                                        stream.Read(guidBytes, 0, 16);
                                        param.ID       = new Guid(guidBytes);
                                        param.Name     = stream.ReadStr(97);
                                        param.IsPublic = stream.ReadByte() != 0;
                                        var isStatic     = stream.ReadByte() != 0;
                                        var isUIVisible  = stream.ReadByte() != 0;
                                        var isUIEditable = stream.ReadByte() != 0;

                                        // References [Deprecated]
                                        int refsCount = stream.ReadInt32();
                                        for (int k = 0; k < refsCount; k++)
                                        {
                                            stream.ReadUInt32();
                                        }

                                        // Value
                                        stream.ReadCommonValue(ref param.Value);

                                        // Meta
                                        param.Meta.Load(stream);
                                    }
                                }
                                else if (version == 7000)
                                {
                                    // Nodes count
                                    int nodesCount = stream.ReadInt32();

                                    // Parameters count
                                    int parametersCount = stream.ReadInt32();

                                    // For each node
                                    for (int j = 0; j < nodesCount; j++)
                                    {
                                        // ID
                                        stream.ReadUInt32();

                                        // Type
                                        stream.ReadUInt16();
                                        stream.ReadUInt16();
                                    }

                                    // For each param
                                    surfaceParameters = new SurfaceParameter[parametersCount];
                                    for (int j = 0; j < parametersCount; j++)
                                    {
                                        // Create param
                                        var param = new SurfaceParameter();
                                        surfaceParameters[j] = param;

                                        // Properties
                                        param.Type = stream.ReadVariantScriptType();
                                        stream.Read(guidBytes, 0, 16);
                                        param.ID       = new Guid(guidBytes);
                                        param.Name     = stream.ReadStr(97);
                                        param.IsPublic = stream.ReadByte() != 0;

                                        // Value
                                        param.Value = stream.ReadVariant();

                                        // Meta
                                        param.Meta.Load(stream);
                                    }
                                }
                            }
                    }
                }
            }
            catch (Exception ex)
            {
                Editor.LogError("Failed to get material parameters metadata.");
                Editor.LogWarning(ex);
            }
            finally
            {
                Profiler.EndEvent();
            }

            foreach (var parameter in parameters)
            {
                var surfaceParameter = surfaceParameters?.FirstOrDefault(x => x.ID == parameter.ParameterID);
                var attributes       = surfaceParameter?.Meta.GetAttributes() ?? FlaxEngine.Utils.GetEmptyArray <Attribute>();
                data[i] = new GraphParameterData(null, parameter.Name, parameter.IsPublic, ToType(parameter.ParameterType), attributes, parameter);
                i++;
            }
            Array.Sort(data, GraphParameterData.Compare);
            return(data);
        }
Пример #9
0
        private unsafe bool loadGraph(BinaryReader stream)
        {
            // IMPORTANT! This must match C++ Graph format

            // Magic Code
            int tmp = stream.ReadInt32();

            if (tmp != 1963542358)
            {
                // Error
                Debug.LogWarning("Invalid Grpah format version");
                return(true);
            }

            // Engine Build
            uint engineBuild = stream.ReadUInt32();

            // Load1
            {
                // Time saved
                DateTime tiemSaved = new DateTime(stream.ReadInt64());
                byte[]   guidBytes = new byte[16];

                // Nodes count
                int nodesCount = stream.ReadInt32();
                if (_nodes.Capacity < nodesCount)
                {
                    _nodes.Capacity = nodesCount;
                }
                List <ConnectionHint> tmpHints = new List <ConnectionHint>(nodesCount * 4);

                // Parameters count
                int parametersCount = stream.ReadInt32();
                if (Parameters.Capacity < parametersCount)
                {
                    Parameters.Capacity = parametersCount;
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    // ID
                    uint id = stream.ReadUInt32();

                    // Type
                    ushort typeId  = stream.ReadUInt16();
                    ushort groupId = stream.ReadUInt16();

                    // Create node
                    var node = NodeFactory.CreateNode(id, this, groupId, typeId);
                    if (node == null)
                    {
                        // Error
                        return(true);
                    }
                    _nodes.Add(node);
                }

                // For each param
                for (int i = 0; i < parametersCount; i++)
                {
                    // Create param
                    var param = new SurfaceParameter();
                    Parameters.Add(param);

                    // Properties
                    param.Type = (ParameterType)stream.ReadByte();
                    stream.Read(guidBytes, 0, 16);
                    param.ID           = new Guid(guidBytes);
                    param.Name         = ReadStr(stream, 97);
                    param.IsPublic     = stream.ReadByte() != 0;
                    param.IsStatic     = stream.ReadByte() != 0;
                    param.IsUIVisible  = stream.ReadByte() != 0;
                    param.IsUIEditable = stream.ReadByte() != 0;

                    // References
                    int refsCount = stream.ReadInt32();
                    param.ReferencedBy.Capacity = refsCount;
                    for (int j = 0; j < refsCount; j++)
                    {
                        uint refID = stream.ReadUInt32();
                        var  node  = FindNode(refID);
                        if (node == null)
                        {
                            // Error
                            Debug.LogWarning($"Invalid node reference id (param: {param.Name}, node ref: {refID})");
                        }
                        else
                        {
                            param.ReferencedBy.Add(node);
                        }
                    }

                    // Value
                    ReadCommonValue(stream, ref param.Value);

                    // Meta
                    param.Meta.Load(engineBuild, stream);
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    var node = _nodes[i];

                    // Values
                    int valuesCnt     = stream.ReadInt32();
                    int nodeValuesCnt = node.Values?.Length ?? 0;
                    if (valuesCnt == nodeValuesCnt)
                    {
                        for (int j = 0; j < valuesCnt; j++)
                        {
                            ReadCommonValue(stream, ref node.Values[j]);
                        }
                    }
                    else
                    {
                        Debug.LogWarning(string.Format("Invalid node values. Loaded: {0}, expected: {1}. Type: {2}, {3}", valuesCnt, nodeValuesCnt, node.Archetype.Title, node.Archetype.TypeID));

                        object dummy = null;
                        for (int j = 0; j < valuesCnt; j++)
                        {
                            ReadCommonValue(stream, ref dummy);
                        }
                    }

                    // Boxes
                    ushort boxesCount = stream.ReadUInt16();
                    for (int j = 0; j < boxesCount; j++)
                    {
                        var    id             = stream.ReadByte();
                        uint   type           = stream.ReadUInt32();
                        ushort connectionsCnt = stream.ReadUInt16();

                        ConnectionHint hint;
                        hint.NodeB = node;
                        hint.BoxB  = id;

                        for (int k = 0; k < connectionsCnt; k++)
                        {
                            uint targetNodeID = stream.ReadUInt32();
                            byte targetBoxID  = stream.ReadByte();

                            hint.NodeA = FindNode(targetNodeID);
                            if (hint.NodeA == null)
                            {
                                // Error
                                Debug.LogWarning("Invalid connected node id.");
                            }
                            else
                            {
                                hint.BoxA = targetBoxID;

                                tmpHints.Add(hint);
                            }
                        }
                    }

                    // Meta
                    node.Meta.Load(engineBuild, stream);

                    OnNodeLoaded(node);
                }

                // Visject Meta
                Meta.Load(engineBuild, stream);

                // Setup connections
                for (int i = 0; i < tmpHints.Count; i++)
                {
                    var c    = tmpHints[i];
                    var boxA = c.NodeA.GetBox(c.BoxA);
                    var boxB = c.NodeB.GetBox(c.BoxB);
                    if (boxA != null && boxB != null)
                    {
                        boxA.Connections.Add(boxB);
                    }
                }

                // Ending char
                byte end = stream.ReadByte();
                if (end != '\t')
                {
                    // Error
                    Debug.LogWarning("Invalid data.");
                    return(true);
                }
            }

            return(false);
        }
Пример #10
0
        private void LoadGraph(BinaryReader stream)
        {
            // IMPORTANT! This must match C++ Graph format

            // Magic Code
            int tmp = stream.ReadInt32();

            if (tmp != 1963542358)
            {
                // Error
                throw new Exception("Invalid Graph format version");
            }

            // Engine Build
            uint engineBuild = stream.ReadUInt32();

            // Load1
            {
                // Time saved (not used anymore to prevent binary diffs after saving unmodified surface)
                stream.ReadInt64();
                byte[] guidBytes = new byte[16];

                // Nodes count
                int nodesCount = stream.ReadInt32();
                if (Nodes.Capacity < nodesCount)
                {
                    Nodes.Capacity = nodesCount;
                }
                List <ConnectionHint> tmpHints = _cachedConnections.Value;
                tmpHints.Clear();
                tmpHints.Capacity = Mathf.Max(tmpHints.Capacity, nodesCount * 4);

                // Parameters count
                int parametersCount = stream.ReadInt32();
                if (Parameters.Capacity < parametersCount)
                {
                    Parameters.Capacity = parametersCount;
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    // ID
                    uint id = stream.ReadUInt32();

                    // Type
                    ushort typeId  = stream.ReadUInt16();
                    ushort groupId = stream.ReadUInt16();

                    // Create node
                    var node = NodeFactory.CreateNode(_surface.NodeArchetypes, id, this, groupId, typeId);
                    if (node == null)
                    {
                        // Error
                        throw new Exception("Cannot create graph node.");
                    }
                    Nodes.Add(node);
                }

                // For each param
                for (int i = 0; i < parametersCount; i++)
                {
                    // Create param
                    var param = new SurfaceParameter();
                    Parameters.Add(param);

                    // Properties
                    param.Type = (ParameterType)stream.ReadByte();
                    stream.Read(guidBytes, 0, 16);
                    param.ID           = new Guid(guidBytes);
                    param.Name         = Utils.ReadStr(stream, 97);
                    param.IsPublic     = stream.ReadByte() != 0;
                    param.IsStatic     = stream.ReadByte() != 0;
                    param.IsUIVisible  = stream.ReadByte() != 0;
                    param.IsUIEditable = stream.ReadByte() != 0;

                    // References
                    int refsCount = stream.ReadInt32();
                    param.ReferencedBy.Capacity = refsCount;
                    for (int j = 0; j < refsCount; j++)
                    {
                        uint refID = stream.ReadUInt32();
                        var  node  = FindNode(refID);
                        if (node == null)
                        {
                            // Error
                            Editor.LogWarning($"Invalid node reference id (param: {param.Name}, node ref: {refID})");
                        }
                        else
                        {
                            param.ReferencedBy.Add(node);
                        }
                    }

                    // Value
                    Utils.ReadCommonValue(stream, ref param.Value);

                    // Meta
                    param.Meta.Load(engineBuild, stream);
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    var node = Nodes[i];

                    // Values
                    int valuesCnt     = stream.ReadInt32();
                    int nodeValuesCnt = node.Values?.Length ?? 0;
                    if (valuesCnt == nodeValuesCnt)
                    {
                        for (int j = 0; j < valuesCnt; j++)
                        {
                            // ReSharper disable once PossibleNullReferenceException
                            Utils.ReadCommonValue(stream, ref node.Values[j]);
                        }
                    }
                    else
                    {
                        Editor.LogWarning(String.Format("Invalid node values. Loaded: {0}, expected: {1}. Type: {2}, {3}", valuesCnt, nodeValuesCnt, node.Archetype.Title, node.Archetype.TypeID));

                        object dummy = null;
                        for (int j = 0; j < valuesCnt; j++)
                        {
                            Utils.ReadCommonValue(stream, ref dummy);
                        }
                    }

                    // Boxes
                    ushort boxesCount = stream.ReadUInt16();
                    for (int j = 0; j < boxesCount; j++)
                    {
                        var    id             = stream.ReadByte();
                        uint   type           = stream.ReadUInt32();
                        ushort connectionsCnt = stream.ReadUInt16();

                        ConnectionHint hint;
                        hint.NodeB = node;
                        hint.BoxB  = id;

                        for (int k = 0; k < connectionsCnt; k++)
                        {
                            uint targetNodeID = stream.ReadUInt32();
                            byte targetBoxID  = stream.ReadByte();

                            hint.NodeA = FindNode(targetNodeID);
                            if (hint.NodeA == null)
                            {
                                // Error
                                Editor.LogWarning("Invalid connected node id.");
                            }
                            else
                            {
                                hint.BoxA = targetBoxID;

                                tmpHints.Add(hint);
                            }
                        }
                    }

                    // Meta
                    node.Meta.Load(engineBuild, stream);

                    OnControlLoaded(node);
                }

                // Visject Meta
                _meta.Load(engineBuild, stream);

                // Setup connections
                for (int i = 0; i < tmpHints.Count; i++)
                {
                    var c    = tmpHints[i];
                    var boxA = c.NodeA.GetBox(c.BoxA);
                    var boxB = c.NodeB.GetBox(c.BoxB);
                    if (boxA != null && boxB != null)
                    {
                        boxA.Connections.Add(boxB);
                    }
                }

                // Ending char
                byte end = stream.ReadByte();
                if (end != '\t')
                {
                    // Error
                    throw new Exception("Invalid data.");
                }
            }
        }
Пример #11
0
        private void LoadGraph(BinaryReader stream)
        {
            // IMPORTANT! This must match C++ Graph format

            // Magic Code
            int tmp = stream.ReadInt32();

            if (tmp != 1963542358)
            {
                // Error
                throw new Exception("Invalid Graph format version");
            }

            // Version
            var version   = stream.ReadUInt32();
            var tmpHints  = _cachedConnections.Value;
            var guidBytes = new byte[16];

            if (version < 7000)
            {
                // Time saved (not used anymore to prevent binary diffs after saving unmodified surface)
                stream.ReadInt64();

                // Nodes count
                int nodesCount = stream.ReadInt32();
                if (Nodes.Capacity < nodesCount)
                {
                    Nodes.Capacity = nodesCount;
                }
                tmpHints.Clear();
                tmpHints.Capacity = Mathf.Max(tmpHints.Capacity, nodesCount * 4);

                // Parameters count
                int parametersCount = stream.ReadInt32();
                if (Parameters.Capacity < parametersCount)
                {
                    Parameters.Capacity = parametersCount;
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    // ID
                    uint id = stream.ReadUInt32();

                    // Type
                    ushort typeId  = stream.ReadUInt16();
                    ushort groupId = stream.ReadUInt16();

                    // Create node
                    SurfaceNode node;
                    if (groupId == Archetypes.Custom.GroupID)
                    {
                        node = new DummyCustomNode(id, this);
                    }
                    else
                    {
                        node = NodeFactory.CreateNode(_surface.NodeArchetypes, id, this, groupId, typeId);
                    }
                    if (node == null)
                    {
                        node = new MissingNode(id, this, groupId, typeId);
                    }
                    Nodes.Add(node);
                }

                // For each param
                for (int i = 0; i < parametersCount; i++)
                {
                    // Create param
                    var param = new SurfaceParameter();
                    Parameters.Add(param);

                    // Properties
                    param.Type = new ScriptType(GetGraphParameterValueType((GraphParamType_Deprecated)stream.ReadByte()));
                    stream.Read(guidBytes, 0, 16);
                    param.ID       = new Guid(guidBytes);
                    param.Name     = stream.ReadStr(97);
                    param.IsPublic = stream.ReadByte() != 0;
                    bool isStatic     = stream.ReadByte() != 0;
                    bool isUIVisible  = stream.ReadByte() != 0;
                    bool isUIEditable = stream.ReadByte() != 0;

                    // References [Deprecated]
                    int refsCount = stream.ReadInt32();
                    for (int j = 0; j < refsCount; j++)
                    {
                        uint refID = stream.ReadUInt32();
                    }

                    // Value
                    stream.ReadCommonValue(ref param.Value);

                    // Meta
                    param.Meta.Load(stream);
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    var node = Nodes[i];

                    int valuesCnt         = stream.ReadInt32();
                    int firstValueReadIdx = 0;

                    // Special case for missing nodes
                    if (node is DummyCustomNode customNode)
                    {
                        node = null;

                        // Values check
                        if (valuesCnt < 2)
                        {
                            throw new Exception("Missing custom nodes data.");
                        }

                        // Node typename check
                        object typeNameValue = null;
                        stream.ReadCommonValue(ref typeNameValue);
                        firstValueReadIdx = 1;
                        string typeName = typeNameValue as string ?? string.Empty;

                        // Find custom node archetype that matches this node type (it must be unique)
                        var customNodes = _surface.GetCustomNodes();
                        if (customNodes?.Archetypes != null && typeName.Length != 0)
                        {
                            NodeArchetype arch = null;
                            foreach (var nodeArchetype in customNodes.Archetypes)
                            {
                                if (string.Equals(Archetypes.Custom.GetNodeTypeName(nodeArchetype), typeName, StringComparison.OrdinalIgnoreCase))
                                {
                                    arch = nodeArchetype;
                                    break;
                                }
                            }
                            if (arch != null)
                            {
                                node = NodeFactory.CreateNode(customNode.ID, this, customNodes, arch);
                            }
                        }

                        // Fallback to the
                        if (node == null)
                        {
                            Editor.LogWarning(string.Format("Cannot find custom node archetype for {0}", typeName));
                            node = new MissingNode(customNode.ID, this, Archetypes.Custom.GroupID, customNode.Archetype.TypeID);
                        }
                        Nodes[i] = node;

                        // Store node typename in values container
                        node.Values[0] = typeName;
                    }
                    if (node is MissingNode)
                    {
                        // Read all values
                        Array.Resize(ref node.Values, valuesCnt);
                        for (int j = firstValueReadIdx; j < valuesCnt; j++)
                        {
                            // ReSharper disable once PossibleNullReferenceException
                            stream.ReadCommonValue(ref node.Values[j]);
                        }
                        firstValueReadIdx = valuesCnt = node.Values.Length;
                    }

                    // Values
                    int nodeValuesCnt = node.Values?.Length ?? 0;
                    if (valuesCnt == nodeValuesCnt)
                    {
                        for (int j = firstValueReadIdx; j < valuesCnt; j++)
                        {
                            // ReSharper disable once PossibleNullReferenceException
                            stream.ReadCommonValue(ref node.Values[j]);
                        }
                    }
                    else
                    {
                        Editor.LogWarning(string.Format("Invalid node values. Loaded: {0}, expected: {1}. Type: {2}, {3}", valuesCnt, nodeValuesCnt, node.Archetype.Title, node.Archetype.TypeID));

                        object dummy = null;
                        for (int j = firstValueReadIdx; j < valuesCnt; j++)
                        {
                            stream.ReadCommonValue(ref dummy);

                            if (j < nodeValuesCnt &&
                                dummy != null &&
                                node.Values[j] != null &&
                                node.Values[j].GetType() == dummy.GetType())
                            {
                                node.Values[j] = dummy;
                            }
                        }
                    }

                    // Boxes
                    ushort boxesCount = stream.ReadUInt16();
                    for (int j = 0; j < boxesCount; j++)
                    {
                        var id = stream.ReadByte();
                        stream.ReadUInt32(); // Skip type
                        ushort connectionsCnt = stream.ReadUInt16();

                        ConnectionHint hint;
                        hint.NodeB = node.ID;
                        hint.BoxB  = id;

                        for (int k = 0; k < connectionsCnt; k++)
                        {
                            uint targetNodeID = stream.ReadUInt32();
                            byte targetBoxID  = stream.ReadByte();

                            hint.NodeA = targetNodeID;
                            hint.BoxA  = targetBoxID;

                            tmpHints.Add(hint);
                        }
                    }

                    // Meta
                    node.Meta.Load(stream);

                    OnControlLoaded(node);
                }
            }
            else if (version == 7000)
            {
                // Nodes count
                int nodesCount = stream.ReadInt32();
                if (Nodes.Capacity < nodesCount)
                {
                    Nodes.Capacity = nodesCount;
                }
                tmpHints.Clear();
                tmpHints.Capacity = Mathf.Max(tmpHints.Capacity, nodesCount * 4);

                // Parameters count
                int parametersCount = stream.ReadInt32();
                if (Parameters.Capacity < parametersCount)
                {
                    Parameters.Capacity = parametersCount;
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    uint   id      = stream.ReadUInt32();
                    ushort typeId  = stream.ReadUInt16();
                    ushort groupId = stream.ReadUInt16();

                    // Create node
                    SurfaceNode node;
                    if (groupId == Archetypes.Custom.GroupID)
                    {
                        node = new DummyCustomNode(id, this);
                    }
                    else
                    {
                        node = NodeFactory.CreateNode(_surface.NodeArchetypes, id, this, groupId, typeId);
                    }
                    if (node == null)
                    {
                        node = new MissingNode(id, this, groupId, typeId);
                    }
                    Nodes.Add(node);
                }

                // For each param
                for (int i = 0; i < parametersCount; i++)
                {
                    // Create param
                    var param = new SurfaceParameter();
                    Parameters.Add(param);
                    param.Type = stream.ReadVariantScriptType();
                    stream.Read(guidBytes, 0, 16);
                    param.ID       = new Guid(guidBytes);
                    param.Name     = stream.ReadStr(97);
                    param.IsPublic = stream.ReadByte() != 0;

                    // Value
                    param.Value = stream.ReadVariant();

                    // Meta
                    param.Meta.Load(stream);
                }

                // For each node
                for (int i = 0; i < nodesCount; i++)
                {
                    var node = Nodes[i];

                    int valuesCnt         = stream.ReadInt32();
                    int firstValueReadIdx = 0;

                    // Special case for missing nodes
                    if (node is DummyCustomNode customNode)
                    {
                        node = null;

                        // Values check
                        if (valuesCnt < 2)
                        {
                            throw new Exception("Missing custom nodes data.");
                        }

                        // Node typename check
                        object typeNameValue = stream.ReadVariant();
                        firstValueReadIdx = 1;
                        string typeName = typeNameValue as string ?? string.Empty;

                        // Find custom node archetype that matches this node type (it must be unique)
                        var customNodes = _surface.GetCustomNodes();
                        if (customNodes?.Archetypes != null && typeName.Length != 0)
                        {
                            NodeArchetype arch = null;
                            foreach (var nodeArchetype in customNodes.Archetypes)
                            {
                                if (string.Equals(Archetypes.Custom.GetNodeTypeName(nodeArchetype), typeName, StringComparison.OrdinalIgnoreCase))
                                {
                                    arch = nodeArchetype;
                                    break;
                                }
                            }
                            if (arch != null)
                            {
                                node = NodeFactory.CreateNode(customNode.ID, this, customNodes, arch);
                            }
                        }

                        // Fallback to the
                        if (node == null)
                        {
                            Editor.LogWarning(string.Format("Cannot find custom node archetype for {0}", typeName));
                            node = new MissingNode(customNode.ID, this, Archetypes.Custom.GroupID, customNode.Archetype.TypeID);
                        }
                        Nodes[i] = node;

                        // Store node typename in values container
                        node.Values[0] = typeName;
                    }
                    if (node is MissingNode)
                    {
                        // Read all values
                        Array.Resize(ref node.Values, valuesCnt);
                        for (int j = firstValueReadIdx; j < valuesCnt; j++)
                        {
                            node.Values[j] = stream.ReadVariant();
                        }
                        firstValueReadIdx = valuesCnt = node.Values.Length;
                    }

                    // Values
                    int nodeValuesCnt = node.Values?.Length ?? 0;
                    if (valuesCnt == nodeValuesCnt)
                    {
                        for (int j = firstValueReadIdx; j < valuesCnt; j++)
                        {
                            node.Values[j] = stream.ReadVariant();
                        }
                    }
                    else
                    {
                        Editor.LogWarning(string.Format("Invalid node values. Loaded: {0}, expected: {1}. Type: {2}, {3}", valuesCnt, nodeValuesCnt, node.Archetype.Title, node.Archetype.TypeID));

                        object dummy;
                        for (int j = firstValueReadIdx; j < valuesCnt; j++)
                        {
                            dummy = stream.ReadVariant();

                            if (j < nodeValuesCnt &&
                                dummy != null &&
                                node.Values[j] != null &&
                                node.Values[j].GetType() == dummy.GetType())
                            {
                                node.Values[j] = dummy;
                            }
                        }
                    }

                    // Boxes
                    ushort boxesCount = stream.ReadUInt16();
                    for (int j = 0; j < boxesCount; j++)
                    {
                        var id = stream.ReadByte();
                        stream.ReadVariantType(); // Skip type
                        var connectionsCnt = stream.ReadUInt16();

                        ConnectionHint hint;
                        hint.NodeB = node.ID;
                        hint.BoxB  = id;

                        for (int k = 0; k < connectionsCnt; k++)
                        {
                            uint targetNodeID = stream.ReadUInt32();
                            byte targetBoxID  = stream.ReadByte();
                            hint.NodeA = targetNodeID;
                            hint.BoxA  = targetBoxID;
                            tmpHints.Add(hint);
                        }
                    }

                    // Meta
                    node.Meta.Load(stream);

                    OnControlLoaded(node);
                }
            }
            else
            {
                throw new Exception($"Unsupported graph version {version}.");
            }

            // Visject Meta
            _meta.Load(stream);

            // Setup connections
            for (int i = 0; i < tmpHints.Count; i++)
            {
                var c = tmpHints[i];

                var nodeA = FindNode(c.NodeA);
                var nodeB = FindNode(c.NodeB);
                if (nodeA == null || nodeB == null)
                {
                    // Error
                    Editor.LogWarning("Invalid connected node id.");
                    continue;
                }

                var boxA = nodeA.GetBox(c.BoxA);
                var boxB = nodeB.GetBox(c.BoxB);
                if (boxA != null && boxB != null)
                {
                    boxA.Connections.Add(boxB);
                }
            }

            // Ending char
            byte end = stream.ReadByte();

            if (end != '\t')
            {
                throw new Exception("Invalid data.");
            }
        }