using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; [SelectionBase] public class IsoHandler : MonoBehaviour { private HashSet<IsoItem> items = new HashSet<IsoItem>(); private List<IsoItem> spriteList = new List<IsoItem>(); private List<IsoItem> objectList = new List<IsoItem>(); private List<IsoItem> allList = new List<IsoItem>(); private Camera mainCamera; public int ChunksX = 40; public int ChunksY = 40; private int numChunks; private List<List<IsoItem>> chunks; // Use this for initialization void Start() { numChunks = ChunksX * ChunksY; mainCamera = GameObject.Find("Main Camera").GetComponent<Camera>(); mainCamera.transparencySortMode = TransparencySortMode.Orthographic; chunks = new List<List<IsoItem>>(); for (int i = 0; i < numChunks; i++) { chunks.Add(new List<IsoItem>()); } } public void AddIsoItem(IsoItem item) { if (items.Add(item)) { if (item.IsoType == IsoItem.IsoTypes.Sprite) { spriteList.Add(item); } else { objectList.Add(item); } allList.Add(item); } } public void RemoveIsoItem(IsoItem item) { if (items.Remove(item)) { if (item.IsoType == IsoItem.IsoTypes.Sprite) { spriteList.Remove(item); } else { objectList.Remove(item); } allList.Remove(item); } } int ItemSort(IsoItem a, IsoItem b) { float diff = b.CameraSpace.z - a.CameraSpace.z; if (diff > 0) return 1; if (diff < 0) return -1; return 0; } private float nextDepth = 0; private Vector3 camForward; private Vector3 camRight; private Vector3 camUp; private Vector3 camPos; private List<IsoItem> ordered = new List<IsoItem>(); //private HashSet<int> usedChunks = new HashSet<int>(); void LateUpdate() { camForward = mainCamera.transform.forward; camRight = mainCamera.transform.right; camUp = mainCamera.transform.up; camPos = mainCamera.transform.position; float worldSizeH = mainCamera.orthographicSize * 2; float worldSizeW = worldSizeH * mainCamera.aspect; Vector3 worldBottomLeft = mainCamera.ViewportToWorldPoint(new Vector3()); //remaining.Clear(); ordered.Clear(); nextDepth = 10; for (int i = 0; i < spriteList.Count; i++) { spriteList[i].Behind.Clear(); spriteList[i].MarkTemp = false; spriteList[i].MarkPerm = false; //remaining.Add(spriteList[i]); } for (int i = 0; i < objectList.Count; i++) { objectList[i].Behind.Clear(); objectList[i].MarkTemp = false; objectList[i].MarkPerm = false; //remaining.Add(objectList[i]); } Ray outRay = new Ray(); outRay.direction = camForward; Ray inRay = new Ray(); inRay.direction = -camForward; int layerIn = LayerMask.GetMask("iso_piece", "leaf", "player_controller"); int layerOut = LayerMask.GetMask("iso_piece"); RaycastHit hitInfo = new RaycastHit(); //usedChunks.Clear(); int count = spriteList.Count; for (int i = 0; i < count; i++) { IsoItem item = spriteList[i]; Vector3 screenSpace = mainCamera.WorldToViewportPoint(item.transform.position); //item.CameraSpace.x = worldBottomLeft.x + screenSpace.x * worldSizeW; //item.CameraSpace.y = worldBottomLeft.y + screenSpace.y * worldSizeH; //item.CameraSpace.z = screenSpace.z; item.CameraSpace = screenSpace; /* if (item.IsoRadius > 0) { float scale = 1; // Mathf.Max(item.LinkedImage.transform.lossyScale.x, Mathf.Max(item.LinkedImage.transform.lossyScale.y, item.LinkedImage.transform.lossyScale.z)); float radiusCamX = item.IsoRadius / worldSizeW * scale; float radiusCamY = item.IsoRadius / worldSizeH * scale; int leftBucket = Mathf.Max(0, Mathf.Min(ChunksX - 1, (int)Mathf.Floor((screenSpace.x - radiusCamX) * ChunksX))); int rightBucket = Mathf.Max(0, Mathf.Min(ChunksX - 1, (int)Mathf.Ceil((screenSpace.x + radiusCamX) * ChunksX))); int bottomBucket = Mathf.Max(0, Mathf.Min(ChunksY - 1, (int)Mathf.Floor((screenSpace.y - radiusCamY) * ChunksY))); int topBucket = Mathf.Max(0, Mathf.Min(ChunksY - 1, (int)Mathf.Ceil((screenSpace.y + radiusCamY) * ChunksY))); for (int x = leftBucket; x <= rightBucket; x++) { for (int y = bottomBucket; y <= topBucket; y++) { int chunkIndex = y * ChunksX + x; List<IsoItem> chunk = chunks[chunkIndex]; bool placed = false; for (var j = 0; j < chunk.Count; j++) { if (item.CameraSpace.z > chunk[j].CameraSpace.z) { chunk.Insert(j, item); placed = true; break; } } if (!placed) { chunk.Add(item); } //usedChunks.Add(chunkIndex); } } } */ //if (item.Moved) //{ outRay.origin = inRay.origin = item.transform.position; bool hit = Physics.Raycast(inRay, out hitInfo, item.CameraSpace.z, layerIn); //if (hit && hitInfo.collider.transform.IsChildOf(item.transform)) //{ // inRay.origin += inRay.direction * hitInfo.distance * 1.1f; // hit = Physics.Raycast(inRay, out hitInfo, item.CameraSpace.z, layerIn); //} if (hit) { IsoItem otherItem = hitInfo.collider.GetComponentInParent<IsoItem>(); if (otherItem != null) { item.Behind.Add(otherItem); } } hit = Physics.Raycast(outRay, out hitInfo, 50, layerIn); //if (hit && hitInfo.collider.transform.IsChildOf(item.transform)) //{ // outRay.origin += outRay.direction * hitInfo.distance * 1.1f; // hit = Physics.Raycast(inRay, out hitInfo, item.CameraSpace.z, layerIn); //} if (hit) { IsoItem otherItem = hitInfo.collider.GetComponentInParent<IsoItem>(); if (otherItem != null) { otherItem.Behind.Add(item); } } //} } /* //foreach (int i in usedChunks) //{ for (int i = 0; i < numChunks; i++) { List<IsoItem> chunk = chunks[i]; for (int j = 0; j < chunk.Count - 1; j++) { chunk[j].Behind.Add(chunk[j + 1]);/ } chunk.Clear(); } */ for (int i = 0; i < objectList.Count; i++) { IsoItem item = objectList[i]; item.CameraSpace = mainCamera.WorldToViewportPoint(item.LinkedImage.transform.position); } objectList.Sort(ItemSort); for (int i = 0; i < objectList.Count - 1; i++) { objectList[i].Behind.Add(objectList[i + 1]); } int nextUnmarked = 0; int total = allList.Count; while (nextUnmarked < total) { IsoItem item = allList[nextUnmarked]; Visit(item); nextUnmarked++; while (nextUnmarked < total && allList[nextUnmarked].MarkPerm) { nextUnmarked++; } } } private void Visit(IsoItem item) { if (item.MarkPerm) return; if (item.MarkTemp) { Debug.LogError("CYCLICAL RENDER GRAPH"); item.MarkTemp = false; item.MarkPerm = true; //remaining.Remove(item); return; } item.MarkTemp = true; //for (int i = 0; i < item.Behind.Count; i++) //{ // Visit(item.Behind[i]); //} foreach (IsoItem nextItem in item.Behind) { Visit(nextItem); } item.MarkTemp = false; item.MarkPerm = true; //remaining.Remove(item); item.SetDepth = nextDepth; Vector3 camPos = item.CameraSpace; camPos.z = nextDepth; item.LinkedImage.transform.position = mainCamera.ViewportToWorldPoint(camPos); nextDepth += 0.01f; } }