// UnityEngine.UIElements.VectorImage is internal, so this method needs to be part of the internal bridge for now. internal static void MakeVectorImageAsset(IEnumerable <VectorUtils.Geometry> geoms, uint rasterSize, out UnityEngine.Object outAsset, out Texture2D outTexAtlas) { var atlas = VectorUtils.GenerateAtlas(geoms, rasterSize, false, false); if (atlas != null) { VectorUtils.FillUVs(geoms, atlas); } bool hasTexture = atlas != null && atlas.Texture != null; outTexAtlas = hasTexture ? atlas.Texture : null; var vertices = new List <VectorImageVertex>(100); var indices = new List <UInt16>(300); var settings = new List <GradientSettings>(); var min = new Vector2(float.MaxValue, float.MaxValue); var max = new Vector2(float.MinValue, float.MinValue); foreach (var geom in geoms) { if (geom.Vertices.Length == 0) { continue; } var b = VectorUtils.Bounds(geom.Vertices.Select(v => geom.WorldTransform.MultiplyPoint(v))); min = Vector2.Min(min, b.min); max = Vector2.Max(max, b.max); } var bounds = Rect.zero; if (min.x != float.MaxValue) { bounds = new Rect(min, max - min); } // Save written settings to avoid duplicates var writtenSettings = new HashSet <int>(); writtenSettings.Add(0); // Create a map of filling -> atlas entry var fillEntries = new Dictionary <IFill, VectorUtils.PackRectItem>(); if (atlas != null && atlas.Entries != null) { foreach (var entry in atlas.Entries) { if (entry.Fill != null) { fillEntries[entry.Fill] = entry; } } } if (hasTexture && atlas != null && atlas.Entries != null && atlas.Entries.Count > 0) { // Write the 'white' texel info var entry = atlas.Entries[atlas.Entries.Count - 1]; settings.Add(new GradientSettings() { gradientType = UnityEngine.UIElements.GradientType.Linear, addressMode = UnityEngine.UIElements.AddressMode.Wrap, radialFocus = Vector2.zero, location = new RectInt((int)entry.Position.x, (int)entry.Position.y, (int)entry.Size.x, (int)entry.Size.y) }); } foreach (var geom in geoms) { for (int i = 0; i < geom.Vertices.Length; ++i) { var v = geom.WorldTransform.MultiplyPoint(geom.Vertices[i]); v -= bounds.position; geom.Vertices[i] = v; } VectorUtils.AdjustWinding(geom.Vertices, geom.Indices, VectorUtils.WindingDir.CCW); var count = vertices.Count; for (int i = 0; i < geom.Vertices.Length; ++i) { Vector3 p = (Vector3)geom.Vertices[i]; p.z = Vertex.nearZ; vertices.Add(new VectorImageVertex() { position = p, uv = hasTexture ? geom.UVs[i] : Vector2.zero, tint = geom.Color, settingIndex = (uint)geom.SettingIndex }); } indices.AddRange(geom.Indices.Select(i => (UInt16)(i + count))); if (atlas != null && atlas.Entries != null && atlas.Entries.Count > 0) { VectorUtils.PackRectItem entry; if (geom.Fill == null || !fillEntries.TryGetValue(geom.Fill, out entry) || writtenSettings.Contains(entry.SettingIndex)) { continue; } writtenSettings.Add(entry.SettingIndex); var gradientType = GradientFillType.Linear; var radialFocus = Vector2.zero; var addressMode = AddressMode.Wrap; var gradientFill = geom.Fill as GradientFill; if (gradientFill != null) { gradientType = gradientFill.Type; radialFocus = gradientFill.RadialFocus; addressMode = gradientFill.Addressing; } var textureFill = geom.Fill as TextureFill; if (textureFill != null) { addressMode = textureFill.Addressing; } settings.Add(new GradientSettings() { gradientType = (UnityEngine.UIElements.GradientType)gradientType, addressMode = (UnityEngine.UIElements.AddressMode)addressMode, radialFocus = radialFocus, location = new RectInt((int)entry.Position.x, (int)entry.Position.y, (int)entry.Size.x, (int)entry.Size.y) }); } } var vectorImage = ScriptableObject.CreateInstance <VectorImage>(); vectorImage.vertices = vertices.ToArray(); vectorImage.indices = indices.ToArray(); vectorImage.atlas = outTexAtlas; vectorImage.settings = settings.ToArray(); vectorImage.size = bounds.size; outAsset = vectorImage; }