浏览代码
Merge branch 'master' of gitlab.cds.internal.unity3d.com:upm-packages/ui-widgets/com.unity.uiwidgets into material
/main
Merge branch 'master' of gitlab.cds.internal.unity3d.com:upm-packages/ui-widgets/com.unity.uiwidgets into material
/main
xingwei.zhu
6 年前
当前提交
fb3be64c
共有 65 个文件被更改,包括 4191 次插入 和 1867 次删除
-
2Runtime/editor/rasterizer.cs
-
39Runtime/foundation/basic_types.cs
-
9Runtime/material/text_selection.cs
-
2Runtime/painting/box_decoration.cs
-
508Runtime/painting/gradient.cs
-
80Runtime/painting/image_resolution.cs
-
20Runtime/painting/matrix_utils.cs
-
6Runtime/painting/text_painter.cs
-
2Runtime/painting/text_style.cs
-
15Runtime/rendering/editable.cs
-
6Runtime/rendering/paragraph.cs
-
13Runtime/ui/geometry.cs
-
50Runtime/ui/matrix.cs
-
33Runtime/ui/painting/canvas.cs
-
75Runtime/ui/painting/canvas_clip.cs
-
905Runtime/ui/painting/canvas_impl.cs
-
112Runtime/ui/painting/painting.cs
-
136Runtime/ui/painting/path.cs
-
296Runtime/ui/painting/picture.cs
-
27Runtime/ui/painting/txt/font_manager.cs
-
106Runtime/ui/painting/txt/mesh_generator.cs
-
56Runtime/ui/painting/txt/text_blob.cs
-
4Runtime/ui/text.cs
-
314Runtime/ui/txt/linebreaker.cs
-
721Runtime/ui/txt/paragraph.cs
-
6Runtime/ui/txt/word_separate.cs
-
4Runtime/widgets/basic.cs
-
2Runtime/widgets/routes.cs
-
105Tests/Editor/CanvasAndLayers.cs
-
8Tests/Editor/EditableTextWiget.cs
-
11Tests/Editor/Widgets.cs
-
178Runtime/Resources/UIWidgets_canvas.cginc
-
9Runtime/Resources/UIWidgets_canvas.cginc.meta
-
64Runtime/Resources/UIWidgets_canvas_convexFill.shader
-
9Runtime/Resources/UIWidgets_canvas_convexfill.shader.meta
-
31Runtime/Resources/UIWidgets_canvas_fill0.shader
-
9Runtime/Resources/UIWidgets_canvas_fill0.shader.meta
-
66Runtime/Resources/UIWidgets_canvas_fill1.shader
-
9Runtime/Resources/UIWidgets_canvas_fill1.shader.meta
-
18Runtime/Resources/UIWidgets_canvas_filter.shader
-
9Runtime/Resources/UIWidgets_canvas_filter.shader.meta
-
56Runtime/Resources/UIWidgets_canvas_stencil.shader
-
9Runtime/Resources/UIWidgets_canvas_stencil.shader.meta
-
65Runtime/Resources/UIWidgets_canvas_stroke0.shader
-
9Runtime/Resources/UIWidgets_canvas_stroke0.shader.meta
-
27Runtime/Resources/UIWidgets_canvas_stroke1.shader
-
9Runtime/Resources/UIWidgets_canvas_stroke1.shader.meta
-
64Runtime/Resources/UIWidgets_canvas_tex.shader
-
9Runtime/Resources/UIWidgets_canvas_tex.shader.meta
-
453Runtime/ui/painting/canvas_shader.cs
-
11Runtime/ui/painting/canvas_shader.cs.meta
-
603Runtime/ui/painting/shader.cs
-
11Runtime/ui/painting/shader.cs.meta
-
102Runtime/ui/txt/layout.cs
-
11Runtime/ui/txt/layout.cs.meta
-
14Runtime/ui/txt/layout_utils.cs
-
11Runtime/ui/txt/layout_utils.cs.meta
-
147Runtime/ui/txt/wordbreaker.cs
-
11Runtime/ui/txt/wordbreaker.cs.meta
-
8Tests/Resources.meta
-
3Tests/Resources/6.png
-
88Tests/Resources/6.png.meta
-
3Runtime/Resources/UIWidgets_canvas.shader.meta
-
259Runtime/Resources/UIWidgets_canvas.shader
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
|
|||
class _ColorsAndStops { |
|||
public _ColorsAndStops(List<Color> colors, List<double> stops) { |
|||
this.colors = colors; |
|||
this.stops = stops; |
|||
} |
|||
|
|||
public readonly List<Color> colors; |
|||
public readonly List<double> stops; |
|||
|
|||
public static _ColorsAndStops _interpolateColorsAndStops( |
|||
List<Color> aColors, List<double> aStops, List<Color> bColors, List<double> bStops, double t) { |
|||
D.assert(aColors.Count == bColors.Count, |
|||
"Cannot interpolate between two gradients with a different number of colors."); |
|||
D.assert((aStops == null && aColors.Count == 2) || (aStops != null && aStops.Count == aColors.Count)); |
|||
D.assert((bStops == null && bColors.Count == 2) || (bStops != null && bStops.Count == bColors.Count)); |
|||
List<Color> interpolatedColors = new List<Color>(); |
|||
|
|||
for (int i = 0; i < aColors.Count; i += 1) { |
|||
interpolatedColors.Add(Color.lerp(aColors[i], bColors[i], t)); |
|||
} |
|||
|
|||
List<double> interpolatedStops = null; |
|||
if (aStops != null || bStops != null) { |
|||
aStops = aStops ?? new List<double> {0.0, 1.0}; |
|||
bStops = bStops ?? new List<double> {0.0, 1.0}; |
|||
|
|||
D.assert(aStops.Count == bStops.Count); |
|||
interpolatedStops = new List<double>(); |
|||
for (int i = 0; i < aStops.Count; i += 1) { |
|||
interpolatedStops.Add(MathUtils.lerpDouble(aStops[i], bStops[i], t).clamp(0.0, 1.0)); |
|||
} |
|||
} |
|||
|
|||
return new _ColorsAndStops(interpolatedColors, interpolatedStops); |
|||
} |
|||
} |
|||
|
|||
|
|||
public Gradient( |
|||
List<Color> colors = null, |
|||
List<double> stops = null |
|||
) { |
|||
D.assert(colors != null); |
|||
this.colors = colors; |
|||
this.stops = stops; |
|||
} |
|||
|
|||
public readonly List<Color> colors; |
|||
|
|||
public readonly List<double> stops; |
|||
|
|||
protected List<double> _impliedStops() { |
|||
if (this.stops != null) { |
|||
return this.stops; |
|||
} |
|||
if (this.colors.Count == 2) { |
|||
return null; |
|||
} |
|||
|
|||
D.assert(this.colors.Count >= 2, "colors list must have at least two colors"); |
|||
double separation = 1.0 / (this.colors.Count - 1); |
|||
|
|||
return Enumerable.Range(0, this.colors.Count).Select(i => i * separation).ToList(); |
|||
} |
|||
|
|||
public abstract PaintShader createShader(Rect rect); |
|||
|
|||
protected virtual Gradient lerpFrom(Gradient a, double t) { |
|||
if (a == null) { |
|||
return this.scale(t); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
protected virtual Gradient lerpTo(Gradient b, double t) { |
|||
if (b == null) { |
|||
return this.scale(1.0 - t); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
|
|||
return null; |
|||
Gradient result = null; |
|||
if (b != null) { |
|||
result = b.lerpFrom(a, t); // if a is null, this must return non-null
|
|||
} |
|||
|
|||
if (result == null && a != null) { |
|||
result = a.lerpTo(b, t); // if b is null, this must return non-null
|
|||
} |
|||
|
|||
if (result != null) { |
|||
return result; |
|||
} |
|||
|
|||
if (a == null && b == null) { |
|||
return null; |
|||
} |
|||
|
|||
D.assert(a != null && b != null); |
|||
return t < 0.5 ? a.scale(1.0 - (t * 2.0)) : b.scale((t - 0.5) * 2.0); |
|||
} |
|||
} |
|||
|
|||
|
|||
public class LinearGradient : Gradient, IEquatable<LinearGradient> { |
|||
|
|||
public LinearGradient( |
|||
Alignment begin = null, |
|||
Alignment end = null, |
|||
List<Color> colors = null, |
|||
List<double> stops = null, |
|||
TileMode tileMode = TileMode.clamp |
|||
) : base(colors: colors, stops: stops) { |
|||
this.begin = begin ?? Alignment.centerLeft; |
|||
this.end = end ?? Alignment.centerRight; |
|||
this.tileMode = tileMode; |
|||
} |
|||
|
|||
public readonly Alignment begin; |
|||
|
|||
public readonly Alignment end; |
|||
|
|||
public readonly TileMode tileMode; |
|||
|
|||
public override PaintShader createShader(Rect rect) { |
|||
return ui.Gradient.linear( |
|||
this.begin.withinRect(rect), |
|||
this.end.withinRect(rect), |
|||
this.colors, this._impliedStops(), |
|||
this.tileMode |
|||
); |
|||
} |
|||
|
|||
public override Gradient scale(double factor) { |
|||
return new LinearGradient( |
|||
begin: this.begin, |
|||
end: this.end, |
|||
colors: this.colors.Select(color => Color.lerp(null, color, factor)).ToList(), |
|||
stops: this.stops, |
|||
tileMode: this.tileMode |
|||
); |
|||
} |
|||
|
|||
protected override Gradient lerpFrom(Gradient a, double t) { |
|||
if (a == null || (a is LinearGradient && a.colors.Count == this.colors.Count)) { |
|||
return LinearGradient.lerp((LinearGradient) a, this, t); |
|||
} |
|||
|
|||
return base.lerpFrom(a, t); |
|||
} |
|||
|
|||
protected override Gradient lerpTo(Gradient b, double t) { |
|||
if (b == null || (b is LinearGradient && b.colors.Count == this.colors.Count)) { |
|||
return LinearGradient.lerp(this, (LinearGradient) b, t); |
|||
} |
|||
return base.lerpTo(b, t); |
|||
} |
|||
|
|||
public static LinearGradient lerp(LinearGradient a, LinearGradient b, double t) { |
|||
if (a == null && b == null) { |
|||
return null; |
|||
} |
|||
if (a == null) { |
|||
return (LinearGradient) b.scale(t); |
|||
} |
|||
if (b == null) { |
|||
return (LinearGradient) a.scale(1.0 - t); |
|||
} |
|||
|
|||
_ColorsAndStops interpolated = |
|||
_ColorsAndStops._interpolateColorsAndStops(a.colors, a.stops, b.colors, b.stops, t); |
|||
return new LinearGradient( |
|||
begin: Alignment.lerp(a.begin, b.begin, t), |
|||
end: Alignment.lerp(a.end, b.end, t), |
|||
colors: interpolated.colors, |
|||
stops: interpolated.stops, |
|||
tileMode: t < 0.5 ? a.tileMode : b.tileMode |
|||
); |
|||
} |
|||
|
|||
public bool Equals(LinearGradient other) { |
|||
if (ReferenceEquals(null, other)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, other)) { |
|||
return true; |
|||
} |
|||
return |
|||
this.colors.equalsList(other.colors) && |
|||
this.stops.equalsList(other.stops) && |
|||
Equals(this.begin, other.begin) && |
|||
Equals(this.end, other.end) && |
|||
this.tileMode == other.tileMode; |
|||
} |
|||
|
|||
public override bool Equals(object obj) { |
|||
if (ReferenceEquals(null, obj)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, obj)) { |
|||
return true; |
|||
} |
|||
if (obj.GetType() != this.GetType()) { |
|||
return false; |
|||
} |
|||
return this.Equals((LinearGradient) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
unchecked { |
|||
var hashCode = this.colors.hashList(); |
|||
hashCode = (hashCode * 397) ^ this.stops.hashList(); |
|||
hashCode = (hashCode * 397) ^ (this.begin != null ? this.begin.GetHashCode() : 0); |
|||
hashCode = (hashCode * 397) ^ (this.end != null ? this.end.GetHashCode() : 0); |
|||
hashCode = (hashCode * 397) ^ (int) this.tileMode; |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
public static bool operator ==(LinearGradient left, LinearGradient right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(LinearGradient left, LinearGradient right) { |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
public override String ToString() { |
|||
return $"{this.GetType()}({this.begin}, {this.end}," + |
|||
$"{this.colors.toStringList()}, {this.stops.toStringList()}, {this.tileMode})"; |
|||
} |
|||
} |
|||
|
|||
public class RadialGradient : Gradient, IEquatable<RadialGradient> { |
|||
|
|||
public RadialGradient( |
|||
Alignment center = null, |
|||
double radius = 0.5, |
|||
List<Color> colors = null, |
|||
List<double> stops = null, |
|||
TileMode tileMode = TileMode.clamp |
|||
) : base(colors: colors, stops: stops) { |
|||
this.center = center ?? Alignment.center; |
|||
this.radius = radius; |
|||
this.tileMode = tileMode; |
|||
} |
|||
|
|||
public readonly Alignment center; |
|||
|
|||
public readonly double radius; |
|||
|
|||
public readonly TileMode tileMode; |
|||
|
|||
|
|||
public override PaintShader createShader(Rect rect) { |
|||
return ui.Gradient.radial( |
|||
this.center.withinRect(rect), |
|||
this.radius * rect.shortestSide, |
|||
this.colors, this._impliedStops(), |
|||
this.tileMode |
|||
); |
|||
} |
|||
|
|||
public override Gradient scale(double factor) { |
|||
return new RadialGradient( |
|||
center: this.center, |
|||
radius: this.radius, |
|||
colors: this.colors.Select(color => Color.lerp(null, color, factor)).ToList(), |
|||
stops: this.stops, |
|||
tileMode: this.tileMode |
|||
); |
|||
} |
|||
|
|||
protected override Gradient lerpFrom(Gradient a, double t) { |
|||
if (a == null || (a is RadialGradient && a.colors.Count == this.colors.Count)) { |
|||
return RadialGradient.lerp((RadialGradient) a, this, t); |
|||
} |
|||
|
|||
return base.lerpFrom(a, t); |
|||
} |
|||
|
|||
protected override Gradient lerpTo(Gradient b, double t) { |
|||
if (b == null || (b is RadialGradient && b.colors.Count == this.colors.Count)) { |
|||
return RadialGradient.lerp(this, (RadialGradient) b, t); |
|||
} |
|||
return base.lerpTo(b, t); |
|||
} |
|||
|
|||
public static RadialGradient lerp(RadialGradient a, RadialGradient b, double t) { |
|||
if (a == null && b == null) { |
|||
return null; |
|||
} |
|||
if (a == null) { |
|||
return (RadialGradient) b.scale(t); |
|||
} |
|||
if (b == null) { |
|||
return (RadialGradient) a.scale(1.0 - t); |
|||
} |
|||
|
|||
_ColorsAndStops interpolated = |
|||
_ColorsAndStops._interpolateColorsAndStops(a.colors, a.stops, b.colors, b.stops, t); |
|||
return new RadialGradient( |
|||
center: Alignment.lerp(a.center, b.center, t), |
|||
radius: Math.Max(0.0, MathUtils.lerpDouble(a.radius, b.radius, t)), |
|||
colors: interpolated.colors, |
|||
stops: interpolated.stops, |
|||
tileMode: t < 0.5 ? a.tileMode : b.tileMode |
|||
); |
|||
} |
|||
|
|||
public bool Equals(RadialGradient other) { |
|||
if (ReferenceEquals(null, other)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, other)) { |
|||
return true; |
|||
} |
|||
return |
|||
this.colors.equalsList(other.colors) && |
|||
this.stops.equalsList(other.stops) && |
|||
Equals(this.center, other.center) && |
|||
Equals(this.radius, other.radius) && |
|||
this.tileMode == other.tileMode; |
|||
} |
|||
|
|||
public override bool Equals(object obj) { |
|||
if (ReferenceEquals(null, obj)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, obj)) { |
|||
return true; |
|||
} |
|||
if (obj.GetType() != this.GetType()) { |
|||
return false; |
|||
} |
|||
return this.Equals((RadialGradient) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
unchecked { |
|||
var hashCode = this.colors.hashList(); |
|||
hashCode = (hashCode * 397) ^ this.stops.hashList(); |
|||
hashCode = (hashCode * 397) ^ (this.center != null ? this.center.GetHashCode() : 0); |
|||
hashCode = (hashCode * 397) ^ this.radius.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ (int) this.tileMode; |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
public static bool operator ==(RadialGradient left, RadialGradient right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(RadialGradient left, RadialGradient right) { |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
public override String ToString() { |
|||
return $"{this.GetType()}({this.center}, {this.radius}," + |
|||
$"{this.colors.toStringList()}, {this.stops.toStringList()}, {this.tileMode})"; |
|||
} |
|||
} |
|||
|
|||
public class SweepGradient : Gradient, IEquatable<SweepGradient> { |
|||
|
|||
public SweepGradient( |
|||
Alignment center = null, |
|||
double startAngle = 0.0, |
|||
double endAngle = Math.PI * 2, |
|||
List<Color> colors = null, |
|||
List<double> stops = null, |
|||
TileMode tileMode = TileMode.clamp |
|||
) : base(colors: colors, stops: stops) { |
|||
this.center = center ?? Alignment.center; |
|||
this.startAngle = startAngle; |
|||
this.endAngle = endAngle; |
|||
this.tileMode = tileMode; |
|||
} |
|||
|
|||
public readonly Alignment center; |
|||
|
|||
public readonly double startAngle; |
|||
|
|||
public readonly double endAngle; |
|||
|
|||
public readonly TileMode tileMode; |
|||
|
|||
|
|||
public override PaintShader createShader(Rect rect) { |
|||
return ui.Gradient.sweep( |
|||
this.center.withinRect(rect), |
|||
this.colors, this._impliedStops(), |
|||
this.tileMode, |
|||
this.startAngle, this.endAngle |
|||
); |
|||
} |
|||
|
|||
public override Gradient scale(double factor) { |
|||
return new SweepGradient( |
|||
center: this.center, |
|||
startAngle: this.startAngle, |
|||
endAngle: this.endAngle, |
|||
colors: this.colors.Select(color => Color.lerp(null, color, factor)).ToList(), |
|||
stops: this.stops, |
|||
tileMode: this.tileMode |
|||
); |
|||
} |
|||
|
|||
protected override Gradient lerpFrom(Gradient a, double t) { |
|||
if (a == null || (a is SweepGradient && a.colors.Count == this.colors.Count)) { |
|||
return SweepGradient.lerp((SweepGradient) a, this, t); |
|||
} |
|||
|
|||
return base.lerpFrom(a, t); |
|||
} |
|||
|
|||
protected override Gradient lerpTo(Gradient b, double t) { |
|||
if (b == null || (b is SweepGradient && b.colors.Count == this.colors.Count)) { |
|||
return SweepGradient.lerp(this, (SweepGradient) b, t); |
|||
} |
|||
return base.lerpTo(b, t); |
|||
} |
|||
|
|||
public static SweepGradient lerp(SweepGradient a, SweepGradient b, double t) { |
|||
if (a == null && b == null) { |
|||
return null; |
|||
} |
|||
if (a == null) { |
|||
return (SweepGradient) b.scale(t); |
|||
} |
|||
if (b == null) { |
|||
return (SweepGradient) a.scale(1.0 - t); |
|||
} |
|||
|
|||
_ColorsAndStops interpolated = |
|||
_ColorsAndStops._interpolateColorsAndStops(a.colors, a.stops, b.colors, b.stops, t); |
|||
return new SweepGradient( |
|||
center: Alignment.lerp(a.center, b.center, t), |
|||
startAngle: Math.Max(0.0, MathUtils.lerpDouble(a.startAngle, b.startAngle, t)), |
|||
endAngle: Math.Max(0.0, MathUtils.lerpDouble(a.endAngle, b.endAngle, t)), |
|||
colors: interpolated.colors, |
|||
stops: interpolated.stops, |
|||
tileMode: t < 0.5 ? a.tileMode : b.tileMode |
|||
); |
|||
} |
|||
|
|||
public bool Equals(SweepGradient other) { |
|||
if (ReferenceEquals(null, other)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, other)) { |
|||
return true; |
|||
} |
|||
return |
|||
this.colors.equalsList(other.colors) && |
|||
this.stops.equalsList(other.stops) && |
|||
Equals(this.center, other.center) && |
|||
Equals(this.startAngle, other.startAngle) && |
|||
Equals(this.endAngle, other.endAngle) && |
|||
this.tileMode == other.tileMode; |
|||
} |
|||
|
|||
public override bool Equals(object obj) { |
|||
if (ReferenceEquals(null, obj)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, obj)) { |
|||
return true; |
|||
} |
|||
if (obj.GetType() != this.GetType()) { |
|||
return false; |
|||
} |
|||
return this.Equals((SweepGradient) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
unchecked { |
|||
var hashCode = this.colors.hashList(); |
|||
hashCode = (hashCode * 397) ^ this.stops.hashList(); |
|||
hashCode = (hashCode * 397) ^ (this.center != null ? this.center.GetHashCode() : 0); |
|||
hashCode = (hashCode * 397) ^ this.startAngle.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.endAngle.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ (int) this.tileMode; |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
public static bool operator ==(SweepGradient left, SweepGradient right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(SweepGradient left, SweepGradient right) { |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
public override String ToString() { |
|||
return $"{this.GetType()}({this.center}, {this.startAngle}, {this.endAngle}, " + |
|||
$"{this.colors.toStringList()}, {this.stops.toStringList()}, {this.tileMode})"; |
|||
} |
|||
} |
|||
} |
905
Runtime/ui/painting/canvas_impl.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
using Unity.UIWidgets.foundation; |
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
|
|||
public TextBlob(string text, int start, int end, Vector2d[] positions, TextStyle style, Rect bounds) { |
|||
D.assert(start < end); |
|||
public TextBlob(string text, int textOffset, int textSize, Vector2d[] positions, Rect bounds, TextStyle style) { |
|||
this.instanceId = ++_nextInstanceId; |
|||
this.positions = positions; |
|||
this.start = start; |
|||
this.end = end; |
|||
this.positions = positions; |
|||
this.textOffset = textOffset; |
|||
this.textSize = textSize; |
|||
get { return this.bounds.shift(new Offset(this.positions[this.start].x, this.positions[this.start].y)); } |
|||
get { return this.bounds.shift(new Offset(this.positions[0].x, this.positions[0].y)); } |
|||
static long _nextInstanceId = 0; |
|||
public readonly long instanceId; |
|||
public readonly int start; |
|||
public readonly int end; |
|||
public readonly int textOffset; |
|||
public readonly int textSize; |
|||
} |
|||
|
|||
public class TextBlobBuilder { |
|||
TextStyle _style; |
|||
public Vector2d[] positions; |
|||
string _text; |
|||
int _textOffset; |
|||
int _size; |
|||
Rect _bounds; |
|||
|
|||
public void allocRunPos(TextStyle style, string text, int offset, int size) { |
|||
|
|||
this._style = style; |
|||
this._text = text; |
|||
this._textOffset = offset; |
|||
this._size = size; |
|||
if (this.positions == null || this.positions.Length < size) { |
|||
this.positions = new Vector2d[size]; |
|||
} |
|||
} |
|||
|
|||
public void setBounds(Rect bounds) { |
|||
this._bounds = bounds; |
|||
} |
|||
|
|||
public TextBlob make() { |
|||
var result = new TextBlob(this._text, this._textOffset, |
|||
this._size, this.positions, this._bounds, this._style); |
|||
this.positions = null; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
public class TabStops { |
|||
int _tabWidth = int.MaxValue; |
|||
|
|||
Font _font; |
|||
|
|||
int _fontSize; |
|||
|
|||
const int kTabSpaceCount = 4; |
|||
|
|||
List<int> _stops = new List<int>(); |
|||
|
|||
public void set(List<int> stops, int tabWidth) { |
|||
this._stops.Clear(); |
|||
if (stops != null) { |
|||
this._stops.AddRange(stops); |
|||
} |
|||
|
|||
this._tabWidth = tabWidth; |
|||
} |
|||
|
|||
public void setFont(Font font, int size) { |
|||
if (this._font != font || this._fontSize != size) { |
|||
this._tabWidth = int.MaxValue; |
|||
} |
|||
|
|||
this._font = font; |
|||
this._fontSize = size; |
|||
} |
|||
|
|||
public float nextTab(float widthSoFar) { |
|||
for (int i = 0; i < this._stops.Count; i++) { |
|||
if (this._stops[i] > widthSoFar) { |
|||
return this._stops[i]; |
|||
} |
|||
} |
|||
|
|||
if (this._tabWidth == int.MaxValue) { |
|||
this._font.RequestCharactersInTexture(" ", this._fontSize); |
|||
CharacterInfo characterInfo; |
|||
this._font.GetCharacterInfo(' ', out characterInfo, this._fontSize); |
|||
this._tabWidth = characterInfo.advance * kTabSpaceCount; |
|||
} |
|||
|
|||
if (this._tabWidth == 0) { |
|||
return widthSoFar; |
|||
} |
|||
|
|||
return (float) (Math.Floor(widthSoFar / this._tabWidth + 1) * this._tabWidth); |
|||
} |
|||
} |
|||
|
|||
public class Candidate { |
|||
public int offset; |
|||
public int pre; |
|||
public double preBreak; |
|||
public float penalty; |
|||
|
|||
public double postBreak; |
|||
public int preSpaceCount; |
|||
public int postSpaceCount; |
|||
} |
|||
|
|||
public class LineInfo { |
|||
public int start; |
|||
public double width; |
|||
} |
|||
const float ScoreInfty = float.MaxValue; |
|||
const float ScoreDesperate = 1e10f; |
|||
StyledRuns _runs; |
|||
string _textBuf; |
|||
int _textOffset; |
|||
int _textLength; |
|||
List<float> _charWidths = new List<float>(); |
|||
List<int> _breaks = new List<int>(); |
|||
List<float> _widths = new List<float>(); |
|||
WordBreaker _wordBreaker = new WordBreaker(); |
|||
double _width = 0.0; |
|||
double _preBreak; |
|||
double _lineWidth; |
|||
int _lastBreak; |
|||
int _bestBreak; |
|||
float _bestScore; |
|||
int _spaceCount; |
|||
TabStops _tabStops; |
|||
int mFirstTabIndex; |
|||
List<Candidate> _candidates = new List<Candidate>(); |
|||
public Vector2d[] _characterPositions; |
|||
public double[] _characterWidth; |
|||
string _text; |
|||
double _width; |
|||
int _lineStart; |
|||
int _wordStart; |
|||
int _spaceCount = 0; |
|||
int tabCount = 4; |
|||
double _lineLength; |
|||
public int computeBreaks() { |
|||
int nCand = this._candidates.Count; |
|||
if (nCand > 0 && (nCand == 1 || this._lastBreak != nCand - 1)) { |
|||
var cand = this._candidates[this._candidates.Count - 1]; |
|||
this._pushBreak(cand.offset, (float) (cand.postBreak - this._preBreak)); |
|||
} |
|||
List<LineInfo> _lines; |
|||
return this._breaks.Count; |
|||
} |
|||
public void setup(string text, StyledRuns runs, double width, Vector2d[] characterPositions, |
|||
double[] characterWidth) { |
|||
this._text = text; |
|||
this._runs = runs; |
|||
this._characterPositions = characterPositions; |
|||
this._characterWidth = characterWidth; |
|||
this._width = width; |
|||
public List<int> getBreaks() { |
|||
return this._breaks; |
|||
public List<LineInfo> getLines() { |
|||
return this._lines; |
|||
public void resize(int size) { |
|||
if (this._charWidths.Count < size) { |
|||
this._charWidths.AddRange(Enumerable.Repeat(0.0f, size - this._charWidths.Count)); |
|||
} |
|||
public void doBreak(int blockStart, int blockEnd) { |
|||
this._lines = new List<LineInfo>(); |
|||
this._lineStart = blockStart; |
|||
this._wordStart = blockStart; |
|||
public void setText(string text, int textOffset, int textLength) { |
|||
this._textBuf = text; |
|||
this._textOffset = textOffset; |
|||
this._textLength = textLength; |
|||
this._wordBreaker.setText(this._textBuf, textOffset, textLength); |
|||
this._wordBreaker.next(); |
|||
this._candidates.Clear(); |
|||
Candidate can = new Candidate { |
|||
offset = 0, postBreak = 0, preBreak = 0, postSpaceCount = 0, preSpaceCount = 0, pre = 0 |
|||
}; |
|||
this._candidates.Add(can); |
|||
this._lastBreak = 0; |
|||
this._bestBreak = 0; |
|||
this._bestScore = ScoreInfty; |
|||
this._preBreak = 0; |
|||
this.mFirstTabIndex = int.MaxValue; |
|||
} |
|||
double offsetX = 0.0; |
|||
var runIterator = this._runs.iterator(); |
|||
for (var charIndex = blockStart; charIndex < blockEnd; charIndex++) { |
|||
runIterator.nextTo(charIndex); |
|||
var run = runIterator.run; |
|||
var font = FontManager.instance.getOrCreate(run.style.fontFamily).font; |
|||
public void setLineWidth(float lineWidth) { |
|||
this._lineWidth = lineWidth; |
|||
} |
|||
var style = run.style; |
|||
var charInfo = new CharacterInfo(); |
|||
public float addStyleRun(TextStyle style, int start, int end) { |
|||
float width = 0.0f; |
|||
if (style != null) { |
|||
width = Layout.measureText(this._width - this._preBreak, this._textBuf, |
|||
start + this._textOffset, end - start, style, |
|||
this._charWidths, start, this._tabStops); |
|||
} |
|||
if (this._text[charIndex] == '\t') { |
|||
this._spaceCount++; |
|||
var font = FontManager.instance.getOrCreate(style.fontFamily).font; |
|||
int current = this._wordBreaker.current(); |
|||
int afterWord = start; |
|||
int lastBreak = start; |
|||
font.GetCharacterInfo(' ', out charInfo, |
|||
style.UnityFontSize, style.UnityFontStyle); |
|||
double tabSize = charInfo.advance * this.tabCount; |
|||
var newX = Math.Floor(((offsetX / tabSize) + 1) * tabSize); |
|||
if (newX > this._width && this._lineStart != charIndex) { |
|||
this._characterWidth[charIndex] = tabSize; |
|||
this.makeLine(charIndex, charIndex); |
|||
} |
|||
else { |
|||
this._characterWidth[charIndex] = newX - offsetX; |
|||
this._characterPositions[charIndex].x = offsetX; |
|||
} |
|||
double lastBreakWidth = this._width; |
|||
double postBreak = this._width; |
|||
int postSpaceCount = this._spaceCount; |
|||
offsetX = this._characterPositions[charIndex].x + this._characterWidth[charIndex]; |
|||
} |
|||
else if (this._text[charIndex] == ' ') { |
|||
font.GetCharacterInfo(this._text[charIndex], out charInfo, style.UnityFontSize, |
|||
run.style.UnityFontStyle); |
|||
this._spaceCount++; |
|||
this._characterPositions[charIndex].x = offsetX; |
|||
this._characterWidth[charIndex] = charInfo.advance; |
|||
offsetX = this._characterPositions[charIndex].x + this._characterWidth[charIndex]; |
|||
// todo no wrap in space ?
|
|||
for (int i = start; i < end; i++) { |
|||
char c = this._textBuf[i + this._textOffset]; |
|||
if (c == '\t') { |
|||
this._width = this._preBreak + this._tabStops.nextTab((float) (this._width - this._preBreak)); |
|||
if (this.mFirstTabIndex == int.MaxValue) { |
|||
this.mFirstTabIndex = i; |
|||
} |
|||
font.GetCharacterInfo(this._text[charIndex], out charInfo, style.UnityFontSize, |
|||
run.style.UnityFontStyle); |
|||
if (this._spaceCount > 0 || blockStart == charIndex) { |
|||
this._wordStart = charIndex; |
|||
if (LayoutUtils.isWordSpace(c)) { |
|||
this._spaceCount += 1; |
|||
this._characterPositions[charIndex].x = offsetX; |
|||
this._characterWidth[charIndex] = charInfo.advance; |
|||
this._width += this._charWidths[i]; |
|||
if (!LayoutUtils.isLineEndSpace(c)) { |
|||
postBreak = this._width; |
|||
postSpaceCount = this._spaceCount; |
|||
afterWord = i + 1; |
|||
} |
|||
} |
|||
if (offsetX + charInfo.advance > this._width && this._lineStart != charIndex) { |
|||
if (this._lineStart == this._wordStart) { |
|||
this.makeLine(charIndex, charIndex); |
|||
this._wordStart = charIndex; |
|||
} |
|||
else { |
|||
this.makeLine(this._wordStart, charIndex); |
|||
} |
|||
if (i + 1 == current) { |
|||
int wordStart = this._wordBreaker.wordStart(); |
|||
int wordEnd = this._wordBreaker.wordEnd(); |
|||
if (style != null || current == end || this._charWidths[current] > 0) { |
|||
this._addWordBreak(current, this._width, postBreak, this._spaceCount, postSpaceCount, 0); |
|||
offsetX = this._characterPositions[charIndex].x + this._characterWidth[charIndex]; |
|||
this._spaceCount = 0; |
|||
lastBreak = current; |
|||
lastBreakWidth = this._width; |
|||
current = this._wordBreaker.next(); |
|||
this.makeLine(blockEnd, blockEnd); |
|||
return width; |
|||
} |
|||
|
|||
public void finish() { |
|||
this._wordBreaker.finish(); |
|||
this._width = 0; |
|||
this._candidates.Clear(); |
|||
this._widths.Clear(); |
|||
this._breaks.Clear(); |
|||
this._textBuf = null; |
|||
public List<float> getWidths() { |
|||
return this._widths; |
|||
} |
|||
void makeLine(int end, int last) { |
|||
Debug.Assert(this._lineStart < end); |
|||
Debug.Assert(end <= last); |
|||
this._lines.Add(new LineInfo() { |
|||
start = this._lineStart, |
|||
width = this._characterPositions[end - 1].x + this._characterWidth[end - 1], |
|||
}); |
|||
this._lineStart = end; |
|||
public void setTabStops(TabStops tabStops) { |
|||
this._tabStops = tabStops; |
|||
} |
|||
if (end >= this._characterPositions.Length) { |
|||
return; |
|||
void _addWordBreak(int offset, double preBreak, double postBreak, int preSpaceCount, int postSpaceCount, |
|||
float penalty) { |
|||
Candidate cand = new Candidate(); |
|||
double width = this._candidates[this._candidates.Count - 1].preBreak; |
|||
if (postBreak - width > this._lineWidth) { |
|||
int i = this._candidates[this._candidates.Count - 1].offset; |
|||
width += this._charWidths[i++]; |
|||
for (; i < offset; i++) { |
|||
float w = this._charWidths[i]; |
|||
if (w > 0) { |
|||
cand.offset = i; |
|||
cand.preBreak = width; |
|||
cand.postBreak = width; |
|||
cand.preSpaceCount = postSpaceCount; |
|||
cand.preSpaceCount = postSpaceCount; |
|||
cand.penalty = ScoreDesperate; |
|||
this._addCandidate(cand); |
|||
width += w; |
|||
} |
|||
} |
|||
var offset = new Vector2d(-this._characterPositions[end].x, 0); |
|||
this._characterPositions[end].x = 0; |
|||
if (end < last) { |
|||
Paragraph.offsetCharacters(offset, this._characterPositions, end + 1, last + 1); |
|||
cand.offset = offset; |
|||
cand.preBreak = preBreak; |
|||
cand.postBreak = postBreak; |
|||
cand.penalty = penalty; |
|||
cand.preSpaceCount = preSpaceCount; |
|||
cand.preSpaceCount = postSpaceCount; |
|||
this._addCandidate(cand); |
|||
} |
|||
|
|||
|
|||
void _addCandidate(Candidate cand) { |
|||
int candIndex = this._candidates.Count; |
|||
this._candidates.Add(cand); |
|||
if (cand.postBreak - this._preBreak > this._lineWidth) { |
|||
this._pushGreedyBreak(); |
|||
} |
|||
|
|||
if (cand.penalty <= this._bestScore) { |
|||
this._bestBreak = candIndex; |
|||
this._bestScore = cand.penalty; |
|||
} |
|||
|
|||
void _pushGreedyBreak() { |
|||
var bestCandidate = this._candidates[this._bestBreak]; |
|||
this._pushBreak(bestCandidate.offset, (float) (bestCandidate.postBreak - this._preBreak)); |
|||
this._bestScore = ScoreInfty; |
|||
this._lastBreak = this._bestBreak; |
|||
this._preBreak = bestCandidate.preBreak; |
|||
} |
|||
|
|||
void _pushBreak(int offset, float width) { |
|||
this._breaks.Add(offset); |
|||
this._widths.Add(width); |
|||
} |
|||
} |
|||
} |
|
|||
float4 _viewport; |
|||
float _mat[9]; |
|||
|
|||
half4 _color; |
|||
fixed _alpha; |
|||
half4x4 _shaderMat; |
|||
sampler2D _shaderTex; |
|||
half4 _leftColor; |
|||
half4 _rightColor; |
|||
half _bias; |
|||
half _scale; |
|||
int _tileMode; // 0 = clamp, 1 = mirror, 2 = repeated |
|||
|
|||
sampler2D _tex; |
|||
int _texMode; // 0 = post alpha, 1 = pre alpha, 2 = alpha only |
|||
|
|||
half2 _mf_imgInc; // _mf stands for mask filter |
|||
int _mf_radius; |
|||
half _mf_kernel[25]; |
|||
|
|||
struct appdata_t { |
|||
float4 vertex : POSITION; |
|||
float2 tcoord : TEXCOORD0; |
|||
}; |
|||
|
|||
struct v2f { |
|||
float4 vertex : SV_POSITION; |
|||
float2 ftcoord : TEXCOORD0; |
|||
float2 fpos : TEXCOORD1; |
|||
}; |
|||
|
|||
|
|||
half shader_gradient_layout(half2 pos) { |
|||
half4 p4 = half4(pos, 0.0, 1.0); |
|||
#if defined(UIWIDGETS_LINEAR) |
|||
return mul(_shaderMat, p4).x; |
|||
#elif defined(UIWIDGETS_RADIAL) |
|||
return length(mul(_shaderMat, p4).xy); |
|||
#elif defined(UIWIDGETS_SWEEP) |
|||
half2 p2 = mul(_shaderMat, p4).xy; |
|||
half angle = atan2(-p2.y, -p2.x); |
|||
// 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi] |
|||
return (angle * 0.1591549430918 + 0.5 + _bias) * _scale; |
|||
#else |
|||
return 0; |
|||
#endif |
|||
} |
|||
|
|||
half4 shader_gradient_colorize(half pt) { |
|||
if (_tileMode == 0) { // clamp |
|||
if (pt <= 0.0) { |
|||
return _leftColor; |
|||
} else if (pt >= 1.0) { |
|||
return _rightColor; |
|||
} |
|||
|
|||
half2 coord = half2(pt, 0.5); |
|||
return tex2D(_shaderTex, coord); |
|||
} else if (_tileMode == 1) { // mirror |
|||
pt = pt - 1; |
|||
pt = pt - 2 * floor(pt * 0.5) - 1; |
|||
pt = abs(pt); |
|||
|
|||
half2 coord = half2(pt, 0.5); |
|||
return tex2D(_shaderTex, coord); |
|||
} else if (_tileMode == 2) { // repeated |
|||
pt = frac(pt); |
|||
|
|||
half2 coord = half2(pt, 0.5); |
|||
return tex2D(_shaderTex, coord); |
|||
} |
|||
|
|||
return half4(0, 0, 0, 0); |
|||
} |
|||
|
|||
|
|||
half2 shader_image_layout(half2 pos) { |
|||
half4 p4 = half4(pos, 0.0, 1.0); |
|||
return mul(_shaderMat, p4).xy; |
|||
} |
|||
|
|||
half4 shader_image_colorize(half2 pt) { |
|||
if (_tileMode == 0) { // clamp |
|||
pt.x = clamp(pt.x, 0.0, 1.0); |
|||
pt.y = clamp(pt.y, 0.0, 1.0); |
|||
} else if (_tileMode == 1) { // mirror |
|||
pt.x = pt.x - 1; |
|||
pt.x = pt.x - 2 * floor(pt.x * 0.5) - 1; |
|||
pt.x = abs(pt.x); |
|||
pt.y = pt.y - 1; |
|||
pt.y = pt.y - 2 * floor(pt.y * 0.5) - 1; |
|||
pt.y = abs(pt.y); |
|||
} else if (_tileMode == 2) { // repeated |
|||
pt.x = frac(pt.x); |
|||
pt.y = frac(pt.y); |
|||
} |
|||
|
|||
return tex2D(_shaderTex, pt); |
|||
} |
|||
|
|||
half4 prealpha(half4 color) { |
|||
return half4(color.x * color.w, color.y * color.w, color.z * color.w, color.w); |
|||
} |
|||
|
|||
half4 shader_color (v2f i) { |
|||
half4 c; |
|||
|
|||
#if defined(UIWIDGETS_COLOR) |
|||
c = _color; |
|||
#elif defined(UIWIDGETS_IMAGE) |
|||
half2 pt = shader_image_layout(i.fpos); |
|||
c = shader_image_colorize(pt); |
|||
#else |
|||
half pt = shader_gradient_layout(i.fpos); |
|||
c = shader_gradient_colorize(pt); |
|||
#endif |
|||
|
|||
c.w *= _alpha; |
|||
return c; |
|||
} |
|||
|
|||
|
|||
v2f vert (appdata_t v) { |
|||
v2f o; |
|||
o.ftcoord = v.tcoord; |
|||
o.fpos = v.vertex; |
|||
|
|||
float3x3 mat = float3x3(_mat[0], _mat[1], _mat[2], _mat[3], _mat[4], _mat[5], 0, 0, 1); |
|||
|
|||
half2 p = mul(mat, half3(v.vertex.xy, 1.0)).xy - _viewport.xy; |
|||
|
|||
#if UNITY_UV_STARTS_AT_TOP |
|||
o.vertex = float4(2.0 * p.x / _viewport.z - 1.0, 2.0 * p.y / _viewport.w - 1.0, 0, 1); |
|||
#else |
|||
o.vertex = float4(2.0 * p.x / _viewport.z - 1.0, 1.0 - 2.0 * p.y / _viewport.w, 0, 1); |
|||
#endif |
|||
|
|||
return o; |
|||
} |
|||
|
|||
fixed4 frag (v2f i) : SV_Target { |
|||
return prealpha(shader_color(i)); |
|||
} |
|||
|
|||
fixed4 frag_stencil (v2f i) : SV_Target { |
|||
return half4(0, 0, 0, 0); |
|||
} |
|||
|
|||
fixed4 frag_tex (v2f i) : SV_Target { |
|||
half4 tintColor = shader_color(i); |
|||
|
|||
half4 color = tex2D(_tex, i.ftcoord); |
|||
if (_texMode == 0) { // post alpha |
|||
color = color * tintColor; |
|||
color = prealpha(color); |
|||
} else if (_texMode == 1) { // pre alpha |
|||
color = color * tintColor; |
|||
color = half4(color.x * tintColor.w, color.y * tintColor.w, color.z * tintColor.w, color.w); |
|||
} else if (_texMode == 2) { // alpha only |
|||
color = half4(1, 1, 1, color.w) * tintColor; |
|||
color = prealpha(color); |
|||
} |
|||
|
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_mf (v2f i) : SV_Target { |
|||
half4 color = half4(0, 0, 0, 0); |
|||
|
|||
float2 coord = i.ftcoord - _mf_radius * _mf_imgInc; |
|||
int width = _mf_radius * 2 + 1; |
|||
for (int i = 0; i < width; i++) { |
|||
color += tex2D(_tex, coord) * _mf_kernel[i]; |
|||
coord += _mf_imgInc; |
|||
} |
|||
|
|||
return color; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6565922d18a5e4ee29fa183d2600eccc |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_convexFill" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
_StencilComp("_StencilComp", Float) = 3 // - Equal, 8 - Always |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Stencil { |
|||
Ref 128 |
|||
Comp [_StencilComp] |
|||
} |
|||
|
|||
Pass { // 0, color |
|||
CGPROGRAM |
|||
#define UIWIDGETS_COLOR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, linear |
|||
CGPROGRAM |
|||
#define UIWIDGETS_LINEAR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, radial |
|||
CGPROGRAM |
|||
#define UIWIDGETS_RADIAL |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, sweep |
|||
CGPROGRAM |
|||
#define UIWIDGETS_SWEEP |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, image |
|||
CGPROGRAM |
|||
#define UIWIDGETS_IMAGE |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: da4e74e0b377e41699f5c3ed2c7c69e4 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_fill0" |
|||
{ |
|||
Properties { |
|||
_StencilComp("_StencilComp", Float) = 3 // - Equal, 8 - Always |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
|
|||
Cull Off |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
CompFront [_StencilComp] |
|||
CompBack [_StencilComp] |
|||
ReadMask 128 |
|||
WriteMask 127 |
|||
PassFront IncrWrap |
|||
PassBack DecrWrap |
|||
} |
|||
|
|||
Pass { |
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e75e9debfc1ad4e1687365932de72aa0 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_fill1" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Stencil { |
|||
Ref 0 |
|||
Comp NotEqual |
|||
ReadMask 127 |
|||
WriteMask 127 |
|||
Pass Zero |
|||
} |
|||
|
|||
Pass { // 0, color |
|||
CGPROGRAM |
|||
#define UIWIDGETS_COLOR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, linear |
|||
CGPROGRAM |
|||
#define UIWIDGETS_LINEAR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, radial |
|||
CGPROGRAM |
|||
#define UIWIDGETS_RADIAL |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, sweep |
|||
CGPROGRAM |
|||
#define UIWIDGETS_SWEEP |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, image |
|||
CGPROGRAM |
|||
#define UIWIDGETS_IMAGE |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7dbfb4eecc7a84ddc90c53891aa77e0b |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_filter" |
|||
{ |
|||
Properties { |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
|
|||
Pass { // 0, mask filter |
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_mf |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 756de2a3eb91745ba853728245a033d9 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_stencil" |
|||
{ |
|||
Properties { |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
|
|||
Pass { // 0, stencil clear |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Pass Replace |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, stencil intersect 0 |
|||
Cull Off |
|||
ColorMask 0 |
|||
Stencil { |
|||
WriteMask 127 |
|||
PassFront IncrWrap |
|||
PassBack DecrWrap |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, stencil intersect 1 |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Less |
|||
Pass Replace |
|||
Fail Zero |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b4673a8cf87214fdb8643b32e0ec3316 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_stroke0" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
_StencilComp("_StencilComp", Float) = 3 // - Equal, 8 - Always |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Stencil { |
|||
Ref 128 |
|||
Comp [_StencilComp] |
|||
Pass IncrSat |
|||
} |
|||
|
|||
Pass { // 0, color |
|||
CGPROGRAM |
|||
#define UIWIDGETS_COLOR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, linear |
|||
CGPROGRAM |
|||
#define UIWIDGETS_LINEAR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, radial |
|||
CGPROGRAM |
|||
#define UIWIDGETS_RADIAL |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, sweep |
|||
CGPROGRAM |
|||
#define UIWIDGETS_SWEEP |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, image |
|||
CGPROGRAM |
|||
#define UIWIDGETS_IMAGE |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7e33032771e1e46a6b5eda923148503f |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_stroke1" |
|||
{ |
|||
Properties { |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
|
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 0 |
|||
Comp NotEqual |
|||
ReadMask 127 |
|||
WriteMask 127 |
|||
Pass Zero |
|||
} |
|||
|
|||
Pass { |
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ee8a29ca6a09f4510bbf6e3b70922edc |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_tex" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
_StencilComp("_StencilComp", Float) = 3 // - Equal, 8 - Always |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Stencil { |
|||
Ref 128 |
|||
Comp [_StencilComp] |
|||
} |
|||
|
|||
Pass { // 0, color |
|||
CGPROGRAM |
|||
#define UIWIDGETS_COLOR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, linear |
|||
CGPROGRAM |
|||
#define UIWIDGETS_LINEAR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, radial |
|||
CGPROGRAM |
|||
#define UIWIDGETS_RADIAL |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, sweep |
|||
CGPROGRAM |
|||
#define UIWIDGETS_SWEEP |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, image |
|||
CGPROGRAM |
|||
#define UIWIDGETS_IMAGE |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1702a648d08de40d9aacd9bbab1188b3 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using Unity.UIWidgets.painting; |
|||
using UnityEngine; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
|
|||
static class MaterialProps { |
|||
static readonly int _srcBlend = Shader.PropertyToID("_SrcBlend"); |
|||
static readonly int _dstBlend = Shader.PropertyToID("_DstBlend"); |
|||
static readonly int _stencilComp = Shader.PropertyToID("_StencilComp"); |
|||
|
|||
public static void set(Material mat, BlendMode op) { |
|||
if (op == BlendMode.srcOver) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} else if (op == BlendMode.srcIn) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.DstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
} else if (op == BlendMode.srcOut) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusDstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
} else if (op == BlendMode.srcATop) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.DstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} else if (op == BlendMode.dstOver) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusDstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
} else if (op == BlendMode.dstIn) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.SrcAlpha); |
|||
} else if (op == BlendMode.dstOut) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} else if (op == BlendMode.dstATop) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusDstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.SrcAlpha); |
|||
} else if (op == BlendMode.plus) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
} else if (op == BlendMode.src) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
} else if (op == BlendMode.dst) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
} else if (op == BlendMode.xor) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusDstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} else if (op == BlendMode.clear) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
} else { |
|||
Debug.LogWarning("Not supported BlendMode: " + op + ". Defaults to srcOver"); |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} |
|||
} |
|||
|
|||
public static void set(Material mat, CompareFunction op) { |
|||
mat.SetFloat(_stencilComp, (int) op); |
|||
} |
|||
} |
|||
|
|||
class MaterialByBlendMode { |
|||
public MaterialByBlendMode(Shader shader) { |
|||
this._shader = shader; |
|||
} |
|||
|
|||
readonly Shader _shader; |
|||
readonly Material[] _materials = new Material[30]; |
|||
|
|||
public Material getMaterial(BlendMode op) { |
|||
var key = (int) op; |
|||
var mat = this._materials[key]; |
|||
if (mat) { |
|||
return mat; |
|||
} |
|||
|
|||
mat = new Material(this._shader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
MaterialProps.set(mat, op); |
|||
|
|||
this._materials[key] = mat; |
|||
return mat; |
|||
} |
|||
} |
|||
|
|||
class MaterialByStencilComp { |
|||
public MaterialByStencilComp(Shader shader) { |
|||
this._shader = shader; |
|||
} |
|||
|
|||
readonly Shader _shader; |
|||
readonly Material[] _materials = new Material[2]; |
|||
|
|||
public Material getMaterial(bool ignoreClip) { |
|||
var key = ignoreClip ? 1 : 0; |
|||
var mat = this._materials[key]; |
|||
if (mat) { |
|||
return mat; |
|||
} |
|||
|
|||
mat = new Material(this._shader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
MaterialProps.set(mat, ignoreClip ? CompareFunction.Always : CompareFunction.Equal); |
|||
|
|||
this._materials[key] = mat; |
|||
return mat; |
|||
} |
|||
} |
|||
|
|||
class MaterialByBlendModeStencilComp { |
|||
public MaterialByBlendModeStencilComp(Shader shader) { |
|||
this._shader = shader; |
|||
} |
|||
|
|||
readonly Shader _shader; |
|||
readonly Material[] _materials = new Material[30 * 2]; |
|||
|
|||
public Material getMaterial(BlendMode blend, bool ignoreClip) { |
|||
var key = (int) blend * 2 + (ignoreClip ? 1 : 0); |
|||
var mat = this._materials[key]; |
|||
if (mat) { |
|||
return mat; |
|||
} |
|||
|
|||
mat = new Material(this._shader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
MaterialProps.set(mat, blend); |
|||
MaterialProps.set(mat, ignoreClip ? CompareFunction.Always : CompareFunction.Equal); |
|||
|
|||
this._materials[key] = mat; |
|||
return mat; |
|||
} |
|||
} |
|||
|
|||
static class CanvasShader { |
|||
static readonly MaterialByBlendModeStencilComp _convexFillMat; |
|||
static readonly MaterialByStencilComp _fill0Mat; |
|||
static readonly MaterialByBlendMode _fill1Mat; |
|||
static readonly MaterialByBlendModeStencilComp _stroke0Mat; |
|||
static readonly Material _stroke1Mat; |
|||
static readonly MaterialByBlendModeStencilComp _texMat; |
|||
static readonly Material _stencilMat; |
|||
static readonly Material _filterMat; |
|||
|
|||
static CanvasShader() { |
|||
var convexFillShader = Shader.Find("UIWidgets/canvas_convexFill"); |
|||
if (convexFillShader == null) { |
|||
throw new Exception("UIWidgets/canvas_convexFill not found"); |
|||
} |
|||
var fill0Shader = Shader.Find("UIWidgets/canvas_fill0"); |
|||
if (fill0Shader == null) { |
|||
throw new Exception("UIWidgets/canvas_fill0 not found"); |
|||
} |
|||
var fill1Shader = Shader.Find("UIWidgets/canvas_fill1"); |
|||
if (fill1Shader == null) { |
|||
throw new Exception("UIWidgets/canvas_fill1 not found"); |
|||
} |
|||
var stroke0Shader = Shader.Find("UIWidgets/canvas_stroke0"); |
|||
if (stroke0Shader == null) { |
|||
throw new Exception("UIWidgets/canvas_stroke0 not found"); |
|||
} |
|||
var stroke1Shader = Shader.Find("UIWidgets/canvas_stroke1"); |
|||
if (stroke1Shader == null) { |
|||
throw new Exception("UIWidgets/canvas_stroke1 not found"); |
|||
} |
|||
var texShader = Shader.Find("UIWidgets/canvas_tex"); |
|||
if (texShader == null) { |
|||
throw new Exception("UIWidgets/canvas_tex not found"); |
|||
} |
|||
var stencilShader = Shader.Find("UIWidgets/canvas_stencil"); |
|||
if (stencilShader == null) { |
|||
throw new Exception("UIWidgets/canvas_stencil not found"); |
|||
} |
|||
var filterShader = Shader.Find("UIWidgets/canvas_filter"); |
|||
if (filterShader == null) { |
|||
throw new Exception("UIWidgets/canvas_filter not found"); |
|||
} |
|||
|
|||
_convexFillMat = new MaterialByBlendModeStencilComp(convexFillShader); |
|||
_fill0Mat = new MaterialByStencilComp(fill0Shader); |
|||
_fill1Mat = new MaterialByBlendMode(fill1Shader); |
|||
_stroke0Mat = new MaterialByBlendModeStencilComp(stroke0Shader); |
|||
_stroke1Mat = new Material(stroke1Shader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
_texMat = new MaterialByBlendModeStencilComp(texShader); |
|||
_stencilMat = new Material(stencilShader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
_filterMat = new Material(filterShader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
} |
|||
|
|||
static Vector4 _colorToVector4(Color c) { |
|||
return new Vector4( |
|||
c.red / 255f, |
|||
c.green / 255f, |
|||
c.blue / 255f, |
|||
c.alpha / 255f |
|||
); |
|||
} |
|||
|
|||
static void _getShaderPassAndProps(Vector4 viewport, Matrix3 ctm, Paint paint, float alpha, |
|||
out int pass, out MaterialPropertyBlock props) { |
|||
props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
props.SetFloat("_alpha", alpha); |
|||
|
|||
switch (paint.shader) { |
|||
case null: |
|||
pass = 0; |
|||
props.SetVector("_color", _colorToVector4(paint.color)); |
|||
return; |
|||
case _LinearGradient linear: |
|||
pass = 1; |
|||
props.SetMatrix("_shaderMat", linear.getGradientMat(ctm).toMatrix4x4()); |
|||
props.SetTexture("_shaderTex", linear.gradientTex.texture); |
|||
props.SetVector("_leftColor", _colorToVector4(linear.leftColor)); |
|||
props.SetVector("_rightColor", _colorToVector4(linear.rightColor)); |
|||
props.SetInt("_tileMode", (int) linear.tileMode); |
|||
return; |
|||
case _RadialGradient radial: |
|||
pass = 2; |
|||
props.SetMatrix("_shaderMat", radial.getGradientMat(ctm).toMatrix4x4()); |
|||
props.SetTexture("_shaderTex", radial.gradientTex.texture); |
|||
props.SetVector("_leftColor", _colorToVector4(radial.leftColor)); |
|||
props.SetVector("_rightColor", _colorToVector4(radial.rightColor)); |
|||
props.SetInt("_tileMode", (int) radial.tileMode); |
|||
return; |
|||
case _SweepGradient sweep: |
|||
pass = 3; |
|||
props.SetMatrix("_shaderMat", sweep.getGradientMat(ctm).toMatrix4x4()); |
|||
props.SetTexture("_shaderTex", sweep.gradientTex.texture); |
|||
props.SetVector("_leftColor", _colorToVector4(sweep.leftColor)); |
|||
props.SetVector("_rightColor", _colorToVector4(sweep.rightColor)); |
|||
props.SetInt("_tileMode", (int) sweep.tileMode); |
|||
props.SetFloat("_bias", (float) sweep.bias); |
|||
props.SetFloat("_scale", (float) sweep.scale); |
|||
return; |
|||
case ImageShader image: |
|||
pass = 4; |
|||
props.SetMatrix("_shaderMat", image.getShaderMat(ctm).toMatrix4x4()); |
|||
props.SetTexture("_shaderTex", image.image.texture); |
|||
props.SetInt("_tileMode", (int) image.tileMode); |
|||
return; |
|||
default: |
|||
throw new Exception("Unknown paint.shader: " + paint.shader); |
|||
} |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw convexFill(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _convexFillMat.getMaterial(paint.blendMode, layer.ignoreClip); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw fill0(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _fill0Mat.getMaterial(layer.ignoreClip); |
|||
|
|||
var pass = 0; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw fill1(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _fill1Mat.getMaterial(paint.blendMode); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh.boundsMesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stroke0(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
float alpha, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _stroke0Mat.getMaterial(paint.blendMode, layer.ignoreClip); |
|||
_getShaderPassAndProps(viewport, ctm, paint, alpha, out var pass, out var props); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stroke1(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _stroke1Mat; |
|||
|
|||
var pass = 0; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stencilClear( |
|||
CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _stencilMat; |
|||
|
|||
var pass = 0; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stencil0(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _stencilMat; |
|||
|
|||
var pass = 1; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stencil1(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _stencilMat; |
|||
|
|||
var pass = 2; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw tex(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh, Image image) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _texMat.getMaterial(paint.blendMode, layer.ignoreClip); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
props.SetTexture("_tex", image.texture); |
|||
props.SetInt("_texMode", image.texture is RenderTexture ? 1 : 0); // pre alpha if RT else post alpha
|
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
image = image, // keep a reference to avoid GC.
|
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw texRT(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh, CommandBufferCanvas.RenderLayer renderLayer) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
|
|||
var mat = _texMat.getMaterial(paint.blendMode, layer.ignoreClip); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
props.SetInt("_texMode", 1); // pre alpha
|
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
layer = renderLayer, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw texAlpha(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh, Texture tex) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _texMat.getMaterial(paint.blendMode, layer.ignoreClip); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
props.SetTexture("_tex", tex); |
|||
props.SetInt("_texMode", 2); // alpha only
|
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw maskFilter(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh, |
|||
CommandBufferCanvas.RenderLayer renderLayer, float radius, Vector2 imgInc, float[] kernel) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _filterMat; |
|||
|
|||
var pass = 0; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
props.SetFloat("_mf_radius", radius); |
|||
props.SetVector("_mf_imgInc", imgInc); |
|||
props.SetFloatArray("_mf_kernel", kernel); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
layer = renderLayer, |
|||
}; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6c897b209ded34c03ac522c5f76ae23d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public enum TileMode : int { |
|||
clamp = 0, |
|||
mirror = 1, |
|||
repeated = 2, |
|||
} |
|||
|
|||
public abstract class PaintShader { |
|||
} |
|||
|
|||
|
|||
public class Gradient : PaintShader { |
|||
|
|||
public static Gradient linear( |
|||
Offset start, Offset end, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
Matrix3 matrix = null) { |
|||
D.assert(PaintingUtils._offsetIsValid(start)); |
|||
D.assert(PaintingUtils._offsetIsValid(end)); |
|||
D.assert(colors != null && colors.Count >= 2); |
|||
|
|||
_validateColorStops(ref colors, ref colorStops); |
|||
|
|||
return new _LinearGradient(start, end, colors, colorStops, tileMode, matrix); |
|||
} |
|||
|
|||
public static Gradient radial( |
|||
Offset center, double radius, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
Matrix3 matrix = null) { |
|||
D.assert(PaintingUtils._offsetIsValid(center)); |
|||
D.assert(colors != null && colors.Count >= 2); |
|||
|
|||
_validateColorStops(ref colors, ref colorStops); |
|||
|
|||
return new _RadialGradient(center, radius, colors, colorStops, tileMode, matrix); |
|||
} |
|||
|
|||
public static Gradient sweep( |
|||
Offset center, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
double startAngle = 0.0, double endAngle = Math.PI * 2, |
|||
Matrix3 matrix = null) { |
|||
D.assert(PaintingUtils._offsetIsValid(center)); |
|||
D.assert(colors != null && colors.Count >= 2); |
|||
D.assert(startAngle < endAngle); |
|||
|
|||
_validateColorStops(ref colors, ref colorStops); |
|||
|
|||
return new _SweepGradient(center, colors, colorStops, tileMode, startAngle, endAngle, matrix); |
|||
} |
|||
|
|||
static void _validateColorStops(ref List<Color> colors, ref List<double> colorStops) { |
|||
if (colorStops == null) { |
|||
colors = new List<Color>(colors); |
|||
|
|||
colorStops = new List<double>(colors.Count); |
|||
colorStops.Add(0); |
|||
var stepCount = colors.Count - 1; |
|||
var step = 1.0 / stepCount; |
|||
for (int i = 1; i < stepCount; i++) { |
|||
colorStops.Add(colorStops[i - 1] + step); |
|||
} |
|||
colorStops.Add(1); |
|||
|
|||
return; |
|||
} |
|||
|
|||
if (colors.Count != colorStops.Count) { |
|||
throw new ArgumentException("\"colors\" and \"colorStops\" arguments must have equal length."); |
|||
} |
|||
|
|||
var dummyFirst = colorStops[0] != 0; |
|||
var dummyLast = colorStops[colorStops.Count - 1] != 1; |
|||
var count = colors.Count + (dummyFirst ? 1 : 0) + (dummyFirst ? 1 : 0); |
|||
|
|||
var newColors = new List<Color>(count); |
|||
if (dummyFirst) { |
|||
newColors.Add(colors[0]); |
|||
} |
|||
for (int i = 0; i < colors.Count; i++) { |
|||
newColors.Add(colors[i]); |
|||
} |
|||
if (dummyLast) { |
|||
newColors.Add(colors[colors.Count - 1]); |
|||
} |
|||
|
|||
var newColorStops = new List<double>(count); |
|||
if (dummyFirst) { |
|||
newColorStops.Add(0.0); |
|||
} |
|||
var prevStop = 0.0; |
|||
for (int i = 0; i < colorStops.Count; i++) { |
|||
var stop = Math.Max(Math.Min(colorStops[i], 1.0), prevStop); |
|||
newColorStops.Add(stop); |
|||
prevStop = stop; |
|||
} |
|||
if (dummyLast) { |
|||
newColorStops.Add(1.0); |
|||
} |
|||
|
|||
colors = newColors; |
|||
colorStops = newColorStops; |
|||
} |
|||
|
|||
static readonly GradientBitmapCache _cache = new GradientBitmapCache(); |
|||
|
|||
internal static Image makeTexturedColorizer(List<Color> colors, List<double> positions) { |
|||
int count = colors.Count; |
|||
D.assert(count >= 2); |
|||
|
|||
bool bottomHardStop = ScalarUtils.ScalarNearlyEqual((float) positions[0], (float) positions[1]); |
|||
bool topHardStop = ScalarUtils.ScalarNearlyEqual((float) positions[count - 2], (float) positions[count - 1]); |
|||
|
|||
int offset = 0; |
|||
if (bottomHardStop) { |
|||
offset += 1; |
|||
count--; |
|||
} |
|||
if (topHardStop) { |
|||
count--; |
|||
} |
|||
|
|||
if (offset != 0 || count != colors.Count) { |
|||
colors = colors.GetRange(offset, count); |
|||
positions = positions.GetRange(offset, count); |
|||
} |
|||
|
|||
return _cache.getGradient(colors, positions); |
|||
} |
|||
} |
|||
|
|||
class GradientBitmapCache : IDisposable { |
|||
public GradientBitmapCache(int maxEntries = 32, int resolution = 256) { |
|||
this.maxEntries = maxEntries; |
|||
this.resolution = resolution; |
|||
this._entryCount = 0; |
|||
this._head = this._tail = null; |
|||
|
|||
D.assert(this.validate); |
|||
} |
|||
|
|||
public readonly int maxEntries; |
|||
public readonly int resolution; |
|||
|
|||
int _entryCount; |
|||
_Entry _head; |
|||
_Entry _tail; |
|||
|
|||
public Image getGradient(List<Color> colors, List<double> positions) { |
|||
var key = new _Key(colors, positions); |
|||
|
|||
if (!this.find(key, out var image)) { |
|||
image = this.fillGradient(colors, positions); |
|||
this.add(key, image); |
|||
} |
|||
|
|||
return image; |
|||
} |
|||
|
|||
public void Dispose() { |
|||
D.assert(this.validate); |
|||
|
|||
// just remove the references, Image will dispose by themselves.
|
|||
this._entryCount = 0; |
|||
this._head = this._tail = null; |
|||
} |
|||
|
|||
_Entry release(_Entry entry) { |
|||
if (entry.prev != null) { |
|||
D.assert(this._head != entry); |
|||
entry.prev.next = entry.next; |
|||
} else { |
|||
D.assert(this._head == entry); |
|||
this._head = entry.next; |
|||
} |
|||
|
|||
if (entry.next != null) { |
|||
D.assert(this._tail != entry); |
|||
entry.next.prev = entry.prev; |
|||
} else { |
|||
D.assert(this._tail == entry); |
|||
this._tail = entry.prev; |
|||
} |
|||
|
|||
return entry; |
|||
} |
|||
|
|||
void attachToHead(_Entry entry) { |
|||
entry.prev = null; |
|||
entry.next = this._head; |
|||
if (this._head != null) { |
|||
this._head.prev = entry; |
|||
} else { |
|||
this._tail = entry; |
|||
} |
|||
this._head = entry; |
|||
} |
|||
|
|||
bool find(_Key key, out Image image) { |
|||
D.assert(this.validate); |
|||
|
|||
var entry = this._head; |
|||
while (entry != null) { |
|||
if (entry.key == key) { |
|||
image = entry.image; |
|||
|
|||
// move to the head of our list, so we purge it last
|
|||
this.release(entry); |
|||
this.attachToHead(entry); |
|||
D.assert(this.validate); |
|||
return true; |
|||
} |
|||
entry = entry.next; |
|||
} |
|||
|
|||
D.assert(this.validate); |
|||
image = null; |
|||
return false; |
|||
} |
|||
|
|||
void add(_Key key, Image image) { |
|||
if (this._entryCount == this.maxEntries) { |
|||
D.assert(this._tail != null); |
|||
this.release(this._tail); |
|||
this._entryCount--; |
|||
} |
|||
|
|||
var entry = new _Entry {key = key, image = image}; |
|||
this.attachToHead(entry); |
|||
this._entryCount++; |
|||
} |
|||
|
|||
Image fillGradient(List<Color> colors, List<double> positions) { |
|||
Texture2D tex = new Texture2D(this.resolution, 1, TextureFormat.RGBA32, false); |
|||
tex.hideFlags = HideFlags.HideAndDontSave; |
|||
tex.wrapMode = TextureWrapMode.Clamp; |
|||
|
|||
var bytes = new byte[this.resolution * 4]; |
|||
|
|||
int count = colors.Count; |
|||
int prevIndex = 0; |
|||
for (int i = 1; i < count; i++) { |
|||
// Historically, stops have been mapped to [0, 256], with 256 then nudged to the next
|
|||
// smaller value, then truncate for the texture index. This seems to produce the best
|
|||
// results for some common distributions, so we preserve the behavior.
|
|||
int nextIndex = (int) Mathf.Min((float) positions[i] * this.resolution, this.resolution - 1); |
|||
|
|||
if (nextIndex > prevIndex) { |
|||
var c0 = colors[i - 1]; |
|||
var c1 = colors[i]; |
|||
|
|||
var step = 1.0f / (nextIndex - prevIndex); |
|||
var t = 0.0; |
|||
|
|||
for (int curIndex = prevIndex; curIndex <= nextIndex; ++curIndex) { |
|||
var c = Color.lerp(c0, c1, t); |
|||
|
|||
var baseIndex = curIndex << 2; |
|||
bytes[baseIndex] = (byte) c.red; |
|||
bytes[baseIndex + 1] = (byte) c.green; |
|||
bytes[baseIndex + 2] = (byte) c.blue; |
|||
bytes[baseIndex + 3] = (byte) c.alpha; |
|||
|
|||
t += step; |
|||
} |
|||
} |
|||
|
|||
prevIndex = nextIndex; |
|||
} |
|||
|
|||
D.assert(prevIndex == this.resolution - 1); |
|||
|
|||
tex.LoadRawTextureData(bytes); |
|||
tex.Apply(); |
|||
return new Image(tex); |
|||
} |
|||
|
|||
bool validate() { |
|||
D.assert(this._entryCount >= 0 && this._entryCount <= this.maxEntries); |
|||
|
|||
if (this._entryCount > 0) { |
|||
D.assert(null == this._head.prev); |
|||
D.assert(null == this._tail.next); |
|||
|
|||
if (this._entryCount == 1) { |
|||
D.assert(this._head == this._tail); |
|||
} else { |
|||
D.assert(this._head != this._tail); |
|||
} |
|||
|
|||
var entry = this._head; |
|||
int count = 0; |
|||
while (entry != null) { |
|||
count += 1; |
|||
entry = entry.next; |
|||
} |
|||
D.assert(count == this._entryCount); |
|||
|
|||
entry = this._tail; |
|||
while (entry != null) { |
|||
count -= 1; |
|||
entry = entry.prev; |
|||
} |
|||
D.assert(0 == count); |
|||
} else { |
|||
D.assert(null == this._head); |
|||
D.assert(null == this._tail); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
class _Entry { |
|||
public _Entry prev; |
|||
public _Entry next; |
|||
|
|||
public _Key key; |
|||
public Image image; |
|||
} |
|||
|
|||
class _Key : IEquatable<_Key> { |
|||
public _Key(List<Color> colors, List<double> positions) { |
|||
D.assert(colors != null); |
|||
D.assert(positions != null); |
|||
D.assert(colors.Count == positions.Count); |
|||
|
|||
this.colors = colors; |
|||
this.positions = positions; |
|||
this._hashCode = _getHashCode(this.colors) ^ _getHashCode(this.positions); |
|||
; |
|||
} |
|||
|
|||
public readonly List<Color> colors; |
|||
|
|||
public readonly List<double> positions; |
|||
|
|||
readonly int _hashCode; |
|||
|
|||
public bool Equals(_Key other) { |
|||
if (ReferenceEquals(null, other)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, other)) { |
|||
return true; |
|||
} |
|||
return _listEquals(this.colors, other.colors) && |
|||
_listEquals(this.positions, other.positions); |
|||
} |
|||
|
|||
public override bool Equals(object obj) { |
|||
if (ReferenceEquals(null, obj)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, obj)) { |
|||
return true; |
|||
} |
|||
if (obj.GetType() != this.GetType()) { |
|||
return false; |
|||
} |
|||
return this.Equals((_Key) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
return this._hashCode; |
|||
} |
|||
|
|||
public static bool operator ==(_Key left, _Key right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(_Key left, _Key right) { |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
static int _getHashCode<T>(List<T> list) { |
|||
unchecked { |
|||
var hashCode = 0; |
|||
foreach (var item in list) { |
|||
hashCode = (hashCode * 397) ^ item.GetHashCode(); |
|||
} |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
static bool _listEquals<T>(List<T> left, List<T> right) { |
|||
if (left.Count != right.Count) { |
|||
return false; |
|||
} |
|||
|
|||
for (int i = 0; i < left.Count; i++) { |
|||
if (!left[i].Equals(right[i])) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
class _LinearGradient : Gradient { |
|||
public _LinearGradient( |
|||
Offset start, Offset end, List<Color> colors, |
|||
List<double> colorStops, TileMode tileMode, |
|||
Matrix3 matrix = null) { |
|||
this.start = start; |
|||
this.end = end; |
|||
this.colors = colors; |
|||
this.colorStops = colorStops; |
|||
this.tileMode = tileMode; |
|||
this.matrix = matrix; |
|||
this.ptsToUnit = ptsToUnitMatrix(start, end); |
|||
this.gradientTex = makeTexturedColorizer(colors, colorStops); |
|||
} |
|||
|
|||
public readonly Offset start; |
|||
public readonly Offset end; |
|||
public readonly List<Color> colors; |
|||
public readonly List<double> colorStops; |
|||
public readonly TileMode tileMode; |
|||
public readonly Matrix3 matrix; |
|||
public readonly Matrix3 ptsToUnit; |
|||
public readonly Image gradientTex; |
|||
|
|||
public Color leftColor { |
|||
get { return this.colors[0]; } |
|||
} |
|||
|
|||
public Color rightColor { |
|||
get { return this.colors[this.colors.Count - 1]; } |
|||
} |
|||
|
|||
public Matrix3 getGradientMat(Matrix3 ctm) { |
|||
var mat = Matrix3.I(); |
|||
ctm.invert(mat); // just use I() if not invertible.
|
|||
|
|||
if (this.matrix != null) { |
|||
mat.postConcat(this.matrix); |
|||
} |
|||
mat.postConcat(this.ptsToUnit); |
|||
return mat; |
|||
} |
|||
|
|||
static Matrix3 ptsToUnitMatrix(Offset start, Offset end) { |
|||
var vec = end - start; |
|||
var mag = vec.distance; |
|||
var inv = mag != 0 ? 1 / mag : 0; |
|||
vec = vec.scale(inv); |
|||
|
|||
var matrix = Matrix3.I(); |
|||
matrix.setSinCos((float) -vec.dy, (float) vec.dx, (float) start.dx, (float) start.dy); |
|||
matrix.postTranslate((float) -start.dx, (float) -start.dy); |
|||
matrix.postScale((float) inv, (float) inv); |
|||
return matrix; |
|||
} |
|||
} |
|||
|
|||
class _RadialGradient : Gradient { |
|||
public _RadialGradient( |
|||
Offset center, double radius, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
Matrix3 matrix = null |
|||
) { |
|||
this.center = center; |
|||
this.radius = radius; |
|||
this.colors = colors; |
|||
this.colorStops = colorStops; |
|||
this.tileMode = tileMode; |
|||
this.matrix = matrix; |
|||
this.ptsToUnit = radToUnitMatrix(center, radius); |
|||
this.gradientTex = makeTexturedColorizer(colors, colorStops); |
|||
} |
|||
|
|||
public readonly Offset center; |
|||
public readonly double radius; |
|||
public readonly List<Color> colors; |
|||
public readonly List<double> colorStops; |
|||
public readonly TileMode tileMode; |
|||
public readonly Matrix3 matrix; |
|||
public readonly Matrix3 ptsToUnit; |
|||
public readonly Image gradientTex; |
|||
|
|||
public Color leftColor { |
|||
get { return this.colors[0]; } |
|||
} |
|||
|
|||
public Color rightColor { |
|||
get { return this.colors[this.colors.Count - 1]; } |
|||
} |
|||
|
|||
public Matrix3 getGradientMat(Matrix3 ctm) { |
|||
var mat = Matrix3.I(); |
|||
ctm.invert(mat); // just use I() if not invertible.
|
|||
|
|||
if (this.matrix != null) { |
|||
mat.postConcat(this.matrix); |
|||
} |
|||
mat.postConcat(this.ptsToUnit); |
|||
return mat; |
|||
} |
|||
|
|||
static Matrix3 radToUnitMatrix(Offset center, double radius) { |
|||
var inv = radius != 0 ? 1 / radius : 0; |
|||
|
|||
var matrix = Matrix3.I(); |
|||
matrix.setTranslate((float) -center.dx, (float) -center.dy); |
|||
matrix.postScale((float) inv, (float) inv); |
|||
return matrix; |
|||
} |
|||
} |
|||
|
|||
class _SweepGradient : Gradient { |
|||
|
|||
public _SweepGradient( |
|||
Offset center, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
double startAngle = 0.0, double endAngle = Math.PI * 2, |
|||
Matrix3 matrix = null |
|||
) { |
|||
this.center = center; |
|||
this.colors = colors; |
|||
this.colorStops = colorStops; |
|||
this.tileMode = tileMode; |
|||
this.startAngle = startAngle; |
|||
this.endAngle = endAngle; |
|||
this.matrix = matrix; |
|||
|
|||
var t0 = startAngle / (Math.PI * 2f); |
|||
var t1 = endAngle / (Math.PI * 2f); |
|||
this.bias = -t0; |
|||
this.scale = 1f / (t1 - t0); |
|||
|
|||
var ptsToUnit = Matrix3.I(); |
|||
ptsToUnit.setTranslate((float) -center.dx, (float) -center.dy); |
|||
this.ptsToUnit = ptsToUnit; |
|||
|
|||
this.gradientTex = makeTexturedColorizer(colors, colorStops); |
|||
} |
|||
|
|||
public readonly Offset center; |
|||
public readonly List<Color> colors; |
|||
public readonly List<double> colorStops; |
|||
public readonly TileMode tileMode; |
|||
public readonly double startAngle; |
|||
public readonly double endAngle; |
|||
public readonly Matrix3 matrix; |
|||
public readonly Matrix3 ptsToUnit; |
|||
public readonly Image gradientTex; |
|||
public readonly double bias; |
|||
public readonly double scale; |
|||
|
|||
public Color leftColor { |
|||
get { return this.colors[0]; } |
|||
} |
|||
|
|||
public Color rightColor { |
|||
get { return this.colors[this.colors.Count - 1]; } |
|||
} |
|||
|
|||
public Matrix3 getGradientMat(Matrix3 ctm) { |
|||
var mat = Matrix3.I(); |
|||
ctm.invert(mat); // just use I() if not invertible.
|
|||
|
|||
if (this.matrix != null) { |
|||
mat.postConcat(this.matrix); |
|||
} |
|||
mat.postConcat(this.ptsToUnit); |
|||
return mat; |
|||
} |
|||
} |
|||
|
|||
public class ImageShader : PaintShader { |
|||
public ImageShader(Image image, |
|||
TileMode tileMode = TileMode.clamp, Matrix3 matrix = null) { |
|||
this.image = image; |
|||
this.tileMode = tileMode; |
|||
this.matrix = matrix; |
|||
} |
|||
|
|||
public readonly Image image; |
|||
public readonly TileMode tileMode; |
|||
public readonly Matrix3 matrix; |
|||
|
|||
public Matrix3 getShaderMat(Matrix3 ctm) { |
|||
var mat = Matrix3.I(); |
|||
ctm.invert(mat); // just use I() if not invertible.
|
|||
|
|||
if (this.matrix != null) { |
|||
mat.postConcat(this.matrix); |
|||
} |
|||
|
|||
mat.postScale(1f / this.image.width, 1f / this.image.height); |
|||
return mat; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 740926ff13f534c8d8ec44b0b017ff61 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public class Layout { |
|||
int _start; |
|||
int _count; |
|||
List<float> _advances = new List<float>(); |
|||
List<float> _positions = new List<float>(); |
|||
float _advance; |
|||
Rect _bounds; |
|||
string _text; |
|||
TabStops _tabStops; |
|||
|
|||
|
|||
public static float measureText(double offset, string buf, int start, int count, TextStyle style, |
|||
List<float> advances, int advanceOffset, TabStops tabStops) { |
|||
Layout layout = new Layout(); |
|||
layout.setTabStops(tabStops); |
|||
layout.doLayout(offset, buf, start, count, style); |
|||
if (advances != null) { |
|||
var layoutAdv = layout.getAdvances(); |
|||
for (int i = 0; i < count; i++) { |
|||
advances[i + advanceOffset] = layoutAdv[i]; |
|||
} |
|||
} |
|||
|
|||
return layout.getAdvance(); |
|||
} |
|||
|
|||
public void doLayout(double offset, string text, int start, int count, TextStyle style) { |
|||
this._text = text; |
|||
this._advances.Clear(); |
|||
this._positions.Clear(); |
|||
this._count = count; |
|||
var font = FontManager.instance.getOrCreate(style.fontFamily).font; |
|||
font.RequestCharactersInTexture(this._text.Substring(start, count), |
|||
style.UnityFontSize, |
|||
style.UnityFontStyle); |
|||
|
|||
this._advance = 0; |
|||
this._bounds = null; |
|||
for (int i = 0; i < count; i++) { |
|||
int charIndex = start + i; |
|||
var ch = text[charIndex]; |
|||
CharacterInfo characterInfo; |
|||
font.GetCharacterInfo(ch, out characterInfo, style.UnityFontSize, style.UnityFontStyle); |
|||
|
|||
var rect = Rect.fromLTRB(characterInfo.minX, -characterInfo.maxY, characterInfo.maxX, |
|||
-characterInfo.minY); |
|||
rect = rect.translate(this._advance, 0); |
|||
if (this._bounds == null) { |
|||
this._bounds = rect; |
|||
} |
|||
else { |
|||
this._bounds = this._bounds.expandToInclude(rect); |
|||
} |
|||
|
|||
this._positions.Add(this._advance); |
|||
float advance = characterInfo.advance; |
|||
if (ch == '\t') { |
|||
advance = this._tabStops.nextTab((float) (this._advance + offset)) - this._advance; |
|||
} |
|||
|
|||
this._advances.Add(advance); |
|||
this._advance += advance; |
|||
} |
|||
} |
|||
|
|||
public void setTabStops(TabStops tabStops) { |
|||
this._tabStops = tabStops; |
|||
} |
|||
|
|||
public int nGlyphs() { |
|||
return this._count; |
|||
} |
|||
|
|||
public List<float> getAdvances() { |
|||
return this._advances; |
|||
} |
|||
|
|||
public float getAdvance() { |
|||
return this._advance; |
|||
} |
|||
|
|||
public float getX(int index) { |
|||
return this._positions[index]; |
|||
} |
|||
|
|||
public float getY(int index) { |
|||
return 0; |
|||
} |
|||
|
|||
public float getCharAdvance(int index) { |
|||
return this._advances[index]; |
|||
} |
|||
|
|||
public Rect getBounds() { |
|||
return this._bounds; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 291468e4e150b495fa305f2d62b134e3 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace Unity.UIWidgets.ui { |
|||
public static class LayoutUtils { |
|||
public const char CHAR_NBSP = '\u00A0'; |
|||
|
|||
public static bool isWordSpace(char ch) { |
|||
return ch == ' ' || ch == CHAR_NBSP; |
|||
} |
|||
|
|||
public static bool isLineEndSpace(char c) { |
|||
return c == '\n' || c == ' ' || c == 0x1680 || (0x2000 <= c && c <= 0x200A && c != 0x2007) || |
|||
c == 0x205F || c == 0x3000; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1b1768a705ffe4cb7ab2638ac53c657e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace Unity.UIWidgets.ui { |
|||
public class WordBreaker { |
|||
public const uint U16_SURROGATE_OFFSET = ((0xd800 << 10) + 0xdc00 - 0x10000); |
|||
string _text; |
|||
int _offset; |
|||
int _size; |
|||
int _current; |
|||
int _last; |
|||
int _scanOffset; |
|||
bool _inEmailOrUrl; |
|||
|
|||
|
|||
public int next() { |
|||
this._last = this._current; |
|||
this._detectEmailOrUrl(); |
|||
if (this._inEmailOrUrl) { |
|||
this._current = this._findNextBreakInEmailOrUrl(); |
|||
} |
|||
else { |
|||
this._current = this._findNextBreakNormal(); |
|||
} |
|||
|
|||
return this._current; |
|||
} |
|||
|
|||
public void setText(string data, int offset, int size) { |
|||
this._text = data; |
|||
this._offset = offset; |
|||
this._size = size; |
|||
this._last = 0; |
|||
this._current = 0; |
|||
this._scanOffset = 0; |
|||
this._inEmailOrUrl = false; |
|||
} |
|||
|
|||
public int current() { |
|||
return this._current; |
|||
} |
|||
|
|||
public int wordStart() { |
|||
if (this._inEmailOrUrl) { |
|||
return this._last; |
|||
} |
|||
|
|||
var result = this._last; |
|||
while (result < this._current) { |
|||
int ix = result; |
|||
uint c = nextCode(this._text, ref ix, this._current); |
|||
if (!LayoutUtils.isLineEndSpace((char) c)) { |
|||
break; |
|||
} |
|||
|
|||
result = ix; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public int wordEnd() { |
|||
if (this._inEmailOrUrl) { |
|||
return this._last; |
|||
} |
|||
|
|||
int result = this._current; |
|||
while (result > this._last) { |
|||
int ix = result; |
|||
uint ch = preCode(this._text, ref ix, this._last); |
|||
if (!LayoutUtils.isLineEndSpace((char) ch)) { |
|||
break; |
|||
} |
|||
|
|||
result = ix; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public int breakBadness() { |
|||
return (this._inEmailOrUrl && this._current < this._scanOffset) ? 1 : 0; |
|||
} |
|||
|
|||
public void finish() { |
|||
this._text = null; |
|||
} |
|||
|
|||
int _findNextBreakInEmailOrUrl() { |
|||
return 0; |
|||
} |
|||
|
|||
int _findNextBreakNormal() { |
|||
if (this._current == this._size) { |
|||
return -1; |
|||
} |
|||
|
|||
this._current++; |
|||
for (; this._current < this._size; ++this._current) { |
|||
char c = this._text[this._current + this._offset]; |
|||
if (LayoutUtils.isWordSpace(c) || c == '\t') { |
|||
return this._current; |
|||
} |
|||
} |
|||
|
|||
return this._current; |
|||
} |
|||
|
|||
void _detectEmailOrUrl() { |
|||
} |
|||
|
|||
static uint nextCode(string text, ref int index, int end) { |
|||
uint ch = text[index++]; |
|||
if (isLeadSurrogate(ch)) { |
|||
if (index < end && isTrailSurrogate(text[index])) { |
|||
char ch2 = text[index]; |
|||
index++; |
|||
ch = getSupplementary(ch, ch2); |
|||
} |
|||
} |
|||
|
|||
return ch; |
|||
} |
|||
|
|||
static uint preCode(string text, ref int index, int start) { |
|||
uint ch = text[--index]; |
|||
if (isTrailSurrogate(ch)) { |
|||
if (index > start && isLeadSurrogate(text[index - 1])) { |
|||
ch = getSupplementary(text[index - 1], ch); |
|||
--index; |
|||
} |
|||
} |
|||
|
|||
return ch; |
|||
} |
|||
|
|||
public static bool isLeadSurrogate(uint c) { |
|||
return ((c) & 0xfffffc00) == 0xd800; |
|||
} |
|||
|
|||
|
|||
public static bool isTrailSurrogate(uint c) { |
|||
return ((c) & 0xfffffc00) == 0xdc00; |
|||
} |
|||
|
|||
public static uint getSupplementary(uint lead, uint trail) { |
|||
return (char) (((uint) (lead) << 10) + (uint) (trail - U16_SURROGATE_OFFSET)); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 30b4907a8b76c4df9a243dcd8d3518fb |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: a4bf4806dd96141b189111637bb1f450 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d8fa175306ac44f8ea120cf256fd21d9 |
|||
TextureImporter: |
|||
fileIDToRecycleName: {} |
|||
externalObjects: {} |
|||
serializedVersion: 7 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 1 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: -1 |
|||
mipBias: -100 |
|||
wrapU: -1 |
|||
wrapV: -1 |
|||
wrapW: -1 |
|||
nPOTScale: 1 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 0 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 0 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
platformSettings: |
|||
- serializedVersion: 2 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: baf507ab371c4f4c9eb9ce70a004ba0d |
|||
timeCreated: 1543832597 |
|
|||
Shader "UIWidgets/canvas" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
} |
|||
|
|||
CGINCLUDE |
|||
float4 _viewport; |
|||
float4x4 _paintMat; |
|||
half4 _innerCol; |
|||
half4 _outerCol; |
|||
float2 _extent; |
|||
float _radius; |
|||
float _feather; |
|||
sampler2D _tex; |
|||
|
|||
half2 _mf_imgInc; // _mf stands for mask filter |
|||
int _mf_radius; |
|||
half _mf_kernel[25]; |
|||
|
|||
struct appdata_t { |
|||
float4 vertex : POSITION; |
|||
float2 tcoord : TEXCOORD0; |
|||
}; |
|||
|
|||
struct v2f { |
|||
float4 vertex : SV_POSITION; |
|||
float2 ftcoord : TEXCOORD0; |
|||
float2 fpos : TEXCOORD1; |
|||
}; |
|||
|
|||
float sdroundrect (float2 pt, float2 ext, float rad) { |
|||
float2 ext2 = ext - float2(rad, rad); |
|||
float2 d = abs(pt) - ext2; |
|||
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - rad; |
|||
} |
|||
|
|||
#pragma vertex vert |
|||
v2f vert (appdata_t v) { |
|||
v2f o; |
|||
o.ftcoord = v.tcoord; |
|||
o.fpos = v.vertex; |
|||
|
|||
float x = v.vertex.x - _viewport.x; |
|||
float y = v.vertex.y - _viewport.y; |
|||
|
|||
#if UNITY_UV_STARTS_AT_TOP |
|||
o.vertex = float4(2.0 * x / _viewport.z - 1.0, 2.0 * y / _viewport.w - 1.0, 0, 1); |
|||
#else |
|||
o.vertex = float4(2.0 * x / _viewport.z - 1.0, 1.0 - 2.0 * y / _viewport.w, 0, 1); |
|||
#endif |
|||
|
|||
return o; |
|||
} |
|||
|
|||
fixed4 frag (v2f i) : SV_Target { |
|||
float2 pt = (mul(_paintMat, float3(i.fpos, 1.0))).xy; |
|||
float d = clamp((sdroundrect(pt, _extent, _radius) + _feather * 0.5) / _feather, 0.0, 1.0); |
|||
half4 color = lerp(_innerCol, _outerCol, d); |
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_stencil (v2f i) : SV_Target { |
|||
return half4(0, 0, 0, 0); |
|||
} |
|||
|
|||
fixed4 frag_tex (v2f i) : SV_Target { |
|||
half4 color = tex2D(_tex, i.ftcoord); |
|||
color = color * _innerCol; // tint color |
|||
color = half4(color.xyz * color.w, color.w); |
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_texrt (v2f i) : SV_Target { |
|||
half4 color = tex2D(_tex, i.ftcoord); |
|||
color = color * _innerCol; // tint color |
|||
color = half4(color.xyz * _innerCol.w, color.w); |
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_texfont (v2f i) : SV_Target { |
|||
half4 color = tex2D(_tex, i.ftcoord); |
|||
color = half4(1, 1, 1, color.w) * _innerCol; // tint color |
|||
color = half4(color.xyz * color.w, color.w); |
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_mf (v2f i) : SV_Target { |
|||
half4 color = half4(0, 0, 0, 0); |
|||
|
|||
float2 coord = i.ftcoord - _mf_radius * _mf_imgInc; |
|||
int width = _mf_radius * 2 + 1; |
|||
for (int i = 0; i < width; i++) { |
|||
color += tex2D(_tex, coord) * _mf_kernel[i]; |
|||
coord += _mf_imgInc; |
|||
} |
|||
|
|||
color = color * _innerCol; // tint color |
|||
color = half4(color.xyz * _innerCol.w, color.w); |
|||
return color; |
|||
} |
|||
|
|||
ENDCG |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Pass { // 0, fill pass 0 |
|||
Cull Off |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
CompFront Equal |
|||
CompBack Equal |
|||
ReadMask 128 |
|||
WriteMask 127 |
|||
PassFront IncrWrap |
|||
PassBack DecrWrap |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, fill pass 1 |
|||
Stencil { |
|||
Ref 0 |
|||
Comp NotEqual |
|||
ReadMask 127 |
|||
WriteMask 127 |
|||
Pass Zero |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, convex fill |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
CGPROGRAM |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, stroke pass 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
Pass IncrSat |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, stroke pass 1 |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 0 |
|||
Comp NotEqual |
|||
ReadMask 127 |
|||
WriteMask 127 |
|||
Pass Zero |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 5, texture pass 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 6, render texture pass 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_texrt |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 7, stencil clear |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Pass Replace |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 8, stencil intersect 0 |
|||
Cull Off |
|||
ColorMask 0 |
|||
Stencil { |
|||
WriteMask 127 |
|||
PassFront IncrWrap |
|||
PassBack DecrWrap |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 9, stencil intersect 1 |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Less |
|||
Pass Replace |
|||
Fail Zero |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 10, font texture pass 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_texfont |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 11, mask filter |
|||
CGPROGRAM |
|||
#pragma fragment frag_mf |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue