Ejemplo n.º 1
0
        /// <summary>
        /// Reloads an asset. If possible, same recursively referenced objects are reused.
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="settings">The settings.</param>
        /// <returns>True if it could be reloaded, false otherwise.</returns>
        /// <exception cref="System.InvalidOperationException">Asset not loaded through this AssetManager.</exception>
        public bool Reload(object obj, AssetManagerLoaderSettings settings = null)
        {
            if (settings == null)
            {
                settings = AssetManagerLoaderSettings.Default;
            }

            lock (LoadedAssetUrls)
            {
                AssetReference assetReference;
                if (!LoadedAssetReferences.TryGetValue(obj, out assetReference))
                {
                    return(false);
                }

                var url = assetReference.Url;

                using (var profile = Profiler.Begin(AssetProfilingKeys.AssetReload, url))
                {
                    DeserializeObject(url, obj.GetType(), obj, settings);
                }

                return(true);
            }
        }
Ejemplo n.º 2
0
        private object DeserializeObject(string url, Type type, object obj, AssetManagerLoaderSettings settings)
        {
            var serializeOperations = new Queue <DeserializeOperation>();

            serializeOperations.Enqueue(new DeserializeOperation(null, url, type, obj));

            AssetReference reference = null;

            if (obj != null)
            {
                reference = FindDeserializedObject(url, type);
                if (reference.Object != obj)
                {
                    throw new InvalidOperationException("Object doesn't match, can't reload");
                }
            }

            // Let's put aside old references, so that we unload them only afterwise (avoid a referenced object to be unloaded for no reason)
            HashSet <AssetReference> references = null;

            if (reference != null)
            {
                // Let's collect dependent reference, and reset current list
                references           = reference.References;
                reference.References = new HashSet <AssetReference>();

                // Mark object as not deserialized yet
                reference.Deserialized = false;
            }

            bool   isFirstOperation = true;
            object result           = null;

            while (serializeOperations.Count > 0)
            {
                var serializeOperation = serializeOperations.Dequeue();
                var deserializedObject = DeserializeObject(serializeOperations, serializeOperation.ParentAssetReference, serializeOperation.Url, serializeOperation.ObjectType, serializeOperation.Object, settings);
                if (isFirstOperation)
                {
                    result           = deserializedObject;
                    isFirstOperation = false;
                }
            }

            if (reference != null)
            {
                foreach (var dependentReference in references)
                {
                    DecrementReference(dependentReference, false);
                }
            }

            return(result);
        }
Ejemplo n.º 3
0
        internal object DeserializeObjectRecursive(AssetReference parentAssetReference, out AssetReference assetReference,
                                                   string url, Type objType, AssetManagerLoaderSettings settings, ContentSerializerContext otherContext, Stream stream, Type headerObjType, ConverterContext converterContext = null)
        {
            // Resolve URL
            ObjectId objectId;

            if (!FileProvider.AssetIndexMap.TryGetValue(url, out objectId))
            {
                throw new InvalidOperationException(string.Format("Asset [{0}] not found.", url));
            }

            // Find serializer
            var serializer = Serializer.GetSerializer(headerObjType, objType);

            if (serializer == null)
            {
                throw new InvalidOperationException(string.Format("Content serializer for {0}/{1} could not be found.", headerObjType, objType));
            }
            var contentSerializerContext = new ContentSerializerContext(url, ArchiveMode.Deserialize, this);

            contentSerializerContext.chunkReferences.AddRange(otherContext.chunkReferences);

            // Create AssetReference
            assetReference = new AssetReference(objectId, url, parentAssetReference == null);
            contentSerializerContext.AssetReference = assetReference;

            var result = serializer.Construct(contentSerializerContext);

            var streamReader = new BinarySerializationReader(stream);

            PrepareSerializerContext(contentSerializerContext, streamReader.Context);
            contentSerializerContext.ConverterContext = converterContext;

            result = contentSerializerContext.SerializeContent(streamReader, serializer, result);

            SetAssetObject(assetReference, result);

            // Add reference
            if (parentAssetReference != null)
            {
                parentAssetReference.References.Add(assetReference);
            }

            return(result);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Loads an asset from the specified URL.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="url">The URL.</param>
        /// <param name="settings">The settings.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">url</exception>
        public object Load(Type type, string url, AssetManagerLoaderSettings settings = null)
        {
            if (settings == null)
            {
                settings = AssetManagerLoaderSettings.Default;
            }

            if (url == null)
            {
                throw new ArgumentNullException("url");
            }

            lock (LoadedAssetUrls)
            {
                using (var profile = Profiler.Begin(AssetProfilingKeys.AssetLoad, url))
                {
                    return(DeserializeObject(url, type, null, settings));
                }
            }
        }
Ejemplo n.º 5
0
        public T Load <T>(string url, AssetManagerLoaderSettings settings = null) where T : class
        {
            if (settings == null)
            {
                settings = AssetManagerLoaderSettings.Default;
            }

            if (url == null)
            {
                throw new ArgumentNullException("url");
            }

            lock (loadedAssetsByUrl)
            {
                using (var profile = Profiler.Begin(AssetProfilingKeys.AssetLoad, url))
                {
                    AssetReference assetReference;
                    return((T)DeserializeObject(null, out assetReference, url, typeof(T), settings));
                }
            }
        }
Ejemplo n.º 6
0
        private object DeserializeObject(Queue <DeserializeOperation> serializeOperations, AssetReference parentAssetReference, string url, Type objType, object obj, AssetManagerLoaderSettings settings)
        {
            // Try to find already loaded object
            AssetReference assetReference = FindDeserializedObject(url, objType);

            if (assetReference != null && assetReference.Deserialized)
            {
                // Add reference
                bool isRoot = parentAssetReference == null;
                if (isRoot || parentAssetReference.References.Add(assetReference))
                {
                    IncrementReference(assetReference, isRoot);
                }

                return(assetReference.Object);
            }

            if (!FileProvider.FileExists(url))
            {
                HandleAssetNotFound(url);
                return(null);
            }

            ContentSerializerContext contentSerializerContext;
            object result;

            // Open asset binary stream
            using (var stream = FileProvider.OpenStream(url, VirtualFileMode.Open, VirtualFileAccess.Read))
            {
                // File does not exist
                // TODO/Benlitz: Add a log entry for that, it's not expected to happen
                if (stream == null)
                {
                    return(null);
                }

                Type headerObjType = null;

                // Read header
                var streamReader = new BinarySerializationReader(stream);
                var chunkHeader  = ChunkHeader.Read(streamReader);
                if (chunkHeader != null)
                {
                    headerObjType = Type.GetType(chunkHeader.Type);
                }

                // Find serializer
                var serializer = Serializer.GetSerializer(headerObjType, objType);
                if (serializer == null)
                {
                    throw new InvalidOperationException(string.Format("Content serializer for {0}/{1} could not be found.", headerObjType, objType));
                }
                contentSerializerContext = new ContentSerializerContext(url, ArchiveMode.Deserialize, this)
                {
                    LoadContentReferences = settings.LoadContentReferences
                };

                // Read chunk references
                if (chunkHeader != null && chunkHeader.OffsetToReferences != -1)
                {
                    // Seek to where references are stored and deserialize them
                    streamReader.NativeStream.Seek(chunkHeader.OffsetToReferences, SeekOrigin.Begin);
                    contentSerializerContext.SerializeReferences(streamReader);
                    streamReader.NativeStream.Seek(chunkHeader.OffsetToObject, SeekOrigin.Begin);
                }

                if (assetReference == null)
                {
                    // Create AssetReference
                    assetReference = new AssetReference(url, parentAssetReference == null);
                    contentSerializerContext.AssetReference = assetReference;
                    result = obj ?? serializer.Construct(contentSerializerContext);
                    SetAssetObject(assetReference, result);
                }
                else
                {
                    result = assetReference.Object;
                    contentSerializerContext.AssetReference = assetReference;
                }

                assetReference.Deserialized = true;

                PrepareSerializerContext(contentSerializerContext, streamReader.Context);

                contentSerializerContext.SerializeContent(streamReader, serializer, result);

                // Add reference
                if (parentAssetReference != null)
                {
                    parentAssetReference.References.Add(assetReference);
                }
            }

            if (settings.LoadContentReferences)
            {
                // Process content references
                // TODO: Should we work at ChunkReference level?
                foreach (var contentReference in contentSerializerContext.ContentReferences)
                {
                    bool shouldBeLoaded = true;

                    //AssetReference childReference;

                    if (settings.ContentFilter != null)
                    {
                        settings.ContentFilter(contentReference, ref shouldBeLoaded);
                    }

                    if (shouldBeLoaded)
                    {
                        serializeOperations.Enqueue(new DeserializeOperation(assetReference, contentReference.Location, contentReference.Type, contentReference.ObjectValue));
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Loads an asset from the specified URL asynchronously.
 /// </summary>
 /// <param name="type">The type.</param>
 /// <param name="url">The URL.</param>
 /// <param name="settings">The settings.</param>
 /// <returns></returns>
 public Task <object> LoadAsync(Type type, string url, AssetManagerLoaderSettings settings = null)
 {
     return(Task.Factory.StartNew(() => Load(type, url, settings)));
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Loads an asset from the specified URL asynchronously.
 /// </summary>
 /// <typeparam name="T">The content type.</typeparam>
 /// <param name="url">The URL to load from.</param>
 /// <param name="settings">The settings. If null, fallback to <see cref="AssetManagerLoaderSettings.Default" />.</param>
 /// <returns></returns>
 public Task <T> LoadAsync <T>(string url, AssetManagerLoaderSettings settings = null) where T : class
 {
     return(Task.Factory.StartNew(() => Load <T>(url, settings)));
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Loads an asset from the specified URL.
 /// </summary>
 /// <typeparam name="T">The content type.</typeparam>
 /// <param name="url">The URL to load from.</param>
 /// <param name="settings">The settings. If null, fallback to <see cref="AssetManagerLoaderSettings.Default" />.</param>
 /// <returns></returns>
 public T Load <T>(string url, AssetManagerLoaderSettings settings = null) where T : class
 {
     return((T)Load(typeof(T), url, settings));
 }
Ejemplo n.º 10
0
        internal object DeserializeObject(AssetReference parentAssetReference, out AssetReference assetReference, string url, Type objType, AssetManagerLoaderSettings settings, ConverterContext converterContext = null)
        {
            // Resolve URL
            ObjectId objectId;

            if (!FileProvider.AssetIndexMap.TryGetValue(url, out objectId))
            {
                throw new InvalidOperationException(string.Format("Asset [{0}] not found.", url));
            }

            // Try to find already loaded object
            if (loadedAssetsByUrl.TryGetValue(objectId, out assetReference))
            {
                while (assetReference != null && !objType.GetTypeInfo().IsAssignableFrom(assetReference.Object.GetType().GetTypeInfo()))
                {
                    assetReference = assetReference.Next;
                }

                if (assetReference != null)
                {
                    // Add reference
                    bool isRoot = parentAssetReference == null;
                    if (isRoot || parentAssetReference.References.Add(assetReference))
                    {
                        IncrementReference(assetReference, isRoot);
                    }

                    return(assetReference.Object);
                }
            }

            if (!FileProvider.FileExists(url))
            {
                throw new InvalidOperationException(string.Format("Asset [{0}] not found.", url));
            }

            ContentSerializerContext contentSerializerContext;
            object result;

            // Open asset binary stream
            using (var stream = FileProvider.OpenStream(url, VirtualFileMode.Open, VirtualFileAccess.Read))
            {
                // File does not exist
                // TODO/Benlitz: Add a log entry for that, it's not expected to happen
                if (stream == null)
                {
                    return(null);
                }

                Type headerObjType = null;

                // Read header
                var streamReader = new BinarySerializationReader(stream);
                var chunkHeader  = ChunkHeader.Read(streamReader);
                if (chunkHeader != null)
                {
                    headerObjType = Type.GetType(chunkHeader.Type);
                }

                // Find serializer
                var serializer = Serializer.GetSerializer(headerObjType, objType);
                if (serializer == null)
                {
                    throw new InvalidOperationException(string.Format("Content serializer for {0}/{1} could not be found.", headerObjType, objType));
                }
                contentSerializerContext = new ContentSerializerContext(url, ArchiveMode.Deserialize, this);

                // Read chunk references
                if (chunkHeader != null && chunkHeader.OffsetToReferences != -1)
                {
                    // Seek to where references are stored and deserialize them
                    streamReader.NativeStream.Seek(chunkHeader.OffsetToReferences, SeekOrigin.Begin);
                    contentSerializerContext.SerializeReferences(streamReader);
                    streamReader.NativeStream.Seek(chunkHeader.OffsetToObject, SeekOrigin.Begin);
                }

                // Create AssetReference
                assetReference = new AssetReference(objectId, url, parentAssetReference == null);
                contentSerializerContext.AssetReference = assetReference;

                result = serializer.Construct(contentSerializerContext);

                PrepareSerializerContext(contentSerializerContext, streamReader.Context);
                contentSerializerContext.ConverterContext = converterContext;

                result = contentSerializerContext.SerializeContent(streamReader, serializer, result);

                SetAssetObject(assetReference, result);

                // Add reference
                if (parentAssetReference != null)
                {
                    parentAssetReference.References.Add(assetReference);
                }
            }

            if (settings.LoadContentReferences)
            {
                // Process content references
                // TODO: Should we work at ChunkReference level?
                foreach (var contentReference in contentSerializerContext.ContentReferences)
                {
                    bool shouldBeLoaded = true;

                    AssetReference childReference;

                    if (settings.ContentFilter != null)
                    {
                        settings.ContentFilter(contentReference, ref shouldBeLoaded);
                    }

                    if (shouldBeLoaded)
                    {
                        contentReference.ObjectValue = DeserializeObject(assetReference, out childReference, contentReference.Location, contentReference.Type, settings);
                    }
                }
            }

            return(result);
        }