1. svn -> git

This commit is contained in:
2017-04-12 01:23:07 +09:00
commit daaaf2997b
406 changed files with 68990 additions and 0 deletions

View File

@@ -0,0 +1,443 @@
using UnityEngine;
using System.Collections.Generic;
public static class D2D_EdgeCalculator
{
enum Edge
{
Left,
Right,
Bottom,
Top
}
class Point
{
public bool Used;
public Point Other;
public Vector2 Position;
public Edge Inner;
public Edge Outer;
}
class Cell
{
public int X;
public int Y;
public int PointIndex;
public int PointCount;
}
private static int xMin;
private static int xMax;
private static int yMin;
private static int yMax;
private static int width;
private static int height;
private static int cellCount;
private static List<Cell> cells = new List<Cell>();
private static List<EdgeCollider2D> generatedEdgeColliders = new List<EdgeCollider2D>();
private static List<Vector2> generatedPoints = new List<Vector2>();
private static int cellPointCount;
private static List<Point> cellPoints = new List<Point>();
private static LinkedList<Point> tracedEdges = new LinkedList<Point>();
private static Vector2 translation;
private static Color[] pixels;
private static int pixelsX;
private static int pixelsY;
private static int pixelsWidth;
private static int pixelsHeight;
private static void GetPixels(Texture2D alphaTex, int l, int b, int r, int t)
{
l = Mathf.Max(l, 0);
b = Mathf.Max(b, 0);
r = Mathf.Min(r, alphaTex.width);
t = Mathf.Min(t, alphaTex.height);
pixelsX = l;
pixelsY = b;
pixelsWidth = r - l;
pixelsHeight = t - b;
pixels = alphaTex.GetPixels(pixelsX, pixelsY, pixelsWidth, pixelsHeight);
}
public static List<EdgeCollider2D> Generate(GameObject gameObject, Texture2D alphaTex, int newXMin, int newXMax, int newYMin, int newYMax, float tolerance)
{
cellCount = 0;
cellPointCount = 0;
generatedEdgeColliders.Clear();
if (gameObject != null && alphaTex != null)
{
xMin = newXMin; if (xMin == 0) xMin -= 1; // Expand left?
yMin = newYMin; if (yMin == 0) yMin -= 1; // Expand bottom?
xMax = newXMax;
yMax = newYMax;
width = xMax - xMin;
height = yMax - yMin;
GetPixels(alphaTex, newXMin - 1, newYMin - 1, newXMax + 1, newYMax + 1);
if (width > 0 && height > 0)
{
if (cells.Capacity < width * height)
{
cells.Capacity = width * height;
}
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
var cell = GetNextCell();
var bl = GetAlphaOrDefault(xMin + x , yMin + y );
var br = GetAlphaOrDefault(xMin + x + 1, yMin + y );
var tl = GetAlphaOrDefault(xMin + x , yMin + y + 1);
var tr = GetAlphaOrDefault(xMin + x + 1, yMin + y + 1);
cell.X = x;
cell.Y = y;
translation.x = xMin + x + 0.5f;
translation.y = yMin + y + 0.5f;
CalculateCell(cell, bl, br, tl, tr, 0.5f);
}
}
for (var i = 0; i < cellCount; i++)
{
var cell = cells[i];
for (var j = 0; j < cell.PointCount; j++)
{
var point = cellPoints[cell.PointIndex + j];
if (point.Used == false)
{
TraceEdges(cell, point);
OptimizeEdges(tolerance);
CompileTracedEdges(gameObject);
}
}
}
/*
var border = gameObject.AddComponent<EdgeCollider2D>(); generatedEdgeColliders.Add(border);
border.points = new Vector2[] {
new Vector2(xMin, yMin),
new Vector2(xMax, yMin),
new Vector2(xMax, yMax),
new Vector2(xMin, yMax),
new Vector2(xMin, yMin) };*/
}
}
return generatedEdgeColliders;
}
private static Cell GetNextCell()
{
var cell = default(Cell);
if (cellCount >= cells.Count)
{
cell = new Cell(); cells.Add(cell);
}
else
{
cell = cells[cellCount];
}
cellCount += 1;
return cell;
}
private static Point GetNextCellPoint()
{
var point = default(Point);
if (cellPointCount >= cellPoints.Count)
{
point = new Point(); cellPoints.Add(point);
}
else
{
point = cellPoints[cellPointCount];
point.Used = false;
}
cellPointCount += 1;
return point;
}
private static void CompileTracedEdges(GameObject gameObject)
{
var edgeCollider2D = gameObject.AddComponent<EdgeCollider2D>(); generatedEdgeColliders.Add(edgeCollider2D);
generatedPoints.Clear();
foreach (var point in tracedEdges)
{
generatedPoints.Add(point.Position);
}
edgeCollider2D.points = generatedPoints.ToArray();
}
private static void CalculateCell(Cell cell, float bl, float br, float tl, float tr, float threshold)
{
var index = cellPointCount;
var count = 0;
var useBl = bl >= threshold;
var useBr = br >= threshold;
var useTl = tl >= threshold;
var useTr = tr >= threshold;
// Top
if (useTl ^ useTr)
{
var point = GetNextCellPoint(); count += 1;
point.Position = Transform((tl - threshold) / (tl - tr), 1.0f);
point.Inner = Edge.Top;
point.Outer = Edge.Bottom;
}
// Right
if (useTr ^ useBr)
{
var point = GetNextCellPoint(); count += 1;
point.Position = Transform(1.0f, (br - threshold) / (br - tr));
point.Inner = Edge.Right;
point.Outer = Edge.Left;
}
// Bottom
if (useBl ^ useBr)
{
var point = GetNextCellPoint(); count += 1;
point.Position = Transform((bl - threshold) / (bl - br), 0.0f);
point.Inner = Edge.Bottom;
point.Outer = Edge.Top;
}
// Left
if (useTl ^ useBl)
{
var point = GetNextCellPoint(); count += 1;
point.Position = Transform(0.0f, (bl - threshold) / (bl - tl));
point.Inner = Edge.Left;
point.Outer = Edge.Right;
}
// Pair up points
switch (count)
{
case 2:
{
cellPoints[index + 0].Other = cellPoints[index + 1];
cellPoints[index + 1].Other = cellPoints[index + 0];
}
break;
case 4:
{
if (useTl == true && useBr == true)
{
cellPoints[index + 0].Other = cellPoints[index + 3];
cellPoints[index + 1].Other = cellPoints[index + 2];
cellPoints[index + 2].Other = cellPoints[index + 1];
cellPoints[index + 3].Other = cellPoints[index + 0];
}
else
{
cellPoints[index + 0].Other = cellPoints[index + 1];
cellPoints[index + 1].Other = cellPoints[index + 0];
cellPoints[index + 2].Other = cellPoints[index + 3];
cellPoints[index + 3].Other = cellPoints[index + 2];
}
}
break;
}
cell.PointIndex = index;
cell.PointCount = count;
}
private static void TraceEdges(Cell cell, Point point)
{
tracedEdges.Clear();
TraceEdge(cell, point, false);
TraceEdge(cell, point.Other, true);
}
private static void TraceEdge(Cell cell, Point point, bool last)
{
point.Used = true;
if (last == true)
{
tracedEdges.AddLast(point);
}
else
{
tracedEdges.AddFirst(point);
}
switch (point.Inner)
{
case Edge.Left:
{
cell = GetCell(cell.X - 1, cell.Y);
}
break;
case Edge.Right:
{
cell = GetCell(cell.X + 1, cell.Y);
}
break;
case Edge.Bottom:
{
cell = GetCell(cell.X, cell.Y - 1);
}
break;
case Edge.Top:
{
cell = GetCell(cell.X, cell.Y + 1);
}
break;
}
if (cell != null)
{
for (var i = 0; i < cell.PointCount; i++)
{
var outerPoint = cellPoints[cell.PointIndex + i];
if (outerPoint.Used == false && outerPoint.Inner == point.Outer)
{
outerPoint.Used = true;
TraceEdge(cell, outerPoint.Other, last);
}
}
}
}
private static void OptimizeEdges(float tolerance)
{
if (tolerance > 0.0f && tracedEdges.Count > 2)
{
var a = tracedEdges.First;
var b = a.Next;
var c = b.Next;
while (true)
{
var ab = Vector3.Normalize(b.Value.Position - a.Value.Position);
var bc = Vector3.Normalize(c.Value.Position - b.Value.Position);
var abc = Vector3.Dot(ab, bc);
if (abc > (1.0f - tolerance))
{
tracedEdges.Remove(b);
if (c != tracedEdges.Last)
{
b = c;
c = c.Next;
}
else
{
return;
}
}
else
{
if (c != tracedEdges.Last)
{
a = b;
b = c;
c = c.Next;
}
else
{
return;
}
}
}
}
}
private static float GetAlphaOrDefault(int x, int y)
{
x -= pixelsX;
y -= pixelsY;
if (x >= 0 && y >= 0 && x < pixelsWidth && y < pixelsHeight)
{
return pixels[x + y * pixelsWidth].a;
}
return default(float);
}
private static Cell GetCell(int x, int y)
{
if (x >= 0 && y >= 0 && x < width && y < height)
{
return cells[x + y * width];
}
return null;
}
private static Vector2 Transform(float x, float y)
{
x = x + translation.x;
y = y + translation.y;
return new Vector2(x, y);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5ff43b95fef4b8240b7c27f680217911
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,512 @@
using UnityEngine;
using System.Collections.Generic;
public static partial class D2D_Helper
{
public static int MeshVertexLimit = 65000;
public static void GetPixelsBilinear(Texture2D t, int x, int y)
{
}
public static void Swap<T>(ref T a, ref T b)
{
var c = b;
b = a;
a = c;
}
public static float Atan2(Vector2 xy)
{
return Mathf.Atan2(xy.x, xy.y);
}
public static void ResizeArrayTo<T>(List<T> array, int size, System.Func<int, T> newT, System.Action<T> removeT)
{
if (array != null)
{
while (array.Count < size)
{
array.Add(newT != null ? newT(array.Count) : default(T));
}
while (array.Count > size)
{
if (removeT != null)
{
removeT(array[array.Count - 1]);
}
array.RemoveAt(array.Count - 1);
}
}
}
private static HideFlags oldHideFlags;
public static void BeginStealthSet(Object o)
{
if (o != null)
{
oldHideFlags = o.hideFlags;
o.hideFlags = HideFlags.DontSave;
}
}
public static void EndStealthSet(Object o)
{
if (o != null)
{
o.hideFlags = oldHideFlags;
}
}
public static void StealthSet(MeshFilter mf, Mesh m)
{
if (mf != null && mf.sharedMesh != m)
{
#if UNITY_EDITOR
var hf = mf.hideFlags;
mf.hideFlags = HideFlags.DontSave;
mf.sharedMesh = m;
mf.hideFlags = hf;
#else
mf.sharedMesh = m;
#endif
}
}
public static void StealthSet(MeshRenderer mr, Material m)
{
if (mr != null && mr.sharedMaterial != m)
{
#if UNITY_EDITOR
var hf = mr.hideFlags;
mr.hideFlags = HideFlags.DontSave;
mr.sharedMaterial = m;
mr.hideFlags = hf;
#else
mr.sharedMaterial = m;
#endif
}
}
public static void SetPosition(Transform t, Vector3 v)
{
if (t != null)
{
#if UNITY_EDITOR
if (Application.isPlaying == false && t.position == v) return;
#endif
t.position = v;
}
}
public static void Destroy(Object o)
{
#if UNITY_EDITOR
if (Application.isPlaying == false)
{
Object.DestroyImmediate(o, true); return;
}
#endif
Object.Destroy(o);
}
public static void DestroyManaged(System.Action DestroyAction)
{
if (DestroyAction != null)
{
#if UNITY_EDITOR
var isPlaying = Application.isPlaying;
UnityEditor.EditorApplication.delayCall += () =>
{
if (Application.isPlaying == isPlaying)
{
DestroyAction();
}
};
#else
DestroyAction();
#endif
}
}
public static void SetParent(Transform t, Transform newParent, bool keepLocalTransform = true)
{
if (t != null && t.parent != newParent)
{
if (keepLocalTransform == true)
{
var oldLocalPosition = t.localPosition;
var oldLocalRotation = t.localRotation;
var oldLocalScale = t.localScale;
t.parent = newParent;
t.localPosition = oldLocalPosition;
t.localRotation = oldLocalRotation;
t.localScale = oldLocalScale;
}
else
{
t.parent = newParent;
}
}
}
public static void SetLocalPosition(Transform t, float x, float y, float z)
{
SetLocalPosition(t, new Vector3(x, y, z));
}
public static void SetLocalPosition(Transform t, Vector3 v)
{
if (t != null)
{
#if UNITY_EDITOR
if (Application.isPlaying == false && t.localPosition == v) return;
#endif
t.localPosition = v;
}
}
public static void SetLocalScale(Transform t, float v)
{
SetLocalScale(t, new Vector3(v, v, v));
}
public static void SetLocalScale(Transform t, Vector3 v)
{
if (t != null)
{
#if UNITY_EDITOR
if (Application.isPlaying == false && t.localScale == v) return;
#endif
if (t.localScale == v) return;
t.localScale = v;
}
}
public static T GetComponentUpwards<T>(Transform transform, bool skipFirst = false)
where T : Component
{
if (transform != null)
{
if (skipFirst == true)
{
transform = transform.parent;
}
while (transform != null)
{
var component = transform.GetComponent<T>();
if (component != null) return component;
transform = transform.parent;
}
}
return null;
}
public static T GetOrAddComponent<T>(GameObject gameObject)
where T : Component
{
if (gameObject != null)
{
var component = gameObject.GetComponent<T>();
if (component == null) component = gameObject.AddComponent<T>();
return component;
}
return null;
}
public static GameObject CloneGameObject(GameObject source, Transform parent, bool keepName = false)
{
if (source != null)
{
var clone = (GameObject)GameObject.Instantiate(source); if (clone == null) throw new System.NullReferenceException();
if (parent != null) SetParent(clone.transform, parent, true);
if (keepName == true) clone.name = source.name;
return clone;
}
return source;
}
public static GameObject CloneGameObject(GameObject source, Transform parent, Vector3 xyz, Quaternion rot, bool keepName = false)
{
if (source != null)
{
var clone = (GameObject)GameObject.Instantiate(source, xyz, rot); if (clone == null) throw new System.NullReferenceException();
if (parent != null) SetParent(clone.transform, parent, true);
if (keepName == true) clone.name = source.name;
return clone;
}
return source;
}
public static GameObject CreateGameObject(string name = "", Transform parent = null)
{
return CreateGameObject(name, parent, Vector3.zero, Quaternion.identity, Vector3.one);
}
public static GameObject CreateGameObject(string name, Transform parent, Vector3 position, Quaternion identity, Vector3 scale)
{
var gameObject = new GameObject(name);
gameObject.transform.parent = parent;
gameObject.transform.localPosition = Vector3.zero;
gameObject.transform.localRotation = Quaternion.identity;
gameObject.transform.localScale = Vector3.one;
return gameObject;
}
public static T Clone<T>(T o, bool keepName = true)
where T : Object
{
if (o != null)
{
var c = (T)Object.Instantiate(o);
if (c != null && keepName == true) c.name = o.name;
return c;
}
return null;
}
public static bool Enabled(Behaviour b)
{
return b != null && b.enabled == true && b.gameObject.activeInHierarchy == true;
}
public static float Divide(float a, float b)
{
return Zero(b) == false ? a / b : 0.0f;
}
public static Vector2 Divide(float xA, float yA, float xB, float yB)
{
return new Vector2(Divide(xA, xB), Divide(yA, yB));
}
public static float Reciprocal(float v)
{
return Zero(v) == false ? 1.0f / v : 0.0f;
}
public static Vector2 Reciprocal(Vector2 v)
{
return new Vector2(Reciprocal(v.x), Reciprocal(v.y));
}
public static Vector2 Reciprocal(float x, float y)
{
return new Vector2(Reciprocal(x), Reciprocal(y));
}
public static Vector3 Reciprocal(Vector3 v)
{
return new Vector3(Reciprocal(v.x), Reciprocal(v.y), Reciprocal(v.z));
}
public static Vector3 Reciprocal(float x, float y, float z)
{
return new Vector3(Reciprocal(x), Reciprocal(y), Reciprocal(z));
}
public static bool Zero(float v)
{
return Mathf.Approximately(v, 0.0f);
}
public static Matrix4x4 RotationMatrix(Quaternion q)
{
var matrix = Matrix4x4.TRS(Vector3.zero, q, Vector3.one);
return matrix;
}
public static Matrix4x4 TranslationMatrix(Vector3 xyz)
{
return TranslationMatrix(xyz.x, xyz.y, xyz.z);
}
public static Matrix4x4 TranslationMatrix(float x, float y, float z)
{
var matrix = Matrix4x4.identity;
matrix.m03 = x;
matrix.m13 = y;
matrix.m23 = z;
return matrix;
}
public static Matrix4x4 ScalingMatrix(float xyz)
{
return ScalingMatrix(xyz, xyz, xyz);
}
public static Matrix4x4 ScalingMatrix(Vector3 xyz)
{
return ScalingMatrix(xyz.x, xyz.y, xyz.z);
}
public static Matrix4x4 ScalingMatrix(float x, float y, float z)
{
var matrix = Matrix4x4.identity;
matrix.m00 = x;
matrix.m11 = y;
matrix.m22 = z;
return matrix;
}
public static float DampenFactor(float dampening, float elapsed)
{
return 1.0f - Mathf.Pow((float)System.Math.E, - dampening * elapsed);
}
public static Quaternion Dampen(Quaternion current, Quaternion target, float dampening, float elapsed, float minStep = 0.0f)
{
var factor = DampenFactor(dampening, elapsed);
var maxDelta = Quaternion.Angle(current, target) * factor + minStep * elapsed;
return MoveTowards(current, target, maxDelta);
}
public static float Dampen(float current, float target, float dampening, float elapsed, float minStep = 0.0f)
{
var factor = DampenFactor(dampening, elapsed);
var maxDelta = Mathf.Abs(target - current) * factor + minStep * elapsed;
return MoveTowards(current, target, maxDelta);
}
public static Vector3 Dampen3(Vector3 current, Vector3 target, float dampening, float elapsed, float minStep = 0.0f)
{
var factor = DampenFactor(dampening, elapsed);
var maxDelta = Mathf.Abs((target - current).magnitude) * factor + minStep * elapsed;
return Vector3.MoveTowards(current, target, maxDelta);
}
public static Quaternion MoveTowards(Quaternion current, Quaternion target, float maxDelta)
{
var delta = Quaternion.Angle(current, target);
return Quaternion.Slerp(current, target, Divide(maxDelta, delta));
}
public static float MoveTowards(float current, float target, float maxDelta)
{
if (target > current)
{
current = System.Math.Min(target, current + maxDelta);
}
else
{
current = System.Math.Max(target, current - maxDelta);
}
return current;
}
public static Vector3 ClosestPointToLineSegment(Vector3 a, Vector3 b, Vector3 point)
{
var l = (b - a).magnitude;
var d = (b - a).normalized;
return a + Mathf.Clamp(Vector3.Dot(point - a, d), 0.0f, l) * d;
}
public static Vector3 ClosestPointToTriangle(Vector3 a, Vector3 b, Vector3 c, Vector3 p)
{
var r = Quaternion.Inverse(Quaternion.LookRotation(-Vector3.Cross(a - b, a - c)));
var ra = r * a;
var rb = r * b;
var rc = r * c;
var rp = r * p;
var a2 = D2D_Helper.VectorXY(ra);
var b2 = D2D_Helper.VectorXY(rb);
var c2 = D2D_Helper.VectorXY(rc);
var p2 = D2D_Helper.VectorXY(rp);
if (PointLeftOfLine(a2, b2, p2) == true)
{
return ClosestPointToLineSegment(a, b, p);
}
if (PointLeftOfLine(b2, c2, p2) == true)
{
return ClosestPointToLineSegment(b, c, p);
}
if (PointLeftOfLine(c2, a2, p2) == true)
{
return ClosestPointToLineSegment(c, a, p);
}
var barycentric = GetBarycentric(a2, b2, c2, p2);
return barycentric.x * a + barycentric.y * b + barycentric.z * c;
}
public static Vector3 GetBarycentric(Vector2 a, Vector2 b, Vector2 c, Vector2 p)
{
var barycentric = Vector3.zero;
var v0 = b - a;
var v1 = c - a;
var v2 = p - a;
var d00 = Vector2.Dot(v0, v0);
var d01 = Vector2.Dot(v0, v1);
var d11 = Vector2.Dot(v1, v1);
var d20 = Vector2.Dot(v2, v0);
var d21 = Vector2.Dot(v2, v1);
var denom = D2D_Helper.Reciprocal(d00 * d11 - d01 * d01);
barycentric.y = (d11 * d20 - d01 * d21) * denom;
barycentric.z = (d00 * d21 - d01 * d20) * denom;
barycentric.x = 1.0f - barycentric.y - barycentric.z;
return barycentric;
}
public static bool PointLeftOfLine(Vector2 a, Vector2 b, Vector2 p) // NOTE: CCW
{
return ((b.x - a.x) * (p.y - a.y) - (p.x - a.x) * (b.y - a.y)) >= 0.0f;
}
public static bool PointRightOfLine(Vector2 a, Vector2 b, Vector2 p) // NOTE: CCW
{
return ((b.x - a.x) * (p.y - a.y) - (p.x - a.x) * (b.y - a.y)) <= 0.0f;
}
public static Vector2 VectorXY(Vector3 xyz)
{
return new Vector2(xyz.x, xyz.y);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2a0dca602cf01b8499a666502d6b1c77
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,214 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
public static partial class D2D_Helper
{
public static bool BaseRectSet;
public static Rect BaseRect;
private static GUIStyle none;
private static GUIStyle error;
private static GUIStyle noError;
public static GUIStyle None
{
get
{
if (none == null)
{
none = new GUIStyle();
}
return none;
}
}
public static GUIStyle Error
{
get
{
if (error == null)
{
error = new GUIStyle();
error.border = new RectOffset(3, 3, 3, 3);
error.normal = new GUIStyleState();
error.normal.background = CreateTempTexture(12, 12, "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAALElEQVQIHWP4z8CgC8SHgfg/lNZlQBIACYIlGEEMBjTABOQfQRM7AlKGYSYAoOwcvDRV9/MAAAAASUVORK5CYII=");
}
return error;
}
}
public static GUIStyle NoError
{
get
{
if (noError == null)
{
noError = new GUIStyle();
noError.border = new RectOffset(3, 3, 3, 3);
noError.normal = new GUIStyleState();
}
return noError;
}
}
public static Texture2D CreateTempTexture(int width, int height, string encoded)
{
var texture = new Texture2D(width, height, TextureFormat.ARGB32, false);
texture.hideFlags = HideFlags.HideAndDontSave;
texture.LoadImage(System.Convert.FromBase64String(encoded));
texture.Apply();
return texture;
}
public static Rect Reserve(float height = 16.0f)
{
var rect = default(Rect);
EditorGUILayout.BeginVertical(NoError);
{
rect = EditorGUILayout.BeginVertical();
{
EditorGUILayout.LabelField(string.Empty, GUILayout.Height(height));
}
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndVertical();
if (BaseRectSet == true)
{
rect.xMin = BaseRect.xMin;
rect.xMax = BaseRect.xMax;
}
return rect;
}
public static void Record<T>(T t, string desc)
where T : Object
{
if (t != null)
{
Undo.RecordObject(t, desc);
}
}
public static void Record<T>(T[] ts, string desc)
where T : Object
{
if (ts != null)
{
Undo.RecordObjects(ts, desc);
}
}
public static void SetDirty<T>(T t)
where T : Object
{
if (t != null)
{
EditorUtility.SetDirty(t);
}
}
public static void SetDirty<T>(T[] ts)
where T : Object
{
foreach (var t in ts)
{
SetDirty(t);
}
}
public static List<T> LoadAllAssets<T>(string pattern) // e.g. "*.prefab"
where T : Object
{
var assets = new List<T>();
var basePath = Application.dataPath;
var files = new List<string>(); GetFilesRecursive(files, basePath, pattern);
var sub = basePath.Length - "Assets".Length;
for (var i = 0; i < files.Count; i++)
{
EditorUtility.DisplayProgressBar("Loading Assets", "", (float)files.Count / (float)i);
var file = files[i];
var path = file.Substring(sub);
var asset = LoadAsset<T>(path);
if (asset != null)
{
assets.Add(asset);
}
}
EditorUtility.ClearProgressBar();
return assets;
}
public static T LoadAsset<T>(string path)
where T : Object
{
return (T)AssetDatabase.LoadAssetAtPath(path, typeof(T));
}
private static void GetFilesRecursive(List<string> files, string path, string pattern)
{
files.AddRange(System.IO.Directory.GetFiles(path, pattern));
var directories = System.IO.Directory.GetDirectories(path);
foreach (var directory in directories)
{
GetFilesRecursive(files, directory, pattern);
}
}
public static T GetAssetImporter<T>(Object asset)
where T : AssetImporter
{
return GetAssetImporter<T>((AssetDatabase.GetAssetPath(asset)));
}
public static T GetAssetImporter<T>(string path)
where T : AssetImporter
{
return (T)AssetImporter.GetAtPath(path);
}
public static void ReimportAsset(Object asset)
{
ReimportAsset(AssetDatabase.GetAssetPath(asset));
}
public static void ReimportAsset(string path)
{
AssetDatabase.ImportAsset(path);
}
public static void MakeTextureReadable(Texture2D texture)
{
if (texture != null)
{
var importer = D2D_Helper.GetAssetImporter<UnityEditor.TextureImporter>(texture);
if (importer != null && importer.isReadable == false)
{
importer.isReadable = true;
D2D_Helper.ReimportAsset(importer.assetPath);
}
}
}
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 958e55e465f5714428368c324eca0449
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,278 @@
using UnityEngine;
[System.Serializable]
public class D2D_Pixels
{
[SerializeField]
private int width;
[SerializeField]
private int height;
[SerializeField]
private Color32[] pixels;
public int Width
{
get
{
return width;
}
}
public int Height
{
get
{
return height;
}
}
public Color32[] Pixels
{
get
{
return pixels;
}
}
public D2D_Pixels()
{
}
public D2D_Pixels(Texture texture) : this((Texture2D)texture)
{
}
public D2D_Pixels(Sprite sprite)
{
if (sprite == null) throw new System.ArgumentNullException();
#if UNITY_EDITOR
D2D_Helper.MakeTextureReadable(sprite.texture);
#endif
var rect = sprite.textureRect;
var sourceWidth = sprite.texture.width;
var sourcePixels = sprite.texture.GetPixels32();
var sourceOffset = sourceWidth * (int)rect.yMin + (int)rect.xMin;
var targetOffset = 0;
width = (int)rect.width;
height = (int)rect.height;
pixels = new Color32[width * height];
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
pixels[targetOffset + x] = sourcePixels[sourceOffset + x];
}
sourceOffset += sourceWidth;
targetOffset += width;
}
}
public D2D_Pixels(Texture2D texture)
{
if (texture == null) throw new System.ArgumentNullException();
#if UNITY_EDITOR
D2D_Helper.MakeTextureReadable(texture);
#endif
width = texture.width;
height = texture.height;
pixels = texture.GetPixels32();
}
public D2D_Pixels(int newWidth, int newHeight)
{
if (newWidth < 0) throw new System.ArgumentOutOfRangeException();
if (newHeight < 0) throw new System.ArgumentOutOfRangeException();
width = newWidth;
height = newHeight;
pixels = new Color32[newWidth * newHeight];
}
public D2D_Pixels(int newWidth, int newHeight, Color32[] newPixels)
{
if (newWidth < 0) throw new System.ArgumentOutOfRangeException();
if (newHeight < 0) throw new System.ArgumentOutOfRangeException();
if (newPixels == null) throw new System.ArgumentNullException();
if (newWidth * newHeight != newPixels.Length) throw new System.ArgumentOutOfRangeException();
width = newWidth;
height = newHeight;
pixels = newPixels;
}
public Color32 GetPixel(int x, int y)
{
return pixels[x + width * y];
}
public Color32 GetPixelTransparent(int x, int y)
{
if (x < 0 || y < 0 || x >= width || y >= height) return new Color32(0, 0, 0, 0);
return pixels[x + width * y];
}
public Color32 GetPixelClamp(int x, int y)
{
if (x < 0) x = 0; else if (x >= width ) x = width -1;
if (y < 0) y = 0; else if (y >= height) y = height -1;
return pixels[x + width * y];
}
public Color32 GetPixelRepeat(int x, int y)
{
x = x >= 0 ? x % width : width + (x % width );
y = y >= 0 ? y % height : height + (y % height);
return pixels[x + width * y];
}
public Color32 GetPixelBilinear(float u, float v)
{
u = u * (width - 1);
v = v * (height - 1);
var x = Mathf.FloorToInt(u);
var y = Mathf.FloorToInt(v);
var s = u - x;
var t = v - y;
var bl = GetPixelClamp(x , y );
var br = GetPixelClamp(x + 1, y );
var tl = GetPixelClamp(x , y + 1);
var tr = GetPixelClamp(x + 1, y + 1);
var bb = Color32.Lerp(bl, br, s);
var tt = Color32.Lerp(tl, tr, s);
return Color32.Lerp(bb, tt, t);
}
public void SetPixel(int x, int y, Color32 colour)
{
pixels[x + width * y] = colour;
}
public void SetPixelClamp(int x, int y, Color32 colour)
{
if (x < 0) x = 0; else if (x >= width ) x = width -1;
if (y < 0) y = 0; else if (y >= height) y = height -1;
pixels[x + width * y] = colour;
}
public void SetPixels(int x, int y, D2D_Pixels s)
{
for (var sy = 0; sy < s.height; sy++)
{
for (var sx = 0; sx < s.width; sx++)
{
SetPixel(x + sx, y + sy, s.GetPixel(sx, sy));
}
}
}
public void SetPixelsClamp(int x, int y, D2D_Pixels s)
{
for (var sy = 0; sy < s.height; sy++)
{
for (var sx = 0; sx < s.width; sx++)
{
SetPixelClamp(x + sx, y + sy, s.GetPixelClamp(sx, sy));
}
}
}
public D2D_Pixels GetResized(int newWidth, int newHeight)
{
var o = new D2D_Pixels(newWidth, newHeight);
var w = (float)(newWidth - 1);
var h = (float)(newHeight - 1);
for (var y = 0; y < newHeight; y++)
{
for (var x = 0; x < newWidth; x++)
{
var pixel = GetPixelBilinear((float)x / w, (float)y / h);
o.SetPixel(x, y, pixel);
}
}
return o;
}
public D2D_Pixels GetBlurredAlpha()
{
var o = new D2D_Pixels(width, height);
// Horizontal
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
var a = GetPixelTransparent(x - 1, y);
var b = GetPixelTransparent(x , y);
var c = GetPixelTransparent(x + 1, y);
var t = (int)a.a + (int)b.a + (int)c.a;
b.a = (byte)(t / 3);
o.SetPixel(x, y, b);
}
}
// Vertical
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
var a = GetPixelTransparent(x, y - 1);
var b = GetPixelTransparent(x, y );
var c = GetPixelTransparent(x, y + 1);
var t = (int)a.a + (int)b.a + (int)c.a;
b.a = (byte)(t / 3);
o.SetPixel(x, y, b);
}
}
return o;
}
public Texture2D Apply(TextureFormat format, bool mipmap = false, bool linear = false)
{
var texture = new Texture2D(width, height, format, mipmap, linear);
texture.SetPixels32(pixels);
texture.Apply();
return texture;
}
public byte[] ApplyAlpha()
{
var alphas = new byte[pixels.Length];
for (var i = 0; i < pixels.Length; i++)
{
alphas[i] = pixels[i].a;
}
return alphas;
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4b391339ee853d4438312b6530a2dc37
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,445 @@
using UnityEngine;
using System.Collections.Generic;
public static class D2D_PolygonCalculator
{
enum Edge
{
Left,
Right,
Bottom,
Top
}
class Point
{
public bool Used;
public Point Other;
public Vector2 Position;
public Edge Inner;
public Edge Outer;
}
class Cell
{
public int X;
public int Y;
public int PointIndex;
public int PointCount;
}
private static int xMin;
private static int xMax;
private static int yMin;
private static int yMax;
private static int width;
private static int height;
private static int cellCount;
private static List<Cell> cells = new List<Cell>();
private static List<Vector2> generatedPoints = new List<Vector2>();
private static int cellPointCount;
private static List<Point> cellPoints = new List<Point>();
private static LinkedList<Point> tracedEdges = new LinkedList<Point>();
private static Vector2 translation;
private static Color[] pixels;
private static int pixelsX;
private static int pixelsY;
private static int pixelsWidth;
private static int pixelsHeight;
public static PolygonCollider2D Generate(GameObject gameObject, PolygonCollider2D polygonCollider, Texture2D alphaTex, int newXMin, int newXMax, int newYMin, int newYMax, float tolerance)
{
cellCount = 0;
cellPointCount = 0;
if (gameObject != null && alphaTex != null)
{
if (polygonCollider == null)
{
polygonCollider = gameObject.AddComponent<PolygonCollider2D>();
}
xMin = newXMin - 1;
yMin = newYMin - 1;
xMax = newXMax + 1;
yMax = newYMax + 1;
width = xMax - xMin;
height = yMax - yMin;
GetPixels(alphaTex, newXMin, newYMin, newXMax, newYMax);
if (width > 0 && height > 0)
{
if (cells.Capacity < width * height)
{
cells.Capacity = width * height;
}
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
var cell = GetNextCell();
var bl = GetAlphaOrDefault(xMin + x , yMin + y );
var br = GetAlphaOrDefault(xMin + x + 1, yMin + y );
var tl = GetAlphaOrDefault(xMin + x , yMin + y + 1);
var tr = GetAlphaOrDefault(xMin + x + 1, yMin + y + 1);
cell.X = x;
cell.Y = y;
translation.x = xMin + x + 0.5f;
translation.y = yMin + y + 0.5f;
CalculateCell(cell, bl, br, tl, tr, 0.5f);
}
}
var pathCount = 0;
for (var i = 0; i < cellCount; i++)
{
var cell = cells[i];
for (var j = 0; j < cell.PointCount; j++)
{
var point = cellPoints[cell.PointIndex + j];
if (point.Used == false)
{
TraceEdges(cell, point);
OptimizeEdges(tolerance);
CompileTracedEdges(polygonCollider, pathCount); pathCount += 1;
}
}
}
if (polygonCollider.pathCount > pathCount)
{
polygonCollider.pathCount = pathCount;
}
}
return polygonCollider;
}
return null;
}
private static void GetPixels(Texture2D alphaTex, int l, int b, int r, int t)
{
l = Mathf.Max(l, 0);
b = Mathf.Max(b, 0);
r = Mathf.Min(r, alphaTex.width);
t = Mathf.Min(t, alphaTex.height);
pixelsX = l;
pixelsY = b;
pixelsWidth = r - l;
pixelsHeight = t - b;
pixels = alphaTex.GetPixels(pixelsX, pixelsY, pixelsWidth, pixelsHeight);
}
private static void CompileTracedEdges(PolygonCollider2D polygonCollider, int pathCount)
{
generatedPoints.Clear();
foreach (var point in tracedEdges)
{
generatedPoints.Add(point.Position);
}
if (polygonCollider.pathCount <= pathCount)
{
polygonCollider.pathCount += 1;
}
polygonCollider.SetPath(pathCount, generatedPoints.ToArray());
}
private static void CalculateCell(Cell cell, float bl, float br, float tl, float tr, float threshold)
{
var count = 0;
var index = cellPointCount;
var useBl = bl >= threshold;
var useBr = br >= threshold;
var useTl = tl >= threshold;
var useTr = tr >= threshold;
// Top
if (useTl ^ useTr)
{
var point = GetNextCellPoint(); count += 1;
point.Position = Transform((tl - threshold) / (tl - tr), 1.0f);
point.Inner = Edge.Top;
point.Outer = Edge.Bottom;
}
// Right
if (useTr ^ useBr)
{
var point = GetNextCellPoint(); count += 1;
point.Position = Transform(1.0f, (br - threshold) / (br - tr));
point.Inner = Edge.Right;
point.Outer = Edge.Left;
}
// Bottom
if (useBl ^ useBr)
{
var point = GetNextCellPoint(); count += 1;
point.Position = Transform((bl - threshold) / (bl - br), 0.0f);
point.Inner = Edge.Bottom;
point.Outer = Edge.Top;
}
// Left
if (useTl ^ useBl)
{
var point = GetNextCellPoint(); count += 1;
point.Position = Transform(0.0f, (bl - threshold) / (bl - tl));
point.Inner = Edge.Left;
point.Outer = Edge.Right;
}
// Pair up points
switch (count)
{
case 2:
{
cellPoints[index + 0].Other = cellPoints[index + 1];
cellPoints[index + 1].Other = cellPoints[index + 0];
}
break;
case 4:
{
if (useTl == true && useBl == true)
{
cellPoints[index + 0].Other = cellPoints[index + 1];
cellPoints[index + 1].Other = cellPoints[index + 0];
cellPoints[index + 2].Other = cellPoints[index + 3];
cellPoints[index + 3].Other = cellPoints[index + 2];
}
else
{
cellPoints[index + 0].Other = cellPoints[index + 3];
cellPoints[index + 1].Other = cellPoints[index + 2];
cellPoints[index + 2].Other = cellPoints[index + 1];
cellPoints[index + 3].Other = cellPoints[index + 0];
}
}
break;
}
cell.PointIndex = index;
cell.PointCount = count;
}
private static Cell GetNextCell()
{
var cell = default(Cell);
if (cellCount >= cells.Count)
{
cell = new Cell(); cells.Add(cell);
}
else
{
cell = cells[cellCount];
}
cellCount += 1;
return cell;
}
private static Point GetNextCellPoint()
{
var point = default(Point);
if (cellPointCount >= cellPoints.Count)
{
point = new Point(); cellPoints.Add(point);
}
else
{
point = cellPoints[cellPointCount];
point.Used = false;
}
cellPointCount += 1;
return point;
}
private static void TraceEdges(Cell cell, Point point)
{
tracedEdges.Clear();
TraceEdge(cell, point, false);
TraceEdge(cell, point.Other, true);
}
private static void TraceEdge(Cell cell, Point point, bool last)
{
point.Used = true;
if (last == true)
{
tracedEdges.AddLast(point);
}
else
{
tracedEdges.AddFirst(point);
}
switch (point.Inner)
{
case Edge.Left:
{
cell = GetCell(cell.X - 1, cell.Y);
}
break;
case Edge.Right:
{
cell = GetCell(cell.X + 1, cell.Y);
}
break;
case Edge.Bottom:
{
cell = GetCell(cell.X, cell.Y - 1);
}
break;
case Edge.Top:
{
cell = GetCell(cell.X, cell.Y + 1);
}
break;
}
if (cell != null)
{
for (var i = 0; i < cell.PointCount; i++)
{
var outerPoint = cellPoints[cell.PointIndex + i];
if (outerPoint.Used == false && outerPoint.Inner == point.Outer)
{
outerPoint.Used = true;
TraceEdge(cell, outerPoint.Other, last);
}
}
}
}
private static void OptimizeEdges(float tolerance)
{
if (tolerance > 0.0f && tracedEdges.Count > 2)
{
var a = tracedEdges.First;
var b = a.Next;
var c = b.Next;
while (true)
{
var ab = Vector3.Normalize(b.Value.Position - a.Value.Position);
var bc = Vector3.Normalize(c.Value.Position - b.Value.Position);
var abc = Vector3.Dot(ab, bc);
if (abc > (1.0f - tolerance))
{
tracedEdges.Remove(b);
if (c != tracedEdges.Last)
{
b = c;
c = c.Next;
}
else
{
return;
}
}
else
{
if (c != tracedEdges.Last)
{
a = b;
b = c;
c = c.Next;
}
else
{
return;
}
}
}
}
}
private static float GetAlphaOrDefault(int x, int y)
{
x -= pixelsX;
y -= pixelsY;
if (x >= 0 && y >= 0 && x < pixelsWidth && y < pixelsHeight)
{
return pixels[x + y * pixelsWidth].a;
}
return default(float);
}
private static Cell GetCell(int x, int y)
{
if (x >= 0 && y >= 0 && x < width && y < height)
{
return cells[x + y * width];
}
return null;
}
private static Vector2 Transform(float x, float y)
{
x = x + translation.x;
y = y + translation.y;
return new Vector2(x, y);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6fa7253934c605b4396e5c5715ab962d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,38 @@
using UnityEngine;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class D2D_PopupAttribute : PropertyAttribute
{
public GUIContent[] Names;
public int[] Values;
public D2D_PopupAttribute(params int[] newValues)
{
Names = newValues.Select(v => new GUIContent(v.ToString())).ToArray();
Values = newValues.Select(v => v).ToArray();
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(D2D_PopupAttribute))]
public class D2D_PopupDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (D2D_Helper.BaseRectSet == true)
{
position.x = D2D_Helper.BaseRect.x;
position.width = D2D_Helper.BaseRect.width;
}
var Attribute = (D2D_PopupAttribute)attribute;
EditorGUI.IntPopup(position, property, Attribute.Names, Attribute.Values, label);
}
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b4152e5044d65f84a8deb3eb6face827
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,37 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class D2D_RangeAttribute : PropertyAttribute
{
public float Min;
public float Max;
public D2D_RangeAttribute(float newMin, float newMax)
{
Min = newMin;
Max = newMax;
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(D2D_RangeAttribute))]
public class D2D_RangeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (D2D_Helper.BaseRectSet == true)
{
position.x = D2D_Helper.BaseRect.x;
position.width = D2D_Helper.BaseRect.width;
}
var Attribute = (D2D_RangeAttribute)attribute;
EditorGUI.showMixedValue = property.hasMultipleDifferentValues;
EditorGUI.Slider(position, property, Attribute.Min, Attribute.Max, label);
}
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a8eebccf5a9710945bf59a7f22418110
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,263 @@
using UnityEngine;
using System.Collections.Generic;
public static class D2D_SplitCalculator
{
class Fill
{
public List<int> Indices = new List<int>();
public List<Color32> Colours = new List<Color32>();
public int Count;
public int XMin;
public int XMax;
public int YMin;
public int YMax;
public bool Valid;
}
class Spread
{
public int i;
public int x;
public int y;
}
private static D2D_Destructible target;
private static List<bool> cells = new List<bool>();
private static List<Fill> fills = new List<Fill>();
private static List<Spread> spreads = new List<Spread>();
private static int spreadCount;
private static Fill currentFill;
private static Color32[] pixels;
private static Texture2D tex;
private static int width;
private static int height;
private static int total;
public static bool Generate(D2D_Destructible destructible, D2D_SpriteSplitOrder splitOrder)
{
cells.Clear();
if (destructible != null && destructible.AlphaTex != null)
{
target = destructible;
tex = target.AlphaTex;
width = tex.width;
height = tex.height;
total = width * height;
pixels = tex.GetPixels32();
if (cells.Capacity < total)
{
cells.Capacity = total;
}
var threshold = (byte)(target.SplitThreshold * 255.0f);
for (var i = 0; i < total; i++)
{
cells.Add(pixels[i].a >= threshold);
}
fills.Clear();
var validFillCount = 0;
for (var i = 0; i < total; i++)
{
if (cells[i] == true)
{
currentFill = new Fill(); fills.Add(currentFill);
currentFill.XMin = currentFill.XMax = i % width;
currentFill.YMin = currentFill.YMax = i / width;
BeginFloodFill(i, currentFill.XMin, currentFill.YMin);
// Skip the first floodfill
if (currentFill.Count >= target.SplitMinPixels)
{
currentFill.Valid = true; validFillCount += 1;
}
}
}
// Can we split?
if (validFillCount > 1)
{
var firstSet = false;
switch (splitOrder)
{
case D2D_SpriteSplitOrder.KeepLargest: fills.Sort((a, b) => b.Count.CompareTo(a.Count)); break;
case D2D_SpriteSplitOrder.KeepSmallest: fills.Sort((a, b) => a.Count.CompareTo(b.Count)); break;
}
foreach (var fill in fills)
{
if (fill.Valid == true)
{
if (firstSet == false)
{
firstSet = true;
Split(destructible, fill, false);
}
else
{
var clonedGameObject = D2D_Helper.CloneGameObject(destructible.gameObject, destructible.transform.parent);
var clonedDestructible = clonedGameObject.GetComponent<D2D_Destructible>();
Split(clonedDestructible, fill, true);
}
}
}
return true;
}
if (validFillCount == 0)
{
D2D_Helper.Destroy(destructible.gameObject);
}
}
return false;
}
private static void Split(D2D_Destructible destructible, Fill fill, bool isClone)
{
var clear = new Color32(0, 0, 0, 0);
for (var i = 0; i < total; i++)
{
pixels[i] = clear;
}
for (var i = 0; i < fill.Count; i++)
{
pixels[fill.Indices[i]] = fill.Colours[i];
}
destructible.ReplaceAlphaWith(width, height, pixels);
// Split notification
destructible.BroadcastMessage("OnSpriteSplit", isClone, SendMessageOptions.DontRequireReceiver);
}
private static void BeginFloodFill(int i, int x, int y)
{
var oldSpreadCount = spreadCount = 0;
SpreadTo(i, x, y);
// Non-recursive floodfill
while (spreadCount != oldSpreadCount)
{
var start = oldSpreadCount;
var end = oldSpreadCount = spreadCount;
for (var j = start; j < end; j++)
{
var spread = spreads[j];
FloodFill(spread.i, spread.x, spread.y);
}
}
}
private static void SpreadTo(int i, int x, int y)
{
cells[i] = false;
var spread = default(Spread);
if (spreadCount >= spreads.Count)
{
spread = new Spread(); spreads.Add(spread);
}
else
{
spread = spreads[spreadCount];
}
spread.i = i;
spread.x = x;
spread.y = y;
spreadCount += 1;
}
private static void FloodFill(int i, int x, int y)
{
currentFill.Count += 1;
currentFill.Indices.Add(i);
currentFill.Colours.Add(pixels[i]);
currentFill.XMin = Mathf.Min(currentFill.XMin, x);
currentFill.XMax = Mathf.Max(currentFill.XMax, x);
currentFill.YMin = Mathf.Min(currentFill.YMin, y);
currentFill.YMax = Mathf.Max(currentFill.YMax, y);
// Left
if (x > 0)
{
var n = i - 1;
if (cells[n] == true)
{
SpreadTo(n, x - 1, y);
}
}
// Right
if (x < width - 1)
{
var n = i + 1;
if (cells[n] == true)
{
SpreadTo(n, x + 1, y);
}
}
// Bottom
if (y > 0)
{
var n = i - width;
if (cells[n] == true)
{
SpreadTo(n, x, y - 1);
}
}
// Top
if (y < height - 1)
{
var n = i + width;
if (cells[n] == true)
{
SpreadTo(n, x, y + 1);
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c281e527c4903c14eabbb78f1ff2b654
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData: