Editor stuff

This commit is contained in:
Starpelly
2022-01-05 19:11:33 -05:00
parent 775fd7e580
commit 576b0d8482
458 changed files with 37611 additions and 15 deletions

View File

@ -0,0 +1,62 @@
/// Credit Melang
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
using System.Collections.Generic;
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/BestFit Outline")]
public class BestFitOutline : Shadow
{
//
// Constructors
//
protected BestFitOutline ()
{
}
//
// Methods
//
public override void ModifyMesh (Mesh mesh)
{
if (!this.IsActive ())
{
return;
}
List<UIVertex> verts = new List<UIVertex>();
using (var helper = new VertexHelper(mesh))
{
helper.GetUIVertexStream(verts);
}
Text foundtext = GetComponent<Text>();
float best_fit_adjustment = 1f;
if (foundtext && foundtext.resizeTextForBestFit)
{
best_fit_adjustment = (float)foundtext.cachedTextGenerator.fontSizeUsedForBestFit / (foundtext.resizeTextMaxSize-1); //max size seems to be exclusive
}
int start = 0;
int count = verts.Count;
base.ApplyShadowZeroAlloc(verts, base.effectColor, start, verts.Count, base.effectDistance.x*best_fit_adjustment, base.effectDistance.y*best_fit_adjustment);
start = count;
count = verts.Count;
base.ApplyShadowZeroAlloc(verts, base.effectColor, start, verts.Count, base.effectDistance.x*best_fit_adjustment, -base.effectDistance.y*best_fit_adjustment);
start = count;
count = verts.Count;
base.ApplyShadowZeroAlloc(verts, base.effectColor, start, verts.Count, -base.effectDistance.x*best_fit_adjustment, base.effectDistance.y*best_fit_adjustment);
start = count;
count = verts.Count;
base.ApplyShadowZeroAlloc(verts, base.effectColor, start, verts.Count, -base.effectDistance.x*best_fit_adjustment, -base.effectDistance.y*best_fit_adjustment);
using (var helper = new VertexHelper())
{
helper.AddUIVertexTriangleStream(verts);
helper.FillMesh(mesh);
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7b30dd83a12669d4f973ff5a79ca9842
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: e8f8c7784bd14f146a01bb324949f7cb
folderAsset: yes
timeCreated: 1501406849
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,116 @@
/// Credit Titinious (https://github.com/Titinious)
/// Sourced from - https://github.com/Titinious/CurlyUI
namespace UnityEngine.UI.Extensions
{
/// <summary>
/// Assume to be a cubic bezier curve at the moment.
/// </summary>
public class CUIBezierCurve : MonoBehaviour
{
public readonly static int CubicBezierCurvePtNum = 4;
#region Descriptions
[SerializeField]
protected Vector3[] controlPoints;
public Vector3[] ControlPoints
{
get
{
return controlPoints;
}
}
#if UNITY_EDITOR
/// <summary>
/// Reserve for editor only
/// </summary>
public Vector3[] EDITOR_ControlPoints
{
set
{
controlPoints = value;
}
}
#endif
#endregion
#region Events
#if UNITY_EDITOR
protected void OnValidate()
{
Refresh();
}
#endif
public void Refresh()
{
if (OnRefresh != null)
OnRefresh();
}
#endregion
#region Services
/// <summary>
/// call this to get a sample
/// </summary>
/// <param name="_time"></param>
/// <returns>sample returned by said time</returns>
public Vector3 GetPoint(float _time)
{
float oneMinusTime = 1 - _time;
return oneMinusTime * oneMinusTime * oneMinusTime * controlPoints[0] +
3 * oneMinusTime * oneMinusTime * _time * controlPoints[1] +
3 * oneMinusTime * _time * _time * controlPoints[2] +
_time * _time * _time * controlPoints[3];
}
public Vector3 GetTangent(float _time)
{
float oneMinusTime = 1 - _time;
return 3 * oneMinusTime * oneMinusTime * (controlPoints[1] - controlPoints[0]) +
6 * oneMinusTime * _time * (controlPoints[2] - controlPoints[1]) +
3 * _time * _time * (controlPoints[3] - controlPoints[2]);
}
#endregion
#region Configurations
public void ReportSet()
{
if (controlPoints == null)
{
controlPoints = new Vector3[CUIBezierCurve.CubicBezierCurvePtNum];
controlPoints[0] = new Vector3(0, 0, 0);
controlPoints[1] = new Vector3(0, 1, 0);
controlPoints[2] = new Vector3(1, 1, 0);
controlPoints[3] = new Vector3(1, 0, 0);
}
bool isPointsReady = true;
isPointsReady = isPointsReady & controlPoints.Length == CUIBezierCurve.CubicBezierCurvePtNum;
}
#endregion
#region Services
public System.Action OnRefresh;
#endregion
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 983a3e151cd916d4faf111dc86266574
timeCreated: 1485671878
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,617 @@
/// Credit Titinious (https://github.com/Titinious)
/// Sourced from - https://github.com/Titinious/CurlyUI
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Graphic))]
[DisallowMultipleComponent]
[AddComponentMenu("UI/Effects/Extensions/Curly UI Graphic")]
public class CUIGraphic : BaseMeshEffect
{
// Describing the properties that are shared by all objects of this class
#region Nature
readonly public static int bottomCurveIdx = 0;
readonly public static int topCurveIdx = 1;
#endregion
/// <summary>
/// Describing the properties of this object.
/// </summary>
#region Description
[Tooltip("Set true to make the curve/morph to work. Set false to quickly see the original UI.")]
[SerializeField]
protected bool isCurved = true;
public bool IsCurved
{
get
{
return isCurved;
}
}
[Tooltip("Set true to dynamically change the curve according to the dynamic change of the UI layout")]
[SerializeField]
protected bool isLockWithRatio = true;
public bool IsLockWithRatio
{
get
{
return isLockWithRatio;
}
}
[Tooltip("Pick a higher resolution to improve the quality of the curved graphic.")]
[SerializeField]
[Range(0.01f, 30.0f)]
protected float resolution = 5.0f;
#endregion
/// <summary>
/// Reference to other objects that are needed by this object.
/// </summary>
#region Links
protected RectTransform rectTrans;
public RectTransform RectTrans
{
get
{
return rectTrans;
}
}
[Tooltip("Put in the Graphic you want to curve/morph here.")]
[SerializeField]
protected Graphic uiGraphic;
public Graphic UIGraphic
{
get
{
return uiGraphic;
}
}
[Tooltip("Put in the reference Graphic that will be used to tune the bezier curves. Think button image and text.")]
[SerializeField]
protected CUIGraphic refCUIGraphic;
public CUIGraphic RefCUIGraphic
{
get
{
return refCUIGraphic;
}
}
[Tooltip("Do not touch this unless you are sure what you are doing. The curves are (re)generated automatically.")]
[SerializeField]
protected CUIBezierCurve[] refCurves;
public CUIBezierCurve[] RefCurves
{
get
{
return refCurves;
}
}
[HideInInspector]
[SerializeField]
protected Vector3_Array2D[] refCurvesControlRatioPoints;
public Vector3_Array2D[] RefCurvesControlRatioPoints
{
get
{
return refCurvesControlRatioPoints;
}
}
#if UNITY_EDITOR
public CUIBezierCurve[] EDITOR_RefCurves
{
set
{
refCurves = value;
}
}
public Vector3_Array2D[] EDITOR_RefCurvesControlRatioPoints
{
set
{
refCurvesControlRatioPoints = value;
}
}
#endif
#endregion
// Methods that are used often.
#region Reuse
protected List<UIVertex> reuse_quads = new List<UIVertex>();
#endregion
#region Action
protected void solveDoubleEquationWithVector(float _x_1, float _y_1, float _x_2, float _y_2, Vector3 _constant_1, Vector3 _contant_2, out Vector3 _x, out Vector3 _y)
{
Vector3 f;
float g;
if (Mathf.Abs(_x_1) > Mathf.Abs(_x_2))
{
f = _constant_1 * _x_2 / _x_1;
g = _y_1 * _x_2 / _x_1;
_y = (_contant_2 - f) / (_y_2 - g);
if (_x_2 != 0)
_x = (f - g * _y) / _x_2;
else
_x = (_constant_1 - _y_1 * _y) / _x_1;
}
else
{
f = _contant_2 * _x_1 / _x_2;
g = _y_2 * _x_1 / _x_2;
_x = (_constant_1 - f) / (_y_1 - g);
if (_x_1 != 0)
_y = (f - g * _x) / _x_1;
else
_y = (_contant_2 - _y_2 * _x) / _x_2;
}
}
protected UIVertex uiVertexLerp(UIVertex _a, UIVertex _b, float _time)
{
UIVertex tmpUIVertex = new UIVertex();
tmpUIVertex.position = Vector3.Lerp(_a.position, _b.position, _time);
tmpUIVertex.normal = Vector3.Lerp(_a.normal, _b.normal, _time);
tmpUIVertex.tangent = Vector3.Lerp(_a.tangent, _b.tangent, _time);
tmpUIVertex.uv0 = Vector2.Lerp(_a.uv0, _b.uv0, _time);
tmpUIVertex.uv1 = Vector2.Lerp(_a.uv1, _b.uv1, _time);
tmpUIVertex.color = Color.Lerp(_a.color, _b.color, _time);
return tmpUIVertex;
}
/// <summary>
/// Bilinear Interpolation
/// </summary>
protected UIVertex uiVertexBerp(UIVertex v_bottomLeft, UIVertex v_topLeft, UIVertex v_topRight, UIVertex v_bottomRight, float _xTime, float _yTime)
{
UIVertex topX = uiVertexLerp(v_topLeft, v_topRight, _xTime);
UIVertex bottomX = uiVertexLerp(v_bottomLeft, v_bottomRight, _xTime);
return uiVertexLerp(bottomX, topX, _yTime);
}
protected void tessellateQuad(List<UIVertex> _quads, int _thisQuadIdx)
{
UIVertex v_bottomLeft = _quads[_thisQuadIdx];
UIVertex v_topLeft = _quads[_thisQuadIdx + 1];
UIVertex v_topRight = _quads[_thisQuadIdx + 2];
UIVertex v_bottomRight = _quads[_thisQuadIdx + 3];
float quadSize = 100.0f / resolution;
int heightQuadEdgeNum = Mathf.Max(1, Mathf.CeilToInt((v_topLeft.position - v_bottomLeft.position).magnitude / quadSize));
int widthQuadEdgeNum = Mathf.Max(1, Mathf.CeilToInt((v_topRight.position - v_topLeft.position).magnitude / quadSize));
int quadIdx = 0;
for (int x = 0; x < widthQuadEdgeNum; x++)
{
for (int y = 0; y < heightQuadEdgeNum; y++, quadIdx++)
{
_quads.Add(new UIVertex());
_quads.Add(new UIVertex());
_quads.Add(new UIVertex());
_quads.Add(new UIVertex());
float xRatio = (float)x / widthQuadEdgeNum;
float yRatio = (float)y / heightQuadEdgeNum;
float xPlusOneRatio = (float)(x + 1) / widthQuadEdgeNum;
float yPlusOneRatio = (float)(y + 1) / heightQuadEdgeNum;
_quads[_quads.Count - 4] = uiVertexBerp(v_bottomLeft, v_topLeft, v_topRight, v_bottomRight, xRatio, yRatio);
_quads[_quads.Count - 3] = uiVertexBerp(v_bottomLeft, v_topLeft, v_topRight, v_bottomRight, xRatio, yPlusOneRatio);
_quads[_quads.Count - 2] = uiVertexBerp(v_bottomLeft, v_topLeft, v_topRight, v_bottomRight, xPlusOneRatio, yPlusOneRatio);
_quads[_quads.Count - 1] = uiVertexBerp(v_bottomLeft, v_topLeft, v_topRight, v_bottomRight, xPlusOneRatio, yRatio);
}
}
}
protected void tessellateGraphic(List<UIVertex> _verts)
{
for (int v = 0; v < _verts.Count; v += 6)
{
reuse_quads.Add(_verts[v]); // bottom left
reuse_quads.Add(_verts[v + 1]); // top left
reuse_quads.Add(_verts[v + 2]); // top right
// verts[3] is redundant, top right
reuse_quads.Add(_verts[v + 4]); // bottom right
// verts[5] is redundant, bottom left
}
int oriQuadNum = reuse_quads.Count / 4;
for (int q = 0; q < oriQuadNum; q++)
{
tessellateQuad(reuse_quads, q * 4);
}
// remove original quads
reuse_quads.RemoveRange(0, oriQuadNum * 4);
_verts.Clear();
// process new quads and turn them into triangles
for (int q = 0; q < reuse_quads.Count; q += 4)
{
_verts.Add(reuse_quads[q]);
_verts.Add(reuse_quads[q + 1]);
_verts.Add(reuse_quads[q + 2]);
_verts.Add(reuse_quads[q + 2]);
_verts.Add(reuse_quads[q + 3]);
_verts.Add(reuse_quads[q]);
}
reuse_quads.Clear();
}
#endregion
// Events are for handling reoccurring function calls that react to the changes of the environment.
#region Events
protected override void OnRectTransformDimensionsChange()
{
if (isLockWithRatio)
{
UpdateCurveControlPointPositions();
}
}
public void Refresh()
{
ReportSet();
// we use local position as the true value. Ratio position follows it, so it should be updated when refresh
for (int c = 0; c < refCurves.Length; c++)
{
CUIBezierCurve curve = refCurves[c];
if (curve.ControlPoints != null)
{
Vector3[] controlPoints = curve.ControlPoints;
for (int p = 0; p < CUIBezierCurve.CubicBezierCurvePtNum; p++)
{
#if UNITY_EDITOR
Undo.RecordObject(this, "Move Point");
#endif
Vector3 ratioPoint = controlPoints[p];
ratioPoint.x = (ratioPoint.x + rectTrans.rect.width * rectTrans.pivot.x) / rectTrans.rect.width;
ratioPoint.y = (ratioPoint.y + rectTrans.rect.height * rectTrans.pivot.y) / rectTrans.rect.height;
refCurvesControlRatioPoints[c][p] = ratioPoint;
}
}
}
//uiText.SetAllDirty();
// need this to refresh the UI text, SetAllDirty does not seem to work for all cases
if (uiGraphic != null)
{
uiGraphic.enabled = false;
uiGraphic.enabled = true;
}
}
#endregion
// Methods that change the behaviour of the object.
#region Flash-Phase
protected override void Awake()
{
base.Awake();
OnRectTransformDimensionsChange();
}
protected override void OnEnable()
{
base.OnEnable();
OnRectTransformDimensionsChange();
}
#endregion
#region Configurations
/// <summary>
/// Check, prepare and set everything needed.
/// </summary>
public virtual void ReportSet()
{
if (rectTrans == null)
rectTrans = GetComponent<RectTransform>();
if (refCurves == null)
refCurves = new CUIBezierCurve[2];
bool isCurvesReady = true;
for (int c = 0; c < 2; c++)
{
isCurvesReady = isCurvesReady & refCurves[c] != null;
}
isCurvesReady = isCurvesReady & refCurves.Length == 2;
if (!isCurvesReady)
{
CUIBezierCurve[] curves = refCurves;
for (int c = 0; c < 2; c++)
{
if (refCurves[c] == null)
{
GameObject go = new GameObject();
go.transform.SetParent(transform);
go.transform.localPosition = Vector3.zero;
go.transform.localEulerAngles = Vector3.zero;
if (c == 0)
{
go.name = "BottomRefCurve";
}
else
{
go.name = "TopRefCurve";
}
curves[c] = go.AddComponent<CUIBezierCurve>();
}
else
{
curves[c] = refCurves[c];
}
curves[c].ReportSet();
}
refCurves = curves;
}
if (refCurvesControlRatioPoints == null)
{
refCurvesControlRatioPoints = new Vector3_Array2D[refCurves.Length];
for (int c = 0; c < refCurves.Length; c++)
{
{
refCurvesControlRatioPoints[c].array = new Vector3[refCurves[c].ControlPoints.Length];
}
}
FixTextToRectTrans();
Refresh();
}
for (int c = 0; c < 2; c++)
{
refCurves[c].OnRefresh = Refresh;
}
}
public void FixTextToRectTrans()
{
for (int c = 0; c < refCurves.Length; c++)
{
CUIBezierCurve curve = refCurves[c];
for (int p = 0; p < CUIBezierCurve.CubicBezierCurvePtNum; p++)
{
if (curve.ControlPoints != null)
{
Vector3[] controlPoints = curve.ControlPoints;
if (c == 0)
{
controlPoints[p].y = -rectTrans.rect.height * rectTrans.pivot.y;
}
else
{
controlPoints[p].y = rectTrans.rect.height - rectTrans.rect.height * rectTrans.pivot.y;
}
controlPoints[p].x = rectTrans.rect.width * p / (CUIBezierCurve.CubicBezierCurvePtNum - 1);
controlPoints[p].x -= rectTrans.rect.width * rectTrans.pivot.x;
controlPoints[p].z = 0;
}
}
}
}
public void ReferenceCUIForBCurves()
{
// compute the position ratio of this rect transform in perspective of reference rect transform
Vector3 posDeltaBetweenBottomLeftCorner = rectTrans.localPosition;// Difference between pivot
posDeltaBetweenBottomLeftCorner.x += -rectTrans.rect.width * rectTrans.pivot.x + (refCUIGraphic.rectTrans.rect.width * refCUIGraphic.rectTrans.pivot.x);
posDeltaBetweenBottomLeftCorner.y += -rectTrans.rect.height * rectTrans.pivot.y + (refCUIGraphic.rectTrans.rect.height * refCUIGraphic.rectTrans.pivot.y);
//posDeltaBetweenBottomLeftCorner.z = rectTrans.localPosition.z;
Vector3 bottomLeftPosRatio = new Vector3(posDeltaBetweenBottomLeftCorner.x / refCUIGraphic.RectTrans.rect.width, posDeltaBetweenBottomLeftCorner.y / refCUIGraphic.RectTrans.rect.height, posDeltaBetweenBottomLeftCorner.z);
Vector3 topRightPosRatio = new Vector3((posDeltaBetweenBottomLeftCorner.x + rectTrans.rect.width) / refCUIGraphic.RectTrans.rect.width, (posDeltaBetweenBottomLeftCorner.y + rectTrans.rect.height) / refCUIGraphic.RectTrans.rect.height, posDeltaBetweenBottomLeftCorner.z);
refCurves[0].ControlPoints[0] = refCUIGraphic.GetBCurveSandwichSpacePoint(bottomLeftPosRatio.x, bottomLeftPosRatio.y) - rectTrans.localPosition;
refCurves[0].ControlPoints[3] = refCUIGraphic.GetBCurveSandwichSpacePoint(topRightPosRatio.x, bottomLeftPosRatio.y) - rectTrans.localPosition;
refCurves[1].ControlPoints[0] = refCUIGraphic.GetBCurveSandwichSpacePoint(bottomLeftPosRatio.x, topRightPosRatio.y) - rectTrans.localPosition;
refCurves[1].ControlPoints[3] = refCUIGraphic.GetBCurveSandwichSpacePoint(topRightPosRatio.x, topRightPosRatio.y) - rectTrans.localPosition;
// use two sample points from the reference curves to find the second and third controls points for this curves
for (int c = 0; c < refCurves.Length; c++)
{
CUIBezierCurve curve = refCurves[c];
float yTime = c == 0 ? bottomLeftPosRatio.y : topRightPosRatio.y;
Vector3 leftPoint = refCUIGraphic.GetBCurveSandwichSpacePoint(bottomLeftPosRatio.x, yTime);
Vector3 rightPoint = refCUIGraphic.GetBCurveSandwichSpacePoint(topRightPosRatio.x, yTime);
float quarter = 0.25f,
threeQuarter = 0.75f;
Vector3 quarterPoint = refCUIGraphic.GetBCurveSandwichSpacePoint((bottomLeftPosRatio.x * 0.75f + topRightPosRatio.x * 0.25f) / 1.0f, yTime);
Vector3 threeQuaterPoint = refCUIGraphic.GetBCurveSandwichSpacePoint((bottomLeftPosRatio.x * 0.25f + topRightPosRatio.x * 0.75f) / 1.0f, yTime);
float x_1 = 3 * threeQuarter * threeQuarter * quarter, // (1 - t)(1 - t)t
y_1 = 3 * threeQuarter * quarter * quarter,
x_2 = 3 * quarter * quarter * threeQuarter,
y_2 = 3 * quarter * threeQuarter * threeQuarter;
Vector3 contant_1 = quarterPoint - Mathf.Pow(threeQuarter, 3) * leftPoint - Mathf.Pow(quarter, 3) * rightPoint,
contant_2 = threeQuaterPoint - Mathf.Pow(quarter, 3) * leftPoint - Mathf.Pow(threeQuarter, 3) * rightPoint,
p1,
p2;
solveDoubleEquationWithVector(x_1, y_1, x_2, y_2, contant_1, contant_2, out p1, out p2);
curve.ControlPoints[1] = p1 - rectTrans.localPosition;
curve.ControlPoints[2] = p2 - rectTrans.localPosition;
}
// use tangent and start and end time to derive control point 2 and 3
}
public override void ModifyMesh(Mesh _mesh)
{
if (!IsActive())
return;
using (VertexHelper vh = new VertexHelper(_mesh))
{
ModifyMesh(vh);
vh.FillMesh(_mesh);
}
}
public override void ModifyMesh(VertexHelper _vh)
{
if (!IsActive())
return;
List<UIVertex> vertexList = new List<UIVertex>();
_vh.GetUIVertexStream(vertexList);
modifyVertices(vertexList);
_vh.Clear();
_vh.AddUIVertexTriangleStream(vertexList);
}
protected virtual void modifyVertices(List<UIVertex> _verts)
{
if (!IsActive())
return;
tessellateGraphic(_verts);
if (!isCurved)
{
return;
}
for (int index = 0; index < _verts.Count; index++)
{
var uiVertex = _verts[index];
// finding the horizontal ratio position (0.0 - 1.0) of a vertex
float horRatio = (uiVertex.position.x + rectTrans.rect.width * rectTrans.pivot.x) / rectTrans.rect.width;
float verRatio = (uiVertex.position.y + rectTrans.rect.height * rectTrans.pivot.y) / rectTrans.rect.height;
//Vector3 pos = Vector3.Lerp(refCurves[0].GetPoint(horRatio), refCurves[1].GetPoint(horRatio), verRatio);
Vector3 pos = GetBCurveSandwichSpacePoint(horRatio, verRatio);
uiVertex.position.x = pos.x;
uiVertex.position.y = pos.y;
uiVertex.position.z = pos.z;
_verts[index] = uiVertex;
}
}
public void UpdateCurveControlPointPositions()
{
ReportSet();
for (int c = 0; c < refCurves.Length; c++)
{
CUIBezierCurve curve = refCurves[c];
#if UNITY_EDITOR
Undo.RecordObject(curve, "Move Rect");
#endif
for (int p = 0; p < refCurves[c].ControlPoints.Length; p++)
{
Vector3 newPt = refCurvesControlRatioPoints[c][p];
newPt.x = newPt.x * rectTrans.rect.width - rectTrans.rect.width * rectTrans.pivot.x;
newPt.y = newPt.y * rectTrans.rect.height - rectTrans.rect.height * rectTrans.pivot.y;
curve.ControlPoints[p] = newPt;
}
}
}
#endregion
// Methods that serves other objects
#region Services
public Vector3 GetBCurveSandwichSpacePoint(float _xTime, float _yTime)
{
//return Vector3.Lerp(refCurves[0].GetPoint(_xTime), refCurves[1].GetPoint(_xTime), _yTime);
return refCurves[0].GetPoint(_xTime) * (1 - _yTime) + refCurves[1].GetPoint(_xTime) * _yTime; // use a custom made lerp so that the value is not clamped between 0 and 1
}
public Vector3 GetBCurveSandwichSpaceTangent(float _xTime, float _yTime)
{
return refCurves[0].GetTangent(_xTime) * (1 - _yTime) + refCurves[1].GetTangent(_xTime) * _yTime;
}
#endregion
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e011f2cb554f96547bbfc22e5f001c17
timeCreated: 1485600090
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,165 @@
/// Credit Titinious (https://github.com/Titinious)
/// Sourced from - https://github.com/Titinious/CurlyUI
using System.Collections.Generic;
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Image))]
[AddComponentMenu("UI/Effects/Extensions/Curly UI Image")]
public class CUIImage : CUIGraphic
{
#region Nature
public static int SlicedImageCornerRefVertexIdx = 2;
public static int FilledImageCornerRefVertexIdx = 0;
/// <summary>
/// For sliced and filled image only.
/// </summary>
/// <param name="_type"></param>
/// <returns></returns>
public static int ImageTypeCornerRefVertexIdx(Image.Type _type)
{
if (_type == Image.Type.Sliced)
{
return SlicedImageCornerRefVertexIdx;
}
else
{
return FilledImageCornerRefVertexIdx;
}
}
#endregion
#region Description
[Tooltip("For changing the size of the corner for tiled or sliced Image")]
[HideInInspector]
[SerializeField]
public Vector2 cornerPosRatio = Vector2.one * -1; // -1 means unset value
[HideInInspector]
[SerializeField]
protected Vector2 oriCornerPosRatio = Vector2.one * -1;
public Vector2 OriCornerPosRatio
{
get
{
return oriCornerPosRatio;
}
}
#endregion
public Image UIImage
{
get
{
return (Image)uiGraphic;
}
}
#region Configurations
public override void ReportSet()
{
if (uiGraphic == null)
uiGraphic = GetComponent<Image>();
base.ReportSet();
}
protected override void modifyVertices(List<UIVertex> _verts)
{
if (!IsActive())
return;
if (UIImage.type == Image.Type.Filled)
{
Debug.LogWarning("Might not work well Radial Filled at the moment!");
}
else if (UIImage.type == Image.Type.Sliced || UIImage.type == Image.Type.Tiled)
{
// setting the starting cornerRatio
if (cornerPosRatio == Vector2.one * -1)
{
cornerPosRatio = _verts[ImageTypeCornerRefVertexIdx(UIImage.type)].position;
cornerPosRatio.x = (cornerPosRatio.x + rectTrans.pivot.x * rectTrans.rect.width) / rectTrans.rect.width;
cornerPosRatio.y = (cornerPosRatio.y + rectTrans.pivot.y * rectTrans.rect.height) / rectTrans.rect.height;
oriCornerPosRatio = cornerPosRatio;
}
// constraining the corner ratio
if (cornerPosRatio.x < 0)
{
cornerPosRatio.x = 0;
}
if (cornerPosRatio.x >= 0.5f)
{
cornerPosRatio.x = 0.5f;
}
if (cornerPosRatio.y < 0)
{
cornerPosRatio.y = 0;
}
if (cornerPosRatio.y >= 0.5f)
{
cornerPosRatio.y = 0.5f;
}
for (int index = 0; index < _verts.Count; index++)
{
var uiVertex = _verts[index];
// finding the horizontal ratio position (0.0 - 1.0) of a vertex
float horRatio = (uiVertex.position.x + rectTrans.rect.width * rectTrans.pivot.x) / rectTrans.rect.width;
float verRatio = (uiVertex.position.y + rectTrans.rect.height * rectTrans.pivot.y) / rectTrans.rect.height;
if (horRatio < oriCornerPosRatio.x)
{
horRatio = Mathf.Lerp(0, cornerPosRatio.x, horRatio / oriCornerPosRatio.x);
}
else if (horRatio > 1 - oriCornerPosRatio.x)
{
horRatio = Mathf.Lerp(1 - cornerPosRatio.x, 1, (horRatio - (1 - oriCornerPosRatio.x)) / oriCornerPosRatio.x);
}
else
{
horRatio = Mathf.Lerp(cornerPosRatio.x, 1 - cornerPosRatio.x, (horRatio - oriCornerPosRatio.x) / (1 - oriCornerPosRatio.x * 2));
}
if (verRatio < oriCornerPosRatio.y)
{
verRatio = Mathf.Lerp(0, cornerPosRatio.y, verRatio / oriCornerPosRatio.y);
}
else if (verRatio > 1 - oriCornerPosRatio.y)
{
verRatio = Mathf.Lerp(1 - cornerPosRatio.y, 1, (verRatio - (1 - oriCornerPosRatio.y)) / oriCornerPosRatio.y);
}
else
{
verRatio = Mathf.Lerp(cornerPosRatio.y, 1 - cornerPosRatio.y, (verRatio - oriCornerPosRatio.y) / (1 - oriCornerPosRatio.y * 2));
}
uiVertex.position.x = horRatio * rectTrans.rect.width - rectTrans.rect.width * rectTrans.pivot.x;
uiVertex.position.y = verRatio * rectTrans.rect.height - rectTrans.rect.height * rectTrans.pivot.y;
//uiVertex.position.z = pos.z;
_verts[index] = uiVertex;
}
}
base.modifyVertices(_verts);
}
#endregion
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9ab7726a352b5004cbf5f8e153868637
timeCreated: 1485600090
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
/// Credit Titinious (https://github.com/Titinious)
/// Sourced from - https://github.com/Titinious/CurlyUI
namespace UnityEngine.UI.Extensions
{
[System.Serializable]
public struct Vector3_Array2D
{
[SerializeField]
public Vector3[] array;
public Vector3 this[int _idx]
{
get
{
return array[_idx];
}
set
{
array[_idx] = value;
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2e82bd2b2afc435438d5d8d7d3459dd0
timeCreated: 1485704814
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
/// Credit Titinious (https://github.com/Titinious)
/// Sourced from - https://github.com/Titinious/CurlyUI
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Text))]
[AddComponentMenu("UI/Effects/Extensions/Curly UI Text")]
public class CUIText : CUIGraphic
{
public override void ReportSet()
{
if (uiGraphic == null)
uiGraphic = GetComponent<Text>();
base.ReportSet();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 64c40f35eca5d5d4da4eefac2a627005
timeCreated: 1485600090
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,84 @@
/// Credit Breyer
/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/#post-1777407
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(Text), typeof(RectTransform))]
[AddComponentMenu("UI/Effects/Extensions/Curved Text")]
public class CurvedText : BaseMeshEffect
{
[SerializeField]
private AnimationCurve _curveForText = AnimationCurve.Linear(0, 0, 1, 10);
public AnimationCurve CurveForText
{
get { return _curveForText; }
set { _curveForText = value; graphic.SetVerticesDirty(); }
}
[SerializeField]
private float _curveMultiplier = 1;
public float CurveMultiplier
{
get { return _curveMultiplier; }
set { _curveMultiplier = value; graphic.SetVerticesDirty(); }
}
private RectTransform rectTrans;
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
if (_curveForText[0].time != 0)
{
var tmpRect = _curveForText[0];
tmpRect.time = 0;
_curveForText.MoveKey(0, tmpRect);
}
if (rectTrans == null)
rectTrans = GetComponent<RectTransform>();
if (_curveForText[_curveForText.length - 1].time != rectTrans.rect.width)
OnRectTransformDimensionsChange();
}
#endif
protected override void Awake()
{
base.Awake();
rectTrans = GetComponent<RectTransform>();
OnRectTransformDimensionsChange();
}
protected override void OnEnable()
{
base.OnEnable();
rectTrans = GetComponent<RectTransform>();
OnRectTransformDimensionsChange();
}
public override void ModifyMesh(VertexHelper vh)
{
int count = vh.currentVertCount;
if (!IsActive() || count == 0)
{
return;
}
for (int index = 0; index < vh.currentVertCount; index++)
{
UIVertex uiVertex = new UIVertex();
vh.PopulateUIVertex(ref uiVertex, index);
uiVertex.position.y += _curveForText.Evaluate(rectTrans.rect.width * rectTrans.pivot.x + uiVertex.position.x) * _curveMultiplier;
vh.SetUIVertex(uiVertex, index);
}
}
protected override void OnRectTransformDimensionsChange()
{
if (rectTrans)
{
Keyframe tmpRect = _curveForText[_curveForText.length - 1];
tmpRect.time = rectTrans.rect.width;
_curveForText.MoveKey(_curveForText.length - 1, tmpRect);
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c38666cb4d43a304588cf0b7e5f86db6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,54 @@
/// adaption for cylindrical bending by herbst
/// Credit Breyer
/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/#post-1777407
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(Text), typeof(RectTransform))]
[AddComponentMenu("UI/Effects/Extensions/Cylinder Text")]
public class CylinderText : BaseMeshEffect
{
public float radius;
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
}
#endif
protected override void Awake()
{
base.Awake();
OnRectTransformDimensionsChange();
}
protected override void OnEnable()
{
base.OnEnable();
OnRectTransformDimensionsChange();
}
public override void ModifyMesh(VertexHelper vh)
{
if (! IsActive()) return;
int count = vh.currentVertCount;
if (!IsActive() || count == 0)
{
return;
}
for (int index = 0; index < vh.currentVertCount; index++)
{
UIVertex uiVertex = new UIVertex();
vh.PopulateUIVertex(ref uiVertex, index);
// get x position
var x = uiVertex.position.x;
// calculate bend based on pivot and radius
uiVertex.position.z = -radius * Mathf.Cos(x / radius);
uiVertex.position.x = radius * Mathf.Sin(x / radius);
vh.SetUIVertex(uiVertex, index);
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0ec526a95e7733b4396be80d3e1df80e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,119 @@
/// Credit Breyer
/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/#post-1780095
using System.Collections.Generic;
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/Gradient")]
public class Gradient : BaseMeshEffect
{
[SerializeField]
private GradientMode _gradientMode = GradientMode.Global;
[SerializeField]
private GradientDir _gradientDir = GradientDir.Vertical;
[SerializeField]
private bool _overwriteAllColor = false;
[SerializeField]
private Color _vertex1 = Color.white;
[SerializeField]
private Color _vertex2 = Color.black;
private Graphic targetGraphic;
#region Properties
public GradientMode GradientMode { get { return _gradientMode; } set { _gradientMode = value; graphic.SetVerticesDirty(); } }
public GradientDir GradientDir { get { return _gradientDir; } set { _gradientDir = value; graphic.SetVerticesDirty(); } }
public bool OverwriteAllColor { get { return _overwriteAllColor; } set { _overwriteAllColor = value; graphic.SetVerticesDirty(); } }
public Color Vertex1 { get { return _vertex1; } set { _vertex1 = value; graphic.SetAllDirty(); } }
public Color Vertex2 { get { return _vertex2; } set { _vertex2 = value; graphic.SetAllDirty(); } }
#endregion
protected override void Awake()
{
targetGraphic = GetComponent<Graphic>();
}
public override void ModifyMesh(VertexHelper vh)
{
int count = vh.currentVertCount;
if (!IsActive() || count == 0)
{
return;
}
var vertexList = new List<UIVertex>();
vh.GetUIVertexStream(vertexList);
UIVertex uiVertex = new UIVertex();
if (_gradientMode == GradientMode.Global)
{
if (_gradientDir == GradientDir.DiagonalLeftToRight || _gradientDir == GradientDir.DiagonalRightToLeft)
{
#if UNITY_EDITOR
Debug.LogWarning("Diagonal dir is not supported in Global mode");
#endif
_gradientDir = GradientDir.Vertical;
}
float bottomY = _gradientDir == GradientDir.Vertical ? vertexList[vertexList.Count - 1].position.y : vertexList[vertexList.Count - 1].position.x;
float topY = _gradientDir == GradientDir.Vertical ? vertexList[0].position.y : vertexList[0].position.x;
float uiElementHeight = topY - bottomY;
for (int i = 0; i < count; i++)
{
vh.PopulateUIVertex(ref uiVertex, i);
if (!_overwriteAllColor && uiVertex.color != targetGraphic.color)
continue;
uiVertex.color *= Color.Lerp(_vertex2, _vertex1, ((_gradientDir == GradientDir.Vertical ? uiVertex.position.y : uiVertex.position.x) - bottomY) / uiElementHeight);
vh.SetUIVertex(uiVertex, i);
}
}
else
{
for (int i = 0; i < count; i++)
{
vh.PopulateUIVertex(ref uiVertex, i);
if (!_overwriteAllColor && !CompareCarefully(uiVertex.color, targetGraphic.color))
continue;
switch (_gradientDir)
{
case GradientDir.Vertical:
uiVertex.color *= (i % 4 == 0 || (i - 1) % 4 == 0) ? _vertex1 : _vertex2;
break;
case GradientDir.Horizontal:
uiVertex.color *= (i % 4 == 0 || (i - 3) % 4 == 0) ? _vertex1 : _vertex2;
break;
case GradientDir.DiagonalLeftToRight:
uiVertex.color *= (i % 4 == 0) ? _vertex1 : ((i - 2) % 4 == 0 ? _vertex2 : Color.Lerp(_vertex2, _vertex1, 0.5f));
break;
case GradientDir.DiagonalRightToLeft:
uiVertex.color *= ((i - 1) % 4 == 0) ? _vertex1 : ((i - 3) % 4 == 0 ? _vertex2 : Color.Lerp(_vertex2, _vertex1, 0.5f));
break;
}
vh.SetUIVertex(uiVertex, i);
}
}
}
private bool CompareCarefully(Color col1, Color col2)
{
if (Mathf.Abs(col1.r - col2.r) < 0.003f && Mathf.Abs(col1.g - col2.g) < 0.003f && Mathf.Abs(col1.b - col2.b) < 0.003f && Mathf.Abs(col1.a - col2.a) < 0.003f)
return true;
return false;
}
}
public enum GradientMode
{
Global,
Local
}
public enum GradientDir
{
Vertical,
Horizontal,
DiagonalLeftToRight,
DiagonalRightToLeft
//Free
}
//enum color mode Additive, Multiply, Overwrite
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0671953a9c649e5438e4d961d1983915
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,536 @@
/// Credit Brad Nelson (playemgames - bitbucket)
/// Modified Gradient effect script from http://answers.unity3d.com/questions/1086415/gradient-text-in-unity-522-basevertexeffect-is-obs.html
/// <summary>
/// -Uses Unity's Gradient class to define the color
/// -Offset is now limited to -1,1
/// -Multiple color blend modes
///
/// Remember that for radial and diamond gradients, colors are applied per-vertex so if you have multiple points on your gradient where the color changes and there aren't enough vertices, you won't see all of the colors.
/// </summary>
using System;
using System.Collections.Generic;
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/Gradient2")]
public class Gradient2 : BaseMeshEffect
{
[SerializeField]
Type _gradientType;
[SerializeField]
Blend _blendMode = Blend.Multiply;
[SerializeField]
[Tooltip("Add vertices to display complex gradients. Turn off if your shape is already very complex, like text.")]
bool _modifyVertices = true;
[SerializeField]
[Range(-1, 1)]
float _offset = 0f;
[SerializeField]
[Range(0.1f, 10)]
float _zoom = 1f;
[SerializeField]
UnityEngine.Gradient _effectGradient = new UnityEngine.Gradient() { colorKeys = new GradientColorKey[] { new GradientColorKey(Color.black, 0), new GradientColorKey(Color.white, 1) } };
#region Properties
public Blend BlendMode
{
get { return _blendMode; }
set
{
_blendMode = value;
graphic.SetVerticesDirty();
}
}
public UnityEngine.Gradient EffectGradient
{
get { return _effectGradient; }
set
{
_effectGradient = value;
graphic.SetVerticesDirty();
}
}
public Type GradientType
{
get { return _gradientType; }
set
{
_gradientType = value;
graphic.SetVerticesDirty();
}
}
public bool ModifyVertices
{
get { return _modifyVertices; }
set
{
_modifyVertices = value;
graphic.SetVerticesDirty();
}
}
public float Offset
{
get { return _offset; }
set
{
_offset = Mathf.Clamp(value, -1f, 1f);
graphic.SetVerticesDirty();
}
}
public float Zoom
{
get { return _zoom; }
set
{
_zoom = Mathf.Clamp(value, 0.1f, 10f);
graphic.SetVerticesDirty();
}
}
#endregion
public override void ModifyMesh(VertexHelper helper)
{
if (!IsActive() || helper.currentVertCount == 0)
return;
List<UIVertex> _vertexList = new List<UIVertex>();
helper.GetUIVertexStream(_vertexList);
int nCount = _vertexList.Count;
switch (GradientType)
{
case Type.Horizontal:
case Type.Vertical:
{
Rect bounds = GetBounds(_vertexList);
float min = bounds.xMin;
float w = bounds.width;
Func<UIVertex, float> GetPosition = v => v.position.x;
if (GradientType == Type.Vertical)
{
min = bounds.yMin;
w = bounds.height;
GetPosition = v => v.position.y;
}
float width = w == 0f ? 0f : 1f / w / Zoom;
float zoomOffset = (1 - (1 / Zoom)) * 0.5f;
float offset = (Offset * (1 - zoomOffset)) - zoomOffset;
if (ModifyVertices)
{
SplitTrianglesAtGradientStops(_vertexList, bounds, zoomOffset, helper);
}
UIVertex vertex = new UIVertex();
for (int i = 0; i < helper.currentVertCount; i++)
{
helper.PopulateUIVertex(ref vertex, i);
vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate((GetPosition(vertex) - min) * width - offset));
helper.SetUIVertex(vertex, i);
}
}
break;
case Type.Diamond:
{
Rect bounds = GetBounds(_vertexList);
float height = bounds.height == 0f ? 0f : 1f / bounds.height / Zoom;
float radius = bounds.center.y / 2f;
Vector3 center = (Vector3.right + Vector3.up) * radius + Vector3.forward * _vertexList[0].position.z;
if (ModifyVertices)
{
helper.Clear();
for (int i = 0; i < nCount; i++) helper.AddVert(_vertexList[i]);
UIVertex centralVertex = new UIVertex();
centralVertex.position = center;
centralVertex.normal = _vertexList[0].normal;
centralVertex.uv0 = new Vector2(0.5f, 0.5f);
centralVertex.color = Color.white;
helper.AddVert(centralVertex);
for (int i = 1; i < nCount; i++) helper.AddTriangle(i - 1, i, nCount);
helper.AddTriangle(0, nCount - 1, nCount);
}
UIVertex vertex = new UIVertex();
for (int i = 0; i < helper.currentVertCount; i++)
{
helper.PopulateUIVertex(ref vertex, i);
vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate(
Vector3.Distance(vertex.position, center) * height - Offset));
helper.SetUIVertex(vertex, i);
}
}
break;
case Type.Radial:
{
Rect bounds = GetBounds(_vertexList);
float width = bounds.width == 0f ? 0f : 1f / bounds.width / Zoom;
float height = bounds.height == 0f ? 0f : 1f / bounds.height / Zoom;
if (ModifyVertices)
{
helper.Clear();
float radiusX = bounds.width / 2f;
float radiusY = bounds.height / 2f;
UIVertex centralVertex = new UIVertex();
centralVertex.position = Vector3.right * bounds.center.x + Vector3.up * bounds.center.y + Vector3.forward * _vertexList[0].position.z;
centralVertex.normal = _vertexList[0].normal;
centralVertex.uv0 = new Vector2(0.5f, 0.5f);
centralVertex.color = Color.white;
int steps = 64;
for (int i = 0; i < steps; i++)
{
UIVertex curVertex = new UIVertex();
float angle = (float)i * 360f / (float)steps;
float cosX = Mathf.Cos(Mathf.Deg2Rad * angle);
float cosY = Mathf.Sin(Mathf.Deg2Rad * angle);
curVertex.position = Vector3.right * cosX * radiusX + Vector3.up * cosY * radiusY + Vector3.forward * _vertexList[0].position.z;
curVertex.normal = _vertexList[0].normal;
curVertex.uv0 = new Vector2((cosX + 1) * 0.5f, (cosY + 1) * 0.5f);
curVertex.color = Color.white;
helper.AddVert(curVertex);
}
helper.AddVert(centralVertex);
for (int i = 1; i < steps; i++) helper.AddTriangle(i - 1, i, steps);
helper.AddTriangle(0, steps - 1, steps);
}
UIVertex vertex = new UIVertex();
for (int i = 0; i < helper.currentVertCount; i++)
{
helper.PopulateUIVertex(ref vertex, i);
vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate(
Mathf.Sqrt(
Mathf.Pow(Mathf.Abs(vertex.position.x - bounds.center.x) * width, 2f) +
Mathf.Pow(Mathf.Abs(vertex.position.y - bounds.center.y) * height, 2f)) * 2f - Offset));
helper.SetUIVertex(vertex, i);
}
}
break;
}
}
Rect GetBounds(List<UIVertex> vertices)
{
float left = vertices[0].position.x;
float right = left;
float bottom = vertices[0].position.y;
float top = bottom;
for (int i = vertices.Count - 1; i >= 1; --i)
{
float x = vertices[i].position.x;
float y = vertices[i].position.y;
if (x > right) right = x;
else if (x < left) left = x;
if (y > top) top = y;
else if (y < bottom) bottom = y;
}
return new Rect(left, bottom, right - left, top - bottom);
}
void SplitTrianglesAtGradientStops(List<UIVertex> _vertexList, Rect bounds, float zoomOffset, VertexHelper helper)
{
List<float> stops = FindStops(zoomOffset, bounds);
if (stops.Count > 0)
{
helper.Clear();
int nCount = _vertexList.Count;
for (int i = 0; i < nCount; i += 3)
{
float[] positions = GetPositions(_vertexList, i);
List<int> originIndices = new List<int>(3);
List<UIVertex> starts = new List<UIVertex>(3);
List<UIVertex> ends = new List<UIVertex>(2);
for (int s = 0; s < stops.Count; s++)
{
int initialCount = helper.currentVertCount;
bool hadEnds = ends.Count > 0;
bool earlyStart = false;
// find any start vertices for this stop
for (int p = 0; p < 3; p++)
{
if (!originIndices.Contains(p) && positions[p] < stops[s])
{
// make sure the first index crosses the stop
int p1 = (p + 1) % 3;
var start = _vertexList[p + i];
if (positions[p1] > stops[s])
{
originIndices.Insert(0, p);
starts.Insert(0, start);
earlyStart = true;
}
else
{
originIndices.Add(p);
starts.Add(start);
}
}
}
// bail if all before or after the stop
if (originIndices.Count == 0)
continue;
if (originIndices.Count == 3)
break;
// report any start vertices
foreach (var start in starts)
helper.AddVert(start);
// make two ends, splitting at the stop
ends.Clear();
foreach (int index in originIndices)
{
int oppositeIndex = (index + 1) % 3;
if (positions[oppositeIndex] < stops[s])
oppositeIndex = (oppositeIndex + 1) % 3;
ends.Add(CreateSplitVertex(_vertexList[index + i], _vertexList[oppositeIndex + i], stops[s]));
}
if (ends.Count == 1)
{
int oppositeIndex = (originIndices[0] + 2) % 3;
ends.Add(CreateSplitVertex(_vertexList[originIndices[0] + i], _vertexList[oppositeIndex + i], stops[s]));
}
// report end vertices
foreach (var end in ends)
helper.AddVert(end);
// make triangles
if (hadEnds)
{
helper.AddTriangle(initialCount - 2, initialCount, initialCount + 1);
helper.AddTriangle(initialCount - 2, initialCount + 1, initialCount - 1);
if (starts.Count > 0)
{
if (earlyStart)
helper.AddTriangle(initialCount - 2, initialCount + 3, initialCount);
else
helper.AddTriangle(initialCount + 1, initialCount + 3, initialCount - 1);
}
}
else
{
int vertexCount = helper.currentVertCount;
helper.AddTriangle(initialCount, vertexCount - 2, vertexCount - 1);
if (starts.Count > 1)
helper.AddTriangle(initialCount, vertexCount - 1, initialCount + 1);
}
starts.Clear();
}
// clean up after looping through gradient stops
if (ends.Count > 0)
{
// find any final vertices after the gradient stops
if (starts.Count == 0)
{
for (int p = 0; p < 3; p++)
{
if (!originIndices.Contains(p) && positions[p] > stops[stops.Count - 1])
{
int p1 = (p + 1) % 3;
UIVertex end = _vertexList[p + i];
if (positions[p1] > stops[stops.Count - 1])
starts.Insert(0, end);
else
starts.Add(end);
}
}
}
// report final vertices
foreach (var start in starts)
helper.AddVert(start);
// make final triangle(s)
int vertexCount = helper.currentVertCount;
if (starts.Count > 1)
{
helper.AddTriangle(vertexCount - 4, vertexCount - 2, vertexCount - 1);
helper.AddTriangle(vertexCount - 4, vertexCount - 1, vertexCount - 3);
}
else if (starts.Count > 0)
{
helper.AddTriangle(vertexCount - 3, vertexCount - 1, vertexCount - 2);
}
}
else
{
// if the triangle wasn't split, add it as-is
helper.AddVert(_vertexList[i]);
helper.AddVert(_vertexList[i + 1]);
helper.AddVert(_vertexList[i + 2]);
int vertexCount = helper.currentVertCount;
helper.AddTriangle(vertexCount - 3, vertexCount - 2, vertexCount - 1);
}
}
}
}
float[] GetPositions(List<UIVertex> _vertexList, int index)
{
float[] positions = new float[3];
if (GradientType == Type.Horizontal)
{
positions[0] = _vertexList[index].position.x;
positions[1] = _vertexList[index + 1].position.x;
positions[2] = _vertexList[index + 2].position.x;
}
else
{
positions[0] = _vertexList[index].position.y;
positions[1] = _vertexList[index + 1].position.y;
positions[2] = _vertexList[index + 2].position.y;
}
return positions;
}
List<float> FindStops(float zoomOffset, Rect bounds)
{
List<float> stops = new List<float>();
var offset = Offset * (1 - zoomOffset);
var startBoundary = zoomOffset - offset;
var endBoundary = (1 - zoomOffset) - offset;
foreach (var color in EffectGradient.colorKeys)
{
if (color.time >= endBoundary)
break;
if (color.time > startBoundary)
stops.Add((color.time - startBoundary) * Zoom);
}
foreach (var alpha in EffectGradient.alphaKeys)
{
if (alpha.time >= endBoundary)
break;
if (alpha.time > startBoundary)
stops.Add((alpha.time - startBoundary) * Zoom);
}
float min = bounds.xMin;
float size = bounds.width;
if (GradientType == Type.Vertical)
{
min = bounds.yMin;
size = bounds.height;
}
stops.Sort();
for (int i = 0; i < stops.Count; i++)
{
stops[i] = (stops[i] * size) + min;
if (i > 0 && Math.Abs(stops[i] - stops[i - 1]) < 2)
{
stops.RemoveAt(i);
--i;
}
}
return stops;
}
UIVertex CreateSplitVertex(UIVertex vertex1, UIVertex vertex2, float stop)
{
if (GradientType == Type.Horizontal)
{
float sx = vertex1.position.x - stop;
float dx = vertex1.position.x - vertex2.position.x;
float dy = vertex1.position.y - vertex2.position.y;
float uvx = vertex1.uv0.x - vertex2.uv0.x;
float uvy = vertex1.uv0.y - vertex2.uv0.y;
float ratio = sx / dx;
float splitY = vertex1.position.y - (dy * ratio);
UIVertex splitVertex = new UIVertex();
splitVertex.position = new Vector3(stop, splitY, vertex1.position.z);
splitVertex.normal = vertex1.normal;
splitVertex.uv0 = new Vector2(vertex1.uv0.x - (uvx * ratio), vertex1.uv0.y - (uvy * ratio));
splitVertex.color = Color.white;
return splitVertex;
}
else
{
float sy = vertex1.position.y - stop;
float dy = vertex1.position.y - vertex2.position.y;
float dx = vertex1.position.x - vertex2.position.x;
float uvx = vertex1.uv0.x - vertex2.uv0.x;
float uvy = vertex1.uv0.y - vertex2.uv0.y;
float ratio = sy / dy;
float splitX = vertex1.position.x - (dx * ratio);
UIVertex splitVertex = new UIVertex();
splitVertex.position = new Vector3(splitX, stop, vertex1.position.z);
splitVertex.normal = vertex1.normal;
splitVertex.uv0 = new Vector2(vertex1.uv0.x - (uvx * ratio), vertex1.uv0.y - (uvy * ratio));
splitVertex.color = Color.white;
return splitVertex;
}
}
Color BlendColor(Color colorA, Color colorB)
{
switch (BlendMode)
{
default: return colorB;
case Blend.Add: return colorA + colorB;
case Blend.Multiply: return colorA * colorB;
}
}
public enum Type
{
Horizontal,
Vertical,
Radial,
Diamond
}
public enum Blend
{
Override,
Add,
Multiply
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 45facfdc6a639f041b007c036dc527b8
timeCreated: 1479244798
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,168 @@
/// Credit Deeperbeige
/// Sourced from - http://forum.unity3d.com/threads/adjustable-character-spacing-free-script.288277/
/*
Produces an simple tracking/letter-spacing effect on UI Text components.
Set the spacing parameter to adjust letter spacing.
Negative values cuddle the text up tighter than normal. Go too far and it'll look odd.
Positive values spread the text out more than normal. This will NOT respect the text area you've defined.
Zero spacing will present the font with no changes.
Relies on counting off characters in your Text component's text property and
matching those against the quads passed in via the verts array. This is really
rather primitive, but I can't see any better way at the moment. It means that
all sorts of things can break the effect...
This component should be placed higher in component list than any other vertex
modifiers that alter the total number of vertices. EG, place this above Shadow
or Outline effects. If you don't, the outline/shadow won't match the position
of the letters properly. If you place the outline/shadow effect second however,
it will just work on the altered vertices from this component, and function
as expected.
This component works best if you don't allow text to automatically wrap. It also
blows up outside of the given text area. Basically, it's a cheap and dirty effect,
not a clever text layout engine. It can't affect how Unity chooses to break up
your lines. If you manually use line breaks however, it should detect those and
function more or less as you'd expect.
The spacing parameter is measured in pixels multiplied by the font size. This was
chosen such that when you adjust the font size, it does not change the visual spacing
that you've dialed in. There's also a scale factor of 1/100 in this number to
bring it into a comfortable adjustable range. There's no limit on this parameter,
but obviously some values will look quite strange.
This component doesn't really work with Rich Text. You don't need to remember to
turn off Rich Text via the checkbox, but because it can't see what makes a
printable character and what doesn't, it will typically miscount characters when you
use HTML-like tags in your text. Try it out, you'll see what I mean. It doesn't
break down entirely, but it doesn't really do what you'd want either.
*/
using System.Collections.Generic;
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/Letter Spacing")]
///Summary
/// Note, Vertex Count has changed in 5.2.1+, is now 6 (two tris) instead of 4 (tri strip).
public class LetterSpacing : BaseMeshEffect
{
[SerializeField]
private float m_spacing = 0f;
protected LetterSpacing() { }
#if UNITY_EDITOR
protected override void OnValidate()
{
spacing = m_spacing;
base.OnValidate();
}
#endif
public float spacing
{
get { return m_spacing; }
set
{
if (m_spacing == value) return;
m_spacing = value;
if (graphic != null) graphic.SetVerticesDirty();
}
}
public override void ModifyMesh(VertexHelper vh)
{
if (! IsActive()) return;
List<UIVertex> verts = new List<UIVertex>();
vh.GetUIVertexStream(verts);
Text text = GetComponent<Text>();
if (text == null)
{
Debug.LogWarning("LetterSpacing: Missing Text component");
return;
}
string[] lines = text.text.Split('\n');
Vector3 pos;
float letterOffset = spacing * (float)text.fontSize / 100f;
float alignmentFactor = 0;
int glyphIdx = 0;
switch (text.alignment)
{
case TextAnchor.LowerLeft:
case TextAnchor.MiddleLeft:
case TextAnchor.UpperLeft:
alignmentFactor = 0f;
break;
case TextAnchor.LowerCenter:
case TextAnchor.MiddleCenter:
case TextAnchor.UpperCenter:
alignmentFactor = 0.5f;
break;
case TextAnchor.LowerRight:
case TextAnchor.MiddleRight:
case TextAnchor.UpperRight:
alignmentFactor = 1f;
break;
}
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
{
string line = lines[lineIdx];
float lineOffset = (line.Length -1) * letterOffset * alignmentFactor;
for (int charIdx = 0; charIdx < line.Length; charIdx++)
{
int idx1 = glyphIdx * 6 + 0;
int idx2 = glyphIdx * 6 + 1;
int idx3 = glyphIdx * 6 + 2;
int idx4 = glyphIdx * 6 + 3;
int idx5 = glyphIdx * 6 + 4;
int idx6 = glyphIdx * 6 + 5;
// Check for truncated text (doesn't generate verts for all characters)
if (idx6 > verts.Count - 1) return;
UIVertex vert1 = verts[idx1];
UIVertex vert2 = verts[idx2];
UIVertex vert3 = verts[idx3];
UIVertex vert4 = verts[idx4];
UIVertex vert5 = verts[idx5];
UIVertex vert6 = verts[idx6];
pos = Vector3.right * (letterOffset * charIdx - lineOffset);
vert1.position += pos;
vert2.position += pos;
vert3.position += pos;
vert4.position += pos;
vert5.position += pos;
vert6.position += pos;
verts[idx1] = vert1;
verts[idx2] = vert2;
verts[idx3] = vert3;
verts[idx4] = vert4;
verts[idx5] = vert5;
verts[idx6] = vert6;
glyphIdx++;
}
// Offset for carriage return character that still generates verts
glyphIdx++;
}
vh.Clear();
vh.AddUIVertexTriangleStream(verts);
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8ee10f5b9a0e16c40b25e079c03a17a2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,190 @@
/// Credit herbst / derived from LetterSpacing by Deeperbeige
/// Sourced from - http://forum.unity3d.com/threads/adjustable-character-spacing-free-script.288277/
/*
Produces an simple mono-spacing effect on UI Text components.
Set the spacing parameter to adjust mono spacing.
Negative values cuddle the text up tighter than normal. Go too far and it'll look odd.
Positive values spread the text out more than normal. This will NOT respect the text area you've defined.
Zero spacing will present the font with no changes.
Relies on counting off characters in your Text component's text property and
matching those against the quads passed in via the verts array. This is really
rather primitive, but I can't see any better way at the moment. It means that
all sorts of things can break the effect...
This component should be placed higher in component list than any other vertex
modifiers that alter the total number of vertices. EG, place this above Shadow
or Outline effects. If you don't, the outline/shadow won't match the position
of the letters properly. If you place the outline/shadow effect second however,
it will just work on the altered vertices from this component, and function
as expected.
This component works best if you don't allow text to automatically wrap. It also
blows up outside of the given text area. Basically, it's a cheap and dirty effect,
not a clever text layout engine. It can't affect how Unity chooses to break up
your lines. If you manually use line breaks however, it should detect those and
function more or less as you'd expect.
The spacing parameter is measured in pixels multiplied by the font size. This was
chosen such that when you adjust the font size, it does not change the visual spacing
that you've dialed in. There's also a scale factor of 1/100 in this number to
bring it into a comfortable adjustable range. There's no limit on this parameter,
but obviously some values will look quite strange.
This component doesn't really work with Rich Text. You don't need to remember to
turn off Rich Text via the checkbox, but because it can't see what makes a
printable character and what doesn't, it will typically miscount characters when you
use HTML-like tags in your text. Try it out, you'll see what I mean. It doesn't
break down entirely, but it doesn't really do what you'd want either.
*/
using System.Collections.Generic;
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/Mono Spacing")]
[RequireComponent(typeof(Text))]
[RequireComponent(typeof(RectTransform))]
///Summary
/// Note, Vertex Count has changed in 5.2.1+, is now 6 (two tris) instead of 4 (tri strip).
public class MonoSpacing : BaseMeshEffect
{
[SerializeField]
private float m_spacing = 0f;
public float HalfCharWidth = 1;
public bool UseHalfCharWidth = false;
private RectTransform rectTransform;
private Text text;
protected MonoSpacing() { }
protected override void Awake()
{
text = GetComponent<Text>();
if (text == null)
{
Debug.LogWarning("MonoSpacing: Missing Text component");
return;
}
rectTransform = text.GetComponent<RectTransform>();
}
#if UNITY_EDITOR
protected override void OnValidate()
{
Spacing = m_spacing;
base.OnValidate();
}
#endif
public float Spacing
{
get { return m_spacing; }
set
{
if (m_spacing == value) return;
m_spacing = value;
if (graphic != null) graphic.SetVerticesDirty();
}
}
public override void ModifyMesh(VertexHelper vh)
{
if (! IsActive()) return;
List<UIVertex> verts = new List<UIVertex>();
vh.GetUIVertexStream(verts);
string[] lines = text.text.Split('\n');
// Vector3 pos;
float letterOffset = Spacing * (float)text.fontSize / 100f;
float alignmentFactor = 0;
int glyphIdx = 0;
switch (text.alignment)
{
case TextAnchor.LowerLeft:
case TextAnchor.MiddleLeft:
case TextAnchor.UpperLeft:
alignmentFactor = 0f;
break;
case TextAnchor.LowerCenter:
case TextAnchor.MiddleCenter:
case TextAnchor.UpperCenter:
alignmentFactor = 0.5f;
break;
case TextAnchor.LowerRight:
case TextAnchor.MiddleRight:
case TextAnchor.UpperRight:
alignmentFactor = 1f;
break;
}
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
{
string line = lines[lineIdx];
float lineOffset = (line.Length - 1) * letterOffset * (alignmentFactor) - (alignmentFactor - 0.5f) * rectTransform.rect.width;
var offsetX = -lineOffset + letterOffset / 2 * (1 - alignmentFactor * 2);
for (int charIdx = 0; charIdx < line.Length; charIdx++)
{
int idx1 = glyphIdx * 6 + 0;
int idx2 = glyphIdx * 6 + 1;
int idx3 = glyphIdx * 6 + 2;
int idx4 = glyphIdx * 6 + 3;
int idx5 = glyphIdx * 6 + 4;
int idx6 = glyphIdx * 6 + 5;
// Check for truncated text (doesn't generate verts for all characters)
if (idx6 > verts.Count - 1) return;
UIVertex vert1 = verts[idx1];
UIVertex vert2 = verts[idx2];
UIVertex vert3 = verts[idx3];
UIVertex vert4 = verts[idx4];
UIVertex vert5 = verts[idx5];
UIVertex vert6 = verts[idx6];
// pos = Vector3.right * (letterOffset * (charIdx) - lineOffset);
float charWidth = (vert2.position - vert1.position).x;
var smallChar = UseHalfCharWidth && (charWidth < HalfCharWidth);
var smallCharOffset = smallChar ? -letterOffset/4 : 0;
vert1.position += new Vector3(-vert1.position.x + offsetX + -.5f * charWidth + smallCharOffset, 0, 0);
vert2.position += new Vector3(-vert2.position.x + offsetX + .5f * charWidth + smallCharOffset, 0, 0);
vert3.position += new Vector3(-vert3.position.x + offsetX + .5f * charWidth + smallCharOffset, 0, 0);
vert4.position += new Vector3(-vert4.position.x + offsetX + .5f * charWidth + smallCharOffset, 0, 0);
vert5.position += new Vector3(-vert5.position.x + offsetX + -.5f * charWidth + smallCharOffset, 0, 0);
vert6.position += new Vector3(-vert6.position.x + offsetX + -.5f * charWidth + smallCharOffset, 0, 0);
if (smallChar)
offsetX += letterOffset / 2;
else
offsetX += letterOffset;
verts[idx1] = vert1;
verts[idx2] = vert2;
verts[idx3] = vert3;
verts[idx4] = vert4;
verts[idx5] = vert5;
verts[idx6] = vert6;
glyphIdx++;
}
// Offset for carriage return character that still generates verts
glyphIdx++;
}
vh.Clear();
vh.AddUIVertexTriangleStream(verts);
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 97a58789aa01843488ef44dc747ee8e8
timeCreated: 1490183235
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,190 @@
/// Credit Melang
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
using System.Collections.Generic;
namespace UnityEngine.UI.Extensions
{
//An outline that looks a bit nicer than the default one. It has less "holes" in the outline by drawing more copies of the effect
[AddComponentMenu("UI/Effects/Extensions/Nicer Outline")]
public class NicerOutline : BaseMeshEffect
{
[SerializeField]
private Color m_EffectColor = new Color (0f, 0f, 0f, 0.5f);
[SerializeField]
private Vector2 m_EffectDistance = new Vector2 (1f, -1f);
[SerializeField]
private bool m_UseGraphicAlpha = true;
private List < UIVertex > m_Verts = new List<UIVertex>();
//
// Properties
//
public Color effectColor
{
get
{
return this.m_EffectColor;
}
set
{
this.m_EffectColor = value;
if (base.graphic != null)
{
base.graphic.SetVerticesDirty ();
}
}
}
public Vector2 effectDistance
{
get
{
return this.m_EffectDistance;
}
set
{
if (value.x > 600f)
{
value.x = 600f;
}
if (value.x < -600f)
{
value.x = -600f;
}
if (value.y > 600f)
{
value.y = 600f;
}
if (value.y < -600f)
{
value.y = -600f;
}
if (this.m_EffectDistance == value)
{
return;
}
this.m_EffectDistance = value;
if (base.graphic != null)
{
base.graphic.SetVerticesDirty ();
}
}
}
public bool useGraphicAlpha
{
get
{
return this.m_UseGraphicAlpha;
}
set
{
this.m_UseGraphicAlpha = value;
if (base.graphic != null)
{
base.graphic.SetVerticesDirty ();
}
}
}
protected void ApplyShadowZeroAlloc(List<UIVertex> verts, Color32 color, int start, int end, float x, float y)
{
UIVertex vt;
var neededCpacity = verts.Count * 2;
if (verts.Capacity < neededCpacity)
verts.Capacity = neededCpacity;
for (int i = start; i < end; ++i)
{
vt = verts[i];
verts.Add(vt);
Vector3 v = vt.position;
v.x += x;
v.y += y;
vt.position = v;
var newColor = color;
if (m_UseGraphicAlpha)
newColor.a = (byte)((newColor.a * verts[i].color.a) / 255);
vt.color = newColor;
verts[i] = vt;
}
}
protected void ApplyShadow(List<UIVertex> verts, Color32 color, int start, int end, float x, float y)
{
var neededCpacity = verts.Count * 2;
if (verts.Capacity < neededCpacity)
verts.Capacity = neededCpacity;
ApplyShadowZeroAlloc(verts, color, start, end, x, y);
}
public override void ModifyMesh(VertexHelper vh)
{
if (!this.IsActive ())
{
return;
}
m_Verts.Clear();
vh.GetUIVertexStream(m_Verts);
Text foundtext = GetComponent<Text>();
float best_fit_adjustment = 1f;
if (foundtext && foundtext.resizeTextForBestFit)
{
best_fit_adjustment = (float)foundtext.cachedTextGenerator.fontSizeUsedForBestFit / (foundtext.resizeTextMaxSize-1); //max size seems to be exclusive
}
float distanceX = this.effectDistance.x * best_fit_adjustment;
float distanceY = this.effectDistance.y * best_fit_adjustment;
int start = 0;
int count = m_Verts.Count;
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, distanceX, distanceY);
start = count;
count = m_Verts.Count;
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, distanceX, -distanceY);
start = count;
count = m_Verts.Count;
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, -distanceX, distanceY);
start = count;
count = m_Verts.Count;
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, -distanceX, -distanceY);
start = count;
count = m_Verts.Count;
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, distanceX, 0);
start = count;
count = m_Verts.Count;
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, -distanceX, 0);
start = count;
count = m_Verts.Count;
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, 0, distanceY);
start = count;
count = m_Verts.Count;
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, 0, -distanceY);
vh.Clear();
vh.AddUIVertexTriangleStream(m_Verts);
}
#if UNITY_EDITOR
protected override void OnValidate ()
{
this.effectDistance = this.m_EffectDistance;
base.OnValidate ();
}
#endif
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: db125c7de00668f4e98849d0aaf366d7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,125 @@
/// Credit senritsu
/// Sourced from - https://github.com/senritsu/unitility/blob/master/Assets/Unitility/GUI/RaycastMask.cs
/***************************************************************************\
The MIT License (MIT)
Copyright (c) 2014 Jonas Schiegl (https://github.com/senritsu)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
\***************************************************************************/
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Image))]
[AddComponentMenu("UI/Extensions/Raycast Mask")]
public class RaycastMask : MonoBehaviour, ICanvasRaycastFilter
{
private Image _image;
private Sprite _sprite;
void Start()
{
_image = GetComponent<Image>();
}
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
_sprite = _image.sprite;
var rectTransform = (RectTransform)transform;
Vector2 localPositionPivotRelative;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, sp, eventCamera, out localPositionPivotRelative);
// convert to bottom-left origin coordinates
var localPosition = new Vector2(localPositionPivotRelative.x + rectTransform.pivot.x * rectTransform.rect.width,
localPositionPivotRelative.y + rectTransform.pivot.y * rectTransform.rect.height);
var spriteRect = _sprite.textureRect;
var maskRect = rectTransform.rect;
var x = 0;
var y = 0;
// convert to texture space
switch (_image.type)
{
case Image.Type.Sliced:
{
var border = _sprite.border;
// x slicing
if (localPosition.x < border.x)
{
x = Mathf.FloorToInt(spriteRect.x + localPosition.x);
}
else if (localPosition.x > maskRect.width - border.z)
{
x = Mathf.FloorToInt(spriteRect.x + spriteRect.width - (maskRect.width - localPosition.x));
}
else
{
x = Mathf.FloorToInt(spriteRect.x + border.x +
((localPosition.x - border.x) /
(maskRect.width - border.x - border.z)) *
(spriteRect.width - border.x - border.z));
}
// y slicing
if (localPosition.y < border.y)
{
y = Mathf.FloorToInt(spriteRect.y + localPosition.y);
}
else if (localPosition.y > maskRect.height - border.w)
{
y = Mathf.FloorToInt(spriteRect.y + spriteRect.height - (maskRect.height - localPosition.y));
}
else
{
y = Mathf.FloorToInt(spriteRect.y + border.y +
((localPosition.y - border.y) /
(maskRect.height - border.y - border.w)) *
(spriteRect.height - border.y - border.w));
}
}
break;
case Image.Type.Simple:
default:
{
// conversion to uniform UV space
x = Mathf.FloorToInt(spriteRect.x + spriteRect.width * localPosition.x / maskRect.width);
y = Mathf.FloorToInt(spriteRect.y + spriteRect.height * localPosition.y / maskRect.height);
}
break;
}
// destroy component if texture import settings are wrong
try
{
return _sprite.texture.GetPixel(x, y).a > 0;
}
catch (UnityException)
{
Debug.LogWarning("Mask texture not readable, set your sprite to Texture Type 'Advanced' and check 'Read/Write Enabled'");
Destroy(this);
return false;
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 22757922dd9d4064d8186fbef72b0772
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f9656bd8c19a5a74c90babab7228f771
folderAsset: yes
timeCreated: 1467468503
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
/// Credit 00christian00
/// Sourced from - http://forum.unity3d.com/threads/any-way-to-show-part-of-an-image-without-using-mask.360085/#post-2332030
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/UIAdditiveEffect")]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
public class UIAdditiveEffect : MonoBehaviour
{
MaskableGraphic mGraphic;
// Use this for initialization
void Start()
{
SetMaterial();
}
public void SetMaterial()
{
mGraphic = this.GetComponent<MaskableGraphic>();
if (mGraphic != null)
{
if (mGraphic.material == null || mGraphic.material.name == "Default UI Material")
{
//Applying default material with UI Image Crop shader
mGraphic.material = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/UIAdditive"));
}
}
else
{
Debug.LogError("Please attach component to a Graphical UI component");
}
}
public void OnValidate()
{
SetMaterial();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7a29c8587a101744ea9e6198d89cb2df
timeCreated: 1464643709
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,70 @@
/// Credit 00christian00
/// Sourced from - http://forum.unity3d.com/threads/any-way-to-show-part-of-an-image-without-using-mask.360085/#post-2332030
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/UIImageCrop")]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
public class UIImageCrop : MonoBehaviour
{
MaskableGraphic mGraphic;
Material mat;
int XCropProperty, YCropProperty;
public float XCrop = 0f;
public float YCrop = 0f;
// Use this for initialization
void Start()
{
SetMaterial();
}
public void SetMaterial()
{
mGraphic = this.GetComponent<MaskableGraphic>();
XCropProperty = Shader.PropertyToID("_XCrop");
YCropProperty = Shader.PropertyToID("_YCrop");
if (mGraphic != null)
{
if (mGraphic.material == null || mGraphic.material.name == "Default UI Material")
{
//Applying default material with UI Image Crop shader
mGraphic.material = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/UI Image Crop"));
}
mat = mGraphic.material;
}
else
{
Debug.LogError("Please attach component to a Graphical UI component");
}
}
public void OnValidate()
{
SetMaterial();
SetXCrop(XCrop);
SetYCrop(YCrop);
}
/// <summary>
/// Set the x crop factor, with x being a normalized value 0-1f.
/// </summary>
/// <param name="xcrop"></param>
public void SetXCrop(float xcrop)
{
XCrop = Mathf.Clamp01(xcrop);
mat.SetFloat(XCropProperty, XCrop);
}
/// <summary>
/// Set the y crop factor, with y being a normalized value 0-1f.
/// </summary>
/// <param name="ycrop"></param>
public void SetYCrop(float ycrop)
{
YCrop = Mathf.Clamp01(ycrop);
mat.SetFloat(YCropProperty, YCrop);
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 022c3983095dce44c9504739a8ed7324
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,41 @@
/// Credit 00christian00
/// Sourced from - http://forum.unity3d.com/threads/any-way-to-show-part-of-an-image-without-using-mask.360085/#post-2332030
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/UILinearDodgeEffect")]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
public class UILinearDodgeEffect : MonoBehaviour
{
MaskableGraphic mGraphic;
// Use this for initialization
void Start()
{
SetMaterial();
}
public void SetMaterial()
{
mGraphic = this.GetComponent<MaskableGraphic>();
if (mGraphic != null)
{
if (mGraphic.material == null || mGraphic.material.name == "Default UI Material")
{
//Applying default material with UI Image Crop shader
mGraphic.material = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/UILinearDodge"));
}
}
else
{
Debug.LogError("Please attach component to a Graphical UI component");
}
}
public void OnValidate()
{
SetMaterial();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b4fbdc2185cba1c42ad07e43eea19561
timeCreated: 1464643896
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
/// Credit 00christian00
/// Sourced from - http://forum.unity3d.com/threads/any-way-to-show-part-of-an-image-without-using-mask.360085/#post-2332030
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/UIMultiplyEffect")]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
public class UIMultiplyEffect : MonoBehaviour
{
MaskableGraphic mGraphic;
// Use this for initialization
void Start()
{
SetMaterial();
}
public void SetMaterial()
{
mGraphic = this.GetComponent<MaskableGraphic>();
if (mGraphic != null)
{
if (mGraphic.material == null || mGraphic.material.name == "Default UI Material")
{
//Applying default material with UI Image Crop shader
mGraphic.material = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/UIMultiply"));
}
}
else
{
Debug.LogError("Please attach component to a Graphical UI component");
}
}
public void OnValidate()
{
SetMaterial();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3a1216dfb98544e44afb7fb3abc093f2
timeCreated: 1464643921
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
/// Credit 00christian00
/// Sourced from - http://forum.unity3d.com/threads/any-way-to-show-part-of-an-image-without-using-mask.360085/#post-2332030
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/UIScreenEffect")]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
public class UIScreenEffect : MonoBehaviour
{
MaskableGraphic mGraphic;
// Use this for initialization
void Start()
{
SetMaterial();
}
public void SetMaterial()
{
mGraphic = this.GetComponent<MaskableGraphic>();
if (mGraphic != null)
{
if (mGraphic.material == null || mGraphic.material.name == "Default UI Material")
{
//Applying default material with UI Image Crop shader
mGraphic.material = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/UIScreen"));
}
}
else
{
Debug.LogError("Please attach component to a Graphical UI component");
}
}
public void OnValidate()
{
SetMaterial();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 07afba72913387d488019cbb35ec1965
timeCreated: 1464643319
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
/// Credit 00christian00
/// Sourced from - http://forum.unity3d.com/threads/any-way-to-show-part-of-an-image-without-using-mask.360085/#post-2332030
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/UISoftAdditiveEffect")]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
public class UISoftAdditiveEffect : MonoBehaviour
{
MaskableGraphic mGraphic;
// Use this for initialization
void Start()
{
SetMaterial();
}
public void SetMaterial()
{
mGraphic = this.GetComponent<MaskableGraphic>();
if (mGraphic != null)
{
if (mGraphic.material == null || mGraphic.material.name == "Default UI Material")
{
//Applying default material with UI Image Crop shader
mGraphic.material = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/UISoftAdditive"));
}
}
else
{
Debug.LogError("Please attach component to a Graphical UI component");
}
}
public void OnValidate()
{
SetMaterial();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 692867a1eddc7df419ec15b05b4084ec
timeCreated: 1464643947
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,95 @@
/// Credit ömer faruk sayılır
/// Sourced from - https://bitbucket.org/snippets/Lordinarius/nrn4L
namespace UnityEngine.UI.Extensions
{
public class ShineEffect : MaskableGraphic
{
[SerializeField]
float yoffset = -1;
public float Yoffset
{
get
{
return yoffset;
}
set
{
SetVerticesDirty();
yoffset = value;
}
}
[SerializeField]
float width = 1;
public float Width
{
get
{
return width;
}
set
{
SetAllDirty();
width = value;
}
}
protected override void OnPopulateMesh(VertexHelper vh)
{
var r = GetPixelAdjustedRect();
var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
float dif = (v.w - v.y) * 2;
Color32 color32 = color;
vh.Clear();
color32.a = (byte)0;
vh.AddVert(new Vector3(v.x - 50, width * v.y + yoffset * dif), color32, new Vector2(0f, 0f));
vh.AddVert(new Vector3(v.z + 50, width * v.y + yoffset * dif), color32, new Vector2(1f, 0f));
color32.a = (byte)(color.a * 255);
vh.AddVert(new Vector3(v.x - 50, width * (v.y / 4) + yoffset * dif), color32, new Vector2(0f, 1f));
vh.AddVert(new Vector3(v.z + 50, width * (v.y / 4) + yoffset * dif), color32, new Vector2(1f, 1f));
color32.a = (byte)(color.a * 255);
vh.AddVert(new Vector3(v.x - 50, width * (v.w / 4) + yoffset * dif), color32, new Vector2(0f, 1f));
vh.AddVert(new Vector3(v.z + 50, width * (v.w / 4) + yoffset * dif), color32, new Vector2(1f, 1f));
color32.a = (byte)(color.a * 255);
color32.a = (byte)0;
vh.AddVert(new Vector3(v.x - 50, width * v.w + yoffset * dif), color32, new Vector2(0f, 1f));
vh.AddVert(new Vector3(v.z + 50, width * v.w + yoffset * dif), color32, new Vector2(1f, 1f));
vh.AddTriangle(0, 1, 2);
vh.AddTriangle(2, 3, 1);
vh.AddTriangle(2, 3, 4);
vh.AddTriangle(4, 5, 3);
vh.AddTriangle(4, 5, 6);
vh.AddTriangle(6, 7, 5);
}
public void Triangulate(VertexHelper vh)
{
int triangleCount = vh.currentVertCount - 2;
Debug.Log(triangleCount);
for (int i = 0; i <= triangleCount / 2 + 1; i += 2)
{
vh.AddTriangle(i, i + 1, i + 2);
vh.AddTriangle(i + 2, i + 3, i + 1);
}
}
#if UNITY_EDITOR
public override void OnRebuildRequested()
{
base.OnRebuildRequested();
}
#endif
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 453baf32313c0bc41a532c409ec25177
timeCreated: 1464388954
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,115 @@
/// Credit ömer faruk sayılır
/// Sourced from - https://bitbucket.org/snippets/Lordinarius/nrn4L
namespace UnityEngine.UI.Extensions
{
[ExecuteInEditMode, RequireComponent(typeof(Image))]
[AddComponentMenu("UI/Effects/Extensions/Shining Effect")]
public class ShineEffector : MonoBehaviour
{
public ShineEffect effector;
[SerializeField, HideInInspector]
GameObject effectRoot;
[Range(-1, 1)]
public float yOffset = -1;
public float YOffset
{
get
{
return yOffset;
}
set
{
ChangeVal(value);
yOffset = value;
}
}
[Range(0.1f, 1)]
public float width = 0.5f;
RectTransform effectorRect;
void OnEnable()
{
if (effector == null)
{
GameObject effectorobj = new GameObject("effector");
effectRoot = new GameObject("ShineEffect");
effectRoot.transform.SetParent(this.transform);
effectRoot.AddComponent<Image>().sprite = gameObject.GetComponent<Image>().sprite;
effectRoot.GetComponent<Image>().type = gameObject.GetComponent<Image>().type;
effectRoot.AddComponent<Mask>().showMaskGraphic = false;
effectRoot.transform.localScale = Vector3.one;
effectRoot.GetComponent<RectTransform>().anchoredPosition3D = Vector3.zero;
effectRoot.GetComponent<RectTransform>().anchorMax = Vector2.one;
effectRoot.GetComponent<RectTransform>().anchorMin = Vector2.zero;
effectRoot.GetComponent<RectTransform>().offsetMax = Vector2.zero;
effectRoot.GetComponent<RectTransform>().offsetMin = Vector2.zero;
effectRoot.transform.SetAsFirstSibling();
effectorobj.AddComponent<RectTransform>();
effectorobj.transform.SetParent(effectRoot.transform);
effectorRect = effectorobj.GetComponent<RectTransform>();
effectorRect.localScale = Vector3.one;
effectorRect.anchoredPosition3D = Vector3.zero;
effectorRect.gameObject.AddComponent<ShineEffect>();
effectorRect.anchorMax = Vector2.one;
effectorRect.anchorMin = Vector2.zero;
effectorRect.Rotate(0, 0, -8);
effector = effectorobj.GetComponent<ShineEffect>();
effectorRect.offsetMax = Vector2.zero;
effectorRect.offsetMin = Vector2.zero;
OnValidate();
}
}
void OnValidate()
{
effector.Yoffset = yOffset;
effector.Width = width;
if (yOffset <= -1 || yOffset >= 1)
{
effectRoot.SetActive(false);
}
else if (!effectRoot.activeSelf)
{
effectRoot.SetActive(true);
}
{
}
}
void ChangeVal(float value)
{
effector.Yoffset = value;
if (value <= -1 || value >= 1)
{
effectRoot.SetActive(false);
}
else if (!effectRoot.activeSelf)
{
effectRoot.SetActive(true);
}
{
}
}
void OnDestroy()
{
if (!Application.isPlaying)
{
DestroyImmediate(effectRoot);
}
else
{
Destroy(effectRoot);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ced63edd65f3aed41a6c4125a5f54217
timeCreated: 1464388991
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,112 @@
/// Credit NemoKrad (aka Charles Humphrey) / valtain
/// Sourced from - http://www.randomchaos.co.uk/SoftAlphaUIMask.aspx
/// Updated by valtain - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/pull-requests/33
namespace UnityEngine.UI.Extensions
{
[ExecuteInEditMode]
[AddComponentMenu("UI/Effects/Extensions/SoftMaskScript")]
public class SoftMaskScript : MonoBehaviour
{
Material mat;
Canvas cachedCanvas = null;
Transform cachedCanvasTransform = null;
readonly Vector3[] m_WorldCorners = new Vector3[4];
readonly Vector3[] m_CanvasCorners = new Vector3[4];
[Tooltip("The area that is to be used as the container.")]
public RectTransform MaskArea;
[Tooltip("Texture to be used to do the soft alpha")]
public Texture AlphaMask;
[Tooltip("At what point to apply the alpha min range 0-1")]
[Range(0, 1)]
public float CutOff = 0;
[Tooltip("Implement a hard blend based on the Cutoff")]
public bool HardBlend = false;
[Tooltip("Flip the masks alpha value")]
public bool FlipAlphaMask = false;
[Tooltip("If a different Mask Scaling Rect is given, and this value is true, the area around the mask will not be clipped")]
public bool DontClipMaskScalingRect = false;
Vector2 maskOffset = Vector2.zero;
Vector2 maskScale = Vector2.one;
// Use this for initialization
void Start()
{
if (MaskArea == null)
{
MaskArea = GetComponent<RectTransform>();
}
var text = GetComponent<Text>();
if (text != null)
{
mat = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/SoftMaskShader"));
text.material = mat;
cachedCanvas = text.canvas;
cachedCanvasTransform = cachedCanvas.transform;
// For some reason, having the mask control on the parent and disabled stops the mouse interacting
// with the texture layer that is not visible.. Not needed for the Image.
if (transform.parent.GetComponent<Mask>() == null)
transform.parent.gameObject.AddComponent<Mask>();
transform.parent.GetComponent<Mask>().enabled = false;
return;
}
var graphic = GetComponent<Graphic>();
if (graphic != null)
{
mat = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/SoftMaskShader"));
graphic.material = mat;
cachedCanvas = graphic.canvas;
cachedCanvasTransform = cachedCanvas.transform;
}
}
void Update()
{
if (cachedCanvas != null)
{
SetMask();
}
}
void SetMask()
{
var worldRect = GetCanvasRect();
var size = worldRect.size;
maskScale.Set(1.0f / size.x, 1.0f / size.y);
maskOffset = -worldRect.min;
maskOffset.Scale(maskScale);
mat.SetTextureOffset("_AlphaMask", maskOffset);
mat.SetTextureScale("_AlphaMask", maskScale);
mat.SetTexture("_AlphaMask", AlphaMask);
mat.SetFloat("_HardBlend", HardBlend ? 1 : 0);
mat.SetInt("_FlipAlphaMask", FlipAlphaMask ? 1 : 0);
mat.SetInt("_NoOuterClip", DontClipMaskScalingRect ? 1 : 0);
mat.SetFloat("_CutOff", CutOff);
}
public Rect GetCanvasRect()
{
if (cachedCanvas == null)
return new Rect();
MaskArea.GetWorldCorners(m_WorldCorners);
for (int i = 0; i < 4; ++i)
m_CanvasCorners[i] = cachedCanvasTransform.InverseTransformPoint(m_WorldCorners[i]);
return new Rect(m_CanvasCorners[0].x, m_CanvasCorners[0].y, m_CanvasCorners[2].x - m_CanvasCorners[0].x, m_CanvasCorners[2].y - m_CanvasCorners[0].y);
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b8ee60af491978345bc197ed4e1316bc
timeCreated: 1448034177
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,78 @@
/// Credit ChoMPHi
/// Sourced from - http://forum.unity3d.com/threads/script-flippable-for-ui-graphics.291711/
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(RectTransform), typeof(Graphic)), DisallowMultipleComponent]
[AddComponentMenu("UI/Effects/Extensions/Flippable")]
public class UIFlippable : BaseMeshEffect
{
[SerializeField] private bool m_Horizontal = false;
[SerializeField] private bool m_Veritical = false;
#if UNITY_EDITOR
protected override void Awake()
{
OnValidate();
}
#endif
/// <summary>
/// Gets or sets a value indicating whether this <see cref="UnityEngine.UI.UIFlippable"/> should be flipped horizontally.
/// </summary>
/// <value><c>true</c> if horizontal; otherwise, <c>false</c>.</value>
public bool horizontal
{
get { return this.m_Horizontal; }
set { this.m_Horizontal = value; }
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="UnityEngine.UI.UIFlippable"/> should be flipped vertically.
/// </summary>
/// <value><c>true</c> if vertical; otherwise, <c>false</c>.</value>
public bool vertical
{
get { return this.m_Veritical; }
set { this.m_Veritical = value; }
}
public override void ModifyMesh(VertexHelper verts)
{
RectTransform rt = this.transform as RectTransform;
for (int i = 0; i < verts.currentVertCount; ++i)
{
UIVertex uiVertex = new UIVertex();
verts.PopulateUIVertex(ref uiVertex,i);
// Modify positions
uiVertex.position = new Vector3(
(this.m_Horizontal ? (uiVertex.position.x + (rt.rect.center.x - uiVertex.position.x) * 2) : uiVertex.position.x),
(this.m_Veritical ? (uiVertex.position.y + (rt.rect.center.y - uiVertex.position.y) * 2) : uiVertex.position.y),
uiVertex.position.z
);
// Apply
verts.SetUIVertex(uiVertex, i);
}
}
#if UNITY_EDITOR
protected override void OnValidate()
{
var components = gameObject.GetComponents(typeof(BaseMeshEffect));
foreach (var comp in components)
{
if (comp.GetType() != typeof(UIFlippable))
{
UnityEditorInternal.ComponentUtility.MoveComponentUp(this);
}
else break;
}
this.GetComponent<Graphic>().SetVerticesDirty();
base.OnValidate();
}
#endif
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 67f304b9bd84e9848bcfb79f47790081
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,410 @@
/// Credit glennpow, Zarlang
/// Sourced from - http://forum.unity3d.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/
/// Updated by Zarlang with a more robust implementation, including TextureSheet animation support
namespace UnityEngine.UI.Extensions
{
#if UNITY_5_3_OR_NEWER
[ExecuteInEditMode]
[RequireComponent(typeof(CanvasRenderer), typeof(ParticleSystem))]
[AddComponentMenu("UI/Effects/Extensions/UIParticleSystem")]
public class UIParticleSystem : MaskableGraphic
{
[Tooltip("Having this enabled run the system in LateUpdate rather than in Update making it faster but less precise (more clunky)")]
public bool fixedTime = true;
[Tooltip("Enables 3d rotation for the particles")]
public bool use3dRotation = false;
private Transform _transform;
private ParticleSystem pSystem;
private ParticleSystem.Particle[] particles;
private UIVertex[] _quad = new UIVertex[4];
private Vector4 imageUV = Vector4.zero;
private ParticleSystem.TextureSheetAnimationModule textureSheetAnimation;
private int textureSheetAnimationFrames;
private Vector2 textureSheetAnimationFrameSize;
private ParticleSystemRenderer pRenderer;
private bool isInitialised = false;
private Material currentMaterial;
private Texture currentTexture;
#if UNITY_5_5_OR_NEWER
private ParticleSystem.MainModule mainModule;
#endif
public override Texture mainTexture
{
get
{
return currentTexture;
}
}
protected bool Initialize()
{
// initialize members
if (_transform == null)
{
_transform = transform;
}
if (pSystem == null)
{
pSystem = GetComponent<ParticleSystem>();
if (pSystem == null)
{
return false;
}
#if UNITY_5_5_OR_NEWER
mainModule = pSystem.main;
if (pSystem.main.maxParticles > 14000)
{
mainModule.maxParticles = 14000;
}
#else
if (pSystem.maxParticles > 14000)
pSystem.maxParticles = 14000;
#endif
pRenderer = pSystem.GetComponent<ParticleSystemRenderer>();
if (pRenderer != null)
pRenderer.enabled = false;
if (material == null)
{
var foundShader = ShaderLibrary.GetShaderInstance("UI Extensions/Particles/Additive");
if (foundShader)
{
material = new Material(foundShader);
}
}
currentMaterial = material;
if (currentMaterial && currentMaterial.HasProperty("_MainTex"))
{
currentTexture = currentMaterial.mainTexture;
if (currentTexture == null)
currentTexture = Texture2D.whiteTexture;
}
material = currentMaterial;
// automatically set scaling
#if UNITY_5_5_OR_NEWER
mainModule.scalingMode = ParticleSystemScalingMode.Hierarchy;
#else
pSystem.scalingMode = ParticleSystemScalingMode.Hierarchy;
#endif
particles = null;
}
#if UNITY_5_5_OR_NEWER
if (particles == null)
particles = new ParticleSystem.Particle[pSystem.main.maxParticles];
#else
if (particles == null)
particles = new ParticleSystem.Particle[pSystem.maxParticles];
#endif
imageUV = new Vector4(0, 0, 1, 1);
// prepare texture sheet animation
textureSheetAnimation = pSystem.textureSheetAnimation;
textureSheetAnimationFrames = 0;
textureSheetAnimationFrameSize = Vector2.zero;
if (textureSheetAnimation.enabled)
{
textureSheetAnimationFrames = textureSheetAnimation.numTilesX * textureSheetAnimation.numTilesY;
textureSheetAnimationFrameSize = new Vector2(1f / textureSheetAnimation.numTilesX, 1f / textureSheetAnimation.numTilesY);
}
return true;
}
protected override void Awake()
{
base.Awake();
if (!Initialize())
enabled = false;
}
protected override void OnPopulateMesh(VertexHelper vh)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
if (!Initialize())
{
return;
}
}
#endif
// prepare vertices
vh.Clear();
if (!gameObject.activeInHierarchy)
{
return;
}
if (!isInitialised && !pSystem.main.playOnAwake)
{
pSystem.Stop(false, ParticleSystemStopBehavior.StopEmittingAndClear);
isInitialised = true;
}
Vector2 temp = Vector2.zero;
Vector2 corner1 = Vector2.zero;
Vector2 corner2 = Vector2.zero;
// iterate through current particles
int count = pSystem.GetParticles(particles);
for (int i = 0; i < count; ++i)
{
ParticleSystem.Particle particle = particles[i];
// get particle properties
#if UNITY_5_5_OR_NEWER
Vector2 position = (mainModule.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
#else
Vector2 position = (pSystem.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
#endif
float rotation = -particle.rotation * Mathf.Deg2Rad;
float rotation90 = rotation + Mathf.PI / 2;
Color32 color = particle.GetCurrentColor(pSystem);
float size = particle.GetCurrentSize(pSystem) * 0.5f;
// apply scale
#if UNITY_5_5_OR_NEWER
if (mainModule.scalingMode == ParticleSystemScalingMode.Shape)
position /= canvas.scaleFactor;
#else
if (pSystem.scalingMode == ParticleSystemScalingMode.Shape)
position /= canvas.scaleFactor;
#endif
// apply texture sheet animation
Vector4 particleUV = imageUV;
if (textureSheetAnimation.enabled)
{
#if UNITY_5_5_OR_NEWER
float frameProgress = 1 - (particle.remainingLifetime / particle.startLifetime);
if (textureSheetAnimation.frameOverTime.curveMin != null)
{
frameProgress = textureSheetAnimation.frameOverTime.curveMin.Evaluate(1 - (particle.remainingLifetime / particle.startLifetime));
}
else if (textureSheetAnimation.frameOverTime.curve != null)
{
frameProgress = textureSheetAnimation.frameOverTime.curve.Evaluate(1 - (particle.remainingLifetime / particle.startLifetime));
}
else if (textureSheetAnimation.frameOverTime.constant > 0)
{
frameProgress = textureSheetAnimation.frameOverTime.constant - (particle.remainingLifetime / particle.startLifetime);
}
#else
float frameProgress = 1 - (particle.lifetime / particle.startLifetime);
#endif
frameProgress = Mathf.Repeat(frameProgress * textureSheetAnimation.cycleCount, 1);
int frame = 0;
switch (textureSheetAnimation.animation)
{
case ParticleSystemAnimationType.WholeSheet:
frame = Mathf.FloorToInt(frameProgress * textureSheetAnimationFrames);
break;
case ParticleSystemAnimationType.SingleRow:
frame = Mathf.FloorToInt(frameProgress * textureSheetAnimation.numTilesX);
int row = textureSheetAnimation.rowIndex;
#if UNITY_2020 || UNITY_2019
if (textureSheetAnimation.rowMode == ParticleSystemAnimationRowMode.Random)
#else
if (textureSheetAnimation.useRandomRow)
#endif
{ // FIXME - is this handled internally by rowIndex?
row = Mathf.Abs((int)particle.randomSeed % textureSheetAnimation.numTilesY);
}
frame += row * textureSheetAnimation.numTilesX;
break;
}
frame %= textureSheetAnimationFrames;
particleUV.x = (frame % textureSheetAnimation.numTilesX) * textureSheetAnimationFrameSize.x;
particleUV.y = 1.0f - ((frame / textureSheetAnimation.numTilesX) + 1) * textureSheetAnimationFrameSize.y;
particleUV.z = particleUV.x + textureSheetAnimationFrameSize.x;
particleUV.w = particleUV.y + textureSheetAnimationFrameSize.y;
}
temp.x = particleUV.x;
temp.y = particleUV.y;
_quad[0] = UIVertex.simpleVert;
_quad[0].color = color;
_quad[0].uv0 = temp;
temp.x = particleUV.x;
temp.y = particleUV.w;
_quad[1] = UIVertex.simpleVert;
_quad[1].color = color;
_quad[1].uv0 = temp;
temp.x = particleUV.z;
temp.y = particleUV.w;
_quad[2] = UIVertex.simpleVert;
_quad[2].color = color;
_quad[2].uv0 = temp;
temp.x = particleUV.z;
temp.y = particleUV.y;
_quad[3] = UIVertex.simpleVert;
_quad[3].color = color;
_quad[3].uv0 = temp;
if (rotation == 0)
{
// no rotation
corner1.x = position.x - size;
corner1.y = position.y - size;
corner2.x = position.x + size;
corner2.y = position.y + size;
temp.x = corner1.x;
temp.y = corner1.y;
_quad[0].position = temp;
temp.x = corner1.x;
temp.y = corner2.y;
_quad[1].position = temp;
temp.x = corner2.x;
temp.y = corner2.y;
_quad[2].position = temp;
temp.x = corner2.x;
temp.y = corner1.y;
_quad[3].position = temp;
}
else
{
if (use3dRotation)
{
// get particle properties
#if UNITY_5_5_OR_NEWER
Vector3 pos3d = (mainModule.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
#else
Vector3 pos3d = (pSystem.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
#endif
// apply scale
#if UNITY_5_5_OR_NEWER
if (mainModule.scalingMode == ParticleSystemScalingMode.Shape)
position /= canvas.scaleFactor;
#else
if (pSystem.scalingMode == ParticleSystemScalingMode.Shape)
position /= canvas.scaleFactor;
#endif
Vector3[] verts = new Vector3[4]
{
new Vector3(-size, -size, 0),
new Vector3(-size, size, 0),
new Vector3(size, size, 0),
new Vector3(size, -size, 0)
};
Quaternion particleRotation = Quaternion.Euler(particle.rotation3D);
_quad[0].position = pos3d + particleRotation * verts[0];
_quad[1].position = pos3d + particleRotation * verts[1];
_quad[2].position = pos3d + particleRotation * verts[2];
_quad[3].position = pos3d + particleRotation * verts[3];
}
else
{
// apply rotation
Vector2 right = new Vector2(Mathf.Cos(rotation), Mathf.Sin(rotation)) * size;
Vector2 up = new Vector2(Mathf.Cos(rotation90), Mathf.Sin(rotation90)) * size;
_quad[0].position = position - right - up;
_quad[1].position = position - right + up;
_quad[2].position = position + right + up;
_quad[3].position = position + right - up;
}
}
vh.AddUIVertexQuad(_quad);
}
}
private void Update()
{
if (!fixedTime && Application.isPlaying)
{
pSystem.Simulate(Time.unscaledDeltaTime, false, false, true);
SetAllDirty();
if ((currentMaterial != null && currentTexture != currentMaterial.mainTexture) ||
(material != null && currentMaterial != null && material.shader != currentMaterial.shader))
{
pSystem = null;
Initialize();
}
}
}
private void LateUpdate()
{
if (!Application.isPlaying)
{
SetAllDirty();
}
else
{
if (fixedTime)
{
pSystem.Simulate(Time.unscaledDeltaTime, false, false, true);
SetAllDirty();
if ((currentMaterial != null && currentTexture != currentMaterial.mainTexture) ||
(material != null && currentMaterial != null && material.shader != currentMaterial.shader))
{
pSystem = null;
Initialize();
}
}
}
if (material == currentMaterial)
return;
pSystem = null;
Initialize();
}
protected override void OnDestroy()
{
currentMaterial = null;
currentTexture = null;
}
public void StartParticleEmission()
{
pSystem.time = 0;
pSystem.Play();
}
public void StopParticleEmission()
{
pSystem.Stop(false, ParticleSystemStopBehavior.StopEmittingAndClear);
}
public void PauseParticleEmission()
{
pSystem.Stop(false, ParticleSystemStopBehavior.StopEmitting);
}
}
#endif
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f5f85388e938d9e4599afc6d9441ed57
timeCreated: 1464383716
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: