private static void RemoveBufferFromDict(LW_VertexBuffer buffer) { foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict) { LW_MaterialBuffer materialBuffer = kvp.Value; if (materialBuffer.vertexBuffers.Contains(buffer)) { int index = materialBuffer.vertexBuffers.IndexOf(buffer); if (!materialBuffer.emptyIndices.Contains(index)) { materialBuffer.emptyIndices.Push(index); } } } }
private static void RemoveGraphicFromDict(LW_Graphic graphic) { foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict) { LW_MaterialBuffer materialBuffer = kvp.Value; for (int i = 0; i < materialBuffer.vertexBuffers.Count; i++) { LW_VertexBuffer buffer = materialBuffer.vertexBuffers[i]; if (buffer.graphic == graphic) { if (!materialBuffer.emptyIndices.Contains(i)) { materialBuffer.emptyIndices.Push(i); } } } } }
public static void Clean() { s_LastMaterial = null; if (s_DirtyTextures.Count > 0) { while (s_DirtyTextures.Count > 0) { s_DirtyTextures.Pop().Apply(); } } if (s_MaterialPoolDirty) { #if UNITY_EDITOR || DEVELOPMENT if (s_DebugMaterialPool) { Debug.Log("Clean MaterialPool"); } #endif s_ToRemoveFromDict.Clear(); foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict) { Material poolMat = kvp.Key; LW_MaterialBuffer materialBuffer = kvp.Value; List <LW_VertexBuffer> vertexBuffers = materialBuffer.vertexBuffers; Stack <int> emptyIndices = materialBuffer.emptyIndices; if (poolMat == null || vertexBuffers.Count == 0 || emptyIndices.Count == vertexBuffers.Count) { s_ToRemoveFromDict.Add(poolMat); } else { bool removeMaterialFromDict = true; for (int i = 0; i < vertexBuffers.Count; i++) { if (emptyIndices.Contains(i)) { continue; } LW_VertexBuffer buffer = vertexBuffers[i]; if (buffer.isValid && MaterialMatchesBuffer(poolMat, buffer) && poolMat.renderQueue == buffer.renderQueue) { removeMaterialFromDict = false; } else { #if UNITY_EDITOR || DEVELOPMENT if (s_DebugMaterialPool) { Debug.Log("Cleaning MaterialPool: vBuffer: " + i); } #endif emptyIndices.Push(i); } } if (removeMaterialFromDict) { s_ToRemoveFromDict.Add(poolMat); } } } for (int i = 0; i < s_ToRemoveFromDict.Count; i++) { if (s_MaterialDict.ContainsKey(s_ToRemoveFromDict[i])) { s_MaterialDict.Remove(s_ToRemoveFromDict[i]); } } s_MaterialPoolDirty = false; } }
private static void RebuildStyleData(Material material, LW_MaterialBuffer materialBuffer, bool forceRebuild = false) { //Debug.Log("RebuildStyleData material: " + material.name); if (!(material != null && materialBuffer != null && materialBuffer.vertexBuffers != null && materialBuffer.isAdvancedShader && (forceRebuild || materialBuffer.isDirty))) { return; } List <LW_VertexBuffer> vertexBuffers = materialBuffer.vertexBuffers; Stack <int> emptyIndices = materialBuffer.emptyIndices; // Setup int width = s_GradientDataLength + s_GradientPrecision; int height = vertexBuffers.Count; bool hasChanged = false; bool rebuildAllRows = forceRebuild; Texture2D styleData = material.GetTexture("_StyleData") as Texture2D; // Resizing StyleData if (styleData != null) { if (styleData.height < height) { int oldHeight = styleData.height; int oldWidth = styleData.width; Color[] pixels = styleData.GetPixels(); styleData.Resize(width, height, TextureFormat.RGBAFloat, false); styleData.SetPixels(0, 0, oldWidth, oldHeight, pixels, 0); material.SetVector("_StyleDataSize", new Vector4(width, height, s_GradientDataLength, s_GradientPrecision)); hasChanged = true; } else if (styleData.height > height) { styleData = null; } } // Creating StyleData if (styleData == null) { styleData = new Texture2D(width, height, TextureFormat.RGBAFloat, false); styleData.hideFlags = HideFlags.DontSave; styleData.filterMode = FilterMode.Bilinear; styleData.wrapMode = TextureWrapMode.Clamp; styleData.anisoLevel = 0; material.SetTexture("_StyleData", styleData); material.SetVector("_StyleDataSize", new Vector4(width, height, s_GradientDataLength, s_GradientPrecision)); hasChanged = true; rebuildAllRows = true; } // Updating StyleData for (int i = 0; i < vertexBuffers.Count; i++) { int index = i; LW_VertexBuffer buffer = vertexBuffers[i]; if (buffer.isEmpty || emptyIndices.Contains(i) || (buffer.styleDataIndex == index && !buffer.style.isDirty && !rebuildAllRows)) { continue; } //Debug.Log("buffer.styleDataIndex = " + index); hasChanged = true; buffer.styleDataIndex = index; //LW_Graphic graphic = buffer.graphic; //LW_Canvas canvas = buffer.canvas; LW_PaintStyle style = buffer.style as LW_PaintStyle; float boundsMin = Mathf.Min(buffer.bounds.min.x, buffer.bounds.min.y); float boundsMax = Mathf.Max(buffer.bounds.max.x, buffer.bounds.max.y); float strokeJustification = -1; float strokeWidth = 0; float strokeLength = 0; float screenSpaceMiterLimit = 0; float caps = -1; float joins = -1; // Vertex Data if (style is LW_Stroke) { LW_Stroke stroke = style as LW_Stroke; strokeJustification = ((int)stroke.justification - 1); strokeWidth = stroke.MaxWidth(); strokeLength = buffer.totalLength; screenSpaceMiterLimit = stroke.screenSpace ? stroke.miterLimit : -stroke.miterLimit; caps = (int)stroke.linecap; joins = (int)stroke.linejoin; } if (style is LW_Fill) { strokeWidth = buffer.bounds.size.y; strokeLength = buffer.bounds.size.x; caps = (int)Linecap.Round; joins = (int)Linejoin.Round; } // Fragment Data Matrix4x4 gradTransform = style.gradientUnits == GradientUnits.objectBoundingBox ? style.BoundsToLocalMatrix(buffer.bounds) * style.gradientTransform * style.LocalToBoundsMatrix(buffer.bounds) : style.gradientTransform; Vector2 start = gradTransform.MultiplyPoint(style.gradientStart); Vector2 end = gradTransform.MultiplyPoint(style.gradientEnd); Vector2 gradientDirection = end - start; float gradAngle = Mathf.Atan2(gradientDirection.x, gradientDirection.y); float gradScale = gradientDirection.magnitude; styleData.SetPixel(0, index, new Color(screenSpaceMiterLimit, strokeJustification, strokeWidth, strokeLength)); styleData.SetPixel(1, index, new Color((int)style.uvMode, (int)style.gradientUnits, boundsMin, boundsMax)); styleData.SetPixel(2, index, new Color(start.x, start.y, (int)style.gradientSpreadMethod, (int)style.paintMode)); styleData.SetPixel(3, index, new Color(gradAngle, gradScale, caps, joins)); for (int p = 0; p < s_GradientPrecision + 1; p++) { float percentage = (float)p / (float)s_GradientPrecision; Color color = style.ColorAtPercentage(percentage); styleData.SetPixel(s_GradientDataLength + p, i, color); } } if (hasChanged) { if (!s_DirtyTextures.Contains(styleData)) { s_DirtyTextures.Push(styleData); } } materialBuffer.isDirty = false; }
public static Material Get(LW_VertexBuffer buffer) { if (!buffer.isValid) { return(null); } // Setup Material material = null; // Check for Custom Materials LW_PaintStyle style = buffer.style as LW_PaintStyle; if (style.material != null) { material = style.material; buffer.renderQueue = material.renderQueue; } else if (buffer.canvas.material != null) { material = buffer.canvas.material; buffer.renderQueue = material.renderQueue; } // Check Last Material and Update RenderQue If needed. if (material == null) { buffer.renderQueue = GetRenderQueue(buffer); if (s_LastMaterial != null && buffer.renderQueue < s_LastMaterial.renderQueue) { buffer.renderQueue = s_LastMaterial.renderQueue + 1; } if (s_LastMaterial != null && MaterialMatchesBuffer(s_LastMaterial, buffer)) { material = s_LastMaterial; } } // Check Material Dictionary for Match if (material == null) { foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict) { if (kvp.Key == null) { continue; } Material poolMat = kvp.Key; if (MaterialMatchesBuffer(poolMat, buffer) && poolMat.renderQueue == buffer.renderQueue) { material = kvp.Key; break; } } } // Check Material Dictionary for Unused Material if (material == null) { foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict) { if (kvp.Key == null) { continue; } Material poolMat = kvp.Key; List <LW_VertexBuffer> bufferList = kvp.Value.vertexBuffers; if (bufferList == null || bufferList.Count == 0 || (bufferList.Count == 1 && bufferList[0] == buffer)) { material = poolMat; MatchMaterialToBuffer(material, buffer); break; } } } // Create New Material if (material == null) { Shader shader = defaultShader; if (shader == null) { Debug.Log("LineWorks Shader: \"LineWorks/Default\" is Missing. Make sure required LineWorks Shader is included in the scene or in a Resources Folder. Using UI/Default shader but Vector Graphics may not display correctly."); shader = Shader.Find("UI/Default"); } material = new Material(shader); material.hideFlags = HideFlags.DontSave; material.name = string.Format("LineWorks Material {0}", s_MaterialNameCount++); MatchMaterialToBuffer(material, buffer); } //MatchMaterialToBuffer(material, buffer); // Add Material to Dictionary if needed. LW_MaterialBuffer materialBuffer = null; if (s_MaterialDict.ContainsKey(material)) { materialBuffer = s_MaterialDict[material]; List <LW_VertexBuffer> vertexBuffers = materialBuffer.vertexBuffers; Stack <int> emptyIndices = materialBuffer.emptyIndices; if (!vertexBuffers.Contains(buffer)) { if (emptyIndices.Count > 0) { vertexBuffers[emptyIndices.Pop()] = buffer; } else { vertexBuffers.Add(buffer); } buffer.styleDataIndex = -1; } } else { materialBuffer = new LW_MaterialBuffer(); materialBuffer.vertexBuffers.Add(buffer); s_MaterialDict.Add(material, materialBuffer); buffer.styleDataIndex = -1; } materialBuffer.isDirty = !buffer.isValid || buffer.style.isDirty || buffer.styleDataIndex == -1; materialBuffer.isLineWorksShader = material.shader.name.StartsWith("LineWorks"); materialBuffer.isAdvancedShader = materialBuffer.isLineWorksShader && material.IsKeywordEnabled("_ADVANCED_ON"); // Finish s_LastMaterial = material; return(material); }