public async Task PushContentReference(AbsoluteId referencerId, AssetId contentId, IGraphNode contentNode, NodeIndex index)
        {
            gameDispatcher.EnsureAccess();
            using (await loader.LockDatabaseAsynchronously())
            {
                if (!references.ContainsKey(referencerId))
                {
                    throw new InvalidOperationException("The given referencer is not registered.");
                }

                var referencer = references[referencerId];
                List <ReferenceAccessor> accessors;
                if (!referencer.TryGetValue(contentId, out accessors))
                {
                    accessors             = new List <ReferenceAccessor>();
                    referencer[contentId] = accessors;
                }
                var accessor = new ReferenceAccessor(contentNode, index);
                if (accessors.Contains(accessor))
                {
                    // If the reference already exists, clear it and re-enter
                    await ClearContentReference(referencerId, contentId, contentNode, index);
                    await PushContentReference(referencerId, contentId, contentNode, index);

                    return;
                }

                accessors.Add(accessor);

                object value;
                if (contents.TryGetValue(contentId, out value))
                {
                    accessor.Update(value);
                }
                else
                {
                    // Build only if not requested yet (otherwise we just need to wait for ReplaceContent() to be called, it will also replace this reference since it was added just before)
                    if (buildPending.Add(contentId))
                    {
                        loader.BuildAndReloadAsset(contentId);
                    }
                }
            }
        }
        public async Task ClearContentReference(AbsoluteId referencerId, AssetId contentId, IGraphNode contentNode, NodeIndex index)
        {
            gameDispatcher.EnsureAccess();
            using (await loader.LockDatabaseAsynchronously())
            {
                if (!references.ContainsKey(referencerId))
                {
                    throw new InvalidOperationException("The given referencer is not registered.");
                }

                var referencer = references[referencerId];
                if (!referencer.ContainsKey(contentId))
                {
                    throw new InvalidOperationException("The given content is not registered to the given referencer.");
                }

                var accessors    = referencer[contentId];
                var accessor     = new ReferenceAccessor(contentNode, index);
                var accesorIndex = accessors.IndexOf(accessor);
                if (accesorIndex < 0)
                {
                    throw new InvalidOperationException("The given reference is not registered for the given content and referencer.");
                }

                accessors.RemoveAt(accesorIndex);
                if (accessors.Count == 0)
                {
                    referencer.Remove(contentId);
                    // Unload the content if nothing else is referencing it anymore
                    var unloadContent = references.Values.SelectMany(x => x.Keys).All(x => x != contentId);
                    if (unloadContent)
                    {
                        await loader.UnloadAsset(contentId);

                        contents.Remove(contentId);
                    }
                }
            }
        }
Example #3
0
 public static TRet Create <TRet>(ref StringChunk reference, Func <StringReference, TRet> outputFunc)
 {
     return(ReferenceAccessor.Create(ref reference, r => outputFunc(Create(r))));
 }
Example #4
0
 public static void Create(ref StringChunk reference, Action <StringReference> outputAct)
 {
     ReferenceAccessor.Create(ref reference, r => outputAct(Create(r)));
 }