Files
unity-iso-tools/Assets/IsoTools/Scripts/Internal/IsoSortingSolver.cs
2016-12-29 07:11:48 +07:00

195 lines
5.6 KiB
C#

using UnityEngine;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
#if UNITY_5_5_OR_NEWER
using UnityEngine.Profiling;
#endif
namespace IsoTools.Internal {
public class IsoSortingSolver {
List<Renderer> _tmpRenderers = new List<Renderer>();
// ---------------------------------------------------------------------
//
// Callbacks
//
// ---------------------------------------------------------------------
public void OnAddIsoObject(IsoObject iso_object) {
if ( iso_object.isCachedRenderers ) {
iso_object.UpdateCachedRenderers();
}
}
public void OnRemoveIsoObject(IsoObject iso_object) {
if ( iso_object.isCachedRenderers ) {
iso_object.ClearCachedRenderers();
}
}
public bool OnMarkDirtyIsoObject(IsoObject iso_object) {
return false;
}
public void OnDrawGizmos() {
}
// ---------------------------------------------------------------------
//
// Functions
//
// ---------------------------------------------------------------------
public bool StepSortingAction(IsoWorld iso_world, IsoScreenSolver screen_solver) {
Profiler.BeginSample("IsoSortingSolver.ResolveVisibles");
var dirty = ResolveVisibles(screen_solver);
Profiler.EndSample();
if ( dirty ) {
Profiler.BeginSample("IsoSortingSolver.PlaceVisibles");
PlaceVisibles(iso_world, screen_solver);
Profiler.EndSample();
}
return dirty;
}
public void Clear() {
}
// ---------------------------------------------------------------------
//
// ResolveVisibles
//
// ---------------------------------------------------------------------
bool ResolveVisibles(IsoScreenSolver screen_solver) {
var mark_dirty = false;
var old_visibles = screen_solver.oldVisibles;
var cur_visibles = screen_solver.curVisibles;
for ( int i = 0, e = cur_visibles.Count; i < e; ++i ) {
var iso_object = cur_visibles[i];
if ( iso_object.Internal.Dirty ) {
screen_solver.SetupIsoObjectDepends(iso_object);
iso_object.Internal.Dirty = false;
mark_dirty = true;
}
if ( iso_object.renderersMode == IsoObject.RenderersMode.Mode3d ) {
if ( UpdateIsoObjectBounds3d(iso_object) ) {
mark_dirty = true;
}
}
}
for ( int i = 0, e = old_visibles.Count; i < e; ++i ) {
var iso_object = old_visibles[i];
if ( !cur_visibles.Contains(iso_object) ) {
screen_solver.ClearIsoObjectDepends(iso_object);
iso_object.Internal.Dirty = true;
mark_dirty = true;
}
}
_tmpRenderers.Clear();
return mark_dirty;
}
bool UpdateIsoObjectBounds3d(IsoObject iso_object) {
var minmax3d = IsoObjectMinMax3D(iso_object);
var offset3d = iso_object.Internal.Transform.position.z - minmax3d.center;
if ( iso_object.Internal.MinMax3d.Approximately(minmax3d) ||
!Mathf.Approximately(iso_object.Internal.Offset3d, offset3d) )
{
iso_object.Internal.MinMax3d = minmax3d;
iso_object.Internal.Offset3d = offset3d;
return true;
}
return false;
}
IsoMinMax IsoObjectMinMax3D(IsoObject iso_object) {
bool inited = false;
var result = IsoMinMax.zero;
var renderers = GetIsoObjectRenderers(iso_object);
for ( int i = 0, e = renderers.Count; i < e; ++i ) {
var renderer = renderers[i];
if ( renderer && renderer.enabled ) {
var bounds = renderer.bounds;
var extents = bounds.extents;
if ( extents.x > 0.0f || extents.y > 0.0f || extents.z > 0.0f ) {
var center = bounds.center.z;
var minbounds = center - extents.z;
var maxbounds = center + extents.z;
if ( inited ) {
if ( result.min > minbounds ) {
result.min = minbounds;
}
if ( result.max < maxbounds ) {
result.max = maxbounds;
}
} else {
inited = true;
result.Set(minbounds, maxbounds);
}
}
}
}
return inited ? result : IsoMinMax.zero;
}
List<Renderer> GetIsoObjectRenderers(IsoObject iso_object) {
if ( iso_object.isCachedRenderers ) {
return iso_object.Internal.Renderers;
} else {
iso_object.GetComponentsInChildren<Renderer>(_tmpRenderers);
return _tmpRenderers;
}
}
// ---------------------------------------------------------------------
//
// PlaceVisibles
//
// ---------------------------------------------------------------------
void PlaceVisibles(IsoWorld iso_world, IsoScreenSolver screen_solver) {
var step_depth = iso_world.stepDepth;
var start_depth = iso_world.startDepth;
var cur_visibles = screen_solver.curVisibles;
for ( int i = 0, e = cur_visibles.Count; i < e; ++i ) {
start_depth = RecursivePlaceIsoObject(
cur_visibles[i], step_depth, start_depth);
}
}
float RecursivePlaceIsoObject(IsoObject iso_object, float step_depth, float start_depth) {
if ( iso_object.Internal.Placed ) {
return start_depth;
}
iso_object.Internal.Placed = true;
var self_depends = iso_object.Internal.SelfDepends;
for ( int i = 0, e = self_depends.Count; i < e; ++i ) {
start_depth = RecursivePlaceIsoObject(self_depends[i], step_depth, start_depth);
}
if ( iso_object.renderersMode == IsoObject.RenderersMode.Mode3d ) {
var zoffset = iso_object.Internal.Offset3d;
var extents = iso_object.Internal.MinMax3d.size;
PlaceIsoObject(iso_object, start_depth + extents * 0.5f + zoffset);
return start_depth + extents + step_depth;
} else {
PlaceIsoObject(iso_object, start_depth);
return start_depth + step_depth;
}
}
void PlaceIsoObject(IsoObject iso_object, float depth) {
var iso_internal = iso_object.Internal;
var old_position = iso_internal.LastTrans;
iso_internal.Transform.position =
IsoUtils.Vec3FromVec2(old_position, depth);
}
}
}