void ComputeEffectiveInputLinks(ref SubgraphInfos subgraphInfos, IEnumerable <VFXContext> compilableContexts) { var contextEffectiveInputLinks = subgraphInfos.contextEffectiveInputLinks; foreach (var context in compilableContexts.Where(t => !(t is VFXSubgraphContext))) { contextEffectiveInputLinks[context] = ComputeContextEffectiveLinks(context, ref subgraphInfos); ComputeEffectiveInputLinks(ref subgraphInfos, contextEffectiveInputLinks[context].SelectMany(t => t).Select(t => t.context).Where(t => !contextEffectiveInputLinks.ContainsKey(t))); } }
private static void FillEvent(List <VFXEventDesc> outEventDesc, Dictionary <VFXContext, SpawnInfo> contextSpawnToSpawnInfo, IEnumerable <VFXContext> contexts, ref SubgraphInfos subgraphInfos) { var contextEffectiveInputLinks = subgraphInfos.contextEffectiveInputLinks; var allPlayNotLinked = contextSpawnToSpawnInfo.Where(o => !contextEffectiveInputLinks[o.Key][0].Any()).Select(o => (uint)o.Value.systemIndex).ToList(); var allStopNotLinked = contextSpawnToSpawnInfo.Where(o => !contextEffectiveInputLinks[o.Key][1].Any()).Select(o => (uint)o.Value.systemIndex).ToList(); var eventDescTemp = new[] { new { eventName = "OnPlay", playSystems = allPlayNotLinked, stopSystems = new List <uint>() }, new { eventName = "OnStop", playSystems = new List <uint>(), stopSystems = allStopNotLinked }, }.ToList(); var specialNames = new HashSet <string>(new string[] { VisualEffectAsset.PlayEventName, VisualEffectAsset.StopEventName, VFXSubgraphContext.triggerEventName }); var events = contexts.Where(o => o.contextType == VFXContextType.Event); foreach (var evt in events) { var eventName = (evt as VFXBasicEvent).eventName; if (subgraphInfos.spawnerSubgraph.ContainsKey(evt) && specialNames.Contains(eventName)) { continue; } foreach (var link in evt.outputFlowSlot[0].link) { if (contextSpawnToSpawnInfo.ContainsKey(link.context)) { var eventIndex = eventDescTemp.FindIndex(o => o.eventName == eventName); if (eventIndex == -1) { eventIndex = eventDescTemp.Count; eventDescTemp.Add(new { eventName = eventName, playSystems = new List <uint>(), stopSystems = new List <uint>(), }); } var startSystem = link.slotIndex == 0; var spawnerIndex = (uint)contextSpawnToSpawnInfo[link.context].systemIndex; if (startSystem) { eventDescTemp[eventIndex].playSystems.Add(spawnerIndex); } else { eventDescTemp[eventIndex].stopSystems.Add(spawnerIndex); } } } } outEventDesc.Clear(); outEventDesc.AddRange(eventDescTemp.Select(o => new VFXEventDesc() { name = o.eventName, startSystems = o.playSystems.ToArray(), stopSystems = o.stopSystems.ToArray() })); }
private static void FillSpawner(Dictionary <VFXContext, SpawnInfo> outContextSpawnToSpawnInfo, List <VFXCPUBufferDesc> outCpuBufferDescs, List <VFXEditorSystemDesc> outSystemDescs, IEnumerable <VFXContext> contexts, VFXExpressionGraph graph, List <VFXLayoutElementDesc> globalEventAttributeDescs, Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData, ref SubgraphInfos subgraphInfos) { var spawners = CollectSpawnersHierarchy(contexts, ref subgraphInfos); foreach (var it in spawners.Select((spawner, index) => new { spawner, index })) { outContextSpawnToSpawnInfo.Add(it.spawner, new SpawnInfo() { bufferIndex = outCpuBufferDescs.Count, systemIndex = it.index }); outCpuBufferDescs.Add(new VFXCPUBufferDesc() { capacity = 1u, stride = globalEventAttributeDescs.First().offset.structure, layout = globalEventAttributeDescs.ToArray(), initialData = ComputeArrayOfStructureInitialData(globalEventAttributeDescs) }); } foreach (var spawnContext in spawners) { var buffers = new List <VFXMapping>(); buffers.Add(new VFXMapping() { index = outContextSpawnToSpawnInfo[spawnContext].bufferIndex, name = "spawner_output" }); for (int indexSlot = 0; indexSlot < 2 && indexSlot < spawnContext.inputFlowSlot.Length; ++indexSlot) { foreach (var input in subgraphInfos.contextEffectiveInputLinks[spawnContext][indexSlot]) { var inputContext = input.context; if (outContextSpawnToSpawnInfo.ContainsKey(inputContext)) { buffers.Add(new VFXMapping() { index = outContextSpawnToSpawnInfo[inputContext].bufferIndex, name = "spawner_input_" + (indexSlot == 0 ? "OnPlay" : "OnStop") }); } } } var contextData = contextToCompiledData[spawnContext]; outSystemDescs.Add(new VFXEditorSystemDesc() { buffers = buffers.ToArray(), capacity = 0u, flags = VFXSystemFlag.SystemDefault, layer = uint.MaxValue, tasks = spawnContext.activeFlattenedChildrenWithImplicit.Select((b, index) => { var spawnerBlock = b as VFXAbstractSpawner; if (spawnerBlock == null) { throw new InvalidCastException("Unexpected block type in spawnerContext"); } if (spawnerBlock.spawnerType == VFXTaskType.CustomCallbackSpawner && spawnerBlock.customBehavior == null) { throw new InvalidOperationException("VFXAbstractSpawner excepts a custom behavior for custom callback type"); } if (spawnerBlock.spawnerType != VFXTaskType.CustomCallbackSpawner && spawnerBlock.customBehavior != null) { throw new InvalidOperationException("VFXAbstractSpawner only expects a custom behavior for custom callback type"); } var cpuExpression = contextData.cpuMapper.CollectExpression(index, false).Select(o => { return(new VFXMapping { index = graph.GetFlattenedIndex(o.exp), name = o.name }); }).ToArray(); Object processor = null; if (spawnerBlock.customBehavior != null) { var assets = AssetDatabase.FindAssets("t:TextAsset " + spawnerBlock.customBehavior.Name); if (assets.Length != 1) { // AssetDatabase.FindAssets will not search in package by default. Search in our package explicitely assets = AssetDatabase.FindAssets("t:TextAsset " + spawnerBlock.customBehavior.Name, new string[] { VisualEffectGraphPackageInfo.assetPackagePath }); if (assets.Length != 1) { throw new InvalidOperationException("Unable to find the definition .cs file for " + spawnerBlock.customBehavior + " Make sure that the class name and file name match"); } } var assetPath = AssetDatabase.GUIDToAssetPath(assets[0]); processor = AssetDatabase.LoadAssetAtPath <TextAsset>(assetPath); } return(new VFXEditorTaskDesc { type = spawnerBlock.spawnerType, buffers = new VFXMapping[0], values = cpuExpression.ToArray(), parameters = contextData.parameters, externalProcessor = processor }); }).ToArray() }); } }
static List <VFXContextLink>[] ComputeContextEffectiveLinks(VFXContext context, ref SubgraphInfos subgraphInfos) { List <VFXContextLink>[] result = new List <VFXContextLink> [context.inputFlowSlot.Length]; Dictionary <string, int> eventNameIndice = new Dictionary <string, int>(); for (int i = 0; i < context.inputFlowSlot.Length; ++i) { result[i] = new List <VFXContextLink>(); VFXSubgraphContext parentSubgraph = null; subgraphInfos.spawnerSubgraph.TryGetValue(context, out parentSubgraph); List <VFXContext> subgraphAncestors = new List <VFXContext>(); subgraphAncestors.Add(context); while (parentSubgraph != null) { subgraphAncestors.Add(parentSubgraph); if (!subgraphInfos.subgraphParents.TryGetValue(parentSubgraph, out parentSubgraph)) { parentSubgraph = null; } } List <List <int> > defaultEventPaths = new List <List <int> >(); defaultEventPaths.Add(new List <int>(new int[] { i })); List <List <int> > newEventPaths = new List <List <int> >(); var usedContexts = new List <VFXContext>(); var namedEvents = new Dictionary <string, VFXContext>(); for (int j = 0; j < subgraphAncestors.Count; ++j) { var sg = subgraphAncestors[j]; var nextSg = j < subgraphAncestors.Count - 1 ? subgraphAncestors[j + 1] as VFXSubgraphContext : null; foreach (var path in defaultEventPaths) { int currentFlowIndex = path.Last(); var eventSlot = sg.inputFlowSlot[currentFlowIndex]; // -1 in path is Trigger therefore 2 in subgraph input var eventSlotSpawners = eventSlot.link.Where(t => !(t.context is VFXBasicEvent)); if (eventSlotSpawners.Any()) { foreach (var evt in eventSlotSpawners) { result[i].Add(evt); } } var eventSlotEvents = eventSlot.link.Where(t => t.context is VFXBasicEvent); if (eventSlotEvents.Any()) { foreach (var evt in eventSlotEvents) { string eventName = (evt.context as VFXBasicEvent).eventName; switch (eventName) { case VisualEffectAsset.PlayEventName: newEventPaths.Add(path.Concat(new int[] { 0 }).ToList()); break; case VisualEffectAsset.StopEventName: newEventPaths.Add(path.Concat(new int[] { 1 }).ToList()); break; default: { if (nextSg != null) { int eventIndex = nextSg.GetInputFlowIndex(eventName); if (eventIndex != -1) { namedEvents[eventName] = evt.context; newEventPaths.Add(path.Concat(new int[] { eventIndex }).ToList()); } } else { result[i].Add(evt); } } break; } } } else if (!eventSlot.link.Any()) { if (!(sg is VFXSubgraphContext)) { newEventPaths.Add(path.Concat(new int[] { currentFlowIndex }).ToList()); } else { var sgsg = sg as VFXSubgraphContext; var eventName = sgsg.GetInputFlowName(currentFlowIndex); var eventCtx = sgsg.GetEventContext(eventName); if (eventCtx != null) { result[i].Add(new VFXContextLink() { slotIndex = 0, context = eventCtx }); } } } } defaultEventPaths.Clear(); defaultEventPaths.AddRange(newEventPaths); newEventPaths.Clear(); } } return(result); }
private static VFXContext[] CollectSpawnersHierarchy(IEnumerable <VFXContext> vfxContext, ref SubgraphInfos subgraphContexts) { var initContext = vfxContext.Where(o => o.contextType == VFXContextType.Init).ToList(); var spawnerList = CollectContextParentRecursively(initContext, ref subgraphContexts); return(spawnerList.Where(o => o.contextType == VFXContextType.Spawner).Reverse().ToArray()); }
private static List <VFXContext> CollectContextParentRecursively(IEnumerable <VFXContext> inputList, ref SubgraphInfos subgraphContexts) { var contextEffectiveInputLinks = subgraphContexts.contextEffectiveInputLinks; var contextList = inputList.SelectMany(o => contextEffectiveInputLinks[o].SelectMany(t => t)).Select(t => t.context).Distinct().ToList(); if (contextList.Any(o => contextEffectiveInputLinks[o].Any())) { var parentContextList = CollectContextParentRecursively(contextList.Except(inputList), ref subgraphContexts); foreach (var context in parentContextList) { if (!contextList.Contains(context)) { contextList.Add(context); } } } return(contextList); }