public void TestSerializationHelperCanSerializeThenDeserialize() { var toSerialize = new List <SimpleSerializeClass>() { SimpleSerializeClass.instance }; var serialized = SerializationHelper.Serialize <SimpleSerializeClass>(toSerialize); Assert.AreEqual(1, serialized.Count); var loaded = SerializationHelper.Deserialize <SimpleSerializeClass>(serialized, GraphUtil.GetLegacyTypeRemapping()); Assert.AreEqual(1, loaded.Count); Assert.IsInstanceOf <SimpleSerializeClass>(loaded[0]); loaded[0].AssertAsReference(); }
protected override bool DoShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData) { // CAUTION: Pass Name and Lightmode name must match in master node and .shader. // HDRP use LightMode to do drawRenderer and pass name is use here for stripping! bool isGBufferPass = snippet.passName == "GBuffer"; bool isForwardPass = snippet.passName == "Forward"; bool isDepthOnlyPass = snippet.passName == "DepthOnly"; bool isMotionPass = snippet.passName == "MotionVectors"; bool isTransparentPrepass = snippet.passName == "TransparentDepthPrepass"; bool isTransparentPostpass = snippet.passName == "TransparentDepthPostpass"; bool isTransparentBackface = snippet.passName == "TransparentBackface"; bool isDistortionPass = snippet.passName == "DistortionVectors"; bool isTransparentForwardPass = isTransparentPostpass || isTransparentBackface || isTransparentPrepass || isDistortionPass; // Using Contains to include the Tessellation variants bool isBuiltInTerrainLit = shader.name.Contains("HDRP/TerrainLit"); bool isBuiltInLit = shader.name.Contains("HDRP/Lit") || shader.name.Contains("HDRP/LayeredLit") || isBuiltInTerrainLit; if (shader.IsShaderGraph()) { string shaderPath = AssetDatabase.GetAssetPath(shader); isBuiltInLit |= GraphUtil.GetOutputNodeType(shaderPath) == typeof(HDLitMasterNode); } // Caution: Currently only HDRP/TerrainLit is using keyword _ALPHATEST_ON with multi compile, we shouldn't test any other built in shader if (isBuiltInTerrainLit) { if (inputData.shaderKeywordSet.IsEnabled(m_AlphaTestOn) && !hdrpAsset.currentPlatformRenderPipelineSettings.supportTerrainHole) { return(true); } } // When using forward only, we never need GBuffer pass (only Forward) // Gbuffer Pass is suppose to exist only for Lit shader thus why we test the condition here in case another shader generate a GBuffer pass (like VFX) if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && isGBufferPass) { return(true); } // Variant of light layer only exist in GBuffer pass, so we test it here if (inputData.shaderKeywordSet.IsEnabled(m_LightLayers) && isGBufferPass && !hdrpAsset.currentPlatformRenderPipelineSettings.supportLightLayers) { return(true); } // This test include all Lit variant from Shader Graph (Because we check "DepthOnly" pass) // Other forward material ("DepthForwardOnly") don't use keyword for WriteNormalBuffer but #define if (isDepthOnlyPass) { // When we are full forward, we don't have depth prepass or motion vectors pass without writeNormalBuffer if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && !inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer)) { return(true); } // When we are deferred, we don't have depth prepass or motion vectors pass with writeNormalBuffer // Note: This rule is safe with Forward Material because WRITE_NORMAL_BUFFER is not a keyword for them, so it will not be removed if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly && inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer)) { return(true); } } // Apply following set of rules only to inspector version of shader as we don't have Transparent keyword with shader graph if (isBuiltInLit) { // Forward material don't use keyword for WriteNormalBuffer but #define so we can't test for the keyword outside of isBuiltInLit // otherwise the pass will be remove for non-lit shader graph version (like StackLit) if (isMotionPass) { // When we are full forward, we don't have depth prepass or motion vectors pass without writeNormalBuffer if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && !inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer)) { return(true); } // When we are deferred, we don't have depth prepass or motion vectors pass with writeNormalBuffer // Note: This rule is safe with Forward Material because WRITE_NORMAL_BUFFER is not a keyword for them, so it will not be removed if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly && inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer)) { return(true); } } if (!inputData.shaderKeywordSet.IsEnabled(m_Transparent)) // Opaque { // If opaque, we never need transparent specific passes (even in forward only mode) if (isTransparentForwardPass) { return(true); } if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly) { // When we are in deferred, we only support tile lighting if (inputData.shaderKeywordSet.IsEnabled(m_ClusterLighting)) { return(true); } if (isForwardPass && !inputData.shaderKeywordSet.IsEnabled(m_DebugDisplay)) { return(true); } } // TODO: Should we remove Cluster version if we know MSAA is disabled ? This prevent to manipulate LightLoop Settings (useFPTL option) // For now comment following code // if (inputData.shaderKeywordSet.IsEnabled(m_ClusterLighting) && !hdrpAsset.currentPlatformRenderPipelineSettings.supportMSAA) // return true; } } // We strip passes for transparent passes outside of isBuiltInLit because we want Hair, Fabric // and StackLit shader graphs to be taken in account. if (inputData.shaderKeywordSet.IsEnabled(m_Transparent)) { // If transparent, we never need GBuffer pass. if (isGBufferPass) { return(true); } // If transparent we don't need the depth only pass if (isDepthOnlyPass) { return(true); } // If transparent we don't need the motion vector pass if (isMotionPass) { return(true); } // If we are transparent we use cluster lighting and not tile lighting if (inputData.shaderKeywordSet.IsEnabled(m_TileLighting)) { return(true); } } // TODO: Tests for later // We need to find a way to strip useless shader features for passes/shader stages that don't need them (example, vertex shaders won't ever need SSS Feature flag) // This causes several problems: // - Runtime code that "finds" shader variants based on feature flags might not find them anymore... thus fall backing to the "let's give a score to variant" code path that may find the wrong variant. // - Another issue is that if a feature is declared without a "_" fall-back, if we strip the other variants, none may be left to use! This needs to be changed on our side. //if (snippet.shaderType == ShaderType.Vertex && inputData.shaderKeywordSet.IsEnabled(m_FeatureSSS)) // return true; return(false); }
GraphData DeserializeGraph() { var deserializedGraph = SerializationHelper.Deserialize <GraphData>(m_SerializedGraph, GraphUtil.GetLegacyTypeRemapping()); deserializedGraph.isSubGraph = m_IsSubGraph; deserializedGraph.assetGuid = m_AssetGuid; m_DeserializedVersion = m_SerializedVersion; m_SerializedGraph = default(SerializationHelper.JSONSerializedElement); return(deserializedGraph); }
protected virtual void UpdateLineEnds() { if (Vertex.Get("BackgroundColor:") != null) { BackgroundColor = UIWpf.GetBrushFromColorVertex(Vertex.Get("BackgroundColor:")); } else { BackgroundColor = (Brush)Line.FindResource("0BackgroundBrush"); } if (Vertex.Get("ForegroundColor:") != null) { ForegroundColor = UIWpf.GetBrushFromColorVertex(Vertex.Get("ForegroundColor:")); } else { ForegroundColor = (Brush)Line.FindResource("0ForegroundBrush"); } LineEndings.Stroke = ForegroundColor; Line.Stroke = ForegroundColor; Label.Foreground = ForegroundColor; string StartAnchor = (string)GraphUtil.GetValue(Vertex.Get(@"StartAnchor:")); string EndAnchor = (string)GraphUtil.GetValue(Vertex.Get(@"EndAnchor:")); if (StartAnchor == "Straight") { LineEndings.StartEnding = LineEndEnum.Straight; Line.StartEnding = LineEndEnum.Straight; } if (EndAnchor == "Straight") { LineEndings.EndEnding = LineEndEnum.Straight; Line.EndEnding = LineEndEnum.Straight; } if (StartAnchor == "Arrow") { LineEndings.StartEnding = LineEndEnum.Arrow; Line.StartEnding = LineEndEnum.Arrow; } if (EndAnchor == "Arrow") { LineEndings.EndEnding = LineEndEnum.Arrow; Line.EndEnding = LineEndEnum.Arrow; } if (StartAnchor == "Triangle") { LineEndings.StartEnding = LineEndEnum.Triangle; Line.StartEnding = LineEndEnum.Triangle; FillBrush = BackgroundColor; HighlightFillBrush = BackgroundColor; } if (EndAnchor == "Triangle") { LineEndings.EndEnding = LineEndEnum.Triangle; Line.EndEnding = LineEndEnum.Triangle; FillBrush = BackgroundColor; HighlightFillBrush = BackgroundColor; } if (StartAnchor == "FilledTriangle") { LineEndings.StartEnding = LineEndEnum.FilledTriangle; Line.StartEnding = LineEndEnum.FilledTriangle; FillBrush = ForegroundColor; HighlightFillBrush = (Brush)LineEndings.FindResource("0LightHighlightBrush"); } if (EndAnchor == "FilledTriangle") { LineEndings.EndEnding = LineEndEnum.FilledTriangle; Line.EndEnding = LineEndEnum.FilledTriangle; FillBrush = ForegroundColor; HighlightFillBrush = (Brush)LineEndings.FindResource("0LightHighlightBrush"); } if (StartAnchor == "Diamond") { LineEndings.StartEnding = LineEndEnum.Diamond; Line.StartEnding = LineEndEnum.Diamond; FillBrush = BackgroundColor; HighlightFillBrush = BackgroundColor; } if (EndAnchor == "Diamond") { LineEndings.EndEnding = LineEndEnum.Diamond; Line.EndEnding = LineEndEnum.Diamond; FillBrush = BackgroundColor; HighlightFillBrush = BackgroundColor; } if (StartAnchor == "FilledDiamond") { LineEndings.StartEnding = LineEndEnum.FilledDiamond; Line.StartEnding = LineEndEnum.FilledDiamond; FillBrush = ForegroundColor; HighlightFillBrush = (Brush)LineEndings.FindResource("0LightHighlightBrush"); } if (EndAnchor == "FilledDiamond") { LineEndings.EndEnding = LineEndEnum.FilledDiamond; Line.EndEnding = LineEndEnum.FilledDiamond; FillBrush = ForegroundColor; HighlightFillBrush = (Brush)LineEndings.FindResource("0LightHighlightBrush"); } if (FillBrush != null) { LineEndings.Fill = FillBrush; } LineEndings.ArrowLength = 0; Line.ArrowLength = 0; LineEndings.ArrowLength = 15; Line.ArrowLength = 15; }
static string GetShaderPassFromTemplate(bool isColorPass, string template, SpriteLitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions) { // ----------------------------------------------------- // // SETUP // // ----------------------------------------------------- // // ------------------------------------- // String builders var shaderProperties = new PropertyCollector(); var shaderPropertyUniforms = new ShaderStringBuilder(1); var functionBuilder = new ShaderStringBuilder(1); var functionRegistry = new FunctionRegistry(functionBuilder); var defines = new ShaderStringBuilder(1); var graph = new ShaderStringBuilder(0); var vertexDescriptionInputStruct = new ShaderStringBuilder(1); var vertexDescriptionStruct = new ShaderStringBuilder(1); var vertexDescriptionFunction = new ShaderStringBuilder(1); var surfaceDescriptionInputStruct = new ShaderStringBuilder(1); var surfaceDescriptionStruct = new ShaderStringBuilder(1); var surfaceDescriptionFunction = new ShaderStringBuilder(1); var vertexInputStruct = new ShaderStringBuilder(1); var vertexOutputStruct = new ShaderStringBuilder(2); var vertexShader = new ShaderStringBuilder(2); var vertexShaderDescriptionInputs = new ShaderStringBuilder(2); var vertexShaderOutputs = new ShaderStringBuilder(2); var pixelShader = new ShaderStringBuilder(2); var pixelShaderSurfaceInputs = new ShaderStringBuilder(2); // ------------------------------------- // Get Slot and Node lists per stage var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var vertexNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var pixelNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // ------------------------------------- // Get Requirements var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false); var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment); var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); var modelRequiements = ShaderGraphRequirements.none; modelRequiements.requiresVertexColor = true; if (isColorPass) { modelRequiements.requiresMeshUVs = new List <UVChannel>() { UVChannel.UV0 }; } // ----------------------------------------------------- // // START SHADER GENERATION // // ----------------------------------------------------- // // ------------------------------------- // Calculate material options var blendingBuilder = new ShaderStringBuilder(1); var cullingBuilder = new ShaderStringBuilder(1); var zTestBuilder = new ShaderStringBuilder(1); var zWriteBuilder = new ShaderStringBuilder(1); materialOptions.GetBlend(blendingBuilder); materialOptions.GetCull(cullingBuilder); materialOptions.GetDepthTest(zTestBuilder); materialOptions.GetDepthWrite(zWriteBuilder); // ----------------------------------------------------- // // START VERTEX DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Vertex Description function // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs"); using (vertexDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct); if (vertexRequirements.requiresVertexColor) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (vertexRequirements.requiresScreenPosition) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct()) { vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } } // ------------------------------------- // Generate Output structure for Vertex Description function GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots); // ------------------------------------- // Generate Vertex Description function GraphUtil.GenerateVertexDescriptionFunction( masterNode.owner as GraphData, vertexDescriptionFunction, functionRegistry, shaderProperties, mode, vertexNodes, vertexSlots); // ----------------------------------------------------- // // START SURFACE DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Surface Description function // Surface Description Input requirements are needed to exclude intermediate translation spaces surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs"); using (surfaceDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct); if (surfaceRequirements.requiresVertexColor) { surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (surfaceRequirements.requiresScreenPosition) { surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } if (surfaceRequirements.requiresFaceSign) { surfaceDescriptionInputStruct.AppendLine("float {0};", ShaderGeneratorNames.FaceSign); } foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct()) { surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } } // ------------------------------------- // Generate Output structure for Surface Description function GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots); // ------------------------------------- // Generate Surface Description function GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, masterNode, masterNode.owner as GraphData, surfaceDescriptionFunction, functionRegistry, shaderProperties, pixelRequirements, mode, "PopulateSurfaceData", "SurfaceDescription", null, pixelSlots); // ----------------------------------------------------- // // GENERATE VERTEX > PIXEL PIPELINE // // ----------------------------------------------------- // // ------------------------------------- // Property uniforms shaderProperties.GetPropertiesDeclaration(shaderPropertyUniforms, mode, masterNode.owner.concretePrecision); // ------------------------------------- // Generate Input structure for Vertex shader GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct); // ------------------------------------- // Generate standard transformations // This method ensures all required transform data is available in vertex and pixel stages ShaderGenerator.GenerateStandardTransforms( 3, 10, vertexOutputStruct, vertexShader, vertexShaderDescriptionInputs, vertexShaderOutputs, pixelShader, pixelShaderSurfaceInputs, pixelRequirements, surfaceRequirements, modelRequiements, vertexRequirements, CoordinateSpace.World); // ----------------------------------------------------- // // FINALIZE // // ----------------------------------------------------- // // ------------------------------------- // Combine Graph sections graph.AppendLines(shaderPropertyUniforms.ToString()); graph.AppendLine(vertexDescriptionInputStruct.ToString()); graph.AppendLine(surfaceDescriptionInputStruct.ToString()); graph.AppendLine(functionBuilder.ToString()); graph.AppendLine(vertexDescriptionStruct.ToString()); graph.AppendLine(vertexDescriptionFunction.ToString()); graph.AppendLine(surfaceDescriptionStruct.ToString()); graph.AppendLine(surfaceDescriptionFunction.ToString()); graph.AppendLine(vertexInputStruct.ToString()); // ------------------------------------- // Generate final subshader var resultPass = template.Replace("${Tags}", string.Empty); resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString()); resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString()); resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString()); resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString()); resultPass = resultPass.Replace("${Defines}", defines.ToString()); resultPass = resultPass.Replace("${Graph}", graph.ToString()); resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString()); resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString()); resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString()); resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString()); resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString()); return(resultPass); }
public static void CreateMaterialGraph() { GraphUtil.CreateNewGraph(new HDUnlitMasterNode()); }
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 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(); 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.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); } // 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 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(); }
private static bool GenerateShaderPassLit(AbstractMaterialNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result, List <string> sourceAssetDependencyPaths) { var templateLocation = Path.Combine(Path.Combine(Path.Combine(HDEditorUtils.GetHDRenderPipelinePath(), "Editor"), "ShaderGraph"), pass.TemplateName); if (!File.Exists(templateLocation)) { // TODO: produce error here return(false); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templateLocation); } // grab all of the active nodes (for pixel and vertex graphs) var vertexNodes = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); var pixelNodes = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // graph requirements describe what the graph itself requires var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); // TODO: is ShaderStageCapability.Fragment correct? var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false); // Function Registry tracks functions to remove duplicates, it wraps a string builder that stores the combined function string ShaderStringBuilder graphNodeFunctions = new ShaderStringBuilder(); graphNodeFunctions.IncreaseIndent(); var functionRegistry = new FunctionRegistry(graphNodeFunctions); // TODO: this can be a shared function for all HDRP master nodes -- From here through GraphUtil.GenerateSurfaceDescription(..) // Build the list of active slots based on what the pass requires var pixelSlots = HDSubShaderUtilities.FindMaterialSlotsOnNode(pass.PixelShaderSlots, masterNode); var vertexSlots = HDSubShaderUtilities.FindMaterialSlotsOnNode(pass.VertexShaderSlots, masterNode); // properties used by either pixel and vertex shader PropertyCollector sharedProperties = new PropertyCollector(); // build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active) string pixelGraphInputStructName = "SurfaceDescriptionInputs"; string pixelGraphOutputStructName = "SurfaceDescription"; string pixelGraphEvalFunctionName = "SurfaceDescriptionFunction"; ShaderStringBuilder pixelGraphEvalFunction = new ShaderStringBuilder(); ShaderStringBuilder pixelGraphOutputs = new ShaderStringBuilder(); // dependency tracker -- set of active fields HashSet <string> activeFields = GetActiveFieldsFromMasterNode(masterNode, pass); // build initial requirements HDRPShaderStructs.AddActiveFieldsFromPixelGraphRequirements(activeFields, pixelRequirements); // build the graph outputs structure, and populate activeFields with the fields of that structure GraphUtil.GenerateSurfaceDescriptionStruct(pixelGraphOutputs, pixelSlots, true, pixelGraphOutputStructName, activeFields); // Build the graph evaluation code, to evaluate the specified slots GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, masterNode, masterNode.owner as AbstractMaterialGraph, pixelGraphEvalFunction, functionRegistry, sharedProperties, pixelRequirements, // TODO : REMOVE UNUSED mode, pixelGraphEvalFunctionName, pixelGraphOutputStructName, null, pixelSlots, pixelGraphInputStructName); string vertexGraphInputStructName = "VertexDescriptionInputs"; string vertexGraphOutputStructName = "VertexDescription"; string vertexGraphEvalFunctionName = "VertexDescriptionFunction"; ShaderStringBuilder vertexGraphEvalFunction = new ShaderStringBuilder(); ShaderStringBuilder vertexGraphOutputs = new ShaderStringBuilder(); // check for vertex animation -- enables HAVE_VERTEX_MODIFICATION bool vertexActive = false; if (masterNode.IsSlotConnected(PBRMasterNode.PositionSlotId)) { vertexActive = true; activeFields.Add("features.modifyMesh"); HDRPShaderStructs.AddActiveFieldsFromVertexGraphRequirements(activeFields, vertexRequirements); // ------------------------------------- // Generate Output structure for Vertex Description function GraphUtil.GenerateVertexDescriptionStruct(vertexGraphOutputs, vertexSlots, vertexGraphOutputStructName, activeFields); // ------------------------------------- // Generate Vertex Description function GraphUtil.GenerateVertexDescriptionFunction( masterNode.owner as AbstractMaterialGraph, vertexGraphEvalFunction, functionRegistry, sharedProperties, mode, vertexNodes, vertexSlots, vertexGraphInputStructName, vertexGraphEvalFunctionName, vertexGraphOutputStructName); } var blendCode = new ShaderStringBuilder(); var cullCode = new ShaderStringBuilder(); var zTestCode = new ShaderStringBuilder(); var zWriteCode = new ShaderStringBuilder(); var stencilCode = new ShaderStringBuilder(); var colorMaskCode = new ShaderStringBuilder(); HDSubShaderUtilities.BuildRenderStatesFromPassAndMaterialOptions(pass, materialOptions, blendCode, cullCode, zTestCode, zWriteCode, stencilCode, colorMaskCode); HDRPShaderStructs.AddRequiredFields(pass.RequiredFields, activeFields); // apply dependencies to the active fields, and build interpolators (TODO: split this function) var packedInterpolatorCode = new ShaderGenerator(); HDRPShaderStructs.Generate( packedInterpolatorCode, activeFields); // debug output all active fields var interpolatorDefines = new ShaderGenerator(); { interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:"); foreach (string f in activeFields) { interpolatorDefines.AddShaderChunk("// " + f); } } // build graph inputs structures ShaderGenerator pixelGraphInputs = new ShaderGenerator(); ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.SurfaceDescriptionInputs), activeFields, pixelGraphInputs); ShaderGenerator vertexGraphInputs = new ShaderGenerator(); ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.VertexDescriptionInputs), activeFields, vertexGraphInputs); ShaderGenerator defines = new ShaderGenerator(); { defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true); if (pass.ExtraDefines != null) { foreach (var define in pass.ExtraDefines) { defines.AddShaderChunk(define); } } defines.AddGenerator(interpolatorDefines); } var shaderPassIncludes = new ShaderGenerator(); if (pass.Includes != null) { foreach (var include in pass.Includes) { shaderPassIncludes.AddShaderChunk(include); } } // build graph code var graph = new ShaderGenerator(); { graph.AddShaderChunk("// Shared Graph Properties (uniform inputs)"); graph.AddShaderChunk(sharedProperties.GetPropertiesDeclaration(1)); if (vertexActive) { graph.AddShaderChunk("// Vertex Graph Inputs"); graph.Indent(); graph.AddGenerator(vertexGraphInputs); graph.Deindent(); graph.AddShaderChunk("// Vertex Graph Outputs"); graph.Indent(); graph.AddShaderChunk(vertexGraphOutputs.ToString()); graph.Deindent(); } graph.AddShaderChunk("// Pixel Graph Inputs"); graph.Indent(); graph.AddGenerator(pixelGraphInputs); graph.Deindent(); graph.AddShaderChunk("// Pixel Graph Outputs"); graph.Indent(); graph.AddShaderChunk(pixelGraphOutputs.ToString()); graph.Deindent(); graph.AddShaderChunk("// Shared Graph Node Functions"); graph.AddShaderChunk(graphNodeFunctions.ToString()); if (vertexActive) { graph.AddShaderChunk("// Vertex Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(vertexGraphEvalFunction.ToString()); graph.Deindent(); } graph.AddShaderChunk("// Pixel Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(pixelGraphEvalFunction.ToString()); graph.Deindent(); } // build the hash table of all named fragments TODO: could make this Dictionary<string, ShaderGenerator / string> ? Dictionary <string, string> namedFragments = new Dictionary <string, string>(); namedFragments.Add("${Defines}", defines.GetShaderString(2, false)); namedFragments.Add("${Graph}", graph.GetShaderString(2, false)); namedFragments.Add("${LightMode}", pass.LightMode); namedFragments.Add("${PassName}", pass.Name); namedFragments.Add("${Includes}", shaderPassIncludes.GetShaderString(2, false)); namedFragments.Add("${InterpolatorPacking}", packedInterpolatorCode.GetShaderString(2, false)); namedFragments.Add("${Blending}", blendCode.ToString()); namedFragments.Add("${Culling}", cullCode.ToString()); namedFragments.Add("${ZTest}", zTestCode.ToString()); namedFragments.Add("${ZWrite}", zWriteCode.ToString()); namedFragments.Add("${Stencil}", stencilCode.ToString()); namedFragments.Add("${ColorMask}", colorMaskCode.ToString()); namedFragments.Add("${LOD}", materialOptions.lod.ToString()); // process the template to generate the shader code for this pass TODO: could make this a shared function string[] templateLines = File.ReadAllLines(templateLocation); System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (string line in templateLines) { ShaderSpliceUtil.PreprocessShaderCode(line, activeFields, namedFragments, builder); builder.AppendLine(); } result.AddShaderChunk(builder.ToString(), false); return(true); }
/// <summary> /// Create a SMILES for a reaction of the flavour specified in the constructor and /// write the output order to the provided array. /// </summary> /// <param name="reaction">CDK reaction instance</param> /// <param name="ordering">order of output</param> /// <returns>reaction SMILES</returns> public string Create(IReaction reaction, int[] ordering) { var reactants = reaction.Reactants; var agents = reaction.Agents; var products = reaction.Products; var reactantPart = reaction.Builder.NewAtomContainer(); var agentPart = reaction.Builder.NewAtomContainer(); var productPart = reaction.Builder.NewAtomContainer(); var sgroups = new List <Sgroup>(); foreach (var reactant in reactants) { reactantPart.Add(reactant); SafeAddSgroups(sgroups, reactant); } foreach (var agent in agents) { agentPart.Add(agent); SafeAddSgroups(sgroups, agent); } foreach (var product in products) { productPart.Add(product); SafeAddSgroups(sgroups, product); } var reactantOrder = new int[reactantPart.Atoms.Count]; var agentOrder = new int[agentPart.Atoms.Count]; var productOrder = new int[productPart.Atoms.Count]; var expectedSize = reactantOrder.Length + agentOrder.Length + productOrder.Length; if (expectedSize != ordering.Length) { throw new CDKException($"Output ordering array does not have correct amount of space: {ordering.Length} expected: {expectedSize}"); } // we need to make sure we generate without the CXSMILES layers string smi = Create(reactantPart, flavour & ~SmiFlavors.CxSmilesWithCoords, reactantOrder) + ">" + Create(agentPart, flavour & ~SmiFlavors.CxSmilesWithCoords, agentOrder) + ">" + Create(productPart, flavour & ~SmiFlavors.CxSmilesWithCoords, productOrder); // copy ordering back to unified array and adjust values var agentBeg = reactantOrder.Length; var agentEnd = reactantOrder.Length + agentOrder.Length; var prodEnd = reactantOrder.Length + agentOrder.Length + productOrder.Length; System.Array.Copy(reactantOrder, 0, ordering, 0, agentBeg); System.Array.Copy(agentOrder, 0, ordering, agentBeg, agentEnd - agentBeg); System.Array.Copy(productOrder, 0, ordering, agentEnd, prodEnd - agentEnd); for (int i = agentBeg; i < agentEnd; i++) { ordering[i] += agentBeg; } for (int i = agentEnd; i < prodEnd; i++) { ordering[i] += agentEnd; } if (SmiFlavorTool.IsSet(flavour, SmiFlavors.CxSmilesWithCoords)) { var unified = reaction.Builder.NewAtomContainer(); unified.Add(reactantPart); unified.Add(agentPart); unified.Add(productPart); unified.SetCtabSgroups(sgroups); // base CXSMILES state information var cxstate = GetCxSmilesState(flavour, unified); int[] components = null; // extra state info on fragment grouping, specific to reactions if (SmiFlavorTool.IsSet(flavour, SmiFlavors.CxFragmentGroup)) { cxstate.fragGroups = new List <List <int> >(); // calculate the connected components components = new ConnectedComponents(GraphUtil.ToAdjList(unified)).GetComponents(); // AtomContainerSet is ordered so this is safe, it was actually a set we // would need some extra data structures var tmp = new HashSet <int>(); int beg = 0, end = 0; foreach (var mol in reactants) { end = end + mol.Atoms.Count; tmp.Clear(); for (int i = beg; i < end; i++) { tmp.Add(components[i]); } if (tmp.Count > 1) { cxstate.fragGroups.Add(new List <int>(tmp)); } beg = end; } foreach (var mol in agents) { end = end + mol.Atoms.Count; tmp.Clear(); for (int i = beg; i < end; i++) { tmp.Add(components[i]); } if (tmp.Count > 1) { cxstate.fragGroups.Add(new List <int>(tmp)); } beg = end; } foreach (var mol in products) { end = end + mol.Atoms.Count; tmp.Clear(); for (int i = beg; i < end; i++) { tmp.Add(components[i]); } if (tmp.Count > 1) { cxstate.fragGroups.Add(new List <int>(tmp)); } beg = end; } } smi += CxSmilesGenerator.Generate(cxstate, flavour, components, ordering); } return(smi); }
public override void VisualiserUpdate() { base.VisualiserUpdate(); if (Vertex.Get("ShowMeta:False") != null) { if (Vertex.Get(@"BaseEdge:\To:").Value != null) { this.Title.Text = Vertex.Get(@"BaseEdge:\To:").Value.ToString(); } else { this.Title.Text = "Ø"; } } else { string mtext, ttext; if (Vertex.Get(@"BaseEdge:\Meta:").Value != null) { mtext = Vertex.Get(@"BaseEdge:\Meta:").Value.ToString(); } else { mtext = "Ø"; } if (Vertex.Get(@"BaseEdge:\To:").Value != null) { ttext = Vertex.Get(@"BaseEdge:\To:").Value.ToString(); } else { ttext = "Ø"; } this.Title.Text = mtext + " : " + ttext; } if (Vertex.Get("RoundEdgeSize:") != null) { int esize = GraphUtil.GetIntegerValue(Vertex.Get("RoundEdgeSize:")); this.Frame.CornerRadius = new CornerRadius(esize); if (Vertex.Get("VisualiserClass:") != null) { this.Title.Margin = new Thickness(esize, esize, esize, 0); ((FrameworkElement)this.ContentVisualiser).Margin = new Thickness(esize, 0, esize, esize); TheGrid.RowDefinitions[0].Height = new GridLength(18 + esize); } else { this.Title.Margin = new Thickness(esize); this.Title.TextWrapping = TextWrapping.Wrap; TheGrid.RowDefinitions[0].Height = new GridLength(0, GridUnitType.Auto); TheGrid.Children.Remove(InternalFrame); } } this.Frame.Background = BackgroundColor; this.Title.Foreground = ForegroundColor; this.InternalFrame.BorderBrush = ForegroundColor; this.Frame.BorderBrush = ForegroundColor; if (ContentVisualiser != null) // not always works, but can { GeneralUtil.SetPropertyIfPresent(ContentVisualiser, "Foreground", ForegroundColor); GeneralUtil.SetPropertyIfPresent(ContentVisualiser, "Background", BackgroundColor); } if (LineWidth != 0) { this.Frame.BorderThickness = new Thickness(LineWidth); if (ContentVisualiser != null) { this.InternalFrame.BorderThickness = new Thickness(LineWidth / 2); this.TheGrid.RowDefinitions[1].Height = new GridLength(LineWidth); } } }
/// <summary> /// Create a new RingSearch for the specified container. /// </summary> /// <param name="container">non-null input structure</param> /// <exception cref="ArgumentNullException">if the container was null</exception> /// <exception cref="ArgumentException">if the container contains a bond which references an atom which could not be found</exception> public RingSearch(IAtomContainer container) : this(container, GraphUtil.ToAdjList(container)) { }
public int[] GetShortestHamiltonianCycle() { var cycles = GetAllHamiltorianCycles(); return(cycles.Count == 0 ? null : GraphUtil.ShortestRoute(weights, cycles)); }
protected override void VertexChange(object sender, VertexChangeEventArgs e) { if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "BaseEdge")) || (sender == Vertex.Get("BaseEdge:") && e.Type == VertexChangeType.ValueChanged) || ((sender == Vertex.Get("BaseEdge:")) && (e.Type == VertexChangeType.EdgeAdded) && ((GeneralUtil.CompareStrings(e.Edge.Meta.Value, "To"))))) { UpdateBaseEdge(); } if (sender == Vertex.Get(@"BaseEdge:\To:") && (e.Type == VertexChangeType.EdgeAdded || e.Type == VertexChangeType.EdgeRemoved)) { UpdateBaseEdge(); } if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "ToShowEdgesMeta"))) { UpdateBaseEdge(); } //if (sender == Vertex.Get(@"ToShowEdgesMeta:") && (e.Type == VertexChangeType.EdgeAdded || e.Type == VertexChangeType.EdgeRemoved)) // UpdateBaseEdge(); // there is update loop with this, so commenting out and leaving only what is above if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "SelectedEdges"))) { SelectedVertexesUpdated(); } if ((sender == Vertex.Get("SelectedEdges:")) && ((e.Type == VertexChangeType.EdgeAdded) || (e.Type == VertexChangeType.EdgeRemoved))) { SelectedVertexesUpdated(); } if (sender is IVertex && GraphUtil.FindEdgeByToVertex(Vertex.GetAll(@"SelectedEdges:\"), (IVertex)sender) != null) { SelectedVertexesUpdated(); } if (sender == Vertex.Get("IsMetaRightAlign:") && e.Type == VertexChangeType.ValueChanged) { ResetView(); } if (sender == Vertex.Get("IsAllVisualisersEdit:") && e.Type == VertexChangeType.ValueChanged) { ResetView(); } if (sender == Vertex.Get("ZoomVisualiserContent:") && e.Type == VertexChangeType.ValueChanged) { ChangeZoomVisualiserContent(); } if (sender == Vertex.Get("FilterQuery:") && e.Type == VertexChangeType.ValueChanged) { UpdateBaseEdge(); } if (sender == Vertex.Get("ExpertMode:") && e.Type == VertexChangeType.ValueChanged) { UpdateBaseEdge(); } if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "FilterQuery"))) { UpdateBaseEdge(); } if (sender == Vertex.Get("ShowHeader:") && e.Type == VertexChangeType.ValueChanged) { ResetView(); } if (sender == Vertex.Get("AlternatingRows:") && e.Type == VertexChangeType.ValueChanged) { ResetView(); } if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "ShowHeader"))) { ResetView(); } }
protected override void UpdateBaseEdge() { IVertex bas = Vertex.Get(@"BaseEdge:\To:"); if (bas != null) { ToShowEdgesMeta = null; if (Vertex.Get(@"ToShowEdgesMeta:\Meta:") != null) { ToShowEdgesMeta = Vertex.Get(@"ToShowEdgesMeta:\Meta:"); } if (ToShowEdgesMeta == null) // take first edge from BaseEdge\To, to have Meta as ToShowEdesMeta:\Meta:==null { IEdge e = bas.FirstOrDefault(); if (e != null) { ToShowEdgesMeta = e.Meta; VertexChangeListenOff(); Edge.AddEdgeEdges(Vertex.Get(@"ToShowEdgesMeta:"), e); VertexChangeListenOn(); } } if (ToShowEdgesMeta != null) { ((EasyVertex)Vertex.Get(@"FilterQuery:")).CanFireChangeEvent = false; Vertex.Get(@"FilterQuery:").Value = ToShowEdgesMeta.Value + ":"; ((EasyVertex)Vertex.Get(@"FilterQuery:")).CanFireChangeEvent = true; } if (Vertex.Get(@"FilterQuery:") != null && Vertex.Get(@"FilterQuery:").Value != null) // do the filtering { IVertex data = VertexOperations.DoFilter(bas, Vertex.Get(@"FilterQuery:")); if (data != null) { ThisDataGrid.ItemsSource = data.ToList(); } else { ThisDataGrid.ItemsSource = null; } } else { ThisDataGrid.ItemsSource = bas.ToList(); // if there is no .ToList DataGrid can not edit } if (GraphUtil.GetValueAndCompareStrings(Vertex.Get("ExpertMode:"), "True")) { ExpertMode = true; } else { ExpertMode = false; } ResetView(); } }
public void OnAfterDeserialize() { var nodes = SerializationHelper.Deserialize <AbstractMaterialNode>(m_SerializableNodes, GraphUtil.GetLegacyTypeRemapping()); m_Nodes.Clear(); foreach (var node in nodes) { m_Nodes.Add(node); } m_SerializableNodes = null; var edges = SerializationHelper.Deserialize <IEdge>(m_SerializableEdges, GraphUtil.GetLegacyTypeRemapping()); m_Edges.Clear(); foreach (var edge in edges) { m_Edges.Add(edge); } m_SerializableEdges = null; var inputs = SerializationHelper.Deserialize <ShaderInput>(m_SerilaizeableInputs, GraphUtil.GetLegacyTypeRemapping()); m_Inputs.Clear(); foreach (var input in inputs) { m_Inputs.Add(input); } m_SerilaizeableInputs = null; var metaProperties = SerializationHelper.Deserialize <AbstractShaderProperty>(m_SerializableMetaProperties, GraphUtil.GetLegacyTypeRemapping()); m_MetaProperties.Clear(); foreach (var metaProperty in metaProperties) { m_MetaProperties.Add(metaProperty); } m_SerializableMetaProperties = null; }
public void TestSerializationHelperElementCanSerialize() { var toSerialize = new List <SimpleSerializeClass>() { SimpleSerializeClass.instance }; var serialized = SerializationHelper.Serialize <SimpleSerializeClass>(toSerialize); Assert.AreEqual(1, serialized.Count); var container = new SerializationContainer { serializedElements = serialized }; var serializedContainer = JsonUtility.ToJson(container, true); var deserializedContainer = JsonUtility.FromJson <SerializationContainer>(serializedContainer); var loaded = SerializationHelper.Deserialize <SimpleSerializeClass>(deserializedContainer.serializedElements, GraphUtil.GetLegacyTypeRemapping()); Assert.AreEqual(1, loaded.Count); Assert.IsInstanceOf <SimpleSerializeClass>(loaded[0]); loaded[0].AssertAsReference(); }
public void OnAfterDeserialize() { var deserializedGraph = SerializationHelper.Deserialize <GraphData>(m_SerializedGraph, GraphUtil.GetLegacyTypeRemapping()); deserializedGraph.isSubGraph = m_IsSubGraph; if (graph == null) { graph = deserializedGraph; } else { m_DeserializedGraph = deserializedGraph; } }
public void TestSerializableSlotCanSerialize() { var toSerialize = new List <MaterialSlot>() { new TestSlot(0, "InSlot", SlotType.Input, 0), new TestSlot(1, "OutSlot", SlotType.Output, 5), }; var serialized = SerializationHelper.Serialize <MaterialSlot>(toSerialize); var loaded = SerializationHelper.Deserialize <MaterialSlot>(serialized, GraphUtil.GetLegacyTypeRemapping()); Assert.AreEqual(2, loaded.Count); Assert.IsInstanceOf <MaterialSlot>(loaded[0]); Assert.IsInstanceOf <MaterialSlot>(loaded[1]); Assert.AreEqual(0, loaded[0].id); Assert.AreEqual("InSlot", loaded[0].displayName); Assert.IsTrue(loaded[0].isInputSlot); Assert.AreEqual(0, loaded[0].priority); Assert.AreEqual(1, loaded[1].id); Assert.AreEqual("OutSlot", loaded[1].displayName); Assert.IsTrue(loaded[1].isOutputSlot); Assert.AreEqual(5, loaded[1].priority); }
// Use this for initialization void Start() { m_Graph = new GraphUtil(500, 250); m_CellCountLog = new List<int>(); m_CellMap = new GameObject[width * height]; for(int n = 0; n < m_CellMap.Length; ++n) { m_CellMap[n] = null; } for(int n = 0; n < width * height * first_cell_percent / 100; ++n) { int target = Random.Range(0, width * height - 1); if(m_CellMap[target] == null) { m_CellMap[target] = CreateNewCell(target % width, target / width, Quaternion.identity); } } }
internal static void AddCustomInterpolatorProperties(VisualElement parentElement, BlockNode node, Action setNodesAsDirtyCallback, Action updateNodeViewsCallback) { if (!node.isCustomBlock) { return; } TextField textField = null; { textField = new TextField { value = node.customName, multiline = false }; var propertyRow = new PropertyRow(new Label("Name")); propertyRow.Add(textField, (field) => { field.RegisterCallback <FocusOutEvent>(evt => { if (field.value.Equals(node.customName)) { return; } HashSet <string> usedNames = new HashSet <string>(); foreach (var other in node.contextData.blocks) { if (other != node) { usedNames.Add(other.value.descriptor.displayName); } } setNodesAsDirtyCallback?.Invoke(); node.owner.owner.RegisterCompleteObjectUndo("Change Block Name"); field.value = node.customName = GraphUtil.SanitizeName(usedNames, "{0}_{1}", NodeUtils.ConvertToValidHLSLIdentifier(field.value)); updateNodeViewsCallback?.Invoke(); node.Dirty(ModificationScope.Node); node.owner?.ValidateGraph(); }); }); parentElement.Add(propertyRow); } EnumField typeField = null; { typeField = new EnumField(node.customWidth); var propertyRow = new PropertyRow(new Label("Type")); propertyRow.Add(typeField, (field) => { field.RegisterValueChangedCallback(evt => { if (evt.newValue.Equals(node.customWidth)) { return; } setNodesAsDirtyCallback?.Invoke(); node.owner.owner.RegisterCompleteObjectUndo("Change Block Type"); node.customWidth = (BlockNode.CustomBlockType)evt.newValue; updateNodeViewsCallback?.Invoke(); node.Dirty(ModificationScope.Topological); node.owner?.ValidateGraph(); }); }); parentElement.Add(propertyRow); } }
static string GetExtraPassesFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions) { // ----------------------------------------------------- // // SETUP // // ----------------------------------------------------- // // ------------------------------------- // String builders var dummyBuilder = new ShaderStringBuilder(0); var shaderProperties = new PropertyCollector(); var functionBuilder = new ShaderStringBuilder(1); var functionRegistry = new FunctionRegistry(functionBuilder); var defines = new ShaderStringBuilder(2); var graph = new ShaderStringBuilder(0); var vertexDescriptionInputStruct = new ShaderStringBuilder(1); var vertexDescriptionStruct = new ShaderStringBuilder(1); var vertexDescriptionFunction = new ShaderStringBuilder(1); var vertexInputStruct = new ShaderStringBuilder(1); var vertexShader = new ShaderStringBuilder(2); var vertexDescriptionInputs = new ShaderStringBuilder(2); // ------------------------------------- // Get Slot and Node lists per stage var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var vertexNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); // ------------------------------------- // Get requirements var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false); var modelRequiements = ShaderGraphRequirements.none; modelRequiements.requiresNormal |= m_VertexCoordinateSpace; modelRequiements.requiresPosition |= m_VertexCoordinateSpace; modelRequiements.requiresMeshUVs.Add(UVChannel.UV1); // ----------------------------------------------------- // // START SHADER GENERATION // // ----------------------------------------------------- // // ------------------------------------- // Calculate material options var cullingBuilder = new ShaderStringBuilder(1); materialOptions.GetCull(cullingBuilder); // ------------------------------------- // Generate defines if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId)) { defines.AppendLine("#define _AlphaClip 1"); } // ----------------------------------------------------- // // START VERTEX DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Vertex Description function // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs"); using (vertexDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct); if (vertexRequirements.requiresVertexColor) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (vertexRequirements.requiresScreenPosition) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct()) { vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } } // ------------------------------------- // Generate Output structure for Vertex Description function GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots); // ------------------------------------- // Generate Vertex Description function GraphUtil.GenerateVertexDescriptionFunction( masterNode.owner as AbstractMaterialGraph, vertexDescriptionFunction, functionRegistry, shaderProperties, mode, vertexNodes, vertexSlots); // ----------------------------------------------------- // // GENERATE VERTEX > PIXEL PIPELINE // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Vertex shader GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(modelRequiements), vertexInputStruct); // ------------------------------------- // Generate standard transformations // This method ensures all required transform data is available in vertex and pixel stages ShaderGenerator.GenerateStandardTransforms( 3, 10, dummyBuilder, vertexShader, vertexDescriptionInputs, dummyBuilder, dummyBuilder, dummyBuilder, ShaderGraphRequirements.none, ShaderGraphRequirements.none, modelRequiements, vertexRequirements, CoordinateSpace.World); // ----------------------------------------------------- // // FINALIZE // // ----------------------------------------------------- // // ------------------------------------- // Combine Graph sections graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1)); graph.AppendLine(vertexDescriptionInputStruct.ToString()); graph.AppendLine(functionBuilder.ToString()); graph.AppendLine(vertexDescriptionStruct.ToString()); graph.AppendLine(vertexDescriptionFunction.ToString()); graph.AppendLine(vertexInputStruct.ToString()); // ------------------------------------- // Generate final subshader var resultPass = template.Replace("${Culling}", cullingBuilder.ToString()); resultPass = resultPass.Replace("${Defines}", defines.ToString()); resultPass = resultPass.Replace("${Graph}", graph.ToString()); resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString()); resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexDescriptionInputs.ToString()); return(resultPass); }
public void CreateBirdFormGos(bool posttransform = false) { Transform pvt = null; if (birdformgo != null) { pvt = birdformgo.transform; Destroy(birdformgo); birdformgo = null; } var shrink = 1f; if (posttransform) { // todo: we should probably be translating and rotating too // so we need to test shifted scenes (like when we do error correction) // with "change bird form" shrink = rman.rgoScale; } switch (birdform) { case BirdFormE.sphere: { var sphsize = shrink * 0.2f; birdformgo = GraphUtil.CreateMarkerSphere("sphere", Vector3.zero, size: sphsize, clr: "yellow"); break; } case BirdFormE.olive: { birdformgo = GraphUtil.CreateMarkerSphere("sphere", Vector3.zero, size: 0.2f, clr: "olive"); birdformgo.transform.localScale = shrink * (new Vector3(0.2f, 0.2f, 0.28f)); var nosept = shrink * (new Vector3(0, 0, 0.1f)); var gonose = GraphUtil.CreateMarkerSphere("nose", nosept, size: shrink * 0.1f, clr: "red"); gonose.transform.parent = birdformgo.transform; break; } default: case BirdFormE.hummingbird: { var objPrefab = (GameObject)Resources.Load("hummingbird"); birdformgo = Instantiate(objPrefab) as GameObject; var s = shrink * 0.5e-3f; var minscale = 0.1375f * s; // value experimentally discovered if (s * rman.rgoScale < minscale) { s = minscale / rman.rgoScale; } birdformgo.transform.localScale = new Vector3(s, s, s); break; } case BirdFormE.utahteapot: { var objPrefab = (GameObject)Resources.Load("teapot"); birdformgo = Instantiate(objPrefab) as GameObject; birdformgo.GetComponent <Renderer>().material.SetColor("_Color", GraphUtil.getcolorbyname("chinawhite")); var s = shrink * 60.0f; birdformgo.transform.localScale = new Vector3(s, s, s); birdformgo.transform.Rotate(0, 90, 0); break; } } var pt = birdgo.transform.position; var text = "Hummingbird\n" + pt; addFloatingText(birdgo, pt, text, "yellow"); if (posttransform) { //rman.GlobInvTransGo(birdformgo); //var s = rman.rgoScale; //birdformgo.transform.localScale = new Vector3(s, s, s); //birdformgo.transform.Rotate(0, rman.rgoRotate, 0); //birdformgo.transform.Translate(rman.rgoTranslate); } birdformgo.transform.parent = birdgo.transform; }
void getDepth() { GraphUtil.GetVertexDepths(_graph, SourceRO(), Depth); }
public void OnAfterDeserialize() { m_SourceGraphGuid = SerializationHelper.Deserialize <SerializableGuid>(m_SerializeableSourceGraphGuid, GraphUtil.GetLegacyTypeRemapping()); var nodes = SerializationHelper.Deserialize <INode>(m_SerializableNodes, GraphUtil.GetLegacyTypeRemapping()); m_Nodes.Clear(); foreach (var node in nodes) { m_Nodes.Add(node); } m_SerializableNodes = null; var edges = SerializationHelper.Deserialize <IEdge>(m_SerializableEdges, GraphUtil.GetLegacyTypeRemapping()); m_Edges.Clear(); foreach (var edge in edges) { m_Edges.Add(edge); } m_SerializableEdges = null; var properties = SerializationHelper.Deserialize <IShaderProperty>(m_SerilaizeableProperties, GraphUtil.GetLegacyTypeRemapping()); m_Properties.Clear(); foreach (var property in properties) { m_Properties.Add(property); } m_SerilaizeableProperties = null; var metaProperties = SerializationHelper.Deserialize <IShaderProperty>(m_SerializableMetaProperties, GraphUtil.GetLegacyTypeRemapping()); m_MetaProperties.Clear(); foreach (var metaProperty in metaProperties) { m_MetaProperties.Add(metaProperty); } m_SerializableMetaProperties = null; }
void AttachQuadImageToBackground() { DeactivateBackgroundImage(); var o = 0.5f; var w = Screen.width + 0.5f; var h = Screen.height + 0.5f; var gap = 0.1f; var zdist = cam.farClipPlane - gap; var pos = cam.transform.position; var pos00 = cam.ScreenToWorldPoint(new Vector3(o, o, zdist)); var pos01 = cam.ScreenToWorldPoint(new Vector3(o, h, zdist)); var pos10 = cam.ScreenToWorldPoint(new Vector3(w, o, zdist)); var pos11 = cam.ScreenToWorldPoint(new Vector3(w, h, zdist)); var poscn = cam.transform.position + cam.transform.forward * zdist; pos00 = Vector3.Lerp(pos, pos00, lamb); pos01 = Vector3.Lerp(pos, pos01, lamb); pos10 = Vector3.Lerp(pos, pos10, lamb); pos11 = Vector3.Lerp(pos, pos11, lamb); poscn = Vector3.Lerp(pos, poscn, lamb); quadgo = GameObject.CreatePrimitive(PrimitiveType.Quad); quadgo.transform.position = poscn; quadgo.transform.localRotation = camgo.transform.localRotation; quadgo.transform.parent = camgo.transform; quadgo.transform.localScale = new Vector3(Vector3.Magnitude(pos10 - pos00), Vector3.Magnitude(pos01 - pos00), 1); if (showSpheres) { var sgo00 = GraphUtil.CreateMarkerSphere("csph-00", pos00, 20, "purple"); sgo00.transform.parent = quadgo.transform; var sgo01 = GraphUtil.CreateMarkerSphere("csph-01", pos01, 20, "purple"); sgo01.transform.parent = quadgo.transform; var sgo10 = GraphUtil.CreateMarkerSphere("csph-10", pos10, 20, "purple"); sgo10.transform.parent = quadgo.transform; var sgo11 = GraphUtil.CreateMarkerSphere("csph-11", pos11, 20, "purple"); sgo11.transform.parent = quadgo.transform; var sgo = GraphUtil.CreateMarkerSphere("csph-cen", poscn, 30, "purple"); sgo.transform.parent = quadgo.transform; } bool addLight = false; if (addLight) { var lightob = new GameObject("quadlight"); var dlight = lightob.AddComponent <Light>(); dlight.type = LightType.Directional; lightob.transform.SetParent(quadgo.transform); lightob.transform.localRotation = Quaternion.Euler(66, 0, 0); } if (showBackground) { var tex = LoadImage(); var rend = quadgo.GetComponent <Renderer>(); rend.material.mainTexture = tex; } }
private static bool GenerateShaderPass(PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result) { var templateLocation = Path.Combine(Path.Combine(Path.Combine(HDEditorUtils.GetHDRenderPipelinePath(), "Editor"), "ShaderGraph"), pass.TemplateName); if (!File.Exists(templateLocation)) { // TODO: produce error here return(false); } // grab all of the active nodes var activeNodeList = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // graph requirements describe what the graph itself requires var graphRequirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.Fragment); ShaderStringBuilder graphNodeFunctions = new ShaderStringBuilder(); graphNodeFunctions.IncreaseIndent(); var functionRegistry = new FunctionRegistry(graphNodeFunctions); // Build the list of active slots based on what the pass requires // TODO: this can be a shared function -- From here through GraphUtil.GenerateSurfaceDescription(..) var activeSlots = new List <MaterialSlot>(); foreach (var id in pass.PixelShaderSlots) { MaterialSlot slot = masterNode.FindSlot <MaterialSlot>(id); if (slot != null) { activeSlots.Add(slot); } } // build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active) string graphInputStructName = "SurfaceDescriptionInputs"; string graphOutputStructName = "SurfaceDescription"; string graphEvalFunctionName = "SurfaceDescriptionFunction"; ShaderStringBuilder graphEvalFunction = new ShaderStringBuilder(); ShaderStringBuilder graphOutputs = new ShaderStringBuilder(); PropertyCollector graphProperties = new PropertyCollector(); // build the graph outputs structure, and populate activeFields with the fields of that structure HashSet <string> activeFields = new HashSet <string>(); GraphUtil.GenerateSurfaceDescriptionStruct(graphOutputs, activeSlots, true); //GraphUtil.GenerateSurfaceDescriptionStruct(graphOutputs, activeSlots, true, graphOutputStructName, activeFields); // Build the graph evaluation code, to evaluate the specified slots GraphUtil.GenerateSurfaceDescriptionFunction( activeNodeList, masterNode, masterNode.owner as AbstractMaterialGraph, graphEvalFunction, functionRegistry, graphProperties, graphRequirements, // TODO : REMOVE UNUSED mode, graphEvalFunctionName, graphOutputStructName, null, activeSlots, graphInputStructName); var blendCode = new ShaderStringBuilder(); var cullCode = new ShaderStringBuilder(); var zTestCode = new ShaderStringBuilder(); var zWriteCode = new ShaderStringBuilder(); var stencilCode = new ShaderStringBuilder(); var colorMaskCode = new ShaderStringBuilder(); HDSubShaderUtilities.BuildRenderStatesFromPassAndMaterialOptions(pass, materialOptions, blendCode, cullCode, zTestCode, zWriteCode, stencilCode, colorMaskCode); if (masterNode.twoSided.isOn) { activeFields.Add("DoubleSided"); if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system { // we need to be able to build interpolators using multiple input structs // also: should only require isFrontFace if Normals are required... activeFields.Add("DoubleSided.Mirror"); // TODO: change this depending on what kind of normal flip you want.. activeFields.Add("FragInputs.isFrontFace"); // will need this for determining normal flip mode } } if (pass.PixelShaderSlots != null) { foreach (var slotId in pass.PixelShaderSlots) { var slot = masterNode.FindSlot <MaterialSlot>(slotId); if (slot != null) { var rawSlotName = slot.RawDisplayName().ToString(); var descriptionVar = string.Format("{0}.{1}", graphOutputStructName, rawSlotName); activeFields.Add(descriptionVar); } } } var packedInterpolatorCode = new ShaderGenerator(); var graphInputs = new ShaderGenerator(); HDRPShaderStructs.Generate( packedInterpolatorCode, graphInputs, graphRequirements, pass.RequiredFields, CoordinateSpace.World, activeFields); // debug output all active fields var interpolatorDefines = new ShaderGenerator(); { interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:"); foreach (string f in activeFields) { interpolatorDefines.AddShaderChunk("// " + f); } } ShaderGenerator defines = new ShaderGenerator(); { defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true); if (pass.ExtraDefines != null) { foreach (var define in pass.ExtraDefines) { defines.AddShaderChunk(define); } } defines.AddGenerator(interpolatorDefines); } var shaderPassIncludes = new ShaderGenerator(); if (pass.Includes != null) { foreach (var include in pass.Includes) { shaderPassIncludes.AddShaderChunk(include); } } // build graph code var graph = new ShaderGenerator(); graph.AddShaderChunk("// Graph Inputs"); graph.Indent(); graph.AddGenerator(graphInputs); graph.Deindent(); graph.AddShaderChunk("// Graph Outputs"); graph.Indent(); graph.AddShaderChunk(graphOutputs.ToString()); //graph.AddGenerator(graphOutputs); graph.Deindent(); graph.AddShaderChunk("// Graph Properties (uniform inputs)"); graph.AddShaderChunk(graphProperties.GetPropertiesDeclaration(1)); graph.AddShaderChunk("// Graph Node Functions"); graph.AddShaderChunk(graphNodeFunctions.ToString()); graph.AddShaderChunk("// Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(graphEvalFunction.ToString()); //graph.AddGenerator(graphEvalFunction); graph.Deindent(); // build the hash table of all named fragments TODO: could make this Dictionary<string, ShaderGenerator / string> ? Dictionary <string, string> namedFragments = new Dictionary <string, string>(); namedFragments.Add("${Defines}", defines.GetShaderString(2, false)); namedFragments.Add("${Graph}", graph.GetShaderString(2, false)); namedFragments.Add("${LightMode}", pass.LightMode); namedFragments.Add("${PassName}", pass.Name); namedFragments.Add("${Includes}", shaderPassIncludes.GetShaderString(2, false)); namedFragments.Add("${InterpolatorPacking}", packedInterpolatorCode.GetShaderString(2, false)); namedFragments.Add("${Blending}", blendCode.ToString()); namedFragments.Add("${Culling}", cullCode.ToString()); namedFragments.Add("${ZTest}", zTestCode.ToString()); namedFragments.Add("${ZWrite}", zWriteCode.ToString()); namedFragments.Add("${Stencil}", stencilCode.ToString()); namedFragments.Add("${ColorMask}", colorMaskCode.ToString()); namedFragments.Add("${LOD}", materialOptions.lod.ToString()); namedFragments.Add("${VariantDefines}", GetVariantDefines(masterNode)); // process the template to generate the shader code for this pass TODO: could make this a shared function string[] templateLines = File.ReadAllLines(templateLocation); System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (string line in templateLines) { ShaderSpliceUtil.PreprocessShaderCode(line, activeFields, namedFragments, builder); builder.AppendLine(); } result.AddShaderChunk(builder.ToString(), false); return(true); }
static string GetShaderPassFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions) { // ----------------------------------------------------- // // SETUP // // ----------------------------------------------------- // // ------------------------------------- // String builders var shaderProperties = new PropertyCollector(); var functionBuilder = new ShaderStringBuilder(1); var functionRegistry = new FunctionRegistry(functionBuilder); var defines = new ShaderStringBuilder(1); var graph = new ShaderStringBuilder(0); var vertexDescriptionInputStruct = new ShaderStringBuilder(1); var vertexDescriptionStruct = new ShaderStringBuilder(1); var vertexDescriptionFunction = new ShaderStringBuilder(1); var surfaceDescriptionInputStruct = new ShaderStringBuilder(1); var surfaceDescriptionStruct = new ShaderStringBuilder(1); var surfaceDescriptionFunction = new ShaderStringBuilder(1); var vertexInputStruct = new ShaderStringBuilder(1); var vertexOutputStruct = new ShaderStringBuilder(2); var vertexShader = new ShaderStringBuilder(2); var vertexShaderDescriptionInputs = new ShaderStringBuilder(2); var vertexShaderOutputs = new ShaderStringBuilder(2); var pixelShader = new ShaderStringBuilder(2); var pixelShaderSurfaceInputs = new ShaderStringBuilder(2); var pixelShaderSurfaceRemap = new ShaderStringBuilder(2); // ------------------------------------- // Get Slot and Node lists per stage var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var vertexNodes = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var pixelNodes = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // ------------------------------------- // Get Requirements var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false); var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment); var graphRequirements = pixelRequirements.Union(vertexRequirements); var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); var modelRequiements = ShaderGraphRequirements.none; modelRequiements.requiresNormal |= k_PixelCoordinateSpace; modelRequiements.requiresTangent |= k_PixelCoordinateSpace; modelRequiements.requiresBitangent |= k_PixelCoordinateSpace; modelRequiements.requiresPosition |= k_PixelCoordinateSpace; modelRequiements.requiresViewDir |= k_PixelCoordinateSpace; modelRequiements.requiresMeshUVs.Add(UVChannel.UV1); // ----------------------------------------------------- // // START SHADER GENERATION // // ----------------------------------------------------- // // ------------------------------------- // Calculate material options var blendingBuilder = new ShaderStringBuilder(1); var cullingBuilder = new ShaderStringBuilder(1); var zTestBuilder = new ShaderStringBuilder(1); var zWriteBuilder = new ShaderStringBuilder(1); materialOptions.GetBlend(blendingBuilder); materialOptions.GetCull(cullingBuilder); materialOptions.GetDepthTest(zTestBuilder); materialOptions.GetDepthWrite(zWriteBuilder); // ------------------------------------- // Generate defines if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId)) { defines.AppendLine("#define _AlphaClip 1"); } if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply) { defines.AppendLine("#define _ALPHAPREMULTIPLY_ON 1"); } if (graphRequirements.requiresDepthTexture) { defines.AppendLine("#define REQUIRE_DEPTH_TEXTURE"); } if (graphRequirements.requiresCameraOpaqueTexture) { defines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE"); } // ----------------------------------------------------- // // START VERTEX DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Vertex Description function // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs"); using (vertexDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct); if (vertexRequirements.requiresVertexColor) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (vertexRequirements.requiresScreenPosition) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct()) { vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } } // ------------------------------------- // Generate Output structure for Vertex Description function GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots); // ------------------------------------- // Generate Vertex Description function GraphUtil.GenerateVertexDescriptionFunction( masterNode.owner as AbstractMaterialGraph, vertexDescriptionFunction, functionRegistry, shaderProperties, mode, vertexNodes, vertexSlots); // ----------------------------------------------------- // // START SURFACE DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Surface Description function // Surface Description Input requirements are needed to exclude intermediate translation spaces surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs"); using (surfaceDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct); if (surfaceRequirements.requiresVertexColor) { surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (surfaceRequirements.requiresScreenPosition) { surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } if (surfaceRequirements.requiresFaceSign) { surfaceDescriptionInputStruct.AppendLine("float {0};", ShaderGeneratorNames.FaceSign); } foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct()) { surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } } // ------------------------------------- // Generate Output structure for Surface Description function GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true); // ------------------------------------- // Generate Surface Description function GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, masterNode, masterNode.owner as AbstractMaterialGraph, surfaceDescriptionFunction, functionRegistry, shaderProperties, pixelRequirements, mode, "PopulateSurfaceData", "SurfaceDescription", null, pixelSlots); // ----------------------------------------------------- // // GENERATE VERTEX > PIXEL PIPELINE // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Vertex shader GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct); // ------------------------------------- // Generate standard transformations // This method ensures all required transform data is available in vertex and pixel stages ShaderGenerator.GenerateStandardTransforms( 3, 10, vertexOutputStruct, vertexShader, vertexShaderDescriptionInputs, vertexShaderOutputs, pixelShader, pixelShaderSurfaceInputs, pixelRequirements, surfaceRequirements, modelRequiements, vertexRequirements, CoordinateSpace.World); // ------------------------------------- // Generate pixel shader surface remap foreach (var slot in pixelSlots) { pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName); } // ------------------------------------- // Extra pixel shader work var faceSign = new ShaderStringBuilder(); if (pixelRequirements.requiresFaceSign) { faceSign.AppendLine(", half FaceSign : VFACE"); } // ----------------------------------------------------- // // FINALIZE // // ----------------------------------------------------- // // ------------------------------------- // Combine Graph sections graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1)); graph.AppendLine(vertexDescriptionInputStruct.ToString()); graph.AppendLine(surfaceDescriptionInputStruct.ToString()); graph.AppendLine(functionBuilder.ToString()); graph.AppendLine(vertexDescriptionStruct.ToString()); graph.AppendLine(vertexDescriptionFunction.ToString()); graph.AppendLine(surfaceDescriptionStruct.ToString()); graph.AppendLine(surfaceDescriptionFunction.ToString()); graph.AppendLine(vertexInputStruct.ToString()); // ------------------------------------- // Generate final subshader var resultPass = template.Replace("${Tags}", string.Empty); resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString()); resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString()); resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString()); resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString()); resultPass = resultPass.Replace("${Defines}", defines.ToString()); resultPass = resultPass.Replace("${Graph}", graph.ToString()); resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString()); resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString()); resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString()); resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString()); resultPass = resultPass.Replace("${FaceSign}", faceSign.ToString()); resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString()); return(resultPass); }
/// <summary> /// Calculates priority for atoms in a Molecule. /// </summary> /// <param name="mol">connected molecule</param> /// <seealso cref="Priority"/> internal static void Prioritise(IAtomContainer mol) { Prioritise(mol, GraphUtil.ToAdjList(mol)); }
ExportToNewMatrixWorkbook() { AssertValid(); // Merge duplicate edges and add an edge weight column. (new DuplicateEdgeMerger()).MergeDuplicateEdges(m_oWorkbookToExport); // Read the workbook, including the edge weight column. ReadWorkbookContext oReadWorkbookContext = new ReadWorkbookContext(); oReadWorkbookContext.ReadEdgeWeights = true; IGraph oGraph = (new WorkbookReader()).ReadWorkbook( m_oWorkbookToExport, oReadWorkbookContext); // Get an array of non-isolated vertices. Isolated vertices don't get // exported. List <IVertex> oNonIsolatedVertices = GraphUtil.GetNonIsolatedVertices(oGraph); Int32 iNonIsolatedVertices = oNonIsolatedVertices.Count; if (iNonIsolatedVertices == 0) { throw new ExportWorkbookException( "There are no edges to export." ); } Workbook oNewWorkbook = m_oWorkbookToExport.Application.Workbooks.Add(Missing.Value); Worksheet oNewWorksheet = (Worksheet)oNewWorkbook.ActiveSheet; // Fill in row 1 and column A with the vertex names, starting at B1 and // A2, respectively. String [,] asVertexNamesForRow1 = ExcelUtil.GetSingleRow2DStringArray( iNonIsolatedVertices); String [,] asVertexNamesForColumnA = ExcelUtil.GetSingleColumn2DStringArray(iNonIsolatedVertices); for (Int32 i = 0; i < iNonIsolatedVertices; i++) { asVertexNamesForRow1[1, i + 1] = asVertexNamesForColumnA[i + 1, 1] = oNonIsolatedVertices[i].Name; } ExcelUtil.SetRangeValues((Range)oNewWorksheet.Cells[1, 2], asVertexNamesForRow1); ExcelUtil.SetRangeValues((Range)oNewWorksheet.Cells[2, 1], asVertexNamesForColumnA); asVertexNamesForRow1 = asVertexNamesForColumnA = null; // Now fill in the edge weights, row by row. Range oFirstColumnCell = (Range)oNewWorksheet.Cells[2, 2]; for (Int32 i = 0; i < iNonIsolatedVertices; i++) { Object [,] aoEdgeWeights = ExcelUtil.GetSingleRow2DArray( iNonIsolatedVertices); IVertex oVertexI = oNonIsolatedVertices[i]; for (Int32 j = 0; j < iNonIsolatedVertices; j++) { aoEdgeWeights[1, j + 1] = EdgeUtil.GetEdgeWeight(oVertexI, oNonIsolatedVertices[j]); } ExcelUtil.SetRangeValues(oFirstColumnCell, aoEdgeWeights); oFirstColumnCell = oFirstColumnCell.get_Offset(1, 0); } return(oNewWorkbook); }
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"); // Friendly warning that the user is generating a subgraph that would overwrite the one they are currently working on. if (AssetDatabase.AssetPathToGUID(path) == selectedGuid) { if (!EditorUtility.DisplayDialog("Overwrite Current Subgraph", "Do you want to overwrite this Sub Graph that you are currently working on? You cannot undo this operation.", "Yes", "Cancel")) { path = ""; } } if (path.Length == 0) { return; } 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(); // Convert To Subgraph could create recursive reference loops if the target path already exists // Let's check for that here if (!string.IsNullOrEmpty(path)) { if (GraphUtil.CheckForRecursiveDependencyOnPendingSave(path, nodes.OfType <SubGraphNode>(), "Convert To SubGraph")) { return; } } graphObject.RegisterCompleteObjectUndo("Convert To Subgraph"); 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) != null) { 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 void TestPolymorphicSerializationPreservesTypesViaInterface() { var toSerialize = new List <ITestInterface>() { SimpleSerializeClass.instance, ChildClassA.instance, ChildClassB.instance }; var serialized = SerializationHelper.Serialize <ITestInterface>(toSerialize); Assert.AreEqual(3, serialized.Count); var loaded = SerializationHelper.Deserialize <SimpleSerializeClass>(serialized, GraphUtil.GetLegacyTypeRemapping()); Assert.AreEqual(3, loaded.Count); Assert.IsInstanceOf <SimpleSerializeClass>(loaded[0]); Assert.IsInstanceOf <ChildClassA>(loaded[1]); Assert.IsInstanceOf <ChildClassB>(loaded[2]); loaded[0].AssertAsReference(); loaded[1].AssertAsReference(); loaded[2].AssertAsReference(); }
private bool IsYieldingHeader(GraphUtil.Graph<Block> graph, Block header) { foreach (Block backEdgeNode in graph.BackEdgeNodes(header)) { foreach (Block x in graph.NaturalLoops(header, backEdgeNode)) { foreach (Cmd cmd in x.Cmds) { if (cmd is YieldCmd) return true; if (cmd is ParCallCmd) return true; CallCmd callCmd = cmd as CallCmd; if (callCmd == null) continue; if (callCmd.IsAsync || QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "yields")) return true; } } } return false; }