Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by BilboStabbins · Nov 19, 2014 at 10:42 PM · texturescalingzoomngui

How to scale a sprite to the size of a Rect on screen?

Hi,

I'd like to do some zooming in NGUI and as it's not supposed to have it's camera orthographic size changed (according to the creator), I'm instead scaling and re-positioning a sprite (a map). The map has a number of buttons scattered over it and I'd like to zoom in (scale it up) as much as possible so that they are all on screen (the buttons are also child object of the map).

To give a brief overview of how it works;

Scale

To calculate the correct scale to aim for, I first found all the colliders of the buttons and extracted their X and Y coordinates. I then found the smallest and largest X and Y values and created a Rect box (which I'll refer to as the 'bounding box') from them. The bounding box now surrounds all of the buttons and represents what the scaled map should look like (i.e the full screen view). To find the relative proportions of the Map to the bounding box, I divided the Map's width and height by the bounding box's width and height. I then used this value to determine the best scale value (a single value for both X and Y) to use based on these proportions. I'm using the Map's Transform to scale it (as well as the buttons, as they are child objects). The scaling works well and Lerps to the correct value, (and therefore the size) that the map should be. I know this because if I manually move the camera in Scene view so that all buttons are on screen (once the map is fully scaled) the full screen view is identical to that of the Gizmo showing the bounding box.

Position

However, I'm having some trouble with the positioning of the Map/Camera. I'm thinking that moving the camera is the way to go here as there are fewer things connected to it. To calculate the correct position that it should move to, I'm using the bounding box's centre value (that is, Rect.centre). The problem is, that it doesn't seem to be moving to the correct position. I'm not sure what the problem is but have a feeling is might have to do with the coordinate systems used. I've tried converting the centre position to world space, but this makes no difference.

Object Structure

 NGUIRoot
 - 2D Camera
 - Map Panel (This holds the script)
 - - Map Sprite (this is what is scaled)

Any help would be very much appreciated as I'm not really sure what to try next.

The script is below, I've tried to comment is as much as possible but it should hopefully be quite straight forward.

 public static ScaleMapZoom instance;
     public List<Transform> targets = new List<Transform>();
     public List<float> BBoxXs = new List<float>();
     public List<float> BBoxYs = new List<float>();
 
     public float smallestX;
     public float largestX;
     public float smallestY;
     public float largestY;
 
     public float boundingBoxPadding = 2f;
 
     public bool doZoom = false;
     public float ScaleDuration = 0.5f;
     public Rect BoundingBoxSize;
     public float ZoomedMapScale = 0;
 
     public Camera NGUICam;
     public GameObject Map;
     public Transform LeftAnchor;
     public Transform RightAnchor;
     public Transform TopAnchor;
     public Transform BottomAnchor;
 
     private Vector2 rectBottomleftW;
     private Vector2 rectTopRightW;
 
     private Vector3 pos;
     private float origZpos;
     public Rect boundingBox;
     private Vector2 MidPoint;
     private bool hasZoomed = false;
 
     void Awake()
     {
         instance = this;
 
         // Cache original Z coordinate of camera.
         origZpos = NGUICam.transform.position.z;
     }
 
     void Update()
     {
         if (Input.GetKey(KeyCode.Z) && !hasZoomed)
         {
             hasZoomed = true;
             
             // Add all buttons to list.
             targets.Clear();
             foreach (GameObject go in HeadTracker.instance.HeadsList)
             {
                 targets.Add(go.transform);
             }
                // Find out the size the bounding box needs to be to contain all the heads in the scene.
             boundingBox = CalculateTargetsBoundingBox();
 
             // Find the centre position of the box. This is where the Map will have to moved to.
             pos = CalculateMapPosition(boundingBox);
             
             // Calculate the scale the map has to be to reflect the bounding box and fill the screen.
             ZoomedMapScale = CalculateMapScale(boundingBox);
 
             // Position and scale the map.
             StartCoroutine(TransposeMap());
         }
 }
 
     Rect CalculateTargetsBoundingBox()
     {
         // Initialise the variables required to hold the coordinates and set them to infinity (plus or minus).
         float minX = Mathf.Infinity;
         float maxX = Mathf.NegativeInfinity;
         float minY = Mathf.Infinity;
         float maxY = Mathf.NegativeInfinity;
 
         BBoxXs.Clear();
         BBoxYs.Clear();
 
         // Loop through the targets..
         foreach (Transform t in targets)
         {
             minX = t.GetComponent<Collider>().bounds.min.x;
             maxX = t.GetComponent<Collider>().bounds.max.x;
             minY = t.GetComponent<Collider>().bounds.min.y;
             maxY = t.GetComponent<Collider>().bounds.max.y;
 
             BBoxXs.Add(minX);
             BBoxXs.Add(maxX);
 
             BBoxYs.Add(minY);
             BBoxYs.Add(maxY);
 
             // Find min and max values 
             float[] minMaxX = FindMinMaxValues(BBoxXs.ToArray());
             float[] minMaxY = FindMinMaxValues(BBoxYs.ToArray());
 
             smallestX = minMaxX[0];
             largestX  = minMaxX[1];
 
             smallestY = minMaxY[0];
             largestY  = minMaxY[1];
         }
         
         // Create the Rect Bounding box
         BoundingBoxSize = Rect.MinMaxRect(
                                         smallestX,
                                         largestY,
                                         largestX,
                                         smallestY);
 
         rectBottomleftW = new Vector2(smallestX, smallestY);
         rectTopRightW   = new Vector2(largestX, largestY);
 
         // Used for the GIzmo
         MidPoint = (rectBottomleftW - rectTopRightW) * 0.5f + rectTopRightW;
 
         // Return the Rect
         return BoundingBoxSize;
     }
 
     float[] FindMinMaxValues(float[] floatArray)
     {
         float max = floatArray[0];
         float min = floatArray[0];
 
         for (int i = 1; i < floatArray.Length; i++)
         {
             if (floatArray[i] > max)
             {
                 max = floatArray[i];
             }
             if (floatArray[i] < min)
             {
                 min = floatArray[i];
             }
         }
 
         float[] minMaxArray = { min, max };
         return minMaxArray;
     }
 
     // Not sure about this function
     Vector3 CalculateMapPosition(Rect boundingBox)
     {
         // Cache the center position of the bounding box (i.e. where the camera should be).
         Vector2 boundingBoxCenter = boundingBox.center;
 
         // Turn into a Vector3
         Vector3 centre = new Vector3(boundingBoxCenter.x, boundingBoxCenter.y, Map.transform.position.z);
 
         // Return the position, keeping the original camera Z-coordinate.
         return centre;
     }
 
     float CalculateMapScale(Rect boundingBox)
     {
         // Find the Map width and height - anchors placed on map in scene
         float mapWidth  = RightAnchor.position.x - LeftAnchor.position.x;
         float mapHeight = TopAnchor.position.y - BottomAnchor.position.y;
 
         // Calculate the proportion difference between the Map and Bounding Box (width and height)
         float newMapWScale = (mapWidth / boundingBox.width);
         float newMapHScale = (mapHeight / Mathf.Abs(boundingBox.height));
 
         // Determine what to use as the scale. 
         // Use smallest scale possible.
         float newMapScale = 0;
         if (newMapWScale >= newMapHScale)
             newMapScale = newMapHScale;
         else
             newMapScale = newMapWScale;
 
         return newMapScale;
     }
 
     // Make the position and scale changes
     IEnumerator TransposeMap()
     {
         doZoom = false;
         
         // Cache the initial values of the map scale and and camera position.
         Vector3 initialPos = NGUICam.transform.localPosition;
         Vector3 initialScale = Map.transform.localScale;
 
         Vector3 newMapPos = Vector3.zero;
 
         while (elapsedTime < ScaleDuration)
         {
               // POSITION - move camera
               Vector3 newCamPos = Vector3.Lerp(initialPos, pos, (elapsedTime / ScaleDuration));
               NGUICam.transform.position = new Vector3(pos.x, pos.y, origZpos);
 
             //Vector3 newMapPos = Vector3.Lerp(initialPos, pos, (elapsedTime / ScaleDuration));
             //Map.transform.localPosition = new Vector3(newMapPos.x, newMapPos.y, origZpos);
 
             // SCALE - scale map
             Map.transform.localScale = Vector3.Lerp(initialScale, new Vector3(ZoomedMapScale, ZoomedMapScale, 1), (elapsedTime / ScaleDuration)); 
 
             elapsedTime += Time.deltaTime;
 
             yield return null;
         }
     }
 
     void OnDrawGizmos()
     {
         Gizmos.color = Color.yellow;
         Gizmos.DrawWireCube(MidPoint, new Vector3((largestX - smallestX) - boundingBoxPadding, (largestY - smallestY) + boundingBoxPadding, 0));
     }
 }
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Textures in GUI being scaled slightly? 1 Answer

Scaling/Offsetting a texture based on object size to match up with other objects 2 Answers

How to get Facebook friend's name, score, and picture 1 Answer

how to make textures the same size regardless of object size unity 0 Answers

Best Practices, GUI and Browser Zoom, Scaling 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges