void ResetReferenceName(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out ResetReferenceNameAction"); AssertHelpers.IsNotNull(shaderInputReference, "ShaderInputReference is null while carrying out ResetReferenceNameAction"); graphData.owner.RegisterCompleteObjectUndo("Reset Reference Name"); shaderInputReference.overrideReferenceName = null; }
void AddShaderInput(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out AddShaderInputAction"); // If type property is valid, create instance of that type if (blackboardItemType != null && blackboardItemType.IsSubclassOf(typeof(BlackboardItem))) { shaderInputReference = (BlackboardItem)Activator.CreateInstance(blackboardItemType, true); } else if (shaderInputReferenceGetter != null) { shaderInputReference = shaderInputReferenceGetter(); } // If type is null a direct override object must have been provided or else we are in an error-state else if (shaderInputReference == null) { AssertHelpers.Fail("BlackboardController: Unable to complete Add Shader Input action."); return; } shaderInputReference.generatePropertyBlock = shaderInputReference.isExposable; graphData.owner.RegisterCompleteObjectUndo("Add Shader Input"); graphData.AddGraphInput(shaderInputReference); }
void MoveShaderInput(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out MoveShaderInputAction"); AssertHelpers.IsNotNull(shaderInputReference, "ShaderInputReference is null while carrying out MoveShaderInputAction"); graphData.owner.RegisterCompleteObjectUndo("Move Graph Input"); graphData.MoveItemInCategory(shaderInputReference, newIndexValue, associatedCategoryGuid); }
void ChangeExposedFlag(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out ChangeExposedFlagAction"); AssertHelpers.IsNotNull(shaderInputReference, "ShaderInputReference is null while carrying out ChangeExposedFlagAction"); // The Undos are currently handled in ShaderInputPropertyDrawer but we want to move that out from there and handle here //graphData.owner.RegisterCompleteObjectUndo("Change Exposed Toggle"); shaderInputReference.generatePropertyBlock = newIsExposedValue; }
void ChangeDisplayName(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out ChangeDisplayNameAction"); AssertHelpers.IsNotNull(shaderInputReference, "ShaderInputReference is null while carrying out ChangeDisplayNameAction"); graphData.owner.RegisterCompleteObjectUndo("Change Display Name"); if (newDisplayNameValue != shaderInputReference.displayName) { shaderInputReference.SetDisplayNameAndSanitizeForGraph(graphData, newDisplayNameValue); } }
void CopyCategory(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out CopyCategoryAction"); AssertHelpers.IsNotNull(categoryToCopyReference, "CategoryToCopyReference is null while carrying out CopyCategoryAction"); // This is called by MaterialGraphView currently, no need to repeat it here, though ideally it would live here //graphData.owner.RegisterCompleteObjectUndo("Copy Category"); newCategoryDataReference = graphData.CopyCategory(categoryToCopyReference); }
void AddCategory(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out AddCategoryAction"); graphData.owner.RegisterCompleteObjectUndo("Add Category"); // If categoryDataReference is not null, directly add it to graphData if (categoryDataReference == null) { categoryDataReference = new CategoryData(categoryName, childObjects); } graphData.AddCategory(categoryDataReference); }
void ChangeReferenceName(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out ChangeReferenceNameAction"); AssertHelpers.IsNotNull(shaderInputReference, "ShaderInputReference is null while carrying out ChangeReferenceNameAction"); // The Undos are currently handled in ShaderInputPropertyDrawer but we want to move that out from there and handle here //graphData.owner.RegisterCompleteObjectUndo("Change Reference Name"); if (newReferenceNameValue != shaderInputReference.overrideReferenceName) { graphData.SanitizeGraphInputReferenceName(shaderInputReference, newReferenceNameValue); } }
void AddShaderInput(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out AddShaderInputAction"); // If type property is valid, create instance of that type if (blackboardItemType != null && blackboardItemType.IsSubclassOf(typeof(BlackboardItem))) { shaderInputReference = (BlackboardItem)Activator.CreateInstance(blackboardItemType, true); } else if (m_ShaderInputReferenceGetter != null) { shaderInputReference = m_ShaderInputReferenceGetter(); } // If type is null a direct override object must have been provided or else we are in an error-state else if (shaderInputReference == null) { AssertHelpers.Fail("BlackboardController: Unable to complete Add Shader Input action."); return; } shaderInputReference.generatePropertyBlock = shaderInputReference.isExposable; if (graphData.owner != null) { graphData.owner.RegisterCompleteObjectUndo("Add Shader Input"); } else { AssertHelpers.Fail("GraphObject is null while carrying out AddShaderInputAction"); } graphData.AddGraphInput(shaderInputReference); // If no categoryToAddItemToGuid is provided, add the input to the default category if (categoryToAddItemToGuid == String.Empty) { var defaultCategory = graphData.categories.FirstOrDefault(); AssertHelpers.IsNotNull(defaultCategory, "Default category reference is null."); if (defaultCategory != null) { var addItemToCategoryAction = new AddItemToCategoryAction(); addItemToCategoryAction.categoryGuid = defaultCategory.categoryGuid; addItemToCategoryAction.itemToAdd = shaderInputReference; graphData.owner.graphDataStore.Dispatch(addItemToCategoryAction); } } else { var addItemToCategoryAction = new AddItemToCategoryAction(); addItemToCategoryAction.categoryGuid = categoryToAddItemToGuid; addItemToCategoryAction.itemToAdd = shaderInputReference; graphData.owner.graphDataStore.Dispatch(addItemToCategoryAction); } }
void DeleteShaderInput(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out DeleteShaderInputAction"); AssertHelpers.IsNotNull(shaderInputsToDelete, "ShaderInputsToDelete is null while carrying out DeleteShaderInputAction"); // This is called by MaterialGraphView currently, no need to repeat it here, though ideally it would live here //graphData.owner.RegisterCompleteObjectUndo("Delete Graph Input(s)"); foreach (var shaderInput in shaderInputsToDelete) { graphData.RemoveGraphInput(shaderInput); } }
void CopyShaderInput(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out CopyShaderInputAction"); AssertHelpers.IsNotNull(shaderInputToCopy, "ShaderInputToCopy is null while carrying out CopyShaderInputAction"); // Don't handle undo here as there are different contexts in which this action is used, that define the undo action namea // TODO: Perhaps a sign that each of those need to be made their own actions instead of conflating intent into a single action switch (shaderInputToCopy) { case AbstractShaderProperty property: var copiedProperty = (AbstractShaderProperty)graphData.AddCopyOfShaderInput(property, insertIndex); if (copiedProperty != null) // some property types cannot be duplicated (unknown types) { // Update the property nodes that depends on the copied node foreach (var node in dependentNodeList) { if (node is PropertyNode propertyNode) { propertyNode.owner = graphData; propertyNode.property = copiedProperty; } } } copiedShaderInput = copiedProperty; break; case ShaderKeyword shaderKeyword: // Don't duplicate built-in keywords within the same graph if (shaderKeyword.isBuiltIn && graphData.keywords.Any(p => p.referenceName == shaderInputToCopy.referenceName)) { return; } var copiedKeyword = (ShaderKeyword)graphData.AddCopyOfShaderInput(shaderKeyword, insertIndex); // Update the keyword nodes that depends on the copied node foreach (var node in dependentNodeList) { if (node is KeywordNode propertyNode) { propertyNode.owner = graphData; propertyNode.keyword = copiedKeyword; } } copiedShaderInput = copiedKeyword; break; default: throw new ArgumentOutOfRangeException(); } }
void RemoveCategory(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out DeleteCategoryAction"); AssertHelpers.IsNotNull(categoriesToRemoveGuids, "CategoryToRemove is null while carrying out DeleteCategoryAction"); // This is called by MaterialGraphView currently, no need to repeat it here, though ideally it would live here //graphData.owner.RegisterCompleteObjectUndo("Delete Category"); foreach (var categoryGUID in categoriesToRemoveGuids) { graphData.RemoveCategory(categoryGUID); } }
void MoveCategory(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out MoveCategoryAction"); graphData.owner.RegisterCompleteObjectUndo("Move Category"); // Handling for out of range moves is slightly different, but otherwise we need to reverse for insertion order. var guids = newIndexValue >= graphData.categories.Count() ? categoryGuids : categoryGuids.Reverse <string>(); foreach (var guid in categoryGuids) { var cat = graphData.categories.FirstOrDefault(c => c.categoryGuid == guid); graphData.MoveCategory(cat, newIndexValue); } }
void ChangeIsExpanded(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out ChangeIsExpanded on Category"); foreach (var catid in categoryGuids) { var key = $"{editorPrefsBaseKey}.{catid}.{kEditorPrefKey}"; var currentValue = EditorPrefs.GetBool(key, true); if (currentValue != isExpanded) { EditorPrefs.SetBool(key, isExpanded); } } }
public static void DrawShaderGraphGUI(MaterialEditor materialEditor, IEnumerable <MaterialProperty> properties) { Material m = materialEditor.target as Material; Shader s = m.shader; string path = AssetDatabase.GetAssetPath(s); ShaderGraphMetadata metadata = null; foreach (var obj in AssetDatabase.LoadAllAssetsAtPath(path)) { if (obj is ShaderGraphMetadata meta) { metadata = meta; break; } } AssertHelpers.IsNotNull(metadata, "Cannot draw ShaderGraph GUI on a non-ShaderGraph material: " + materialEditor.target); DrawShaderGraphGUI(materialEditor, properties, metadata.categoryDatas); }
void MoveShaderInput(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out MoveShaderInputAction"); AssertHelpers.IsNotNull(shaderInputReference, "ShaderInputReference is null while carrying out MoveShaderInputAction"); graphData.owner.RegisterCompleteObjectUndo("Move Graph Input"); switch (shaderInputReference) { case AbstractShaderProperty property: graphData.MoveProperty(property, newIndexValue); break; case ShaderKeyword keyword: graphData.MoveKeyword(keyword, newIndexValue); break; default: throw new ArgumentOutOfRangeException(); } }
void ChangePropertyValue(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out ChangePropertyValueAction"); AssertHelpers.IsNotNull(shaderInputReference, "ShaderPropertyReference is null while carrying out ChangePropertyValueAction"); // The Undos are currently handled in ShaderInputPropertyDrawer but we want to move that out from there and handle here //graphData.owner.RegisterCompleteObjectUndo("Change Property Value"); switch (shaderInputReference) { case BooleanShaderProperty booleanProperty: booleanProperty.value = ((ToggleData)newShaderInputValue).isOn; break; case Vector1ShaderProperty vector1Property: vector1Property.value = (float)newShaderInputValue; break; case Vector2ShaderProperty vector2Property: vector2Property.value = (Vector2)newShaderInputValue; break; case Vector3ShaderProperty vector3Property: vector3Property.value = (Vector3)newShaderInputValue; break; case Vector4ShaderProperty vector4Property: vector4Property.value = (Vector4)newShaderInputValue; break; case ColorShaderProperty colorProperty: colorProperty.value = (Color)newShaderInputValue; break; case Texture2DShaderProperty texture2DProperty: texture2DProperty.value.texture = (Texture)newShaderInputValue; break; case Texture2DArrayShaderProperty texture2DArrayProperty: texture2DArrayProperty.value.textureArray = (Texture2DArray)newShaderInputValue; break; case Texture3DShaderProperty texture3DProperty: texture3DProperty.value.texture = (Texture3D)newShaderInputValue; break; case CubemapShaderProperty cubemapProperty: cubemapProperty.value.cubemap = (Cubemap)newShaderInputValue; break; case Matrix2ShaderProperty matrix2Property: matrix2Property.value = (Matrix4x4)newShaderInputValue; break; case Matrix3ShaderProperty matrix3Property: matrix3Property.value = (Matrix4x4)newShaderInputValue; break; case Matrix4ShaderProperty matrix4Property: matrix4Property.value = (Matrix4x4)newShaderInputValue; break; case SamplerStateShaderProperty samplerStateProperty: samplerStateProperty.value = (TextureSamplerState)newShaderInputValue; break; case GradientShaderProperty gradientProperty: gradientProperty.value = (Gradient)newShaderInputValue; break; default: throw new ArgumentOutOfRangeException(); } }
void HandleGraphUndoRedo(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out HandleUndoRedoAction"); AssertHelpers.IsNotNull(newGraphData, "NewGraphData is null while carrying out HandleUndoRedoAction"); graphData?.ReplaceWith(newGraphData); }
void AddItemsToCategory(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out AddItemToCategoryAction"); graphData.owner.RegisterCompleteObjectUndo("Add Item to Category"); graphData.InsertItemIntoCategory(categoryGuid, itemToAdd, indexToAddItemAt); }
void CopyShaderInput(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out CopyShaderInputAction"); AssertHelpers.IsNotNull(shaderInputToCopy, "ShaderInputToCopy is null while carrying out CopyShaderInputAction"); // Don't handle undo here as there are different contexts in which this action is used, that define the undo action // TODO: Perhaps a sign that each of those need to be made their own actions instead of conflating intent into a single action switch (shaderInputToCopy) { case AbstractShaderProperty property: var copiedProperty = (AbstractShaderProperty)graphData.AddCopyOfShaderInput(property, insertIndex); if (copiedProperty != null) // some property types cannot be duplicated (unknown types) { // Update the property nodes that depends on the copied node foreach (var node in dependentNodeList) { if (node is PropertyNode propertyNode) { propertyNode.owner = graphData; propertyNode.property = copiedProperty; } } } copiedShaderInput = copiedProperty; break; case ShaderKeyword shaderKeyword: // Don't duplicate built-in keywords within the same graph if (shaderKeyword.isBuiltIn && graphData.keywords.Any(p => p.referenceName == shaderInputToCopy.referenceName)) { return; } var copiedKeyword = (ShaderKeyword)graphData.AddCopyOfShaderInput(shaderKeyword, insertIndex); // Update the keyword nodes that depends on the copied node foreach (var node in dependentNodeList) { if (node is KeywordNode propertyNode) { propertyNode.owner = graphData; propertyNode.keyword = copiedKeyword; } } copiedShaderInput = copiedKeyword; break; case ShaderDropdown shaderDropdown: var copiedDropdown = (ShaderDropdown)graphData.AddCopyOfShaderInput(shaderDropdown, insertIndex); // Update the dropdown nodes that depends on the copied node foreach (var node in dependentNodeList) { if (node is DropdownNode propertyNode) { propertyNode.owner = graphData; propertyNode.dropdown = copiedDropdown; } } copiedShaderInput = copiedDropdown; break; default: throw new ArgumentOutOfRangeException(); } if (copiedShaderInput != null) { // If specific category to copy to is provided, find and use it foreach (var category in graphData.categories) { if (category.categoryGuid == containingCategoryGuid) { graphData.InsertItemIntoCategory(category.objectId, copiedShaderInput, insertIndex); return; } } // Else, add to default category graphData.categories.First().InsertItemIntoCategory(copiedShaderInput); } }
void ChangeGraphPath(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out ChangeGraphPathAction"); graphData.path = NewGraphPath; }
void ChangeCategoryName(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out ChangeCategoryNameAction"); graphData.owner.RegisterCompleteObjectUndo("Change Category Name"); graphData.ChangeCategoryName(categoryGuid, newCategoryNameValue); }
void CopyShaderInput(GraphData graphData) { AssertHelpers.IsNotNull(graphData, "GraphData is null while carrying out CopyShaderInputAction"); AssertHelpers.IsNotNull(shaderInputToCopy, "ShaderInputToCopy is null while carrying out CopyShaderInputAction"); // Don't handle undo here as there are different contexts in which this action is used, that define the undo action // TODO: Perhaps a sign that each of those need to be made their own actions instead of conflating intent into a single action switch (shaderInputToCopy) { case AbstractShaderProperty property: insertIndex = Mathf.Clamp(insertIndex, -1, graphData.properties.Count() - 1); var copiedProperty = (AbstractShaderProperty)graphData.AddCopyOfShaderInput(property, insertIndex); if (copiedProperty != null) // some property types cannot be duplicated (unknown types) { // Update the property nodes that depends on the copied node foreach (var node in dependentNodeList) { if (node is PropertyNode propertyNode) { propertyNode.owner = graphData; propertyNode.property = copiedProperty; } } } copiedShaderInput = copiedProperty; break; case ShaderKeyword shaderKeyword: // InsertIndex gets passed in relative to the blackboard position of an item overall, // and not relative to the array sizes of the properties/keywords/dropdowns var keywordInsertIndex = insertIndex - graphData.properties.Count(); keywordInsertIndex = Mathf.Clamp(keywordInsertIndex, -1, graphData.keywords.Count() - 1); // Don't duplicate built-in keywords within the same graph if (shaderKeyword.isBuiltIn && graphData.keywords.Any(p => p.referenceName == shaderInputToCopy.referenceName)) { return; } var copiedKeyword = (ShaderKeyword)graphData.AddCopyOfShaderInput(shaderKeyword, keywordInsertIndex); // Update the keyword nodes that depends on the copied node foreach (var node in dependentNodeList) { if (node is KeywordNode propertyNode) { propertyNode.owner = graphData; propertyNode.keyword = copiedKeyword; } } copiedShaderInput = copiedKeyword; break; case ShaderDropdown shaderDropdown: // InsertIndex gets passed in relative to the blackboard position of an item overall, // and not relative to the array sizes of the properties/keywords/dropdowns var dropdownInsertIndex = insertIndex - graphData.properties.Count() - graphData.keywords.Count(); dropdownInsertIndex = Mathf.Clamp(dropdownInsertIndex, -1, graphData.dropdowns.Count() - 1); var copiedDropdown = (ShaderDropdown)graphData.AddCopyOfShaderInput(shaderDropdown, dropdownInsertIndex); // Update the dropdown nodes that depends on the copied node foreach (var node in dependentNodeList) { if (node is DropdownNode propertyNode) { propertyNode.owner = graphData; propertyNode.dropdown = copiedDropdown; } } copiedShaderInput = copiedDropdown; break; default: throw new ArgumentOutOfRangeException(); } if (copiedShaderInput != null) { // If specific category to copy to is provided, find and use it foreach (var category in graphData.categories) { if (category.categoryGuid == containingCategoryGuid) { // Ensures that the new item gets added after the item it was duplicated from insertIndex += 1; // If the source item was already the last item in list, just add to end of list if (insertIndex >= category.childCount) { insertIndex = -1; } graphData.InsertItemIntoCategory(category.objectId, copiedShaderInput, insertIndex); return; } } // Else, add to default category graphData.categories.First().InsertItemIntoCategory(copiedShaderInput); } }