예제 #1
0
        // Adds the given node text to the string
        void BuildString(FbxNode node, LineStringBuilder sb, FbxVersion version, int indentLevel = 0)
        {
            // Write identifier
            sb.Indent(indentLevel);

            node.Identifier.WriteAscii(version, sb, indentLevel);

            // 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(" ");

                p.WriteAscii(version, sb, indentLevel);

                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, version, indentLevel + 1);
                }

                sb.Indent(indentLevel);

                sb.Append("}");
            }
            sb.Append("\n");
        }
예제 #2
0
파일: FbxBinary.cs 프로젝트: tankyx/actools
        // Gets a single timestamp component
        static int GetTimestampVar(FbxNode timestamp, string element)
        {
            var elementNode = timestamp[element].FirstOrDefault();

            if (elementNode != null && elementNode.Properties.Count > 0)
            {
                var prop = elementNode.Properties[0];
                if (prop.TryGetAsLong(out var longValue))
                {
                    return((int)longValue);
                }
            }
            throw new FbxException(-1, "Timestamp has no " + element);
        }
예제 #3
0
 /// <summary>
 /// Add node to node array
 /// </summary>
 /// <param name="node"></param>
 public void AddNode(FbxNode node)
 {
     Nodes.Add(node);
 }
예제 #4
0
        // Writes a single document to the buffer
        void WriteNode(FbxDocument document, FbxNode node)
        {
            if (node == null)
            {
                var data = document.Version >= FbxVersion.v7_5 ? nullData7500 : nullData;
                stream.BaseStream.Write(data, 0, data.Length);
            }
            else
            {
                // Header
                var  endOffsetPos = stream.BaseStream.Position;
                long propertyLengthPos;
                if (document.Version >= FbxVersion.v7_5)
                {
                    stream.Write((long)0); // End offset placeholder
                    stream.Write((long)node.Properties.Count);
                    propertyLengthPos = stream.BaseStream.Position;
                    stream.Write((long)0); // Property length placeholder
                }
                else
                {
                    stream.Write(0); // End offset placeholder
                    stream.Write(node.Properties.Count);
                    propertyLengthPos = stream.BaseStream.Position;
                    stream.Write(0); // Property length placeholder
                }

                node.Identifier.WriteBinary(document.Version, stream);

                // Write properties and length
                var propertyBegin = stream.BaseStream.Position;
                for (int i = 0; i < node.Properties.Count; i++)
                {
                    WriteProperty(document.Version, node.Properties[i]);
                }
                var propertyEnd = stream.BaseStream.Position;
                stream.BaseStream.Position = propertyLengthPos;
                if (document.Version >= FbxVersion.v7_5)
                {
                    stream.Write(propertyEnd - propertyBegin);
                }
                else
                {
                    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(document, n);
                    }
                    WriteNode(document, null);
                }

                // Write end offset
                var dataEnd = stream.BaseStream.Position;
                stream.BaseStream.Position = endOffsetPos;
                if (document.Version >= FbxVersion.v7_5)
                {
                    stream.Write(dataEnd);
                }
                else
                {
                    stream.Write((int)dataEnd);
                }

                stream.BaseStream.Position = dataEnd;
            }
        }
예제 #5
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();

            if (!(first is IdentifierToken id))
            {
                if (first is Token tok && tok.TokenType == TokenType.EndOfStream)
                {
                    return(null);
                }
                throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + first + "', expected an identifier");
            }
            var node = new FbxNode(id);

            // Read properties
            Token token       = ReadToken();
            bool  expectComma = false;

            while (token.TokenType != TokenType.OpenBrace && token.TokenType != TokenType.Identifier && token.TokenType != TokenType.CloseBrace)
            {
                if (expectComma)
                {
                    if (token.TokenType != TokenType.Comma)
                    {
                        throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + token + "', expected a ','");
                    }
                    expectComma = false;
                    token       = ReadToken();
                    continue;
                }

                if (token.TokenType == TokenType.Asterix)
                {
                    token = ReadArray();
                }
                else if (token.TokenType == TokenType.CloseBrace || token.TokenType == TokenType.Comma)
                {
                    throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + token.TokenType + "' in property list");
                }

                node.AddProperty(token);
                expectComma = true; // The final comma before the open brace isn't required
                token       = ReadToken();
            }
            // 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.TokenType == TokenType.Identifier || token.TokenType == TokenType.CloseBrace)
            {
                _tokenStack.Push(token);
                return(node);
            }
            // The while loop can't end unless we're at an open brace, so we can continue right on
            Token endBrace = ReadToken();

            while (endBrace.TokenType != TokenType.CloseBrace)
            {
                _tokenStack.Push(endBrace);
                node.AddNode(ReadNode());
                endBrace = ReadToken();
            }
            if (node.Nodes.Count < 1) // If there's an open brace, we want that to be preserved
            {
                node.AddNode(null);
            }

            return(node);
        }
예제 #6
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(FbxDocument document)
        {
            var endOffset       = document.Version >= FbxVersion.v7_5 ? stream.ReadInt64() : stream.ReadInt32();
            var numProperties   = document.Version >= FbxVersion.v7_5 ? stream.ReadInt64() : stream.ReadInt32();
            var propertyListLen = document.Version >= FbxVersion.v7_5 ? 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(new IdentifierToken(name));

            var propertyEnd = stream.BaseStream.Position + propertyListLen;

            // Read properties
            for (int i = 0; i < numProperties; i++)
            {
                node.AddProperty(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(document);
                    node.AddNode(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);
        }