コード例 #1
0
ファイル: FbxBinary.cs プロジェクト: UkooLabs/FBXSharpie
        // Gets a single timestamp component
        static int GetTimestampVar(FbxNode timestamp, string element)
        {
            var elementNode = timestamp[element].FirstOrDefault();

            if (elementNode != null && elementNode.Properties.Length > 0)
            {
                var prop = elementNode.Properties[0];
                if (prop.TryGetAsLong(out var longValue))
                {
                    return((int)longValue);
                }
            }
            throw new FbxException(-1, "Timestamp has no " + element);
        }
コード例 #2
0
        // Gets a single timestamp component
        static int GetTimestampVar(FbxNode timestamp, string element)
        {
            var elementNode = timestamp[element];

            if (elementNode != null && elementNode.Properties.Length > 0)
            {
                var prop = elementNode.Properties[0].AsObject;
                if (prop is int || prop is long)
                {
                    return((int)prop);
                }
            }
            throw new FbxException(timePath, -1, "Timestamp has no " + element);
        }
コード例 #3
0
ファイル: FbxAsciiWriter.cs プロジェクト: UkooLabs/FBXSharpie
        // 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.Length; 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.Length > 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");
        }
コード例 #4
0
ファイル: FbxBinaryWriter.cs プロジェクト: orage/FBXSharpie
        // 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
            {
                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;
                long propertyLengthPos;
                if (document.Version >= FbxVersion.v7_5)
                {
                    stream.Write((long)0);                     // End offset placeholder
                    stream.Write((long)node.Properties.Length);
                    propertyLengthPos = stream.BaseStream.Position;
                    stream.Write((long)0);                     // Property length placeholder
                }
                else
                {
                    stream.Write(0);                     // End offset placeholder
                    stream.Write(node.Properties.Length);
                    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.Length; i++)
                {
                    WriteProperty(node.Properties[i].AsObject, 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.Length > 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;

                nodePath.Pop();
            }
        }
コード例 #5
0
ファイル: FbxAsciiReader.cs プロジェクト: orage/FBXSharpie
        /// <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 Identifier id))
            {
                if (first is EndOfStream)
                {
                    return(null);
                }

                throw new FbxException(_fbxAsciiFileInfo,
                                       "Unexpected '" + first + "', expected an identifier");
            }
            var node = new FbxNode {
                Name = id.Value
            };

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

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

                    case '}':
                    case ':':
                    case ',':
                        throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + c + "' in property list");
                    }
                }
                node.AddProperty(new FbxValue(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 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 = ReadToken();

            while (!'}'.Equals(endBrace))
            {
                prevToken = endBrace;                 // If it's not an end brace, the next node will need it
                node.AddNode(ReadNode());
                endBrace = ReadToken();
            }
            if (node.Nodes.Length < 1)            // If there's an open brace, we want that to be preserved
            {
                node.AddNode(null);
            }

            return(node);
        }
コード例 #6
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.Length; j++)
            {
                var p = node.Properties[j].AsObject;
                if (p == null)
                {
                    continue;
                }

                if (!first)
                {
                    sb.Append(',');
                }

                sb.Append(' ');
                if (p is string)
                {
                    sb.Append('"').Append(p).Append('"');
                }
                else if (p is Array array)
                {
                    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.GetTypeInfo().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().GetTypeInfo().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.Length > 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();
        }
コード例 #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(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 {
                Name = 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);
        }
コード例 #8
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.Length);
                    propertyLengthPos = stream.BaseStream.Position;
                    stream.Write((long)0);                     // Property length placeholder
                }
                else
                {
                    stream.Write(0);                     // End offset placeholder
                    stream.Write(node.Properties.Length);
                    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.Length; 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.Length > 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;
            }
        }
コード例 #9
0
ファイル: FbxNodeList.cs プロジェクト: UkooLabs/FBXSharpie
 /// <summary>
 /// Add node to node array
 /// </summary>
 /// <param name="node"></param>
 public void AddNode(FbxNode node)
 {
     _nodes.Add(node);
 }
コード例 #10
0
ファイル: FbxAsciiReader.cs プロジェクト: UkooLabs/FBXSharpie
        /// <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.Length < 1)            // If there's an open brace, we want that to be preserved
            {
                node.AddNode(null);
            }

            return(node);
        }