using System.Collections.Generic; using System.Linq; using UnityEngine; public class SeparateFlatMarkerDrawer : MonoBehaviour { public OnlineMapsTileSetControl control; private void Start() { if (!control) control = OnlineMapsTileSetControl.instance; control.markerDrawer = new Drawer(control); } public class Drawer : OnlineMapsMarker2DDrawer { public Transform container; public OnlineMapsTileSetControl control; private Dictionary items = new Dictionary(); public Drawer(OnlineMapsTileSetControl control) { map = control.map; this.control = control; control.OnDrawMarkers += OnDrawMarkers; container = new GameObject("Markers").transform; container.SetParent(control.transform, false); } private void DestroyUnused() { List markersToRemove = new List(); foreach (var pair in items) { if (pair.Value.used) continue; pair.Value.Destroy(); markersToRemove.Add(pair.Key); } foreach (OnlineMapsMarker marker in markersToRemove) items.Remove(marker); } public override void Dispose() { base.Dispose(); foreach (var pair in items) pair.Value.Destroy(); Destroy(container.gameObject); control.OnDrawMarkers -= OnDrawMarkers; control = null; items = null; } private void OnDrawMarkers() { OnlineMapsMarkerManager markerManager = control.markerManager; if (!markerManager) return; double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); if (brx < tlx) brx += 360; double mx, my; var markers = markerManager.items.Where(m => { m.GetPosition(out mx, out my); bool a = my > tly || my < bry || ( (mx < tlx || mx > brx) && (mx + 360 < tlx || mx + 360 > brx) && (mx - 360 < tlx || mx - 360 > brx) ); return !a; }); markers = markers.OrderByDescending(m => { m.GetPosition(out mx, out my); return my; }); foreach (var pair in items) { pair.Value.used = false; } int index = 1; foreach (OnlineMapsMarker marker in markers) { Item item; if (!items.TryGetValue(marker, out item)) { item = new Item(this, marker); items[marker] = item; } item.used = true; item.Draw(index++); } DestroyUnused(); } } private class Item { private static Vector3[] markersVertices = new Vector3[4]; public bool used; private GameObject instance; private MeshRenderer meshRenderer; private Mesh mesh; private OnlineMapsMarker marker; private Texture texture; private Drawer drawer; private Material material; private Texture currentTexture { get { if (marker.texture) return marker.texture; return drawer.control.markerManager.defaultTexture; } } public Item(Drawer drawer, OnlineMapsMarker marker) { this.drawer = drawer; this.marker = marker; instance = new GameObject("Marker"); instance.transform.SetParent(drawer.container, false); InitMaterial(); InitMesh(); } public void Destroy() { Object.Destroy(instance); drawer = null; instance = null; meshRenderer = null; mesh = null; marker = null; texture = null; } public void Draw(int index) { if (marker == null) return; bool updateMesh = false; Texture ct = currentTexture; if (texture != ct) { meshRenderer.sharedMaterial.mainTexture = texture = ct; updateMesh = true; } if (updateMesh) UpdateMesh(); material.renderQueue = index + 3100; double lng, lat; marker.GetPosition(out lng, out lat); Transform t = instance.transform; t.position = drawer.control.GetWorldPosition(lng, lat) + new Vector3(0, index / 10f, 0); t.rotation = Quaternion.Euler(0, marker.rotation * 360, 0); t.localScale = Vector3.one * marker.scale; } private void InitMaterial() { meshRenderer = instance.AddComponent(); if (drawer.control.markerMaterial) material = Instantiate(drawer.control.markerMaterial); else material = new Material(drawer.control.markerShader); texture = currentTexture; material.mainTexture = texture; meshRenderer.sharedMaterial = material; } private void InitMesh() { MeshFilter meshFilter = instance.AddComponent(); mesh = new Mesh(); mesh.MarkDynamic(); meshFilter.mesh = mesh; Vector3[] normals = {Vector3.up, Vector3.up, Vector3.up, Vector3.up}; Vector2[] uv = {new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1)}; int[] triangles = {0, 1, 2, 0, 2, 3}; mesh.SetVertices(markersVertices); mesh.normals = normals; mesh.uv = uv; mesh.triangles = triangles; UpdateMesh(); } private void UpdateMesh() { Texture ct = currentTexture; Vector2 o = marker.GetAlignOffset(); Vector2 p1 = new Vector2(-o.x, -o.y); Vector2 p2 = new Vector2(-o.x + ct.width, -o.y + ct.height); markersVertices[3] = new Vector3(p1.x, 0, p1.y); markersVertices[2] = new Vector3(p2.x, 0, p1.y); markersVertices[1] = new Vector3(p2.x, 0, p2.y); markersVertices[0] = new Vector3(p1.x, 0, p2.y); mesh.SetVertices(markersVertices); } } }