Пример #1
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.");
            }
        }
Пример #2
0
 /// <inheritdoc />
 public override bool CanUseNodeType(NodeArchetype nodeArchetype)
 {
     return((nodeArchetype.Flags & NodeFlags.MaterialGraph) != 0 && base.CanUseNodeType(nodeArchetype));
 }
Пример #3
0
 /// <inheritdoc />
 public override bool CanSpawnNodeType(NodeArchetype nodeArchetype)
 {
     return((nodeArchetype.Flags & NodeFlags.ParticleEmitterGraph) != 0 && base.CanSpawnNodeType(nodeArchetype));
 }