public BufferedAction(bool isAdd, QueryMatchID id, QueryArgs args) : this(isAdd ? ActionKind.AddSingle : ActionKind.RemoveSingle)
 {
     QueryId    = id;
     SingleArgs = args;
 }
 static void ModifySetQueryNoop(QueryMatchID queryMatchID, SetQueryArgs queryArgs)
 {
 }
 public BufferedAction(ActionKind kind, QueryMatchID id) : this(kind)
 {
     QueryId = id;
 }
 void RegisterSetQuery(QueryMatchID queryMatchID, SetQueryArgs queryArgs)
 {
     EnqueueUpdate(new BufferedAction(true, queryMatchID, queryArgs));
 }
 // This dummy function is used to prevent errors from happening if a query tries to unregister after unload
 static bool UnregisterQueryNoop(QueryMatchID queryMatchID, bool allMatches)
 {
     return(false);
 }
 public BufferedAction(QueryMatchID id, SetQueryArgs args) : this(ActionKind.ModifyGroup)
 {
     QueryId   = id;
     GroupArgs = args;
 }
Beispiel #7
0
        internal void Modify(QueryMatchID id, SetQueryArgs args)
        {
            if (!Data.MatchIdToIndex.TryGetValue(id, out var groupIndex))
            {
                return;
            }

            Assert.IsTrue(Data.QueryMatchIds[groupIndex].Equals(id),
                          $"Mismatch between QueryMatchId {id} and group index {groupIndex}");

            k_SetMemberIndices.Clear();
            k_KnownMembers.Clear();

            var hasMembers = MemberData.MatchIdToIndex.TryGetValue(id, out var memberIndices);

            if (hasMembers)
            {
                // collect data on known members to facilitate remove / update
                for (var orderIndex = 0; orderIndex < memberIndices.Count; orderIndex++)
                {
                    var memberIndex = memberIndices[orderIndex];
                    var mrObject    = MemberData.ObjectReferences[memberIndex];
                    k_KnownMembers.Add(new KnownMember(mrObject, memberIndex));
                }

                var children = args.relations.children;

                // remove members that are gone
                for (var i = k_KnownMembers.Count - 1; i >= 0; i--)
                {
                    var knownMember = k_KnownMembers[i];
                    if (children.ContainsKey(knownMember.Reference))
                    {
                        continue;
                    }

                    MemberData.Remove(id, knownMember.DataIndex);
                    // Data child removal will happen with Data.Modify
                    // as that will reconstruct all data buffers / structures
                    // and re-associate with the current set of relations
                    k_KnownMembers.RemoveAt(i);
                }

                // add or update
                foreach (var kvp in children)
                {
                    var knownIndex = -1;
                    for (var i = 0; i < k_KnownMembers.Count; i++)
                    {
                        var knownMember = k_KnownMembers[i];
                        if (!ReferenceEquals(knownMember.Reference, kvp.Key))
                        {
                            continue;
                        }

                        knownIndex = i;
                        break;
                    }

                    if (knownIndex >= 0)
                    {
                        // update
                        var knownMember = k_KnownMembers[knownIndex];

                        MemberData.Modify(id, knownMember.DataIndex, kvp.Value);
                        k_KnownMembers.RemoveAt(knownIndex);
                    }
                    else
                    {
                        // register
                        MemberData.Register(id, kvp.Key, kvp.Value);
                    }
                }

                k_KnownMembers.Clear();
            }
            else
            {
                RegisterRelationChildren(id, args);

                MemberData.MatchIdToIndex.TryGetValue(id, out memberIndices);
            }

            GetIndexPairs(id, args);

            // the index arrays for group & relation members are so small that we create new ones
            // on registration, instead of using pooled Lists
            var memberIndicesArray = memberIndices.ToArray();
            var relationIndexPairs = k_RelationIndexPairs.ToArray();

            Data.Modify(groupIndex, memberIndicesArray, relationIndexPairs, args);

            k_TempChildResults.Clear();
            foreach (var i in memberIndices)
            {
                k_TempChildResults.Add(MemberData.ObjectReferences[i], MemberData.QueryResults[i]);
            }

            Data.QueryResults[groupIndex].SetChildren(k_TempChildResults);

            // for each group member, store a representation of which relations it belongs to.
            Data.GetRelationMemberships(groupIndex, k_RelationMemberships);
            foreach (var kvp in k_RelationMemberships)
            {
                var memberIndex = kvp.Key;
                MemberData.RelationMemberships[memberIndex] = kvp.Value;
            }

            // calculate the solve order weighting for this group
            var weights = QueryPipelineConfiguration.instance.SolveOrderWeighting;
            var order   = GetGroupOrderWeight(memberIndicesArray, relationIndexPairs.Length, MemberData.Exclusivities, weights);

            Data.OrderWeights[groupIndex] = order;

            Data.InitializeSearchData(groupIndex, MemberData.ReducedConditionRatings);
        }
 void RegisterQuery(QueryMatchID queryMatchID, QueryArgs queryArgs)
 {
     AddQuery(queryMatchID, queryArgs);
 }
 void AddQuery(QueryMatchID queryMatchID, QueryArgs args)
 {
     EnqueueUpdate(new BufferedAction(true, queryMatchID, args));
 }
        void Filter(Dictionary <int, HashSet <int> > dataUsedByQueries,
                    Dictionary <int, QueryMatchID> reservedData,
                    Dictionary <int, int> sharedDataUsers,
                    HashSet <int> dataIDs, QueryMatchID matchId, Exclusivity exclusivity)
        {
            if (s_IDsToRemove.Length < dataIDs.Count)
            {
                Array.Resize(ref s_IDsToRemove, dataIDs.Count + MARSMemoryOptions.ResizeHeadroom);
            }

            var removeCounter = 0;
            var queryId       = matchId.queryID;

            // Data should not be used again if this query is already using it
            if (dataUsedByQueries.TryGetValue(queryId, out var dataUsedByQuery))
            {
                dataIDs.ExceptWithNonAlloc(dataUsedByQuery);
            }

            var isReadOnly = exclusivity == Exclusivity.ReadOnly;

            // read only matches are valid if not already used by the query, so we're done with this one
            if (!isReadOnly)
            {
                var isShared = exclusivity == Exclusivity.Shared;
                foreach (var dataID in dataIDs)
                {
                    var idIsPreviouslyReserved = reservedData.ContainsKey(dataID);
                    // if it's previously reserved, neither shared nor reserved can use it
                    if (idIsPreviouslyReserved)
                    {
                        s_IDsToRemove[removeCounter] = dataID;
                        removeCounter++;
                        continue;
                    }
                    // if this query is reserved & something has previously used it as shared, can't use it
                    if (!isShared && sharedDataUsers.ContainsKey(dataID))
                    {
                        s_IDsToRemove[removeCounter] = dataID;
                        removeCounter++;
                    }
                }
            }

#if UNITY_EDITOR
            if (removeCounter > 0)
            {
                // collect information about what, if anything, got filtered, for editor debug purposes
                var filteredList = Pools.IntLists.Get();
                for (var j = 0; j < removeCounter; j++)
                {
                    filteredList.Add(s_IDsToRemove[j]);
                }

                DebugFilteredResults.Add(matchId, filteredList);
            }
#endif
            for (int i = 0; i < removeCounter; i++)
            {
                dataIDs.Remove(s_IDsToRemove[i]);
            }
        }
Beispiel #11
0
        bool TryAssignStandaloneMatch(QueryMatchID queryMatchId, int newDataId, bool matchConditions = true)
        {
            var data = m_PipelinesModule.StandalonePipeline.Data;

            if (!data.MatchIdToIndex.TryGetValue(queryMatchId, out var index))
            {
                throw new ArgumentException($"{queryMatchId} is not registered, so cannot have a match assigned");
            }

            // the bare minimum requirement for a new data match to be valid is that it has every trait required by the Proxy
            var traitRequirements = data.TraitRequirements[index];

            if (!DataHasAllTraitRequirements(newDataId, traitRequirements))
            {
                throw new ArgumentException($"Data ID \"{newDataId}\" does not have all traits required by {queryMatchId}");
            }

            if (matchConditions)
            {
                if (!m_Database.DataPassesAllConditions(data.Conditions[index], newDataId))
                {
                    throw new ArgumentException($"Data ID \"{newDataId}\" did not pass every Condition for {queryMatchId}");
                }
            }

            var exclusivity = data.Exclusivities[index];

            // manual matches must still obey data availability
            if (!m_Database.DataAvailableForUse(newDataId, queryMatchId.queryID, exclusivity))
            {
                throw new ArgumentException($"Data ID \"{newDataId}\" is not available for use by {queryMatchId}");
            }

            // all validity checks have passed, so unmatch the previous data if any
            var previouslyAssignedDataId = data.BestMatchDataIds[index];
            var hasExistingMatch         = previouslyAssignedDataId != (int)ReservedDataIDs.Invalid;

            if (hasExistingMatch)
            {
                UnsetStandaloneMatch(queryMatchId, false, false);
            }
            else
            {
                data.UpdatingIndices.Add(index);
                data.AcquiringIndices.Remove(index);
            }

            UnsetStandaloneMatchIndices.Remove(index);

            // claim the new data id for this proxy
            m_Database.MarkDataUsedForUpdates(newDataId, queryMatchId, exclusivity);
            data.BestMatchDataIds[index] = newDataId;

            // fill the proxy's result with the new data
            var result = data.QueryResults[index];

            result.Clear();
            result.SetDataId(newDataId);
            m_Database.FillQueryResultRequirements(newDataId, traitRequirements, result);

            // if this query had previously acquired, treat setting a new match as an update rather than acquire
            if (hasExistingMatch)
            {
                data.UpdateHandlers[index]?.Invoke(result);
            }
            else
            {
                data.AcquireHandlers[index].Invoke(result);
            }

            return(true);
        }
Beispiel #12
0
 public SetQueryResult(QueryMatchID id)
 {
     queryMatchId = id;
 }
Beispiel #13
0
 public SetQueryResult(QueryMatchID id, IEnumerable <IMRObject> children)
 {
     queryMatchId = id;
     SetChildren(children);
 }
 public void Reset()
 {
     queryMatchId = QueryMatchID.NullQuery;
     Clear();
 }
 public BufferedAction(bool isAdd, QueryMatchID id, SetQueryArgs args) : this(isAdd ? ActionKind.AddGroup : ActionKind.RemoveGroup)
 {
     QueryId   = id;
     GroupArgs = args;
 }
 void RemoveQuery(QueryMatchID queryMatchID)
 {
     EnqueueUpdate(new BufferedAction(BufferedAction.ActionKind.RemoveSingle, queryMatchID));
 }
 public BufferedAction(QueryMatchID id, QueryArgs args) : this(ActionKind.ModifySingle)
 {
     QueryId    = id;
     SingleArgs = args;
 }
 internal void ModifySetQuery(QueryMatchID id, SetQueryArgs args)
 {
     EnqueueUpdate(new BufferedAction(id, args));
 }
 internal bool UnsetStandaloneMatchPublic(QueryMatchID queryMatchId, bool seekNewMatch)
 {
     return(UnsetStandaloneMatch(queryMatchId, seekNewMatch));
 }
 // ReSharper disable once UnusedMember.Local
 void FillQueryResultInternal(int dataId, object conditions, object traits,
                              QueryMatchID matchId, QueryResult result)
 {
 }