using UnityEngine; using System.Collections.Generic; #if UNITY_5_5_OR_NEWER using UnityEngine.Profiling; #endif namespace IsoTools.Internal { public class IsoScreenSolver { Vector2 _minIsoXY = Vector2.zero; IsoAssocList _curVisibles = new IsoAssocList(); IsoAssocList _oldVisibles = new IsoAssocList(); IsoGrid _visibleGrid = new IsoGrid(new IsoGridItemAdapter(), 47); IsoGridLookUpper _gridLookUpper = new IsoGridLookUpper(); List _tmpRenderers = new List(); // --------------------------------------------------------------------- // // IsoGridItemAdapter // // --------------------------------------------------------------------- class IsoGridItemAdapter : IsoGrid.IItemAdapter { public IsoRect GetBounds(IsoObject item) { return item.Internal.ScreenBounds; } public void SetMinMaxCells(IsoObject item, IsoPoint2 min, IsoPoint2 max) { item.Internal.MinGridCell = min; item.Internal.MaxGridCell = max; } public void GetMinMaxCells(IsoObject item, ref IsoPoint2 min, ref IsoPoint2 max) { min = item.Internal.MinGridCell; max = item.Internal.MaxGridCell; } } // --------------------------------------------------------------------- // // IsoGridLookUpper // // --------------------------------------------------------------------- class IsoGridLookUpper : IsoGrid.ILookUpper { IsoObject _isoObject; public void LookUp(IsoList items) { LookUpSectorDepends(_isoObject, items); LookUpSectorRDepends(_isoObject, items); } public void Setup(IsoObject iso_object) { _isoObject = iso_object; } public void Reset() { _isoObject = null; } } // --------------------------------------------------------------------- // // Properties // // --------------------------------------------------------------------- public Vector2 minIsoXY { get { return _minIsoXY; } } public IsoAssocList curVisibles { get { return _curVisibles; } } public IsoAssocList oldVisibles { get { return _oldVisibles; } } // --------------------------------------------------------------------- // // Callbacks // // --------------------------------------------------------------------- public void OnAddInstance(IsoObject iso_object) { } public void OnRemoveInstance(IsoObject iso_object) { _oldVisibles.Remove(iso_object); _curVisibles.Remove(iso_object); ClearIsoObjectDepends(iso_object); } public bool OnMarkDirtyInstance(IsoObject iso_object) { if ( !iso_object.Internal.Dirty && _curVisibles.Contains(iso_object) ) { iso_object.Internal.Dirty = true; return true; } return false; } #if UNITY_EDITOR public void OnDrawGizmos(IsoWorld iso_world) { /* for ( int y = 0, ye = (int)_sectorsNumPosCount.y; y < ye; ++y ) { for ( int x = 0, xe = (int)_sectorsNumPosCount.x; x < xe; ++x ) { var sector = FindSector((float)x, (float)y); if ( sector != null && sector.objects.Count > 0 ) { var rect = new IsoRect( (x * _sectorsSize), (y * _sectorsSize), (x * _sectorsSize) + _sectorsSize, (y * _sectorsSize) + _sectorsSize); rect.Translate(_sectorsMinNumPos * _sectorsSize); IsoUtils.DrawRect(rect, Color.blue); } }}*/ } #endif // --------------------------------------------------------------------- // // Functions // // --------------------------------------------------------------------- public void StepSortingAction(IsoWorld iso_world, IsoAssocList instances) { Profiler.BeginSample("ResolveVisibles"); ResolveVisibles(instances); Profiler.EndSample(); Profiler.BeginSample("ResolveVisibleGrid"); ResolveVisibleGrid(iso_world); Profiler.EndSample(); } public void PostStepSortingAction() { _tmpRenderers.Clear(); } public void Clear() { _curVisibles.Clear(); _oldVisibles.Clear(); _visibleGrid.ClearGrid(); } public void SetupIsoObjectDepends(IsoObject iso_object) { ClearIsoObjectDepends(iso_object); _gridLookUpper.Setup(iso_object); _visibleGrid.LookUpCells( iso_object.Internal.MinGridCell, iso_object.Internal.MaxGridCell, _gridLookUpper); _gridLookUpper.Reset(); } public void ClearIsoObjectDepends(IsoObject iso_object) { var their_depends = iso_object.Internal.TheirDepends; for ( int i = 0, e = their_depends.Count; i < e; ++i ) { var their_iso_object = their_depends[i]; if ( !their_iso_object.Internal.Dirty ) { their_iso_object.Internal.SelfDepends.Remove(iso_object); } } iso_object.Internal.SelfDepends.Clear(); iso_object.Internal.TheirDepends.Clear(); } // --------------------------------------------------------------------- // // ResolveVisibles // // --------------------------------------------------------------------- void ResolveVisibles(IsoAssocList instances) { _oldVisibles.Clear(); if ( instances.Count > 0 ) { _minIsoXY.Set(float.MaxValue, float.MaxValue); for ( int i = 0, e = instances.Count; i < e; ++i ) { var iso_object = instances[i]; var object_pos = iso_object.position; if ( _minIsoXY.x > object_pos.x ) { _minIsoXY.x = object_pos.x; } if ( _minIsoXY.y > object_pos.y ) { _minIsoXY.y = object_pos.y; } if ( !IsoUtils.Vec2Approximately( iso_object.Internal.LastTrans, iso_object.Internal.Transform.position) ) { iso_object.FixIsoPosition(); } if ( IsIsoObjectVisible(iso_object) ) { iso_object.Internal.Placed = false; _oldVisibles.Add(iso_object); } } } else { _minIsoXY.Set(0.0f, 0.0f); } var temp_visibles = _curVisibles; _curVisibles = _oldVisibles; _oldVisibles = temp_visibles; } bool IsIsoObjectVisible(IsoObject iso_object) { var renderers = GetIsoObjectRenderers(iso_object); for ( int i = 0, e = renderers.Count; i < e; ++i ) { if ( renderers[i].isVisible ) { return true; } } return false; } List GetIsoObjectRenderers(IsoObject iso_object) { if ( iso_object.cacheRenderers ) { return iso_object.Internal.Renderers; } else { iso_object.GetComponentsInChildren(_tmpRenderers); return _tmpRenderers; } } // --------------------------------------------------------------------- // // ResolveVisibleGrid // // --------------------------------------------------------------------- void ResolveVisibleGrid(IsoWorld iso_world) { _visibleGrid.ClearItems(); for ( int i = 0, e = _curVisibles.Count; i < e; ++i ) { var iso_object = _curVisibles[i]; _visibleGrid.AddItem(iso_object); } var min_sector_size = IsoUtils.Vec2MaxF( iso_world.IsoToScreen(IsoUtils.vec3OneXY) - iso_world.IsoToScreen(Vector3.zero)); _visibleGrid.RebuildGrid(min_sector_size); } // --------------------------------------------------------------------- // // LookUpSectorDepends // // --------------------------------------------------------------------- static void LookUpSectorDepends(IsoObject obj_a, IsoList others) { for ( int i = 0, e = others.Count; i < e; ++i ) { var obj_b = others[i]; if ( obj_a != obj_b && !obj_b.Internal.Dirty && IsIsoObjectDepends(obj_a, obj_b) ) { obj_a.Internal.SelfDepends.Add(obj_b); obj_b.Internal.TheirDepends.Add(obj_a); } } } static void LookUpSectorRDepends(IsoObject obj_a, IsoList others) { for ( int i = 0, e = others.Count; i < e; ++i ) { var obj_b = others[i]; if ( obj_a != obj_b && !obj_b.Internal.Dirty && IsIsoObjectDepends(obj_b, obj_a) ) { obj_b.Internal.SelfDepends.Add(obj_a); obj_a.Internal.TheirDepends.Add(obj_b); } } } static bool IsIsoObjectDepends(IsoObject a, IsoObject b) { return a.Internal.ScreenBounds.Overlaps(b.Internal.ScreenBounds) && IsIsoObjectDepends(a.position, a.size, b.position, b.size); } static bool IsIsoObjectDepends(Vector3 a_min, Vector3 a_size, Vector3 b_min, Vector3 b_size) { var a_max = a_min + a_size; var b_max = b_min + b_size; var a_yesno = a_max.x > b_min.x && a_max.y > b_min.y && b_max.z > a_min.z; if ( a_yesno ) { var b_yesno = b_max.x > a_min.x && b_max.y > a_min.y && a_max.z > b_min.z; if ( b_yesno ) { //var da_p = new Vector3(a_max.x - b_min.x, a_max.y - b_min.y, b_max.z - a_min.z); //var db_p = new Vector3(b_max.x - a_min.x, b_max.y - a_min.y, a_max.z - b_min.z); //var dp_p = a_size + b_size - IsoUtils.Vec3Abs(da_p - db_p); var dA_x = a_max.x - b_min.x; var dA_y = a_max.y - b_min.y; var dA_z = b_max.z - a_min.z; var dB_x = b_max.x - a_min.x; var dB_y = b_max.y - a_min.y; var dB_z = a_max.z - b_min.z; var dP_x = a_size.x + b_size.x - Mathf.Abs(dA_x - dB_x); var dP_y = a_size.y + b_size.y - Mathf.Abs(dA_y - dB_y); var dP_z = a_size.z + b_size.z - Mathf.Abs(dA_z - dB_z); if ( dP_x <= dP_y && dP_x <= dP_z ) { return dA_x > dB_x; } else if ( dP_y <= dP_x && dP_y <= dP_z ) { return dA_y > dB_y; } else { return dA_z > dB_z; } } } return a_yesno; } } }