/// <summary>
        /// Tries to read all properties that resides in this object instance.
        /// </summary>
        protected void DeserializeProperties()
        {
            Default     = this;
            _Properties = new DefaultPropertiesCollection();
            while (true)
            {
                var tag = new UDefaultProperty(Default);
                if (!tag.Deserialize())
                {
                    break;
                }
                _Properties.Add(tag);
            }

            // We need to keep the MemoryStream alive,
            // because we first deserialize the defaultproperties but we skip the values, which we'll deserialize later on by demand.
            if (Properties.Count == 0)
            {
                _Properties = null;
            }
        }
        /// <summary>
        /// Deserialize a default property value of a specified type.
        /// </summary>
        /// <param name="type">Kind of type to try deserialize.</param>
        /// <returns>The deserialized value if any.</returns>
        private string DeserializeDefaultPropertyValue(PropertyType type, ref DeserializeFlags deserializeFlags)
        {
            if (_Buffer.Position - _ValueOffset > Size)
            {
                throw new DeserializationException("End of defaultproperties stream reached...");
            }

            var    orgOuter      = _Outer;
            string propertyValue = String.Empty;

            try
            {
                // Deserialize Value
                switch (type)
                {
                case PropertyType.BoolProperty:
                {
                    var value = _BoolValue;
                    if (Size == 1 && _Buffer.Version < V3)
                    {
                        value = _Buffer.ReadByte() > 0;
                    }
                    propertyValue = value ? "true" : "false";
                    break;
                }

                case PropertyType.StrProperty:
                    propertyValue = $"\"{_Buffer.ReadText()}\"";
                    break;

                case PropertyType.NameProperty:
                    propertyValue = $"\"{_Buffer.ReadName()}\"";
                    break;

                case PropertyType.IntProperty:
                    propertyValue = _Buffer.ReadInt32().ToString(CultureInfo.InvariantCulture);
                    break;

#if BIOSHOCK
                case PropertyType.QwordProperty:
                    propertyValue = _Buffer.ReadInt64().ToString(CultureInfo.InvariantCulture);
                    break;

                case PropertyType.XWeakReferenceProperty:
                    propertyValue = $"\"XWeakReference\": \"?\":{_Buffer.ReadName()},\"?\":\"{_Buffer.ReadName()}\",\"?\":\"{_Buffer.ReadByte()}\",\"?\":\"{_Buffer.ReadName()}\"";
                    break;
#endif

                case PropertyType.FloatProperty:
                    propertyValue = _Buffer.ReadFloat().ToUFloat();
                    break;

                case PropertyType.ByteProperty:
                    if (_Buffer.Version >= V3 && Size == 8)
                    {
                        var enumValue = _Buffer.ReadName();
                        propertyValue = enumValue;
                        if (_Buffer.Version >= VEnumName)
                        {
                            propertyValue = $"\"{EnumName}.{propertyValue}\"";
                        }
                    }
                    else
                    {
                        propertyValue = _Buffer.ReadByte().ToString(CultureInfo.InvariantCulture);
                    }
                    break;

                case PropertyType.InterfaceProperty:
                case PropertyType.ComponentProperty:
                case PropertyType.ObjectProperty:
                {
                    var obj = _Buffer.ReadObject();
                    _Container.Record("object", obj);
                    if (obj != null)
                    {
                        bool inline = false;
                        // If true, object is an archetype or subobject.
                        if (obj.Outer == _Container && (deserializeFlags & DeserializeFlags.WithinStruct) == 0)
                        {
                            // Unknown objects are only deserialized on demand.
                            obj.BeginDeserializing();
                            if (obj.Properties != null && obj.Properties.Count > 0)
                            {
                                inline        = true;
                                propertyValue = obj.Decompile() + "\r\n" + UDecompilingState.Tabs;

                                _TempFlags |= DoNotAppendName;
                                if ((deserializeFlags & DeserializeFlags.WithinArray) != 0)
                                {
                                    _TempFlags    |= ReplaceNameMarker;
                                    propertyValue += $"\"%ARRAYNAME%\":\"{obj.Name}\"";
                                }
                                else
                                {
                                    propertyValue += $"\"{Name}\":\"{obj.Name}\"";
                                }
                            }
                        }

                        if (!inline)
                        {
                            // =CLASS'Package.Group(s)+.Name'
                            propertyValue = $"{{\"Class\":\"{obj.GetClassName()}\",\"Value\":\"{obj.GetOuterGroup()}\"}}";
                        }
                    }
                    else
                    {
                        // =none
                        propertyValue = "null";
                    }
                    break;
                }

                case PropertyType.ClassProperty:
                {
                    var obj = _Buffer.ReadObject();
                    _Container.Record("object", obj);
                    propertyValue = (obj != null ? $"{{\r\n\"Name\":\"{Name}\",\r\n\"Class\":\"{obj.Class.Name}\",\r\n" : "null");
                    break;
                }

                case PropertyType.DelegateProperty:
                {
                    _TempFlags |= DoNotAppendName;
                    int    outerIndex    = _Buffer.ReadObjectIndex();   // Where the assigned delegate property exists.
                    var    delegateValue = _Buffer.ReadName();
                    string delegateName  = ((string)(Name)).Substring(2, Name.Length - 12);
                    propertyValue = $"\"{delegateName}\":\"{delegateValue}\"";
                    break;
                }

                    #region HardCoded Struct Types
                case PropertyType.Color:
                {
                    string b = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);
                    string g = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);
                    string r = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);
                    string a = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);

                    propertyValue += $"{{\"r\":{r},\"g\":{g},\"b\":{b},\"a\":{a}}}";
                    break;
                }

                case PropertyType.LinearColor:
                {
                    string b = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string g = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string r = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string a = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);

                    propertyValue += $"{{\"r\":{r},\"g\":{g},\"b\":{b},\"a\":{a}}}";
                    break;
                }

                case PropertyType.Vector:
                {
                    string x = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string y = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string z = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);

                    propertyValue += $"{{\"x\":{x},\"y\":{y},\"z\":{z}}}";
                    break;
                }

                case PropertyType.TwoVectors:
                {
                    string v1 = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string v2 = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);

                    propertyValue += $"{{\"v1\":{v1},\"v2\":{v2}}}";
                    break;
                }

                case PropertyType.Vector4:
                {
                    string plane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);

                    propertyValue += plane;
                    break;
                }

                case PropertyType.Vector2D:
                {
                    string x = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string y = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);

                    propertyValue += $"{{\"x\":{x},\"y\":{y}}}";
                    break;
                }

                case PropertyType.Rotator:
                {
                    string pitch = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string yaw   = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string roll  = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);

                    propertyValue += $"{{\"Pitch\":{pitch},\"Yaw\":{yaw},\"Roll\":{roll}}}";
                    break;
                }

                case PropertyType.Guid:
                {
                    string a = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string b = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string c = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string d = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);

                    propertyValue += new Guid(
                        int.Parse(a)
                        , short.Parse(b)
                        , short.Parse(c)
                        , BitConverter.GetBytes(int.Parse(d)))
                                     .ToString();
                    break;
                }

                case PropertyType.Sphere:
                case PropertyType.Plane:
                {
                    string v = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string w = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);

                    propertyValue += $"{{\"v\":{v},\"w\":{w}}}";
                    break;
                }

                case PropertyType.Scale:
                {
                    string scale     = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string sheerRate = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string sheerAxis = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);

                    propertyValue += $"{{\"Scale\":{scale},\"SheerRate\":{sheerRate},\"SheerAxis\":{sheerAxis}}}";
                    break;
                }

                case PropertyType.Box:
                {
                    string min     = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string max     = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string isValid = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);

                    propertyValue += $"{{\"Min\":{min},\"Max\":{max},\"IsValid\":{isValid}}}";
                    break;
                }

                /*case PropertyType.InterpCurve:
                 * {
                 *  // HACK:
                 *  UPropertyTag tag = new UPropertyTag( _Owner );
                 *  tag.Serialize();
                 *  buffer.Seek( tag.ValueOffset, System.IO.SeekOrigin.Begin );
                 *
                 *  int curvescount = buffer.ReadIndex();
                 *  if( curvescount <= 0 )
                 *  {
                 *      break;
                 *  }
                 *  propertyvalue += tag.Name + "=(";
                 *  for( int i = 0; i < curvescount; ++ i )
                 *  {
                 *      propertyvalue += "(" + SerializeDefaultPropertyValue( PropertyType.InterpCurvePoint, buffer, ref serializeFlags ) + ")";
                 *      if( i != curvescount - 1 )
                 *      {
                 *          propertyvalue += ",";
                 *      }
                 *  }
                 *  propertyvalue += ")";
                 *  break;
                 * }*/

                /*case PropertyType.InterpCurvePoint:
                 * {
                 *  string InVal = SerializeDefaultPropertyValue( PropertyType.Float, buffer, ref serializeFlags );
                 *  string OutVal = SerializeDefaultPropertyValue( PropertyType.Float, buffer, ref serializeFlags );
                 *
                 *  propertyvalue += "InVal=" + InVal +
                 *      ",OutVal=" + OutVal;
                 *  break;
                 * }*/

                case PropertyType.Quat:
                {
                    propertyValue += DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    break;
                }

                case PropertyType.Matrix:
                {
                    string xPlane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    string yPlane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    string zPlane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    string wPlane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    propertyValue += $"{{\"XPlane\":{xPlane},\"YPlane\":{yPlane},\"ZPlane\":{zPlane},\"WPlane\":{wPlane}}}";
                    break;
                }

                case PropertyType.IntPoint:
                {
                    string x = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string y = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);

                    propertyValue += $"{{\"X\":{x},\"Y\":{y}}}";
                    break;
                }
                    #endregion

                case PropertyType.PointerProperty:
                case PropertyType.StructProperty:
                {
                    deserializeFlags |= DeserializeFlags.WithinStruct;
                    bool isHardCoded      = false;
                    var  hardcodedStructs = (PropertyType[])Enum.GetValues(typeof(PropertyType));
                    for (var i = (byte)PropertyType.StructOffset; i < hardcodedStructs.Length; ++i)
                    {
                        var structType = Enum.GetName(typeof(PropertyType), (byte)hardcodedStructs[i]);
                        if (string.Compare(ItemName, structType, StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            continue;
                        }

                        isHardCoded    = true;
                        propertyValue += DeserializeDefaultPropertyValue(hardcodedStructs[i], ref deserializeFlags);
                        break;
                    }

                    if (!isHardCoded)
                    {
                        // We have to modify the outer so that dynamic arrays within this struct
                        // will be able to find its variables to determine the array type.
                        FindProperty(out _Outer);
                        propertyValue += "{";
                        while (true)
                        {
                            var tag = new UDefaultProperty(_Container, _Outer);
                            if (tag.Deserialize())
                            {
                                // commented below was for inserting a [0] [1] etc. after the tag name
                                // var t = (tag.ArrayIndex > 0 && tag.Type != PropertyType.BoolProperty
                                //     ? $"{tag.ArrayIndex.ToString()}"
                                //     : string.Empty);
                                propertyValue += $"\"{tag.Name}\":{tag.DeserializeValue(deserializeFlags)},";
                            }
                            else
                            {
                                if (propertyValue.EndsWith(","))
                                {
                                    propertyValue = $"{propertyValue.Remove(propertyValue.Length - 1, 1)}}}";
                                }
                                break;
                            }
                        }
                    }
                    propertyValue = propertyValue.Length != 0 ? propertyValue : "";
                    break;
                }

                case PropertyType.ArrayProperty:
                {
                    int arraySize = _Buffer.ReadIndex();
                    _Container.Record("arraySize", arraySize.ToString());
                    if (arraySize == 0)
                    {
                        propertyValue = "null";
                        break;
                    }

                    // Find the property within the outer/owner or its inheritances.
                    // If found it has to modify the outer so structs within this array can find their array variables.
                    // Additionally we need to know the property to determine the array's type.
                    var arrayType = PropertyType.None;
                    if (FindProperty(out _Outer) is UArrayProperty property && property.InnerProperty != null)
                    {
                        arrayType = property.InnerProperty.Type;
                    }
                    // If we did not find a reference to the associated property(because of imports)
                    // then try to determine the array's type by scanning the definined array types.
                    else if (UnrealConfig.VariableTypes != null && UnrealConfig.VariableTypes.ContainsKey(Name))
                    {
                        var varTuple = UnrealConfig.VariableTypes[Name];
                        if (varTuple != null)
                        {
                            arrayType = varTuple.Item2;
                        }
                    }

                    if (arrayType == PropertyType.None)
                    {
                        propertyValue = "null";
                        break;
                    }

                    deserializeFlags |= DeserializeFlags.WithinArray;
                    if ((deserializeFlags & DeserializeFlags.WithinStruct) != 0)
                    {
                        // Hardcoded fix for InterpCurve and InterpCurvePoint.
                        if (string.Compare(Name, "Points", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            arrayType = PropertyType.StructProperty;
                        }

                        for (int i = 0; i < arraySize; ++i)
                        {
                            propertyValue += DeserializeDefaultPropertyValue(arrayType, ref deserializeFlags) + (i != arraySize - 1 ? "," : string.Empty);
                        }
                        propertyValue = $"{propertyValue}";
                    }
                    else
                    {
                        for (var i = 0; i < arraySize; ++i)
                        {
                            var elementValue = DeserializeDefaultPropertyValue(arrayType, ref deserializeFlags);
                            if ((_TempFlags & ReplaceNameMarker) != 0)
                            {
                                propertyValue += elementValue.Replace("%ARRAYNAME%", $"{Name}");
                                _TempFlags     = 0x00;
                            }
                            else
                            {
                                propertyValue += $"\"{Name}\":{elementValue}";
                            }

                            if (i == arraySize - 1)
                            {
                                propertyValue += "]\r\n" + UDecompilingState.Tabs;
                            }
                        }
                    }

                    _TempFlags |= DoNotAppendName;
                    break;
                }