From 3aa63007d4a0cb8578b70104b3c6bb5fe5d91a96 Mon Sep 17 00:00:00 2001 From: Tim Kuhlmann Date: Thu, 17 Oct 2024 12:25:03 +0200 Subject: [PATCH 1/3] edge direction visualization via shader Implements a dedicated EdgeShader that handles color gradient. A vertex deformation effect can be configured and toggled that allows for a direction visualization. The effect depends on a correct UV mapping and uses the direction as present in our custom 3D edge meshes. The smoothness of the effect relies on several configurable parameters and the vertex density of the original mesh. --- .vscode/settings.json | 1 - .../TransparentEdgePortalMaterial.mat | 92 +++++++++++ .../TransparentEdgePortalMaterial.mat.meta | 8 + .../TransparentEdgePortalShader.shader | 127 +++++++++++++++ .../TransparentEdgePortalShader.shader.meta | 9 + .../Game/Operator/EdgeDirectionVisualizer.cs | 154 ------------------ .../Operator/EdgeDirectionVisualizer.cs.meta | 11 -- Assets/SEE/Game/Operator/EdgeOperator.cs | 7 +- Assets/SEE/GameObjects/Materials.cs | 24 ++- Assets/SEE/GameObjects/SEESpline.cs | 48 ++---- 10 files changed, 270 insertions(+), 211 deletions(-) create mode 100644 Assets/Resources/Materials/TransparentEdgePortalMaterial.mat create mode 100644 Assets/Resources/Materials/TransparentEdgePortalMaterial.mat.meta create mode 100644 Assets/Resources/Shaders/TransparentEdgePortalShader.shader create mode 100644 Assets/Resources/Shaders/TransparentEdgePortalShader.shader.meta delete mode 100644 Assets/SEE/Game/Operator/EdgeDirectionVisualizer.cs delete mode 100644 Assets/SEE/Game/Operator/EdgeDirectionVisualizer.cs.meta diff --git a/.vscode/settings.json b/.vscode/settings.json index f403e6761d..c34fed9d89 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -39,7 +39,6 @@ "**/*.asset": true, "**/*.cubemap": true, "**/*.flare": true, - "**/*.mat": true, "**/*.meta": true, "build/": true, "Build/": true, diff --git a/Assets/Resources/Materials/TransparentEdgePortalMaterial.mat b/Assets/Resources/Materials/TransparentEdgePortalMaterial.mat new file mode 100644 index 0000000000..4f16960992 --- /dev/null +++ b/Assets/Resources/Materials/TransparentEdgePortalMaterial.mat @@ -0,0 +1,92 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TransparentEdgePortalMaterial + m_Shader: {fileID: 4800000, guid: dcc192bee1ca9aa03b1851f89b0beff2, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AnimationFactor: 0.4 + - _AnimationPause: 0.4 + - _BumpScale: 1 + - _ColorGradientEnabled: 0 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _EdgeFlowEnabled: 0 + - _EffectWidth: 0.03 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _GrowthAmount: 0.005 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _EndColor: {r: 0, g: 0, b: 1, a: 1} + - _PortalMax: {r: 10, g: 10, b: 0, a: 0} + - _PortalMin: {r: -10, g: -10, b: 0, a: 0} + m_BuildTextureStacks: [] diff --git a/Assets/Resources/Materials/TransparentEdgePortalMaterial.mat.meta b/Assets/Resources/Materials/TransparentEdgePortalMaterial.mat.meta new file mode 100644 index 0000000000..d1a1b38ead --- /dev/null +++ b/Assets/Resources/Materials/TransparentEdgePortalMaterial.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9575ff8f0b08cd787bb1993d37b2c438 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Shaders/TransparentEdgePortalShader.shader b/Assets/Resources/Shaders/TransparentEdgePortalShader.shader new file mode 100644 index 0000000000..98f260478b --- /dev/null +++ b/Assets/Resources/Shaders/TransparentEdgePortalShader.shader @@ -0,0 +1,127 @@ +Shader "Unlit/SEE/TransparentEdgePortalShader" +{ + Properties + { + // Color + _Color("(Start) Color", color) = (1,0,0,1) + _EndColor("End Color", color) = (0,0,1,1) + _ColorGradientEnabled("Enable Color Gradient?", Range(0, 1)) = 0 // 0 = false, 1 = true + + // Data Flow + _EdgeFlowEnabled("Enable Data Flow Visualization?", Range(0, 1)) = 0 // 0 = false, 1 = true + _AnimationFactor("Animation Speed Factor", Range(0, 3)) = 0.4 + _AnimationPause("Pause Between Animations", Range(0, 3)) = 0.4 + _EffectWidth("Effect Width", Range(0, 1.0)) = 0.03 + _GrowthAmount("Growth Amount", Range(0, 0.04)) = 0.005 + + // Clipping + _PortalMin("Portal Left Front Corner", vector) = (-10, -10, 0, 0) + _PortalMax("Portal Right Back Corner", vector) = (10, 10, 0, 0) + } + SubShader + { + Tags { + "Queue"="Transparent" + "RenderType"="Transparent" + "IgnoreProjector"="True" + "ForceNoShadowCasting" = "True" + "PreviewType" = "Plane" + } + + // Alpha blending mode for transparency + Blend SrcAlpha OneMinusSrcAlpha + // Do not write to depth buffer to allow transparency effect + // Note: We will be able to see parts of the edge through other parts of the same edge, that should be occluded + // on full opacity. This is not a desired effect but not a big issue either. + ZWrite Off + // Makes the inside visible at clipping planes + Cull Off + // Unity's lighting will not be applied + Lighting Off + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float3 normal : NORMAL; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + float3 worldPos : TEXCOORD0; + float2 uv : TEXCOORD1; + }; + + // Color + fixed4 _Color; + fixed4 _EndColor; + float _ColorGradientEnabled; + + // Data Flow + float _EdgeFlowEnabled; + float _AnimationFactor; + float _AnimationPause; + float _EffectWidth; + float _GrowthAmount; + + // Clipping + float2 _PortalMin; + float2 _PortalMax; + + v2f vert (appdata v) + { + v2f o; + + if (_EdgeFlowEnabled > 0.5) + { + // The effect is supposed to move automatically based on the time and the animation factor. + // The position is calculated based on the assumption that the object has a uniform UV mapping (0.0 to 1.0 along the y axis). + // We stretch the effect scale by the effect width so that the effect fades in and out smoothly at both ends, respectively. + // Additionally, the effect scale is stretched to add a pause between the animations. + float effectPosition = frac(_Time.y * _AnimationFactor) * (1.0 + 2 * _EffectWidth + _AnimationPause) - _EffectWidth; + + // Distance between the vertex and the effect position on the y axis in world-space + float distance = abs(v.uv.y - effectPosition); + + if (distance < _EffectWidth) + { + // The effect strength is based on the distance to the effect position + float effectFactor = 1.0 - pow(distance / _EffectWidth, 3); + effectFactor = clamp(effectFactor, 0.0, 1.0); + // We use the direction of the normal to grow outward + float3 outwardDir = normalize(v.normal); + v.vertex.xyz += outwardDir * effectFactor * _GrowthAmount; + } + } + + o.vertex = UnityObjectToClipPos(v.vertex); + o.worldPos = mul(unity_ObjectToWorld, v.vertex); + o.uv = v.uv; + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + // Clipping + // Note: We use a 2D portal (x, y) that spans over a (x, z) plane in the Unity 3D space. + if (i.worldPos.x < _PortalMin.x || i.worldPos.x > _PortalMax.x || + i.worldPos.z < _PortalMin.y || i.worldPos.z > _PortalMax.y) + { + discard; + } + + return _ColorGradientEnabled > 0.5 ? lerp(_Color, _EndColor, i.uv.y) : _Color; + } + ENDCG + } + } +} diff --git a/Assets/Resources/Shaders/TransparentEdgePortalShader.shader.meta b/Assets/Resources/Shaders/TransparentEdgePortalShader.shader.meta new file mode 100644 index 0000000000..f3f61b89da --- /dev/null +++ b/Assets/Resources/Shaders/TransparentEdgePortalShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dcc192bee1ca9aa03b1851f89b0beff2 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SEE/Game/Operator/EdgeDirectionVisualizer.cs b/Assets/SEE/Game/Operator/EdgeDirectionVisualizer.cs deleted file mode 100644 index 7fcf3695ea..0000000000 --- a/Assets/SEE/Game/Operator/EdgeDirectionVisualizer.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System.Linq; -using MoreLinq; -using SEE.GO; -using SEE.Utils; -using UnityEngine; - -namespace SEE.Game.Operator -{ - /// - /// Provides the to the . - /// - public partial class EdgeOperator : GraphElementOperator<(Color start, Color end)> - { - /// - /// Implements a data flow visualization to indicate the direction of an edge. - /// - private class EdgeDirectionVisualizer : MonoBehaviour - { - /// - /// Maximal count of particles. - /// - private const int maxParticleCount = 12; - /// - /// Minimal distance between particles for the actual particle count. - /// - private const float minParticleDistance = 0.16f; - /// - /// Scale of the particle meshes. - /// - private static readonly Vector3 particleScale = new(0.012f, 0.012f, 0.012f); - /// - /// Color of the particle material. - /// - private static readonly Color particleColor = new(0.06f, 0.81f, 1.0f, 1.0f); - /// - /// Particle speed. - /// - private const float particleSpeed = 50f; - - /// - /// The spline the edge is based on. - /// - private SEESpline seeSpline; - /// - /// The coordinates of the edge's vertices. - /// - private Vector3[] vertices; - - /// - /// The actual particle count as calculated based on - /// and capped by . - /// - private int particleCount; - /// - /// The particle game objects. - /// - private GameObject[] particles; - /// - /// The current position of the particles. - /// - private float[] particlePositions; - - /// - /// Destroys the particles when the component is destroyed. - /// - private void OnDestroy() - { - foreach (GameObject particle in particles) - { - seeSpline.OnRendererChanged -= OnSplineChanged; - Destroyer.Destroy(particle); - } - } - - /// - /// Initializes the particles and fields. - /// - public void Start() - { - seeSpline = GetComponent(); - seeSpline.OnRendererChanged += OnSplineChanged; - vertices = seeSpline.GenerateVertices(); - - particleCount = (int)Mathf.Max(Mathf.Min(GetApproxEdgeLength() / minParticleDistance, maxParticleCount), 1); - - particles = new GameObject[particleCount]; - particlePositions = new float[particleCount]; - - float separation = vertices.Length / (float)particleCount; - for (int i = 0; i < particleCount; i++) - { - particles[i] = GameObject.CreatePrimitive(PrimitiveType.Sphere); - particles[i].GetComponent().material.color = particleColor; - particlePositions[i] = separation * i; - particles[i].transform.localScale = particleScale; - particles[i].transform.SetParent(transform); - particles[i].transform.localPosition = GetPositionOnEdge(particlePositions[i]); - } - } - - /// - /// Updates the position and color of the vertices. - /// - private void Update() - { - for (int i = 0; i < particleCount; i++) - { - particlePositions[i] += particleSpeed * Time.deltaTime; - if (particlePositions[i] >= vertices.Length) - { - particlePositions[i] = 0; - } - particles[i].transform.localPosition = GetPositionOnEdge(particlePositions[i]); - } - } - - /// - /// This callback is triggered whenever the spline has changed. - /// It will then re-calculate . - /// - private void OnSplineChanged() - { - vertices = seeSpline.GenerateVertices(); - } - - /// - /// Calculates the coordinate of the position on the edge by interpolating between two - /// neighboring vertices. - /// - /// The vertices of the edge are derived from the integer places of , - /// while the decimal places represent the progress between the two vertices. - /// - /// - /// The position on the edge between zero and - /// .Length - 1. - /// The coordinate of the position on the edge. - private Vector3 GetPositionOnEdge(float position) - { - if (position >= vertices.Length - 1) - { - return vertices[^1]; // last element - } - - return Vector3.Lerp(vertices[(int)position], vertices[(int)position + 1], position - (int)position); - } - - /// - /// Calculates the approximate length of the edge that is represented by . - /// - /// Approximate edge length. - private float GetApproxEdgeLength() => vertices.Pairwise(Vector3.Distance).Sum(); - } - } -} diff --git a/Assets/SEE/Game/Operator/EdgeDirectionVisualizer.cs.meta b/Assets/SEE/Game/Operator/EdgeDirectionVisualizer.cs.meta deleted file mode 100644 index 12a81a5756..0000000000 --- a/Assets/SEE/Game/Operator/EdgeDirectionVisualizer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b7e1e625e7090fca797f6b19f170fd2b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/SEE/Game/Operator/EdgeOperator.cs b/Assets/SEE/Game/Operator/EdgeOperator.cs index 1da8a02a23..4960ce88db 100644 --- a/Assets/SEE/Game/Operator/EdgeOperator.cs +++ b/Assets/SEE/Game/Operator/EdgeOperator.cs @@ -149,14 +149,13 @@ public IOperationCallback ShowOrHide(bool show, EdgeAnimationKind animat /// Enable or disable animation. public void AnimateDataFlow(bool enable = true) { - if (enable) + if (gameObject.TryGetComponent(out MeshRenderer meshRenderer)) { - gameObject.AddOrGetComponent(); + meshRenderer.material.SetFloat("_EdgeFlowEnabled", enable ? 1.0f : 0.0f); } else { - EdgeDirectionVisualizer edfv = gameObject.GetComponent(); - Destroyer.Destroy(edfv); + Debug.LogWarning($"No MeshRenderer found to enable data flow animation on: {gameObject.FullName()}"); } } diff --git a/Assets/SEE/GameObjects/Materials.cs b/Assets/SEE/GameObjects/Materials.cs index b52de084ac..9ee5db593b 100644 --- a/Assets/SEE/GameObjects/Materials.cs +++ b/Assets/SEE/GameObjects/Materials.cs @@ -19,12 +19,13 @@ public class Materials /// public enum ShaderType { - Opaque = 0, // fully drawn with no transparency - TransparentLine = 1, // for lines with transparency - OpaqueMetallic = 2, // for opaque meshes with a more realistic metallic effect - PortalFree = 3, // not limited by a portal (seen everywhere) - DrawableLine = 4, // for drawable lines - DrawableDashedLine = 5, // for drawable dashed lines + Opaque = 0, // fully drawn with no transparency + TransparentLine = 1, // for lines with transparency (LineRenderer) + TransparentEdge = 2, // for edge meshes with transparency (MeshRenderer) + OpaqueMetallic = 3, // for opaque meshes with a more realistic metallic effect + PortalFree = 4, // not limited by a portal (seen everywhere) + DrawableLine = 5, // for drawable lines + DrawableDashedLine = 6, // for drawable dashed lines } /// @@ -32,10 +33,14 @@ public enum ShaderType /// private const string opaqueMaterialName = "Materials/OpaquePortalMaterial"; /// - /// Name of the material for transparent lines (located in folder Resources). + /// Name of the material for transparent lines using LineRenderer (located in folder Resources). /// private const string transparentLineMaterialName = "Materials/TransparentLinePortalMaterial"; /// + /// Name of the material for transparent 3D edges (located in folder Resources). + /// + private const string transparentEdgeMaterialName = "Materials/TransparentEdgePortalMaterial"; + /// /// Name of the material for opaque, metallic meshes (located in folder Resources). /// private const string opaqueMetallicMaterialName = "Materials/SEEMaterial"; @@ -258,13 +263,16 @@ public static Material New(ShaderType shaderType, Color color, Texture texture = case ShaderType.TransparentLine: name = transparentLineMaterialName; break; + case ShaderType.TransparentEdge: + name = transparentEdgeMaterialName; + break; case ShaderType.OpaqueMetallic: name = opaqueMetallicMaterialName; break; case ShaderType.PortalFree: name = portalFreeMaterialName; break; - case ShaderType.DrawableLine: + case ShaderType.DrawableLine: name = drawableLineMaterialName; break; case ShaderType.DrawableDashedLine: diff --git a/Assets/SEE/GameObjects/SEESpline.cs b/Assets/SEE/GameObjects/SEESpline.cs index b4c5952ee6..3e27482644 100644 --- a/Assets/SEE/GameObjects/SEESpline.cs +++ b/Assets/SEE/GameObjects/SEESpline.cs @@ -283,7 +283,7 @@ public Material MeshMaterial private void Awake() { // Corresponds to the material of the LineRenderer. - defaultMaterial = Materials.New(Materials.ShaderType.TransparentLine, Color.white); + defaultMaterial = Materials.New(Materials.ShaderType.TransparentEdge, Color.white); defaultMaterial.renderQueue = (int)(RenderQueue.Transparent + 1); } @@ -515,18 +515,12 @@ private Mesh CreateOrUpdateMesh() // Set up the mesh components. Mesh mesh; // The mesh to work on. - bool updateMaterial; // Whether to call `UpdateMaterial'. + // Does this game object already have a mesh which we can reuse? if (gameObject.TryGetComponent(out MeshFilter filter)) { - // Does this game object already have a mesh which we can reuse? mesh = filter.mesh; - updateMaterial = // The geometrics of the mesh have changed. - mesh.vertices.Length != vertices.Length || - mesh.normals.Length != normals.Length || - mesh.tangents.Length != tangents.Length || - mesh.uv.Length != uvs.Length || - needsColorUpdate; // Or the color of the mesh has been changed. + mesh.Clear(); } else { @@ -535,14 +529,9 @@ private Mesh CreateOrUpdateMesh() mesh.MarkDynamic(); // May improve performance. filter = gameObject.AddComponent(); filter.sharedMesh = mesh; - updateMaterial = true; } // IMPORTANT: Set mesh vertices, normals, tangents etc. before updating the shared mesh of the collider. - if (updateMaterial) - { - mesh.Clear(); - } mesh.vertices = vertices; mesh.normals = normals; mesh.tangents = tangents; @@ -562,15 +551,10 @@ private Mesh CreateOrUpdateMesh() } meshRenderer = gameObject.AddOrGetComponent(); - if (updateMaterial) - { - // Needs the meshRenderer. - UpdateMaterial(); - } + UpdateMaterial(); if (gameObject.TryGetComponent(out LineRenderer lineRenderer)) { - // Remove line meshRenderer. Destroyer.Destroy(lineRenderer); } @@ -582,29 +566,27 @@ private Mesh CreateOrUpdateMesh() /// protected virtual void UpdateMaterial() { + if (meshRenderer == null) + { + Debug.LogWarning("Trying to update MeshRenderer material, but there is none!"); + return; + } + if (meshRenderer.sharedMaterial == null) { meshRenderer.sharedMaterial = defaultMaterial; Portal.SetPortal(transform.parent.parent.gameObject, gameObject); } - if (!gameObject.TryGetComponent(out MeshFilter filter) || meshRenderer == null) + if (meshRenderer.sharedMaterial.shader != defaultMaterial.shader) { + Debug.LogWarning("Cannot update MeshRenderer because the shader does not match!"); return; } - if (meshRenderer.sharedMaterial.shader == defaultMaterial.shader) - { - // Don't re-color non-default material. - Mesh mesh = filter.mesh; - Vector2[] uv = mesh.uv; - Color[] colors = new Color[uv.Length]; - for (int i = 0; i < uv.Length; i++) - { - colors[i] = Color.Lerp(gradientColors.start, gradientColors.end, uv[i].y); - } - mesh.colors = colors; - } + meshRenderer.material.SetColor("_Color", gradientColors.start); + meshRenderer.material.SetColor("_EndColor", gradientColors.end); + meshRenderer.material.SetFloat("_ColorGradientEnabled", 1.0f); } /// From 410ef78d6bc076d19c447d42ceb32ec1f4d3cfad Mon Sep 17 00:00:00 2001 From: Tim Kuhlmann Date: Mon, 21 Oct 2024 10:19:25 +0200 Subject: [PATCH 2/3] minor code improvements Implement changes suggested by reviewer @falko17. --- Assets/SEE/Game/Operator/EdgeOperator.cs | 11 +++++------ Assets/SEE/GameObjects/SEESpline.cs | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Assets/SEE/Game/Operator/EdgeOperator.cs b/Assets/SEE/Game/Operator/EdgeOperator.cs index 4960ce88db..4a8e433194 100644 --- a/Assets/SEE/Game/Operator/EdgeOperator.cs +++ b/Assets/SEE/Game/Operator/EdgeOperator.cs @@ -32,6 +32,9 @@ public partial class EdgeOperator : GraphElementOperator<(Color start, Color end /// private SEESpline spline; + /// Shader property that enables or disables the edge direction (data flow) animation. + private static readonly int EdgeFlowEnabledProperty = Shader.PropertyToID("_EdgeFlowEnabled"); + #region Public API /// @@ -149,13 +152,9 @@ public IOperationCallback ShowOrHide(bool show, EdgeAnimationKind animat /// Enable or disable animation. public void AnimateDataFlow(bool enable = true) { - if (gameObject.TryGetComponent(out MeshRenderer meshRenderer)) - { - meshRenderer.material.SetFloat("_EdgeFlowEnabled", enable ? 1.0f : 0.0f); - } - else + if (gameObject.TryGetComponentOrLog(out MeshRenderer meshRenderer)) { - Debug.LogWarning($"No MeshRenderer found to enable data flow animation on: {gameObject.FullName()}"); + meshRenderer.material.SetFloat(EdgeFlowEnabledProperty, enable ? 1.0f : 0.0f); } } diff --git a/Assets/SEE/GameObjects/SEESpline.cs b/Assets/SEE/GameObjects/SEESpline.cs index 3e27482644..d645aba3d0 100644 --- a/Assets/SEE/GameObjects/SEESpline.cs +++ b/Assets/SEE/GameObjects/SEESpline.cs @@ -277,6 +277,15 @@ public Material MeshMaterial } } + /// Shader property that defines the (start) color. + private static readonly int ColorProperty = Shader.PropertyToID("_Color"); + + /// Shader property that defines the end color of the color gradient. + private static readonly int EndColorProperty = Shader.PropertyToID("_EndColor"); + + /// Shader property that enables or disables the color gradient. + private static readonly int ColorGradientEnabledProperty = Shader.PropertyToID("_ColorGradientEnabled"); + /// /// Called by Unity when an instance of this class is being loaded. /// @@ -584,9 +593,9 @@ protected virtual void UpdateMaterial() return; } - meshRenderer.material.SetColor("_Color", gradientColors.start); - meshRenderer.material.SetColor("_EndColor", gradientColors.end); - meshRenderer.material.SetFloat("_ColorGradientEnabled", 1.0f); + meshRenderer.material.SetColor(ColorProperty, gradientColors.start); + meshRenderer.material.SetColor(EndColorProperty, gradientColors.end); + meshRenderer.material.SetFloat(ColorGradientEnabledProperty, 1.0f); } /// From da627b499199a3b14a815c6880acaf3ad6dbb1de Mon Sep 17 00:00:00 2001 From: Tim Kuhlmann Date: Wed, 23 Oct 2024 09:49:44 +0200 Subject: [PATCH 3/3] add missing summary tags Implement changes suggested by reviewer @falko17. --- Assets/SEE/Game/Operator/EdgeOperator.cs | 2 ++ Assets/SEE/GameObjects/SEESpline.cs | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Assets/SEE/Game/Operator/EdgeOperator.cs b/Assets/SEE/Game/Operator/EdgeOperator.cs index 4a8e433194..2ef6376d36 100644 --- a/Assets/SEE/Game/Operator/EdgeOperator.cs +++ b/Assets/SEE/Game/Operator/EdgeOperator.cs @@ -32,7 +32,9 @@ public partial class EdgeOperator : GraphElementOperator<(Color start, Color end /// private SEESpline spline; + /// /// Shader property that enables or disables the edge direction (data flow) animation. + /// private static readonly int EdgeFlowEnabledProperty = Shader.PropertyToID("_EdgeFlowEnabled"); #region Public API diff --git a/Assets/SEE/GameObjects/SEESpline.cs b/Assets/SEE/GameObjects/SEESpline.cs index d645aba3d0..03ef1349e1 100644 --- a/Assets/SEE/GameObjects/SEESpline.cs +++ b/Assets/SEE/GameObjects/SEESpline.cs @@ -277,13 +277,19 @@ public Material MeshMaterial } } + /// /// Shader property that defines the (start) color. + /// private static readonly int ColorProperty = Shader.PropertyToID("_Color"); + /// /// Shader property that defines the end color of the color gradient. + /// private static readonly int EndColorProperty = Shader.PropertyToID("_EndColor"); + /// /// Shader property that enables or disables the color gradient. + /// private static readonly int ColorGradientEnabledProperty = Shader.PropertyToID("_ColorGradientEnabled"); ///