public void RecreateCopy() { if (m_SubChildren != null) { foreach (var child in m_SubChildren) { if (child != null) { child.onInvalidateDelegate -= SubChildrenOnInvalidate; ScriptableObject.DestroyImmediate(child, true); } } } if (subgraph == null) { m_SubChildren = null; m_SubBlocks = null; return; } var graph = m_Subgraph.GetResource().GetOrCreateGraph(); HashSet <ScriptableObject> dependencies = new HashSet <ScriptableObject>(); var context = graph.children.OfType <VFXBlockSubgraphContext>().FirstOrDefault(); if (context == null) { m_SubChildren = null; m_SubBlocks = null; return; } foreach (var child in graph.children.Where(t => t is VFXOperator || t is VFXParameter)) { dependencies.Add(child); child.CollectDependencies(dependencies); } foreach (var block in context.children) { dependencies.Add(block); block.CollectDependencies(dependencies); } var copy = VFXMemorySerializer.DuplicateObjects(dependencies.ToArray()); m_SubChildren = copy.OfType <VFXModel>().Where(t => t is VFXBlock || t is VFXOperator || t is VFXParameter).ToArray(); m_SubBlocks = m_SubChildren.OfType <VFXBlock>().ToArray(); foreach (var child in m_SubChildren) { child.onInvalidateDelegate += SubChildrenOnInvalidate; } foreach (var child in copy) { child.hideFlags = HideFlags.HideAndDontSave; } SyncSlots(VFXSlot.Direction.kInput, true); PatchInputExpressions(); }
public void RecreateCopy() { ClearCopy(); if (subgraph == null) { m_SubChildren = null; m_UsedSubgraph = null; return; } var graph = m_Subgraph.GetResource().GetOrCreateGraph(); HashSet <ScriptableObject> dependencies = new HashSet <ScriptableObject>(); foreach (var child in graph.children.Where(t => t is VFXOperator || t is VFXParameter)) { dependencies.Add(child); child.CollectDependencies(dependencies); } var copy = VFXMemorySerializer.DuplicateObjects(dependencies.ToArray()); m_UsedSubgraph = graph; m_SubChildren = copy.OfType <VFXModel>().Where(t => t is VFXOperator || t is VFXParameter).ToArray(); foreach (var child in copy) { child.hideFlags = HideFlags.HideAndDontSave; } }
public object Backup() { Profiler.BeginSample("VFXGraph.Backup"); var dependencies = new HashSet <ScriptableObject>(); dependencies.Add(this); CollectDependencies(dependencies); var result = VFXMemorySerializer.StoreObjectsToByteArray(dependencies.ToArray(), CompressionLevel.Fastest); Profiler.EndSample(); return(result); }
public void Restore(object str) { Profiler.BeginSample("VFXGraph.Restore"); var scriptableObject = VFXMemorySerializer.ExtractObjects(str as byte[], false); Profiler.BeginSample("VFXGraph.Restore SendUnknownChange"); foreach (var model in scriptableObject.OfType <VFXModel>()) { model.OnUnknownChange(); } Profiler.EndSample(); Profiler.EndSample(); m_ExpressionGraphDirty = true; m_ExpressionValuesDirty = true; m_DependentDirty = true; }
private static Func <object, bool, ScriptableObject[]> GetExtractObjectsFunction() { var advancedMethod = typeof(VFXMemorySerializer).GetMethod("ExtractObjects", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(byte[]), typeof(bool) }, null); if (advancedMethod != null) { return(delegate(object objects, bool asCopy) { return advancedMethod.Invoke(null, new object[] { objects as byte[], asCopy }) as ScriptableObject[]; }); } return(delegate(object objects, bool asCopy) { return VFXMemorySerializer.ExtractObjects(objects as string, asCopy); }); }
//Temporary : Use reflection to access to StoreObjectsToByteArray (doesn't break previous behavior if editor isn't up to date) //TODO : Clean this when major version is released private static Func <ScriptableObject[], CompressionLevel, object> GetStoreObjectsFunction() { var advancedMethod = typeof(VFXMemorySerializer).GetMethod("StoreObjectsToByteArray", BindingFlags.Public | BindingFlags.Static); if (advancedMethod != null) { return(delegate(ScriptableObject[] objects, CompressionLevel level) { return advancedMethod.Invoke(null, new object[] { objects, level }) as byte[]; }); } return(delegate(ScriptableObject[] objects, CompressionLevel level) { return VFXMemorySerializer.StoreObjects(objects) as object; }); }
public object Backup() { Profiler.BeginSample("VFXGraph.Backup"); var dependencies = new HashSet <ScriptableObject>(); dependencies.Add(this); CollectDependencies(dependencies); // This is a guard where dependencies that couldnt be deserialized (because script is missing for instance) are removed from the list // because else StoreObjectsToByteArray is crashing // TODO Fix that var safeDependencies = dependencies.Where(o => o != null); var result = VFXMemorySerializer.StoreObjectsToByteArray(safeDependencies.ToArray(), CompressionLevel.Fastest); Profiler.EndSample(); return(result); }
static void OnCompileResource(VisualEffectResource resource) { if (resource != null) { VFXGraph graph = resource.graph as VFXGraph; if (graph != null) { if (!graph.sanitized) { //Early return, the reimport will be forced with the next OnPostprocessAllAssets after Sanitize resource.ClearRuntimeData(); } else { //Workaround, use backup system to prevent any modification of the graph during compilation //The responsible of this unexpected change is PrepareSubgraphs => RecurseSubgraphRecreateCopy => ResyncSlots //It will let the VFXGraph in a really bad state after compilation. graph = resource.GetOrCreateGraph(); var dependencies = new HashSet <ScriptableObject>(); dependencies.Add(graph); graph.CollectDependencies(dependencies); var backup = VFXMemorySerializer.StoreObjectsToByteArray(dependencies.ToArray(), CompressionLevel.None); graph.CompileForImport(); VFXMemorySerializer.ExtractObjects(backup, false); //The backup during undo/redo is actually calling UnknownChange after ExtractObjects //You have to avoid because it will call ResyncSlot } } else { Debug.LogError("OnCompileResource error - VisualEffectResource without graph"); } } }
public void RecreateCopy() { DetachFromOriginal(); if (m_Subgraph == null) { m_SubChildren = null; m_UsedSubgraph = null; return; } var resource = m_Subgraph.GetResource(); if (resource == null) { m_SubChildren = null; m_UsedSubgraph = null; return; } var graph = resource.GetOrCreateGraph(); HashSet <ScriptableObject> dependencies = new HashSet <ScriptableObject>(); graph.CollectDependencies(dependencies); var duplicated = VFXMemorySerializer.DuplicateObjects(dependencies.ToArray()); m_SubChildren = duplicated.OfType <VFXModel>().Where(t => t is VFXContext || t is VFXOperator || t is VFXParameter).ToArray(); m_UsedSubgraph = graph; foreach (var child in duplicated.Zip(dependencies, (a, b) => new { copy = a, original = b })) { child.copy.hideFlags = HideFlags.HideAndDontSave; if (child.copy is VFXSlot) { var original = child.original as VFXSlot; var copy = child.copy as VFXSlot; if (original.direction == VFXSlot.Direction.kInput || original.owner is VFXParameter) { m_OriginalToCopy[original] = copy; original.onInvalidateDelegate += OnOriginalSlotModified; } } else if (child.copy is VFXSubgraphBlock subgraphBlock) { subgraphBlock.RecreateCopy(); } } List <string> newInputFlowNames = new List <string>(); foreach (var basicEvent in m_SubChildren.OfType <VFXBasicEvent>()) { if (!newInputFlowNames.Contains(basicEvent.eventName)) { newInputFlowNames.Add(basicEvent.eventName); } } bool hasStart = false; bool hasStop = false; foreach (var initialize in m_SubChildren.OfType <VFXBasicSpawner>()) { if (!hasStart && initialize.inputFlowSlot[0].link.Count() == 0) { hasStart = true; } if (!hasStop && initialize.inputFlowSlot[1].link.Count() == 0) { hasStop = true; } } int directEventCount = newInputFlowNames.Count; foreach (var subContext in m_SubChildren.OfType <VFXSubgraphContext>()) { for (int i = 0; i < subContext.inputFlowCount; ++i) { string name = subContext.GetInputFlowName(i); switch (name) { case VisualEffectAsset.PlayEventName: hasStart = true; break; case VisualEffectAsset.StopEventName: hasStop = true; break; default: m_InputFlowNames.Add(name); break; } } } newInputFlowNames.Sort(0, directEventCount, Comparer <string> .Default); newInputFlowNames.Sort(directEventCount, newInputFlowNames.Count - directEventCount, Comparer <string> .Default); if (hasStop) { newInputFlowNames.Insert(0, VisualEffectAsset.StopEventName); } if (hasStart) { newInputFlowNames.Insert(0, VisualEffectAsset.PlayEventName); } if (m_InputFlowNames == null || !newInputFlowNames.SequenceEqual(m_InputFlowNames) || inputFlowSlot.Length != inputFlowCount) { var oldLinks = new Dictionary <string, List <VFXContextLink> >(); for (int i = 0; i < inputFlowSlot.Count() && i < m_InputFlowNames.Count; ++i) { oldLinks[GetInputFlowName(i)] = inputFlowSlot[i].link.ToList(); } m_InputFlowNames = newInputFlowNames; RefreshInputFlowSlots(); for (int i = 0; i < inputFlowSlot.Count(); ++i) { List <VFXContextLink> ctxSlot; if (oldLinks.TryGetValue(GetInputFlowName(i), out ctxSlot)) { foreach (var link in ctxSlot) { LinkFrom(link.context, link.slotIndex, i); } } } } SyncSlots(VFXSlot.Direction.kInput, true); }