protected void UpdateSlot(InventorySlot slot, int slotIndex, Item item, bool isSubSlot) { bool mouseOn = slot.InteractRect.Contains(PlayerInput.MousePosition) && !Locked; slot.State = GUIComponent.ComponentState.None; if (mouseOn && (draggingItem != null || selectedSlot == null || selectedSlot.Slot == slot) && (highlightedSubInventory == null || highlightedSubInventory == this || highlightedSubInventorySlot?.Slot == slot || highlightedSubInventory.Owner == item)) { slot.State = GUIComponent.ComponentState.Hover; if (selectedSlot == null || (!selectedSlot.IsSubSlot && isSubSlot)) { selectedSlot = new SlotReference(this, slot, slotIndex, isSubSlot); } if (draggingItem == null) { if (PlayerInput.LeftButtonHeld()) { draggingItem = Items[slotIndex]; draggingSlot = slot; } } else if (PlayerInput.LeftButtonReleased()) { if (PlayerInput.DoubleClicked()) { doubleClickedItem = item; } } } }
public IEdge Connect(SlotReference fromSlotRef, SlotReference toSlotRef) { var newEdge = ConnectNoValidate(fromSlotRef, toSlotRef); ValidateGraph(); return(newEdge); }
protected virtual void CreateSlots() { slots = new InventorySlot[capacity]; int rectWidth = 40, rectHeight = 40; int spacing = 10; int rows = (int)Math.Ceiling((double)capacity / slotsPerRow); int startX = (int)centerPos.X - (rectWidth * slotsPerRow + spacing * (slotsPerRow - 1)) / 2; int startY = (int)centerPos.Y - rows * (spacing + rectHeight); Rectangle slotRect = new Rectangle(startX, startY, rectWidth, rectHeight); for (int i = 0; i < capacity; i++) { slotRect.X = startX + (rectWidth + spacing) * (i % slotsPerRow) + (int)DrawOffset.X; slotRect.Y = startY + (rectHeight + spacing) * ((int)Math.Floor((double)i / slotsPerRow)) + (int)DrawOffset.Y; slots[i] = new InventorySlot(slotRect); } if (selectedSlot != null && selectedSlot.Inventory == this) { selectedSlot = new SlotReference(this, slots[selectedSlot.SlotIndex], selectedSlot.SlotIndex, selectedSlot.IsSubSlot); } }
public IEnumerable <IEdge> GetEdges(SlotReference s) { var edges = new List <IEdge>(); GetEdges(s, edges); return(edges); }
public void GetEdges(SlotReference s, List <IEdge> foundEdges) { var node = GetNodeFromGuid(s.nodeGuid); if (node == null) { return; } ISlot slot = node.FindSlot <ISlot>(s.slotId); List <IEdge> candidateEdges; if (!m_NodeEdges.TryGetValue(s.nodeGuid, out candidateEdges)) { return; } foreach (var edge in candidateEdges) { var cs = slot.isInputSlot ? edge.inputSlot : edge.outputSlot; if (cs.nodeGuid == s.nodeGuid && cs.slotId == s.slotId) { foundEdges.Add(edge); } } }
protected static Rectangle GetSubInventoryHoverArea(SlotReference subSlot) { Rectangle hoverArea = subSlot.Slot.Rect; hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint(); hoverArea = Rectangle.Union(hoverArea, subSlot.Slot.EquipButtonRect); if (subSlot.Inventory?.slots != null) { foreach (InventorySlot slot in subSlot.Inventory.slots) { Rectangle subSlotRect = slot.InteractRect; subSlotRect.Location += slot.DrawOffset.ToPoint(); hoverArea = Rectangle.Union(hoverArea, subSlotRect); } if (subSlot.Slot.SubInventoryDir < 0) { hoverArea.Height -= hoverArea.Bottom - subSlot.Slot.Rect.Bottom; } else { int over = subSlot.Slot.Rect.Y - hoverArea.Y; hoverArea.Y += over; hoverArea.Height -= over; } } hoverArea.Inflate(10, 10); return(hoverArea); }
public override void CreateSlots() { if (slots == null) { slots = new InventorySlot[capacity]; } for (int i = 0; i < capacity; i++) { InventorySlot prevSlot = slots[i]; Sprite slotSprite = slotSpriteSmall; Rectangle slotRect = new Rectangle( (int)(SlotPositions[i].X), (int)(SlotPositions[i].Y), (int)(slotSprite.size.X * UIScale), (int)(slotSprite.size.Y * UIScale)); if (Items[i] != null) { ItemContainer itemContainer = Items[i].GetComponent <ItemContainer>(); if (itemContainer != null) { if (itemContainer.InventoryTopSprite != null) { slotRect.Width = Math.Max(slotRect.Width, (int)(itemContainer.InventoryTopSprite.size.X * UIScale)); } if (itemContainer.InventoryBottomSprite != null) { slotRect.Width = Math.Max(slotRect.Width, (int)(itemContainer.InventoryBottomSprite.size.X * UIScale)); } } } slots[i] = new InventorySlot(slotRect) { SubInventoryDir = Math.Sign(HUDLayoutSettings.InventoryAreaUpper.Bottom - slotRect.Center.Y), Disabled = false, SlotSprite = slotSprite, Color = SlotTypes[i] == InvSlotType.Any ? Color.White * 0.2f : Color.White * 0.4f }; if (prevSlot != null) { slots[i].DrawOffset = prevSlot.DrawOffset; slots[i].Color = prevSlot.Color; } if (selectedSlot?.ParentInventory == this && selectedSlot.SlotIndex == i) { selectedSlot = new SlotReference(this, slots[i], i, selectedSlot.IsSubSlot, selectedSlot.Inventory); } } AssignQuickUseNumKeys(); highlightedSubInventorySlots.Clear(); screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); CalculateBackgroundFrame(); }
public bool FindPort(SlotReference slotRef, out ShaderPort port) { port = inputContainer.Query <ShaderPort>().ToList() .Concat(outputContainer.Query <ShaderPort>().ToList()) .First(p => p.slot.slotReference.Equals(slotRef)); return(port != null); }
public virtual void CreateSlots() { slots = new InventorySlot[capacity]; int rows = (int)Math.Ceiling((double)capacity / slotsPerRow); int columns = Math.Min(slotsPerRow, capacity); Vector2 spacing = new Vector2(10 * UIScale, (10 + EquipIndicator.size.Y) * UIScale); Vector2 rectSize = new Vector2(60.0f * UIScale); //y is larger to give more space for the header padding = new Vector4(spacing.X, 40 * UIScale, spacing.X, spacing.X); Vector2 slotAreaSize = new Vector2( columns * rectSize.X + (columns - 1) * spacing.X, rows * rectSize.Y + (rows - 1) * spacing.Y); slotAreaSize.X += padding.X + padding.Z; slotAreaSize.Y += padding.Y + padding.W; Vector2 topLeft = new Vector2( GameMain.GraphicsWidth / 2 - slotAreaSize.X / 2, GameMain.GraphicsHeight / 2 - slotAreaSize.Y / 2); if (RectTransform != null) { Vector2 scale = new Vector2( RectTransform.Rect.Width / slotAreaSize.X, RectTransform.Rect.Height / slotAreaSize.Y); spacing *= scale; rectSize *= scale; padding.X *= scale.X; padding.Z *= scale.X; padding.Y *= scale.Y; padding.W *= scale.Y; topLeft = RectTransform.TopLeft.ToVector2() + new Vector2(padding.X, padding.Y); prevRect = RectTransform.Rect; } Rectangle slotRect = new Rectangle((int)topLeft.X, (int)topLeft.Y, (int)rectSize.X, (int)rectSize.Y); for (int i = 0; i < capacity; i++) { slotRect.X = (int)(topLeft.X + (rectSize.X + spacing.X) * (i % slotsPerRow)); slotRect.Y = (int)(topLeft.Y + (rectSize.Y + spacing.Y) * ((int)Math.Floor((double)i / slotsPerRow))); slots[i] = new InventorySlot(slotRect); slots[i].InteractRect = new Rectangle( (int)(slots[i].Rect.X - spacing.X / 2 - 1), (int)(slots[i].Rect.Y - spacing.Y / 2 - 1), (int)(slots[i].Rect.Width + spacing.X + 2), (int)(slots[i].Rect.Height + spacing.Y + 2)); } if (selectedSlot != null && selectedSlot.ParentInventory == this) { selectedSlot = new SlotReference(this, slots[selectedSlot.SlotIndex], selectedSlot.SlotIndex, selectedSlot.IsSubSlot, selectedSlot.Inventory); } CalculateBackgroundFrame(); }
private static void GetParents(IGraph graph, SlotReference slot, Queue <INode> nodes) { var m_edges = graph.GetEdges(slot); foreach (var edge in m_edges) { var otherSlot = edge.inputSlot.Equals(slot) ? edge.outputSlot : edge.inputSlot; nodes.Enqueue(graph.GetNodeFromGuid(otherSlot.nodeGuid)); } }
private static void GetChildren(IGraph graph, SlotReference slot, IList <INode> nodes) { var m_edges = graph.GetEdges(slot); foreach (var edge in m_edges) { var otherSlot = edge.inputSlot.Equals(slot) ? edge.outputSlot : edge.inputSlot; nodes.Add(graph.GetNodeFromGuid(otherSlot.nodeGuid)); } }
public void GetOutputAndInputSlots(out SlotReference outputSlotRef, out List<SlotReference> inputSlotRefs) { var inputSlot = FindSlot<MaterialSlot>(kInputSlotID); var inEdges = owner.GetEdges(inputSlot.slotReference).ToList(); outputSlotRef = inEdges.Any() ? inEdges.First().outputSlot : new SlotReference(); var outputSlot = FindSlot<MaterialSlot>(kOutputSlotID); // Get the slot where this edge ends. var outEdges = owner.GetEdges(outputSlot.slotReference); inputSlotRefs = new List<SlotReference>(outEdges.Select(edge => edge.inputSlot)); }
IEdge ConnectNoValidate(SlotReference fromSlotRef, SlotReference toSlotRef) { var fromNode = GetNodeFromGuid(fromSlotRef.nodeGuid); var toNode = GetNodeFromGuid(toSlotRef.nodeGuid); if (fromNode == null || toNode == null) { return(null); } // if fromNode is already connected to toNode // do now allow a connection as toNode will then // have an edge to fromNode creating a cycle. // if this is parsed it will lead to an infinite loop. var dependentNodes = new List <AbstractMaterialNode>(); NodeUtils.CollectNodesNodeFeedsInto(dependentNodes, toNode); if (dependentNodes.Contains(fromNode)) { return(null); } var fromSlot = fromNode.FindSlot <ISlot>(fromSlotRef.slotId); var toSlot = toNode.FindSlot <ISlot>(toSlotRef.slotId); if (fromSlot.isOutputSlot == toSlot.isOutputSlot) { return(null); } var outputSlot = fromSlot.isOutputSlot ? fromSlotRef : toSlotRef; var inputSlot = fromSlot.isInputSlot ? fromSlotRef : toSlotRef; s_TempEdges.Clear(); GetEdges(inputSlot, s_TempEdges); // remove any inputs that exits before adding foreach (var edge in s_TempEdges) { RemoveEdgeNoValidate(edge); } var newEdge = new Edge(outputSlot, inputSlot); m_Edges.Add(newEdge); m_AddedEdges.Add(newEdge); AddEdgeToNodeEdges(newEdge); //Debug.LogFormat("Connected edge: {0} -> {1} ({2} -> {3})\n{4}", newEdge.outputSlot.nodeGuid, newEdge.inputSlot.nodeGuid, fromNode.name, toNode.name, Environment.StackTrace); return(newEdge); }
protected override string GetOutputForSlot(SlotReference fromSocketRef, ConcreteSlotValueType valueType, GenerationMode generationMode) { var slotRef = NodeUtils.DepthFirstCollectRedirectNodeFromNode(this); var fromLeftNode = owner.GetNodeFromGuid<AbstractMaterialNode>(slotRef.nodeGuid); if (fromLeftNode is RedirectNodeData) { return GetSlotValue(kInputSlotID, generationMode); } if (fromLeftNode != null) { return GenerationUtils.AdaptNodeOutput(fromLeftNode, slotRef.slotId, valueType); } return base.GetOutputForSlot(fromSocketRef, valueType, generationMode); }
protected internal override string GetOutputForSlot(SlotReference fromSocketRef, ConcreteSlotValueType valueType, GenerationMode generationMode) { var slotRef = NodeUtils.DepthFirstCollectRedirectNodeFromNode(this); var fromLeftNode = slotRef.node; if (fromLeftNode is RedirectNodeData) { return(GetSlotValue(kInputSlotID, generationMode)); } if (fromLeftNode != null) { return(GenerationUtils.AdaptNodeOutput(fromLeftNode, slotRef.slotId, valueType)); } return(base.GetOutputForSlot(fromSocketRef, valueType, generationMode)); }
internal void PasteGraph(CopyPasteGraph graphToPaste, List <INode> remappedNodes, List <IEdge> remappedEdges) { var nodeGuidMap = new Dictionary <Guid, Guid>(); foreach (var node in graphToPaste.GetNodes <INode>()) { var oldGuid = node.guid; var newGuid = node.RewriteGuid(); nodeGuidMap[oldGuid] = newGuid; var drawState = node.drawState; var position = drawState.position; position.x += 30; position.y += 30; drawState.position = position; node.drawState = drawState; remappedNodes.Add(node); AddNode(node); // add the node to the pasted node list m_PastedNodes.Add(node); } // only connect edges within pasted elements, discard // external edges. foreach (var edge in graphToPaste.edges) { var outputSlot = edge.outputSlot; var inputSlot = edge.inputSlot; Guid remappedOutputNodeGuid; Guid remappedInputNodeGuid; if (nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid) && nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid)) { var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId); var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId); remappedEdges.Add(Connect(outputSlotRef, inputSlotRef)); } } ValidateGraph(); }
private void ShowSubInventory(SlotReference slotRef, float deltaTime, Camera cam, List <SlotReference> hideSubInventories, bool isEquippedSubInventory) { Rectangle hoverArea = GetSubInventoryHoverArea(slotRef); if (isEquippedSubInventory) { foreach (SlotReference highlightedSubInventorySlot in highlightedSubInventorySlots) { if (highlightedSubInventorySlot == slotRef) { continue; } if (hoverArea.Intersects(GetSubInventoryHoverArea(highlightedSubInventorySlot))) { return; // If an equipped one intersects with a currently active hover one, do not open } } } if (isEquippedSubInventory) { slotRef.Inventory.OpenState = 1.0f; // Reset animation when initially equipped } highlightedSubInventorySlots.Add(slotRef); slotRef.Inventory.HideTimer = 1f; UpdateSubInventory(deltaTime, slotRef.SlotIndex, cam); //hide previously opened subinventories if this one overlaps with them foreach (SlotReference highlightedSubInventorySlot in highlightedSubInventorySlots) { if (highlightedSubInventorySlot == slotRef) { continue; } if (hoverArea.Intersects(GetSubInventoryHoverArea(highlightedSubInventorySlot))) { hideSubInventories.Add(highlightedSubInventorySlot); highlightedSubInventorySlot.Inventory.HideTimer = 0.0f; } } }
public static void UpdateDragging() { if (draggingItem != null && PlayerInput.LeftButtonReleased()) { if (selectedSlot == null) { draggingItem.ParentInventory?.CreateNetworkEvent(); draggingItem.Drop(); GUI.PlayUISound(GUISoundType.DropItem); } else if (selectedSlot.Inventory.Items[selectedSlot.SlotIndex] != draggingItem) { Inventory selectedInventory = selectedSlot.Inventory; int slotIndex = selectedSlot.SlotIndex; if (selectedInventory.TryPutItem(draggingItem, slotIndex, true, true, Character.Controlled)) { if (selectedInventory.slots != null) { selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f); } GUI.PlayUISound(GUISoundType.PickItem); } else { if (selectedInventory.slots != null) { selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); } GUI.PlayUISound(GUISoundType.PickItemFail); } draggingItem = null; draggingSlot = null; } draggingItem = null; } if (selectedSlot != null && !selectedSlot.Slot.InteractRect.Contains(PlayerInput.MousePosition)) { selectedSlot = null; } }
public void InsertInGraph(IGraph graph, List <INode> remappedNodes, List <IEdge> remappedEdges) { var nodeGuidMap = new Dictionary <Guid, Guid>(); foreach (var node in GetNodes <INode>()) { var oldGuid = node.guid; var newGuid = node.RewriteGuid(); nodeGuidMap[oldGuid] = newGuid; var drawState = node.drawState; var position = drawState.position; position.x += 30; position.y += 30; drawState.position = position; node.drawState = drawState; remappedNodes.Add(node); graph.AddNode(node); } // only connect edges within pasted elements, discard // external edges. foreach (var edge in edges) { var outputSlot = edge.outputSlot; var inputSlot = edge.inputSlot; Guid remappedOutputNodeGuid; Guid remappedInputNodeGuid; if (nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid) && nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid)) { var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId); var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId); remappedEdges.Add(graph.Connect(outputSlotRef, inputSlotRef)); } } m_Nodes.Clear(); m_Edges.Clear(); graph.ValidateGraph(); }
// Static version for testability public static RedirectNodeData Create(GraphData graph, SlotValueType edgeType, Vector2 absolutePosition, SlotReference inputRef, SlotReference outputRef, GroupData group) { var nodeData = new RedirectNodeData(); nodeData.AddSlots(edgeType); nodeData.SetPosition(absolutePosition); nodeData.group = group; // Hard-coded for single input-output. Changes would be needed for multi-input redirects var nodeInSlotRef = nodeData.GetSlotReference(RedirectNodeData.kInputSlotID); var nodeOutSlotRef = nodeData.GetSlotReference(RedirectNodeData.kOutputSlotID); graph.owner.RegisterCompleteObjectUndo("Add Redirect Node"); graph.AddNode(nodeData); graph.Connect(outputRef, nodeInSlotRef); graph.Connect(nodeOutSlotRef, inputRef); return(nodeData); }
internal void PasteGraph(CopyPasteGraph graphToPaste, List <AbstractMaterialNode> remappedNodes, List <IEdge> remappedEdges) { var groupGuidMap = new Dictionary <Guid, Guid>(); foreach (var group in graphToPaste.groups) { var position = group.position; position.x += 30; position.y += 30; GroupData newGroup = new GroupData(group.title, position); var oldGuid = group.guid; var newGuid = newGroup.guid; groupGuidMap[oldGuid] = newGuid; AddGroup(newGroup); m_PastedGroups.Add(newGroup); } var nodeGuidMap = new Dictionary <Guid, Guid>(); foreach (var node in graphToPaste.GetNodes <AbstractMaterialNode>()) { AbstractMaterialNode pastedNode = node; var oldGuid = node.guid; var newGuid = node.RewriteGuid(); nodeGuidMap[oldGuid] = newGuid; // Check if the property nodes need to be made into a concrete node. if (node is PropertyNode) { PropertyNode propertyNode = (PropertyNode)node; // If the property is not in the current graph, do check if the // property can be made into a concrete node. if (!m_Properties.Select(x => x.guid).Contains(propertyNode.propertyGuid)) { // If the property is in the serialized paste graph, make the property node into a property node. var pastedGraphMetaProperties = graphToPaste.metaProperties.Where(x => x.guid == propertyNode.propertyGuid); if (pastedGraphMetaProperties.Any()) { pastedNode = pastedGraphMetaProperties.FirstOrDefault().ToConcreteNode(); pastedNode.drawState = node.drawState; nodeGuidMap[oldGuid] = pastedNode.guid; } } } AbstractMaterialNode abstractMaterialNode = (AbstractMaterialNode)node; // Check if the node is inside a group if (groupGuidMap.ContainsKey(abstractMaterialNode.groupGuid)) { var absNode = pastedNode as AbstractMaterialNode; absNode.groupGuid = groupGuidMap[abstractMaterialNode.groupGuid]; pastedNode = absNode; } var drawState = node.drawState; var position = drawState.position; position.x += 30; position.y += 30; drawState.position = position; node.drawState = drawState; remappedNodes.Add(pastedNode); AddNode(pastedNode); // add the node to the pasted node list m_PastedNodes.Add(pastedNode); } // only connect edges within pasted elements, discard // external edges. foreach (var edge in graphToPaste.edges) { var outputSlot = edge.outputSlot; var inputSlot = edge.inputSlot; Guid remappedOutputNodeGuid; Guid remappedInputNodeGuid; if (nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid) && nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid)) { var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId); var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId); remappedEdges.Add(Connect(outputSlotRef, inputSlotRef)); } } ValidateGraph(); }
public void ToSubGraph() { var graphView = graphEditorView.graphView; var path = EditorUtility.SaveFilePanelInProject("Save Sub Graph", "New Shader Sub Graph", ShaderSubGraphImporter.Extension, ""); path = path.Replace(Application.dataPath, "Assets"); if (path.Length == 0) { return; } graphObject.RegisterCompleteObjectUndo("Convert To Subgraph"); var nodes = graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode || x.node is SubGraphOutputNode)).Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(); var bounds = Rect.MinMaxRect(float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity); foreach (var node in nodes) { var center = node.drawState.position.center; bounds = Rect.MinMaxRect( Mathf.Min(bounds.xMin, center.x), Mathf.Min(bounds.yMin, center.y), Mathf.Max(bounds.xMax, center.x), Mathf.Max(bounds.yMax, center.y)); } var middle = bounds.center; bounds.center = Vector2.zero; // Collect graph inputs var graphInputs = graphView.selection.OfType <BlackboardField>().Select(x => x.userData as ShaderInput); // Collect the property nodes and get the corresponding properties var propertyNodeGuids = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is PropertyNode)).Select(x => ((PropertyNode)x.node).propertyGuid); var metaProperties = graphView.graph.properties.Where(x => propertyNodeGuids.Contains(x.guid)); // Collect the keyword nodes and get the corresponding keywords var keywordNodeGuids = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is KeywordNode)).Select(x => ((KeywordNode)x.node).keywordGuid); var metaKeywords = graphView.graph.keywords.Where(x => keywordNodeGuids.Contains(x.guid)); var copyPasteGraph = new CopyPasteGraph( graphView.graph.assetGuid, graphView.selection.OfType <ShaderGroup>().Select(x => x.userData), graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode || x.node is SubGraphOutputNode)).Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(), graphView.selection.OfType <Edge>().Select(x => x.userData as IEdge), graphInputs, metaProperties, metaKeywords, graphView.selection.OfType <StickyNote>().Select(x => x.userData)); var deserialized = CopyPasteGraph.FromJson(JsonUtility.ToJson(copyPasteGraph, false)); if (deserialized == null) { return; } var subGraph = new GraphData { isSubGraph = true }; subGraph.path = "Sub Graphs"; var subGraphOutputNode = new SubGraphOutputNode(); { var drawState = subGraphOutputNode.drawState; drawState.position = new Rect(new Vector2(bounds.xMax + 200f, 0f), drawState.position.size); subGraphOutputNode.drawState = drawState; } subGraph.AddNode(subGraphOutputNode); // Always copy deserialized keyword inputs foreach (ShaderKeyword keyword in deserialized.metaKeywords) { ShaderInput copiedInput = keyword.Copy(); subGraph.SanitizeGraphInputName(copiedInput); subGraph.SanitizeGraphInputReferenceName(copiedInput, keyword.overrideReferenceName); subGraph.AddGraphInput(copiedInput); // Update the keyword nodes that depends on the copied keyword var dependentKeywordNodes = deserialized.GetNodes <KeywordNode>().Where(x => x.keywordGuid == keyword.guid); foreach (var node in dependentKeywordNodes) { node.owner = graphView.graph; node.keywordGuid = copiedInput.guid; } } var groupGuidMap = new Dictionary <Guid, Guid>(); foreach (GroupData groupData in deserialized.groups) { var oldGuid = groupData.guid; var newGuid = groupData.RewriteGuid(); groupGuidMap[oldGuid] = newGuid; subGraph.CreateGroup(groupData); } List <Guid> groupGuids = new List <Guid>(); var nodeGuidMap = new Dictionary <Guid, Guid>(); foreach (var node in deserialized.GetNodes <AbstractMaterialNode>()) { var oldGuid = node.guid; var newGuid = node.RewriteGuid(); nodeGuidMap[oldGuid] = newGuid; var drawState = node.drawState; drawState.position = new Rect(drawState.position.position - middle, drawState.position.size); node.drawState = drawState; if (!groupGuids.Contains(node.groupGuid)) { groupGuids.Add(node.groupGuid); } // Checking if the group guid is also being copied. // If not then nullify that guid if (node.groupGuid != Guid.Empty) { node.groupGuid = !groupGuidMap.ContainsKey(node.groupGuid) ? Guid.Empty : groupGuidMap[node.groupGuid]; } subGraph.AddNode(node); } foreach (var note in deserialized.stickyNotes) { if (!groupGuids.Contains(note.groupGuid)) { groupGuids.Add(note.groupGuid); } if (note.groupGuid != Guid.Empty) { note.groupGuid = !groupGuidMap.ContainsKey(note.groupGuid) ? Guid.Empty : groupGuidMap[note.groupGuid]; } note.RewriteGuid(); subGraph.AddStickyNote(note); } // figure out what needs remapping var externalOutputSlots = new List <IEdge>(); var externalInputSlots = new List <IEdge>(); foreach (var edge in deserialized.edges) { var outputSlot = edge.outputSlot; var inputSlot = edge.inputSlot; Guid remappedOutputNodeGuid; Guid remappedInputNodeGuid; var outputSlotExistsInSubgraph = nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid); var inputSlotExistsInSubgraph = nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid); // pasting nice internal links! if (outputSlotExistsInSubgraph && inputSlotExistsInSubgraph) { var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId); var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId); subGraph.Connect(outputSlotRef, inputSlotRef); } // one edge needs to go to outside world else if (outputSlotExistsInSubgraph) { externalInputSlots.Add(edge); } else if (inputSlotExistsInSubgraph) { externalOutputSlots.Add(edge); } } // Find the unique edges coming INTO the graph var uniqueIncomingEdges = externalOutputSlots.GroupBy( edge => edge.outputSlot, edge => edge, (key, edges) => new { slotRef = key, edges = edges.ToList() }); var externalInputNeedingConnection = new List <KeyValuePair <IEdge, AbstractShaderProperty> >(); var amountOfProps = uniqueIncomingEdges.Count(); const int height = 40; const int subtractHeight = 20; var propPos = new Vector2(0, -((amountOfProps / 2) + height) - subtractHeight); foreach (var group in uniqueIncomingEdges) { var sr = group.slotRef; var fromNode = graphObject.graph.GetNodeFromGuid(sr.nodeGuid); var fromSlot = fromNode.FindOutputSlot <MaterialSlot>(sr.slotId); AbstractShaderProperty prop; switch (fromSlot.concreteValueType) { case ConcreteSlotValueType.Texture2D: prop = new Texture2DShaderProperty(); break; case ConcreteSlotValueType.Texture2DArray: prop = new Texture2DArrayShaderProperty(); break; case ConcreteSlotValueType.Texture3D: prop = new Texture3DShaderProperty(); break; case ConcreteSlotValueType.Cubemap: prop = new CubemapShaderProperty(); break; case ConcreteSlotValueType.Vector4: prop = new Vector4ShaderProperty(); break; case ConcreteSlotValueType.Vector3: prop = new Vector3ShaderProperty(); break; case ConcreteSlotValueType.Vector2: prop = new Vector2ShaderProperty(); break; case ConcreteSlotValueType.Vector1: prop = new Vector1ShaderProperty(); break; case ConcreteSlotValueType.Boolean: prop = new BooleanShaderProperty(); break; case ConcreteSlotValueType.Matrix2: prop = new Matrix2ShaderProperty(); break; case ConcreteSlotValueType.Matrix3: prop = new Matrix3ShaderProperty(); break; case ConcreteSlotValueType.Matrix4: prop = new Matrix4ShaderProperty(); break; case ConcreteSlotValueType.SamplerState: prop = new SamplerStateShaderProperty(); break; case ConcreteSlotValueType.Gradient: prop = new GradientShaderProperty(); break; default: throw new ArgumentOutOfRangeException(); } if (prop != null) { var materialGraph = (GraphData)graphObject.graph; var fromPropertyNode = fromNode as PropertyNode; var fromProperty = fromPropertyNode != null?materialGraph.properties.FirstOrDefault(p => p.guid == fromPropertyNode.propertyGuid) : null; prop.displayName = fromProperty != null ? fromProperty.displayName : fromSlot.concreteValueType.ToString(); subGraph.AddGraphInput(prop); var propNode = new PropertyNode(); { var drawState = propNode.drawState; drawState.position = new Rect(new Vector2(bounds.xMin - 300f, 0f) + propPos, drawState.position.size); propPos += new Vector2(0, height); propNode.drawState = drawState; } subGraph.AddNode(propNode); propNode.propertyGuid = prop.guid; foreach (var edge in group.edges) { subGraph.Connect( new SlotReference(propNode.guid, PropertyNode.OutputSlotId), new SlotReference(nodeGuidMap[edge.inputSlot.nodeGuid], edge.inputSlot.slotId)); externalInputNeedingConnection.Add(new KeyValuePair <IEdge, AbstractShaderProperty>(edge, prop)); } } } var uniqueOutgoingEdges = externalInputSlots.GroupBy( edge => edge.outputSlot, edge => edge, (key, edges) => new { slot = key, edges = edges.ToList() }); var externalOutputsNeedingConnection = new List <KeyValuePair <IEdge, IEdge> >(); foreach (var group in uniqueOutgoingEdges) { var outputNode = subGraph.outputNode as SubGraphOutputNode; AbstractMaterialNode node = graphView.graph.GetNodeFromGuid(group.edges[0].outputSlot.nodeGuid); MaterialSlot slot = node.FindSlot <MaterialSlot>(group.edges[0].outputSlot.slotId); var slotId = outputNode.AddSlot(slot.concreteValueType); var inputSlotRef = new SlotReference(outputNode.guid, slotId); foreach (var edge in group.edges) { var newEdge = subGraph.Connect(new SlotReference(nodeGuidMap[edge.outputSlot.nodeGuid], edge.outputSlot.slotId), inputSlotRef); externalOutputsNeedingConnection.Add(new KeyValuePair <IEdge, IEdge>(edge, newEdge)); } } if (FileUtilities.WriteShaderGraphToDisk(path, subGraph)) { AssetDatabase.ImportAsset(path); } var loadedSubGraph = AssetDatabase.LoadAssetAtPath(path, typeof(SubGraphAsset)) as SubGraphAsset; if (loadedSubGraph == null) { return; } var subGraphNode = new SubGraphNode(); var ds = subGraphNode.drawState; ds.position = new Rect(middle - new Vector2(100f, 150f), Vector2.zero); subGraphNode.drawState = ds; // Add the subgraph into the group if the nodes was all in the same group group if (groupGuids.Count == 1) { subGraphNode.groupGuid = groupGuids[0]; } graphObject.graph.AddNode(subGraphNode); subGraphNode.asset = loadedSubGraph; foreach (var edgeMap in externalInputNeedingConnection) { graphObject.graph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.guid.GetHashCode())); } foreach (var edgeMap in externalOutputsNeedingConnection) { graphObject.graph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot); } graphObject.graph.RemoveElements( graphView.selection.OfType <IShaderNodeView>().Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(), new IEdge[] {}, new GroupData[] {}, graphView.selection.OfType <StickyNote>().Select(x => x.userData).ToArray()); graphObject.graph.ValidateGraph(); }
public void Connect(SlotReference from, SlotReference to) { _graph.Connect(from, to); }
public void ToSubGraph() { var path = EditorUtility.SaveFilePanelInProject("Save Sub Graph", "New Shader Sub Graph", ShaderSubGraphImporter.Extension, ""); path = path.Replace(Application.dataPath, "Assets"); if (path.Length == 0) { return; } graphObject.RegisterCompleteObjectUndo("Convert To Subgraph"); var graphView = graphEditorView.graphView; var nodes = graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode)).Select(x => x.node as AbstractMaterialNode).ToArray(); var bounds = Rect.MinMaxRect(float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity); foreach (var node in nodes) { var center = node.drawState.position.center; bounds = Rect.MinMaxRect( Mathf.Min(bounds.xMin, center.x), Mathf.Min(bounds.yMin, center.y), Mathf.Max(bounds.xMax, center.x), Mathf.Max(bounds.yMax, center.y)); } var middle = bounds.center; bounds.center = Vector2.zero; // Collect the property nodes and get the corresponding properties var propertyNodeGuids = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is PropertyNode)).Select(x => ((PropertyNode)x.node).propertyGuid); var metaProperties = graphView.graph.properties.Where(x => propertyNodeGuids.Contains(x.guid)); var copyPasteGraph = new CopyPasteGraph( graphView.graph.guid, graphView.selection.OfType <ShaderGroup>().Select(x => x.userData), graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode)).Select(x => x.node as AbstractMaterialNode), graphView.selection.OfType <Edge>().Select(x => x.userData as IEdge), graphView.selection.OfType <BlackboardField>().Select(x => x.userData as AbstractShaderProperty), metaProperties); var deserialized = CopyPasteGraph.FromJson(JsonUtility.ToJson(copyPasteGraph, false)); if (deserialized == null) { return; } var subGraph = new GraphData { isSubGraph = true }; subGraph.path = "Sub Graphs"; var subGraphOutputNode = new SubGraphOutputNode(); { var drawState = subGraphOutputNode.drawState; drawState.position = new Rect(new Vector2(bounds.xMax + 200f, 0f), drawState.position.size); subGraphOutputNode.drawState = drawState; } subGraph.AddNode(subGraphOutputNode); var nodeGuidMap = new Dictionary <Guid, Guid>(); foreach (var node in deserialized.GetNodes <AbstractMaterialNode>()) { var oldGuid = node.guid; var newGuid = node.RewriteGuid(); nodeGuidMap[oldGuid] = newGuid; var drawState = node.drawState; drawState.position = new Rect(drawState.position.position - middle, drawState.position.size); node.drawState = drawState; subGraph.AddNode(node); } // figure out what needs remapping var externalOutputSlots = new List <IEdge>(); var externalInputSlots = new List <IEdge>(); foreach (var edge in deserialized.edges) { var outputSlot = edge.outputSlot; var inputSlot = edge.inputSlot; Guid remappedOutputNodeGuid; Guid remappedInputNodeGuid; var outputSlotExistsInSubgraph = nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid); var inputSlotExistsInSubgraph = nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid); // pasting nice internal links! if (outputSlotExistsInSubgraph && inputSlotExistsInSubgraph) { var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId); var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId); subGraph.Connect(outputSlotRef, inputSlotRef); } // one edge needs to go to outside world else if (outputSlotExistsInSubgraph) { externalInputSlots.Add(edge); } else if (inputSlotExistsInSubgraph) { externalOutputSlots.Add(edge); } } // Find the unique edges coming INTO the graph var uniqueIncomingEdges = externalOutputSlots.GroupBy( edge => edge.outputSlot, edge => edge, (key, edges) => new { slotRef = key, edges = edges.ToList() }); var externalInputNeedingConnection = new List <KeyValuePair <IEdge, AbstractShaderProperty> >(); foreach (var group in uniqueIncomingEdges) { var sr = group.slotRef; var fromNode = graphObject.graph.GetNodeFromGuid(sr.nodeGuid); var fromSlot = fromNode.FindOutputSlot <MaterialSlot>(sr.slotId); AbstractShaderProperty prop; switch (fromSlot.concreteValueType) { case ConcreteSlotValueType.Texture2D: prop = new TextureShaderProperty(); break; case ConcreteSlotValueType.Texture2DArray: prop = new Texture2DArrayShaderProperty(); break; case ConcreteSlotValueType.Texture3D: prop = new Texture3DShaderProperty(); break; case ConcreteSlotValueType.Cubemap: prop = new CubemapShaderProperty(); break; case ConcreteSlotValueType.Vector4: prop = new Vector4ShaderProperty(); break; case ConcreteSlotValueType.Vector3: prop = new Vector3ShaderProperty(); break; case ConcreteSlotValueType.Vector2: prop = new Vector2ShaderProperty(); break; case ConcreteSlotValueType.Vector1: prop = new Vector1ShaderProperty(); break; case ConcreteSlotValueType.Boolean: prop = new BooleanShaderProperty(); break; default: throw new ArgumentOutOfRangeException(); } if (prop != null) { var materialGraph = (GraphData)graphObject.graph; var fromPropertyNode = fromNode as PropertyNode; var fromProperty = fromPropertyNode != null?materialGraph.properties.FirstOrDefault(p => p.guid == fromPropertyNode.propertyGuid) : null; prop.displayName = fromProperty != null ? fromProperty.displayName : fromSlot.concreteValueType.ToString(); subGraph.AddShaderProperty(prop); var propNode = new PropertyNode(); { var drawState = propNode.drawState; drawState.position = new Rect(new Vector2(bounds.xMin - 300f, 0f), drawState.position.size); propNode.drawState = drawState; } subGraph.AddNode(propNode); propNode.propertyGuid = prop.guid; foreach (var edge in group.edges) { subGraph.Connect( new SlotReference(propNode.guid, PropertyNode.OutputSlotId), new SlotReference(nodeGuidMap[edge.inputSlot.nodeGuid], edge.inputSlot.slotId)); externalInputNeedingConnection.Add(new KeyValuePair <IEdge, AbstractShaderProperty>(edge, prop)); } } } var uniqueOutgoingEdges = externalInputSlots.GroupBy( edge => edge.inputSlot, edge => edge, (key, edges) => new { slot = key, edges = edges.ToList() }); var externalOutputsNeedingConnection = new List <KeyValuePair <IEdge, IEdge> >(); foreach (var group in uniqueOutgoingEdges) { var outputNode = subGraph.outputNode as SubGraphOutputNode; AbstractMaterialNode node = graphView.graph.GetNodeFromGuid(group.edges[0].outputSlot.nodeGuid); MaterialSlot slot = node.FindSlot <MaterialSlot>(group.edges[0].outputSlot.slotId); var slotId = outputNode.AddSlot(slot.concreteValueType); var inputSlotRef = new SlotReference(outputNode.guid, slotId); foreach (var edge in group.edges) { var newEdge = subGraph.Connect(new SlotReference(nodeGuidMap[edge.outputSlot.nodeGuid], edge.outputSlot.slotId), inputSlotRef); externalOutputsNeedingConnection.Add(new KeyValuePair <IEdge, IEdge>(edge, newEdge)); } } File.WriteAllText(path, EditorJsonUtility.ToJson(subGraph)); AssetDatabase.ImportAsset(path); var loadedSubGraph = AssetDatabase.LoadAssetAtPath(path, typeof(MaterialSubGraphAsset)) as MaterialSubGraphAsset; if (loadedSubGraph == null) { return; } var subGraphNode = new SubGraphNode(); var ds = subGraphNode.drawState; ds.position = new Rect(middle - new Vector2(100f, 150f), Vector2.zero); subGraphNode.drawState = ds; graphObject.graph.AddNode(subGraphNode); subGraphNode.subGraphAsset = loadedSubGraph; foreach (var edgeMap in externalInputNeedingConnection) { graphObject.graph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.guid.GetHashCode())); } foreach (var edgeMap in externalOutputsNeedingConnection) { graphObject.graph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot); } graphObject.graph.RemoveElements( graphView.selection.OfType <IShaderNodeView>().Select(x => x.node as AbstractMaterialNode), Enumerable.Empty <IEdge>(), Enumerable.Empty <GroupData>()); graphObject.graph.ValidateGraph(); }
public void ToSubGraph() { var graphView = graphEditorView.graphView; string path; string sessionStateResult = SessionState.GetString(k_PrevSubGraphPathKey, k_PrevSubGraphPathDefaultValue); string pathToOriginSG = Path.GetDirectoryName(AssetDatabase.GUIDToAssetPath(selectedGuid)); if (!sessionStateResult.Equals(k_PrevSubGraphPathDefaultValue)) { path = sessionStateResult; } else { path = pathToOriginSG; } path = EditorUtility.SaveFilePanelInProject("Save Sub Graph", "New Shader Sub Graph", ShaderSubGraphImporter.Extension, "", path); path = path.Replace(Application.dataPath, "Assets"); if (path.Length == 0) { return; } graphObject.RegisterCompleteObjectUndo("Convert To Subgraph"); var nodes = graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode || x.node is SubGraphOutputNode)).Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(); var bounds = Rect.MinMaxRect(float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity); foreach (var node in nodes) { var center = node.drawState.position.center; bounds = Rect.MinMaxRect( Mathf.Min(bounds.xMin, center.x), Mathf.Min(bounds.yMin, center.y), Mathf.Max(bounds.xMax, center.x), Mathf.Max(bounds.yMax, center.y)); } var middle = bounds.center; bounds.center = Vector2.zero; // Collect graph inputs var graphInputs = graphView.selection.OfType <BlackboardField>().Select(x => x.userData as ShaderInput); // Collect the property nodes and get the corresponding properties var propertyNodes = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is PropertyNode)).Select(x => ((PropertyNode)x.node).property); var metaProperties = graphView.graph.properties.Where(x => propertyNodes.Contains(x)); // Collect the keyword nodes and get the corresponding keywords var keywordNodes = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is KeywordNode)).Select(x => ((KeywordNode)x.node).keyword); var metaKeywords = graphView.graph.keywords.Where(x => keywordNodes.Contains(x)); var copyPasteGraph = new CopyPasteGraph(graphView.selection.OfType <ShaderGroup>().Select(x => x.userData), graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode || x.node is SubGraphOutputNode)).Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(), graphView.selection.OfType <Edge>().Select(x => x.userData as Graphing.Edge), graphInputs, metaProperties, metaKeywords, graphView.selection.OfType <StickyNote>().Select(x => x.userData), true); // why do we serialize and deserialize only to make copies of everything in the steps below? // is this just to clear out all non-serialized data? var deserialized = CopyPasteGraph.FromJson(MultiJson.Serialize(copyPasteGraph), graphView.graph); if (deserialized == null) { return; } var subGraph = new GraphData { isSubGraph = true, path = "Sub Graphs" }; var subGraphOutputNode = new SubGraphOutputNode(); { var drawState = subGraphOutputNode.drawState; drawState.position = new Rect(new Vector2(bounds.xMax + 200f, 0f), drawState.position.size); subGraphOutputNode.drawState = drawState; } subGraph.AddNode(subGraphOutputNode); subGraph.outputNode = subGraphOutputNode; // Always copy deserialized keyword inputs foreach (ShaderKeyword keyword in deserialized.metaKeywords) { var copiedInput = (ShaderKeyword)keyword.Copy(); subGraph.SanitizeGraphInputName(copiedInput); subGraph.SanitizeGraphInputReferenceName(copiedInput, keyword.overrideReferenceName); subGraph.AddGraphInput(copiedInput); // Update the keyword nodes that depends on the copied keyword var dependentKeywordNodes = deserialized.GetNodes <KeywordNode>().Where(x => x.keyword == keyword); foreach (var node in dependentKeywordNodes) { node.owner = graphView.graph; node.keyword = copiedInput; } } foreach (GroupData groupData in deserialized.groups) { subGraph.CreateGroup(groupData); } foreach (var node in deserialized.GetNodes <AbstractMaterialNode>()) { var drawState = node.drawState; drawState.position = new Rect(drawState.position.position - middle, drawState.position.size); node.drawState = drawState; // Checking if the group guid is also being copied. // If not then nullify that guid if (node.group != null && !subGraph.groups.Contains(node.group)) { node.group = null; } subGraph.AddNode(node); } foreach (var note in deserialized.stickyNotes) { if (note.group != null && !subGraph.groups.Contains(note.group)) { note.group = null; } subGraph.AddStickyNote(note); } // figure out what needs remapping var externalOutputSlots = new List <Graphing.Edge>(); var externalInputSlots = new List <Graphing.Edge>(); foreach (var edge in deserialized.edges) { var outputSlot = edge.outputSlot; var inputSlot = edge.inputSlot; var outputSlotExistsInSubgraph = subGraph.ContainsNode(outputSlot.node); var inputSlotExistsInSubgraph = subGraph.ContainsNode(inputSlot.node); // pasting nice internal links! if (outputSlotExistsInSubgraph && inputSlotExistsInSubgraph) { subGraph.Connect(outputSlot, inputSlot); } // one edge needs to go to outside world else if (outputSlotExistsInSubgraph) { externalInputSlots.Add(edge); } else if (inputSlotExistsInSubgraph) { externalOutputSlots.Add(edge); } } // Find the unique edges coming INTO the graph var uniqueIncomingEdges = externalOutputSlots.GroupBy( edge => edge.outputSlot, edge => edge, (key, edges) => new { slotRef = key, edges = edges.ToList() }); var externalInputNeedingConnection = new List <KeyValuePair <IEdge, AbstractShaderProperty> >(); var amountOfProps = uniqueIncomingEdges.Count(); const int height = 40; const int subtractHeight = 20; var propPos = new Vector2(0, -((amountOfProps / 2) + height) - subtractHeight); foreach (var group in uniqueIncomingEdges) { var sr = group.slotRef; var fromNode = sr.node; var fromSlot = sr.slot; var materialGraph = graphObject.graph; var fromProperty = fromNode is PropertyNode fromPropertyNode ? materialGraph.properties.FirstOrDefault(p => p == fromPropertyNode.property) : null; AbstractShaderProperty prop; switch (fromSlot.concreteValueType) { case ConcreteSlotValueType.Texture2D: prop = new Texture2DShaderProperty(); break; case ConcreteSlotValueType.Texture2DArray: prop = new Texture2DArrayShaderProperty(); break; case ConcreteSlotValueType.Texture3D: prop = new Texture3DShaderProperty(); break; case ConcreteSlotValueType.Cubemap: prop = new CubemapShaderProperty(); break; case ConcreteSlotValueType.Vector4: prop = new Vector4ShaderProperty(); break; case ConcreteSlotValueType.Vector3: prop = new Vector3ShaderProperty(); break; case ConcreteSlotValueType.Vector2: prop = new Vector2ShaderProperty(); break; case ConcreteSlotValueType.Vector1: prop = new Vector1ShaderProperty(); break; case ConcreteSlotValueType.Boolean: prop = new BooleanShaderProperty(); break; case ConcreteSlotValueType.Matrix2: prop = new Matrix2ShaderProperty(); break; case ConcreteSlotValueType.Matrix3: prop = new Matrix3ShaderProperty(); break; case ConcreteSlotValueType.Matrix4: prop = new Matrix4ShaderProperty(); break; case ConcreteSlotValueType.SamplerState: prop = new SamplerStateShaderProperty(); break; case ConcreteSlotValueType.Gradient: prop = new GradientShaderProperty(); break; case ConcreteSlotValueType.VirtualTexture: prop = new VirtualTextureShaderProperty() { // also copy the VT settings over from the original property (if there is one) value = (fromProperty as VirtualTextureShaderProperty)?.value ?? new SerializableVirtualTexture() }; break; default: throw new ArgumentOutOfRangeException(); } prop.displayName = fromProperty != null ? fromProperty.displayName : fromSlot.concreteValueType.ToString(); prop.displayName = GraphUtil.SanitizeName(subGraph.addedInputs.Select(p => p.displayName), "{0} ({1})", prop.displayName); subGraph.AddGraphInput(prop); var propNode = new PropertyNode(); { var drawState = propNode.drawState; drawState.position = new Rect(new Vector2(bounds.xMin - 300f, 0f) + propPos, drawState.position.size); propPos += new Vector2(0, height); propNode.drawState = drawState; } subGraph.AddNode(propNode); propNode.property = prop; foreach (var edge in group.edges) { subGraph.Connect( new SlotReference(propNode, PropertyNode.OutputSlotId), edge.inputSlot); externalInputNeedingConnection.Add(new KeyValuePair <IEdge, AbstractShaderProperty>(edge, prop)); } } var uniqueOutgoingEdges = externalInputSlots.GroupBy( edge => edge.outputSlot, edge => edge, (key, edges) => new { slot = key, edges = edges.ToList() }); var externalOutputsNeedingConnection = new List <KeyValuePair <IEdge, IEdge> >(); foreach (var group in uniqueOutgoingEdges) { var outputNode = subGraph.outputNode as SubGraphOutputNode; AbstractMaterialNode node = group.edges[0].outputSlot.node; MaterialSlot slot = node.FindSlot <MaterialSlot>(group.edges[0].outputSlot.slotId); var slotId = outputNode.AddSlot(slot.concreteValueType); var inputSlotRef = new SlotReference(outputNode, slotId); foreach (var edge in group.edges) { var newEdge = subGraph.Connect(edge.outputSlot, inputSlotRef); externalOutputsNeedingConnection.Add(new KeyValuePair <IEdge, IEdge>(edge, newEdge)); } } if (FileUtilities.WriteShaderGraphToDisk(path, subGraph)) { AssetDatabase.ImportAsset(path); } // Store path for next time if (!pathToOriginSG.Equals(Path.GetDirectoryName(path))) { SessionState.SetString(k_PrevSubGraphPathKey, Path.GetDirectoryName(path)); } else { // Or continue to make it so that next time it will open up in the converted-from SG's directory SessionState.EraseString(k_PrevSubGraphPathKey); } var loadedSubGraph = AssetDatabase.LoadAssetAtPath(path, typeof(SubGraphAsset)) as SubGraphAsset; if (loadedSubGraph == null) { return; } var subGraphNode = new SubGraphNode(); var ds = subGraphNode.drawState; ds.position = new Rect(middle - new Vector2(100f, 150f), Vector2.zero); subGraphNode.drawState = ds; // Add the subgraph into the group if the nodes was all in the same group group var firstNode = copyPasteGraph.GetNodes <AbstractMaterialNode>().FirstOrDefault(); if (firstNode != null && copyPasteGraph.GetNodes <AbstractMaterialNode>().All(x => x.group == firstNode.group)) { subGraphNode.group = firstNode.group; } subGraphNode.asset = loadedSubGraph; graphObject.graph.AddNode(subGraphNode); foreach (var edgeMap in externalInputNeedingConnection) { graphObject.graph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode, edgeMap.Value.guid.GetHashCode())); } foreach (var edgeMap in externalOutputsNeedingConnection) { graphObject.graph.Connect(new SlotReference(subGraphNode, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot); } graphObject.graph.RemoveElements( graphView.selection.OfType <IShaderNodeView>().Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(), new IEdge[] {}, new GroupData[] {}, graphView.selection.OfType <StickyNote>().Select(x => x.userData).ToArray()); graphObject.graph.ValidateGraph(); }
public static void UpdateDragging() { if (draggingItem != null && PlayerInput.LeftButtonReleased()) { if (CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.OnItemDropped(draggingItem, false)) { draggingItem = null; return; } if (selectedSlot == null) { draggingItem.ParentInventory?.CreateNetworkEvent(); draggingItem.Drop(); GUI.PlayUISound(GUISoundType.DropItem); } else if (selectedSlot.ParentInventory.Items[selectedSlot.SlotIndex] != draggingItem) { Inventory selectedInventory = selectedSlot.ParentInventory; int slotIndex = selectedSlot.SlotIndex; if (selectedInventory.TryPutItem(draggingItem, slotIndex, true, true, Character.Controlled)) { if (selectedInventory.slots != null) { selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f); } GUI.PlayUISound(GUISoundType.PickItem); } else { if (selectedInventory.slots != null) { selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); } GUI.PlayUISound(GUISoundType.PickItemFail); } selectedInventory.HideTimer = 1.0f; if (selectedSlot.ParentInventory?.Owner is Item parentItem && parentItem.ParentInventory != null) { for (int i = 0; i < parentItem.ParentInventory.capacity; i++) { if (parentItem.ParentInventory.HideSlot(i)) { continue; } if (parentItem.ParentInventory.Items[i] != parentItem) { continue; } highlightedSubInventorySlots.Add(new SlotReference( parentItem.ParentInventory, parentItem.ParentInventory.slots[i], i, false, selectedSlot.ParentInventory)); break; } } draggingItem = null; draggingSlot = null; } draggingItem = null; } if (selectedSlot != null && !selectedSlot.Slot.MouseOn()) { selectedSlot = null; } }
protected void UpdateSlot(InventorySlot slot, int slotIndex, Item item, bool isSubSlot) { Rectangle interactRect = slot.InteractRect; interactRect.Location += slot.DrawOffset.ToPoint(); bool mouseOnGUI = false; /*if (GUI.MouseOn != null) * { * //block usage if the mouse is on a GUIComponent that's not related to this inventory * if (RectTransform == null || (RectTransform != GUI.MouseOn.RectTransform && !GUI.MouseOn.IsParentOf(RectTransform.GUIComponent))) * { * mouseOnGUI = true; * } * }*/ bool mouseOn = interactRect.Contains(PlayerInput.MousePosition) && !Locked && !mouseOnGUI; if (PlayerInput.LeftButtonHeld() && PlayerInput.RightButtonHeld()) { mouseOn = false; } if (selectedSlot != null && selectedSlot.Slot != slot) { //subinventory slot highlighted -> don't allow highlighting this one if (selectedSlot.IsSubSlot && !isSubSlot) { mouseOn = false; } else if (!selectedSlot.IsSubSlot && isSubSlot && mouseOn) { selectedSlot = null; } } slot.State = GUIComponent.ComponentState.None; if (mouseOn && (draggingItem != null || selectedSlot == null || selectedSlot.Slot == slot)) // && //(highlightedSubInventories.Count == 0 || highlightedSubInventories.Contains(this) || highlightedSubInventorySlot?.Slot == slot || highlightedSubInventory.Owner == item)) { slot.State = GUIComponent.ComponentState.Hover; if (selectedSlot == null || (!selectedSlot.IsSubSlot && isSubSlot)) { selectedSlot = new SlotReference(this, slot, slotIndex, isSubSlot, Items[slotIndex]?.GetComponent <ItemContainer>()?.Inventory); } if (draggingItem == null) { if (PlayerInput.LeftButtonDown()) { draggingItem = Items[slotIndex]; draggingSlot = slot; } } else if (PlayerInput.LeftButtonReleased()) { if (PlayerInput.DoubleClicked()) { doubleClickedItem = item; } } } }
public bool FindPort(SlotReference slot, out ShaderPort port) { port = contentContainer.Q("top")?.Query <ShaderPort>().Where(p => p.slot.slotReference.Equals(slot)).First(); return(port != null); }
public bool FindPort(SlotReference slot, out ShaderPort port) { port = output as ShaderPort; return(port != null && port.slot.slotReference.Equals(slot)); }