Search code examples
imageunity-game-engineunity3d-gui

Unity new UI : GUI.DrawTexture ScaleAndCrop equivalent


I want to implement an image gallery with Unity (2D). I have a Canvas logically divided into squares of, say, 100x100 units. Then:

  • each "square" is populated by an image downloaded dynamically from the internet (using the www class);
  • the image is not necessarily square: in this case, I want to "scale and crop the image": the aspect ratio is preserved and the image fills the whole square;
  • when a user clicks on a square, the image expands to its natural size on the middle of the screen. Another click an the image goes back to the square size/position;
  • at a regular interval, a square is taken randomly and its image is replaced by a new one.

I am new to Unity and I already tried a lot of different approaches. My real problem is for the scale and crop. Indeed:

  • the Gui.DrawTexture() takes an argument scaleMode.ScaleAndCrop, which is exactly what I need. But this is part of the old UI system...
  • the new UI offers Image and RawImage Gui components, but out of the box we can either keep aspect ratio or fill the square, not both.
  • I tried to create a "texture thumbnail" by copying a square of pixels into a new texture. It works, but animations between thumbnail and fullsize image are not possible anymore...

I am sure there is a way to use the new UI functionalities and get the scale and crop effect, but I can't figure out how. Would someone have an advice for me ?


Solution

  • You will need to use scaling an GameObject with Image component, and using Mask component.

    I would do this in this way:

    Create canvas with GridLayoutGroup, that will organize the thumbanils Images as you want (3 rows 3 columns etc).

    each image has a parent GameObject with mask that will be set with GridLayoutGroup. Child of Mask will be an Image where you will show the downloaded content.

    Have a reference to each Image component in controller of your choice.

    image1 is a reference to first thumbnail;

    When image is downloaded assign made Sprite of it to the image1.sprite.

    Call image1.SetNativeSize();

    Check the fimage1.GetComponent<RectTransform>().sizeDelta (this is the width and height) and scale the image1 according to the image size, taking in account to fit it into the mask borders. You need basicly some mathematical small algorithm.

    The image1 also has Button component with attached OnClick event that will fire the lets say "ShowImagePressed (Image img)". Parameter is the Image of image1.

    When this handler is fired, disable the mask by image1.transform.parent.GetComponent<Mask>().enabled = false, and scale the image1, moving it to the center.