Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - justkevin

Pages: [1]
1
NGUI 3 Documentation / Re: UIButton
« on: July 19, 2014, 01:06:09 PM »
How do I set the default color of a button in script?

If I change defaultColor, the change doesn't show up until the next time the user interacts with the button (e.g., by hovering).

The documentation talks about UpdateColor in the the parent class, but that method doesn't seem to exist?

2
NGUI 3 Support / Re: Keeping UI widget inside parent's edges
« on: July 02, 2014, 11:01:44 AM »
Thanks, that helped me get it working!

If anyone else searches for this, here is a working version, in which scannable.ScannerInstance is a UIWidget constrained to the boundaries of whatever UIWidget this component is attached:

  1. private void PositionScannable(IScannable scannable) {
  2.                 // Find the scannable game object's screen position:
  3.                 Vector2 screenPos = Camera.main.WorldToScreenPoint(scannable.GameObject.transform.position);
  4.                 // Get the Camera rendering the overlay layer:
  5.                 Camera cam = NGUITools.FindCameraForLayer(gameObject.layer);
  6.  
  7.                 // Translate the screen pos into the coordinates for the NGUI camera:
  8.                 Vector3 adjustedPos = cam.ScreenToWorldPoint(screenPos);
  9.  
  10.                 scannable.ScannerInstance.transform.position = adjustedPos;
  11.                 // At this point the scanner widget is following the game object, now to constrain it to this widget:
  12.  
  13.                 // Figure out the bounds relative to our mutual parent:
  14.                 Bounds contentBounds = NGUIMath.CalculateRelativeWidgetBounds(transform.parent, scannable.ScannerInstance.transform);
  15.                 Vector2 scanMin = new Vector2(contentBounds.min.x, contentBounds.min.y);
  16.                 Vector2 scanMax = new Vector2(contentBounds.max.x, contentBounds.max.y);
  17.                 Bounds areaBounds = NGUIMath.CalculateRelativeWidgetBounds(transform.parent, transform);
  18.                 Vector2 areaMin = new Vector2(areaBounds.min.x, areaBounds.min.y);
  19.                 Vector2 areaMax = new Vector2(areaBounds.max.x, areaBounds.max.y);
  20.                 // Get the offset in screen space, the amount we need to add to the position to constrain it:
  21.                 Vector2 offset = NGUIMath.ConstrainRect(scanMin,scanMax,areaMin,areaMax);
  22.                 // Re-calculate the screen coordinates of the scanner widget and adjust:
  23.                 screenPos = Camera.main.WorldToScreenPoint(scannable.GameObject.transform.position);
  24.                 screenPos.x += offset.x;
  25.                 screenPos.y += offset.y;
  26.                 // Translate back to world space and we should be good. There may be a simpler way to do this that doesn't
  27.                 // involve doing the camera translations twice, but right now this works.
  28.                 scannable.ScannerInstance.transform.position = cam.ScreenToWorldPoint(screenPos);
  29.  
  30.  
  31.         }
  32.  

3
NGUI 3 Support / Re: Keeping UI widget inside parent's edges
« on: July 01, 2014, 11:49:29 AM »
Thanks for the reply, I still can't seem to get this to work. The content either isn't adjusted at all, or adjusting itself to be half way between the center of the screen and whatever the target its tracking is (so eventually going off screen), depending on what I use as the "relative to" in the CalculateRelativeWidgetBounds.

  1.         private void PositionScannable(IScannable scannable) {
  2.                 // Find the game object's screen position:
  3.                 Vector2 screenPos = Camera.main.WorldToScreenPoint(scannable.GameObject.transform.position);
  4.                 // Get the Camera rendering the overlay layer:
  5.                 Camera cam = NGUITools.FindCameraForLayer(gameObject.layer);
  6.  
  7.                 // Translate the screen pos into the coordinates for the NGUI camera:
  8.                 Vector3 adjustedPos = cam.ScreenToWorldPoint(screenPos);
  9.  
  10.                 scannable.ScannerInstance.transform.position = adjustedPos;
  11.                 // At this point, if nothing else is done, the ScannerInstance follows the target, but can leave the area of the
  12.                 // this widget, which I don't want.
  13.  
  14.                 // Tried a number of variations of the following:
  15.                 /*
  16.                 Bounds contentBounds = NGUIMath.CalculateRelativeWidgetBounds(transform, scannable.ScannerInstance.transform);
  17.                 Vector2 scanMin = new Vector2(contentBounds.min.x, contentBounds.min.y);
  18.                 Vector2 scanMax = new Vector2(contentBounds.max.x, contentBounds.max.y);
  19.                 Bounds areaBounds = NGUIMath.CalculateRelativeWidgetBounds(transform);
  20.                 Vector2 areaMin = new Vector2(areaBounds.min.x, areaBounds.min.y);
  21.                 Vector2 areaMax = new Vector2(areaBounds.max.x, areaBounds.max.y);
  22.  
  23.                 Vector2 offset = NGUIMath.ConstrainRect(scanMin,scanMax,areaMin,areaMax);
  24.  
  25.                 Vector3 constrained = scannable.ScannerInstance.transform.position;
  26.                 constrained.x += offset.x;
  27.                 constrained.y += offset.y;
  28.  
  29.                 scannable.ScannerInstance.transform.position = cam.ScreenToViewportPoint(constrained);
  30.                 */
  31.         }

4
NGUI 3 Support / Keeping UI widget inside parent's edges
« on: June 30, 2014, 12:38:42 PM »
I'm working on a top down game in which there are some NGUI "scanner" widgets that stay over their respective game objects, with the following code on an ngui overlay that's anchored to the edges of the screen:

  1.        
  2. private void PositionScannable(IScannable scannable) {
  3.                 // Find the game object's screen position:
  4.                 Vector2 screenPos = Camera.main.WorldToScreenPoint(scannable.GameObject.transform.position);
  5.                 // Get the Camera rendering the overlay layer:
  6.                 Camera cam = NGUITools.FindCameraForLayer(gameObject.layer);
  7.  
  8.                 // Translate the screen pos into the coordinates for the NGUI camera:
  9.                 Vector3 adjustedPos = cam.ScreenToWorldPoint(screenPos);
  10.                 // ??? Somehow constrain to this widget's edges ???
  11.                 scannable.ScannerInstance.transform.position = adjustedPos;
  12.         }
  13.  

I want to keep the scanner widgets constrained to the overlay rectangle so they don't disappear off the edge of the screen when the object they're tracking does.

5
NGUI 3 Documentation / Re: UIScrollView
« on: June 13, 2014, 10:11:56 AM »
Thanks for the response.

Unfortunately, that doesn't work-- calling ResetPosition for the first Update moves the scrollview, but not to the origin. Calling it for the first 2-3 updates causes it to disappear completely for some reason. Only after calling it for 4 consecutive updates gets it to the origin:

  1.         if (_resetAttempts < 4)
  2.         {
  3.             UIScrollView scrollView = GetComponentInChildren<UIScrollView>();
  4.             scrollView.ResetPosition();
  5.             ++_resetAttempts;
  6.         }
  7.  

That works, but I'm concerned that without understanding why 4 is the magic number of updates it may break with some change to the contents of the scrollview.

Using a delayed coroutine didn't work. Changing timescale had no effect.

6
NGUI 3 Documentation / Re: UIScrollView
« on: June 12, 2014, 03:11:32 PM »
I'm trying to reset the scroll view to the upper left corner after populating it. Calling ResetPosition() before and after I add elements doesn't seem to work.

As a test, I added ResetPosition to the Update() function, and that got it to reset correctly, but obviously I don't want to call it there.

Here's the class that does the layout:

  1. using UnityEngine;
  2. using System.Collections.Generic;
  3.  
  4. public class ResearchWindow : MonoBehaviour {
  5.     // Contains all our tech tree data:
  6.     public TechTreeManager techTree;
  7.  
  8.     // Each row of this will be a tech lineage:
  9.     public GameObject techLineageTable;
  10.     // The prefab we use for each tech node displayed in the tree:
  11.     public GameObject techButtonPrefab;
  12.  
  13.     // Various UI labels:
  14.     public UILabel researchPoints;
  15.     public UILabel techLabel;
  16.     public UILabel techDescription;
  17.     public UILabel techCost;
  18.  
  19.     private TechNode _activeNode;
  20.  
  21.     /**
  22.      * Set the active node details:
  23.      **/
  24.     public TechNode ActiveNode
  25.     {
  26.         get
  27.         {
  28.             return _activeNode;
  29.         }
  30.         set
  31.         {
  32.             _activeNode = value;
  33.             if (value != null)
  34.             {
  35.                 if (techLabel != null)
  36.                 {
  37.                     techLabel.text = _activeNode.name;
  38.                     techDescription.text = _activeNode.description;
  39.                     techCost.text = "Cost: " + _activeNode.researchPoints + " RP";
  40.                 }
  41.             }
  42.            
  43.         }
  44.     }
  45.  
  46.         void Start () {
  47.         DrawTechTree();
  48.         researchPoints.text = "You have " + GameManager.Instance.player.researchPoints + " Research Points";
  49.         }
  50.        
  51.         // Update is called once per frame
  52.         void Update () {
  53.         // This actually DOES reset the position how we want, but we don't want it here:
  54.         //UIScrollView scrollView = GetComponentInChildren<UIScrollView>();
  55.         //scrollView.ResetPosition();
  56.        
  57.         }
  58.  
  59.     /**
  60.      * Adds the individual lineage tables to the overall tech tree table, and the individual
  61.      * node buttons to each of those linage tables.
  62.      **/
  63.     private void DrawTechTree()
  64.     {
  65.         // Get the scrollview:
  66.         UIScrollView scrollView = GetComponentInChildren<UIScrollView>();
  67.         scrollView.ResetPosition();
  68.         // Get a list of all lineages:
  69.         List<string> lineageIds = techTree.GetLineageIds();
  70.         foreach (string id in lineageIds)
  71.         {
  72.             TechLineage lineage = techTree.GetLineage(id);
  73.             // Create a UITable for this lineage row:
  74.             GameObject lineageRow = NGUITools.AddChild(techLineageTable);
  75.             UITable rowTable = lineageRow.AddComponent<UITable>();
  76.             // For each node in the linage, add a button for it:
  77.             foreach (TechNode node in lineage.nodes)
  78.             {
  79.                 GameObject nodeButton = NGUITools.AddChild(lineageRow, techButtonPrefab);
  80.                 TechNodeButton techNodeButton = nodeButton.GetComponent<TechNodeButton>();
  81.                 techNodeButton.Node = node;
  82.                 techNodeButton.researchWindow = this;
  83.             }
  84.             rowTable.Reposition();
  85.         }
  86.         // This does nothing:
  87.         scrollView.ResetPosition();
  88.  
  89.     }
  90. }
  91.  
  92.  

Any suggestions what I might be doing wrong?


7
After further investigation, it appears that NGUI doesn't like it if you modify the transform hierarchy manually, instead the preferred method is to use AddChild().

So my new plan is to change IScannable's signature to have an AttachToNGUI(GameObject parent) method.

I'm still interested in how others have handled this functionality.

8
This is a common feature in games: the UI shows details on the current selected object, with the behavior varying on the object type. I've come up with a way of doing this, and I'm interested in hearing suggestions on easier or more flexible solutions:

  • The player controller caches a reference to the Scanner panel (a script attached to an NGUI panel)
  • Any time a player selects a game object (e.g., clicks on it), the controller checks if the object has a component implementing IScannable
  • IScannable has a GetScanObejct() method which instantiates a Game Object (e.g., from a prefab reference), which contains one or more UIWidgets. The instance is given a reference to the instantiating game object so it can reflect changes, like damage.
  • The scan instance is passed to Scanner panel's SetScanTarget() method, which clears itself by destroying its children and adds the new instance (by setting its parent and local transforms).

Does this seem like a reasonable approach?


Pages: [1]