/// <summary> /// Pack rects inside of a square. Rects should be ordered descending from their volume. /// </summary> public static RectPack PackOrderedRects(List <Rect> rects) { // Find the best packing. Rect drawingArea = new Rect(0, 0, 1, 1); float resizeStep = Mathf.Min(rects[rects.Count - 1].width, rects[rects.Count - 1].height); RectPack finalResult = null; RectPack previousResult = null; while (finalResult == null) { RectPack tempResult = TryPackingRects(rects, drawingArea); if (tempResult.rects.Count == rects.Count) { // Success : retry a pack with a smaller area. previousResult = tempResult; drawingArea = new Rect(drawingArea.position, drawingArea.size - Vector2.one * resizeStep); } else { // Failure: keep the previous result if it was a success, else retry with a bigger area. if (previousResult != null && previousResult.rects.Count == rects.Count) { finalResult = previousResult; } else { drawingArea = new Rect(drawingArea.position, drawingArea.size + Vector2.one * resizeStep); } } } // Trim the edges of the packing area. float maxWidth = 0; float maxHeight = 0; foreach (Rect rect in finalResult.rects) { if (rect.position.x + rect.width > maxWidth) { maxWidth = rect.position.x + rect.width; } if (rect.position.y + rect.width > maxHeight) { maxHeight = rect.position.y + rect.height; } } finalResult.area.size = Vector2.one * Mathf.Max(maxWidth, maxHeight); return(finalResult); }
void OnGUI() { // Get rects from test ratios. List <Rect> ratiosRects = new List <Rect>(); foreach (float ratio in ratios) { ratiosRects.Add(RatioToRect(ratio)); } // Pack rects. if (rects.Count < 1) { RectPack packingResult = RectPacker.PackOrderedRects(ratiosRects); float areaRatio = 1 / packingResult.area.width; foreach (Rect packedRect in packingResult.rects) { rects.Add(new Rect(packedRect.position * areaRatio, packedRect.size * areaRatio)); } } // Draw title and area. GUILayout.Label("UVs", EditorStyles.boldLabel); Rect uVDisplayRect = EditorGUILayout.GetControlRect(GUILayout.Width(300), GUILayout.Height(300)); EditorGUI.DrawRect(new Rect(uVDisplayRect.position, uVDisplayRect.size), Color.grey); // Draw rects. Vector2 startPosition = new Vector2(uVDisplayRect.x, uVDisplayRect.y + uVDisplayRect.height); float displayArea = uVDisplayRect.width * uVDisplayRect.height; for (int i = 0; i < rects.Count; i++) { GUI.Label(new Rect(rects[i].position * uVDisplayRect.width + uVDisplayRect.position, rects[i].size * uVDisplayRect.width), i.ToString(), GUI.skin.textArea); } if (GUILayout.Button("Reset")) { rects.Clear(); } // Ratios property. SerializedObject so = new SerializedObject(this); SerializedProperty ratiosProperty = so.FindProperty("ratios"); EditorGUILayout.PropertyField(ratiosProperty); so.ApplyModifiedProperties(); }