Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

ScrollableContainer now handles child objects and text clipping.

  • Loading branch information...
commit 81398d392bd0640c5c46b89d68a0a1c7b809cf2d 1 parent 3f7ff9b
@nsxdavid nsxdavid authored
View
BIN  Assets/DemoAssets/UIToolkitMaterial (for multiple scene).mat
Binary file not shown
View
23 Assets/DemoSceneScripts/ScrollableContainerManager.cs
@@ -6,7 +6,7 @@
public class ScrollableContainerManager : MonoBehaviour
{
private bool _movedContainer;
-
+ public UIToolkit TextManager;
void Start()
{
@@ -30,6 +30,27 @@ void Start()
{
touchable = UIButton.create( "optionsUp.png", "optionsDown.png", 0, 0 );
}
+ if (i == 1) {
+ var ch = UIToggleButton.create("cbUnchecked.png", "cbChecked.png", "cbDown.png", 0, 0);
+ ch.parentUIObject = touchable;
+ ch.pixelsFromRight(0);
+ ch.client.name = "TEST THINGY";
+ ch.scale = new Vector3(0.5f, 0.5f, 1);
+ }
+ if (i == 4) {
+ var text = new UIText(TextManager, "prototype", "prototype.png");
+
+ var helloText = text.addTextInstance("Child Text", 0, 0,0.5f,-1,Color.cyan,UITextAlignMode.Center,UITextVerticalAlignMode.Middle);
+ helloText.parentUIObject = touchable;
+ helloText.positionCenter();
+
+ var ch = UIToggleButton.create("cbUnchecked.png", "cbChecked.png", "cbDown.png", 0, 0);
+ ch.parentUIObject = helloText;
+ ch.pixelsFromRight(-16);
+ ch.client.name = "subsub";
+ ch.scale = new Vector3(0.25f, 0.25f, -2);
+ }
+
// only add a touchUpInside handler for buttons
if( touchable is UIButton )
View
BIN  Assets/DemoScenes/ScrollableContainerTest.unity
Binary file not shown
View
2  Assets/Plugins/UIToolkit/BaseElements/UIAbstractContainer.cs
@@ -256,9 +256,7 @@ protected virtual void layoutChildren()
// Refresh child position to proper positions
foreach (var item in _children) {
- // if (!item.hidden) {
item.refreshPosition();
- // }
}
}
View
35 Assets/Plugins/UIToolkit/BaseElements/UIAbstractTouchableContainer.cs
@@ -55,7 +55,33 @@ private void calculateMinMaxInsets()
// now that we have new insets clip
clipToBounds();
}
-
+
+ ITouchable TestTouchable(UIObject touchableObj, Vector2 touchPosition)
+ {
+
+
+ foreach (Transform t in touchableObj.client.transform) {
+ UIElement uie = t.GetComponent<UIElement>();
+ if (uie != null) {
+ UIObject o = t.GetComponent<UIElement>().UIObject;
+ if (o != null) {
+ var touched = TestTouchable(o, touchPosition);
+ if (touched != null)
+ return touched;
+ }
+ }
+ }
+
+ ITouchable touchable = touchableObj as ITouchable;
+ if (touchable != null) {
+ if (touchable.hitTest(touchPosition))
+ return touchable as ITouchable;
+ }
+
+
+
+ return null;
+ }
protected ITouchable getButtonForScreenPosition( Vector2 touchPosition )
{
@@ -63,11 +89,12 @@ protected ITouchable getButtonForScreenPosition( Vector2 touchPosition )
// due to their frame overlapping the touchable below
for( int i = _children.Count - 1; i >= 0; i-- )
{
- var touchable = _children[i] as ITouchable;
+ var touchable = _children[i];
if( touchable != null )
{
- if( touchable.hitTest( touchPosition ) )
- return touchable;
+ ITouchable touched = TestTouchable(touchable, touchPosition); // Recursive
+ if (touched != null)
+ return touched;
}
}
View
7 Assets/Plugins/UIToolkit/BaseElements/UIElement.cs
@@ -0,0 +1,7 @@
+using UnityEngine;
+using System.Collections;
+
+public class UIElement : MonoBehaviour {
+
+ public UIObject UIObject;
+}
View
7 Assets/Plugins/UIToolkit/BaseElements/UIElement.cs.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: d7e266a817e80424d9a87493150aa929
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
View
4 Assets/Plugins/UIToolkit/BaseElements/UIObject.cs
@@ -29,6 +29,10 @@ public UIObject()
_client.transform.parent = UI.instance.transform; // Just for orginization in the hierarchy
_client.layer = UI.instance.layer; // Set the proper layer so we only render on the UI camera
+ UIElement uie = _client.AddComponent<UIElement>();
+ uie.UIObject = this;
+
+
// Cache the clientTransform
clientTransform = _client.transform;
// Create a default anchor info object
View
27 Assets/Plugins/UIToolkit/BaseElements/UISprite.cs
@@ -135,8 +135,7 @@ public bool clipped
return;
_clipped = value;
- if( _clipped )
- _clippedTopYOffset = 0;
+ _clippedTopYOffset = 0;
updateVertPositions();
manager.updateUV( this );
@@ -263,18 +262,18 @@ public void updateVertPositions()
if( gameObjectOriginInCenter )
{
// Some objects need to rotate so we set the origin at the center of the GO
- v1 = new Vector3( -width / 2, height / 2, 0 ); // Upper-left
- v2 = new Vector3( -width / 2, -height / 2, 0 ); // Lower-left
- v3 = new Vector3( width / 2, -height / 2, 0 ); // Lower-right
- v4 = new Vector3( width / 2, height / 2, 0 ); // Upper-right
+ v1 = new Vector3( -width / 2, height / 2 - _clippedTopYOffset, 0 ); // Upper-left
+ v2 = new Vector3(-width / 2, -height / 2 - _clippedTopYOffset, 0); // Lower-left
+ v3 = new Vector3(width / 2, -height / 2 - _clippedTopYOffset, 0); // Lower-right
+ v4 = new Vector3(width / 2, height / 2 - _clippedTopYOffset, 0); // Upper-right
}
else
{
// Make the origin the top-left corner of the GO
- v1 = new Vector3( 0, 0, 0 ); // Upper-left
- v2 = new Vector3( 0, -height, 0 ); // Lower-left
- v3 = new Vector3( width, -height, 0 ); // Lower-right
- v4 = new Vector3( width, 0, 0 ); // Upper-right
+ v1 = new Vector3(0, 0 - _clippedTopYOffset, 0); // Upper-left
+ v2 = new Vector3(0, -height - _clippedTopYOffset, 0); // Lower-left
+ v3 = new Vector3(width, -height - _clippedTopYOffset, 0); // Lower-right
+ v4 = new Vector3(width, 0 - _clippedTopYOffset, 0); // Upper-right
}
}
@@ -286,18 +285,16 @@ public void updateVertPositions()
/// </summary>
public void setClippedSize( float width, float height, bool clippingTop )
{
- _clippedWidth = width;
- _clippedHeight = height;
+ _clippedWidth = width;
+ _clippedHeight = height;
if( clippingTop )
_clippedTopYOffset = _height - _clippedHeight;
else
_clippedTopYOffset = 0;
- position = new Vector3( position.x, position.y - _clippedTopYOffset, position.z );
-
updateVertPositions();
- updateTransform();
+ updateTransform();
}
View
272 Assets/Plugins/UIToolkit/Containers/UIScrollableVerticalLayout.cs
@@ -10,7 +10,7 @@ public class UIScrollableVerticalLayout : UIAbstractTouchableContainer
private const float SCROLL_DECELERATION_MODIFIER = 0.93f; // how fast should we slow down
private float TOUCH_MAX_DELTA_FOR_ACTIVATION = UI.instance.isHD ? 10 : 5;
private const float CONTENT_TOUCH_DELAY = 0.15f;
-
+
private float _deltaTouch;
#if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN || UNITY_WEBPLAYER
private UIFakeTouch _lastTouch;
@@ -20,167 +20,192 @@ public class UIScrollableVerticalLayout : UIAbstractTouchableContainer
private Vector2 _lastTouchPosition;
private ITouchable _activeTouchable;
private bool _isDragging;
- private Stack<float> _velocities = new Stack<float>( TOTAL_VELOCITY_SAMPLE_COUNT );
-
-
- public UIScrollableVerticalLayout( int spacing ) : base( UILayoutType.Vertical, spacing )
+ private Stack<float> _velocities = new Stack<float>(TOTAL_VELOCITY_SAMPLE_COUNT);
+
+
+ public UIScrollableVerticalLayout(int spacing)
+ : base(UILayoutType.Vertical, spacing)
{
-
+
}
-
-
+
+
private IEnumerator decelerate()
{
// get the average velocity by summing all the velocities and dividing by count
float total = 0;
- foreach( var v in _velocities )
+ foreach (var v in _velocities)
total += v;
-
+
var avgVelocity = total / _velocities.Count;
-
- while( !_isDragging )
- {
+
+ while (!_isDragging) {
var deltaMovement = avgVelocity * Time.deltaTime;
var newTop = _scrollPosition - deltaMovement;
-
+
// make sure we have some velocity and we are within our bounds
- if( Mathf.Abs( avgVelocity ) > 25 && newTop < _maxEdgeInset.y && newTop > _minEdgeInset.y )
- {
+ if (Mathf.Abs(avgVelocity) > 25 && newTop < _maxEdgeInset.y && newTop > _minEdgeInset.y) {
_scrollPosition = newTop;
layoutChildren();
avgVelocity *= SCROLL_DECELERATION_MODIFIER;
-
+
yield return null;
}
- else
- {
+ else {
break;
}
}
}
-
-
- private IEnumerator scrollToInset( int target )
+
+
+ private IEnumerator scrollToInset(int target)
{
var start = _scrollPosition;
var startTime = Time.time;
var duration = 0.4f;
var running = true;
-
- while( !_isDragging && running )
- {
+
+ while (!_isDragging && running) {
// Get our easing position
- var easPos = Mathf.Clamp01( ( Time.time - startTime ) / duration );
- easPos = Easing.Quartic.easeOut( easPos );
-
- _scrollPosition = (int)Mathf.Lerp( start, target, easPos );
+ var easPos = Mathf.Clamp01((Time.time - startTime) / duration);
+ easPos = Easing.Quartic.easeOut(easPos);
+
+ _scrollPosition = (int)Mathf.Lerp(start, target, easPos);
layoutChildren();
-
- if( ( startTime + duration ) <= Time.time )
+
+ if ((startTime + duration) <= Time.time)
running = false;
-
+
yield return null;
}
layoutChildren();
}
-
-
+
+
public IEnumerator checkDelayedContentTouch()
{
- yield return new WaitForSeconds( CONTENT_TOUCH_DELAY );
-
- if( _isDragging && Mathf.Abs( _deltaTouch ) < TOUCH_MAX_DELTA_FOR_ACTIVATION )
- {
- var fixedTouchPosition = new Vector2( _lastTouch.position.x, Screen.height - _lastTouch.position.y );
- _activeTouchable = getButtonForScreenPosition( fixedTouchPosition );
- if( _activeTouchable != null )
- _activeTouchable.onTouchBegan( _lastTouch, fixedTouchPosition );
+ yield return new WaitForSeconds(CONTENT_TOUCH_DELAY);
+
+ if (_isDragging && Mathf.Abs(_deltaTouch) < TOUCH_MAX_DELTA_FOR_ACTIVATION) {
+ var fixedTouchPosition = new Vector2(_lastTouch.position.x, Screen.height - _lastTouch.position.y);
+ _activeTouchable = getButtonForScreenPosition(fixedTouchPosition);
+ if (_activeTouchable != null)
+ _activeTouchable.onTouchBegan(_lastTouch, fixedTouchPosition);
}
}
-
-
- protected override void clipToBounds()
+
+
+ private void ClipChild(UISprite child)
{
- // clip hidden children
- foreach( var child in _children )
- {
- var topContained = child.position.y < -touchFrame.yMin && child.position.y > -touchFrame.yMax;
- var bottomContained = child.position.y - child.height < -touchFrame.yMin && child.position.y - child.height > -touchFrame.yMax;
-
- // first, handle if we are fully visible
- if( topContained && bottomContained )
- {
- // unclip if we are clipped
- if( child.clipped )
- child.clipped = false;
- child.hidden = false;
+ var topContained = child.position.y < -touchFrame.yMin && child.position.y > -touchFrame.yMax;
+ var bottomContained = child.position.y - child.height < -touchFrame.yMin && child.position.y - child.height > -touchFrame.yMax;
+
+ // first, handle if we are fully visible
+ if (topContained && bottomContained) {
+ // unclip if we are clipped
+ if (child.clipped)
+ child.clipped = false;
+ child.hidden = false;
+ }
+ else if (topContained || bottomContained) {
+ // wrap the changes in a call to beginUpdates to avoid changing verts more than once
+ child.beginUpdates();
+
+ child.hidden = false;
+
+ // are we clipping the top or bottom?
+ if (topContained) // clipping the bottom
+ {
+ var clippedHeight = child.position.y + touchFrame.yMax;
+
+ child.uvFrameClipped = child.uvFrame.rectClippedToBounds(child.width / child.scale.x, clippedHeight / child.scale.y, false, child.manager.textureSize);
+ child.setClippedSize(child.width / child.scale.x, clippedHeight / child.scale.y, false);
}
- else if( topContained || bottomContained )
- {
- // wrap the changes in a call to beginUpdates to avoid changing verts more than once
- child.beginUpdates();
-
- child.hidden = false;
-
- // are we clipping the top or bottom?
- if( topContained ) // clipping the bottom
- {
- var clippedHeight = child.position.y + touchFrame.yMax;
-
- child.uvFrameClipped = child.uvFrame.rectClippedToBounds( child.width, clippedHeight, false, child.manager.textureSize );
- child.setClippedSize( child.width, clippedHeight, false );
- }
- else // clipping the top, so we need to adjust the position.y as well
- {
- var clippedHeight = child.height - child.position.y - touchFrame.yMin;
-
- child.uvFrameClipped = child.uvFrame.rectClippedToBounds( child.width, clippedHeight, true, child.manager.textureSize );
- child.setClippedSize( child.width, clippedHeight, true );
- }
-
- // commit the changes
- child.endUpdates();
+ else // clipping the top, so we need to adjust the position.y as well
+ {
+ var clippedHeight = child.height - child.position.y - touchFrame.yMin;
+
+ child.uvFrameClipped = child.uvFrame.rectClippedToBounds(child.width / child.scale.x, clippedHeight / child.scale.y, true, child.manager.textureSize);
+ child.setClippedSize(child.width / child.scale.x, clippedHeight / child.scale.y, true);
}
- else
- {
- // fully outside our bounds
- child.hidden = true;
+
+ // commit the changes
+ child.endUpdates();
+ }
+ else {
+ // fully outside our bounds
+ child.hidden = true;
+ }
+
+ // Recurse
+
+ RecurseChildren(child);
+
+ }
+ private void RecurseChildren(UIObject child)
+ {
+ foreach (Transform t in child.client.transform) {
+ UIElement uie = t.GetComponent<UIElement>();
+ if (uie != null) {
+ UIObject o = t.GetComponent<UIElement>().UIObject;
+ if (o != null) {
+ UISprite s = o as UISprite;
+ if (s != null) {
+ ClipChild(s);
+ }
+ else {
+ UITextInstance ti = o as UITextInstance;
+ if (ti != null) {
+ // Special handeling for text
+ foreach (UISprite glyph in ti.textSprites) {
+ ClipChild(glyph);
+ }
+ }
+ RecurseChildren(ti);
+ }
+ }
}
}
}
-
-
+ protected override void clipToBounds()
+ {
+ // clip hidden children
+ foreach (var child in _children) {
+ ClipChild(child);
+ }
+ }
+
+
#region ITouchable
// Touch handlers. Subclasses should override these to get their specific behaviour
#if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN || UNITY_WEBPLAYER
- public override void onTouchBegan( UIFakeTouch touch, Vector2 touchPos )
+ public override void onTouchBegan(UIFakeTouch touch, Vector2 touchPos)
#else
public override void onTouchBegan( Touch touch, Vector2 touchPos )
#endif
{
// sanity check in case we lost a touch (happens with Unity on occassion)
- if( _activeTouchable != null )
- {
+ if (_activeTouchable != null) {
// we dont pass onTouchEnded here because technically we are still over the ITouchable
_activeTouchable.highlighted = false;
_activeTouchable = null;
}
-
+
// if we have a couroutine running stop it
//_manager.StopCoroutine( "checkDelayedContentTouch" );
-
+
_deltaTouch = 0;
_isDragging = true;
_velocities.Clear();
-
+
// kick off a new check
- _manager.StartCoroutine( checkDelayedContentTouch() );
+ _manager.StartCoroutine(checkDelayedContentTouch());
}
#if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN || UNITY_WEBPLAYER
- public override void onTouchMoved( UIFakeTouch touch, Vector2 touchPos )
+ public override void onTouchMoved(UIFakeTouch touch, Vector2 touchPos)
#else
public override void onTouchMoved( Touch touch, Vector2 touchPos )
#endif
@@ -188,74 +213,69 @@ public override void onTouchMoved( Touch touch, Vector2 touchPos )
// increment deltaTouch so we can pass on the touch if necessary
_deltaTouch += touch.deltaPosition.y;
_lastTouch = touch;
-
+
// once we move too far unhighlight and stop tracking the touchable
- if( Mathf.Abs( _deltaTouch ) > TOUCH_MAX_DELTA_FOR_ACTIVATION && _activeTouchable != null )
- {
- _activeTouchable.onTouchEnded( touch, touchPos, true );
+ if (Mathf.Abs(_deltaTouch) > TOUCH_MAX_DELTA_FOR_ACTIVATION && _activeTouchable != null) {
+ _activeTouchable.onTouchEnded(touch, touchPos, true);
_activeTouchable = null;
}
-
-
+
+
var newTop = _scrollPosition - touch.deltaPosition.y;
- if( newTop < _maxEdgeInset.y && newTop > _minEdgeInset.y ) // movement within the bounds (ie no bounce yet)
+ if (newTop < _maxEdgeInset.y && newTop > _minEdgeInset.y) // movement within the bounds (ie no bounce yet)
{
_scrollPosition = newTop;
layoutChildren();
}
// pop any extra velocities and push the current velocity onto the stack
- if( _velocities.Count == TOTAL_VELOCITY_SAMPLE_COUNT )
+ if (_velocities.Count == TOTAL_VELOCITY_SAMPLE_COUNT)
_velocities.Pop();
- _velocities.Push( touch.deltaPosition.y / Time.deltaTime );
+ _velocities.Push(touch.deltaPosition.y / Time.deltaTime);
}
#if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN || UNITY_WEBPLAYER
- public override void onTouchEnded( UIFakeTouch touch, Vector2 touchPos, bool touchWasInsideTouchFrame )
+ public override void onTouchEnded(UIFakeTouch touch, Vector2 touchPos, bool touchWasInsideTouchFrame)
#else
public override void onTouchEnded( Touch touch, Vector2 touchPos, bool touchWasInsideTouchFrame )
#endif
{
_isDragging = false;
-
+
// pass on the touch if we still have an active touchable
- if( _activeTouchable != null )
- {
- _activeTouchable.onTouchEnded( touch, touchPos, true );
+ if (_activeTouchable != null) {
+ _activeTouchable.onTouchEnded(touch, touchPos, true);
_activeTouchable.highlighted = false;
_activeTouchable = null;
}
- else
- {
- _manager.StartCoroutine( decelerate() );
+ else {
+ _manager.StartCoroutine(decelerate());
}
}
-
+
#endregion
-
-
+
+
protected override void layoutChildren()
{
base.layoutChildren();
clipToBounds();
}
-
-
+
+
/// <summary>
/// Scrolls to the newTop (using the edgeInsets so 0 is the top and scrolling goes towards negatives)
/// </summary>
- public void scrollTo( int newTop, bool animated )
+ public void scrollTo(int newTop, bool animated)
{
- if( animated )
- {
- _manager.StartCoroutine( scrollToInset( newTop ) );
+ if (animated) {
+ _manager.StartCoroutine(scrollToInset(newTop));
}
- else
- {
+ else {
_scrollPosition = newTop;
layoutChildren();
}
}
-
+
}
View
BIN  Assets/Plugins/UIToolkit/Materials/UIToolkitMaterial.mat
Binary file not shown
View
11 Assets/Plugins/UIToolkit/UIElements/UIText.cs
@@ -459,10 +459,10 @@ private UISprite configureSpriteForCharId( UISprite sprite, int charId, float xP
// in the wrong spot according to the angelcode spec. xadvance is the complete character width
// and offsetx is supposed to be used only during character rendering, not during cursor advance.
// Please note that yPos already has offsety built in.
- var rect = new Rect( xPos + _fontDetails[charId].offsetx * scale,
+ var rect = new Rect( xPos + _fontDetails[charId].offsetx* scale,
yPos,
- _fontDetails[charId].w * scale,
- _fontDetails[charId].h * scale );
+ _fontDetails[charId].w,
+ _fontDetails[charId].h);
if( sprite == null )
{
@@ -475,7 +475,10 @@ private UISprite configureSpriteForCharId( UISprite sprite, int charId, float xP
sprite.position = new Vector3( rect.x, -rect.y, depth );
sprite.setSize( rect.width, rect.height );
}
-
+
+ // We scale the sprite this way so it will work with the container clipping
+ sprite.autoRefreshPositionOnScaling = false;
+ sprite.scale = new Vector3(scale, scale, 1);
return sprite;
}
Please sign in to comment.
Something went wrong with that request. Please try again.