void ApplyShadows(ref ScriptableRenderContext context, ref CullingResults cullingResults) { if (shadowData == null || shadowData.lights == null || shadowData.shadowMaps == null) { return; } ShaderInput.SetShadowMaps(buffer, shadowData.shadowMaps); worldToShadowMatricesBuffer = CreateBuffer(worldToShadowMatrices); ShaderInput.SetWorldToShadowMatrices(buffer, worldToShadowMatricesBuffer); cascadeDataBuffer = CreateBuffer(cascadeData); ShaderInput.SetCascadeData(buffer, cascadeDataBuffer); cullingSpheresBuffer = CreateBuffer(cullingSpheres); ShaderInput.SetCullingSpheres(buffer, cullingSpheresBuffer); shadowSettingsBuffer = CreateBuffer(shadowSettings); ShaderInput.SetShadowSettings(buffer, shadowSettingsBuffer); ShaderInput.SetHardShadows(buffer, hasShadowsHard); ShaderInput.SetSoftShadows(buffer, hasShadowsSoft); SubmitBuffer(ref context, buffer); }
void RenderSpotShadow(ref ScriptableRenderContext context, ref CullingResults cullingResults, int shadowMapSize, int index, ref VisibleLight visibleLight) { if (shadowData.lights[index] == null) { return; } CoreUtils.SetRenderTarget(buffer, shadowData.shadowMaps, ClearFlag.Depth, 0, CubemapFace.Unknown, index); SubmitBuffer(ref context, buffer); if (shadowData.lights[index].cascades[0] == null) { return; } Rect tileViewport = new Rect(0, 0, shadowMapSize, shadowMapSize); buffer.SetViewport(new Rect(tileViewport)); buffer.SetViewProjectionMatrices(shadowData.lights[index].cascades[0].viewMatrix, shadowData.lights[index].cascades[0].projectionMatrix); ShaderInput.SetShadowBias(buffer, visibleLight.light.shadowBias); SubmitBuffer(ref context, buffer); ShadowDrawingSettings shadowSettings = new ShadowDrawingSettings(cullingResults, index); shadowSettings.splitData = shadowData.lights[index].cascades[0].splitData; context.DrawShadows(ref shadowSettings); }
void RenderDirectionalShadow(ref ScriptableRenderContext context, ref CullingResults cullingResults, int shadowMapSize, int index, ref VisibleLight visibleLight) { if (shadowData.lights[index] == null) { return; } CoreUtils.SetRenderTarget(buffer, shadowData.shadowMaps, ClearFlag.Depth, 0, CubemapFace.Unknown, index); SubmitBuffer(ref context, buffer); for (int j = 0; j < 4; j++) { if (shadowData.lights[index].cascades[j] == null) { continue; } Rect tileViewport = new Rect(shadowData.lights[index].cascades[j].tileOffset.x * shadowData.lights[index].tileSize, shadowData.lights[index].cascades[j].tileOffset.y * shadowData.lights[index].tileSize, shadowData.lights[index].tileSize, shadowData.lights[index].tileSize); buffer.SetViewport(new Rect(tileViewport)); buffer.EnableScissorRect(new Rect(tileViewport.x + 4f, tileViewport.y + 4f, shadowData.lights[index].tileSize - 8f, shadowData.lights[index].tileSize - 8f)); buffer.SetViewProjectionMatrices(shadowData.lights[index].cascades[j].viewMatrix, shadowData.lights[index].cascades[j].projectionMatrix); ShaderInput.SetShadowBias(buffer, visibleLight.light.shadowBias); SubmitBuffer(ref context, buffer); ShadowDrawingSettings shadowSettings = new ShadowDrawingSettings(cullingResults, index); shadowSettings.splitData = shadowData.lights[index].cascades[j].splitData; context.DrawShadows(ref shadowSettings); } buffer.DisableScissorRect(); SubmitBuffer(ref context, buffer); }
void OnMouseHover(EventBase evt, ShaderInput input) { var graphView = blackboard.GetFirstAncestorOfType <MaterialGraphView>(); if (evt.eventTypeId == MouseEnterEvent.TypeId()) { foreach (var node in graphView.nodes.ToList()) { if (input is AbstractShaderProperty property) { if (node.userData is PropertyNode propertyNode) { if (propertyNode.propertyGuid == input.guid) { m_SelectedNodes.Add(node); node.AddToClassList("hovered"); } } } } } else if (evt.eventTypeId == MouseLeaveEvent.TypeId() && m_SelectedNodes.Any()) { foreach (var node in m_SelectedNodes) { node.RemoveFromClassList("hovered"); } m_SelectedNodes.Clear(); } }
void BuildKeywordFields(PropertySheet propertySheet, ShaderInput shaderInput) { var keyword = shaderInput as ShaderKeyword; if (keyword == null) { return; } var enumPropertyDrawer = new EnumPropertyDrawer(); propertySheet.Add(enumPropertyDrawer.CreateGUI( newValue => { this._preChangeValueCallback("Change Keyword type"); if (keyword.keywordDefinition == (KeywordDefinition)newValue) { return; } keyword.keywordDefinition = (KeywordDefinition)newValue; }, keyword.keywordDefinition, "Definition", KeywordDefinition.ShaderFeature, out var typeField)); typeField.SetEnabled(!keyword.isBuiltIn); if (keyword.keywordDefinition != KeywordDefinition.Predefined) { propertySheet.Add(enumPropertyDrawer.CreateGUI( newValue => { this._preChangeValueCallback("Change Keyword scope"); if (keyword.keywordScope == (KeywordScope)newValue) { return; } keyword.keywordScope = (KeywordScope)newValue; }, keyword.keywordScope, "Scope", KeywordScope.Local, out var scopeField)); scopeField.SetEnabled(!keyword.isBuiltIn); } switch (keyword.keywordType) { case KeywordType.Boolean: BuildBooleanKeywordField(propertySheet, keyword); break; case KeywordType.Enum: BuildEnumKeywordField(propertySheet, keyword); break; } }
public BlackboardFieldView(GraphData graph, ShaderInput input, BlackBoardCallback updateBlackboardView, Texture icon, string text, string typeText) : base(icon, text, typeText) { styleSheets.Add(Resources.Load <StyleSheet>("Styles/ShaderGraphBlackboard")); m_Graph = graph; m_Input = input; this.BlackBoardUpdateTrigger = updateBlackboardView; }
protected virtual AbstractMaterialNode CreateNodeForShaderInput(ShaderInput shaderInput, ShaderGraphBuilder builder, U unrealNode) { var graphNode = builder.CreateNode <PropertyNode>(); graphNode.propertyGuid = shaderInput.guid; return(graphNode); }
protected override AbstractMaterialNode CreateNodeForShaderInput(ShaderInput shaderInput, ShaderGraphBuilder builder, MaterialExpressionStaticSwitchParameter unrealNode) { var propertyNode = base.CreateNodeForShaderInput(shaderInput, builder, unrealNode); var branchNode = builder.CreateNode <BranchNode>(); builder.PositionNodeOnGraph(propertyNode, unrealNode); builder.Connect(propertyNode.GetSlotReference(0), branchNode.GetSlotReference(0)); return(branchNode); }
void BuildDefaultFields(ShaderInput input) { if (!m_Graph.isSubGraph) { m_ExposedToogle = new Toggle(); m_ExposedToogle.OnToggleChanged(evt => { m_Graph.owner.RegisterCompleteObjectUndo("Change Exposed Toggle"); input.generatePropertyBlock = evt.newValue; m_BlackboardField.icon = input.generatePropertyBlock ? BlackboardProvider.exposedIcon : null; Rebuild(); DirtyNodes(ModificationScope.Graph); }); m_ExposedToogle.value = input.generatePropertyBlock; AddRow("Exposed", m_ExposedToogle, input.isExposable); } if (!m_Graph.isSubGraph || input is ShaderKeyword) { m_ReferenceNameField = new TextField(512, false, false, ' ') { isDelayed = true }; m_ReferenceNameField.styleSheets.Add(Resources.Load <StyleSheet>("Styles/PropertyNameReferenceField")); m_ReferenceNameField.value = input.referenceName; m_ReferenceNameField.RegisterValueChangedCallback(evt => { m_Graph.owner.RegisterCompleteObjectUndo("Change Reference Name"); if (m_ReferenceNameField.value != m_Input.referenceName) { m_Graph.SanitizeGraphInputReferenceName(input, evt.newValue); } m_ReferenceNameField.value = input.referenceName; if (string.IsNullOrEmpty(input.overrideReferenceName)) { m_ReferenceNameField.RemoveFromClassList("modified"); } else { m_ReferenceNameField.AddToClassList("modified"); } Rebuild(); DirtyNodes(ModificationScope.Graph); UpdateReferenceNameResetMenu(); }); if (!string.IsNullOrEmpty(input.overrideReferenceName)) { m_ReferenceNameField.AddToClassList("modified"); } AddRow("Reference", m_ReferenceNameField, input.isRenamable); } }
public BlackboardRow GetBlackboardRow(ShaderInput input) { if (m_InputRows.ContainsKey(input)) { return(m_InputRows[input]); } else { return(null); } }
public override void BuildCustomFields(ShaderInput input) { m_Keyword = input as ShaderKeyword; if (m_Keyword == null) { return; } // KeywordDefinition var keywordDefinitionField = new EnumField((Enum)m_Keyword.keywordDefinition); keywordDefinitionField.RegisterValueChangedCallback(evt => { graph.owner.RegisterCompleteObjectUndo("Change Keyword Type"); if (m_Keyword.keywordDefinition == (KeywordDefinition)evt.newValue) { return; } m_Keyword.keywordDefinition = (KeywordDefinition)evt.newValue; Rebuild(); }); AddRow("Definition", keywordDefinitionField, m_Keyword.isEditable); // KeywordScope if (m_Keyword.keywordDefinition != KeywordDefinition.Predefined) { var keywordScopeField = new EnumField((Enum)m_Keyword.keywordScope); keywordScopeField.RegisterValueChangedCallback(evt => { graph.owner.RegisterCompleteObjectUndo("Change Keyword Type"); if (m_Keyword.keywordScope == (KeywordScope)evt.newValue) { return; } m_Keyword.keywordScope = (KeywordScope)evt.newValue; }); AddRow("Scope", keywordScopeField, m_Keyword.isEditable); } switch (m_Keyword.keywordType) { case KeywordType.Boolean: BuildBooleanKeywordField(m_Keyword); break; case KeywordType.Enum: BuildEnumKeywordField(m_Keyword); break; default: throw new ArgumentOutOfRangeException(); } }
public BlackboardFieldView(GraphData graph, ShaderInput input, BlackBoardCallback updateBlackboardView, Texture icon, string text, string typeText) : base(icon, text, typeText) { styleSheets.Add(Resources.Load <StyleSheet>("Styles/ShaderGraphBlackboard")); m_Graph = graph; m_Input = input; this.BlackBoardUpdateTrigger = updateBlackboardView; this.name = "blackboardFieldView"; ShaderGraphPreferences.onAllowDeprecatedChanged += UpdateTypeText; UpdateRightClickMenu(); }
protected override AbstractMaterialNode CreateNodeForShaderInput(ShaderInput shaderInput, ShaderGraphBuilder builder, MaterialExpressionTextureSampleParameter2D unrealNode) { var propertyNode = base.CreateNodeForShaderInput(shaderInput, builder, unrealNode); var sampleNode = builder.CreateNode <SampleTexture2DNode>(); sampleNode.textureType = TextureType.Default; builder.PositionNodeOnGraph(propertyNode, unrealNode); builder.Connect(propertyNode.GetSlotReference(PropertyNode.OutputSlotId), sampleNode.GetSlotReference(SampleTexture2DNode.TextureInputId)); return(sampleNode); }
public VisualElement DrawProperty( PropertyInfo propertyInfo, object actualObject, InspectableAttribute attribute) { var propertySheet = new PropertySheet(); shaderInput = actualObject as ShaderInput; BuildExposedField(propertySheet); BuildReferenceNameField(propertySheet); BuildPropertyFields(propertySheet); BuildKeywordFields(propertySheet, shaderInput); return(propertySheet); }
public BlackboardFieldView(GraphData graph, ShaderInput input, Texture icon, string text, string typeText) : base(icon, text, typeText) { styleSheets.Add(Resources.Load <StyleSheet>("Styles/ShaderGraphBlackboard")); m_Graph = graph; m_Input = input; this.name = "blackboardFieldView"; ShaderGraphPreferences.onAllowDeprecatedChanged += UpdateTypeText; // add the right click context menu IManipulator contextMenuManipulator = new ContextualMenuManipulator(AddContextMenuOptions); this.AddManipulator(contextMenuManipulator); var nameTextField = this.Q("textField") as TextField; var textinput = nameTextField.Q(TextField.textInputUssName); // When a display name is changed through the BlackboardPill, this callback handle it textinput.RegisterCallback <FocusOutEvent>(e => { this.RegisterPropertyChangeUndo("Change Display Name"); if (nameTextField.text != m_Input.displayName) { m_Input.SetDisplayNameAndSanitizeForGraph(m_Graph, nameTextField.text); } // This gets triggered on property creation so need to check for inspector update trigger being valid (which it might not be at the time) if (this.m_inspectorUpdateTrigger != null) { this.MarkNodesAsDirty(true, ModificationScope.Topological); } else { DirtyNodes(ModificationScope.Topological); } }); m_NameLabelField = this.Q("title-label") as Label; // Set callback association for display name updates m_Input.displayNameUpdateTrigger += UpdateDisplayNameText; }
public BlackboardFieldView(BlackboardField blackboardField, GraphData graph, ShaderInput input) { styleSheets.Add(Resources.Load <StyleSheet>("Styles/ShaderGraphBlackboard")); m_BlackboardField = blackboardField; m_Graph = graph; m_Input = input; m_Rows = new List <VisualElement>(); m_KeyDownCallback = new EventCallback <KeyDownEvent>(evt => { // Record Undo for input field edit if (m_UndoGroup == -1) { m_UndoGroup = Undo.GetCurrentGroup(); graph.owner.RegisterCompleteObjectUndo("Change property value"); } // Handle scaping input field edit if (evt.keyCode == KeyCode.Escape && m_UndoGroup > -1) { Undo.RevertAllDownToGroup(m_UndoGroup); m_UndoGroup = -1; evt.StopPropagation(); } // Dont record Undo again until input field is unfocused m_UndoGroup++; this.MarkDirtyRepaint(); }); m_FocusOutCallback = new EventCallback <FocusOutEvent>(evt => { // Reset UndoGroup when done editing input field m_UndoGroup = -1; }); BuildDefaultFields(input); BuildCustomFields(input); AddToClassList("sgblackboardFieldView"); }
void AddPropertyItems(GenericMenu gm) { var shaderInputTypes = TypeCache.GetTypesWithAttribute <BlackboardInputInfo>().ToList(); // Sort the ShaderInput by priority using the BlackboardInputInfo attribute shaderInputTypes.Sort((s1, s2) => { var info1 = Attribute.GetCustomAttribute(s1, typeof(BlackboardInputInfo)) as BlackboardInputInfo; var info2 = Attribute.GetCustomAttribute(s2, typeof(BlackboardInputInfo)) as BlackboardInputInfo; if (info1.priority == info2.priority) { return((info1.name ?? s1.Name).CompareTo(info2.name ?? s2.Name)); } else { return(info1.priority.CompareTo(info2.priority)); } }); foreach (var t in shaderInputTypes) { if (t.IsAbstract) { continue; } var info = Attribute.GetCustomAttribute(t, typeof(BlackboardInputInfo)) as BlackboardInputInfo; string name = info?.name ?? ObjectNames.NicifyVariableName(t.Name.Replace("ShaderProperty", "")); ShaderInput si = Activator.CreateInstance(t, true) as ShaderInput; gm.AddItem(new GUIContent(name), false, () => AddInputRow(si, true)); //QUICK FIX TO DEAL WITH DEPRECATED COLOR PROPERTY if (ShaderGraphPreferences.allowDeprecatedBehaviors && si is ColorShaderProperty csp) { gm.AddItem(new GUIContent($"Color (Deprecated)"), false, () => AddInputRow(new ColorShaderProperty(ColorShaderProperty.deprecatedVersion), true)); } } gm.AddSeparator($"/"); }
void ApplyLights(ref ScriptableRenderContext context, ref CullingResults cullingResults) { colorsBuffer = CreateBuffer(colors); ShaderInput.SetLightsColors(buffer, colorsBuffer); positionsBuffer = CreateBuffer(positions); ShaderInput.SetLightsPositions(buffer, positionsBuffer); spotDirectionsBuffer = CreateBuffer(spotDirections); ShaderInput.SetLightsSpotDirections(buffer, spotDirectionsBuffer); attenuationsBuffer = CreateBuffer(attenuations); ShaderInput.SetLightsAttenuations(buffer, attenuationsBuffer); if (cullingResults.lightAndReflectionProbeIndexCount >= 1) { lightIndicesBuffer = new ComputeBuffer(cullingResults.lightAndReflectionProbeIndexCount, 4); cullingResults.FillLightAndReflectionProbeIndices(lightIndicesBuffer); ShaderInput.SetLightIndices(buffer, lightIndicesBuffer); } SubmitBuffer(ref context, buffer); }
void OnExpanded(MouseDownEvent evt, ShaderInput input) { m_ExpandedInputs[input] = !m_InputRows[input.guid].expanded; }
void AddInputRow(ShaderInput input, bool create = false, int index = -1) { if (m_InputRows.ContainsKey(input.guid)) { return; } if (create) { m_Graph.SanitizeGraphInputName(input); } if (index < 0) { index = m_InputRows.Count; } BlackboardField field = null; BlackboardRow row = null; switch (input) { case AbstractShaderProperty property: { var icon = (m_Graph.isSubGraph || (property.isExposable && property.generatePropertyBlock)) ? exposedIcon : null; field = new BlackboardField(icon, property.displayName, property.propertyType.ToString()) { userData = property }; var propertyView = new BlackboardFieldPropertyView(field, m_Graph, property); row = new BlackboardRow(field, propertyView) { userData = input }; if (index == m_PropertySection.childCount) { m_PropertySection.Add(row); } else { m_PropertySection.Insert(index, row); } break; } default: throw new ArgumentOutOfRangeException(); } if (field == null || row == null) { return; } var pill = row.Q <Pill>(); pill.RegisterCallback <MouseEnterEvent>(evt => OnMouseHover(evt, input)); pill.RegisterCallback <MouseLeaveEvent>(evt => OnMouseHover(evt, input)); pill.RegisterCallback <DragUpdatedEvent>(OnDragUpdatedEvent); var expandButton = row.Q <Button>("expandButton"); expandButton.RegisterCallback <MouseDownEvent>(evt => OnExpanded(evt, input), TrickleDown.TrickleDown); m_InputRows[input.guid] = row; m_InputRows[input.guid].expanded = SessionState.GetBool(input.guid.ToString(), true); if (create) { row.expanded = true; m_Graph.owner.RegisterCompleteObjectUndo("Create Graph Input"); m_Graph.AddGraphInput(input); field.OpenTextEditor(); } }
void AddInputRow(ShaderInput input, bool addToGraph = false, int index = -1) { if (m_InputRows.ContainsKey(input)) { return; } if (addToGraph) { m_Graph.owner.RegisterCompleteObjectUndo("Create Graph Input"); // this pathway is mostly used for adding newly inputs to the graph // so this is setting up the default state for those inputs // here we flag it exposed, if the input type is exposable input.generatePropertyBlock = input.isExposable; m_Graph.AddGraphInput(input); // TODO: index after currently selected property } BlackboardFieldView field = null; BlackboardRow row = null; switch (input) { case AbstractShaderProperty property: { var icon = (m_Graph.isSubGraph || property.isExposed) ? exposedIcon : null; field = new BlackboardFieldView(m_Graph, property, icon, property.displayName, property.GetPropertyTypeString()) { userData = property }; field.RegisterCallback <AttachToPanelEvent>(UpdateSelectionAfterUndoRedo); property.onBeforeVersionChange += (_) => m_Graph.owner.RegisterCompleteObjectUndo($"Change {property.displayName} Version"); void UpdateField() { field.typeText = property.GetPropertyTypeString(); field.InspectorUpdateTrigger(); } property.onAfterVersionChange += UpdateField; row = new BlackboardRow(field, null); if (index < 0 || index > m_InputRows.Count) { index = m_InputRows.Count; } if (index == m_InputRows.Count) { m_PropertySection.Add(row); } else { m_PropertySection.Insert(index, row); } break; } case ShaderKeyword keyword: { var icon = (m_Graph.isSubGraph || keyword.isExposed) ? exposedIcon : null; string typeText = keyword.keywordType.ToString() + " Keyword"; typeText = keyword.isBuiltIn ? "Built-in " + typeText : typeText; field = new BlackboardFieldView(m_Graph, keyword, icon, keyword.displayName, typeText) { userData = keyword }; field.RegisterCallback <AttachToPanelEvent>(UpdateSelectionAfterUndoRedo); row = new BlackboardRow(field, null); if (index < 0 || index > m_InputRows.Count) { index = m_InputRows.Count; } if (index == m_InputRows.Count) { m_KeywordSection.Add(row); } else { m_KeywordSection.Insert(index, row); } break; } default: throw new ArgumentOutOfRangeException(); } field.RegisterCallback <MouseEnterEvent>(evt => OnMouseHover(evt, input)); field.RegisterCallback <MouseLeaveEvent>(evt => OnMouseHover(evt, input)); field.RegisterCallback <DragUpdatedEvent>(OnDragUpdatedEvent); // These callbacks are used for the property dragging scroll behavior field.RegisterCallback <DragEnterEvent>(evt => blackboard.ShowScrollBoundaryRegions()); field.RegisterCallback <DragExitedEvent>(evt => blackboard.HideScrollBoundaryRegions()); // Removing the expand button from the blackboard, its added by default var expandButton = row.Q <Button>("expandButton"); expandButton.RemoveFromHierarchy(); m_InputRows[input] = row; if (!addToGraph) { m_InputRows[input].expanded = SessionState.GetBool($"Unity.ShaderGraph.Input.{input.objectId}.isExpanded", false); } else { row.expanded = true; field.OpenTextEditor(); if (input as ShaderKeyword != null) { m_Graph.OnKeywordChangedNoValidate(); } } }
public abstract void BuildCustomFields(ShaderInput input);
public BlackboardFieldKeywordView(BlackboardField blackboardField, GraphData graph, ShaderInput input) : base(blackboardField, graph, input) { }
public BlackboardRow GetBlackboardRow(ShaderInput input) { return(m_InputRows[input]); }
void AddInputRow(ShaderInput input, bool create = false, int index = -1) { if (m_InputRows.ContainsKey(input)) { return; } if (create) { m_Graph.SanitizeGraphInputName(input); input.generatePropertyBlock = input.isExposable; } BlackboardFieldView field = null; BlackboardRow row = null; switch (input) { case AbstractShaderProperty property: { var icon = (m_Graph.isSubGraph || (property.isExposable && property.generatePropertyBlock)) ? exposedIcon : null; field = new BlackboardFieldView(m_Graph, property, UpdateBlackboardView, icon, property.displayName, property.GetPropertyTypeString()) { userData = property }; field.RegisterCallback <AttachToPanelEvent>(UpdateSelectionAfterUndoRedo); property.onBeforeVersionChange += (_) => m_Graph.owner.RegisterCompleteObjectUndo($"Change {property.displayName} Version"); void UpdateField() { field.typeText = property.GetPropertyTypeString(); field.InspectorUpdateTrigger(); } property.onAfterVersionChange += UpdateField; row = new BlackboardRow(field, null); if (index < 0 || index > m_InputRows.Count) { index = m_InputRows.Count; } if (index == m_InputRows.Count) { m_PropertySection.Add(row); } else { m_PropertySection.Insert(index, row); } break; } case ShaderKeyword keyword: { var icon = (m_Graph.isSubGraph || (keyword.isExposable && keyword.generatePropertyBlock)) ? exposedIcon : null; string typeText = keyword.keywordType.ToString() + " Keyword"; typeText = keyword.isBuiltIn ? "Built-in " + typeText : typeText; field = new BlackboardFieldView(m_Graph, keyword, UpdateBlackboardView, icon, keyword.displayName, typeText) { userData = keyword }; field.RegisterCallback <AttachToPanelEvent>(UpdateSelectionAfterUndoRedo); row = new BlackboardRow(field, null); if (index < 0 || index > m_InputRows.Count) { index = m_InputRows.Count; } if (index == m_InputRows.Count) { m_KeywordSection.Add(row); } else { m_KeywordSection.Insert(index, row); } break; } default: throw new ArgumentOutOfRangeException(); } field.RegisterCallback <MouseEnterEvent>(evt => OnMouseHover(evt, input)); field.RegisterCallback <MouseLeaveEvent>(evt => OnMouseHover(evt, input)); field.RegisterCallback <DragUpdatedEvent>(OnDragUpdatedEvent); // Removing the expand button from the blackboard, its added by default var expandButton = row.Q <Button>("expandButton"); expandButton.RemoveFromHierarchy(); m_InputRows[input] = row; if (!create) { m_InputRows[input].expanded = SessionState.GetBool($"Unity.ShaderGraph.Input.{input.objectId}.isExpanded", false); } else { row.expanded = true; m_Graph.owner.RegisterCompleteObjectUndo("Create Graph Input"); m_Graph.AddGraphInput(input); field.OpenTextEditor(); if (input as ShaderKeyword != null) { m_Graph.OnKeywordChangedNoValidate(); } } }
public void Load (string S){ S = ShaderUtil.Sanitize(S); string[] parts = S.Split(new string[] { "#^" }, StringSplitOptions.None); // Debug.Log(parts[0]); if (CType == Types.Vec) Vector.Load(parts[0]); if (CType == Types.Float) float.TryParse(parts[0],out Float); if (CType == Types.Type) Type = int.Parse(parts[0]); if (CType == Types.Toggle) On = bool.Parse(parts[0]); if (CType == Types.Text) Text = parts[0]; if (CType == Types.Texture){ ImageGUID = parts[0]; Image = (Texture2D)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(ImageGUID),typeof(Texture2D)); } if (CType == Types.Cubemap){ CubeGUID = parts[0]; Cube = (Cubemap)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(CubeGUID),typeof(Cubemap)); } //int ExpectedLength = 2; if (CType == Types.ObjectArray){ Selected = int.Parse(parts[0]); } if (parts.Length>1){ if (parts[1].Trim()!="AUTO"&&!parts[1].Trim().StartsWith("CC")){ if (ShaderBase.Current.ShaderInputs.Count>int.Parse(parts[1].Trim())) Input = ShaderBase.Current.ShaderInputs[int.Parse(parts[1].Trim())]; } //Debug.Log(parts[1].Trim()); if (parts[1].Trim().StartsWith("CC")){ ColorComponent = int.Parse(parts[1].Trim().Replace("CC","")); } } if (parts.Length==3){ if (parts[2].Trim()!="AUTO"&&!parts[2].Trim().StartsWith("CC")){ if (ShaderBase.Current.ShaderInputs.Count>int.Parse(parts[2].Trim())) Input = ShaderBase.Current.ShaderInputs[int.Parse(parts[2].Trim())]; } } UpdateToInput(); }
public void AddInput(ShaderInput input) { m_Inputs.Add(input); }
internal static void InsertCopyPasteGraph(this MaterialGraphView graphView, CopyPasteGraph copyGraph) { if (copyGraph == null) { return; } // Keywords need to be tested against variant limit based on multiple factors bool keywordsDirty = false; // Make new inputs from the copied graph foreach (ShaderInput input in copyGraph.inputs) { ShaderInput copiedInput = input.Copy(); graphView.graph.SanitizeGraphInputName(copiedInput); graphView.graph.SanitizeGraphInputReferenceName(copiedInput, input.overrideReferenceName); graphView.graph.AddGraphInput(copiedInput); switch (input) { case AbstractShaderProperty property: // Update the property nodes that depends on the copied node var dependentPropertyNodes = copyGraph.GetNodes <PropertyNode>().Where(x => x.propertyGuid == input.guid); foreach (var node in dependentPropertyNodes) { node.owner = graphView.graph; node.propertyGuid = copiedInput.guid; } break; case ShaderKeyword shaderKeyword: // Update the keyword nodes that depends on the copied node var dependentKeywordNodes = copyGraph.GetNodes <KeywordNode>().Where(x => x.keywordGuid == input.guid); foreach (var node in dependentKeywordNodes) { node.owner = graphView.graph; node.keywordGuid = copiedInput.guid; } // Pasting a new Keyword so need to test against variant limit keywordsDirty = true; break; default: throw new ArgumentOutOfRangeException(); } } // Pasting a Sub Graph node that contains Keywords so need to test against variant limit foreach (SubGraphNode subGraphNode in copyGraph.GetNodes <SubGraphNode>()) { if (subGraphNode.asset.keywords.Count > 0) { keywordsDirty = true; } } // Test Keywords against variant limit if (keywordsDirty) { graphView.graph.OnKeywordChangedNoValidate(); } using (var remappedNodesDisposable = ListPool <AbstractMaterialNode> .GetDisposable()) { using (var remappedEdgesDisposable = ListPool <IEdge> .GetDisposable()) { var remappedNodes = remappedNodesDisposable.value; var remappedEdges = remappedEdgesDisposable.value; graphView.graph.PasteGraph(copyGraph, remappedNodes, remappedEdges); if (graphView.graph.assetGuid != copyGraph.sourceGraphGuid) { // Compute the mean of the copied nodes. Vector2 centroid = Vector2.zero; var count = 1; foreach (var node in remappedNodes) { var position = node.drawState.position.position; centroid = centroid + (position - centroid) / count; ++count; } // Get the center of the current view var viewCenter = graphView.contentViewContainer.WorldToLocal(graphView.layout.center); foreach (var node in remappedNodes) { var drawState = node.drawState; var positionRect = drawState.position; var position = positionRect.position; position += viewCenter - centroid; positionRect.position = position; drawState.position = positionRect; node.drawState = drawState; } } // Add new elements to selection graphView.ClearSelection(); graphView.graphElements.ForEach(element => { if (element is Edge edge && remappedEdges.Contains(edge.userData as IEdge)) { graphView.AddToSelection(edge); } if (element is IShaderNodeView nodeView && remappedNodes.Contains(nodeView.node)) { graphView.AddToSelection((Node)nodeView); } }); } } }
public override void BuildCustomFields(ShaderInput input) { AbstractShaderProperty property = input as AbstractShaderProperty; if (property == null) { return; } switch (input) { case Vector1ShaderProperty vector1Property: BuildVector1PropertyField(vector1Property); break; case Vector2ShaderProperty vector2Property: BuildVector2PropertyField(vector2Property); break; case Vector3ShaderProperty vector3Property: BuildVector3PropertyField(vector3Property); break; case Vector4ShaderProperty vector4Property: BuildVector4PropertyField(vector4Property); break; case ColorShaderProperty colorProperty: BuildColorPropertyField(colorProperty); break; case TextureShaderProperty texture2DProperty: BuildTexture2DPropertyField(texture2DProperty); break; case Texture2DArrayShaderProperty texture2DArrayProperty: BuildTexture2DArrayPropertyField(texture2DArrayProperty); break; case Texture3DShaderProperty texture3DProperty: BuildTexture3DPropertyField(texture3DProperty); break; case CubemapShaderProperty cubemapProperty: BuildCubemapPropertyField(cubemapProperty); break; case BooleanShaderProperty booleanProperty: BuildBooleanPropertyField(booleanProperty); break; case Matrix2ShaderProperty matrix2Property: BuildMatrix2PropertyField(matrix2Property); break; case Matrix3ShaderProperty matrix3Property: BuildMatrix3PropertyField(matrix3Property); break; case Matrix4ShaderProperty matrix4Property: BuildMatrix4PropertyField(matrix4Property); break; case SamplerStateShaderProperty samplerStateProperty: BuildSamplerStatePropertyField(samplerStateProperty); break; case GradientShaderProperty gradientProperty: BuildGradientPropertyField(gradientProperty); break; default: throw new ArgumentOutOfRangeException(); } // Precision var precisionField = new EnumField((Enum)property.precision); precisionField.RegisterValueChangedCallback(evt => { graph.owner.RegisterCompleteObjectUndo("Change Precision"); if (property.precision == (Precision)evt.newValue) { return; } property.precision = (Precision)evt.newValue; graph.ValidateGraph(); precisionField.MarkDirtyRepaint(); DirtyNodes(); }); AddRow("Precision", precisionField); }
public void UseEditingMouse(bool Paint){ Rect rect = LastUsedRect; rect.x-=150-LabelOffset; ShaderInput OrigInput = Input; int OrigComponent = ColorComponent; if (EditingPopup>0f){ if ((Event.current.type == EventType.MouseDown) &&( //!(new Rect(rect.x+110,rect.y,20,20).Contains(Event.current.mousePosition))&& !(new Rect(rect.x+110,rect.y-(20*EditingPopup)-20,110,40).Contains(Event.current.mousePosition)) )){ ShaderSandwich.ShaderVarEditing = null; GUI.changed = true; } if (Paint==true){ if (EditingPopup>0f){ //Debug.Log(rect); GUI.color = new Color(GUI.color.r,GUI.color.g,GUI.color.b,EditingPopup); ShaderUtil.BeginGroup(new Rect(rect.x+110,rect.y-(20*EditingPopup)-20,120,40),GUI.skin.button); GUIStyle ButtonStyle = new GUIStyle(GUI.skin.button); ButtonStyle.padding = new RectOffset(0,0,0,0); ButtonStyle.margin = new RectOffset(0,0,0,0); List<string> InputNamesList = new List<string>(); List<int> InputIntsList = new List<int>(); List<ShaderInput> InputInputsList = new List<ShaderInput>(); List<int> InputComponentsList = new List<int>(); InputNamesList.Add("-"); InputIntsList.Add(0); InputInputsList.Add(null); InputComponentsList.Add(0); int ii = 1; foreach(ShaderInput SI in ShaderBase.Current.ShaderInputs){ string SIType = ""; if (SI.Type==0) SIType = "Tex"; if (SI.Type==1) SIType = "Color"; if (SI.Type==2) SIType = "Cube"; if (SI.Type==3) SIType = "Float"; if (SI.Type==4) SIType = "Range"; if ( (CType == Types.Float&&(SI.Type==3||SI.Type==4||SI.Type==1))|| (CType == Types.Vec&&SI.Type==1)|| (CType == Types.Texture&&SI.Type==0)|| (CType == Types.Cubemap&&SI.Type==2) ){ if (CType == Types.Float&&SI.Type==1){ InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")+"/R"); InputIntsList.Add(ii); InputInputsList.Add(SI); InputComponentsList.Add(0); ii++; InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")+"/G"); InputIntsList.Add(ii); InputInputsList.Add(SI); InputComponentsList.Add(1); ii++; InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")+"/B"); InputIntsList.Add(ii); InputInputsList.Add(SI); InputComponentsList.Add(2); ii++; InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")+"/A"); InputIntsList.Add(ii); InputInputsList.Add(SI); InputComponentsList.Add(3); ii++; } else{ InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")); InputIntsList.Add(ii); InputInputsList.Add(SI); InputComponentsList.Add(0); ii++; } } } string[] InputNames = InputNamesList.ToArray(); int[] InputInts = InputIntsList.ToArray(); //InputNames[ii] = "Add New Input"; int IndexOfInput = 0; if (InputInputsList.IndexOf(Input)!=-1) IndexOfInput = InputInputsList.IndexOf(Input)+ColorComponent; //IndexOfInput = ShaderBase.Current.ShaderInputs.IndexOf(Input)+1+ColorComponent; //Debug.Log(IndexOfInput); SU.Label(new Rect(5,5,110,15),"Inputs:",11); //IndexOfInput = 5; //int SIS = InputInts[EditorGUI.Popup(new Rect(5,20,75,15), Array.IndexOf(InputInts,IndexOfInput), InputNames,GUI.skin.GetStyle("MiniPopup"))]; //IntInput = EditorGUI.Popup(new Rect(5,20,75,15),IntInput, InputNames,GUI.skin.GetStyle("MiniPopup")); //int SIS = IntInput; int SIS = EditorGUI.IntPopup(new Rect(5,20,75,15), IndexOfInput, InputNames,InputInts,GUI.skin.GetStyle("MiniPopup")); if (SIS>=InputInputsList.Count) SIS = 0; if (SIS==0) Input = null; else{ Input = InputInputsList[SIS]; ColorComponent = InputComponentsList[SIS]; } //Debug.Log(SIS); //Debug.Log(ColorComponent); //Input = ShaderBase.Current.ShaderInputs[SIS-1]; if (GUI.Button(new Rect(80,20,15,15),ShaderSandwich.Plus,ButtonStyle)||ShaderUtil.MouseUpIn(new Rect(80,20,15,15))){ AddInput(); ShaderSandwich.ShaderVarEditing = null; ShaderSandwich.ValueChanged = true; GUI.changed = true; ShaderSandwich.Instance.RegenShaderPreview(); ShaderSandwich.Instance.UpdateShaderPreview(); } if (GUI.Button(new Rect(100,20,15,15),ShaderSandwich.CrossRed,ButtonStyle)||ShaderUtil.MouseUpIn(new Rect(100,20,15,15))){ /*ShaderBase.Current.ShaderInputs.Remove(Input); List<ShaderVar> SVs = new List<ShaderVar>(); foreach (ShaderLayer SL in ShaderUtil.GetAllLayers()){ SL.UpdateShaderVars(true); SVs.AddRange(SL.ShaderVars); } SVs.AddRange(ShaderBase.Current.GetMyShaderVars()); ShaderInput OldInput = Input; foreach(ShaderVar SV in SVs){ if (SV.Input==OldInput) SV.Input = null; }*/ if (Input!=null){ ShaderInput OldInput = Input; Input = null; List<ShaderVar> SVs = new List<ShaderVar>(); foreach (ShaderLayer SL in ShaderUtil.GetAllLayers()){ SL.UpdateShaderVars(true); SVs.AddRange(SL.ShaderVars); } SVs.AddRange(ShaderBase.Current.GetMyShaderVars()); OldInput.UsedCount = 0; foreach(ShaderVar SV in SVs){ if (SV.Input==OldInput) OldInput.UsedCount+=1; } if (OldInput.UsedCount==0){ ShaderBase.Current.ShaderInputs.Remove(OldInput); foreach(ShaderVar SV in SVs){ if (SV.Input==OldInput) SV.Input = null; } } //UEObject.DestroyImmediate(SL,false); ShaderSandwich.ShaderVarEditing = null; EditorGUIUtility.ExitGUI(); } } if (OrigInput!=Input||OrigComponent!=ColorComponent){ UpdateToInput(); GUI.changed = true; ShaderSandwich.Instance.ChangeSaveTemp(MyParent); } ShaderUtil.EndGroup(); } } } }
public ShaderInput AddInput(){ Input = ShaderInput.CreateInstance<ShaderInput>(); Input.AutoCreated = true; //Debug.Log(MyParent); if (MyParent!=null) Input.VisName = MyParent.Name.Text+" - "+Name; else Input.VisName = Name; ShaderBase.Current.ShaderInputs.Add(Input); ShaderBase.Current.RecalculateAutoInputs(); Input.Number = Float; Input.Range0 = Range0; Input.Range1 = Range1; Input.Color = Vector; if (CType==Types.Vec) Input.Type=1; if (CType==Types.Float) if (NoSlider==false) Input.Type=4; else Input.Type=3; if (CType==Types.Texture){ Input.Image = Image; Input.ImageGUID = ImageGUID; Input.Type = 0; } if (CType==Types.Cubemap){ Input.Cube = Cube; Input.CubeGUID = CubeGUID; Input.Type = 2; } return Input; }
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 BlackboardFieldPropertyView(BlackboardField blackboardField, GraphData graph, ShaderInput input) : base(blackboardField, graph, input) { }