public void ConvertToSubgraphBlock(VFXView sourceView, IEnumerable <Controller> controllers, Rect rect) { this.m_Rect = rect; Init(sourceView, controllers); CreateUniqueSubgraph("SubgraphBlock", VisualEffectSubgraphBlock.Extension, VisualEffectAssetEditorUtility.CreateNew <VisualEffectSubgraphBlock>); m_SourceControllers.RemoveAll(t => t is VFXContextController); // Don't copy contexts CopyPasteNodes(); m_SourceBlockControllers = m_SourceControllers.OfType <VFXBlockController>().OrderBy(t => t.index).ToList(); VFXContextController sourceContextController = m_SourceBlockControllers.First().contextController; object copyData = VFXCopy.CopyBlocks(m_SourceBlockControllers); var targetContext = m_TargetController.graph.children.OfType <VFXBlockSubgraphContext>().FirstOrDefault(); if (targetContext == null) { targetContext = ScriptableObject.CreateInstance <VFXBlockSubgraphContext>(); m_TargetController.graph.AddChild(targetContext); } m_TargetController.LightApplyChanges(); targetContext.position = sourceContextController.position; targetContext.SetSettingValue("m_SuitableContexts", (VFXBlockSubgraphContext.ContextType)m_SourceBlockControllers.Select(t => t.model.compatibleContexts).Aggregate((t, s) => t & s)); m_TargetBlocks = new List <VFXBlockController>(); VFXPaste.PasteBlocks(m_TargetController, copyData, targetContext, 0, m_TargetBlocks); var otherSourceControllers = m_SourceControllers.OfType <VFXNodeController>().Where(t => !(t is VFXBlockController)).ToList(); //Create lost links between nodes and blocks foreach (var edge in m_SourceController.dataEdges.Where(t => otherSourceControllers.Contains(t.output.sourceNode) && m_SourceBlockControllers.Contains(t.input.sourceNode))) { var outputNode = m_TargetControllers[m_SourceControllers.IndexOf(edge.output.sourceNode)]; var output = outputNode.outputPorts.First(t => t.path == edge.output.path); var inputBlock = m_TargetBlocks[m_SourceBlockControllers.IndexOf(edge.input.sourceNode as VFXBlockController)]; var input = inputBlock.inputPorts.First(t => t.path == edge.input.path); m_TargetController.CreateLink(input, output); } var sourceBlock = ScriptableObject.CreateInstance <VFXSubgraphBlock>(); m_SourceNode = sourceBlock; sourceContextController.model.AddChild(m_SourceNode, m_SourceBlockControllers.Select(t => t.index).Min()); sourceContextController.ApplyChanges(); m_SourceNodeController = sourceContextController.blockControllers.First(t => t.model == m_SourceNode); PostSetup(); m_SourceNodeController.ApplyChanges(); var targetContextController = m_TargetController.GetRootNodeController(targetContext, 0) as VFXContextController; m_SourceControllersWithBlocks = m_SourceControllers.Concat(m_SourceBlockControllers); TransferEdges(); UninitSmart(); }
void ConvertContext(VFXNodeProvider.Descriptor d, Vector2 mPos) { VFXView view = GetFirstAncestorOfType <VFXView>(); VFXViewController viewController = controller.viewController; if (view == null) { return; } mPos = view.contentViewContainer.ChangeCoordinatesTo(view, controller.position); var newNodeController = view.AddNode(d, mPos); var newContextController = newNodeController as VFXContextController; //transfer blocks foreach (var block in controller.model.children.ToArray()) // To array needed as the IEnumerable content will change { newContextController.AddBlock(-1, block); } //transfer settings var contextType = controller.model.GetType(); foreach (var setting in newContextController.model.GetSettings(true)) { if (newContextController.model is VFXPlanarPrimitiveOutput && setting.field.Name == "primitiveType") { continue; } if (!setting.valid || setting.field.GetCustomAttributes(typeof(VFXSettingAttribute), true).Length == 0) { continue; } object value; if (VFXConverter.TryConvertTo(setting.value, setting.field.FieldType, out value)) { newContextController.model.SetSettingValue(setting.field.Name, value); } } //transfer flow edges if (controller.flowInputAnchors.Count == 1) { foreach (var output in controller.flowInputAnchors[0].connections.Select(t => t.output).ToArray()) { newContextController.model.LinkFrom(output.context.model, output.slotIndex); } } // Apply the slot changes that can be the result of settings changes newContextController.ApplyChanges(); VFXSlot firstTextureSlot = null; //transfer master slot values foreach (var slot in newContextController.model.inputSlots) { VFXSlot mySlot = controller.model.inputSlots.FirstOrDefault(t => t.name == slot.name); if (mySlot == null) { if (slot.valueType == VFXValueType.Texture2D && firstTextureSlot == null) { firstTextureSlot = slot; } continue; } object value; if (VFXConverter.TryConvertTo(mySlot.value, slot.property.type, out value)) { slot.value = value; } } //Hack to copy the first texture in the first texture slot if not found by name if (firstTextureSlot != null) { VFXSlot mySlot = controller.model.inputSlots.FirstOrDefault(t => t.valueType == VFXValueType.Texture2D); if (mySlot != null) { firstTextureSlot.value = mySlot.value; } } foreach (var anchor in newContextController.inputPorts) { string path = anchor.path; var myAnchor = controller.inputPorts.FirstOrDefault(t => t.path == path); if (myAnchor == null || !myAnchor.HasLink()) { continue; } //There should be only one var output = myAnchor.connections.First().output; viewController.CreateLink(anchor, output); } // Apply the change so that it won't unlink the blocks links controller.ApplyChanges(); viewController.RemoveElement(controller); }
void AddLinkedNode(VFXNodeProvider.Descriptor d, Vector2 mPos) { var mySlot = controller.model; VFXView view = GetFirstAncestorOfType <VFXView>(); VFXViewController viewController = controller.viewController; if (view == null) { return; } var newNodeController = view.AddNode(d, mPos); if (newNodeController == null) { return; } IEnumerable <Type> validTypes = null; var op = controller.sourceNode.model as VFXOperatorNumericCascadedUnified; if (mySlot == null && op != null) { validTypes = op.validTypes; } // If linking to a new parameter, copy the slot value and space if (direction == Direction.Input && controller.model != null) //model will be null for upcomming which won't have a value { if (newNodeController is VFXOperatorController) { var inlineOperator = (newNodeController as VFXOperatorController).model as VFXInlineOperator; if (inlineOperator != null) { var value = controller.model.value; object convertedValue = null; if (VFXConverter.TryConvertTo(value, inlineOperator.type, out convertedValue)) { inlineOperator.inputSlots[0].value = convertedValue; } if (inlineOperator.inputSlots[0].spaceable && controller.model.spaceable) { inlineOperator.inputSlots[0].space = controller.model.space; } } } } var ports = direction == Direction.Input ? newNodeController.outputPorts : newNodeController.inputPorts; int count = ports.Count(); for (int i = 0; i < count; ++i) { var port = ports[i]; if (mySlot != null) { if (viewController.CreateLink(direction == Direction.Input ? controller : port, direction == Direction.Input ? port : controller)) { AlignNodeToLinkedPort(view, port, newNodeController); break; } } else if (validTypes != null) { if (validTypes.Contains(port.model.property.type)) { if (viewController.CreateLink(controller, port)) { break; } } } } }
void IEdgeConnectorListener.OnDropOutsidePort(Edge edge, Vector2 position) { VFXSlot startSlot = controller.model; VFXView view = this.GetFirstAncestorOfType <VFXView>(); VFXViewController viewController = view.controller; List <VisualElement> picked = new List <VisualElement>(); panel.PickAll(position, picked); VFXNodeUI endNode = null; foreach (var element in picked) { if (element is VFXNodeUI node) { endNode = node; break; } } VFXDataEdge dataEdge = edge as VFXDataEdge; bool exists = false; if (dataEdge.controller != null) { exists = true; view.controller.RemoveElement(dataEdge.controller); } if (endNode != null) { VFXNodeController nodeController = endNode.controller; if (nodeController != null) { IVFXSlotContainer slotContainer = nodeController.slotContainer; if (controller.direction == Direction.Input) { foreach (var output in nodeController.outputPorts.Where(t => t.model == null || t.model.IsMasterSlot())) { if (viewController.CreateLink(controller, output)) { break; } } } else { foreach (var input in nodeController.inputPorts.Where(t => t.model == null || t.model.IsMasterSlot() && !t.model.HasLink(true))) { if (viewController.CreateLink(input, controller)) { break; } } } } } else if (controller.direction == Direction.Input && Event.current.modifiers == EventModifiers.Alt) { var targetType = controller.portType; var attribute = VFXLibrary.GetAttributeFromSlotType(controller.portType); VFXModelDescriptorParameters parameterDesc; if (attribute != null && attribute.usages.HasFlag(VFXTypeAttribute.Usage.ExcludeFromProperty)) { parameterDesc = VFXLibrary.GetParameters().FirstOrDefault(t => { if (!t.model.outputSlots[0].CanLink(controller.model)) { return(false); } var attributeCandidate = VFXLibrary.GetAttributeFromSlotType(t.model.type); return(attributeCandidate == null || !attributeCandidate.usages.HasFlag(VFXTypeAttribute.Usage.ExcludeFromProperty)); }); } else { parameterDesc = VFXLibrary.GetParameters().FirstOrDefault(t => { return(t.model.type == targetType); }); } if (parameterDesc != null) { Vector2 pos = view.contentViewContainer.GlobalToBound(position) - new Vector2(140, 20); view.UpdateSelectionWithNewNode(); VFXParameter parameter = viewController.AddVFXParameter(pos, parameterDesc, false); parameter.SetSettingValue("m_Exposed", true); startSlot.Link(parameter.outputSlots[0]); CopyValueToParameter(parameter); viewController.AddVFXModel(pos, parameter); } } else if (!exists) { var window = VFXViewWindow.GetWindow(view); if (direction == Direction.Input || viewController.model.visualEffectObject is VisualEffectSubgraphOperator || viewController.model.visualEffectObject is VisualEffectSubgraphBlock) // no context for subgraph operators. { VFXFilterWindow.Show(window, Event.current.mousePosition, view.ViewToScreenPosition(Event.current.mousePosition), new VFXNodeProvider(viewController, AddLinkedNode, ProviderFilter, new Type[] { typeof(VFXOperator), typeof(VFXParameter) })); } else { VFXFilterWindow.Show(window, Event.current.mousePosition, view.ViewToScreenPosition(Event.current.mousePosition), new VFXNodeProvider(viewController, AddLinkedNode, ProviderFilter, new Type[] { typeof(VFXOperator), typeof(VFXParameter), typeof(VFXContext) })); } } }
void ConvertContext(VFXNodeProvider.Descriptor d, Vector2 mPos) { VFXView view = GetFirstAncestorOfType <VFXView>(); VFXViewController viewController = controller.viewController; if (view == null) { return; } mPos = view.contentViewContainer.ChangeCoordinatesTo(view, controller.position); var newNodeController = view.AddNode(d, mPos); var newContextController = newNodeController as VFXContextController; //transfer blocks foreach (var block in controller.model.children.ToArray()) // To array needed as the IEnumerable content will change { newContextController.AddBlock(-1, block); } //transfer settings var contextType = controller.model.GetType(); foreach (var setting in newContextController.model.GetSettings(true)) { FieldInfo myField = contextType.GetField(setting.Name, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic); if (myField == null || myField.GetCustomAttributes(typeof(VFXSettingAttribute), true).Length == 0) { continue; } object value; if (VFXConverter.TryConvertTo(myField.GetValue(controller.model), setting.FieldType, out value)) { newContextController.model.SetSettingValue(setting.Name, value); } } //transfer flow edges if (controller.flowInputAnchors.Count == 1) { foreach (var output in controller.flowInputAnchors[0].connections.Select(t => t.output).ToArray()) { newContextController.model.LinkFrom(output.context.model, output.slotIndex); } } // Apply the slot changes that can be the result of settings changes newContextController.ApplyChanges(); //transfer master slot values foreach (var slot in newContextController.model.inputSlots) { VFXSlot mySlot = controller.model.inputSlots.FirstOrDefault(t => t.name == slot.name); if (mySlot == null) { continue; } object value; if (VFXConverter.TryConvertTo(mySlot.value, slot.property.type, out value)) { slot.value = value; } } foreach (var anchor in newContextController.inputPorts) { string path = anchor.path; var myAnchor = controller.inputPorts.FirstOrDefault(t => t.path == path); if (myAnchor == null || !myAnchor.HasLink()) { continue; } //There should be only one var output = myAnchor.connections.First().output; viewController.CreateLink(anchor, output); } // Apply the change so that it won't unlink the blocks links controller.ApplyChanges(); viewController.RemoveElement(controller); }
void IEdgeConnectorListener.OnDropOutsidePort(Edge edge, Vector2 position) { VFXSlot startSlot = controller.model; VFXView view = this.GetFirstAncestorOfType <VFXView>(); VFXViewController viewController = view.controller; VFXNodeUI endNode = null; foreach (var node in view.GetAllNodes()) { if (node.worldBound.Contains(position)) { endNode = node; } } VFXDataEdge dataEdge = edge as VFXDataEdge; bool exists = false; if (dataEdge.controller != null) { exists = true; view.controller.RemoveElement(dataEdge.controller); } if (endNode != null) { VFXNodeController nodeController = endNode.controller; if (nodeController != null) { IVFXSlotContainer slotContainer = nodeController.slotContainer; if (controller.direction == Direction.Input) { foreach (var output in nodeController.outputPorts.Where(t => t.model == null || t.model.IsMasterSlot())) { if (viewController.CreateLink(controller, output)) { break; } } } else { foreach (var input in nodeController.inputPorts.Where(t => t.model == null || t.model.IsMasterSlot())) { if (viewController.CreateLink(input, controller)) { break; } } } } } else if (controller.direction == Direction.Input && Event.current.modifiers == EventModifiers.Alt) { VFXModelDescriptorParameters parameterDesc = VFXLibrary.GetParameters().FirstOrDefault(t => t.name == controller.portType.UserFriendlyName()); if (parameterDesc != null) { VFXParameter parameter = viewController.AddVFXParameter(view.contentViewContainer.GlobalToBound(position) - new Vector2(140, 20), parameterDesc); parameter.SetSettingValue("m_Exposed", true); startSlot.Link(parameter.outputSlots[0]); CopyValueToParameter(parameter); } } else if (!exists) { VFXFilterWindow.Show(VFXViewWindow.currentWindow, Event.current.mousePosition, view.ViewToScreenPosition(Event.current.mousePosition), new VFXNodeProvider(viewController, AddLinkedNode, ProviderFilter, new Type[] { typeof(VFXOperator), typeof(VFXParameter), typeof(VFXContext) })); } }
void TransfertDataEdges() { m_SourceControllersWithBlocks = m_SourceControllers.Concat(m_SourceControllers.OfType <VFXContextController>().SelectMany(t => t.blockControllers)); // Search for links between with inputs in the selected part and the output in other parts of the graph. Dictionary <VFXDataAnchorController, List <VFXDataAnchorController> > traversingInEdges = new Dictionary <VFXDataAnchorController, List <VFXDataAnchorController> >(); foreach (var edge in m_SourceController.dataEdges.Where( t => { if (parameterNodeControllers.Contains(t.output.sourceNode)) { return(false); } var inputInControllers = m_SourceControllersWithBlocks.Contains(t.input.sourceNode); var outputInControllers = m_SourceControllersWithBlocks.Contains(t.output.sourceNode); return(inputInControllers && !outputInControllers); } )) { List <VFXDataAnchorController> outputs = null; if (!traversingInEdges.TryGetValue(edge.input, out outputs)) { outputs = new List <VFXDataAnchorController>(); traversingInEdges[edge.input] = outputs; } outputs.Add(edge.output); } var newSourceInputs = traversingInEdges.Keys.ToArray(); for (int i = 0; i < newSourceInputs.Length; ++i) { VFXParameter newTargetParameter = m_TargetController.AddVFXParameter(Vector2.zero, VFXLibrary.GetParameters().First(t => t.model.type == newSourceInputs[i].portType)); m_TargetController.LightApplyChanges(); VFXParameterController newTargetParamController = m_TargetController.GetParameterController(newTargetParameter); newTargetParamController.exposed = true; var outputs = traversingInEdges[newSourceInputs[i]]; var linkedParameter = outputs.FirstOrDefault(t => t.sourceNode is VFXParameterNodeController); if (linkedParameter != null) { newTargetParamController.exposedName = (linkedParameter.sourceNode as VFXParameterNodeController).parentController.exposedName; } else { newTargetParamController.exposedName = newSourceInputs[i].name; } //first the equivalent of sourceInput in the target VFXNodeController targetNode = null; Vector2 position; if (newSourceInputs[i].sourceNode is VFXBlockController) { var blockController = newSourceInputs[i].sourceNode as VFXBlockController; if (m_TargetBlocks != null) { targetNode = m_TargetBlocks[m_SourceBlockControllers.IndexOf(blockController)]; position = blockController.contextController.position; } else { var targetContext = m_TargetControllers[m_SourceControllers.IndexOf(blockController.contextController)] as VFXContextController; targetNode = targetContext.blockControllers[blockController.index]; position = blockController.contextController.position; } } else { targetNode = m_TargetControllers[m_SourceControllers.IndexOf(newSourceInputs[i].sourceNode)]; position = targetNode.position; } VFXDataAnchorController targetAnchor = targetNode.inputPorts.First(t => t.path == newSourceInputs[i].path); position.y += targetAnchor.model.owner.inputSlots.IndexOf(targetAnchor.model) * 32; VFXNodeController parameterNode = m_TargetController.AddVFXParameter(position - new Vector2(200, 0), newTargetParamController, null); // Link the parameternode and the input in the target m_TargetController.CreateLink(targetAnchor, parameterNode.outputPorts[0]); if (m_SourceSlotContainer is VFXOperator) { (m_SourceSlotContainer as VFXOperator).ResyncSlots(true); } else if (m_SourceSlotContainer is VFXSubgraphBlock) { VFXSubgraphBlock blk = (m_SourceSlotContainer as VFXSubgraphBlock); blk.RecreateCopy(); blk.ResyncSlots(true); } else if (m_SourceSlotContainer is VFXSubgraphContext) { VFXSubgraphContext ctx = (m_SourceSlotContainer as VFXSubgraphContext); ctx.RecreateCopy(); ctx.ResyncSlots(true); } m_SourceNodeController.ApplyChanges(); //Link all the outputs to the matching input of the subgraph foreach (var output in outputs) { m_SourceController.CreateLink(m_SourceNodeController.inputPorts.First(t => t.model == m_SourceSlotContainer.inputSlots.Last()), output); } } }