// Create a material instance of a given shader and configure textures and such void CreateMaterial(Shader shader) { string shaderPath = AssetDatabase.GetAssetPath(shader); string shaderDirectory = Path.GetDirectoryName(shaderPath); string shaderParentPath = Path.GetDirectoryName(Path.GetDirectoryName(shaderPath)); string shaderName = shader.name.Substring("Shade/".Length); string materialPath = Path.Combine(shaderParentPath, shaderName); Material material = AssetDatabase.LoadAssetAtPath <Material>(materialPath + ".mat"); if (material == null) { material = new Material(shader); AssetDatabase.CreateAsset(material, materialPath + ".mat"); } material.shader = shader; // Find the Graph.json file for this shader, find any Texture nodes and properly configure the associated material properties for them TextAsset shaderGraphAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(Path.Combine(shaderDirectory, "Graph.json")); ShaderGraph graph = JsonUtility.FromJson <ShaderGraph>(shaderGraphAsset.text); foreach (ShaderNode n in graph.nodes) { if (n.options.userLabel != null) { string lowercaseName = Char.ToLowerInvariant(n.options.userLabel[0]) + n.options.userLabel.Substring(1); string propertyName = "_" + lowercaseName.Replace(" ", ""); if (n.name == "Texture") { Texture2D tex = AssetDatabase.LoadAssetAtPath <Texture2D>(Path.Combine(shaderDirectory, n.options.value + ".png")); if (tex != null) { material.SetTexture(propertyName, tex); } } else if ((n.name == "Gradient" || n.name == "Bake")) { // Gradients need their textures to be clamped, so find the texture asset to update it's import settings string texturePath = Path.Combine(shaderDirectory, n.options.userLabel + ".png"); TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(texturePath); importer.wrapMode = TextureWrapMode.Clamp; importer.SaveAndReimport(); Texture2D tex = AssetDatabase.LoadAssetAtPath <Texture2D>(texturePath); if (tex != null) { material.SetTexture(propertyName, tex); } } } } }
private void Init() { m_graphyManager = transform.root.GetComponentInChildren <GraphyManager>(); m_audioMonitor = GetComponent <AudioMonitor>(); m_shaderGraph = new ShaderGraph(); m_shaderGraph.Image = m_imageGraph; UpdateParameters(); }
private void Init() { m_graphyManager = transform.root.GetComponentInChildren <GraphyManager>(); m_fpsMonitor = GetComponent <FpsMonitor>(); m_shaderGraph = new ShaderGraph(); m_shaderGraph.Material = m_imageGraph.material; m_shaderGraph.InitializeShader(); UpdateParameters(); }
private void Init() { m_graphyManager = transform.root.GetComponentInChildren <GraphyManager>(); m_ramMonitor = GetComponent <RamMonitor>(); m_shaderGraphAllocated = new ShaderGraph(); m_shaderGraphReserved = new ShaderGraph(); m_shaderGraphMono = new ShaderGraph(); m_shaderGraphAllocated.Image = m_imageAllocated; m_shaderGraphReserved.Image = m_imageReserved; m_shaderGraphMono.Image = m_imageMono; UpdateParameters(); }
private void HandleEvents() // Texel added parent input for drag and drop { switch( Event.current.type ) { case EventType.DragUpdated: case EventType.DragPerform : { if (position.Contains(_currentMousePosition)) { var path = DragAndDrop.paths[0]; if (path.EndsWith("sgraph")) { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; if (Event.current.type == EventType.dragPerform) { _shouldLoadGraph = true; _overrideLoadPath = path; _lastGraphPath = path; _markDirtyOnLoad = true; } Event.current.Use(); } } break; } case EventType.MouseDown: { if (Event.current.button == 0 ) { if( LeftMouseDown() ) { Event.current.Use(); return; } } break; } case EventType.ContextClick: { if( RightMouseDown() ) { Event.current.Use(); return; } break; } //Handle drag case EventType.MouseDrag: { _currentMousePosition.x = Event.current.mousePosition.x; _currentMousePosition.y = Event.current.mousePosition.y; //If Left click drag... if (Event.current.button == 0 ) { if( LeftMouseDragged() ) { Event.current.Use(); } } if( Event.current.button == 2 ) { _middleMouseDrag = true; _selectedGraph.CurrentSubGraph.DrawOffset += Event.current.delta; Event.current.Use(); } break; } case EventType.MouseUp: { //Mouse button released, unmark hot _selectedGraph.UnmarkSelectedHot(); if( _focusChanged ) { _focusChangedUpdate = true; _focusChanged = false; } //Selection box if( _doingSelectBox ) { _doingSelectBox = false; if( _selectedGraph.Select( GetSelectionArea(), Event.current.modifiers == EventModifiers.Shift ) ) { NextSelectedNode = _selectedGraph.FirstSelected; _updateSelection = true; MarkDirty(); } Event.current.Use(); } if( _movingNodes ) { _movingNodes = false; MarkDirty(); Event.current.Use(); } if( _middleMouseDrag ) { _middleMouseDrag = false; MarkDirty(); Event.current.Use(); } break; } case EventType.Layout: { if (_nextGraph != null && _nextGraph != _selectedGraph) { _selectedGraph = _nextGraph; if( _markDirtyOnLoad ) { MarkDirty(); _markDirtyOnLoad = false; } _selectedNode = null; } if( _selectedGraph.CurrentSubGraphType != _currentSubGraphType ) { _selectedGraph.CurrentSubGraphType = _currentSubGraphType; _selectedGraph.Deselect(); MarkDirty(); _selectedNode = null; } if( _updateSelection ) { _focusChanged = true; _selectedNode = NextSelectedNode; _updateSelection = false; } break; } case EventType.ValidateCommand: { if( Event.current.commandName == "Copy" || Event.current.commandName == "Paste" || Event.current.commandName == "Duplicate" || Event.current.commandName == "SelectAll") { Event.current.Use(); } break; } case EventType.ExecuteCommand: { if( Event.current.commandName == "Copy" ) { CopySelectedNodes(); Event.current.Use(); } if( Event.current.commandName == "Paste" ) { PasteNodes(); Event.current.Use(); } if( Event.current.commandName == "Duplicate" ) { CopySelectedNodes(); PasteNodes(); MarkDirty(); Event.current.Use(); } if( Event.current.commandName == "SelectAll" ) { _selectedGraph.SelectAll(); NextSelectedNode = _selectedGraph.FirstSelected; _updateSelection = true; MarkDirty(); Event.current.Use(); } break; } } return; }
private void FileMenuSelect( object objProperty ) { if( objProperty.GetType() != typeof( FileMenuOptions ) ) { return; } var option = (FileMenuOptions)objProperty; switch( option ) { case FileMenuOptions.NewGraph: { if (EditorUtility.DisplayDialog("New Graph","Old graph will be lost, are you sure?","Confirm","Cancel")) { _nextGraph = new ShaderGraph(); _nextGraph.Initialize( new Rect( 0, 0, Screen.width, Screen.height ), true); _graphNeedsUpdate = true; _lastGraphPath = ""; _lastExportPath = ""; _undoChain = new GraphHistory( _serializableTypes ); _markDirtyOnLoad = true; } break; } case FileMenuOptions.ExportGraph: case FileMenuOptions.ExportAsGraph: { _shouldExportShader = true; if (!String.IsNullOrEmpty(_lastExportPath) && option == FileMenuOptions.ExportGraph) { _quickExport = true; } if (!String.IsNullOrEmpty(_lastGraphPath)) { _shouldSaveGraph = true; _quickSaving = true; } break; } case FileMenuOptions.SaveGraph: case FileMenuOptions.SaveAsGraph: { _shouldSaveGraph = true; if (!String.IsNullOrEmpty(_lastGraphPath) && option == FileMenuOptions.SaveGraph) { _quickSaving = true; } break; } case FileMenuOptions.LoadGraph: { _shouldLoadGraph = true; break; } } }
public void OnGUI() { if (!_isInstructionCountCached) CacheCount(); GUI.Label(new Rect(5,0,95,45),new GUIContent(_instructionCountDetails,_instructionCountTooltip)); _reservedArea.Clear(); _drawArea = new Rect( 0, 0, Screen.width-300, Screen.height-23 ); _detailsBox = new Rect(Screen.width - 300,0, 300, Screen.height - 40); _optionsBox = new Rect(Screen.width - 300,Screen.height - 40, 300 , 25); //Mouse clicks in the reserved area do not attemp to select on graph _reservedArea.Add( _detailsBox ); _reservedArea.Add( _optionsBox ); _currentMousePosition.x = Event.current.mousePosition.x; _currentMousePosition.y = Event.current.mousePosition.y; // Handle Minimap! (Texel) if (_middleMouseDrag) { var oldColor = GUI.color; var trans = GUI.color * new Vector4(1,1,1,0.3f); // Fairly transparent // First, draw the bounds of the graph. This requires min/maxing the graph var drawCenter = new Vector2((_drawArea.x + (_drawArea.width * 0.5f)),_drawArea.y + (_drawArea.height * 0.5f)); drawCenter.x -= _drawArea.width * 0.1f; drawCenter.y -= _drawArea.height * 0.1f; var redSize = new Vector2(_drawArea.width,_drawArea.height) * 0.2f; GUI.color = trans; GUI.Box(new Rect(drawCenter.x,drawCenter.y,redSize.x,redSize.y),""); GUI.color = oldColor; var oldBkg = GUI.backgroundColor; // Now we will draw the graph centered around the offset (Scaled down ten times) //Rect[] rects = _selectedGraph.CurrentSubGraph.nodePositions; foreach(Node node in _selectedGraph.CurrentSubGraph.Nodes) { var rect = node.NodePositionInGraph; var delta = new Vector2(rect.x,rect.y);// - offset; var size = new Vector2(rect.width,rect.height); delta *= 0.2f; size *= 0.2f; delta += drawCenter; switch (node.CurrentState) { case (NodeState.Valid): GUI.color = Color.white; break; case (NodeState.NotConnected): GUI.color = new Color (0.8f, 0.8f, 1f); break; case (NodeState.CircularReferenceInGraph): GUI.color = new Color (0.8f, 0.8f, 0f); break; case (NodeState.Error): GUI.color = Color.red; break; } if( node == _selectedNode ) GUI.backgroundColor = Color.Lerp(GUI.backgroundColor,Color.green,0.5f); GUI.Box(new Rect(delta.x,delta.y,size.x,size.y),""); GUI.color = oldColor; GUI.backgroundColor = oldBkg; } } HandleEvents(); //GUI fixup for changed focus GUI.SetNextControlName("FocusFixup"); EditorGUI.Toggle(new Rect(-100, -100, 1, 1), false); if (_focusChangedUpdate) { GUI.FocusControl("FocusFixup"); _focusChangedUpdate = false; } //Update each node and draw them _selectedGraph.UpdateErrorState(); GUILayout.BeginArea( _drawArea ); _selectedGraph.Draw( this, _showComments, _drawArea ); UpdateIOChannels(); DrawIOLines(_drawArea); GUILayout.EndArea( ); if( _doingSelectBox ) { var oldColor = GUI.color; var newColor = GUI.color; newColor.a = 0.4f; GUI.color = newColor; GUI.Box( GetSelectionArea(), "" ); GUI.color = oldColor; } DrawSettings(); //Handle node delete / undo and redo if( !GUI.changed && Event.current.type == EventType.KeyDown ) { if (Event.current.keyCode == KeyCode.Z && ( Event.current.modifiers == EventModifiers.Alt ) ) { var graph = _undoChain.Undo(); if( graph != null ) { _nextGraph = graph; _nextGraph.Initialize( new Rect( 0, 0, Screen.width, Screen.height ), false); _graphNeedsUpdate = true; NextSelectedNode = _nextGraph.FirstSelected; _updateSelection = true; Event.current.Use(); } return; } if (Event.current.keyCode == KeyCode.Z && ( Event.current.modifiers == (EventModifiers.Alt | EventModifiers.Shift ) ) ) { var graph = _undoChain.Redo(); if( graph != null ) { _nextGraph = graph; _nextGraph.Initialize( new Rect( 0, 0, Screen.width, Screen.height ), false); _graphNeedsUpdate = true; NextSelectedNode = _nextGraph.FirstSelected; _updateSelection = true; Event.current.Use(); } return; } if (Event.current.keyCode == KeyCode.Delete || Event.current.keyCode == KeyCode.Backspace) { _selectedGraph.CurrentSubGraph.DeleteSelected(); NextSelectedNode = null; _graphNeedsUpdate = true; _updateSelection = true; SelectedInputChannel = null; SelectedOutputChannel = null; MarkDirty(); Event.current.Use(); } } //Draw the current subgraph type var oldFontSize = GUI.skin.label.fontSize; var oldFontStyle = GUI.skin.label.fontStyle; GUI.skin.label.fontSize = 30; GUI.skin.label.fontStyle = FontStyle.BoldAndItalic; GUILayout.BeginArea( _drawArea ); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.Label( _currentSubGraphType.DisplayName(), GUI.skin.label ); GUILayout.Space( 10 ); GUILayout.EndHorizontal(); GUILayout.EndArea(); GUI.skin.label.fontSize = oldFontSize; GUI.skin.label.fontStyle = oldFontStyle; DrawOptions(); }
protected NodeEditor( ) { _shaderEditorResourceDir = Application.dataPath + Path.DirectorySeparatorChar + "StrumpyShaderEditor" + Path.DirectorySeparatorChar + "Editor" + Path.DirectorySeparatorChar + "Resources" + Path.DirectorySeparatorChar; _internalTempDir = "Internal" + Path.DirectorySeparatorChar + "Temp" + Path.DirectorySeparatorChar; _internalTempUnityPath = "Internal/Temp/"; _autosavePath = _shaderEditorResourceDir + _internalTempDir + "autosave.sgraph"; _tempShaderPathFull = _shaderEditorResourceDir + _internalTempDir + TempShaderName + ".shader"; _shaderTemplatePath = _shaderEditorResourceDir + "Internal" + Path.DirectorySeparatorChar + "ShaderTemplate.template"; _graphsDir = _shaderEditorResourceDir + "Public" + Path.DirectorySeparatorChar + "Graphs"; _selectedGraph = new ShaderGraph(); _popupMenu = new PopupMenu( ); //Find all the nodes that exist in the assembly (for submission to popup menu) var types = AppDomain.CurrentDomain.GetAssemblies().ToList().SelectMany(s => s.GetTypes()); foreach (var type in types) { foreach (var attribute in Attribute.GetCustomAttributes(type).OfType<NodeMetaData>()) { NodeMetaData attribute2 = attribute; _popupMenu.AddItem( new ExecutableMenuItem( attribute.Category, attribute.DisplayName, delegate( Vector2 location ){ var toAdd = Activator.CreateInstance(attribute2.NodeType) as Node; if (toAdd == null) { return; } _selectedGraph.CurrentSubGraph.AddNode(toAdd); toAdd.NodePositionInGraph = new EditorRect( location.x, location.y, 10f, 10f); MarkDirty(); }, String.IsNullOrEmpty(attribute.Descriptor) ? "" : attribute.Descriptor ) ); } } _popupMenu.SortMenu(); //Find all the serializable types _serializableTypes.Clear(); foreach (var type in types) { var typeAttributes = Attribute.GetCustomAttributes(type); foreach (var attribute in typeAttributes) { if (attribute is DataContractAttribute) { _serializableTypes.Add(type); } } } //Finally load the last graph LoadLastGraph(); _selectedGraph.Initialize( new Rect( 0,0, Screen.width, Screen.height ), true ); _undoChain = new GraphHistory( _serializableTypes ); _shouldOpenPreviewWindow = true; }
//Load the last 'autosave' graph private void LoadLastGraph() { var fi = new FileInfo(_autosavePath); if (fi.Exists) { try{ var fs = fi.OpenRead(); var reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()); var ser = new DataContractSerializer(typeof(AutoSaveGraph), _serializableTypes, int.MaxValue, false, false, null); var loaded = ser.ReadObject(reader, true) as AutoSaveGraph; if (loaded != null) { _nextGraph = loaded.Graph; if( !string.IsNullOrEmpty( loaded.ExportPath ) && File.Exists( loaded.ExportPath ) ) _lastExportPath = loaded.ExportPath; if( !string.IsNullOrEmpty( loaded.SavePath ) && File.Exists( loaded.SavePath ) ) _lastGraphPath = loaded.SavePath; _nextGraph.Initialize( new Rect( 0, 0, Screen.width, Screen.height ), true); _markDirtyOnLoad = true; } reader.Close(); fs.Close(); } catch( Exception e ) { Debug.Log( e ); EditorUtility.DisplayDialog("Load Shader Error", "Could not load shader", "Ok"); } } }
public void Update() { wantsMouseMove = true; //Need to force recreate the preview window if transitioning from //game to editor or back if( _isPlayingInEditor != EditorApplication.isPlaying ) { DisablePreview(); _shouldOpenPreviewWindow = true; _isPlayingInEditor = EditorApplication.isPlaying; } if( _shouldOpenPreviewWindow && PreviewSupported() ) { //Find the preview window var types = AppDomain.CurrentDomain.GetAssemblies().ToList().SelectMany(s => s.GetTypes()); var previewWindowType = types.FirstOrDefault( x => x.FullName == "StrumpyPreviewWindow" ); if( previewWindowType != null ) { _previewWindow = GetWindow( previewWindowType, true, "Preview" ) as PreviewWindowInternal; if (_previewWindow != null) { _previewWindow.Initialize(this); _previewWindow.wantsMouseMove = true; _previewWindow.ShouldUpdate = true; _shouldOpenPreviewWindow = false; } } } //Update preview if (_shouldUpdateShader) { if (_selectedGraph.IsGraphValid()) { File.WriteAllText(_tempShaderPathFull, _selectedGraph.GetShader(_shaderTemplatePath, true)); var currentShader = Resources.Load(_internalTempUnityPath + TempShaderName) as Shader; var path = AssetDatabase.GetAssetPath(currentShader); AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); if( _previewWindow != null ) _previewWindow.PreviewMaterial = new Material(currentShader); _graphNeedsUpdate = false; InstructionCounter.CountInstructions(); // Update the instruction count CacheCount(); // Solve the tooltip (Cached) } else { EditorUtility.DisplayDialog("Save Shader Error", "Cannot update shader, there are errors in the graph", "Ok"); } _shouldUpdateShader = false; } //Save graph if (_shouldSaveGraph) { var path = _quickSaving ? _lastGraphPath : EditorUtility.SaveFilePanel("Save shader graph to file...", _graphsDir, "shader.sgraph", "sgraph"); if (!string.IsNullOrEmpty(path)) { var writer = new FileStream(path, FileMode.Create); var ser = new DataContractSerializer(typeof (ShaderGraph), _serializableTypes, int.MaxValue, false, false, null); ser.WriteObject(writer, _selectedGraph); writer.Close(); _lastGraphPath = path; } _shouldSaveGraph = false; _quickSaving = false; } //Load graph if( _shouldLoadGraph ) { var loadDir = _graphsDir; if(!String.IsNullOrEmpty(_lastGraphPath)) loadDir = _lastGraphPath; var path = string.IsNullOrEmpty(_overrideLoadPath) ? EditorUtility.OpenFilePanel("Load shader graph...", loadDir, "sgraph") : _overrideLoadPath; bool didLoad = false; if (!string.IsNullOrEmpty(path)) { try { using( var fs = new FileStream(path, FileMode.Open) ) { using( var reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()) ) { var ser = new DataContractSerializer(typeof (ShaderGraph), _serializableTypes, int.MaxValue, false, false, null); var loaded = ser.ReadObject(reader, true) as ShaderGraph; if (loaded != null) { _undoChain = new GraphHistory( _serializableTypes ); _nextGraph = loaded; loaded.Initialize( new Rect(0, 0, Screen.width, Screen.height), true); _lastGraphPath = path; _lastExportPath = ""; didLoad = true; } } } } catch( Exception e ){ Debug.Log( e ); } //Try loading autosave graph (it's in a differnt xml format) try { if( !didLoad ) { using( var fs = new FileStream(path, FileMode.Open) ) { using( var reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()) ) { var ser = new DataContractSerializer(typeof(AutoSaveGraph), _serializableTypes, int.MaxValue, false, false, null); var loaded = ser.ReadObject(reader, true) as AutoSaveGraph; if (loaded != null) { _undoChain = new GraphHistory( _serializableTypes ); _nextGraph = loaded.Graph; _nextGraph.Initialize( new Rect(0, 0, Screen.width, Screen.height), true); _lastGraphPath = ""; _lastExportPath = ""; didLoad = true; } } } } } catch( Exception e) { Debug.Log(e); } if( !didLoad ) { EditorUtility.DisplayDialog("Load Shader Error", "Could not load shader", "Ok"); } } _shouldLoadGraph = false; _shouldUpdateShader = true; _overrideLoadPath = ""; } //Export the shader to a .shader file if (_shouldExportShader) { if (_selectedGraph.IsGraphValid()) { var path = _quickExport ? _lastExportPath : EditorUtility.SaveFilePanel("Export shader to file...", Application.dataPath, "shader.shader", "shader"); _lastExportPath = path; // For quick exporting - Texel if (!string.IsNullOrEmpty(path)) { File.WriteAllText(path, _selectedGraph.GetShader(_shaderTemplatePath, false)); AssetDatabase.Refresh(); // Investigate if this is optimal } InstructionCounter.CountInstructions(); // Update the instruction count CacheCount(); // Solve the tooltip (Cached) } else { EditorUtility.DisplayDialog("Export Shader Error", "Cannot export shader, there are errors in the graph", "Ok"); } _shouldExportShader = false; _quickExport = false; } Repaint(); }
public void AddUndoLevel( ShaderGraph graph ) { var stream = new MemoryStream(); _serializer.WriteObject(stream, graph); stream.Flush(); if( _currentState != null ) { _undoStack.Push( _currentState ); } _currentState = stream; _redoStack.Clear(); }
// Create a material instance of a given shader and configure textures and such void CreateMaterial(Shader shader) { string shaderPath = AssetDatabase.GetAssetPath(shader); string shaderDirectory = Path.GetDirectoryName(shaderPath); string shaderParentPath = Path.GetDirectoryName(Path.GetDirectoryName(shaderPath)); string shaderName = shader.name.Substring("Shade/".Length); string materialPath = Path.Combine(shaderParentPath, shaderName); Material material = AssetDatabase.LoadAssetAtPath <Material>(materialPath + ".mat"); if (material == null) { material = new Material(shader); AssetDatabase.CreateAsset(material, materialPath + ".mat"); } material.shader = shader; // Find the Graph.json file for this shader, find any Texture nodes and properly configure the associated material properties for them TextAsset shaderGraphAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(Path.Combine(shaderDirectory, "Graph.json")); ShaderGraph graph = JsonUtility.FromJson <ShaderGraph>(shaderGraphAsset.text); ShaderImporter shaderImporter = ShaderImporter.GetAtPath(shaderPath) as ShaderImporter; string[] textureTypes = { "Texture", "Gradient", "Bake", "Tiler" }; foreach (ShaderNode n in graph.nodes) { if (n.options.userLabel != null) { string lowercaseName = Char.ToLowerInvariant(n.options.userLabel[0]) + n.options.userLabel.Substring(1); string propertyName = "_" + lowercaseName.Replace(" ", ""); if (Array.Exists(textureTypes, element => element == n.name)) { string textureName = n.options.value != null ? n.options.value : n.options.userLabel; Texture2D tex = AssetDatabase.LoadAssetAtPath <Texture2D>(Path.Combine(shaderDirectory, textureName + ".png")); if (tex != null) { material.SetTexture(propertyName, tex); shaderImporter.SetDefaultTextures(new[] { propertyName }, new[] { tex }); string texturePath = AssetDatabase.GetAssetPath(tex); TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(texturePath); if (n.options.wrapMode != null) { switch (n.options.wrapMode) { case "repeat": importer.wrapMode = TextureWrapMode.Repeat; break; case "clamp": importer.wrapMode = TextureWrapMode.Clamp; break; case "mirror": importer.wrapMode = TextureWrapMode.Mirror; break; } } else { importer.wrapMode = TextureWrapMode.Clamp; } if (n.options.filterMode != null) { switch (n.options.filterMode) { case "point": importer.filterMode = FilterMode.Point; break; case "linear": importer.filterMode = n.options.generateMipmaps ? FilterMode.Trilinear : FilterMode.Bilinear; break; } } importer.textureType = n.options.isNormalMap ? TextureImporterType.NormalMap : TextureImporterType.Default; importer.SaveAndReimport(); } } } } }