mirror of
https://github.com/RHeavenStudio/HeavenStudio.git
synced 2025-06-12 12:07:41 +02:00
Editor stuff
This commit is contained in:
@ -0,0 +1,350 @@
|
||||
/**
|
||||
|
||||
This class demonstrates the code discussed in these two articles:
|
||||
|
||||
http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/
|
||||
http://devmag.org.za/2011/06/23/bzier-path-algorithms/
|
||||
|
||||
Use this code as you wish, at your own risk. If it blows up
|
||||
your computer, makes a plane crash, or otherwise cause damage,
|
||||
injury, or death, it is not my fault.
|
||||
|
||||
@author Herman Tulleken, dev.mag.org.za
|
||||
|
||||
*/
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/**
|
||||
Class for representing a Bezier path, and methods for getting suitable points to
|
||||
draw the curve with line segments.
|
||||
*/
|
||||
public class BezierPath
|
||||
{
|
||||
public int SegmentsPerCurve = 10;
|
||||
public float MINIMUM_SQR_DISTANCE = 0.01f;
|
||||
|
||||
// This corresponds to about 172 degrees, 8 degrees from a straight line
|
||||
public float DIVISION_THRESHOLD = -0.99f;
|
||||
|
||||
private List<Vector2> controlPoints;
|
||||
|
||||
private int curveCount; //how many bezier curves in this path?
|
||||
|
||||
/**
|
||||
Constructs a new empty Bezier curve. Use one of these methods
|
||||
to add points: SetControlPoints, Interpolate, SamplePoints.
|
||||
*/
|
||||
public BezierPath()
|
||||
{
|
||||
controlPoints = new List<Vector2>();
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the control points of this Bezier path.
|
||||
Points 0-3 forms the first Bezier curve, points
|
||||
3-6 forms the second curve, etc.
|
||||
*/
|
||||
public void SetControlPoints(List<Vector2> newControlPoints)
|
||||
{
|
||||
controlPoints.Clear();
|
||||
controlPoints.AddRange(newControlPoints);
|
||||
curveCount = (controlPoints.Count - 1) / 3;
|
||||
}
|
||||
|
||||
public void SetControlPoints(Vector2[] newControlPoints)
|
||||
{
|
||||
controlPoints.Clear();
|
||||
controlPoints.AddRange(newControlPoints);
|
||||
curveCount = (controlPoints.Count - 1) / 3;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the control points for this Bezier curve.
|
||||
*/
|
||||
public List<Vector2> GetControlPoints()
|
||||
{
|
||||
return controlPoints;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Calculates a Bezier interpolated path for the given points.
|
||||
*/
|
||||
public void Interpolate(List<Vector2> segmentPoints, float scale)
|
||||
{
|
||||
controlPoints.Clear();
|
||||
|
||||
if (segmentPoints.Count < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < segmentPoints.Count; i++)
|
||||
{
|
||||
if (i == 0) // is first
|
||||
{
|
||||
Vector2 p1 = segmentPoints[i];
|
||||
Vector2 p2 = segmentPoints[i + 1];
|
||||
|
||||
Vector2 tangent = (p2 - p1);
|
||||
Vector2 q1 = p1 + scale * tangent;
|
||||
|
||||
controlPoints.Add(p1);
|
||||
controlPoints.Add(q1);
|
||||
}
|
||||
else if (i == segmentPoints.Count - 1) //last
|
||||
{
|
||||
Vector2 p0 = segmentPoints[i - 1];
|
||||
Vector2 p1 = segmentPoints[i];
|
||||
Vector2 tangent = (p1 - p0);
|
||||
Vector2 q0 = p1 - scale * tangent;
|
||||
|
||||
controlPoints.Add(q0);
|
||||
controlPoints.Add(p1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 p0 = segmentPoints[i - 1];
|
||||
Vector2 p1 = segmentPoints[i];
|
||||
Vector2 p2 = segmentPoints[i + 1];
|
||||
Vector2 tangent = (p2 - p0).normalized;
|
||||
Vector2 q0 = p1 - scale * tangent * (p1 - p0).magnitude;
|
||||
Vector2 q1 = p1 + scale * tangent * (p2 - p1).magnitude;
|
||||
|
||||
controlPoints.Add(q0);
|
||||
controlPoints.Add(p1);
|
||||
controlPoints.Add(q1);
|
||||
}
|
||||
}
|
||||
|
||||
curveCount = (controlPoints.Count - 1) / 3;
|
||||
}
|
||||
|
||||
/**
|
||||
Sample the given points as a Bezier path.
|
||||
*/
|
||||
public void SamplePoints(List<Vector2> sourcePoints, float minSqrDistance, float maxSqrDistance, float scale)
|
||||
{
|
||||
if (sourcePoints.Count < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Stack<Vector2> samplePoints = new Stack<Vector2>();
|
||||
|
||||
samplePoints.Push(sourcePoints[0]);
|
||||
|
||||
Vector2 potentialSamplePoint = sourcePoints[1];
|
||||
|
||||
int i = 2;
|
||||
|
||||
for (i = 2; i < sourcePoints.Count; i++)
|
||||
{
|
||||
if (
|
||||
((potentialSamplePoint - sourcePoints[i]).sqrMagnitude > minSqrDistance) &&
|
||||
((samplePoints.Peek() - sourcePoints[i]).sqrMagnitude > maxSqrDistance))
|
||||
{
|
||||
samplePoints.Push(potentialSamplePoint);
|
||||
}
|
||||
|
||||
potentialSamplePoint = sourcePoints[i];
|
||||
}
|
||||
|
||||
//now handle last bit of curve
|
||||
Vector2 p1 = samplePoints.Pop(); //last sample point
|
||||
Vector2 p0 = samplePoints.Peek(); //second last sample point
|
||||
Vector2 tangent = (p0 - potentialSamplePoint).normalized;
|
||||
float d2 = (potentialSamplePoint - p1).magnitude;
|
||||
float d1 = (p1 - p0).magnitude;
|
||||
p1 = p1 + tangent * ((d1 - d2) / 2);
|
||||
|
||||
samplePoints.Push(p1);
|
||||
samplePoints.Push(potentialSamplePoint);
|
||||
|
||||
|
||||
Interpolate(new List<Vector2>(samplePoints), scale);
|
||||
}
|
||||
|
||||
/**
|
||||
Calculates a point on the path.
|
||||
|
||||
@param curveIndex The index of the curve that the point is on. For example,
|
||||
the second curve (index 1) is the curve with control points 3, 4, 5, and 6.
|
||||
|
||||
@param t The parameter indicating where on the curve the point is. 0 corresponds
|
||||
to the "left" point, 1 corresponds to the "right" end point.
|
||||
*/
|
||||
public Vector2 CalculateBezierPoint(int curveIndex, float t)
|
||||
{
|
||||
int nodeIndex = curveIndex * 3;
|
||||
|
||||
Vector2 p0 = controlPoints[nodeIndex];
|
||||
Vector2 p1 = controlPoints[nodeIndex + 1];
|
||||
Vector2 p2 = controlPoints[nodeIndex + 2];
|
||||
Vector2 p3 = controlPoints[nodeIndex + 3];
|
||||
|
||||
return CalculateBezierPoint(t, p0, p1, p2, p3);
|
||||
}
|
||||
|
||||
/**
|
||||
Gets the drawing points. This implementation simply calculates a certain number
|
||||
of points per curve.
|
||||
*/
|
||||
public List<Vector2> GetDrawingPoints0()
|
||||
{
|
||||
List<Vector2> drawingPoints = new List<Vector2>();
|
||||
|
||||
for (int curveIndex = 0; curveIndex < curveCount; curveIndex++)
|
||||
{
|
||||
if (curveIndex == 0) //Only do this for the first end point.
|
||||
//When i != 0, this coincides with the
|
||||
//end point of the previous segment,
|
||||
{
|
||||
drawingPoints.Add(CalculateBezierPoint(curveIndex, 0));
|
||||
}
|
||||
|
||||
for (int j = 1; j <= SegmentsPerCurve; j++)
|
||||
{
|
||||
float t = j / (float)SegmentsPerCurve;
|
||||
drawingPoints.Add(CalculateBezierPoint(curveIndex, t));
|
||||
}
|
||||
}
|
||||
|
||||
return drawingPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
Gets the drawing points. This implementation simply calculates a certain number
|
||||
of points per curve.
|
||||
|
||||
This is a slightly different implementation from the one above.
|
||||
*/
|
||||
public List<Vector2> GetDrawingPoints1()
|
||||
{
|
||||
List<Vector2> drawingPoints = new List<Vector2>();
|
||||
|
||||
for (int i = 0; i < controlPoints.Count - 3; i += 3)
|
||||
{
|
||||
Vector2 p0 = controlPoints[i];
|
||||
Vector2 p1 = controlPoints[i + 1];
|
||||
Vector2 p2 = controlPoints[i + 2];
|
||||
Vector2 p3 = controlPoints[i + 3];
|
||||
|
||||
if (i == 0) //only do this for the first end point. When i != 0, this coincides with the end point of the previous segment,
|
||||
{
|
||||
drawingPoints.Add(CalculateBezierPoint(0, p0, p1, p2, p3));
|
||||
}
|
||||
|
||||
for (int j = 1; j <= SegmentsPerCurve; j++)
|
||||
{
|
||||
float t = j / (float)SegmentsPerCurve;
|
||||
drawingPoints.Add(CalculateBezierPoint(t, p0, p1, p2, p3));
|
||||
}
|
||||
}
|
||||
|
||||
return drawingPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
This gets the drawing points of a bezier curve, using recursive division,
|
||||
which results in less points for the same accuracy as the above implementation.
|
||||
*/
|
||||
public List<Vector2> GetDrawingPoints2()
|
||||
{
|
||||
List<Vector2> drawingPoints = new List<Vector2>();
|
||||
|
||||
for (int curveIndex = 0; curveIndex < curveCount; curveIndex++)
|
||||
{
|
||||
List<Vector2> bezierCurveDrawingPoints = FindDrawingPoints(curveIndex);
|
||||
|
||||
if (curveIndex != 0)
|
||||
{
|
||||
//remove the fist point, as it coincides with the last point of the previous Bezier curve.
|
||||
bezierCurveDrawingPoints.RemoveAt(0);
|
||||
}
|
||||
|
||||
drawingPoints.AddRange(bezierCurveDrawingPoints);
|
||||
}
|
||||
|
||||
return drawingPoints;
|
||||
}
|
||||
|
||||
List<Vector2> FindDrawingPoints(int curveIndex)
|
||||
{
|
||||
List<Vector2> pointList = new List<Vector2>();
|
||||
|
||||
Vector2 left = CalculateBezierPoint(curveIndex, 0);
|
||||
Vector2 right = CalculateBezierPoint(curveIndex, 1);
|
||||
|
||||
pointList.Add(left);
|
||||
pointList.Add(right);
|
||||
|
||||
FindDrawingPoints(curveIndex, 0, 1, pointList, 1);
|
||||
|
||||
return pointList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@returns the number of points added.
|
||||
*/
|
||||
int FindDrawingPoints(int curveIndex, float t0, float t1,
|
||||
List<Vector2> pointList, int insertionIndex)
|
||||
{
|
||||
Vector2 left = CalculateBezierPoint(curveIndex, t0);
|
||||
Vector2 right = CalculateBezierPoint(curveIndex, t1);
|
||||
|
||||
if ((left - right).sqrMagnitude < MINIMUM_SQR_DISTANCE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float tMid = (t0 + t1) / 2;
|
||||
Vector2 mid = CalculateBezierPoint(curveIndex, tMid);
|
||||
|
||||
Vector2 leftDirection = (left - mid).normalized;
|
||||
Vector2 rightDirection = (right - mid).normalized;
|
||||
|
||||
if (Vector2.Dot(leftDirection, rightDirection) > DIVISION_THRESHOLD || Mathf.Abs(tMid - 0.5f) < 0.0001f)
|
||||
{
|
||||
int pointsAddedCount = 0;
|
||||
|
||||
pointsAddedCount += FindDrawingPoints(curveIndex, t0, tMid, pointList, insertionIndex);
|
||||
pointList.Insert(insertionIndex + pointsAddedCount, mid);
|
||||
pointsAddedCount++;
|
||||
pointsAddedCount += FindDrawingPoints(curveIndex, tMid, t1, pointList, insertionIndex + pointsAddedCount);
|
||||
|
||||
return pointsAddedCount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Calculates a point on the Bezier curve represented with the four control points given.
|
||||
*/
|
||||
private Vector2 CalculateBezierPoint(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
|
||||
{
|
||||
float u = 1 - t;
|
||||
float tt = t * t;
|
||||
float uu = u * u;
|
||||
float uuu = uu * u;
|
||||
float ttt = tt * t;
|
||||
|
||||
Vector2 p = uuu * p0; //first term
|
||||
|
||||
p += 3 * uu * t * p1; //second term
|
||||
p += 3 * u * tt * p2; //third term
|
||||
p += ttt * p3; //fourth term
|
||||
|
||||
return p;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89b61e0416e1256469165fca78d5ed21
|
||||
timeCreated: 1463598733
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,25 @@
|
||||
Sourced from Unity forums - [LZF compression and decompression for Unity](http://forum.unity3d.com/threads/lzf-compression-and-decompression-for-unity.152579/)
|
||||
|
||||
#Description#
|
||||
The LZF Compression component is a useful extension to Unity to be able to compress data for sending over a network or for more efficient saving.
|
||||
|
||||
This was provided via Unity forum guru [mrbroshkin](http://forum.unity3d.com/members/mrbroshkin.124231/) based of [Agent_007](http://forum.unity3d.com/members/agent_007.78088/) initial conversion work.
|
||||
|
||||
#What's included#
|
||||
The library is complete and has even been patched a few times already through the forum thread, so I took the most stable version without issues. (issus were reported on other versions, so I didn't take them)
|
||||
|
||||
There are some Unit Tests included in the following file:
|
||||
>Assets\unity-ui-extensions\Scripts\Editor\CompressionTests.cs
|
||||
|
||||
These details some sample use cases and also provide a good way to test that the compression/decompression works as expected.
|
||||
To run these Unit Tests In Unity 5.3, open the following editor window from the menu to see the tests and run them.
|
||||
>Window\Editor Tests Runner
|
||||
|
||||
(For earlier versions of Unity, you will need to install the "Unity Test Tools" asset from the store and follow the instructions from there.)
|
||||
|
||||
#Contribute#
|
||||
Feel free to submit patches (if required) back to the project to increase the scope and enjoy
|
||||
|
||||
#Notes#
|
||||
When encoding data to byte array's for compression, it's best to use the Unicode character set to avoid issue. Some other encodings don't work as well with this lib. Example details found in the UnitTests.
|
||||
Part of the reason I added this library, since it's not really UI, is to support the Serialisation component. Both together provide a useful solution for packing data to save or send over a network.
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 125e21ede8cf31746b15797b86e6a479
|
||||
timeCreated: 1464945707
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,340 @@
|
||||
//
|
||||
// http://forum.unity3d.com/threads/lzf-compression-and-decompression-for-unity.152579/
|
||||
//
|
||||
|
||||
/*
|
||||
* Improved version to C# LibLZF Port:
|
||||
* Copyright (c) 2010 Roman Atachiants <kelindar@gmail.com>
|
||||
*
|
||||
* Original CLZF Port:
|
||||
* Copyright (c) 2005 Oren J. Maurice <oymaurice@hazorea.org.il>
|
||||
*
|
||||
* Original LibLZF Library Algorithm:
|
||||
* Copyright (c) 2000-2008 Marc Alexander Lehmann <schmorp@schmorp.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
* tion, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
||||
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
||||
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
||||
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* the GNU General Public License version 2 (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of the above. If you wish to
|
||||
* allow the use of your version of this file only under the terms of the
|
||||
* GPL and not to allow others to use your version of this file under the
|
||||
* BSD license, indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by the GPL. If
|
||||
* you do not delete the provisions above, a recipient may use your version
|
||||
* of this file under either the BSD or the GPL.
|
||||
*/
|
||||
|
||||
/* Benchmark with Alice29 Canterbury Corpus
|
||||
---------------------------------------
|
||||
(Compression) Original CLZF C#
|
||||
Raw = 152089, Compressed = 101092
|
||||
8292,4743 ms.
|
||||
---------------------------------------
|
||||
(Compression) My LZF C#
|
||||
Raw = 152089, Compressed = 101092
|
||||
33,0019 ms.
|
||||
---------------------------------------
|
||||
(Compression) Zlib using SharpZipLib
|
||||
Raw = 152089, Compressed = 54388
|
||||
8389,4799 ms.
|
||||
---------------------------------------
|
||||
(Compression) QuickLZ C#
|
||||
Raw = 152089, Compressed = 83494
|
||||
80,0046 ms.
|
||||
---------------------------------------
|
||||
(Decompression) Original CLZF C#
|
||||
Decompressed = 152089
|
||||
16,0009 ms.
|
||||
---------------------------------------
|
||||
(Decompression) My LZF C#
|
||||
Decompressed = 152089
|
||||
15,0009 ms.
|
||||
---------------------------------------
|
||||
(Decompression) Zlib using SharpZipLib
|
||||
Decompressed = 152089
|
||||
3577,2046 ms.
|
||||
---------------------------------------
|
||||
(Decompression) QuickLZ C#
|
||||
Decompressed = 152089
|
||||
21,0012 ms.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Improved C# LZF Compressor, a very small data compression library. The compression algorithm is extremely fast.
|
||||
/// Note for strings, ensure you only use Unicode else special characters may get corrupted.
|
||||
public static class CLZF2
|
||||
{
|
||||
private static readonly uint HLOG = 14;
|
||||
private static readonly uint HSIZE = (1 << 14);
|
||||
private static readonly uint MAX_LIT = (1 << 5);
|
||||
private static readonly uint MAX_OFF = (1 << 13);
|
||||
private static readonly uint MAX_REF = ((1 << 8) + (1 << 3));
|
||||
|
||||
/// <summary>
|
||||
/// Hashtable, that can be allocated only once
|
||||
/// </summary>
|
||||
private static readonly long[] HashTable = new long[HSIZE];
|
||||
|
||||
// Compresses inputBytes
|
||||
public static byte[] Compress(byte[] inputBytes)
|
||||
{
|
||||
// Starting guess, increase it later if needed
|
||||
int outputByteCountGuess = inputBytes.Length * 2;
|
||||
byte[] tempBuffer = new byte[outputByteCountGuess];
|
||||
int byteCount = lzf_compress(inputBytes, ref tempBuffer);
|
||||
|
||||
// If byteCount is 0, then increase buffer and try again
|
||||
while (byteCount == 0)
|
||||
{
|
||||
outputByteCountGuess *= 2;
|
||||
tempBuffer = new byte[outputByteCountGuess];
|
||||
byteCount = lzf_compress(inputBytes, ref tempBuffer);
|
||||
}
|
||||
|
||||
byte[] outputBytes = new byte[byteCount];
|
||||
Buffer.BlockCopy(tempBuffer, 0, outputBytes, 0, byteCount);
|
||||
return outputBytes;
|
||||
}
|
||||
|
||||
// Decompress outputBytes
|
||||
public static byte[] Decompress(byte[] inputBytes)
|
||||
{
|
||||
// Starting guess, increase it later if needed
|
||||
int outputByteCountGuess = inputBytes.Length * 2;
|
||||
byte[] tempBuffer = new byte[outputByteCountGuess];
|
||||
int byteCount = lzf_decompress(inputBytes, ref tempBuffer);
|
||||
|
||||
// If byteCount is 0, then increase buffer and try again
|
||||
while (byteCount == 0)
|
||||
{
|
||||
outputByteCountGuess *= 2;
|
||||
tempBuffer = new byte[outputByteCountGuess];
|
||||
byteCount = lzf_decompress(inputBytes, ref tempBuffer);
|
||||
}
|
||||
|
||||
byte[] outputBytes = new byte[byteCount];
|
||||
Buffer.BlockCopy(tempBuffer, 0, outputBytes, 0, byteCount);
|
||||
return outputBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compresses the data using LibLZF algorithm
|
||||
/// </summary>
|
||||
/// <param name="input">Reference to the data to compress</param>
|
||||
/// <param name="output">Reference to a buffer which will contain the compressed data</param>
|
||||
/// <returns>The size of the compressed archive in the output buffer</returns>
|
||||
public static int lzf_compress(byte[] input, ref byte[] output)
|
||||
{
|
||||
int inputLength = input.Length;
|
||||
int outputLength = output.Length;
|
||||
|
||||
Array.Clear(HashTable, 0, (int)HSIZE);
|
||||
|
||||
long hslot;
|
||||
uint iidx = 0;
|
||||
uint oidx = 0;
|
||||
long reference;
|
||||
|
||||
uint hval = (uint)(((input[iidx]) << 8) | input[iidx + 1]); // FRST(in_data, iidx);
|
||||
long off;
|
||||
int lit = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (iidx < inputLength - 2)
|
||||
{
|
||||
hval = (hval << 8) | input[iidx + 2];
|
||||
hslot = ((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1));
|
||||
reference = HashTable[hslot];
|
||||
HashTable[hslot] = (long)iidx;
|
||||
|
||||
|
||||
if ((off = iidx - reference - 1) < MAX_OFF
|
||||
&& iidx + 4 < inputLength
|
||||
&& reference > 0
|
||||
&& input[reference + 0] == input[iidx + 0]
|
||||
&& input[reference + 1] == input[iidx + 1]
|
||||
&& input[reference + 2] == input[iidx + 2]
|
||||
)
|
||||
{
|
||||
/* match found at *reference++ */
|
||||
uint len = 2;
|
||||
uint maxlen = (uint)inputLength - iidx - len;
|
||||
maxlen = maxlen > MAX_REF ? MAX_REF : maxlen;
|
||||
|
||||
if (oidx + lit + 1 + 3 >= outputLength)
|
||||
return 0;
|
||||
|
||||
do
|
||||
len++;
|
||||
while (len < maxlen && input[reference + len] == input[iidx + len]);
|
||||
|
||||
if (lit != 0)
|
||||
{
|
||||
output[oidx++] = (byte)(lit - 1);
|
||||
lit = -lit;
|
||||
do
|
||||
output[oidx++] = input[iidx + lit];
|
||||
while ((++lit) != 0);
|
||||
}
|
||||
|
||||
len -= 2;
|
||||
iidx++;
|
||||
|
||||
if (len < 7)
|
||||
{
|
||||
output[oidx++] = (byte)((off >> 8) + (len << 5));
|
||||
}
|
||||
else
|
||||
{
|
||||
output[oidx++] = (byte)((off >> 8) + (7 << 5));
|
||||
output[oidx++] = (byte)(len - 7);
|
||||
}
|
||||
|
||||
output[oidx++] = (byte)off;
|
||||
|
||||
iidx += len - 1;
|
||||
hval = (uint)(((input[iidx]) << 8) | input[iidx + 1]);
|
||||
|
||||
hval = (hval << 8) | input[iidx + 2];
|
||||
HashTable[((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1))] = iidx;
|
||||
iidx++;
|
||||
|
||||
hval = (hval << 8) | input[iidx + 2];
|
||||
HashTable[((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1))] = iidx;
|
||||
iidx++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (iidx == inputLength)
|
||||
break;
|
||||
|
||||
/* one more literal byte we must copy */
|
||||
lit++;
|
||||
iidx++;
|
||||
|
||||
if (lit == MAX_LIT)
|
||||
{
|
||||
if (oidx + 1 + MAX_LIT >= outputLength)
|
||||
return 0;
|
||||
|
||||
output[oidx++] = (byte)(MAX_LIT - 1);
|
||||
lit = -lit;
|
||||
do
|
||||
output[oidx++] = input[iidx + lit];
|
||||
while ((++lit) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (lit != 0)
|
||||
{
|
||||
if (oidx + lit + 1 >= outputLength)
|
||||
return 0;
|
||||
|
||||
output[oidx++] = (byte)(lit - 1);
|
||||
lit = -lit;
|
||||
do
|
||||
output[oidx++] = input[iidx + lit];
|
||||
while ((++lit) != 0);
|
||||
}
|
||||
|
||||
return (int)oidx;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses the data using LibLZF algorithm
|
||||
/// </summary>
|
||||
/// <param name="input">Reference to the data to decompress</param>
|
||||
/// <param name="output">Reference to a buffer which will contain the decompressed data</param>
|
||||
/// <returns>Returns decompressed size</returns>
|
||||
public static int lzf_decompress(byte[] input, ref byte[] output)
|
||||
{
|
||||
int inputLength = input.Length;
|
||||
int outputLength = output.Length;
|
||||
|
||||
uint iidx = 0;
|
||||
uint oidx = 0;
|
||||
|
||||
do
|
||||
{
|
||||
uint ctrl = input[iidx++];
|
||||
|
||||
if (ctrl < (1 << 5)) /* literal run */
|
||||
{
|
||||
ctrl++;
|
||||
|
||||
if (oidx + ctrl > outputLength)
|
||||
{
|
||||
//SET_ERRNO (E2BIG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
output[oidx++] = input[iidx++];
|
||||
while ((--ctrl) != 0);
|
||||
}
|
||||
else /* back reference */
|
||||
{
|
||||
uint len = ctrl >> 5;
|
||||
|
||||
int reference = (int)(oidx - ((ctrl & 0x1f) << 8) - 1);
|
||||
|
||||
if (len == 7)
|
||||
len += input[iidx++];
|
||||
|
||||
reference -= input[iidx++];
|
||||
|
||||
if (oidx + len + 2 > outputLength)
|
||||
{
|
||||
//SET_ERRNO (E2BIG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reference < 0)
|
||||
{
|
||||
//SET_ERRNO (EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
output[oidx++] = output[reference++];
|
||||
output[oidx++] = output[reference++];
|
||||
|
||||
do
|
||||
output[oidx++] = output[reference++];
|
||||
while ((--len) != 0);
|
||||
}
|
||||
}
|
||||
while (iidx < inputLength);
|
||||
|
||||
return (int)oidx;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f69e6f88ce470d742adfcbaf0bcbd001
|
||||
timeCreated: 1464877682
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,233 @@
|
||||
/// Credit Farfarer
|
||||
/// Sourced from - https://gist.github.com/Farfarer/a765cd07920d48a8713a0c1924db6d70
|
||||
/// Updated for UI / 2D - SimonDarksideJ
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[System.Serializable]
|
||||
public class CableCurve
|
||||
{
|
||||
[SerializeField]
|
||||
Vector2 m_start;
|
||||
[SerializeField]
|
||||
Vector2 m_end;
|
||||
[SerializeField]
|
||||
float m_slack;
|
||||
[SerializeField]
|
||||
int m_steps;
|
||||
[SerializeField]
|
||||
bool m_regen;
|
||||
|
||||
static Vector2[] emptyCurve = new Vector2[] { new Vector2(0.0f, 0.0f), new Vector2(0.0f, 0.0f) };
|
||||
[SerializeField]
|
||||
Vector2[] points;
|
||||
|
||||
public bool regenPoints
|
||||
{
|
||||
get { return m_regen; }
|
||||
set
|
||||
{
|
||||
m_regen = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 start
|
||||
{
|
||||
get { return m_start; }
|
||||
set
|
||||
{
|
||||
if (value != m_start)
|
||||
m_regen = true;
|
||||
m_start = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 end
|
||||
{
|
||||
get { return m_end; }
|
||||
set
|
||||
{
|
||||
if (value != m_end)
|
||||
m_regen = true;
|
||||
m_end = value;
|
||||
}
|
||||
}
|
||||
public float slack
|
||||
{
|
||||
get { return m_slack; }
|
||||
set
|
||||
{
|
||||
if (value != m_slack)
|
||||
m_regen = true;
|
||||
m_slack = Mathf.Max(0.0f, value);
|
||||
}
|
||||
}
|
||||
public int steps
|
||||
{
|
||||
get { return m_steps; }
|
||||
set
|
||||
{
|
||||
if (value != m_steps)
|
||||
m_regen = true;
|
||||
m_steps = Mathf.Max(2, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 midPoint
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector2 mid = Vector2.zero;
|
||||
if (m_steps == 2)
|
||||
{
|
||||
return (points[0] + points[1]) * 0.5f;
|
||||
}
|
||||
else if (m_steps > 2)
|
||||
{
|
||||
int m = m_steps / 2;
|
||||
if ((m_steps % 2) == 0)
|
||||
{
|
||||
mid = (points[m] + points[m + 1]) * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mid = points[m];
|
||||
}
|
||||
}
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
|
||||
public CableCurve()
|
||||
{
|
||||
points = emptyCurve;
|
||||
m_start = Vector2.up;
|
||||
m_end = Vector2.up + Vector2.right;
|
||||
m_slack = 0.5f;
|
||||
m_steps = 20;
|
||||
m_regen = true;
|
||||
}
|
||||
|
||||
public CableCurve(Vector2[] inputPoints)
|
||||
{
|
||||
points = inputPoints;
|
||||
m_start = inputPoints[0];
|
||||
m_end = inputPoints[1];
|
||||
m_slack = 0.5f;
|
||||
m_steps = 20;
|
||||
m_regen = true;
|
||||
}
|
||||
|
||||
public CableCurve(List<Vector2> inputPoints)
|
||||
{
|
||||
points = inputPoints.ToArray();
|
||||
m_start = inputPoints[0];
|
||||
m_end = inputPoints[1];
|
||||
m_slack = 0.5f;
|
||||
m_steps = 20;
|
||||
m_regen = true;
|
||||
}
|
||||
|
||||
public CableCurve(CableCurve v)
|
||||
{
|
||||
points = v.Points();
|
||||
m_start = v.start;
|
||||
m_end = v.end;
|
||||
m_slack = v.slack;
|
||||
m_steps = v.steps;
|
||||
m_regen = v.regenPoints;
|
||||
}
|
||||
|
||||
public Vector2[] Points()
|
||||
{
|
||||
if (!m_regen)
|
||||
return points;
|
||||
|
||||
if (m_steps < 2)
|
||||
return emptyCurve;
|
||||
|
||||
float lineDist = Vector2.Distance(m_end, m_start);
|
||||
float lineDistH = Vector2.Distance(new Vector2(m_end.x, m_start.y), m_start);
|
||||
float l = lineDist + Mathf.Max(0.0001f, m_slack);
|
||||
float r = 0.0f;
|
||||
float s = m_start.y;
|
||||
float u = lineDistH;
|
||||
float v = end.y;
|
||||
|
||||
if ((u - r) == 0.0f)
|
||||
return emptyCurve;
|
||||
|
||||
float ztarget = Mathf.Sqrt(Mathf.Pow(l, 2.0f) - Mathf.Pow(v - s, 2.0f)) / (u - r);
|
||||
|
||||
int loops = 30;
|
||||
int iterationCount = 0;
|
||||
int maxIterations = loops * 10; // For safety.
|
||||
bool found = false;
|
||||
|
||||
float z = 0.0f;
|
||||
float ztest = 0.0f;
|
||||
float zstep = 100.0f;
|
||||
float ztesttarget = 0.0f;
|
||||
for (int i = 0; i < loops; i++)
|
||||
{
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
iterationCount++;
|
||||
ztest = z + zstep;
|
||||
ztesttarget = (float)Math.Sinh(ztest) / ztest;
|
||||
|
||||
if (float.IsInfinity(ztesttarget))
|
||||
continue;
|
||||
|
||||
if (ztesttarget == ztarget)
|
||||
{
|
||||
found = true;
|
||||
z = ztest;
|
||||
break;
|
||||
}
|
||||
else if (ztesttarget > ztarget)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
z = ztest;
|
||||
}
|
||||
|
||||
if (iterationCount > maxIterations)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
break;
|
||||
|
||||
zstep *= 0.1f;
|
||||
}
|
||||
|
||||
float a = (u - r) / 2.0f / z;
|
||||
float p = (r + u - a * Mathf.Log((l + v - s) / (l - v + s))) / 2.0f;
|
||||
float q = (v + s - l * (float)Math.Cosh(z) / (float)Math.Sinh(z)) / 2.0f;
|
||||
|
||||
points = new Vector2[m_steps];
|
||||
float stepsf = m_steps - 1;
|
||||
float stepf;
|
||||
for (int i = 0; i < m_steps; i++)
|
||||
{
|
||||
stepf = i / stepsf;
|
||||
Vector2 pos = Vector2.zero;
|
||||
pos.x = Mathf.Lerp(start.x, end.x, stepf);
|
||||
pos.y = a * (float)Math.Cosh(((stepf * lineDistH) - p) / a) + q;
|
||||
points[i] = pos;
|
||||
}
|
||||
|
||||
m_regen = false;
|
||||
return points;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2444f085ab49ff24b888b175f46b55c7
|
||||
timeCreated: 1501871616
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,82 @@
|
||||
/// Credit Board To Bits Games
|
||||
/// Original Sourced from - https://www.youtube.com/watch?v=Or3fA-UjnwU
|
||||
/// Updated and modified for UI Extensions to be more generic
|
||||
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public class Circle
|
||||
{
|
||||
[SerializeField]
|
||||
private float xAxis;
|
||||
|
||||
[SerializeField]
|
||||
private float yAxis;
|
||||
|
||||
[SerializeField]
|
||||
private int steps;
|
||||
|
||||
public float X
|
||||
{
|
||||
get { return xAxis; }
|
||||
set { xAxis = value; }
|
||||
}
|
||||
|
||||
public float Y
|
||||
{
|
||||
get { return yAxis; }
|
||||
set { yAxis = value; }
|
||||
}
|
||||
|
||||
public int Steps
|
||||
{
|
||||
get { return steps; }
|
||||
set { steps = value; }
|
||||
}
|
||||
|
||||
public Circle(float radius)
|
||||
{
|
||||
this.xAxis = radius;
|
||||
this.yAxis = radius;
|
||||
this.steps = 1;
|
||||
}
|
||||
|
||||
public Circle(float radius, int steps)
|
||||
{
|
||||
this.xAxis = radius;
|
||||
this.yAxis = radius;
|
||||
this.steps = steps;
|
||||
}
|
||||
|
||||
public Circle(float xAxis, float yAxis)
|
||||
{
|
||||
this.xAxis = xAxis;
|
||||
this.yAxis = yAxis;
|
||||
this.steps = 10;
|
||||
}
|
||||
|
||||
public Circle(float xAxis, float yAxis, int steps)
|
||||
{
|
||||
this.xAxis = xAxis;
|
||||
this.yAxis = yAxis;
|
||||
this.steps = steps;
|
||||
}
|
||||
|
||||
public Vector2 Evaluate(float t)
|
||||
{
|
||||
float increments = 360f / steps;
|
||||
float angle = Mathf.Deg2Rad * increments * t;
|
||||
float x = Mathf.Sin(angle) * xAxis;
|
||||
float y = Mathf.Cos(angle) * yAxis;
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
public void Evaluate(float t, out Vector2 eval)
|
||||
{
|
||||
float increments = 360f / steps;
|
||||
float angle = Mathf.Deg2Rad * increments * t;
|
||||
eval.x = Mathf.Sin(angle) * xAxis;
|
||||
eval.y = Mathf.Cos(angle) * yAxis;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f11f61a6960d26445a760da7dae63cf2
|
||||
timeCreated: 1498154251
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,31 @@
|
||||
/// Credit FireOApache
|
||||
/// sourced from: http://answers.unity3d.com/questions/1149417/ui-button-onclick-sensitivity-for-high-dpi-devices.html#answer-1197307
|
||||
|
||||
/*USAGE:
|
||||
Simply place the script on the EventSystem in the scene to correct the drag thresholds*/
|
||||
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(EventSystem))]
|
||||
[AddComponentMenu("UI/Extensions/DragCorrector")]
|
||||
public class DragCorrector : MonoBehaviour
|
||||
{
|
||||
public int baseTH = 6;
|
||||
public int basePPI = 210;
|
||||
public int dragTH = 0;
|
||||
|
||||
void Start()
|
||||
{
|
||||
dragTH = baseTH * (int)Screen.dpi / basePPI;
|
||||
|
||||
EventSystem es = GetComponent<EventSystem>();
|
||||
|
||||
if (es)
|
||||
{
|
||||
es.pixelDragThreshold = dragTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af1c809ef037025409983d19f9b0baac
|
||||
timeCreated: 1464969622
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,269 @@
|
||||
using System;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace UnityEngine.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple toggle -- something that has an 'on' and 'off' states: checkbox, toggle button, radio button, etc.
|
||||
/// </summary>
|
||||
[AddComponentMenu("UI/Extensions/Extensions Toggle", 31)]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
public class ExtensionsToggle : Selectable, IPointerClickHandler, ISubmitHandler, ICanvasElement
|
||||
{
|
||||
/// <summary>
|
||||
/// Variable to identify this script, change the datatype if needed to fit your use case
|
||||
/// </summary>
|
||||
public string UniqueID;
|
||||
|
||||
public enum ToggleTransition
|
||||
{
|
||||
None,
|
||||
Fade
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ToggleEvent : UnityEvent<bool>
|
||||
{ }
|
||||
|
||||
[Serializable]
|
||||
public class ToggleEventObject : UnityEvent<ExtensionsToggle>
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Transition type.
|
||||
/// </summary>
|
||||
public ToggleTransition toggleTransition = ToggleTransition.Fade;
|
||||
|
||||
/// <summary>
|
||||
/// Graphic the toggle should be working with.
|
||||
/// </summary>
|
||||
public Graphic graphic;
|
||||
|
||||
// group that this toggle can belong to
|
||||
[SerializeField]
|
||||
private ExtensionsToggleGroup m_Group;
|
||||
|
||||
public ExtensionsToggleGroup Group
|
||||
{
|
||||
get { return m_Group; }
|
||||
set
|
||||
{
|
||||
m_Group = value;
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
#endif
|
||||
{
|
||||
SetToggleGroup(m_Group, true);
|
||||
PlayEffect(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
|
||||
/// </summary>
|
||||
[Tooltip("Use this event if you only need the bool state of the toggle that was changed")]
|
||||
public ToggleEvent onValueChanged = new ToggleEvent();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
|
||||
/// </summary>
|
||||
[Tooltip("Use this event if you need access to the toggle that was changed")]
|
||||
public ToggleEventObject onToggleChanged = new ToggleEventObject();
|
||||
|
||||
// Whether the toggle is on
|
||||
[FormerlySerializedAs("m_IsActive")]
|
||||
[Tooltip("Is the toggle currently on or off?")]
|
||||
[SerializeField]
|
||||
private bool m_IsOn;
|
||||
|
||||
protected ExtensionsToggle()
|
||||
{ }
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
Set(m_IsOn, false);
|
||||
PlayEffect(toggleTransition == ToggleTransition.None);
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
if (!Application.isPlaying)
|
||||
#else
|
||||
var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this);
|
||||
if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying)
|
||||
#endif
|
||||
{
|
||||
CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // if UNITY_EDITOR
|
||||
|
||||
public virtual void Rebuild(CanvasUpdate executing)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (executing == CanvasUpdate.Prelayout)
|
||||
{
|
||||
onValueChanged.Invoke(m_IsOn);
|
||||
onToggleChanged.Invoke(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual void LayoutComplete()
|
||||
{ }
|
||||
|
||||
public virtual void GraphicUpdateComplete()
|
||||
{ }
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
SetToggleGroup(m_Group, false);
|
||||
PlayEffect(true);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
SetToggleGroup(null, false);
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
protected override void OnDidApplyAnimationProperties()
|
||||
{
|
||||
// Check if isOn has been changed by the animation.
|
||||
// Unfortunately there is no way to check if we don't have a graphic.
|
||||
if (graphic != null)
|
||||
{
|
||||
bool oldValue = !Mathf.Approximately(graphic.canvasRenderer.GetColor().a, 0);
|
||||
if (m_IsOn != oldValue)
|
||||
{
|
||||
m_IsOn = oldValue;
|
||||
Set(!oldValue);
|
||||
}
|
||||
}
|
||||
|
||||
base.OnDidApplyAnimationProperties();
|
||||
}
|
||||
|
||||
private void SetToggleGroup(ExtensionsToggleGroup newGroup, bool setMemberValue)
|
||||
{
|
||||
ExtensionsToggleGroup oldGroup = m_Group;
|
||||
|
||||
// Sometimes IsActive returns false in OnDisable so don't check for it.
|
||||
// Rather remove the toggle too often than too little.
|
||||
if (m_Group != null)
|
||||
m_Group.UnregisterToggle(this);
|
||||
|
||||
// At runtime the group variable should be set but not when calling this method from OnEnable or OnDisable.
|
||||
// That's why we use the setMemberValue parameter.
|
||||
if (setMemberValue)
|
||||
m_Group = newGroup;
|
||||
|
||||
// Only register to the new group if this Toggle is active.
|
||||
if (m_Group != null && IsActive())
|
||||
m_Group.RegisterToggle(this);
|
||||
|
||||
// If we are in a new group, and this toggle is on, notify group.
|
||||
// Note: Don't refer to m_Group here as it's not guaranteed to have been set.
|
||||
if (newGroup != null && newGroup != oldGroup && IsOn && IsActive())
|
||||
m_Group.NotifyToggleOn(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the toggle is currently active.
|
||||
/// </summary>
|
||||
public bool IsOn
|
||||
{
|
||||
get { return m_IsOn; }
|
||||
set
|
||||
{
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Set(bool value)
|
||||
{
|
||||
Set(value, true);
|
||||
}
|
||||
|
||||
void Set(bool value, bool sendCallback)
|
||||
{
|
||||
if (m_IsOn == value)
|
||||
return;
|
||||
|
||||
// if we are in a group and set to true, do group logic
|
||||
m_IsOn = value;
|
||||
if (m_Group != null && IsActive())
|
||||
{
|
||||
if (m_IsOn || (!m_Group.AnyTogglesOn() && !m_Group.AllowSwitchOff))
|
||||
{
|
||||
m_IsOn = true;
|
||||
m_Group.NotifyToggleOn(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Always send event when toggle is clicked, even if value didn't change
|
||||
// due to already active toggle in a toggle group being clicked.
|
||||
// Controls like Dropdown rely on this.
|
||||
// It's up to the user to ignore a selection being set to the same value it already was, if desired.
|
||||
PlayEffect(toggleTransition == ToggleTransition.None);
|
||||
if (sendCallback)
|
||||
{
|
||||
onValueChanged.Invoke(m_IsOn);
|
||||
onToggleChanged.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play the appropriate effect.
|
||||
/// </summary>
|
||||
private void PlayEffect(bool instant)
|
||||
{
|
||||
if (graphic == null)
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
graphic.canvasRenderer.SetAlpha(m_IsOn ? 1f : 0f);
|
||||
else
|
||||
#endif
|
||||
graphic.CrossFadeAlpha(m_IsOn ? 1f : 0f, instant ? 0f : 0.1f, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assume the correct visual state.
|
||||
/// </summary>
|
||||
protected override void Start()
|
||||
{
|
||||
PlayEffect(true);
|
||||
}
|
||||
|
||||
private void InternalToggle()
|
||||
{
|
||||
if (!IsActive() || !IsInteractable())
|
||||
return;
|
||||
|
||||
IsOn = !IsOn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// React to clicks.
|
||||
/// </summary>
|
||||
public virtual void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button != PointerEventData.InputButton.Left)
|
||||
return;
|
||||
|
||||
InternalToggle();
|
||||
}
|
||||
|
||||
public virtual void OnSubmit(BaseEventData eventData)
|
||||
{
|
||||
InternalToggle();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc733ccacdce62148ac1f46d1dd84ff6
|
||||
timeCreated: 1450456340
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/Extensions Toggle Group")]
|
||||
[DisallowMultipleComponent]
|
||||
public class ExtensionsToggleGroup : UIBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private bool m_AllowSwitchOff = false;
|
||||
public bool AllowSwitchOff { get { return m_AllowSwitchOff; } set { m_AllowSwitchOff = value; } }
|
||||
|
||||
private List<ExtensionsToggle> m_Toggles = new List<ExtensionsToggle>();
|
||||
|
||||
[Serializable]
|
||||
public class ToggleGroupEvent : UnityEvent<bool>
|
||||
{ }
|
||||
|
||||
public ToggleGroupEvent onToggleGroupChanged = new ToggleGroupEvent();
|
||||
public ToggleGroupEvent onToggleGroupToggleChanged = new ToggleGroupEvent();
|
||||
|
||||
public ExtensionsToggle SelectedToggle { get; private set; }
|
||||
|
||||
|
||||
protected ExtensionsToggleGroup()
|
||||
{ }
|
||||
|
||||
private void ValidateToggleIsInGroup(ExtensionsToggle toggle)
|
||||
{
|
||||
if (toggle == null || !m_Toggles.Contains(toggle))
|
||||
throw new ArgumentException(string.Format("Toggle {0} is not part of ToggleGroup {1}", new object[] { toggle, this }));
|
||||
}
|
||||
|
||||
public void NotifyToggleOn(ExtensionsToggle toggle)
|
||||
{
|
||||
ValidateToggleIsInGroup(toggle);
|
||||
|
||||
// disable all toggles in the group
|
||||
for (var i = 0; i < m_Toggles.Count; i++)
|
||||
{
|
||||
if (m_Toggles[i] == toggle)
|
||||
{
|
||||
SelectedToggle = toggle;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_Toggles[i].IsOn = false;
|
||||
}
|
||||
onToggleGroupChanged.Invoke(AnyTogglesOn());
|
||||
}
|
||||
|
||||
public void UnregisterToggle(ExtensionsToggle toggle)
|
||||
{
|
||||
if (m_Toggles.Contains(toggle))
|
||||
{
|
||||
m_Toggles.Remove(toggle);
|
||||
toggle.onValueChanged.RemoveListener(NotifyToggleChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyToggleChanged(bool isOn)
|
||||
{
|
||||
onToggleGroupToggleChanged.Invoke(isOn);
|
||||
}
|
||||
|
||||
public void RegisterToggle(ExtensionsToggle toggle)
|
||||
{
|
||||
if (!m_Toggles.Contains(toggle))
|
||||
{
|
||||
m_Toggles.Add(toggle);
|
||||
toggle.onValueChanged.AddListener(NotifyToggleChanged);
|
||||
}
|
||||
}
|
||||
|
||||
public bool AnyTogglesOn()
|
||||
{
|
||||
return m_Toggles.Find(x => x.IsOn) != null;
|
||||
}
|
||||
|
||||
public IEnumerable<ExtensionsToggle> ActiveToggles()
|
||||
{
|
||||
return m_Toggles.Where(x => x.IsOn);
|
||||
}
|
||||
|
||||
public void SetAllTogglesOff()
|
||||
{
|
||||
bool oldAllowSwitchOff = m_AllowSwitchOff;
|
||||
m_AllowSwitchOff = true;
|
||||
|
||||
for (var i = 0; i < m_Toggles.Count; i++)
|
||||
m_Toggles[i].IsOn = false;
|
||||
|
||||
m_AllowSwitchOff = oldAllowSwitchOff;
|
||||
}
|
||||
|
||||
public void HasTheGroupToggle(bool value)
|
||||
{
|
||||
Debug.Log("Testing, the group has toggled [" + value + "]");
|
||||
}
|
||||
|
||||
public void HasAToggleFlipped(bool value)
|
||||
{
|
||||
Debug.Log("Testing, a toggle has toggled [" + value + "]");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf31acdd4bba9fc45b8a5cc6de985aee
|
||||
timeCreated: 1450454546
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public static class ExtentionMethods
|
||||
{
|
||||
public static T GetOrAddComponent<T>(this GameObject child) where T : Component
|
||||
{
|
||||
T result = child.GetComponent<T>();
|
||||
if (result == null)
|
||||
{
|
||||
result = child.AddComponent<T>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool IsPrefab(this GameObject gameObject)
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(gameObject));
|
||||
}
|
||||
|
||||
return
|
||||
!gameObject.scene.IsValid() &&
|
||||
!gameObject.scene.isLoaded &&
|
||||
gameObject.GetInstanceID() >= 0 &&
|
||||
// I noticed that ones with IDs under 0 were objects I didn't recognize
|
||||
!gameObject.hideFlags.HasFlag(HideFlags.HideInHierarchy);
|
||||
// I don't care about GameObjects *inside* prefabs, just the overall prefab.
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed85e09a894358f4782be8df50a1221a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,42 @@
|
||||
/// Credit Vicente Russo
|
||||
/// Sourced from - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/issues/23/returnkeytriggersbutton
|
||||
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Usage: Add this component to the input and add the function to execute to the EnterSubmit event of this script
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(InputField))]
|
||||
[AddComponentMenu("UI/Extensions/Input Field Submit")]
|
||||
public class InputFieldEnterSubmit : MonoBehaviour
|
||||
{
|
||||
[System.Serializable]
|
||||
public class EnterSubmitEvent : UnityEvent<string>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EnterSubmitEvent EnterSubmit;
|
||||
public bool defocusInput = true;
|
||||
private InputField _input;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_input = GetComponent<InputField>();
|
||||
_input.onEndEdit.AddListener(OnEndEdit);
|
||||
}
|
||||
|
||||
public void OnEndEdit(string txt)
|
||||
{
|
||||
if (!UIExtensionsInputManager.GetKeyDown(KeyCode.Return) && !UIExtensionsInputManager.GetKeyDown(KeyCode.KeypadEnter))
|
||||
return;
|
||||
EnterSubmit.Invoke(txt);
|
||||
if (defocusInput)
|
||||
{
|
||||
UnityEngine.EventSystems.EventSystem.current.SetSelectedGameObject(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfc77d7b04a86f845b59fb0979e8ec53
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@ -0,0 +1,21 @@
|
||||
/// Credit Slipp Douglas Thompson
|
||||
/// Sourced from - https://gist.github.com/capnslipp/349c18283f2fea316369
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// A concrete subclass of the Unity UI `Graphic` class that just skips drawing.
|
||||
/// Useful for providing a raycast target without actually drawing anything.
|
||||
[AddComponentMenu("Layout/Extensions/NonDrawingGraphic")]
|
||||
public class NonDrawingGraphic : MaskableGraphic
|
||||
{
|
||||
public override void SetMaterialDirty() { return; }
|
||||
public override void SetVerticesDirty() { return; }
|
||||
|
||||
/// Probably not necessary since the chain of calls `Rebuild()`->`UpdateGeometry()`->`DoMeshGeneration()`->`OnPopulateMesh()` won't happen; so here really just as a fail-safe.
|
||||
protected override void OnPopulateMesh(VertexHelper vh)
|
||||
{
|
||||
vh.Clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51db53697a53f7a479b8570674dae649
|
||||
timeCreated: 1483541456
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,28 @@
|
||||
/// Credit FireOApache
|
||||
/// sourced from: http://answers.unity3d.com/questions/1149417/ui-button-onclick-sensitivity-for-high-dpi-devices.html#answer-1197307
|
||||
|
||||
/*USAGE:
|
||||
Simply place the script on A Text control in the scene to display the current PPI / DPI of the screen*/
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(Text))]
|
||||
[AddComponentMenu("UI/Extensions/PPIViewer")]
|
||||
public class PPIViewer : MonoBehaviour
|
||||
{
|
||||
private Text label;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
label = GetComponent<Text>();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (label != null)
|
||||
{
|
||||
label.text = "PPI: " + Screen.dpi.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0f2698294b9b524bb75cb394378eb6e
|
||||
timeCreated: 1464969622
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,139 @@
|
||||
using System.Collections.Generic;
|
||||
/// Credit Brogan King (@BroganKing)
|
||||
/// Original Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/158/pagination-script
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/Pagination Manager")]
|
||||
public class PaginationManager : ToggleGroup
|
||||
{
|
||||
private List<Toggle> m_PaginationChildren;
|
||||
|
||||
[SerializeField]
|
||||
private ScrollSnapBase scrollSnap = null;
|
||||
|
||||
private bool isAClick;
|
||||
|
||||
public int CurrentPage
|
||||
{
|
||||
get { return scrollSnap.CurrentPage; }
|
||||
}
|
||||
|
||||
protected PaginationManager()
|
||||
{ }
|
||||
|
||||
|
||||
// Use this for initialization
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
if (scrollSnap == null)
|
||||
{
|
||||
Debug.LogError("A ScrollSnap script must be attached");
|
||||
return;
|
||||
}
|
||||
|
||||
// do not want the scroll snap pagination
|
||||
if (scrollSnap.Pagination)
|
||||
scrollSnap.Pagination = null;
|
||||
|
||||
// set scroll snap listeners
|
||||
scrollSnap.OnSelectionPageChangedEvent.AddListener(SetToggleGraphics);
|
||||
scrollSnap.OnSelectionChangeEndEvent.AddListener(OnPageChangeEnd);
|
||||
|
||||
ResetPaginationChildren();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remake the internal list of child toggles (m_PaginationChildren).
|
||||
/// Used after adding/removing a toggle.
|
||||
/// </summary>
|
||||
public void ResetPaginationChildren()
|
||||
{
|
||||
// add selectables to list
|
||||
m_PaginationChildren = GetComponentsInChildren<Toggle>().ToList<Toggle>();
|
||||
for (int i = 0; i < m_PaginationChildren.Count; i++)
|
||||
{
|
||||
m_PaginationChildren[i].onValueChanged.AddListener(ToggleClick);
|
||||
m_PaginationChildren[i].group = this;
|
||||
m_PaginationChildren[i].isOn = false;
|
||||
}
|
||||
|
||||
// set toggles on start
|
||||
SetToggleGraphics(CurrentPage);
|
||||
|
||||
// warn user that they have uneven amount of pagination toggles to page count
|
||||
if (m_PaginationChildren.Count != scrollSnap._scroll_rect.content.childCount)
|
||||
Debug.LogWarning("Uneven pagination icon to page count");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calling from other scripts if you need to change screens programmatically
|
||||
/// </summary>
|
||||
/// <param name="pageNo"></param>
|
||||
public void GoToScreen(int pageNo)
|
||||
{
|
||||
scrollSnap.GoToScreen(pageNo, true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calls GoToScreen() based on the index of toggle that was pressed
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
private void ToggleClick(Toggle target)
|
||||
{
|
||||
if (!target.isOn)
|
||||
{
|
||||
isAClick = true;
|
||||
GoToScreen(m_PaginationChildren.IndexOf(target));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ToggleClick(bool toggle)
|
||||
{
|
||||
if (toggle)
|
||||
{
|
||||
for (int i = 0; i < m_PaginationChildren.Count; i++)
|
||||
{
|
||||
if (m_PaginationChildren[i].isOn && !scrollSnap._suspendEvents)
|
||||
{
|
||||
GoToScreen(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls GoToScreen() based on the index of toggle that was pressed
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
private void ToggleClick(int target)
|
||||
{
|
||||
isAClick = true;
|
||||
GoToScreen(target);
|
||||
}
|
||||
|
||||
private void SetToggleGraphics(int pageNo)
|
||||
{
|
||||
if (!isAClick)
|
||||
{
|
||||
m_PaginationChildren[pageNo].isOn = true;
|
||||
//for (int i = 0; i < m_PaginationChildren.Count; i++)
|
||||
//{
|
||||
// m_PaginationChildren[i].isOn = pageNo == i ? true : false;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPageChangeEnd(int pageNo)
|
||||
{
|
||||
isAClick = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cff19ba98ef11d4ebf2e8cbeb6a4342
|
||||
timeCreated: 1502291570
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,7 @@
|
||||
/// Credit tanoshimi
|
||||
/// Sourced from - https://forum.unity3d.com/threads/read-only-fields.68976/
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public class ReadOnlyAttribute : PropertyAttribute { }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 244394c76ae0d484d83567b74f4332cd
|
||||
timeCreated: 1498392707
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,36 @@
|
||||
/// Credit Melang
|
||||
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
|
||||
/// Updated SimonDarksideJ - reworked to 4.6.1 standards
|
||||
|
||||
using UnityEngine.EventSystems;
|
||||
namespace UnityEngine.UI
|
||||
{
|
||||
[RequireComponent(typeof(InputField))]
|
||||
[AddComponentMenu("UI/Extensions/Return Key Trigger")]
|
||||
public class ReturnKeyTriggersButton : MonoBehaviour, ISubmitHandler
|
||||
{
|
||||
private EventSystem _system;
|
||||
|
||||
public Button button;
|
||||
private bool highlight = true;
|
||||
public float highlightDuration = 0.2f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
_system = EventSystem.current;
|
||||
}
|
||||
|
||||
void RemoveHighlight()
|
||||
{
|
||||
button.OnPointerExit(new PointerEventData(_system));
|
||||
}
|
||||
|
||||
public void OnSubmit(BaseEventData eventData)
|
||||
{
|
||||
if (highlight) button.OnPointerEnter(new PointerEventData(_system));
|
||||
button.OnPointerClick(new PointerEventData(_system));
|
||||
|
||||
if (highlight) Invoke("RemoveHighlight", highlightDuration);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f08f1bd2c562a474c99ff9d746d3c99b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@ -0,0 +1,149 @@
|
||||
/// Credit srinivas sunil
|
||||
/// sourced from: https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/pull-requests/21/develop_53/diff
|
||||
/// Updated by Hiep Eldest : https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/300/scrollconflictmanager-not-working-if
|
||||
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
/// <summary>
|
||||
/// This is the most efficient way to handle scroll conflicts when there are multiple scroll rects, this is useful when there is a vertical scrollrect in/on a horizontal scrollrect or vice versa
|
||||
/// Attach the script to the rect scroll and assign other rectscroll in the inspector (one is vertical and other is horizontal) gathered and modified from unity answers(delta snipper)
|
||||
/// </summary>
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(ScrollRect))]
|
||||
[AddComponentMenu("UI/Extensions/Scrollrect Conflict Manager")]
|
||||
public class ScrollConflictManager : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
|
||||
{
|
||||
[Tooltip("The parent ScrollRect control hosting this ScrollSnap")]
|
||||
public ScrollRect ParentScrollRect;
|
||||
|
||||
[Tooltip("The parent ScrollSnap control hosting this Scroll Snap.\nIf left empty, it will use the ScrollSnap of the ParentScrollRect")]
|
||||
private ScrollSnapBase ParentScrollSnap;
|
||||
|
||||
private ScrollRect _myScrollRect;
|
||||
private IBeginDragHandler[] _beginDragHandlers;
|
||||
private IEndDragHandler[] _endDragHandlers;
|
||||
private IDragHandler[] _dragHandlers;
|
||||
//This tracks if the other one should be scrolling instead of the current one.
|
||||
private bool scrollOther;
|
||||
//This tracks whether the other one should scroll horizontally or vertically.
|
||||
private bool scrollOtherHorizontally;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (ParentScrollRect)
|
||||
{
|
||||
InitialiseConflictManager();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitialiseConflictManager()
|
||||
{
|
||||
//Get the current scroll rect so we can disable it if the other one is scrolling
|
||||
_myScrollRect = this.GetComponent<ScrollRect>();
|
||||
//If the current scroll Rect has the vertical checked then the other one will be scrolling horizontally.
|
||||
scrollOtherHorizontally = _myScrollRect.vertical;
|
||||
//Check some attributes to let the user know if this wont work as expected
|
||||
if (scrollOtherHorizontally)
|
||||
{
|
||||
if (_myScrollRect.horizontal)
|
||||
Debug.LogError("You have added the SecondScrollRect to a scroll view that already has both directions selected");
|
||||
if (!ParentScrollRect.horizontal)
|
||||
Debug.LogError("The other scroll rect does not support scrolling horizontally");
|
||||
}
|
||||
else if (!ParentScrollRect.vertical)
|
||||
{
|
||||
Debug.LogError("The other scroll rect does not support scrolling vertically");
|
||||
}
|
||||
|
||||
if (ParentScrollRect && !ParentScrollSnap)
|
||||
{
|
||||
ParentScrollSnap = ParentScrollRect.GetComponent<ScrollSnapBase>();
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (ParentScrollRect)
|
||||
{
|
||||
AssignScrollRectHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
private void AssignScrollRectHandlers()
|
||||
{
|
||||
_beginDragHandlers = ParentScrollRect.GetComponents<IBeginDragHandler>();
|
||||
_dragHandlers = ParentScrollRect.GetComponents<IDragHandler>();
|
||||
_endDragHandlers = ParentScrollRect.GetComponents<IEndDragHandler>();
|
||||
}
|
||||
|
||||
public void SetParentScrollRect(ScrollRect parentScrollRect)
|
||||
{
|
||||
ParentScrollRect = parentScrollRect;
|
||||
InitialiseConflictManager();
|
||||
AssignScrollRectHandlers();
|
||||
}
|
||||
|
||||
#region DragHandler
|
||||
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
//Get the absolute values of the x and y differences so we can see which one is bigger and scroll the other scroll rect accordingly
|
||||
float horizontal = Mathf.Abs(eventData.position.x - eventData.pressPosition.x);
|
||||
float vertical = Mathf.Abs(eventData.position.y - eventData.pressPosition.y);
|
||||
if (scrollOtherHorizontally)
|
||||
{
|
||||
if (horizontal > vertical)
|
||||
{
|
||||
scrollOther = true;
|
||||
//disable the current scroll rect so it does not move.
|
||||
_myScrollRect.enabled = false;
|
||||
for (int i = 0, length = _beginDragHandlers.Length; i < length; i++)
|
||||
{
|
||||
_beginDragHandlers[i].OnBeginDrag(eventData);
|
||||
if(ParentScrollSnap) ParentScrollSnap.OnBeginDrag(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (vertical > horizontal)
|
||||
{
|
||||
scrollOther = true;
|
||||
//disable the current scroll rect so it does not move.
|
||||
_myScrollRect.enabled = false;
|
||||
for (int i = 0, length = _beginDragHandlers.Length; i < length; i++)
|
||||
{
|
||||
_beginDragHandlers[i].OnBeginDrag(eventData);
|
||||
if (ParentScrollSnap) ParentScrollSnap.OnBeginDrag(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
if (scrollOther)
|
||||
{
|
||||
_myScrollRect.enabled = true;
|
||||
scrollOther = false;
|
||||
for (int i = 0, length = _endDragHandlers.Length; i < length; i++)
|
||||
{
|
||||
_endDragHandlers[i].OnEndDrag(eventData);
|
||||
if (ParentScrollSnap) ParentScrollSnap.OnEndDrag(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (scrollOther)
|
||||
{
|
||||
for (int i = 0, length = _endDragHandlers.Length; i < length; i++)
|
||||
{
|
||||
_dragHandlers[i].OnDrag(eventData);
|
||||
if (ParentScrollSnap) ParentScrollSnap.OnDrag(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion DragHandler
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cee880d45d4659540ada44c73f95a947
|
||||
timeCreated: 1463521238
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,109 @@
|
||||
/// Credit CaptainSchnittchen
|
||||
/// Credit TouchPad (OnScroll function) update - GamesRUs
|
||||
/// sourced from: http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-2011648
|
||||
|
||||
/*USAGE:
|
||||
Simply place the script on the ScrollRect that contains the selectable children we'll be scrolling to
|
||||
and drag'n'drop the RectTransform of the options "container" that we'll be scrolling.*/
|
||||
|
||||
using System;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/ScrollRectEx")]
|
||||
public class ScrollRectEx : ScrollRect
|
||||
{
|
||||
private bool routeToParent = false;
|
||||
|
||||
/// <summary>
|
||||
/// Do action for all parents
|
||||
/// </summary>
|
||||
private void DoForParents<T>(Action<T> action) where T : IEventSystemHandler
|
||||
{
|
||||
Transform parent = transform.parent;
|
||||
while (parent != null)
|
||||
{
|
||||
foreach (var component in parent.GetComponents<Component>())
|
||||
{
|
||||
if (component is T)
|
||||
action((T)(IEventSystemHandler)component);
|
||||
}
|
||||
parent = parent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Always route initialize potential drag event to parents
|
||||
/// </summary>
|
||||
public override void OnInitializePotentialDrag(PointerEventData eventData)
|
||||
{
|
||||
DoForParents<IInitializePotentialDragHandler>((parent) => { parent.OnInitializePotentialDrag(eventData); });
|
||||
base.OnInitializePotentialDrag(eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drag event
|
||||
/// </summary>
|
||||
public override void OnDrag(UnityEngine.EventSystems.PointerEventData eventData)
|
||||
{
|
||||
if (routeToParent)
|
||||
DoForParents<IDragHandler>((parent) => { parent.OnDrag(eventData); });
|
||||
else
|
||||
base.OnDrag(eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begin drag event
|
||||
/// </summary>
|
||||
public override void OnBeginDrag(UnityEngine.EventSystems.PointerEventData eventData)
|
||||
{
|
||||
if (!horizontal && Math.Abs(eventData.delta.x) > Math.Abs(eventData.delta.y))
|
||||
routeToParent = true;
|
||||
else if (!vertical && Math.Abs(eventData.delta.x) < Math.Abs(eventData.delta.y))
|
||||
routeToParent = true;
|
||||
else
|
||||
routeToParent = false;
|
||||
|
||||
if (routeToParent)
|
||||
DoForParents<IBeginDragHandler>((parent) => { parent.OnBeginDrag(eventData); });
|
||||
else
|
||||
base.OnBeginDrag(eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// End drag event
|
||||
/// </summary>
|
||||
public override void OnEndDrag(UnityEngine.EventSystems.PointerEventData eventData)
|
||||
{
|
||||
if (routeToParent)
|
||||
DoForParents<IEndDragHandler>((parent) => { parent.OnEndDrag(eventData); });
|
||||
else
|
||||
base.OnEndDrag(eventData);
|
||||
routeToParent = false;
|
||||
}
|
||||
|
||||
public override void OnScroll(PointerEventData eventData)
|
||||
{
|
||||
if (!horizontal && Math.Abs(eventData.scrollDelta.x) > Math.Abs(eventData.scrollDelta.y))
|
||||
{
|
||||
routeToParent = true;
|
||||
}
|
||||
else if (!vertical && Math.Abs(eventData.scrollDelta.x) < Math.Abs(eventData.scrollDelta.y))
|
||||
{
|
||||
routeToParent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
routeToParent = false;
|
||||
}
|
||||
|
||||
if (routeToParent)
|
||||
DoForParents<IScrollHandler>((parent) => {
|
||||
parent.OnScroll(eventData);
|
||||
});
|
||||
else
|
||||
base.OnScroll(eventData);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a7b69ea2282ad240824a4bce7a65a46
|
||||
timeCreated: 1440844492
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,17 @@
|
||||
/// Credit Feaver1968
|
||||
/// Sourced from - http://forum.unity3d.com/threads/scroll-to-the-bottom-of-a-scrollrect-in-code.310919/
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public static class ScrollRectExtensions
|
||||
{
|
||||
public static void ScrollToTop(this ScrollRect scrollRect)
|
||||
{
|
||||
scrollRect.normalizedPosition = new Vector2(0, 1);
|
||||
}
|
||||
public static void ScrollToBottom(this ScrollRect scrollRect)
|
||||
{
|
||||
scrollRect.normalizedPosition = new Vector2(0, 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9abaa5d90896b4d4a937574b6b3878ab
|
||||
timeCreated: 1440845965
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,34 @@
|
||||
/// Credit Martin Sharkbomb
|
||||
/// Sourced from - http://www.sharkbombs.com/2015/08/26/unity-ui-scrollrect-tools/
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(ScrollRect))]
|
||||
[AddComponentMenu("UI/Extensions/ScrollRectLinker")]
|
||||
public class ScrollRectLinker : MonoBehaviour
|
||||
{
|
||||
|
||||
public bool clamp = true;
|
||||
|
||||
[SerializeField]
|
||||
ScrollRect controllingScrollRect = null;
|
||||
ScrollRect scrollRect = null;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
scrollRect = GetComponent<ScrollRect>();
|
||||
if (controllingScrollRect != null)
|
||||
controllingScrollRect.onValueChanged.AddListener(MirrorPos);
|
||||
}
|
||||
|
||||
void MirrorPos(Vector2 scrollPos)
|
||||
{
|
||||
|
||||
if (clamp)
|
||||
scrollRect.normalizedPosition = new Vector2(Mathf.Clamp01(scrollPos.x), Mathf.Clamp01(scrollPos.y));
|
||||
else
|
||||
scrollRect.normalizedPosition = scrollPos;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f1f9a7e297738d47b8c6286a737406f
|
||||
timeCreated: 1440840782
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,141 @@
|
||||
/// Credit Martin Sharkbomb
|
||||
/// Sourced from - http://www.sharkbombs.com/2015/08/26/unity-ui-scrollrect-tools/
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(ScrollRect))]
|
||||
[AddComponentMenu("UI/Extensions/ScrollRectTweener")]
|
||||
public class ScrollRectTweener : MonoBehaviour, IDragHandler
|
||||
{
|
||||
|
||||
ScrollRect scrollRect;
|
||||
Vector2 startPos;
|
||||
Vector2 targetPos;
|
||||
|
||||
bool wasHorizontal;
|
||||
bool wasVertical;
|
||||
|
||||
public float moveSpeed = 5000f;
|
||||
public bool disableDragWhileTweening = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
scrollRect = GetComponent<ScrollRect>();
|
||||
wasHorizontal = scrollRect.horizontal;
|
||||
wasVertical = scrollRect.vertical;
|
||||
}
|
||||
|
||||
public void ScrollHorizontal(float normalizedX)
|
||||
{
|
||||
Scroll(new Vector2(normalizedX, scrollRect.verticalNormalizedPosition));
|
||||
}
|
||||
|
||||
public void ScrollHorizontal(float normalizedX, float duration)
|
||||
{
|
||||
Scroll(new Vector2(normalizedX, scrollRect.verticalNormalizedPosition), duration);
|
||||
}
|
||||
|
||||
public void ScrollVertical(float normalizedY)
|
||||
{
|
||||
Scroll(new Vector2(scrollRect.horizontalNormalizedPosition, normalizedY));
|
||||
}
|
||||
|
||||
public void ScrollVertical(float normalizedY, float duration)
|
||||
{
|
||||
Scroll(new Vector2(scrollRect.horizontalNormalizedPosition, normalizedY), duration);
|
||||
}
|
||||
|
||||
public void Scroll(Vector2 normalizedPos)
|
||||
{
|
||||
Scroll(normalizedPos, GetScrollDuration(normalizedPos));
|
||||
}
|
||||
|
||||
float GetScrollDuration(Vector2 normalizedPos)
|
||||
{
|
||||
Vector2 currentPos = GetCurrentPos();
|
||||
return Vector2.Distance(DeNormalize(currentPos), DeNormalize(normalizedPos)) / moveSpeed;
|
||||
}
|
||||
|
||||
Vector2 DeNormalize(Vector2 normalizedPos)
|
||||
{
|
||||
return new Vector2(normalizedPos.x * scrollRect.content.rect.width, normalizedPos.y * scrollRect.content.rect.height);
|
||||
}
|
||||
|
||||
Vector2 GetCurrentPos()
|
||||
{
|
||||
return new Vector2(scrollRect.horizontalNormalizedPosition, scrollRect.verticalNormalizedPosition);
|
||||
}
|
||||
|
||||
public void Scroll(Vector2 normalizedPos, float duration)
|
||||
{
|
||||
startPos = GetCurrentPos();
|
||||
targetPos = normalizedPos;
|
||||
|
||||
if (disableDragWhileTweening)
|
||||
LockScrollability();
|
||||
|
||||
StopAllCoroutines();
|
||||
StartCoroutine(DoMove(duration));
|
||||
}
|
||||
|
||||
IEnumerator DoMove(float duration)
|
||||
{
|
||||
|
||||
// Abort if movement would be too short
|
||||
if (duration < 0.05f)
|
||||
yield break;
|
||||
|
||||
Vector2 posOffset = targetPos - startPos;
|
||||
|
||||
float currentTime = 0f;
|
||||
while (currentTime < duration)
|
||||
{
|
||||
currentTime += Time.deltaTime;
|
||||
scrollRect.normalizedPosition = EaseVector(currentTime, startPos, posOffset, duration);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
scrollRect.normalizedPosition = targetPos;
|
||||
|
||||
if (disableDragWhileTweening)
|
||||
RestoreScrollability();
|
||||
}
|
||||
|
||||
public Vector2 EaseVector(float currentTime, Vector2 startValue, Vector2 changeInValue, float duration)
|
||||
{
|
||||
return new Vector2(
|
||||
changeInValue.x * Mathf.Sin(currentTime / duration * (Mathf.PI / 2)) + startValue.x,
|
||||
changeInValue.y * Mathf.Sin(currentTime / duration * (Mathf.PI / 2)) + startValue.y
|
||||
);
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!disableDragWhileTweening)
|
||||
StopScroll();
|
||||
}
|
||||
|
||||
void StopScroll()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
if (disableDragWhileTweening)
|
||||
RestoreScrollability();
|
||||
}
|
||||
|
||||
void LockScrollability()
|
||||
{
|
||||
scrollRect.horizontal = false;
|
||||
scrollRect.vertical = false;
|
||||
}
|
||||
|
||||
void RestoreScrollability()
|
||||
{
|
||||
scrollRect.horizontal = wasHorizontal;
|
||||
scrollRect.vertical = wasVertical;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37838caa3fcff7f46a5e1418b35173c2
|
||||
timeCreated: 1440840781
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,93 @@
|
||||
///Credit Tomek S
|
||||
///Sourced from - https://pastebin.com/NXYu37jC
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/Selectable Scalar")]
|
||||
[RequireComponent(typeof(Button))]
|
||||
public class SelectableScaler : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
public AnimationCurve animCurve;
|
||||
[Tooltip("Animation speed multiplier")]
|
||||
public float speed = 1;
|
||||
private Vector3 initScale;
|
||||
public Transform target;
|
||||
|
||||
Selectable selectable;
|
||||
public Selectable Target
|
||||
{
|
||||
get
|
||||
{
|
||||
if (selectable == null)
|
||||
selectable = GetComponent<Selectable>();
|
||||
|
||||
return selectable;
|
||||
}
|
||||
}
|
||||
// Use this for initialization
|
||||
void Awake()
|
||||
{
|
||||
if (target == null)
|
||||
target = transform;
|
||||
|
||||
initScale = target.localScale;
|
||||
}
|
||||
void OnEnable()
|
||||
{
|
||||
target.localScale = initScale;
|
||||
}
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (Target != null && !Target.interactable)
|
||||
return;
|
||||
|
||||
StopCoroutine("ScaleOUT");
|
||||
StartCoroutine("ScaleIN");
|
||||
}
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
if (Target != null && !Target.interactable)
|
||||
return;
|
||||
|
||||
StopCoroutine("ScaleIN");
|
||||
StartCoroutine("ScaleOUT");
|
||||
}
|
||||
|
||||
IEnumerator ScaleIN()
|
||||
{
|
||||
if (animCurve.keys.Length > 0)
|
||||
{
|
||||
target.localScale = initScale;
|
||||
float t = 0;
|
||||
float maxT = animCurve.keys[animCurve.length - 1].time;
|
||||
|
||||
while (t < maxT)
|
||||
{
|
||||
t += speed * Time.unscaledDeltaTime;
|
||||
target.localScale = Vector3.one * animCurve.Evaluate(t);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
IEnumerator ScaleOUT()
|
||||
{
|
||||
if (animCurve.keys.Length > 0)
|
||||
{
|
||||
//target.localScale = initScale;
|
||||
float t = 0;
|
||||
float maxT = animCurve.keys[animCurve.length - 1].time;
|
||||
|
||||
while (t < maxT)
|
||||
{
|
||||
t += speed * Time.unscaledDeltaTime;
|
||||
target.localScale = Vector3.one * animCurve.Evaluate(maxT - t);
|
||||
yield return null;
|
||||
}
|
||||
transform.localScale = initScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65fce2c84ce1eff4383c094d715a7e1b
|
||||
timeCreated: 1492258094
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,36 @@
|
||||
/// <summary>
|
||||
/// Tool script taken from the UI source as it's set to Internal for some reason. So to use in the extensions project it is needed here also.
|
||||
/// </summary>
|
||||
///
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
internal static class SetPropertyUtility
|
||||
{
|
||||
public static bool SetColor(ref Color currentValue, Color newValue)
|
||||
{
|
||||
if (currentValue.r == newValue.r && currentValue.g == newValue.g && currentValue.b == newValue.b && currentValue.a == newValue.a)
|
||||
return false;
|
||||
|
||||
currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool SetStruct<T>(ref T currentValue, T newValue) where T: struct
|
||||
{
|
||||
if (currentValue.Equals(newValue))
|
||||
return false;
|
||||
|
||||
currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool SetClass<T>(ref T currentValue, T newValue) where T: class
|
||||
{
|
||||
if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
|
||||
return false;
|
||||
|
||||
currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d373cce4b1f361a40a126bd74d26ebc9
|
||||
timeCreated: 1440851864
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,27 @@
|
||||
/// Credit SimonDarksideJ
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public static class ShaderLibrary
|
||||
{
|
||||
public static Dictionary<string, Shader> shaderInstances = new Dictionary<string, Shader>();
|
||||
public static Shader[] preLoadedShaders;
|
||||
|
||||
public static Shader GetShaderInstance(string shaderName)
|
||||
{
|
||||
if (shaderInstances.ContainsKey(shaderName))
|
||||
{
|
||||
return shaderInstances[shaderName];
|
||||
}
|
||||
|
||||
var newInstance = Shader.Find(shaderName);
|
||||
if (newInstance != null)
|
||||
{
|
||||
shaderInstances.Add(shaderName, newInstance);
|
||||
}
|
||||
return newInstance;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d4dc4c08600582419712a4f2370c81b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,14 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class TestCompression : MonoBehaviour {
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 585e75d4a56389b4690b3506f37751bc
|
||||
timeCreated: 1464883584
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,65 @@
|
||||
/// Credit Simon (simonDarksideJ) Jackson
|
||||
/// Sourced from - My head
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public static class UIExtensionMethods
|
||||
{
|
||||
public static Canvas GetParentCanvas(this RectTransform rt)
|
||||
{
|
||||
RectTransform parent = rt;
|
||||
Canvas parentCanvas = rt.GetComponent<Canvas>();
|
||||
|
||||
int SearchIndex = 0;
|
||||
while (parentCanvas == null || SearchIndex > 50)
|
||||
{
|
||||
parentCanvas = rt.GetComponentInParent<Canvas>();
|
||||
if (parentCanvas == null)
|
||||
{
|
||||
parent = parent.parent.GetComponent<RectTransform>();
|
||||
SearchIndex++;
|
||||
}
|
||||
}
|
||||
return parentCanvas;
|
||||
}
|
||||
|
||||
public static Vector2 TransformInputBasedOnCanvasType(this Vector2 input, Canvas canvas)
|
||||
{
|
||||
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
return canvas.GetEventCamera().ScreenToWorldPoint(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector3 TransformInputBasedOnCanvasType(this Vector2 input, RectTransform rt)
|
||||
{
|
||||
var canvas = rt.GetParentCanvas();
|
||||
if (input == Vector2.zero || canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Needs work :S
|
||||
Vector2 movePos;
|
||||
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
rt,
|
||||
input, canvas.GetEventCamera(),
|
||||
out movePos);
|
||||
|
||||
Vector3 output = canvas.transform.TransformPoint(movePos);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
public static Camera GetEventCamera(this Canvas input)
|
||||
{
|
||||
return input.worldCamera == null ? Camera.main : input.worldCamera;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08fd87e2db0639a4caf7a053f227a470
|
||||
timeCreated: 1498086098
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,296 @@
|
||||
/// Credit SimonDarksideJ
|
||||
/// Sourced from: https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/348/menu-manager-does-not-work-with-the-new
|
||||
|
||||
#if UNITY_2019_1_OR_NEWER && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
#define NEW_INPUT_SYSTEM
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if NEW_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
#endif
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public static class UIExtensionsInputManager
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
private static bool[] mouseButtons = new bool[3] { false, false, false };
|
||||
private static Dictionary<KeyCode, bool> keys = new Dictionary<KeyCode, bool>();
|
||||
private static Dictionary<String, bool> buttons = new Dictionary<String, bool>();
|
||||
#endif
|
||||
|
||||
public static bool GetMouseButton(int button)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
if (Mouse.current == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Mouse.current.leftButton.isPressed;
|
||||
#else
|
||||
return Input.GetMouseButton(button);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetMouseButtonDown(int button)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
if (Mouse.current == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Mouse.current.leftButton.isPressed)
|
||||
{
|
||||
if (!mouseButtons[button])
|
||||
{
|
||||
mouseButtons[button] = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return Input.GetMouseButtonDown(button);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetMouseButtonUp(int button)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
if (Mouse.current == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mouseButtons[button] && !Mouse.current.leftButton.isPressed)
|
||||
{
|
||||
mouseButtons[button] = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return Input.GetMouseButtonUp(button);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetButton(string input)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
ButtonControl buttonPressed = GetButtonControlFromString(input);
|
||||
|
||||
if (!buttons.ContainsKey(input))
|
||||
{
|
||||
buttons.Add(input, false);
|
||||
}
|
||||
|
||||
return buttonPressed != null ? buttonPressed.isPressed : false;
|
||||
#else
|
||||
return Input.GetButton(input);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NEW_INPUT_SYSTEM
|
||||
private static ButtonControl GetButtonControlFromString(string input)
|
||||
{
|
||||
if (Gamepad.current == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (input)
|
||||
{
|
||||
case "Submit":
|
||||
return Gamepad.current.aButton;
|
||||
case "Cancel":
|
||||
return Gamepad.current.bButton;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool GetButtonDown(string input)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
ButtonControl buttonPressed = GetButtonControlFromString(input);
|
||||
|
||||
if (buttonPressed.isPressed)
|
||||
{
|
||||
if (!buttons.ContainsKey(input))
|
||||
{
|
||||
buttons.Add(input, false);
|
||||
}
|
||||
|
||||
if (!buttons[input])
|
||||
{
|
||||
buttons[input] = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buttons[input] = false;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return Input.GetButtonDown(input);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetButtonUp(string input)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
ButtonControl buttonPressed = GetButtonControlFromString(input);
|
||||
|
||||
if (buttons[input] && !buttonPressed.isPressed)
|
||||
{
|
||||
buttons[input] = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return Input.GetButtonUp(input);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetKey(KeyCode key)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
KeyControl keyPressed = GetKeyControlFromKeyCode(key);
|
||||
if (!keys.ContainsKey(key))
|
||||
{
|
||||
keys.Add(key, false);
|
||||
}
|
||||
|
||||
return keyPressed != null ? keyPressed.isPressed : false;
|
||||
#else
|
||||
return Input.GetKey(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NEW_INPUT_SYSTEM
|
||||
private static KeyControl GetKeyControlFromKeyCode(KeyCode key)
|
||||
{
|
||||
if (Keyboard.current == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case KeyCode.Escape:
|
||||
return Keyboard.current.escapeKey;
|
||||
case KeyCode.KeypadEnter:
|
||||
return Keyboard.current.numpadEnterKey;
|
||||
case KeyCode.UpArrow:
|
||||
return Keyboard.current.upArrowKey;
|
||||
case KeyCode.DownArrow:
|
||||
return Keyboard.current.downArrowKey;
|
||||
case KeyCode.RightArrow:
|
||||
return Keyboard.current.rightArrowKey;
|
||||
case KeyCode.LeftArrow:
|
||||
return Keyboard.current.leftArrowKey;
|
||||
case KeyCode.LeftShift:
|
||||
return Keyboard.current.leftShiftKey;
|
||||
case KeyCode.Tab:
|
||||
return Keyboard.current.tabKey;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool GetKeyDown(KeyCode key)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
KeyControl keyPressed = GetKeyControlFromKeyCode(key);
|
||||
if (keyPressed.isPressed)
|
||||
{
|
||||
if (!keys.ContainsKey(key))
|
||||
{
|
||||
keys.Add(key, false);
|
||||
}
|
||||
|
||||
if (!keys[key])
|
||||
{
|
||||
keys[key] = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
keys[key] = false;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return Input.GetKeyDown(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetKeyUp(KeyCode key)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
KeyControl keyPressed = GetKeyControlFromKeyCode(key);
|
||||
if (keys[key] && !keyPressed.isPressed)
|
||||
{
|
||||
keys[key] = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return Input.GetKeyUp(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static float GetAxisRaw(string axis)
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
if (Gamepad.current == null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case "Horizontal":
|
||||
return Gamepad.current.leftStick.x.ReadValue();
|
||||
case "Vertical":
|
||||
return Gamepad.current.leftStick.y.ReadValue();
|
||||
|
||||
}
|
||||
return 0f;
|
||||
#else
|
||||
return Input.GetAxisRaw(axis);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Vector3 MousePosition
|
||||
{
|
||||
get
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
return Mouse.current.position.ReadValue();
|
||||
#else
|
||||
return Input.mousePosition;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector3 MouseScrollDelta
|
||||
{
|
||||
get
|
||||
{
|
||||
#if NEW_INPUT_SYSTEM
|
||||
return Mouse.current.position.ReadValue();
|
||||
#else
|
||||
return Input.mouseScrollDelta;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de7e73fc10fb95143a19dbc76c2595a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,119 @@
|
||||
/// Credit SimonDarksideJ
|
||||
/// Sourced from - Issue Proposal #153
|
||||
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/UI Highlightable Extension")]
|
||||
[RequireComponent(typeof(RectTransform), typeof(Graphic))]
|
||||
public class UIHighlightable : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
private Graphic m_Graphic;
|
||||
private bool m_Highlighted;
|
||||
private bool m_Pressed;
|
||||
|
||||
[System.Serializable]
|
||||
public class InteractableChangedEvent : Events.UnityEvent<bool> { }
|
||||
|
||||
[SerializeField][Tooltip("Can this panel be interacted with or is it disabled? (does not affect child components)")]
|
||||
private bool m_Interactable = true;
|
||||
[SerializeField][Tooltip("Does the panel remain in the pressed state when clicked? (default false)")]
|
||||
private bool m_ClickToHold;
|
||||
|
||||
public bool Interactable
|
||||
{
|
||||
get { return m_Interactable; }
|
||||
set
|
||||
{
|
||||
m_Interactable = value;
|
||||
HighlightInteractable(m_Graphic);
|
||||
OnInteractableChanged.Invoke(m_Interactable);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ClickToHold
|
||||
{
|
||||
get { return m_ClickToHold; }
|
||||
set { m_ClickToHold = value; }
|
||||
}
|
||||
|
||||
[Tooltip("The default color for the panel")]
|
||||
public Color NormalColor = Color.grey;
|
||||
[Tooltip("The color for the panel when a mouse is over it or it is in focus")]
|
||||
public Color HighlightedColor = Color.yellow;
|
||||
[Tooltip("The color for the panel when it is clicked/held")]
|
||||
public Color PressedColor = Color.green;
|
||||
[Tooltip("The color for the panel when it is not interactable (see Interactable)")]
|
||||
public Color DisabledColor = Color.gray;
|
||||
|
||||
[Tooltip("Event for when the panel is enabled / disabled, to enable disabling / enabling of child or other gameobjects")]
|
||||
public InteractableChangedEvent OnInteractableChanged;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
m_Graphic = GetComponent<Graphic>();
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
if (Interactable && !m_Pressed)
|
||||
{
|
||||
m_Highlighted = true;
|
||||
m_Graphic.color = HighlightedColor;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
if (Interactable && !m_Pressed)
|
||||
{
|
||||
m_Highlighted = false;
|
||||
m_Graphic.color = NormalColor;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (Interactable)
|
||||
{
|
||||
m_Graphic.color = PressedColor;
|
||||
if (ClickToHold)
|
||||
{
|
||||
m_Pressed = !m_Pressed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
if(!m_Pressed) HighlightInteractable(m_Graphic);
|
||||
}
|
||||
|
||||
private void HighlightInteractable(Graphic graphic)
|
||||
{
|
||||
if (m_Interactable)
|
||||
{
|
||||
if (m_Highlighted)
|
||||
{
|
||||
graphic.color = HighlightedColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
graphic.color = NormalColor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
graphic.color = DisabledColor;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
HighlightInteractable(GetComponent<Graphic>());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d51a356e057c54d48abe97aa2cee2291
|
||||
timeCreated: 1499808539
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,86 @@
|
||||
/// Credit Alastair Aitchison
|
||||
/// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/123/uilinerenderer-issues-with-specifying
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/UI Line Connector")]
|
||||
[RequireComponent(typeof(UILineRenderer))]
|
||||
[ExecuteInEditMode]
|
||||
public class UILineConnector : MonoBehaviour
|
||||
{
|
||||
|
||||
// The elements between which line segments should be drawn
|
||||
public RectTransform[] transforms;
|
||||
private Vector3[] previousPositions;
|
||||
private RectTransform canvas;
|
||||
private RectTransform rt;
|
||||
private UILineRenderer lr;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
canvas = GetComponentInParent<RectTransform>().GetParentCanvas().GetComponent<RectTransform>();
|
||||
rt = GetComponent<RectTransform>();
|
||||
lr = GetComponent<UILineRenderer>();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if (transforms == null || transforms.Length < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Performance check to only redraw when the child transforms move
|
||||
if (previousPositions != null && previousPositions.Length == transforms.Length)
|
||||
{
|
||||
bool updateLine = false;
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
if (!updateLine && previousPositions[i] != transforms[i].position)
|
||||
{
|
||||
updateLine = true;
|
||||
}
|
||||
}
|
||||
if (!updateLine) return;
|
||||
}
|
||||
|
||||
// Get the pivot points
|
||||
Vector2 thisPivot = rt.pivot;
|
||||
Vector2 canvasPivot = canvas.pivot;
|
||||
|
||||
// Set up some arrays of coordinates in various reference systems
|
||||
Vector3[] worldSpaces = new Vector3[transforms.Length];
|
||||
Vector3[] canvasSpaces = new Vector3[transforms.Length];
|
||||
Vector2[] points = new Vector2[transforms.Length];
|
||||
|
||||
// First, convert the pivot to worldspace
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
worldSpaces[i] = transforms[i].TransformPoint(thisPivot);
|
||||
}
|
||||
|
||||
// Then, convert to canvas space
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
canvasSpaces[i] = canvas.InverseTransformPoint(worldSpaces[i]);
|
||||
}
|
||||
|
||||
// Calculate delta from the canvas pivot point
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
points[i] = new Vector2(canvasSpaces[i].x, canvasSpaces[i].y);
|
||||
}
|
||||
|
||||
// And assign the converted points to the line renderer
|
||||
lr.Points = points;
|
||||
lr.RelativeSize = false;
|
||||
lr.drivenExternally = true;
|
||||
|
||||
previousPositions = new Vector3[transforms.Length];
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
previousPositions[i] = transforms[i].position;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b52ee3a4491f3742bb35fa3eec798d3
|
||||
timeCreated: 1498085244
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,303 @@
|
||||
/// Credit zero3growlithe
|
||||
/// sourced from: http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-2011648
|
||||
|
||||
/*USAGE:
|
||||
Simply place the script on the ScrollRect that contains the selectable children you will be scrolling
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(ScrollRect))]
|
||||
[AddComponentMenu("UI/Extensions/UIScrollToSelection")]
|
||||
public class UIScrollToSelection : MonoBehaviour
|
||||
{
|
||||
#region MEMBERS
|
||||
|
||||
[Header("[ References ]")]
|
||||
[SerializeField, Tooltip("View (boundaries/mask) rect transform. Used to check if automatic scroll to selection is required.")]
|
||||
private RectTransform viewportRectTransform;
|
||||
[SerializeField, Tooltip("Scroll rect used to reach selected element.")]
|
||||
private ScrollRect targetScrollRect;
|
||||
|
||||
[Header("[ Scrolling ]")]
|
||||
[SerializeField, Tooltip("Allow automatic scrolling only on these axes.")]
|
||||
private Axis scrollAxes = Axis.ANY;
|
||||
[SerializeField, Tooltip("MOVE_TOWARDS: stiff movement, LERP: smoothed out movement")]
|
||||
private ScrollMethod usedScrollMethod = ScrollMethod.MOVE_TOWARDS;
|
||||
[SerializeField]
|
||||
private float scrollSpeed = 50;
|
||||
|
||||
[Space(5)]
|
||||
[SerializeField, Tooltip("Scroll speed used when element to select is out of \"JumpOffsetThreshold\" range")]
|
||||
private float endOfListJumpScrollSpeed = 150;
|
||||
[SerializeField, Range(0, 1), Tooltip("If next element to scroll to is located over this screen percentage, use \"EndOfListJumpScrollSpeed\" to reach this element faster.")]
|
||||
private float jumpOffsetThreshold = 1;
|
||||
|
||||
[Header("[ Input ]")]
|
||||
[SerializeField]
|
||||
private MouseButton cancelScrollMouseButtons = MouseButton.ANY;
|
||||
[SerializeField]
|
||||
private KeyCode[] cancelScrollKeys = new KeyCode[0];
|
||||
|
||||
// INTERNAL - MEMBERS ONLY
|
||||
private Vector3[] viewRectCorners = new Vector3[4];
|
||||
private Vector3[] selectedElementCorners = new Vector3[4];
|
||||
|
||||
#endregion
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
// REFERENCES
|
||||
public RectTransform ViewRectTransform
|
||||
{
|
||||
get { return viewportRectTransform; }
|
||||
set { viewportRectTransform = value; }
|
||||
}
|
||||
public ScrollRect TargetScrollRect
|
||||
{
|
||||
get { return targetScrollRect; }
|
||||
set { targetScrollRect = value; }
|
||||
}
|
||||
|
||||
// SCROLLING
|
||||
public Axis ScrollAxes => scrollAxes;
|
||||
public ScrollMethod UsedScrollMethod => usedScrollMethod;
|
||||
public float ScrollSpeed => scrollSpeed;
|
||||
public float EndOfListJumpScrollSpeed => endOfListJumpScrollSpeed;
|
||||
public float JumpOffsetThreshold => jumpOffsetThreshold;
|
||||
|
||||
// INPUT
|
||||
public MouseButton CancelScrollMouseButtons => cancelScrollMouseButtons;
|
||||
public KeyCode[] CancelScrollKeys => cancelScrollKeys;
|
||||
|
||||
// VARIABLES
|
||||
private RectTransform scrollRectContentTransform;
|
||||
private GameObject lastCheckedSelection;
|
||||
|
||||
// COROUTINES
|
||||
private Coroutine animationCoroutine;
|
||||
|
||||
#endregion
|
||||
|
||||
#region FUNCTIONS
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
ValidateReferences();
|
||||
}
|
||||
|
||||
protected void LateUpdate()
|
||||
{
|
||||
TryToScrollToSelection();
|
||||
}
|
||||
|
||||
protected void Reset()
|
||||
{
|
||||
TargetScrollRect = gameObject.GetComponentInParent<ScrollRect>() ?? gameObject.GetComponentInChildren<ScrollRect>();
|
||||
ViewRectTransform = gameObject.GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
private void ValidateReferences()
|
||||
{
|
||||
if (!targetScrollRect)
|
||||
{
|
||||
targetScrollRect = GetComponent<ScrollRect>();
|
||||
}
|
||||
|
||||
if (!targetScrollRect)
|
||||
{
|
||||
Debug.LogError("[UIScrollToSelection] No ScrollRect found. Either attach this script to a ScrollRect or assign on in the 'Target Scroll Rect' property");
|
||||
gameObject.SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ViewRectTransform == null)
|
||||
{
|
||||
ViewRectTransform = TargetScrollRect.GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
if (TargetScrollRect != null)
|
||||
{
|
||||
scrollRectContentTransform = TargetScrollRect.content;
|
||||
}
|
||||
|
||||
if (EventSystem.current == null)
|
||||
{
|
||||
Debug.LogError("[UIScrollToSelection] Unity UI EventSystem not found. It is required to check current selected object.");
|
||||
gameObject.SetActive(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void TryToScrollToSelection()
|
||||
{
|
||||
// update references if selection changed
|
||||
GameObject selection = EventSystem.current.currentSelectedGameObject;
|
||||
|
||||
if (selection == null || selection.activeInHierarchy == false || selection == lastCheckedSelection ||
|
||||
selection.transform.IsChildOf(transform) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RectTransform selectionRect = selection.GetComponent<RectTransform>();
|
||||
|
||||
ViewRectTransform.GetWorldCorners(viewRectCorners);
|
||||
selectionRect.GetWorldCorners(selectedElementCorners);
|
||||
|
||||
ScrollToSelection(selection);
|
||||
|
||||
lastCheckedSelection = selection;
|
||||
}
|
||||
|
||||
private void ScrollToSelection(GameObject selection)
|
||||
{
|
||||
// initial check if we can scroll at all
|
||||
if (selection == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this is just to make names shorter a bit
|
||||
Vector3[] corners = viewRectCorners;
|
||||
Vector3[] selectionCorners = selectedElementCorners;
|
||||
|
||||
// calculate scroll offset
|
||||
Vector2 offsetToSelection = Vector2.zero;
|
||||
|
||||
offsetToSelection.x =
|
||||
(selectionCorners[0].x < corners[0].x ? selectionCorners[0].x - corners[0].x : 0) +
|
||||
(selectionCorners[2].x > corners[2].x ? selectionCorners[2].x - corners[2].x : 0);
|
||||
offsetToSelection.y =
|
||||
(selectionCorners[0].y < corners[0].y ? selectionCorners[0].y - corners[0].y : 0) +
|
||||
(selectionCorners[1].y > corners[1].y ? selectionCorners[1].y - corners[1].y : 0);
|
||||
|
||||
// calculate final scroll speed
|
||||
float finalScrollSpeed = ScrollSpeed;
|
||||
|
||||
if (Math.Abs(offsetToSelection.x) / Screen.width >= JumpOffsetThreshold || Math.Abs(offsetToSelection.y) / Screen.height >= JumpOffsetThreshold)
|
||||
{
|
||||
finalScrollSpeed = EndOfListJumpScrollSpeed;
|
||||
}
|
||||
|
||||
// initiate animation coroutine
|
||||
Vector2 targetPosition = (Vector2)scrollRectContentTransform.localPosition - offsetToSelection;
|
||||
|
||||
if (animationCoroutine != null)
|
||||
{
|
||||
StopCoroutine(animationCoroutine);
|
||||
}
|
||||
|
||||
animationCoroutine = StartCoroutine(ScrollToPosition(targetPosition, finalScrollSpeed));
|
||||
}
|
||||
|
||||
private IEnumerator ScrollToPosition(Vector2 targetPosition, float speed)
|
||||
{
|
||||
Vector3 startPosition = scrollRectContentTransform.localPosition;
|
||||
|
||||
// cancel movement on axes not specified in ScrollAxes mask
|
||||
targetPosition.x = ((ScrollAxes | Axis.HORIZONTAL) == ScrollAxes) ? targetPosition.x : startPosition.x;
|
||||
targetPosition.y = ((ScrollAxes | Axis.VERTICAL) == ScrollAxes) ? targetPosition.y : startPosition.y;
|
||||
|
||||
// move to target position
|
||||
Vector2 currentPosition2D = startPosition;
|
||||
float horizontalSpeed = (Screen.width / Screen.dpi) * speed;
|
||||
float verticalSpeed = (Screen.height / Screen.dpi) * speed;
|
||||
|
||||
while (currentPosition2D != targetPosition && CheckIfScrollInterrupted() == false)
|
||||
{
|
||||
currentPosition2D.x = MoveTowardsValue(currentPosition2D.x, targetPosition.x, horizontalSpeed, UsedScrollMethod);
|
||||
currentPosition2D.y = MoveTowardsValue(currentPosition2D.y, targetPosition.y, verticalSpeed, UsedScrollMethod);
|
||||
|
||||
scrollRectContentTransform.localPosition = currentPosition2D;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
scrollRectContentTransform.localPosition = currentPosition2D;
|
||||
}
|
||||
|
||||
private bool CheckIfScrollInterrupted()
|
||||
{
|
||||
bool mouseButtonClicked = false;
|
||||
|
||||
// check mouse buttons
|
||||
switch (CancelScrollMouseButtons)
|
||||
{
|
||||
case MouseButton.LEFT:
|
||||
mouseButtonClicked |= Input.GetMouseButtonDown(0);
|
||||
break;
|
||||
case MouseButton.RIGHT:
|
||||
mouseButtonClicked |= Input.GetMouseButtonDown(1);
|
||||
break;
|
||||
case MouseButton.MIDDLE:
|
||||
mouseButtonClicked |= Input.GetMouseButtonDown(2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mouseButtonClicked == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// check keyboard buttons
|
||||
for (int i = 0; i < CancelScrollKeys.Length; i++)
|
||||
{
|
||||
if (Input.GetKeyDown(CancelScrollKeys[i]) == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private float MoveTowardsValue(float from, float to, float delta, ScrollMethod method)
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case ScrollMethod.MOVE_TOWARDS:
|
||||
return Mathf.MoveTowards(from, to, delta * Time.unscaledDeltaTime);
|
||||
case ScrollMethod.LERP:
|
||||
return Mathf.Lerp(from, to, delta * Time.unscaledDeltaTime);
|
||||
default:
|
||||
return from;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CLASS_ENUMS
|
||||
|
||||
[Flags]
|
||||
public enum Axis
|
||||
{
|
||||
NONE = 0x00000000,
|
||||
HORIZONTAL = 0x00000001,
|
||||
VERTICAL = 0x00000010,
|
||||
ANY = 0x00000011
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MouseButton
|
||||
{
|
||||
NONE = 0x00000000,
|
||||
LEFT = 0x00000001,
|
||||
RIGHT = 0x00000010,
|
||||
MIDDLE = 0x00000100,
|
||||
ANY = 0x00000111
|
||||
}
|
||||
|
||||
public enum ScrollMethod
|
||||
{
|
||||
MOVE_TOWARDS,
|
||||
LERP
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b35bd2ce6e015bb4f840cf9267dbe421
|
||||
timeCreated: 1438721836
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,123 @@
|
||||
/// Credit zero3growlithe
|
||||
/// sourced from: http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-2011648
|
||||
/// Update by xesenix - based on UIScrollToSelection centers on selected element in scrollrect which can move in XY
|
||||
/// you can restrict movement by locking axis on ScrollRect component
|
||||
|
||||
/*USAGE:
|
||||
Simply place the script on the ScrollRect that contains the selectable children we'll be scrolling to
|
||||
and drag'n'drop the RectTransform of the options "container" that we'll be scrolling.*/
|
||||
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/UI ScrollTo Selection XY")]
|
||||
[RequireComponent(typeof(ScrollRect))]
|
||||
public class UIScrollToSelectionXY : MonoBehaviour
|
||||
{
|
||||
|
||||
#region Variables
|
||||
|
||||
// settings
|
||||
public float scrollSpeed = 10f;
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform layoutListGroup = null;
|
||||
|
||||
// temporary variables
|
||||
private RectTransform targetScrollObject;
|
||||
private bool scrollToSelection = true;
|
||||
|
||||
// references
|
||||
private RectTransform scrollWindow = null;
|
||||
private ScrollRect targetScrollRect = null;
|
||||
#endregion
|
||||
|
||||
// Use this for initialization
|
||||
private void Start()
|
||||
{
|
||||
targetScrollRect = GetComponent<ScrollRect>();
|
||||
scrollWindow = targetScrollRect.GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
private void Update()
|
||||
{
|
||||
ScrollRectToLevelSelection();
|
||||
}
|
||||
|
||||
private void ScrollRectToLevelSelection()
|
||||
{
|
||||
// FIX: if you do not do that here events can have null value
|
||||
var events = EventSystem.current;
|
||||
|
||||
// check main references
|
||||
bool referencesAreIncorrect =
|
||||
(targetScrollRect == null || layoutListGroup == null || scrollWindow == null);
|
||||
if (referencesAreIncorrect == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get calculation references
|
||||
RectTransform selection = events.currentSelectedGameObject != null ?
|
||||
events.currentSelectedGameObject.GetComponent<RectTransform>() :
|
||||
null;
|
||||
|
||||
if (selection != targetScrollObject)
|
||||
{
|
||||
scrollToSelection = true;
|
||||
}
|
||||
|
||||
// check if scrolling is possible
|
||||
bool isScrollDirectionUnknown = (selection == null || scrollToSelection == false);
|
||||
|
||||
if (isScrollDirectionUnknown == true || selection.transform.parent != layoutListGroup.transform)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool finishedX = false, finishedY = false;
|
||||
|
||||
if (targetScrollRect.vertical)
|
||||
{
|
||||
// move the current scroll rect to correct position
|
||||
float selectionPos = -selection.anchoredPosition.y;
|
||||
|
||||
float listPixelAnchor = layoutListGroup.anchoredPosition.y;
|
||||
|
||||
// get the element offset value depending on the cursor move direction
|
||||
float offlimitsValue = 0;
|
||||
|
||||
offlimitsValue = listPixelAnchor - selectionPos;
|
||||
// move the target scroll rect
|
||||
targetScrollRect.verticalNormalizedPosition += (offlimitsValue / layoutListGroup.sizeDelta.y) * Time.deltaTime * scrollSpeed;
|
||||
|
||||
finishedY = Mathf.Abs(offlimitsValue) < 2f;
|
||||
}
|
||||
|
||||
if (targetScrollRect.horizontal)
|
||||
{
|
||||
// move the current scroll rect to correct position
|
||||
float selectionPos = -selection.anchoredPosition.x;
|
||||
|
||||
float listPixelAnchor = layoutListGroup.anchoredPosition.x;
|
||||
|
||||
// get the element offset value depending on the cursor move direction
|
||||
float offlimitsValue = 0;
|
||||
|
||||
offlimitsValue = listPixelAnchor - selectionPos;
|
||||
// move the target scroll rect
|
||||
targetScrollRect.horizontalNormalizedPosition += (offlimitsValue / layoutListGroup.sizeDelta.x) * Time.deltaTime * scrollSpeed;
|
||||
|
||||
finishedX = Mathf.Abs(offlimitsValue) < 2f;
|
||||
}
|
||||
// check if we reached our destination
|
||||
if (finishedX && finishedY) {
|
||||
scrollToSelection = false;
|
||||
}
|
||||
// save last object we were "heading to" to prevent blocking
|
||||
targetScrollObject = selection;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6580683838fcc12479150dd5e76e6b2e
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@ -0,0 +1,119 @@
|
||||
/// Credit AriathTheWise, Sfyne
|
||||
/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-1796783
|
||||
/// Additional disabled - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/issues/47/uiselectableextension-_pressed-bug
|
||||
/// Extended to include a HELD state that continually fires while the button is held down.
|
||||
/// Refactored so it can be added to any button and expose the events in the editor.
|
||||
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// UIButton
|
||||
/// </summary>
|
||||
[AddComponentMenu("UI/Extensions/UI Selectable Extension")]
|
||||
[RequireComponent(typeof(Selectable))]
|
||||
public class UISelectableExtension : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
#region Sub-Classes
|
||||
[System.Serializable]
|
||||
public class UIButtonEvent : UnityEvent<PointerEventData.InputButton> { }
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
[Tooltip("Event that fires when a button is initially pressed down")]
|
||||
public UIButtonEvent OnButtonPress;
|
||||
[Tooltip("Event that fires when a button is released")]
|
||||
public UIButtonEvent OnButtonRelease;
|
||||
[Tooltip("Event that continually fires while a button is held down")]
|
||||
public UIButtonEvent OnButtonHeld;
|
||||
#endregion
|
||||
|
||||
private bool _pressed;
|
||||
private PointerEventData _heldEventData;
|
||||
|
||||
void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
//Can't set the state as it's too locked down.
|
||||
//DoStateTransition(SelectionState.Pressed, false);
|
||||
|
||||
if (OnButtonPress != null)
|
||||
{
|
||||
OnButtonPress.Invoke(eventData.button);
|
||||
}
|
||||
_pressed = true;
|
||||
_heldEventData = eventData;
|
||||
}
|
||||
|
||||
|
||||
void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
//DoStateTransition(SelectionState.Normal, false);
|
||||
|
||||
if (OnButtonRelease != null)
|
||||
{
|
||||
OnButtonRelease.Invoke(eventData.button);
|
||||
}
|
||||
_pressed = false;
|
||||
_heldEventData = null;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!_pressed)
|
||||
return;
|
||||
|
||||
if (OnButtonHeld != null)
|
||||
{
|
||||
OnButtonHeld.Invoke(_heldEventData.button);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test method to verify a control has been clicked
|
||||
/// </summary>
|
||||
public void TestClicked()
|
||||
{
|
||||
#if DEBUG || UNITY_EDITOR
|
||||
Debug.Log("Control Clicked");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test method to verify a control is pressed
|
||||
/// </summary>
|
||||
public void TestPressed()
|
||||
{
|
||||
#if DEBUG || UNITY_EDITOR
|
||||
Debug.Log("Control Pressed");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// est method to verify if a control is released
|
||||
/// </summary>
|
||||
public void TestReleased()
|
||||
{
|
||||
#if DEBUG || UNITY_EDITOR
|
||||
Debug.Log("Control Released");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// est method to verify if a control is being held
|
||||
/// </summary>
|
||||
public void TestHold()
|
||||
{
|
||||
#if DEBUG || UNITY_EDITOR
|
||||
Debug.Log("Control Held");
|
||||
#endif
|
||||
}
|
||||
|
||||
//Fixed UISelectableExtension inactive bug (if gameObject becomes inactive while button is held down it never goes back to _pressed = false)
|
||||
void OnDisable()
|
||||
{
|
||||
_pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bb501adc62c7394fae41ae7a6032eb3
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@ -0,0 +1,218 @@
|
||||
/// Credit Tomasz Schelenz
|
||||
/// Sourced from - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/issues/81/infinite-scrollrect
|
||||
/// Demo - https://www.youtube.com/watch?v=uVTV7Udx78k - configures automatically. - works in both vertical and horizontal (but not both at the same time) - drag and drop - can be initialized by code (in case you populate your scrollview content from code)
|
||||
/// Updated by Febo Zodiaco - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/349/magnticinfinitescroll
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Infinite scroll view with automatic configuration
|
||||
///
|
||||
/// Fields
|
||||
/// - InitByUSer - in case your scrollrect is populated from code, you can explicitly Initialize the infinite scroll after your scroll is ready
|
||||
/// by calling Init() method
|
||||
///
|
||||
/// Notes
|
||||
/// - does not work in both vertical and horizontal orientation at the same time.
|
||||
/// - in order to work it disables layout components and size fitter if present(automatically)
|
||||
///
|
||||
/// </summary>
|
||||
[AddComponentMenu("UI/Extensions/UI Infinite Scroll")]
|
||||
public class UI_InfiniteScroll : MonoBehaviour
|
||||
{
|
||||
//if true user will need to call Init() method manually (in case the contend of the scrollview is generated from code or requires special initialization)
|
||||
[Tooltip("If false, will Init automatically, otherwise you need to call Init() method")]
|
||||
public bool InitByUser = false;
|
||||
protected ScrollRect _scrollRect;
|
||||
private ContentSizeFitter _contentSizeFitter;
|
||||
private VerticalLayoutGroup _verticalLayoutGroup;
|
||||
private HorizontalLayoutGroup _horizontalLayoutGroup;
|
||||
private GridLayoutGroup _gridLayoutGroup;
|
||||
protected bool _isVertical = false;
|
||||
protected bool _isHorizontal = false;
|
||||
private float _disableMarginX = 0;
|
||||
private float _disableMarginY = 0;
|
||||
private bool _hasDisabledGridComponents = false;
|
||||
protected List<RectTransform> items = new List<RectTransform>();
|
||||
private Vector2 _newAnchoredPosition = Vector2.zero;
|
||||
//TO DISABLE FLICKERING OBJECT WHEN SCROLL VIEW IS IDLE IN BETWEEN OBJECTS
|
||||
private float _threshold = 100f;
|
||||
private int _itemCount = 0;
|
||||
private float _recordOffsetX = 0;
|
||||
private float _recordOffsetY = 0;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (!InitByUser)
|
||||
Init();
|
||||
}
|
||||
|
||||
public virtual void SetNewItems(ref List<Transform> newItems)
|
||||
{
|
||||
if (_scrollRect != null)
|
||||
{
|
||||
if (_scrollRect.content == null && newItems == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (items != null)
|
||||
{
|
||||
items.Clear();
|
||||
}
|
||||
|
||||
for (int i = _scrollRect.content.childCount - 1; i >= 0; i--)
|
||||
{
|
||||
Transform child = _scrollRect.content.GetChild(i);
|
||||
child.SetParent(null);
|
||||
GameObject.DestroyImmediate(child.gameObject);
|
||||
}
|
||||
|
||||
foreach (Transform newItem in newItems)
|
||||
{
|
||||
newItem.SetParent(_scrollRect.content);
|
||||
}
|
||||
|
||||
SetItems();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetItems()
|
||||
{
|
||||
for (int i = 0; i < _scrollRect.content.childCount; i++)
|
||||
{
|
||||
items.Add(_scrollRect.content.GetChild(i).GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
_itemCount = _scrollRect.content.childCount;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
if (GetComponent<ScrollRect>() != null)
|
||||
{
|
||||
_scrollRect = GetComponent<ScrollRect>();
|
||||
_scrollRect.onValueChanged.AddListener(OnScroll);
|
||||
_scrollRect.movementType = ScrollRect.MovementType.Unrestricted;
|
||||
|
||||
if (_scrollRect.content.GetComponent<VerticalLayoutGroup>() != null)
|
||||
{
|
||||
_verticalLayoutGroup = _scrollRect.content.GetComponent<VerticalLayoutGroup>();
|
||||
}
|
||||
if (_scrollRect.content.GetComponent<HorizontalLayoutGroup>() != null)
|
||||
{
|
||||
_horizontalLayoutGroup = _scrollRect.content.GetComponent<HorizontalLayoutGroup>();
|
||||
}
|
||||
if (_scrollRect.content.GetComponent<GridLayoutGroup>() != null)
|
||||
{
|
||||
_gridLayoutGroup = _scrollRect.content.GetComponent<GridLayoutGroup>();
|
||||
}
|
||||
if (_scrollRect.content.GetComponent<ContentSizeFitter>() != null)
|
||||
{
|
||||
_contentSizeFitter = _scrollRect.content.GetComponent<ContentSizeFitter>();
|
||||
}
|
||||
|
||||
_isHorizontal = _scrollRect.horizontal;
|
||||
_isVertical = _scrollRect.vertical;
|
||||
|
||||
if (_isHorizontal && _isVertical)
|
||||
{
|
||||
Debug.LogError("UI_InfiniteScroll doesn't support scrolling in both directions, please choose one direction (horizontal or vertical)");
|
||||
}
|
||||
|
||||
SetItems();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("UI_InfiniteScroll => No ScrollRect component found");
|
||||
}
|
||||
}
|
||||
|
||||
void DisableGridComponents()
|
||||
{
|
||||
if (_isVertical)
|
||||
{
|
||||
_recordOffsetY = items[1].GetComponent<RectTransform>().anchoredPosition.y - items[0].GetComponent<RectTransform>().anchoredPosition.y;
|
||||
if (_recordOffsetY < 0)
|
||||
{
|
||||
_recordOffsetY *= -1;
|
||||
}
|
||||
_disableMarginY = _recordOffsetY * _itemCount / 2;
|
||||
}
|
||||
if (_isHorizontal)
|
||||
{
|
||||
_recordOffsetX = items[1].GetComponent<RectTransform>().anchoredPosition.x - items[0].GetComponent<RectTransform>().anchoredPosition.x;
|
||||
if (_recordOffsetX < 0)
|
||||
{
|
||||
_recordOffsetX *= -1;
|
||||
}
|
||||
_disableMarginX = _recordOffsetX * _itemCount / 2;
|
||||
}
|
||||
|
||||
if (_verticalLayoutGroup)
|
||||
{
|
||||
_verticalLayoutGroup.enabled = false;
|
||||
}
|
||||
if (_horizontalLayoutGroup)
|
||||
{
|
||||
_horizontalLayoutGroup.enabled = false;
|
||||
}
|
||||
if (_contentSizeFitter)
|
||||
{
|
||||
_contentSizeFitter.enabled = false;
|
||||
}
|
||||
if (_gridLayoutGroup)
|
||||
{
|
||||
_gridLayoutGroup.enabled = false;
|
||||
}
|
||||
_hasDisabledGridComponents = true;
|
||||
}
|
||||
|
||||
public void OnScroll(Vector2 pos)
|
||||
{
|
||||
if (!_hasDisabledGridComponents)
|
||||
DisableGridComponents();
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
if (_isHorizontal)
|
||||
{
|
||||
if (_scrollRect.transform.InverseTransformPoint(items[i].gameObject.transform.position).x > _disableMarginX + _threshold)
|
||||
{
|
||||
_newAnchoredPosition = items[i].anchoredPosition;
|
||||
_newAnchoredPosition.x -= _itemCount * _recordOffsetX;
|
||||
items[i].anchoredPosition = _newAnchoredPosition;
|
||||
_scrollRect.content.GetChild(_itemCount - 1).transform.SetAsFirstSibling();
|
||||
}
|
||||
else if (_scrollRect.transform.InverseTransformPoint(items[i].gameObject.transform.position).x < -_disableMarginX)
|
||||
{
|
||||
_newAnchoredPosition = items[i].anchoredPosition;
|
||||
_newAnchoredPosition.x += _itemCount * _recordOffsetX;
|
||||
items[i].anchoredPosition = _newAnchoredPosition;
|
||||
_scrollRect.content.GetChild(0).transform.SetAsLastSibling();
|
||||
}
|
||||
}
|
||||
|
||||
if (_isVertical)
|
||||
{
|
||||
if (_scrollRect.transform.InverseTransformPoint(items[i].gameObject.transform.position).y > _disableMarginY + _threshold)
|
||||
{
|
||||
_newAnchoredPosition = items[i].anchoredPosition;
|
||||
_newAnchoredPosition.y -= _itemCount * _recordOffsetY;
|
||||
items[i].anchoredPosition = _newAnchoredPosition;
|
||||
_scrollRect.content.GetChild(_itemCount - 1).transform.SetAsFirstSibling();
|
||||
}
|
||||
else if (_scrollRect.transform.InverseTransformPoint(items[i].gameObject.transform.position).y < -_disableMarginY)
|
||||
{
|
||||
_newAnchoredPosition = items[i].anchoredPosition;
|
||||
_newAnchoredPosition.y += _itemCount * _recordOffsetY;
|
||||
items[i].anchoredPosition = _newAnchoredPosition;
|
||||
_scrollRect.content.GetChild(0).transform.SetAsLastSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61fe0f6272fa94d4eb3dafc6aecd50ff
|
||||
timeCreated: 1467462282
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,200 @@
|
||||
/// Credit Febo Zodiaco
|
||||
/// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/349/magnticinfinitescroll
|
||||
///
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/UI Magnetic Infinite Scroll")]
|
||||
[RequireComponent(typeof(ScrollRect))]
|
||||
public class UI_MagneticInfiniteScroll : UI_InfiniteScroll, IDragHandler, IEndDragHandler, IScrollHandler
|
||||
{
|
||||
public event Action<GameObject> OnNewSelect;
|
||||
|
||||
[Tooltip("The pointer to the pivot, the visual element for centering objects.")]
|
||||
[SerializeField]
|
||||
private RectTransform pivot = null;
|
||||
[Tooltip("The maximum speed that allows you to activate the magnet to center on the pivot")]
|
||||
[SerializeField]
|
||||
private float maxSpeedForMagnetic = 10f;
|
||||
[SerializeField]
|
||||
[Tooltip("The index of the object which must be initially centered")]
|
||||
private int indexStart = 0;
|
||||
[SerializeField]
|
||||
[Tooltip("The time to decelerate and aim to the pivot")]
|
||||
private float timeForDeceleration = 0.05f;
|
||||
|
||||
private float _pastPositionMouseSpeed;
|
||||
private float _initMovementDirection = 0;
|
||||
private float _pastPosition = 0;
|
||||
|
||||
private float _currentSpeed = 0.0f;
|
||||
private float _stopValue = 0.0f;
|
||||
private readonly float _waitForContentSet = 0.1f;
|
||||
private float _currentTime = 0;
|
||||
private int _nearestIndex = 0;
|
||||
|
||||
private bool _useMagnetic = true;
|
||||
private bool _isStopping = false;
|
||||
private bool _isMovement = false;
|
||||
|
||||
public List<RectTransform> Items { get; }
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
StartCoroutine(SetInitContent());
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_scrollRect == null || !_scrollRect.content || !pivot || !_useMagnetic || !_isMovement || items == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float currentPosition = GetRightAxis(_scrollRect.content.anchoredPosition);
|
||||
_currentSpeed = Mathf.Abs(currentPosition - _pastPosition);
|
||||
_pastPosition = currentPosition;
|
||||
if (Mathf.Abs(_currentSpeed) > maxSpeedForMagnetic)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isStopping)
|
||||
{
|
||||
Vector2 anchoredPosition = _scrollRect.content.anchoredPosition;
|
||||
_currentTime += Time.deltaTime;
|
||||
float valueLerp = _currentTime / timeForDeceleration;
|
||||
|
||||
float newPosition = Mathf.Lerp(GetRightAxis(anchoredPosition), _stopValue, valueLerp);
|
||||
|
||||
_scrollRect.content.anchoredPosition = _isVertical ? new Vector2(anchoredPosition.x, newPosition) :
|
||||
new Vector2(newPosition, anchoredPosition.y);
|
||||
|
||||
|
||||
if (newPosition == GetRightAxis(anchoredPosition) && _nearestIndex > 0 && _nearestIndex < items.Count)
|
||||
{
|
||||
_isStopping = false;
|
||||
_isMovement = false;
|
||||
var item = items[_nearestIndex];
|
||||
if (item != null && OnNewSelect != null)
|
||||
{
|
||||
|
||||
OnNewSelect.Invoke(item.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float distance = Mathf.Infinity * (-_initMovementDirection);
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
var item = items[i];
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var aux = GetRightAxis(item.position) - GetRightAxis(pivot.position);
|
||||
|
||||
if ((_initMovementDirection <= 0 && aux < distance && aux > 0) ||
|
||||
(_initMovementDirection > 0 && aux > distance && aux < 0))
|
||||
{
|
||||
distance = aux;
|
||||
_nearestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
_isStopping = true;
|
||||
_stopValue = GetAnchoredPositionForPivot(_nearestIndex);
|
||||
_scrollRect.StopMovement();
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetNewItems(ref List<Transform> newItems)
|
||||
{
|
||||
foreach (var element in newItems)
|
||||
{
|
||||
RectTransform rectTransform = element.GetComponent<RectTransform>();
|
||||
if (rectTransform && pivot)
|
||||
{
|
||||
rectTransform.sizeDelta = pivot.sizeDelta;
|
||||
}
|
||||
}
|
||||
base.SetNewItems(ref newItems);
|
||||
}
|
||||
|
||||
public void SetContentInPivot(int index)
|
||||
{
|
||||
float newPos = GetAnchoredPositionForPivot(index);
|
||||
Vector2 anchoredPosition = _scrollRect.content.anchoredPosition;
|
||||
|
||||
if (_scrollRect.content)
|
||||
{
|
||||
_scrollRect.content.anchoredPosition = _isVertical ? new Vector2(anchoredPosition.x, newPos) :
|
||||
new Vector2(newPos, anchoredPosition.y);
|
||||
_pastPosition = GetRightAxis(_scrollRect.content.anchoredPosition);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator SetInitContent()
|
||||
{
|
||||
yield return new WaitForSeconds(_waitForContentSet);
|
||||
SetContentInPivot(indexStart);
|
||||
}
|
||||
|
||||
private float GetAnchoredPositionForPivot(int index)
|
||||
{
|
||||
if (!pivot || items == null || items.Count < 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
index = Mathf.Clamp(index, 0, items.Count - 1);
|
||||
|
||||
float posItem = GetRightAxis(items[index].anchoredPosition);
|
||||
float posPivot = GetRightAxis(pivot.anchoredPosition);
|
||||
return posPivot - posItem;
|
||||
}
|
||||
|
||||
private void FinishPrepareMovement()
|
||||
{
|
||||
_isMovement = true;
|
||||
_useMagnetic = true;
|
||||
_isStopping = false;
|
||||
_currentTime = 0;
|
||||
}
|
||||
|
||||
private float GetRightAxis(Vector2 vector)
|
||||
{
|
||||
return _isVertical ? vector.y : vector.x;
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
float currentPosition = GetRightAxis(UIExtensionsInputManager.MousePosition);
|
||||
|
||||
_initMovementDirection = Mathf.Sign(currentPosition - _pastPositionMouseSpeed);
|
||||
_pastPositionMouseSpeed = currentPosition;
|
||||
_useMagnetic = false;
|
||||
_isStopping = false;
|
||||
}
|
||||
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
FinishPrepareMovement();
|
||||
}
|
||||
|
||||
public void OnScroll(PointerEventData eventData)
|
||||
{
|
||||
_initMovementDirection = -UIExtensionsInputManager.MouseScrollDelta.y;
|
||||
FinishPrepareMovement();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a2ddc0989b894a499a02fb975aa0322
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,200 @@
|
||||
/// Credit Tomasz Schelenz
|
||||
/// Sourced from - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/issues/82/scrollrectocclusion
|
||||
/// Demo - https://youtu.be/uVTV7Udx78k?t=39s ScrollRectOcclusion - disables the objects outside of the scrollrect viewport. Useful for scrolls with lots of content, reduces geometry and drawcalls (if content is not batched) In some cases it might create a bit of spikes, especially if you have lots of UI.Text objects in the childs. In that case consider to Add CanvasGroup to your childs and instead of calling setActive on game object change CanvasGroup.alpha value. At 0 it is not being rendered hence will also optimize the performance.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// ScrollRectOcclusion - disables the objects outside of the scrollrect viewport.
|
||||
/// Useful for scrolls with lots of content, reduces geometry and drawcalls (if content is not batched)
|
||||
///
|
||||
/// Fields
|
||||
/// - InitByUSer - in case your scrollrect is populated from code, you can explicitly Initialize the infinite scroll after your scroll is ready
|
||||
/// by calling Init() method
|
||||
///
|
||||
/// Notes
|
||||
/// - In some cases it might create a bit of spikes, especially if you have lots of UI.Text objects in the child's. In that case consider to Add
|
||||
/// CanvasGroup to your child's and instead of calling setActive on game object change CanvasGroup.alpha value. At 0 it is not being rendered hence will
|
||||
/// also optimize the performance.
|
||||
/// - works for both vertical and horizontal scrolls, even at the same time (grid layout)
|
||||
/// - in order to work it disables layout components and size fitter if present (automatically)
|
||||
/// </summary>
|
||||
|
||||
[AddComponentMenu("UI/Extensions/UI Scrollrect Occlusion")]
|
||||
public class UI_ScrollRectOcclusion : MonoBehaviour
|
||||
{
|
||||
//if true user will need to call Init() method manually (in case the contend of the scrollview is generated from code or requires special initialization)
|
||||
public bool InitByUser = false;
|
||||
private bool _initialised = false;
|
||||
private ScrollRect _scrollRect;
|
||||
private ContentSizeFitter _contentSizeFitter;
|
||||
private VerticalLayoutGroup _verticalLayoutGroup;
|
||||
private HorizontalLayoutGroup _horizontalLayoutGroup;
|
||||
private GridLayoutGroup _gridLayoutGroup;
|
||||
private bool _isVertical = false;
|
||||
private bool _isHorizontal = false;
|
||||
private float _disableMarginX = 0;
|
||||
private float _disableMarginY = 0;
|
||||
private bool _hasDisabledGridComponents = false;
|
||||
private List<RectTransform> _items = new List<RectTransform>();
|
||||
private bool _reset = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (InitByUser)
|
||||
return;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
if (_initialised)
|
||||
{
|
||||
Debug.LogError("Control already initialized\nYou have to enable the InitByUser setting on the control in order to use Init() when running");
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetComponent<ScrollRect>() != null)
|
||||
{
|
||||
_initialised = true;
|
||||
_scrollRect = GetComponent<ScrollRect>();
|
||||
_scrollRect.onValueChanged.AddListener(OnScroll);
|
||||
|
||||
_isHorizontal = _scrollRect.horizontal;
|
||||
_isVertical = _scrollRect.vertical;
|
||||
|
||||
for (int i = 0; i < _scrollRect.content.childCount; i++)
|
||||
{
|
||||
_items.Add(_scrollRect.content.GetChild(i).GetComponent<RectTransform>());
|
||||
}
|
||||
if (_scrollRect.content.GetComponent<VerticalLayoutGroup>() != null)
|
||||
{
|
||||
_verticalLayoutGroup = _scrollRect.content.GetComponent<VerticalLayoutGroup>();
|
||||
}
|
||||
if (_scrollRect.content.GetComponent<HorizontalLayoutGroup>() != null)
|
||||
{
|
||||
_horizontalLayoutGroup = _scrollRect.content.GetComponent<HorizontalLayoutGroup>();
|
||||
}
|
||||
if (_scrollRect.content.GetComponent<GridLayoutGroup>() != null)
|
||||
{
|
||||
_gridLayoutGroup = _scrollRect.content.GetComponent<GridLayoutGroup>();
|
||||
}
|
||||
if (_scrollRect.content.GetComponent<ContentSizeFitter>() != null)
|
||||
{
|
||||
_contentSizeFitter = _scrollRect.content.GetComponent<ContentSizeFitter>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("UI_ScrollRectOcclusion => No ScrollRect component found");
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleGridComponents(bool toggle)
|
||||
{
|
||||
if (_isVertical)
|
||||
_disableMarginY = _scrollRect.GetComponent<RectTransform>().rect.height / 2 + _items[0].sizeDelta.y;
|
||||
|
||||
if (_isHorizontal)
|
||||
_disableMarginX = _scrollRect.GetComponent<RectTransform>().rect.width / 2 + _items[0].sizeDelta.x;
|
||||
|
||||
if (_verticalLayoutGroup)
|
||||
{
|
||||
_verticalLayoutGroup.enabled = toggle;
|
||||
}
|
||||
if (_horizontalLayoutGroup)
|
||||
{
|
||||
_horizontalLayoutGroup.enabled = toggle;
|
||||
}
|
||||
if (_contentSizeFitter)
|
||||
{
|
||||
_contentSizeFitter.enabled = toggle;
|
||||
}
|
||||
if (_gridLayoutGroup)
|
||||
{
|
||||
_gridLayoutGroup.enabled = toggle;
|
||||
}
|
||||
_hasDisabledGridComponents = !toggle;
|
||||
}
|
||||
|
||||
public void OnScroll(Vector2 pos)
|
||||
{
|
||||
if (_reset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_hasDisabledGridComponents)
|
||||
{
|
||||
ToggleGridComponents(false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _items.Count; i++)
|
||||
{
|
||||
if (_isVertical && _isHorizontal)
|
||||
{
|
||||
if (_scrollRect.transform.InverseTransformPoint(_items[i].position).y < -_disableMarginY || _scrollRect.transform.InverseTransformPoint(_items[i].position).y > _disableMarginY
|
||||
|| _scrollRect.transform.InverseTransformPoint(_items[i].position).x < -_disableMarginX || _scrollRect.transform.InverseTransformPoint(_items[i].position).x > _disableMarginX)
|
||||
{
|
||||
_items[i].gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_items[i].gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_isVertical)
|
||||
{
|
||||
if (_scrollRect.transform.InverseTransformPoint(_items[i].position).y < -_disableMarginY || _scrollRect.transform.InverseTransformPoint(_items[i].position).y > _disableMarginY)
|
||||
{
|
||||
_items[i].gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_items[i].gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (_isHorizontal)
|
||||
{
|
||||
if (_scrollRect.transform.InverseTransformPoint(_items[i].position).x < -_disableMarginX || _scrollRect.transform.InverseTransformPoint(_items[i].position).x > _disableMarginX)
|
||||
{
|
||||
_items[i].gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_items[i].gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDirty()
|
||||
{
|
||||
_reset = true;
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (_reset)
|
||||
{
|
||||
_reset = false;
|
||||
_items.Clear();
|
||||
|
||||
for (int i = 0; i < _scrollRect.content.childCount; i++)
|
||||
{
|
||||
_items.Add(_scrollRect.content.GetChild(i).GetComponent<RectTransform>());
|
||||
_items[i].gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
ToggleGridComponents(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1bb7fb3155d62546a876bd63cdcd81f
|
||||
timeCreated: 1467462085
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,104 @@
|
||||
/// Credit Tomasz Schelenz
|
||||
/// Sourced from - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/issues/83/ui_tweenscale
|
||||
/// Demo - https://youtu.be/uVTV7Udx78k?t=1m33s Dynamic scaling of text or image (including button) based on curves. works on scrollrect scale so you can pretty much use it for any ui type.
|
||||
/// Notes In some cases it can create spikes due to redrawing on change, it is recommended to use it on simple objects in separated canvases to avoid redrawing full canvas.
|
||||
|
||||
|
||||
using System.Collections;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Dynamic scaling of text or image (including button) based on curves
|
||||
///
|
||||
/// Fields
|
||||
/// - animCurve - animation curve for scale (if isUniform set to false, will apply only to X scale)
|
||||
/// - speed - animation speed
|
||||
/// - isLoop - animation will play infinitely (in order to make it work set your animation curve to loop)
|
||||
/// - playAtAwake - starts automatically with script becoming active. Otherwise you need to call Play() method.
|
||||
/// - isUniform - if false animCurve will modify object X scale and animCurveY - Y scale.
|
||||
///
|
||||
///
|
||||
/// Notes
|
||||
/// - If you want to stop the animation call the ResetTween() method.
|
||||
/// - In some cases it can create spikes due to redrawing on change, it is recommended to use it on simple objects in separated canvases to
|
||||
/// avoid redrawing full canvas.
|
||||
/// - If you want to scale object only in 1 axis select non unifor and use linear curve from 1 to 1 to lock the scale.
|
||||
///
|
||||
/// </summary>
|
||||
[AddComponentMenu("UI/Extensions/UI Tween Scale")]
|
||||
public class UI_TweenScale : MonoBehaviour
|
||||
{
|
||||
//ANIMATION FOR X AND Y, OR X IF isUniform set to false
|
||||
public AnimationCurve animCurve;
|
||||
[Tooltip("Animation speed multiplier")]
|
||||
public float speed = 1;
|
||||
|
||||
[Tooltip("If true animation will loop, for best effect set animation curve to loop on start and end point")]
|
||||
|
||||
public bool isLoop = false;
|
||||
//IF TRUE ANIMATION STARTS AUTOMATICALLY
|
||||
[Tooltip("If true animation will start automatically, otherwise you need to call Play() method to start the animation")]
|
||||
|
||||
public bool playAtAwake = false;
|
||||
|
||||
[Space(10)]
|
||||
//if true both x and y axis will be using animCurve;
|
||||
[Header("Non uniform scale")]
|
||||
[Tooltip("If true component will scale by the same amount in X and Y axis, otherwise use animCurve for X scale and animCurveY for Y scale")]
|
||||
public bool isUniform = true;
|
||||
//IF isUniform set to false use this for Y axis
|
||||
public AnimationCurve animCurveY;
|
||||
private Vector3 initScale;
|
||||
private Transform myTransform;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
myTransform = GetComponent<Transform>();
|
||||
initScale = myTransform.localScale;
|
||||
if (playAtAwake)
|
||||
{
|
||||
Play();
|
||||
}
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
StartCoroutine("Tween");
|
||||
}
|
||||
|
||||
Vector3 newScale = Vector3.one;
|
||||
|
||||
IEnumerator Tween()
|
||||
{
|
||||
myTransform.localScale = initScale;
|
||||
float t = 0;
|
||||
float maxT = animCurve.keys[animCurve.length - 1].time;
|
||||
|
||||
while (t < maxT || isLoop)
|
||||
{
|
||||
t += speed * Time.deltaTime;
|
||||
|
||||
if (!isUniform)
|
||||
{
|
||||
newScale.x = 1 * animCurve.Evaluate(t);
|
||||
newScale.y = 1 * animCurveY.Evaluate(t);
|
||||
|
||||
myTransform.localScale = newScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
myTransform.localScale = Vector3.one * animCurve.Evaluate(t);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetTween()
|
||||
{
|
||||
StopCoroutine("Tween");
|
||||
myTransform.localScale = initScale;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61bf9d6fa29ed164e8a1df46e0d40835
|
||||
timeCreated: 1467462200
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,24 @@
|
||||
/// Credit Izitmee
|
||||
/// Sourced from - http://forum.unity3d.com/threads/find-anchoredposition-of-a-recttransform-relative-to-another-recttransform.330560/#post-2300992
|
||||
/// Updated by Brave Michael - http://forum.unity3d.com/threads/find-anchoredposition-of-a-recttransform-relative-to-another-recttransform.330560/#post-2300992
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public static class RectTransformExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the anchoredPosition of the first RectTransform to the second RectTransform,
|
||||
/// taking into consideration offset, anchors and pivot, and returns the new anchoredPosition
|
||||
/// </summary>
|
||||
public static Vector2 switchToRectTransform(this RectTransform from, RectTransform to)
|
||||
{
|
||||
Vector2 localPoint;
|
||||
Vector2 fromPivotDerivedOffset = new Vector2(from.rect.width * from.pivot.x + from.rect.xMin, from.rect.height * from.pivot.y + from.rect.yMin);
|
||||
Vector2 screenP = RectTransformUtility.WorldToScreenPoint(null, from.position);
|
||||
screenP += fromPivotDerivedOffset;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(to, screenP, null, out localPoint);
|
||||
Vector2 pivotDerivedOffset = new Vector2(to.rect.width * to.pivot.x + to.rect.xMin, to.rect.height * to.pivot.y + to.rect.yMin);
|
||||
return to.anchoredPosition + localPoint - pivotDerivedOffset;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 977482c1b88728145ba612c0fdec3b92
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
Reference in New Issue
Block a user