浏览代码

1. fix some bugs in notched shape.

2. add conicTo, arcToPoint in canvas.
3. fix some bugs in the animation.
/main
kg 5 年前
当前提交
60aee8d0
共有 14 个文件被更改,包括 356 次插入48 次删除
  1. 2
      Runtime/animation/animations.cs
  2. 4
      Runtime/animation/tween.cs
  3. 29
      Runtime/async/timer.cs
  4. 2
      Runtime/foundation/change_notifier.cs
  5. 12
      Runtime/material/arc.cs
  6. 12
      Runtime/material/chip.cs
  7. 2
      Runtime/material/list_tile.cs
  8. 2
      Runtime/material/scaffold.cs
  9. 12
      Runtime/painting/notched_shapes.cs
  10. 4
      Runtime/rendering/object.cs
  11. 4
      Runtime/ui/matrix.cs
  12. 4
      Runtime/ui/painting/canvas_impl.cs
  13. 309
      Runtime/ui/painting/path.cs
  14. 6
      Samples/UIWidgetsGallery/gallery/app.cs

2
Runtime/animation/animations.cs


T _lastValue;
void _maybeNotifyListeners() {
if (Equals(this.value, this._lastValue)) {
if (!Equals(this.value, this._lastValue)) {
this._lastValue = this.value;
this.notifyListeners();
}

4
Runtime/animation/tween.cs


this.end = end;
}
public T begin;
public virtual T begin { get; set; }
public T end;
public virtual T end { get; set; }
public abstract T lerp(float t);

29
Runtime/async/timer.cs


return timer;
}
static readonly List<TimerImpl> _timers = new List<TimerImpl>();
static readonly List<TimerImpl> _appendList = new List<TimerImpl>();
List<TimerImpl> timers = null;
List<TimerImpl> appendList = null;
_timers.Clear();
_appendList.Clear();
if (timers == null) {
timers = new List<TimerImpl>();
}
timers.Add(timer);
_timers.Add(timer);
if (timers != null) {
foreach (var timer in timers) {
if (_timers.Count != 0) {
foreach (var timer in _timers) {
if (flushMicroTasks != null) {
flushMicroTasks();
}

if (appendList == null) {
appendList = new List<TimerImpl>();
}
appendList.Add(timer);
_appendList.Add(timer);
if (appendList != null) {
if (_appendList.Count != 0) {
foreach (var timer in appendList) {
foreach (var timer in _appendList) {
this._queue.enqueue(timer);
}
}

2
Runtime/foundation/change_notifier.cs


this._value = value;
}
public T value {
public virtual T value {
get { return this._value; }
set {
if (Equals(value, this._value)) {

12
Runtime/material/arc.cs


float? _endAngle;
public new Offset begin {
public override Offset begin {
get { return base.begin; }
set {
if (value != base.begin) {

}
}
public new Offset end {
public override Offset end {
get { return base.end; }
set {
if (value != base.end) {

MaterialPointArcTween _endArc;
public new Rect begin {
public override Rect begin {
get { return base.begin; }
set {
if (value != base.begin) {

}
}
public new Rect end {
public override Rect end {
get { return base.end; }
set {
if (value != base.end) {

MaterialPointArcTween _centerArc;
public new Rect begin {
public override Rect begin {
get { return base.begin; }
set {
if (value != base.begin) {

}
}
public new Rect end {
public override Rect end {
get { return base.end; }
set {
if (value != base.end) {

12
Runtime/material/chip.cs


vsync: this
);
float checkmarkPercentage = ChipUtils._kCheckmarkDuration.Milliseconds /
ChipUtils._kSelectDuration.Milliseconds;
float checkmarkReversePercentage = ChipUtils._kCheckmarkReverseDuration.Milliseconds /
ChipUtils._kSelectDuration.Milliseconds;
float avatarDrawerReversePercentage = ChipUtils._kReverseDrawerDuration.Milliseconds /
ChipUtils._kSelectDuration.Milliseconds;
float checkmarkPercentage = (float) (ChipUtils._kCheckmarkDuration.TotalMilliseconds /
ChipUtils._kSelectDuration.TotalMilliseconds);
float checkmarkReversePercentage = (float) (ChipUtils._kCheckmarkReverseDuration.TotalMilliseconds /
ChipUtils._kSelectDuration.TotalMilliseconds);
float avatarDrawerReversePercentage = (float) (ChipUtils._kReverseDrawerDuration.TotalMilliseconds /
ChipUtils._kSelectDuration.TotalMilliseconds);
this.checkmarkAnimation = new CurvedAnimation(
parent: this.selectController,
curve: new Interval(1.0f - checkmarkPercentage, 1.0f, curve: Curves.fastOutSlowIn),

2
Runtime/material/list_tile.cs


return value;
}
public new bool sizedByParent {
protected override bool sizedByParent {
get { return false; }
}

2
Runtime/material/scaffold.cs


ScaffoldGeometry geometry;
public new ScaffoldGeometry value {
public override ScaffoldGeometry value {
get {
D.assert(() => {
RenderObject renderObject = this.context.findRenderObject();

12
Runtime/painting/notched_shapes.cs


float notchRadius = guest.width / 2.0f;
const float s1 = 15.0f;
const float s2 = 1.0f;

float p2yA = Mathf.Sqrt(r * r - p2xA * p2xA);
float p2yB = Mathf.Sqrt(r * r - p2xB * p2xB);
List<Offset> p = new List<Offset>(6);
Offset[] p = new Offset[6];
p[0] = new Offset(a - s1, b);
p[1] = new Offset(a, b);

p[4] = new Offset(-1.0f * p[1].dx, p[1].dy);
p[5] = new Offset(-1.0f * p[0].dx, p[0].dy);
for (int i = 0; i < p.Count; i += 1) {
for (int i = 0; i < p.Length; i += 1) {
p[i] += guest.center;
}

ret.quadraticBezierTo(p[1].dx, p[1].dy, p[2].dx, p[2].dy);
// TODO: replace this lineTo() with arcToPoint when arcToPoint is ready
ret.lineTo(p[3].dx, p[3].dy);
// ret.arcToPoint(p[3], p[3], radius: Radius.circular(notchRadius), clockwise: false);
ret.arcToPoint(
p[3],
radius: Radius.circular(notchRadius),
clockwise: false);
ret.quadraticBezierTo(p[4].dx, p[4].dy, p[5].dx, p[5].dy);
ret.lineTo(host.right, host.top);
ret.lineTo(host.right, host.bottom);

4
Runtime/rendering/object.cs


if (needsCompositing) {
var inverse = Matrix3.I();
var invertible = effectiveTransform.invert(inverse);
D.assert(invertible);
// it could just be "scale == 0", ignore the assertion.
// D.assert(invertible);
this.pushLayer(
new TransformLayer(effectiveTransform),

4
Runtime/ui/matrix.cs


D.assert(tolerance >= 0);
return Mathf.Abs(x - y) <= tolerance;
}
public static bool ScalarIsInteger(float scalar) {
return scalar == Mathf.FloorToInt(scalar);
}
public static float DegreesToRadians(float degrees) {
return degrees * (Mathf.PI / 180);

4
Runtime/ui/painting/canvas_impl.cs


toClear = false;
}
}
void _drawLayer(RenderLayer layer, CommandBuffer cmdBuf) {
bool toClear = true;

}
break;
case CmdScissor cmd:
this._setRenderTarget(cmdBuf, layer.rtID, ref toClear);
if (cmd.deviceScissor == null) {
cmdBuf.DisableScissorRect();
} else {

309
Runtime/ui/painting/path.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unity.UIWidgets.foundation;
using UnityEngine;

this.quadraticBezierTo(x0 + cx, y0 + cy, x0 + x, y0 + y);
}
public void conicTo(float x1, float y1, float x2, float y2, float w) {
if (!(w > 0)) {
this.lineTo(x2, y2);
return;
}
if (w.isInfinite()) {
this.lineTo(x1, y1);
this.lineTo(x2, y2);
return;
}
if (w == 1) {
this.quadraticBezierTo(x1, y1, x2, y2);
return;
}
var x0 = this._commandx;
var y0 = this._commandy;
var conic = new _Conic {
x0 = x0, y0 = y0,
x1 = x1, y1 = y1,
x2 = x2, y2 = y2,
w = w,
};
var quadX = new float[5];
var quadY = new float[5];
conic.chopIntoQuadsPOW2(quadX, quadY, 1);
this.quadraticBezierTo(quadX[1], quadY[1], quadX[2], quadY[2]);
this.quadraticBezierTo(quadX[3], quadY[3], quadX[4], quadY[4]);
}
public void relativeConicTo(float x1, float y1, float x2, float y2, float w) {
var x0 = this._commandx;
var y0 = this._commandy;
this.conicTo(x0 + x1, y0 + y1, x0 + x2, y0 + y2, w);
}
// http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
public void arcToPoint(Offset arcEnd,
Radius radius = null,
float rotation = 0.0f,
bool largeArc = false,
bool clockwise = false) {
radius = radius ?? Radius.zero;
D.assert(PaintingUtils._offsetIsValid(arcEnd));
D.assert(PaintingUtils._radiusIsValid(radius));
var x0 = this._commandx;
var y0 = this._commandy;
var x1 = arcEnd.dx;
var y1 = arcEnd.dy;
var rx = Mathf.Abs(radius.x);
var ry = Mathf.Abs(radius.y);
if (rx == 0 || ry == 0) {
this.lineTo(x1, y1);
return;
}
if (x0 == x1 && y0 == y1) {
this.lineTo(x1, y1);
return;
}
var midPointDistanceX = (x0 - x1) * 0.5f;
var midPointDistanceY = (y0 - y1) * 0.5f;
var pointTransform = Matrix3.makeRotate(rotation);
var transformedMidPoint = pointTransform.mapXY(midPointDistanceX, midPointDistanceY);
var squareRx = rx * rx;
var squareRy = ry * ry;
var squareX = transformedMidPoint.dx * transformedMidPoint.dx;
var squareY = transformedMidPoint.dy * transformedMidPoint.dy;
// Check if the radii are big enough to draw the arc, scale radii if not.
// http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii
var radiiScale = squareX / squareRx + squareY / squareRy;
if (radiiScale > 1) {
radiiScale = Mathf.Sqrt(radiiScale);
rx *= radiiScale;
ry *= radiiScale;
}
pointTransform.setScale(1 / rx, 1 / ry);
pointTransform.preRotate(-rotation);
var unitPts = new [] {
pointTransform.mapXY(x0, y0),
pointTransform.mapXY(x1, y1),
};
var delta = unitPts[1] - unitPts[0];
var d = delta.dx * delta.dx + delta.dy * delta.dy;
var scaleFactorSquared = Mathf.Max(1 / d - 0.25f, 0.0f);
var scaleFactor = Mathf.Sqrt(scaleFactorSquared);
if (!clockwise != largeArc) { // flipped from the original implementation
scaleFactor = -scaleFactor;
}
delta = delta.scale(scaleFactor);
var centerPoint = unitPts[0] + unitPts[1];
centerPoint *= 0.5f;
centerPoint = centerPoint.translate(-delta.dy, delta.dx);
unitPts[0] -= centerPoint;
unitPts[1] -= centerPoint;
var theta1 = Mathf.Atan2(unitPts[0].dy, unitPts[0].dx);
var theta2 = Mathf.Atan2(unitPts[1].dy, unitPts[1].dx);
var thetaArc = theta2 - theta1;
if (thetaArc < 0 && clockwise) { // arcSweep flipped from the original implementation
thetaArc += Mathf.PI * 2;
} else if (thetaArc > 0 && !clockwise) { // arcSweep flipped from the original implementation
thetaArc -= Mathf.PI * 2;
}
pointTransform.setRotate(rotation);
pointTransform.preScale(rx, ry);
// the arc may be slightly bigger than 1/4 circle, so allow up to 1/3rd
int segments = Mathf.CeilToInt(Mathf.Abs(thetaArc / (2 * Mathf.PI / 3)));
var thetaWidth = thetaArc / segments;
var t = Mathf.Tan(0.5f * thetaWidth);
if (!t.isFinite()) {
return;
}
var startTheta = theta1;
var w = Mathf.Sqrt(0.5f + Mathf.Cos(thetaWidth) * 0.5f);
bool expectIntegers = ScalarUtils.ScalarNearlyZero(Mathf.PI/2 - Mathf.Abs(thetaWidth)) &&
ScalarUtils.ScalarIsInteger(rx) && ScalarUtils.ScalarIsInteger(ry) &&
ScalarUtils.ScalarIsInteger(x1) && ScalarUtils.ScalarIsInteger(y1);
for (int i = 0; i < segments; ++i) {
var endTheta = startTheta + thetaWidth;
var sinEndTheta = ScalarUtils.ScalarSinCos(endTheta, out var cosEndTheta);
unitPts[1] = new Offset(cosEndTheta, sinEndTheta);
unitPts[1] += centerPoint;
unitPts[0] = unitPts[1];
unitPts[0] = unitPts[0].translate(t * sinEndTheta, -t * cosEndTheta);
var mapped = new [] {
pointTransform.mapPoint(unitPts[0]),
pointTransform.mapPoint(unitPts[1]),
};
/*
Computing the arc width introduces rounding errors that cause arcs to start
outside their marks. A round rect may lose convexity as a result. If the input
values are on integers, place the conic on integers as well.
*/
if (expectIntegers) {
for (int index = 0; i < mapped.Length; index++) {
mapped[index] = new Offset(
Mathf.Round(mapped[index].dx),
Mathf.Round(mapped[index].dy)
);
}
}
this.conicTo(mapped[0].dx, mapped[0].dy, mapped[1].dx, mapped[1].dy, w);
startTheta = endTheta;
}
}
public void close() {
this._appendCommands(new[] {
(float) PathCommand.close,

winding,
}
class _Conic {
public float x0;
public float y0;
public float x1;
public float y1;
public float x2;
public float y2;
public float w;
public int chopIntoQuadsPOW2(float[] quadX, float[] quadY, int pow2) {
quadX[0] = this.x0;
quadY[0] = this.y0;
var endIndex = this._subdivide(quadX, quadY, 1, pow2);
var quadCount = 1 << pow2;
var ptCount = 2 * quadCount + 1;
D.assert(endIndex == ptCount);
if (!(_areFinite(quadX, 0, ptCount) && _areFinite(quadY, 0, ptCount))) {
for (int i = 1; i < ptCount - 1; i++) {
quadX[i] = this.x1;
quadY[i] = this.y1;
}
}
return quadCount;
}
static bool _areFinite(float[] array, int index, int count) {
float prod = 0;
count += index;
for (int i = index; i < count; ++i) {
prod *= array[i];
}
// At this point, prod will either be NaN or 0
return prod == 0; // if prod is NaN, this check will return false
}
int _subdivide(float[] quadX, float[] quadY, int index, int level) {
D.assert(level >= 0);
if (0 == level) {
quadX[0 + index] = this.x1;
quadY[0 + index] = this.y1;
quadX[1 + index] = this.x2;
quadY[1 + index] = this.y2;
return 2 + index;
}
_Conic c1, c2;
this._chop(out c1, out c2);
var startY = this.y0;
var endY = this.y2;
if (_between(startY, this.y1, endY)) {
// If the input is monotonic and the output is not, the scan converter hangs.
// Ensure that the chopped conics maintain their y-order.
var midY = c1.y2;
if (!_between(startY, midY, endY)) {
// If the computed midpoint is outside the ends, move it to the closer one.
var closerY = Mathf.Abs(midY - startY) < Mathf.Abs(midY - endY) ? startY : endY;
c1.y2 = c2.y0 = closerY;
}
if (!_between(startY, c1.y1, c1.y2)) {
// If the 1st control is not between the start and end, put it at the start.
// This also reduces the quad to a line.
c1.y1 = startY;
}
if (!_between(c2.y0, c2.y1, endY)) {
// If the 2nd control is not between the start and end, put it at the end.
// This also reduces the quad to a line.
c2.y1 = endY;
}
// Verify that all five points are in order.
D.assert(_between(startY, c1.y1, c1.y2));
D.assert(_between(c1.y1, c1.y2, c2.y1));
D.assert(_between(c1.y2, c2.y1, endY));
}
--level;
index = c1._subdivide(quadX, quadY, index, level);
return c2._subdivide(quadX, quadY, index, level);
}
static bool _between(float a, float b, float c) {
return (a - b) * (c - b) <= 0;
}
void _chop(out _Conic c1, out _Conic c2) {
var scale = 1.0f / (1.0f + this.w);
var newW = Mathf.Sqrt(0.5f + this.w * 0.5f);
var wp1X = this.w * this.x1;
var wp1Y = this.w * this.y1;
var mX = (this.x0 + (wp1X + wp1X) + this.x2) * scale * 0.5f;
var mY = (this.y0 + (wp1Y + wp1Y) + this.y2) * scale * 0.5f;
if (!(mX.isFinite() && mY.isFinite())) {
double w_d = this.w;
double w_2 = w_d * 2.0;
double scale_half = 1.0 / (1.0 + w_d) * 0.5;
mX = (float) ((this.x0 + w_2 * this.x1 + this.x2) * scale_half);
mY = (float) ((this.y0 + w_2 * this.y1 + this.y2) * scale_half);
}
c1 = new _Conic {
x0 = this.x0,
y0 = this.y0,
x1 = (this.x0 + wp1X) * scale,
y1 = (this.y0 + wp1Y) * scale,
x2 = mX,
y2 = mY,
w = newW,
};
c2 = new _Conic {
x0 = mX,
y0 = mY,
x1 = (wp1X + this.x2) * scale,
y1 = (wp1Y + this.y2) * scale,
x2 = this.x2,
y2 = this.y2,
w = newW,
};
}
}
class PathPath {
public int first;
public int count;

return;
}
var path = this._paths.Last();
var path = this._paths[this._paths.Count - 1];
path.closed = true;
}

}
else {
var mesh = new Mesh();
mesh.MarkDynamic();
mesh.hideFlags = HideFlags.HideAndDontSave;
return mesh;
}

6
Samples/UIWidgetsGallery/gallery/app.cs


public GalleryApp(
Key key = null,
UpdateUrlFetcher updateUrlFetcher = null,
bool enablePerformanceOverlay = true,
bool enableRasterCacheImagesCheckerboard = true,
bool enableOffscreenLayersCheckerboard = true,
bool enablePerformanceOverlay = false,
bool enableRasterCacheImagesCheckerboard = false,
bool enableOffscreenLayersCheckerboard = false,
VoidCallback onSendFeedback = null,
bool testMode = false
) : base(key: key) {

正在加载...
取消
保存