kg
6 年前
当前提交
f9625421
共有 6 个文件被更改,包括 559 次插入 和 8 次删除
-
8Runtime/Resources/UIWidgets_canvas.cginc
-
39Runtime/foundation/basic_types.cs
-
2Runtime/painting/box_decoration.cs
-
508Runtime/painting/gradient.cs
-
1Runtime/ui/painting/shader.cs
-
9Tests/Editor/Widgets.cs
|
|||
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})"; |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue