LSLib.Granny.GR2.GR2Reader.ReadElement C# (CSharp) Method

ReadElement() private method

private ReadElement ( MemberDefinition definition, object node, Type propertyType, object parent ) : object
definition MemberDefinition
node object
propertyType System.Type
parent object
return object
        private object ReadElement(MemberDefinition definition, object node, Type propertyType, object parent)
        {
#if DEBUG_GR2_SERIALIZATION
            var offsetInFile = Stream.Position;
#endif

            var kind = definition.SerializationKind;
            Debug.Assert(kind == SerializationKind.Builtin || !definition.IsScalar);
            if (node == null && 
                propertyType != null && 
                !definition.IsScalar &&
                (kind == SerializationKind.Builtin || kind == SerializationKind.UserElement) && 
                // Variant construction is a special case as we don't know the struct defn beforehand
                definition.Type != MemberType.VariantReference)
            {
                node = Helpers.CreateInstance(propertyType);
            }

            switch (definition.Type)
            {
                case MemberType.Inline:
                    Debug.Assert(definition.Definition.IsValid);
#if DEBUG_GR2_SERIALIZATION
                    System.Console.WriteLine(String.Format(" === Inline Struct {0} === ", definition.Name));
#endif
                    if (kind == SerializationKind.UserElement || kind == SerializationKind.UserMember)
                        node = definition.Serializer.Read(this, definition.Definition.Resolve(this), definition, 0, parent);
                    else
                        node = ReadStruct(definition.Definition.Resolve(this), definition.Type, node, parent);
#if DEBUG_GR2_SERIALIZATION
                    System.Console.WriteLine(" === End Struct === ");
#endif
                    break;

                case MemberType.Reference:
                    {
                        Debug.Assert(definition.Definition.IsValid);
                        var r = ReadReference();

                        if (r.IsValid && parent != null)
                        {
                            var originalPos = Stream.Position;
                            Seek(r);
#if DEBUG_GR2_SERIALIZATION
                            System.Console.WriteLine(String.Format(" === Struct <{0}> at {1:X8} === ", definition.Name, Stream.Position));
#endif
                            if (kind == SerializationKind.UserElement || kind == SerializationKind.UserMember)
                                node = definition.Serializer.Read(this, definition.Definition.Resolve(this), definition, 0, parent);
                            else
                                node = ReadStruct(definition.Definition.Resolve(this), definition.Type, node, parent);
#if DEBUG_GR2_SERIALIZATION
                            System.Console.WriteLine(" === End Struct === ");
#endif
                            Stream.Seek(originalPos, SeekOrigin.Begin);
                        }
                        else
                            node = null;
                        break;
                    }

                case MemberType.VariantReference:
                    {
                        var structRef = ReadStructReference();
                        var r = ReadReference();

                        if (r.IsValid && parent != null)
                        {
                            var structDefn = structRef.Resolve(this);
                            if (definition.TypeSelector != null && definition.Type == MemberType.VariantReference)
                                propertyType = definition.TypeSelector.SelectType(definition, structDefn, parent);
                            if (propertyType != null)
                                node = Helpers.CreateInstance(propertyType);

                            if (node != null)
                            {
                                var originalPos = Stream.Position;
                                Seek(r);
#if DEBUG_GR2_SERIALIZATION
                                System.Console.WriteLine(String.Format(" === Variant Struct <{0}> at {1:X8} === ", definition.Name, Stream.Position));
#endif
                                if (kind == SerializationKind.UserElement || kind == SerializationKind.UserMember)
                                    node = definition.Serializer.Read(this, structDefn, definition, 0, parent);
                                else
                                    node = ReadStruct(structRef.Resolve(this), definition.Type, node, parent);
#if DEBUG_GR2_SERIALIZATION
                                System.Console.WriteLine(" === End Struct === ");
#endif
                                Stream.Seek(originalPos, SeekOrigin.Begin);
                            }
                        }
                        else
                            node = null;
                        break;
                    }

                case MemberType.ArrayOfReferences:
                    {
                        // Serializing as a struct member is nooooot a very good idea here.
                        Debug.Assert(kind != SerializationKind.UserMember);
                        Debug.Assert(definition.Definition.IsValid);
                        var indices = ReadArrayIndicesReference();
#if DEBUG_GR2_SERIALIZATION
                        System.Console.WriteLine(String.Format("    Array of references at [{0:X8}]", indices.Offset));
#endif

                        Debug.Assert(indices.IsValid == (indices.Size != 0));

                        if (indices.IsValid && node != null && parent != null)
                        {
                            var items = node as System.Collections.IList;
                            var type = items.GetType().GetGenericArguments().Single();

                            var refs = indices.Resolve(this);
                            var originalPos = Stream.Position;
                            for (int i = 0; i < refs.Count; i++)
                            {
                                Seek(refs[i]);
#if DEBUG_GR2_SERIALIZATION
                                System.Console.WriteLine(String.Format(" === Struct <{0}> at {1:X8} === ", definition.Name, Stream.Position));
#endif
                                if (kind == SerializationKind.UserElement)
                                {
                                    object element = definition.Serializer.Read(this, definition.Definition.Resolve(this), definition, 0, parent);
                                    items.Add(element);
                                }
                                else
                                {
                                    object element = Helpers.CreateInstance(type);
                                    // TODO: Only create a new instance if we don't have a CachedStruct available!
                                    element = ReadStruct(definition.Definition.Resolve(this), definition.Type, element, parent);
                                    items.Add(element);

                                }
#if DEBUG_GR2_SERIALIZATION
                                System.Console.WriteLine(" === End Struct === ");
#endif
                            }

                            Stream.Seek(originalPos, SeekOrigin.Begin);
                            node = items;
                        }
                        else
                            node = null;
                        break;
                    }

                case MemberType.ReferenceToArray:
                case MemberType.ReferenceToVariantArray:
                    {
                        StructReference structRef;
                        if (definition.Type == MemberType.ReferenceToVariantArray)
                            structRef = ReadStructReference();
                        else
                            structRef = definition.Definition;

                        var itemsRef = ReadArrayReference();

                        Debug.Assert(itemsRef.IsValid == (itemsRef.Size != 0));

                        if (itemsRef.IsValid && 
                            parent != null &&
                            (node != null || kind == SerializationKind.UserMember))
                        {
                            Debug.Assert(structRef.IsValid);
                            var structType = structRef.Resolve(this);
                            var originalPos = Stream.Position;
                            Seek(itemsRef);

                            if (kind == SerializationKind.UserMember)
                            {
                                // For ReferenceTo(Variant)Array, we start serialization after resolving the array ref itself.
                                node = definition.Serializer.Read(this, structType, definition, itemsRef.Size, parent);
                            }
                            else
                            {
                                var items = node as System.Collections.IList;
                                var type = items.GetType().GetGenericArguments().Single();
                                if (definition.Type == MemberType.ReferenceToVariantArray && 
                                    kind != SerializationKind.UserElement &&
                                    definition.TypeSelector != null)
                                    type = definition.TypeSelector.SelectType(definition, structType, parent);

                                for (int i = 0; i < itemsRef.Size; i++)
                                {
#if DEBUG_GR2_SERIALIZATION
                                    System.Console.WriteLine(String.Format(" === Struct <{0}> at {1:X8} === ", definition.Name, Stream.Position));
#endif
                                    if (kind == SerializationKind.UserElement)
                                    {
                                        object element = definition.Serializer.Read(this, structType, definition, 0, parent);
                                        items.Add(element);
                                    }
                                    else
                                    {
                                        object element = Helpers.CreateInstance(type);
                                        element = ReadStruct(structType, definition.Type, element, parent);
                                        items.Add(element);
                                    }
#if DEBUG_GR2_SERIALIZATION
                                    System.Console.WriteLine(" === End Struct === ");
#endif
                                }
                            }

                            Stream.Seek(originalPos, SeekOrigin.Begin);
                        }
                        else
                            node = null;
                        break;
                    }

                case MemberType.String:
                    var str = ReadStringReference();
                    if (str.IsValid)
                        node = str.Resolve(this);
                    else
                        node = null;
                    break;

                case MemberType.Transform:
                    var transform = new Transform();
                    transform.Flags = Reader.ReadUInt32();

                    for (int i = 0; i < 3; i++)
                        transform.Translation[i] = Reader.ReadSingle();

                    transform.Rotation.X = Reader.ReadSingle();
                    transform.Rotation.Y = Reader.ReadSingle();
                    transform.Rotation.Z = Reader.ReadSingle();
                    transform.Rotation.W = Reader.ReadSingle();

                    for (int i = 0; i < 3; i++)
                    {
                        for (int j = 0; j < 3; j++)
                            transform.ScaleShear[i, j] = Reader.ReadSingle();
                    }

                    node = transform;
                    break;

                case MemberType.Real16:
                    throw new NotImplementedException("TODO");

                case MemberType.Real32:
                    node = Reader.ReadSingle();
                    break;

                case MemberType.Int8:
                case MemberType.BinormalInt8:
                    node = Reader.ReadSByte();
                    break;

                case MemberType.UInt8:
                case MemberType.NormalUInt8:
                    node = Reader.ReadByte();
                    break;

                case MemberType.Int16:
                case MemberType.BinormalInt16:
                    node = Reader.ReadInt16();
                    break;

                case MemberType.UInt16:
                case MemberType.NormalUInt16:
                    node = Reader.ReadUInt16();
                    break;

                case MemberType.Int32:
                    node = Reader.ReadInt32();
                    break;

                case MemberType.UInt32:
                    node = Reader.ReadUInt32();
                    break;

                default:
                    throw new ParsingException(String.Format("Unhandled member type: {0}", definition.Type.ToString()));
            }

#if DEBUG_GR2_SERIALIZATION
            if (node != null)
                System.Console.WriteLine(String.Format("    [{0:X8}] {1}: {2}", offsetInFile, definition.Name, node.ToString()));
            else
                System.Console.WriteLine(String.Format("    [{0:X8}] {1}: <null>", offsetInFile, definition.Name));
#endif

            return node;
        }