Ejemplo n.º 1
0
        // Gets a single timestamp component
        static int GetTimestampVar(FbxNode timestamp, string element)
        {
            var elementNode = timestamp[element];

            if (elementNode != null && elementNode.Properties.Count > 0)
            {
                var prop = elementNode.Properties[0];
                if (prop is int || prop is long)
                {
                    return((int)prop);
                }
            }
            throw new FbxException(timePath, -1, "Timestamp has no " + element);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Returns all sub-nodes with name
        /// </summary>
        /// <returns></returns>
        private List <FbxNode> GetNodesByValue(FbxNode node, string value, List <FbxNode> c = null)
        {
            if (c == null)
            {
                c = new List <FbxNode>();
            }

            if (node == null)
            {
                return(c);
            }

            if (node.Value != null && node.Value.ToString().Equals(value))
            {
                c.Add(node);
            }

            foreach (var child in node.Nodes)
            {
                GetNodesByValue(child, value, c);
            }

            return(c);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns all sub-nodes with name
        /// </summary>
        /// <returns></returns>
        private List <FbxNode> GetNodesByName(FbxNode node, string name, List <FbxNode> c = null)
        {
            if (c == null)
            {
                c = new List <FbxNode>();
            }

            if (node == null)
            {
                return(c);
            }

            if (node.Name.Equals(name))
            {
                c.Add(node);
            }

            foreach (var child in node.Nodes)
            {
                GetNodesByName(child, name, c);
            }

            return(c);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Reads the next node from the stream
        /// </summary>
        /// <returns>The read node, or <c>null</c></returns>
        public FbxNode ReadNode()
        {
            var first = ReadToken();
            var id    = first as Identifier;

            if (id == null)
            {
                if (first is EndOfStream)
                {
                    return(null);
                }
                throw new FbxException(line, column,
                                       "Unexpected '" + first + "', expected an identifier");
            }
            var node = new FbxNode {
                Name = id.String
            };

            // Read properties
            object token;
            bool   expectComma = false;

            while (!'{'.Equals(token = ReadToken()) && !(token is Identifier) && !'}'.Equals(token))
            {
                if (expectComma)
                {
                    if (!','.Equals(token))
                    {
                        throw new FbxException(line, column,
                                               "Unexpected '" + token + "', expected a ','");
                    }
                    expectComma = false;
                    continue;
                }
                if (token is char)
                {
                    var c = (char)token;
                    switch (c)
                    {
                    case '*':
                        token = ReadArray();
                        break;

                    case '}':
                    case ':':
                    case ',':
                        throw new FbxException(line, column,
                                               "Unexpected '" + c + "' in property list");
                    }
                }
                node.Properties.Add(token);
                expectComma = true;                 // The final comma before the open brace isn't required
            }
            // TODO: Merge property list into an array as necessary
            // Now we're either at an open brace, close brace or a new node
            if (token is Identifier || '}'.Equals(token))
            {
                prevToken = token;
                return(node);
            }
            // The while loop can't end unless we're at an open brace, so we can continue right on
            object endBrace;

            while (!'}'.Equals(endBrace = ReadToken()))
            {
                prevToken = endBrace;                 // If it's not an end brace, the next node will need it
                node.Nodes.Add(ReadNode());
            }
            if (node.Nodes.Count < 1)            // If there's an open brace, we want that to be preserved
            {
                node.Nodes.Add(null);
            }
            return(node);
        }
Ejemplo n.º 5
0
        // Adds the given node text to the string
        void BuildString(FbxNode node, StringBuilder sb, bool writeArrayLength, int indentLevel = 0)
        {
            nodePath.Push(node.Name ?? "");
            int lineStart = sb.Length;

            // Write identifier
            for (int i = 0; i < indentLevel; i++)
            {
                sb.Append('\t');
            }
            sb.Append(node.Name).Append(':');

            // Write properties
            var first = true;

            for (int j = 0; j < node.Properties.Count; j++)
            {
                var p = node.Properties[j];
                if (p == null)
                {
                    continue;
                }
                if (!first)
                {
                    sb.Append(',');
                }
                sb.Append(' ');
                if (p is string)
                {
                    sb.Append('"').Append(p).Append('"');
                }
                else if (p is Array)
                {
                    var array       = (Array)p;
                    var elementType = p.GetType().GetElementType();
                    // ReSharper disable once PossibleNullReferenceException
                    // We know it's an array, so we don't need to check for null
                    if (array.Rank != 1 || !elementType.IsPrimitive)
                    {
                        throw new FbxException(nodePath, j,
                                               "Invalid array type " + p.GetType());
                    }
                    if (writeArrayLength)
                    {
                        sb.Append('*').Append(array.Length).Append(" {\n");
                        lineStart = sb.Length;
                        for (int i = -1; i < indentLevel; i++)
                        {
                            sb.Append('\t');
                        }
                        sb.Append("a: ");
                    }
                    bool pFirst = true;
                    foreach (var v in (Array)p)
                    {
                        if (!pFirst)
                        {
                            sb.Append(',');
                        }
                        var vstr = v.ToString();
                        if ((sb.Length - lineStart) + vstr.Length >= MaxLineLength)
                        {
                            sb.Append('\n');
                            lineStart = sb.Length;
                        }
                        sb.Append(vstr);
                        pFirst = false;
                    }
                    if (writeArrayLength)
                    {
                        sb.Append('\n');
                        for (int i = 0; i < indentLevel; i++)
                        {
                            sb.Append('\t');
                        }
                        sb.Append('}');
                    }
                }
                else if (p is char)
                {
                    sb.Append((char)p);
                }
                else if (p.GetType().IsPrimitive&& p is IFormattable)
                {
                    sb.Append(p);
                }
                else
                {
                    throw new FbxException(nodePath, j,
                                           "Invalid property type " + p.GetType());
                }
                first = false;
            }

            // Write child nodes
            if (node.Nodes.Count > 0)
            {
                sb.Append(" {\n");
                foreach (var n in node.Nodes)
                {
                    if (n == null)
                    {
                        continue;
                    }
                    BuildString(n, sb, writeArrayLength, indentLevel + 1);
                }
                for (int i = 0; i < indentLevel; i++)
                {
                    sb.Append('\t');
                }
                sb.Append('}');
            }
            sb.Append('\n');

            nodePath.Pop();
        }
Ejemplo n.º 6
0
        // Writes a single document to the buffer
        void WriteNode(FbxNode node)
        {
            if (node == null)
            {
                stream.BaseStream.Write(nullData, 0, nullData.Length);
            }
            else
            {
                nodePath.Push(node.Name ?? "");
                var name = string.IsNullOrEmpty(node.Name) ? null : Encoding.ASCII.GetBytes(node.Name);
                if (name != null && name.Length > byte.MaxValue)
                {
                    throw new FbxException(stream.BaseStream.Position,
                                           "Node name is too long");
                }

                // Header
                var endOffsetPos = stream.BaseStream.Position;
                stream.Write(0);                 // End offset placeholder
                stream.Write(node.Properties.Count);
                var propertyLengthPos = stream.BaseStream.Position;
                stream.Write(0);                 // Property length placeholder
                stream.Write((byte)(name?.Length ?? 0));
                if (name != null)
                {
                    stream.Write(name);
                }

                // Write properties and length
                var propertyBegin = stream.BaseStream.Position;
                for (int i = 0; i < node.Properties.Count; i++)
                {
                    WriteProperty(node.Properties[i], i);
                }
                var propertyEnd = stream.BaseStream.Position;
                stream.BaseStream.Position = propertyLengthPos;
                stream.Write((int)(propertyEnd - propertyBegin));
                stream.BaseStream.Position = propertyEnd;

                // Write child nodes
                if (node.Nodes.Count > 0)
                {
                    foreach (var n in node.Nodes)
                    {
                        if (n == null)
                        {
                            continue;
                        }
                        WriteNode(n);
                    }
                    WriteNode(null);
                }

                // Write end offset
                var dataEnd = stream.BaseStream.Position;
                stream.BaseStream.Position = endOffsetPos;
                stream.Write((int)dataEnd);
                stream.BaseStream.Position = dataEnd;

                nodePath.Pop();
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Reads a single node.
        /// </summary>
        /// <remarks>
        /// This won't read the file header or footer, and as such will fail if the stream is a full FBX file
        /// </remarks>
        /// <returns>The node</returns>
        /// <exception cref="FbxException">The FBX data was malformed
        /// for the reader's error level</exception>
        public FbxNode ReadNode(int version)
        {
            var endOffset       = (version > 7400) ? stream.ReadInt64() : stream.ReadInt32();
            var numProperties   = (version > 7400) ? stream.ReadInt64() : stream.ReadInt32();
            var propertyListLen = (version > 7400) ? stream.ReadInt64() : stream.ReadInt32();
            var nameLen         = stream.ReadByte();
            var name            = nameLen == 0 ? "" : Encoding.ASCII.GetString(stream.ReadBytes(nameLen));

            if (endOffset == 0)
            {
                // The end offset should only be 0 in a null node
                if (errorLevel >= ErrorLevel.Checked && (numProperties != 0 || propertyListLen != 0 || !string.IsNullOrEmpty(name)))
                {
                    throw new FbxException(stream.BaseStream.Position,
                                           "Invalid node; expected NULL record");
                }
                return(null);
            }

            var node = new FbxNode {
                Name = name
            };

            var propertyEnd = stream.BaseStream.Position + propertyListLen;

            // Read properties
            for (int i = 0; i < numProperties; i++)
            {
                node.Properties.Add(ReadProperty());
            }

            if (errorLevel >= ErrorLevel.Checked && stream.BaseStream.Position != propertyEnd)
            {
                throw new FbxException(stream.BaseStream.Position,
                                       "Too many bytes in property list, end point is " + propertyEnd);
            }

            // Read nested nodes
            var listLen = endOffset - stream.BaseStream.Position;

            if (errorLevel >= ErrorLevel.Checked && listLen < 0)
            {
                throw new FbxException(stream.BaseStream.Position,
                                       "Node has invalid end point");
            }
            if (listLen > 0)
            {
                FbxNode nested;
                do
                {
                    nested = ReadNode(version);
                    node.Nodes.Add(nested);
                } while (nested != null);
                if (errorLevel >= ErrorLevel.Checked && stream.BaseStream.Position != endOffset)
                {
                    throw new FbxException(stream.BaseStream.Position,
                                           "Too many bytes in node, end point is " + endOffset);
                }
            }
            return(node);
        }