Example #1
0
    /// <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);
    }
Example #2
0
    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();
    }