protected virtual void Update() { if (destructible == null) destructible = GetComponent<D2D_Destructible>(); if (splittable == null) splittable = GetComponent<D2D_Splittable>(); if (fracturer == null) fracturer = GetComponent<D2D_Fracturer>(); var splitDepth = destructible.SplitDepth; var pixelCount = destructible.SolidPixelCount; if (pixelCount < MinPixelsForDestructible || splitDepth > MaxDepthForDestructible) { destructible.Indestructible = true; } if (splittable != null) { if (pixelCount < MinPixelsForSplitting || splitDepth > MaxDepthForSplitting) { D2D_Helper.Destroy(splittable); } } if (fracturer != null) { if (pixelCount < MinPixelsForFracturing || splitDepth > MaxDepthForFracturing) { D2D_Helper.Destroy(fracturer); } } }
public void UpdateSplit() { if (destructible == null) { destructible = GetComponent <D2D_Destructible>(); } BeginSplitting(); { // Find which pixels are solid for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { cells.Add(alphaTex.GetPixel(x, y).a >= Threshold); } } // Go through all pixels for (var i = 0; i < total; i++) { // First pixel of unclaimed island? if (cells[i] == true) { splitGroup = D2D_SplitBuilder.CreateGroup(); BeginFloodFill(i, i % width, i / width); } } } EndSplitting(); }
private static void Split(D2D_Destructible destructible, D2D_SplitGroup group, bool isClone) { var subX = group.XMin; var subY = group.YMin; var subWidth = group.XMax - group.XMin + 1; var subHeight = group.YMax - group.YMin + 1; var subTotal = subWidth * subHeight; var subAlpha = new byte[subTotal]; for (var i = group.Count - 1; i >= 0; i--) { var j = group.Indices[i]; var a = group.Alphas[i]; var x = (j % AlphaTexWidth) - subX; var y = (j / AlphaTexWidth) - subY; var s = x + y * subWidth; subAlpha[s] = a; } destructible.SubsetAlphaWith(subAlpha, subWidth, subHeight, subX, subY); // Split notification D2D_Helper.BroadcastMessage(destructible.transform, "OnDestructibleSplit", splitData, SendMessageOptions.DontRequireReceiver); }
protected virtual void Update() { if (dirty == true) { dirty = false; destructible = D2D_Helper.GetComponentUpwards <D2D_Destructible>(transform); if (destructible != null) { var alpha = destructible.GetAlpha(transform.TransformPoint(Offset)); // Break fixture? if (alpha < Threshold) { DestroyFixture(); } // Break others? else if (fixtureID > 0) { for (var i = AllFixtures.Count - 1; i >= 0; i--) { var fixture = AllFixtures[i]; if (fixture != null && fixture != this && fixture.fixtureID == fixtureID) { fixture.DestroyFixture(); } } } } } }
public void UpdateSplit() { if (destructible == null) destructible = GetComponent<D2D_Destructible>(); BeginSplitting(); { // Find which pixels are solid for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { cells.Add(alphaTex.GetPixel(x, y).a >= Threshold); } } // Go through all pixels for (var i = 0; i < total; i++) { // First pixel of unclaimed island? if (cells[i] == true) { splitGroup = D2D_SplitBuilder.CreateGroup(); BeginFloodFill(i, i % width, i / width); } } } EndSplitting(); }
protected virtual void Update() { if (dirty == true) { dirty = false; destructible = D2D_Helper.GetComponentUpwards<D2D_Destructible>(transform); if (destructible != null) { var alpha = destructible.GetAlpha(transform.position); // Break fixture? if (alpha < Threshold) { DestroyFixture(); } // Break others? else if (fixtureID > 0) { for (var i = Fixtures.Count - 1; i >= 0; i--) { var fixture = Fixtures[i]; if (fixture != null && fixture != this && fixture.fixtureID == fixtureID) { fixture.DestroyFixture(); } } } } } }
protected virtual void Update() { if (Input.GetMouseButtonDown(0) == true && Camera.main != null) { var ray = Camera.main.ScreenPointToRay(Input.mousePosition); var distance = D2D_Helper.Divide(ray.origin.z, ray.direction.z); var point = ray.origin - ray.direction * distance; D2D_Destructible.StampAll(point, Size, Angle, StampTex, Hardness, Layers); } }
private static void GetPixels(D2D_Destructible destructible, int l, int b, int r, int t) { l = Mathf.Max(l, 0); b = Mathf.Max(b, 0); r = Mathf.Min(r, destructible.AlphaWidth); t = Mathf.Min(t, destructible.AlphaHeight); pixelsL = l; pixelsR = r; pixelsB = b; pixelsT = t; pixelsW = destructible.AlphaWidth; pixels = destructible.AlphaData; }
public static void BeginSplitting(D2D_Destructible newDestructible) { if (newDestructible != null) { D2D_ClassPool <D2D_SplitGroup> .Add(Groups, g => g.AddToPool()); // EndSplitting may not get called, so call here in case destructible = newDestructible; AlphaTex = newDestructible.AlphaTex; AlphaTexWidth = AlphaTex.width; AlphaTexHeight = AlphaTex.height; } }
public void Fracture() { if (destructible == null) { destructible = GetComponent <D2D_Destructible>(); } alphaTex = destructible.AlphaTex; width = alphaTex.width; height = alphaTex.height; total = width * height; D2D_SplitBuilder.BeginSplitting(destructible); { DoFracture(); } D2D_SplitBuilder.EndSplitting(D2D_SplitOrder.Default, Blur); }
protected virtual void Update() { if (Input.GetKey(Requires) == true && down == false) { down = true; startMousePosition = Input.mousePosition; } if (Input.GetKey(Requires) == false && down == true) { down = false; if (Camera.main != null) { var endMousePosition = Input.mousePosition; var startPos = Camera.main.ScreenToWorldPoint(startMousePosition); var endPos = Camera.main.ScreenToWorldPoint(endMousePosition); D2D_Destructible.SliceAll(startPos, endPos, Thickness, StampTex, Hardness); } } if (Indicator != null) { Indicator.enabled = down; if (Camera.main != null && down == true) { var currentMousePosition = Input.mousePosition; var startPos = Camera.main.ScreenToWorldPoint(startMousePosition); var currentPos = Camera.main.ScreenToWorldPoint(currentMousePosition); var scale = Vector3.Distance(currentPos, startPos); var angle = D2D_Helper.Atan2(currentPos - startPos) * Mathf.Rad2Deg; var newPosition = Camera.main.ScreenToWorldPoint(startMousePosition); newPosition.z = Indicator.transform.position.z; Indicator.transform.position = newPosition; Indicator.transform.localRotation = Quaternion.Euler(0.0f, 0.0f, -angle); Indicator.transform.localScale = new Vector3(Thickness, scale, scale); } } }
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); }
protected virtual void Update() { if (destructible == null) { destructible = GetComponent <D2D_Destructible>(); } if (splittable == null) { splittable = GetComponent <D2D_Splittable>(); } if (fracturer == null) { fracturer = GetComponent <D2D_Fracturer>(); } var splitDepth = destructible.SplitDepth; var pixelCount = destructible.SolidPixelCount; if (pixelCount < MinPixelsForDestructible || splitDepth > MaxDepthForDestructible) { destructible.Indestructible = true; } if (splittable != null) { if (pixelCount < MinPixelsForSplitting || splitDepth > MaxDepthForSplitting) { D2D_Helper.Destroy(splittable); } } if (fracturer != null) { if (pixelCount < MinPixelsForFracturing || splitDepth > MaxDepthForFracturing) { D2D_Helper.Destroy(fracturer); } } }
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); }
protected override void Execute() { // var angle = transform.rotation.eulerAngles.z + AngleOffset + Random.Range(-0.5f, 0.5f) * AngleRandomness; D2D_Destructible.StampAll(transform.position, Size, 0f, StampTex, Hardness, Layers); }
public static void EndSplitting(D2D_SplitOrder order, bool blur) { if (destructible != null) { if (Groups.Count > 0) { // Sort switch (order) { case D2D_SplitOrder.KeepLargest: Groups.Sort((a, b) => b.Count.CompareTo(a.Count)); break; case D2D_SplitOrder.KeepSmallest: Groups.Sort((a, b) => a.Count.CompareTo(b.Count)); break; } // Store list of others splitData.SolidPixelCounts.Clear(); for (var i = 0; i < Groups.Count; i++) { splitData.SolidPixelCounts.Add(Groups[i].Count); } // Split for (var i = Groups.Count - 1; i >= 0; i--) { var group = Groups[i]; splitData.Index = i; splitData.IsClone = i > 0; // Split if (i > 0) { var tempAlphaData = destructible.AlphaData; destructible.AlphaData = null; // Clone this destructible without alpha data, because we will manually set it after this var clonedDestructible = D2D_Helper.CloneGameObject(destructible.gameObject, destructible.transform.parent).GetComponent <D2D_Destructible>(); destructible.AlphaData = tempAlphaData; Split(clonedDestructible, group, true, blur); } // Overwrite original else { Split(destructible, group, false, blur); } } } else { D2D_Helper.Destroy(destructible.gameObject); } destructible = null; } D2D_ClassPool <D2D_SplitGroup> .Add(Groups, g => g.AddToPool()); }
// Go through all pixels in the defined area, convert them into cells, and find the lines that pass through the 0.5 opacity threshold public static void Calculate(D2D_Destructible destructible, int newXMin, int newXMax, int newYMin, int newYMax, bool cutEdges, bool binary) { cellCount = 0; cellPointCount = 0; if (destructible != null) { if (cutEdges == true) { xMin = newXMin; if (xMin == 0) { xMin -= 1; // Expand left? } yMin = newYMin; if (yMin == 0) { yMin -= 1; // Expand bottom? } xMax = newXMax; yMax = newYMax; GetPixels(destructible, newXMin - 1, newYMin - 1, newXMax + 1, newYMax + 1); } else { xMin = newXMin - 1; yMin = newYMin - 1; xMax = newXMax + 1; yMax = newYMax + 1; GetPixels(destructible, newXMin, newYMin, newXMax, newYMax); } width = xMax - xMin; height = yMax - yMin; if (width > 0 && height > 0) { if (cells.Capacity < width * height) { cells.Capacity = width * height; } for (var y = 0; y < height; y++) { var y0 = yMin + y; var y1 = y0 + 1; for (var x = 0; x < width; x++) { var x0 = xMin + x; var x1 = x0 + 1; var cell = GetNextCell(); var bl = GetAlphaOrDefault(x0, y0); var br = GetAlphaOrDefault(x1, y0); var tl = GetAlphaOrDefault(x0, y1); var tr = GetAlphaOrDefault(x1, y1); if (binary == true) { bl = bl > 0.5f ? 1.0f : 0.0f; br = br > 0.5f ? 1.0f : 0.0f; tl = tl > 0.5f ? 1.0f : 0.0f; tr = tr > 0.5f ? 1.0f : 0.0f; } cell.X = x; cell.Y = y; translation.x = x0 + 0.5f; translation.y = y0 + 0.5f; CalculateCell(cell, bl, br, tl, tr, 0.5f); } } } } }
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; }
public void Explode() { var angle = transform.rotation.eulerAngles.z + AngleOffset + Random.Range(-0.5f, 0.5f) * AngleRandomness; D2D_Destructible.StampAll(transform.position, Size, angle, StampTex, Hardness, Layers); }