Initial commit

This commit is contained in:
AbstractConcept 2022-09-13 00:36:34 -05:00
commit 3c7cc0c973
8391 changed files with 704313 additions and 0 deletions

View file

@ -0,0 +1,213 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.U2D.Common
{
internal interface IImagePackNodeVisitor
{
void Visit(ImagePackNode node);
}
class CollectEmptyNodePositionVisitor : IImagePackNodeVisitor
{
public List<RectInt> emptyAreas = new List<RectInt>();
public void Visit(ImagePackNode node)
{
if (node.imageId == -1)
{
emptyAreas.Add(node.rect);
}
}
}
class CollectPackNodePositionVisitor : IImagePackNodeVisitor
{
public CollectPackNodePositionVisitor()
{
positions = new Vector2Int[0];
}
public void Visit(ImagePackNode node)
{
if (node.imageId != -1)
{
if (positions.Length < node.imageId + 1)
{
var p = positions;
Array.Resize(ref p, node.imageId + 1);
positions = p;
}
positions[node.imageId].x = node.rect.x;
positions[node.imageId].y = node.rect.y;
}
}
public Vector2Int[] positions { get; private set; }
}
internal class ImagePackNode
{
public ImagePackNode left;
public ImagePackNode right;
public RectInt rect;
public Vector2Int imageWidth;
public int imageId = -1;
public void AcceptVisitor(IImagePackNodeVisitor visitor)
{
visitor.Visit(this);
if (left != null)
left.AcceptVisitor(visitor);
if (right != null)
right.AcceptVisitor(visitor);
}
public void AdjustSize(int oriWidth, int oriHeight, int deltaW, int deltaH, out int adjustx, out int adjusty)
{
adjustx = adjusty = 0;
int adjustXleft = 0, adjustYleft = 0, adjustXRight = 0, adjustYRight = 0;
if (imageId == -1 || left == null)
{
if (rect.x + rect.width == oriWidth)
{
rect.width += deltaW;
adjustx = deltaW;
}
if (rect.y + rect.height == oriHeight)
{
rect.height += deltaH;
adjusty = deltaH;
}
}
else
{
left.AdjustSize(oriWidth, oriHeight, deltaW, deltaH, out adjustXleft, out adjustYleft);
right.AdjustSize(oriWidth, oriHeight, deltaW, deltaH, out adjustXRight, out adjustYRight);
adjustx = Mathf.Max(adjustXleft, adjustXRight);
rect.width += adjustx;
adjusty = Mathf.Max(adjustYleft, adjustYRight);
rect.height += adjusty;
}
}
public bool TryInsert(ImagePacker.ImagePackRect insert, int padding, out Vector2Int remainingSpace)
{
remainingSpace = Vector2Int.zero;
int insertWidth = insert.rect.width + padding * 2;
int insertHeight = insert.rect.height + padding * 2;
if (insertWidth > rect.width || insertHeight > rect.height)
return false;
if (imageId == -1)
{
remainingSpace.x = rect.width - insertWidth;
remainingSpace.y = rect.height - insertHeight;
}
else
{
Vector2Int spaceLeft, spaceRight;
bool insertLeft, insertRight;
ImagePackNode tryLeft, tryRight;
tryLeft = left;
tryRight = right;
if (left == null && !SplitRects(this, insert, padding, out tryLeft, out tryRight))
{
return false;
}
insertLeft = tryLeft.TryInsert(insert, padding, out spaceLeft);
insertRight = tryRight.TryInsert(insert, padding, out spaceRight);
if (insertLeft && insertRight)
{
remainingSpace = spaceLeft.sqrMagnitude < spaceRight.sqrMagnitude ? spaceLeft : spaceRight;
}
else if (insertLeft)
remainingSpace = spaceLeft;
else if (insertRight)
remainingSpace = spaceRight;
else
return false;
}
return true;
}
static bool SplitRects(ImagePackNode node, ImagePacker.ImagePackRect insert, int padding, out ImagePackNode left, out ImagePackNode right)
{
// Find the best way to split the rect based on a new rect
left = right = null;
var tryRects = new[]
{
new ImagePackNode(), new ImagePackNode(),
new ImagePackNode(), new ImagePackNode()
};
tryRects[0].rect = new RectInt(node.rect.x + node.imageWidth.x, node.rect.y, node.rect.width - node.imageWidth.x, node.rect.height);
tryRects[1].rect = new RectInt(node.rect.x, node.rect.y + node.imageWidth.y, node.imageWidth.x, node.rect.height - node.imageWidth.y);
tryRects[2].rect = new RectInt(node.rect.x, node.rect.y + node.imageWidth.y, node.rect.width, node.rect.height - node.imageWidth.y);
tryRects[3].rect = new RectInt(node.rect.x + node.imageWidth.x, node.rect.y, node.rect.width - node.imageWidth.x, node.imageWidth.y);
float smallestSpace = float.MinValue;
for (int i = 0; i < tryRects.GetLength(0); ++i)
{
//for (int j = 0; j < tryRects.GetLength(1); ++j)
{
Vector2Int newSpaceLeft;
if (tryRects[i].TryInsert(insert, padding, out newSpaceLeft))
{
if (smallestSpace < newSpaceLeft.sqrMagnitude)
{
smallestSpace = newSpaceLeft.sqrMagnitude;
int index = i / 2 * 2;
left = tryRects[index];
right = tryRects[index + 1];
}
}
}
}
return left != null;
}
public bool Insert(ImagePacker.ImagePackRect insert, int padding)
{
int insertWidth = insert.rect.width + padding * 2;
int insertHeight = insert.rect.height + padding * 2;
if (insertWidth > rect.width || insertHeight > rect.height)
return false;
if (imageId == -1)
{
imageId = insert.index;
imageWidth = new Vector2Int(insertWidth, insertHeight);
}
else
{
if (left == null && !SplitRects(this, insert, padding, out left, out right))
{
return false;
}
// We assign to the node that has a better fit for the image
Vector2Int spaceLeft, spaceRight;
bool insertLeft, insertRight;
insertLeft = left.TryInsert(insert, padding, out spaceLeft);
insertRight = right.TryInsert(insert, padding, out spaceRight);
if (insertLeft && insertRight)
{
if (spaceLeft.sqrMagnitude < spaceRight.sqrMagnitude)
left.Insert(insert, padding);
else
right.Insert(insert, padding);
}
else if (insertLeft)
left.Insert(insert, padding);
else if (insertRight)
right.Insert(insert, padding);
else
return false;
}
return true;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 488b804e650114066b55d51eefc85775
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,193 @@
//#define PACKING_DEBUG
using System;
using UnityEngine;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace UnityEditor.U2D.Common
{
internal static class ImagePacker
{
/// <summary>
/// Given an array of rects, the method returns an array of rects arranged within outPackedWidth and outPackedHeight
/// </summary>
/// <param name="rects">Rects to pack</param>
/// <param name="padding">Padding between each rect</param>
/// <param name="outPackedRects">Rects arranged within outPackedWidth and outPackedHeight</param>
/// <param name="outPackedWidth">Width of the packed rects</param>
/// <param name="outPackedHeight">Height of the packed rects</param>
public static void Pack(RectInt[] rects, int padding, out RectInt[] outPackedRects, out int outPackedWidth, out int outPackedHeight)
{
var packNode = InternalPack(rects, padding);
outPackedWidth = packNode.rect.width;
outPackedHeight = packNode.rect.height;
var visitor = new CollectPackNodePositionVisitor();
packNode.AcceptVisitor(visitor);
outPackedRects = new RectInt[rects.Length];
for (int i = 0; i < rects.Length; ++i)
outPackedRects[i] = new RectInt(visitor.positions[i].x + padding, visitor.positions[i].y + padding, rects[i].width, rects[i].height);
#if PACKING_DEBUG
var emptyNodeCollector = new CollectEmptyNodePositionVisitor();
packNode.AcceptVisitor(emptyNodeCollector);
Array.Resize(ref outPackedRects, rects.Length + emptyNodeCollector.emptyAreas.Count);
for (int i = rects.Length; i < outPackedRects.Length; ++i)
outPackedRects[i] = emptyNodeCollector.emptyAreas[i - rects.Length];
#endif
}
/// <summary>
/// Packs image buffer into a single buffer. Image buffers are assumed to be 4 bytes per pixel in RGBA format
/// </summary>
/// <param name="buffers">Image buffers to pack</param>
/// <param name="width">Image buffers width</param>
/// <param name="height">Image buffers height</param>
/// <param name="padding">Padding between each packed image</param>
/// <param name="outPackedBuffer">Packed image buffer</param>
/// <param name="outPackedBufferWidth">Packed image buffer's width</param>
/// <param name="outPackedBufferHeight">Packed iamge buffer's height</param>
/// <param name="outPackedRect">Location of each image buffers in the packed buffer</param>
/// <param name="outUVTransform">Translation data from image original buffer to packed buffer</param>
public static void Pack(NativeArray<Color32>[] buffers, int width, int height, int padding, out NativeArray<Color32> outPackedBuffer, out int outPackedBufferWidth, out int outPackedBufferHeight, out RectInt[] outPackedRect, out Vector2Int[] outUVTransform)
{
UnityEngine.Profiling.Profiler.BeginSample("Pack");
// Determine the area that contains data in the buffer
outPackedBuffer = default(NativeArray<Color32>);
try
{
var tightRects = FindTightRectJob.Execute(buffers, width, height);
Pack(tightRects, padding, out outPackedRect, out outPackedBufferWidth, out outPackedBufferHeight);
outUVTransform = new Vector2Int[tightRects.Length];
for (int i = 0; i < outUVTransform.Length; ++i)
{
outUVTransform[i] = new Vector2Int(outPackedRect[i].x - tightRects[i].x, outPackedRect[i].y - tightRects[i].y);
}
outPackedBuffer = new NativeArray<Color32>(outPackedBufferWidth * outPackedBufferHeight, Allocator.Temp);
Blit(outPackedBuffer, outPackedRect, outPackedBufferWidth, buffers, tightRects, width, padding);
}
catch (Exception ex)
{
if (outPackedBuffer.IsCreated)
outPackedBuffer.Dispose();
throw ex;
}
finally
{
UnityEngine.Profiling.Profiler.EndSample();
}
}
static ImagePackNode InternalPack(RectInt[] rects, int padding)
{
if (rects == null || rects.Length == 0)
return new ImagePackNode() { rect = new RectInt(0, 0, 0, 0)};
var sortedRects = new ImagePackRect[rects.Length];
for (int i = 0; i < rects.Length; ++i)
{
sortedRects[i] = new ImagePackRect();
sortedRects[i].rect = rects[i];
sortedRects[i].index = i;
}
Array.Sort<ImagePackRect>(sortedRects);
var root = new ImagePackNode();
root.rect = new RectInt(0, 0, (int)NextPowerOfTwo((ulong)rects[0].width), (int)NextPowerOfTwo((ulong)rects[0].height));
for (int i = 0; i < rects.Length; ++i)
{
if (!root.Insert(sortedRects[i], padding)) // we can't fit
{
int newWidth = root.rect.width , newHeight = root.rect.height;
if (root.rect.width < root.rect.height)
newWidth = (int)NextPowerOfTwo((ulong)root.rect.width + 1);
else
newHeight = (int)NextPowerOfTwo((ulong)root.rect.height + 1);
// Reset all packing and try again
root = new ImagePackNode();
root.rect = new RectInt(0, 0, newWidth, newHeight);
i = -1;
}
}
return root;
}
public static unsafe void Blit(NativeArray<Color32> buffer, RectInt[] blitToArea, int bufferbytesPerRow, NativeArray<Color32>[] originalBuffer, RectInt[] blitFromArea, int bytesPerRow, int padding)
{
UnityEngine.Profiling.Profiler.BeginSample("Blit");
var c = (Color32*)buffer.GetUnsafePtr();
for (int bufferIndex = 0; bufferIndex < blitToArea.Length && bufferIndex < originalBuffer.Length && bufferIndex < blitFromArea.Length; ++bufferIndex)
{
var b = (Color32*)originalBuffer[bufferIndex].GetUnsafeReadOnlyPtr();
var rectFrom = blitFromArea[bufferIndex];
var rectTo = blitToArea[bufferIndex];
for (int i = 0; i < rectFrom.height; ++i)
{
for (int j = 0; j < rectFrom.width; ++j)
{
Color32 cc = b[(rectFrom.y + i) * bytesPerRow + rectFrom.x + j];
c[((rectTo.y + i) * bufferbytesPerRow) + rectTo.x + j] = cc;
}
}
}
#if PACKING_DEBUG
var emptyColors = new Color32[]
{
new Color32((byte)255, (byte)0, (byte)0, (byte)255),
new Color32((byte)255, (byte)255, (byte)0, (byte)255),
new Color32((byte)255, (byte)0, (byte)255, (byte)255),
new Color32((byte)255, (byte)255, (byte)255, (byte)255),
new Color32((byte)0, (byte)255, (byte)0, (byte)255),
new Color32((byte)0, (byte)0, (byte)255, (byte)255)
};
for (int k = originalBuffer.Length; k < blitToArea.Length; ++k)
{
var rectFrom = blitToArea[k];
for (int i = 0; i < rectFrom.height; ++i)
{
for (int j = 0; j < rectFrom.width; ++j)
{
c[((rectFrom.y + i) * bufferbytesPerRow) + rectFrom.x + j] =
emptyColors[k % emptyColors.Length];
}
}
}
#endif
UnityEngine.Profiling.Profiler.EndSample();
}
internal static ulong NextPowerOfTwo(ulong v)
{
v -= 1;
v |= v >> 16;
v |= v >> 8;
v |= v >> 4;
v |= v >> 2;
v |= v >> 1;
return v + 1;
}
internal class ImagePackRect : IComparable<ImagePackRect>
{
public RectInt rect;
public int index;
public int CompareTo(ImagePackRect obj)
{
var lhsArea = rect.width * rect.height;
var rhsArea = obj.rect.width * obj.rect.height;
if (lhsArea > rhsArea)
return -1;
if (lhsArea < rhsArea)
return 1;
if (index < obj.index)
return -1;
return 1;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ea81e02715034d7e81c7c8e6f5e3329
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,300 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.U2D.Sprites;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
namespace UnityEditor.U2D.Common
{
internal class ImagePackerDebugEditor : EditorWindow
{
[MenuItem("internal:Window/2D/Common/Image Packer Debug Editor")]
static void Launch()
{
var window = EditorWindow.GetWindow<ImagePackerDebugEditor>();
var pos = window.position;
pos.height = pos.width = 400;
window.position = pos;
window.Show();
}
ReorderableList m_ReorderableList;
ImagePacker.ImagePackRect[] m_PackingRect = null;
List<RectInt> m_PackRects = new List<RectInt>();
RectInt[] m_PackResult = null;
SpriteRect[] m_SpriteRects = null;
Texture2D m_Texture;
int m_TextureActualWidth = 0;
int m_TextureActualHeight = 0;
int m_PackWidth = 0;
int m_PackHeight = 0;
int m_Padding = 0;
Vector2 m_ConfigScroll = Vector2.zero;
float m_Zoom = 1;
IMGUIContainer m_PackArea;
int m_PackStep = -1;
protected const float k_MinZoomPercentage = 0.9f;
protected const float k_WheelZoomSpeed = 0.03f;
protected const float k_MouseZoomSpeed = 0.005f;
void OnEnable()
{
var visualContainer = new VisualElement()
{
name = "Container",
style =
{
flexGrow = 1,
flexDirection = FlexDirection.Row
}
};
this.rootVisualElement.Add(visualContainer);
var imgui = new IMGUIContainer(OnConfigGUI)
{
name = "Config",
style =
{
width = 300
}
};
visualContainer.Add(imgui);
m_PackArea = new IMGUIContainer(OnImagePackerGUI)
{
name = "ImagePacker",
style =
{
flexGrow = 1,
}
};
visualContainer.Add(m_PackArea);
SetupConfigGUI();
}
void SetupConfigGUI()
{
m_ReorderableList = new ReorderableList(m_PackRects, typeof(RectInt), false, false, true, true);
m_ReorderableList.elementHeightCallback = (int index) =>
{
return EditorGUIUtility.singleLineHeight * 2 + 6;
};
m_ReorderableList.drawElementCallback = DrawListElement;
m_ReorderableList.onAddCallback = (list) =>
{
m_PackRects.Add(new RectInt());
};
m_ReorderableList.onRemoveCallback = (list) =>
{
m_PackRects.RemoveAt(list.index);
};
}
void DrawListElement(Rect rect, int index, bool isactive, bool isfocused)
{
var rectInt = m_PackRects[index];
var name = m_SpriteRects == null || index >= m_SpriteRects.Length ? index.ToString() : m_SpriteRects[index].
name;
rectInt.size = EditorGUI.Vector2IntField(rect, name, rectInt.size);
m_PackRects[index] = rectInt;
}
void OnConfigGUI()
{
EditorGUILayout.BeginVertical();
m_ConfigScroll = EditorGUILayout.BeginScrollView(m_ConfigScroll);
m_ReorderableList.DoLayoutList();
EditorGUILayout.EndScrollView();
GUILayout.FlexibleSpace();
m_PackStep = EditorGUILayout.IntSlider("Step", m_PackStep, 0, m_PackRects.Count);
EditorGUI.BeginChangeCheck();
m_Texture = EditorGUILayout.ObjectField(new GUIContent("Texture"), (Object)m_Texture, typeof(Texture2D), false) as Texture2D;
if (EditorGUI.EndChangeCheck())
UpdateSpriteRect();
m_Padding = EditorGUILayout.IntField("Padding", m_Padding);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("<<"))
{
m_PackStep = m_PackStep <= 0 ? 0 : m_PackStep - 1;
Pack();
}
if (GUILayout.Button("Pack"))
Pack();
if (GUILayout.Button(">>"))
{
m_PackStep = m_PackStep > m_PackRects.Count ? m_PackRects.Count : m_PackStep + 1;
Pack();
}
if (GUILayout.Button("Clear"))
{
m_PackRects.Clear();
m_Texture = null;
m_PackingRect = null;
m_PackResult = null;
m_SpriteRects = null;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
void UpdateSpriteRect()
{
var dataProvider = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(m_Texture)) as ISpriteEditorDataProvider;
if (dataProvider == null)
return;
dataProvider.InitSpriteEditorDataProvider();
dataProvider.GetDataProvider<ITextureDataProvider>().GetTextureActualWidthAndHeight(out m_TextureActualWidth, out m_TextureActualHeight);
m_SpriteRects = dataProvider.GetDataProvider<ISpriteEditorDataProvider>().GetSpriteRects();
m_PackRects.Clear();
m_PackRects.AddRange(m_SpriteRects.Select(x => new RectInt((int)x.rect.x, (int)x.rect.y, (int)x.rect.width, (int)x.rect.height)));
m_PackResult = null;
m_PackStep = m_PackRects.Count;
}
void Pack()
{
int count = m_PackStep > 0 && m_PackStep < m_PackRects.Count ? m_PackStep : m_PackRects.Count;
m_PackingRect = new ImagePacker.ImagePackRect[m_PackRects.Count];
for (int i = 0; i < m_PackRects.Count; ++i)
{
m_PackingRect[i] = new ImagePacker.ImagePackRect()
{
rect = m_PackRects[i],
index = i
};
}
Array.Sort(m_PackingRect);
ImagePacker.Pack(m_PackingRect.Take(count).Select(x => x.rect).ToArray(), m_Padding, out m_PackResult, out m_PackWidth, out m_PackHeight);
}
void DrawLabel(Rect rect, string label)
{
rect.position = Handles.matrix.MultiplyPoint(rect.position);
GUI.Label(rect, label);
}
void OnImagePackerGUI()
{
if (m_PackResult == null)
return;
HandleZoom();
var oldMatrix = Handles.matrix;
SetupHandlesMatrix();
Handles.DrawSolidRectangleWithOutline(new Rect(0, 0, m_PackWidth, m_PackHeight), Color.gray, Color.black);
DrawLabel(new Rect(0, 0, m_PackWidth, m_PackHeight), m_PackWidth + "x" + m_PackHeight);
int index = 0;
foreach (var rect in m_PackResult)
{
Handles.DrawSolidRectangleWithOutline(new Rect(rect.x, rect.y, rect.width, rect.height), Color.white, Color.black);
var rect1 = new Rect(rect.x, rect.y + rect.height * 0.5f, rect.width, EditorGUIUtility.singleLineHeight);
DrawLabel(rect1, m_PackingRect[index].index.ToString());
++index;
}
index = 0;
if (m_Texture != null && m_SpriteRects != null)
{
var material = new Material(Shader.Find("Sprites/Default"));
material.mainTexture = m_Texture;
material.SetPass(0);
int mouseOverIndex = -1;
GL.PushMatrix();
GL.LoadIdentity();
GL.MultMatrix(GUI.matrix * Handles.matrix);
GL.Begin(GL.QUADS);
for (int i = 0; i < m_PackResult.Length; ++i)
{
index = m_PackingRect[i].index;
if (index >= m_SpriteRects.Length)
continue;
var rect = m_PackResult[i];
GL.TexCoord(new Vector3(m_SpriteRects[index].rect.x / m_TextureActualWidth, m_SpriteRects[index].rect.y / m_TextureActualHeight, 0));
GL.Vertex(new Vector3(rect.x, rect.y, 0));
GL.TexCoord(new Vector3(m_SpriteRects[index].rect.xMax / m_TextureActualWidth, m_SpriteRects[index].rect.y / m_TextureActualHeight, 0));
GL.Vertex(new Vector3(rect.x + rect.width, rect.y, 0));
GL.TexCoord(new Vector3(m_SpriteRects[index].rect.xMax / m_TextureActualWidth, m_SpriteRects[index].rect.yMax / m_TextureActualHeight, 0));
GL.Vertex(new Vector3(rect.x + rect.width, rect.y + rect.height, 0));
GL.TexCoord(new Vector3(m_SpriteRects[index].rect.x / m_TextureActualWidth, m_SpriteRects[index].rect.yMax / m_TextureActualHeight, 0));
GL.Vertex(new Vector3(rect.x, rect.y + rect.height, 0));
var m = Handles.matrix.inverse.MultiplyPoint(Event.current.mousePosition);
if (rect.Contains(new Vector2Int((int)m.x, (int)m.y)))
{
mouseOverIndex = index;
}
++index;
}
GL.End();
GL.PopMatrix();
if (mouseOverIndex >= 0)
{
var text = new GUIContent(m_SpriteRects[mouseOverIndex].name + " " + index);
var length = EditorStyles.textArea.CalcSize(text);
var rect1 = new Rect(m_PackResult[mouseOverIndex].x, m_PackResult[mouseOverIndex].y + m_PackResult[mouseOverIndex].height * 0.5f, length.x, length.y);
rect1.position = Handles.matrix.MultiplyPoint(rect1.position);
if (Event.current.type == EventType.Repaint)
EditorStyles.textArea.Draw(rect1, text, false, false, false, false);
}
}
Handles.matrix = oldMatrix;
}
void SetupHandlesMatrix()
{
Vector3 handlesPos = new Vector3(0, m_PackHeight * m_Zoom, 0f);
Vector3 handlesScale = new Vector3(m_Zoom, -m_Zoom, 1f);
Handles.matrix = Matrix4x4.TRS(handlesPos, Quaternion.identity, handlesScale);
}
protected void HandleZoom()
{
bool zoomMode = Event.current.alt && Event.current.button == 1;
if (zoomMode)
{
EditorGUIUtility.AddCursorRect(m_PackArea.worldBound, MouseCursor.Zoom);
}
if (
((Event.current.type == EventType.MouseUp || Event.current.type == EventType.MouseDown) && zoomMode) ||
((Event.current.type == EventType.KeyUp || Event.current.type == EventType.KeyDown) && Event.current.keyCode == KeyCode.LeftAlt)
)
{
Repaint();
}
if (Event.current.type == EventType.ScrollWheel || (Event.current.type == EventType.MouseDrag && Event.current.alt && Event.current.button == 1))
{
float zoomMultiplier = 1f - Event.current.delta.y * (Event.current.type == EventType.ScrollWheel ? k_WheelZoomSpeed : -k_MouseZoomSpeed);
// Clamp zoom
float wantedZoom = m_Zoom * zoomMultiplier;
float currentZoom = Mathf.Clamp(wantedZoom, GetMinZoom(), 1);
if (currentZoom != m_Zoom)
{
m_Zoom = currentZoom;
Event.current.Use();
}
}
}
protected float GetMinZoom()
{
if (m_Texture == null)
return 1.0f;
return Mathf.Min(m_PackArea.worldBound.width / m_PackWidth, m_PackArea.worldBound.height / m_PackHeight, 0.05f) * k_MinZoomPercentage;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13c5c1934f6f927419763b01ff95ed74
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 55c552c82618a429ebc328c8ba27b416
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,59 @@
using System;
using UnityEngine;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
namespace UnityEditor.U2D.Common
{
public struct FindTightRectJob : IJobParallelFor
{
[ReadOnly]
[DeallocateOnJobCompletion]
NativeArray<IntPtr> m_Buffers;
[ReadOnly]
int m_Width;
[ReadOnly]
int m_Height;
NativeArray<RectInt> m_Output;
public unsafe void Execute(int index)
{
var rect = new RectInt(m_Width, m_Height, 0, 0);
var color = (Color32*)m_Buffers[index].ToPointer();
for (int i = 0; i < m_Height; ++i)
{
for (int j = 0; j < m_Width; ++j)
{
if (color->a != 0)
{
rect.x = Mathf.Min(j, rect.x);
rect.y = Mathf.Min(i, rect.y);
rect.width = Mathf.Max(j, rect.width);
rect.height = Mathf.Max(i, rect.height);
}
++color;
}
}
rect.width = Mathf.Max(0, rect.width - rect.x + 1);
rect.height = Mathf.Max(0, rect.height - rect.y + 1);
m_Output[index] = rect;
}
public static unsafe RectInt[] Execute(NativeArray<Color32>[] buffers, int width, int height)
{
var job = new FindTightRectJob();
job.m_Buffers = new NativeArray<IntPtr>(buffers.Length, Allocator.TempJob);
for (int i = 0; i < buffers.Length; ++i)
job.m_Buffers[i] = new IntPtr(buffers[i].GetUnsafeReadOnlyPtr());
job.m_Output = new NativeArray<RectInt>(buffers.Length, Allocator.TempJob);
job.m_Width = width;
job.m_Height = height;
// Ensure all jobs are completed before we return since we don't own the buffers
job.Schedule(buffers.Length, 1).Complete();
var rects = job.m_Output.ToArray();
job.m_Output.Dispose();
return rects;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9b3eb1ded0fb747809431ebbd42aa4f3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: