gewentao
6 年前
当前提交
120d9e31
共有 59 个文件被更改,包括 1806 次插入 和 330 次删除
-
2Assets/UIWidgets/Tests/Paragraph.cs
-
4Assets/UIWidgets/foundation/basic_types.cs
-
65Assets/UIWidgets/foundation/change_notifier.cs
-
11Assets/UIWidgets/gestures/recognizer.cs
-
36Assets/UIWidgets/rendering/viewport_offset.cs
-
8Assets/UIWidgets/ui/geometry.cs
-
14Assets/UIWidgets/ui/painting/canvas.cs
-
24Assets/UIWidgets/ui/painting/canvas_impl.cs
-
16Assets/UIWidgets/ui/painting/draw_cmd.cs
-
10Assets/UIWidgets/ui/painting/picture.cs
-
2Assets/UIWidgets/ui/txt/linebreaker.cs
-
110Assets/UIWidgets/ui/txt/paragraph.cs
-
4Assets/UIWidgets/widgets/framework.cs
-
3Assets/UIWidgets/ui/painting/txt.meta
-
42Assets/UIWidgets/ui/txt/paint_record.cs
-
3Assets/UIWidgets/ui/txt/paint_record.cs.meta
-
70Assets/UIWidgets/widgets/notification_listener.cs
-
3Assets/UIWidgets/widgets/notification_listener.cs.meta
-
75Assets/UIWidgets/widgets/scroll_matrics.cs
-
3Assets/UIWidgets/widgets/scroll_matrics.cs.meta
-
139Assets/UIWidgets/widgets/scroll_notification.cs
-
3Assets/UIWidgets/widgets/scroll_notification.cs.meta
-
53Assets/UIWidgets/widgets/scroll_notification.mixin.gen.cs
-
11Assets/UIWidgets/widgets/scroll_notification.mixin.gen.cs.meta
-
32Assets/UIWidgets/widgets/scroll_notification.mixin.njk
-
3Assets/UIWidgets/widgets/scroll_notification.mixin.njk.meta
-
352Assets/UIWidgets/widgets/scroll_physics.cs
-
3Assets/UIWidgets/widgets/scroll_physics.cs.meta
-
7Assets/UIWidgets/widgets/scroll_position.cs
-
3Assets/UIWidgets/widgets/scroll_position.cs.meta
-
169Assets/UIWidgets/widgets/scroll_simulation.cs
-
3Assets/UIWidgets/widgets/scroll_simulation.cs.meta
-
4Assets/UIWidgets/animation/curves.cs
-
44Assets/UIWidgets/physics/clamped_simulation.cs
-
3Assets/UIWidgets/physics/clamped_simulation.cs.meta
-
96Assets/UIWidgets/physics/friction_simulation.cs
-
3Assets/UIWidgets/physics/friction_simulation.cs.meta
-
36Assets/UIWidgets/physics/gravity_simulation.cs
-
3Assets/UIWidgets/physics/gravity_simulation.cs.meta
-
15Assets/UIWidgets/physics/simulation.cs
-
11Assets/UIWidgets/physics/simulation.cs.meta
-
238Assets/UIWidgets/physics/spring_simulation.cs
-
3Assets/UIWidgets/physics/spring_simulation.cs.meta
-
28Assets/UIWidgets/physics/tolerance.cs
-
3Assets/UIWidgets/physics/tolerance.cs.meta
-
14Assets/UIWidgets/physics/utils.cs
-
3Assets/UIWidgets/physics/utils.cs.meta
-
37Assets/UIWidgets/ui/painting/txt/font_manager.cs
-
80Assets/UIWidgets/ui/painting/txt/mesh_generator.cs
-
3Assets/UIWidgets/ui/painting/txt/mesh_generator.cs.meta
-
31Assets/UIWidgets/ui/painting/txt/text_blob.cs
-
3Assets/UIWidgets/ui/painting/txt/text_blob.cs.meta
-
73Assets/UIWidgets/ui/txt/font_manager.cs
-
119Assets/UIWidgets/ui/txt/mesh.cs
-
3Assets/UIWidgets/ui/txt/mesh.cs.meta
-
0/Assets/UIWidgets/ui/painting/txt/font_manager.cs.meta
|
|||
fileFormatVersion: 2 |
|||
guid: 9438a28ff5974aac92d56928b06692ad |
|||
timeCreated: 1536299863 |
|
|||
using UIWidgets.ui.txt; |
|||
|
|||
namespace UIWidgets.ui |
|||
{ |
|||
public class PaintRecord |
|||
{ |
|||
public PaintRecord(TextStyle style, TextBlob _text, |
|||
int line, double runWidth) |
|||
{ |
|||
this._style = style; |
|||
this._text = _text; |
|||
this._line = line; |
|||
this._runWidth = runWidth; |
|||
} |
|||
|
|||
public TextBlob text |
|||
{ |
|||
get { return _text; } |
|||
} |
|||
|
|||
public TextStyle style |
|||
{ |
|||
get { return _style; } |
|||
} |
|||
|
|||
public int line |
|||
{ |
|||
get { return _line; } |
|||
} |
|||
|
|||
public double runWidth |
|||
{ |
|||
get { return _runWidth; } |
|||
} |
|||
|
|||
private TextStyle _style; |
|||
private TextBlob _text; |
|||
private int _line; |
|||
private double _runWidth; |
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2695fb8e8f284b95ad9a175da41a9101 |
|||
timeCreated: 1536300023 |
|
|||
using System.Collections.Generic; |
|||
using UIWidgets.foundation; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
public delegate bool NotificationListenerCallback<T>(T notification) where T : Notification; |
|||
|
|||
public abstract class Notification { |
|||
protected virtual bool visitAncestor(Element element) { |
|||
if (element is StatelessElement) { |
|||
StatelessWidget widget = (StatelessWidget) element.widget; |
|||
var listener = widget as _NotificationListener; |
|||
if (listener != null) { |
|||
if (listener._dispatch(this, element)) { |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public void dispatch(BuildContext target) { |
|||
D.assert(target != null); |
|||
target.visitAncestorElements(this.visitAncestor); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
var description = new List<string>(); |
|||
this.debugFillDescription(description); |
|||
return string.Format("{0}({1})", this.GetType(), string.Join(", ", description.ToArray())); |
|||
} |
|||
|
|||
protected virtual void debugFillDescription(List<string> description) { |
|||
} |
|||
} |
|||
|
|||
interface _NotificationListener { |
|||
bool _dispatch(Notification notification, Element element); |
|||
} |
|||
|
|||
public class NotificationListener<T> : StatelessWidget, _NotificationListener where T : Notification { |
|||
public NotificationListener( |
|||
string key = null, |
|||
Widget child = null, |
|||
NotificationListenerCallback<T> onNotification = null) : base(key) { |
|||
this.child = child; |
|||
this.onNotification = onNotification; |
|||
} |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public readonly NotificationListenerCallback<T> onNotification; |
|||
|
|||
bool _NotificationListener._dispatch(Notification notification, Element element) { |
|||
if (this.onNotification != null && notification is T) { |
|||
bool result = this.onNotification((T) notification); |
|||
return result; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return this.child; |
|||
} |
|||
} |
|||
|
|||
public class LayoutChangedNotification : Notification { |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 647bb259966f4e4e8196f7c9c4ef56dc |
|||
timeCreated: 1536582324 |
|
|||
using System; |
|||
using UIWidgets.painting; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
public interface ScrollMetrics { |
|||
double minScrollExtent { get; } |
|||
|
|||
double maxScrollExtent { get; } |
|||
|
|||
double pixels { get; } |
|||
|
|||
double viewportDimension { get; } |
|||
|
|||
AxisDirection axisDirection { get; } |
|||
} |
|||
|
|||
public static class ScrollMetricsUtils { |
|||
public static Axis axis(this ScrollMetrics it) { |
|||
return AxisUtils.axisDirectionToAxis(it.axisDirection); |
|||
} |
|||
|
|||
public static bool outOfRange(this ScrollMetrics it) { |
|||
return it.pixels < it.minScrollExtent || it.pixels > it.maxScrollExtent; |
|||
} |
|||
|
|||
public static bool atEdge(this ScrollMetrics it) { |
|||
return it.pixels == it.minScrollExtent || it.pixels == it.maxScrollExtent; |
|||
} |
|||
|
|||
public static double extentBefore(this ScrollMetrics it) { |
|||
return Math.Max(it.pixels - it.minScrollExtent, 0.0); |
|||
} |
|||
|
|||
public static double extentInside(this ScrollMetrics it) { |
|||
return Math.Min(it.pixels, it.maxScrollExtent) - |
|||
Math.Max(it.pixels, it.minScrollExtent) + |
|||
Math.Min(it.viewportDimension, it.maxScrollExtent - it.minScrollExtent); |
|||
} |
|||
|
|||
public static double extentAfter(this ScrollMetrics it) { |
|||
return Math.Max(it.maxScrollExtent - it.pixels, 0.0); |
|||
} |
|||
} |
|||
|
|||
public class FixedScrollMetrics : ScrollMetrics { |
|||
public FixedScrollMetrics( |
|||
double minScrollExtent = 0.0, |
|||
double maxScrollExtent = 0.0, |
|||
double pixels = 0.0, |
|||
double viewportDimension = 0.0, |
|||
AxisDirection axisDirection = AxisDirection.down |
|||
) { |
|||
this.minScrollExtent = minScrollExtent; |
|||
this.maxScrollExtent = maxScrollExtent; |
|||
this.pixels = pixels; |
|||
this.viewportDimension = viewportDimension; |
|||
this.axisDirection = axisDirection; |
|||
} |
|||
|
|||
public double minScrollExtent { get; private set; } |
|||
|
|||
public double maxScrollExtent { get; private set; } |
|||
|
|||
public double pixels { get; private set; } |
|||
|
|||
public double viewportDimension { get; private set; } |
|||
|
|||
public AxisDirection axisDirection { get; private set; } |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}({1:F1})..[{2:F1}]..{3:F1})", |
|||
this.GetType(), this.extentBefore(), this.extentInside(), this.extentAfter()); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 25e09958cead4597adacd8c3dbf7b12f |
|||
timeCreated: 1536561228 |
|
|||
using System.Collections.Generic; |
|||
using UIWidgets.gestures; |
|||
using UIWidgets.rendering; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
public abstract class ScrollNotification : ViewportNotificationMixinLayoutChangedNotification { |
|||
protected ScrollNotification( |
|||
ScrollMetrics metrics = null, |
|||
BuildContext context = null |
|||
) { |
|||
this.metrics = metrics; |
|||
this.context = context; |
|||
} |
|||
|
|||
public readonly ScrollMetrics metrics; |
|||
|
|||
public readonly BuildContext context; |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
description.Add(this.metrics.ToString()); |
|||
} |
|||
|
|||
public static bool defaultScrollNotificationPredicate(ScrollNotification notification) { |
|||
return notification.depth == 0; |
|||
} |
|||
} |
|||
|
|||
public class ScrollStartNotification : ScrollNotification { |
|||
public ScrollStartNotification( |
|||
ScrollMetrics metrics = null, |
|||
BuildContext context = null, |
|||
DragStartDetails dragDetails = null |
|||
) : base(metrics: metrics, context: context) { |
|||
this.dragDetails = dragDetails; |
|||
} |
|||
|
|||
public readonly DragStartDetails dragDetails; |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
if (this.dragDetails != null) |
|||
description.Add(this.dragDetails.ToString()); |
|||
} |
|||
} |
|||
|
|||
public class ScrollUpdateNotification : ScrollNotification { |
|||
public ScrollUpdateNotification( |
|||
ScrollMetrics metrics = null, |
|||
BuildContext context = null, |
|||
DragUpdateDetails dragDetails = null, |
|||
double scrollDelta = 0 |
|||
) : base(metrics: metrics, context: context) { |
|||
this.dragDetails = dragDetails; |
|||
this.scrollDelta = scrollDelta; |
|||
} |
|||
|
|||
public readonly DragUpdateDetails dragDetails; |
|||
|
|||
public readonly double scrollDelta; |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
description.Add(string.Format("scrollDelta: {0}", this.scrollDelta)); |
|||
if (this.dragDetails != null) { |
|||
description.Add(this.dragDetails.ToString()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class OverscrollNotification : ScrollNotification { |
|||
public OverscrollNotification( |
|||
ScrollMetrics metrics = null, |
|||
BuildContext context = null, |
|||
DragUpdateDetails dragDetails = null, |
|||
double overscroll = 0, |
|||
double velocity = 0 |
|||
) : base(metrics: metrics, context: context) { |
|||
this.dragDetails = dragDetails; |
|||
this.overscroll = overscroll; |
|||
this.velocity = velocity; |
|||
} |
|||
|
|||
public readonly DragUpdateDetails dragDetails; |
|||
|
|||
public readonly double overscroll; |
|||
|
|||
public readonly double velocity; |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
description.Add(string.Format("overscroll: {0:F1}", this.overscroll)); |
|||
description.Add(string.Format("velocity: {0:F1}", this.velocity)); |
|||
if (this.dragDetails != null) { |
|||
description.Add(this.dragDetails.ToString()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class ScrollEndNotification : ScrollNotification { |
|||
public ScrollEndNotification( |
|||
ScrollMetrics metrics = null, |
|||
BuildContext context = null, |
|||
DragEndDetails dragDetails = null, |
|||
double overscroll = 0, |
|||
double velocity = 0 |
|||
) : base(metrics: metrics, context: context) { |
|||
this.dragDetails = dragDetails; |
|||
} |
|||
|
|||
public readonly DragEndDetails dragDetails; |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
if (this.dragDetails != null) { |
|||
description.Add(this.dragDetails.ToString()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class UserScrollNotification : ScrollNotification { |
|||
public UserScrollNotification( |
|||
ScrollMetrics metrics = null, |
|||
BuildContext context = null, |
|||
ScrollDirection direction = ScrollDirection.idle |
|||
) : base(metrics: metrics, context: context) { |
|||
this.direction = direction; |
|||
} |
|||
|
|||
public readonly ScrollDirection direction; |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
description.Add(string.Format("direction: {0}", this.direction)); |
|||
} |
|||
} |
|||
|
|||
public delegate bool ScrollNotificationPredicate(ScrollNotification notification); |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 76d5830e8d5948e8a312ac1699cbfcb1 |
|||
timeCreated: 1536583483 |
|
|||
using System.Collections.Generic; |
|||
using UIWidgets.rendering; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
|
|||
|
|||
public abstract class ViewportNotificationMixinNotification : Notification { |
|||
public int depth { |
|||
get { return _depth; } |
|||
} |
|||
|
|||
int _depth = 0; |
|||
|
|||
protected override bool visitAncestor(Element element) { |
|||
if (element is RenderObjectElement && element.renderObject is RenderAbstractViewport) { |
|||
this._depth += 1; |
|||
} |
|||
|
|||
return base.visitAncestor(element); |
|||
} |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
description.Add(string.Format("depth: {0} ({1})", |
|||
this._depth, this._depth == 0 ? "local" : "remote")); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
public abstract class ViewportNotificationMixinLayoutChangedNotification : LayoutChangedNotification { |
|||
public int depth { |
|||
get { return _depth; } |
|||
} |
|||
|
|||
int _depth = 0; |
|||
|
|||
protected override bool visitAncestor(Element element) { |
|||
if (element is RenderObjectElement && element.renderObject is RenderAbstractViewport) { |
|||
this._depth += 1; |
|||
} |
|||
|
|||
return base.visitAncestor(element); |
|||
} |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
description.Add(string.Format("depth: {0} ({1})", |
|||
this._depth, this._depth == 0 ? "local" : "remote")); |
|||
} |
|||
} |
|||
|
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 76fcf9dfb96bf49579e29af4f80c2d52 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using UIWidgets.rendering; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
{% macro ViewportNotificationMixin(with) %} |
|||
public abstract class ViewportNotificationMixin{{with}} : {{with}} { |
|||
public int depth { |
|||
get { return _depth; } |
|||
} |
|||
|
|||
int _depth = 0; |
|||
|
|||
protected override bool visitAncestor(Element element) { |
|||
if (element is RenderObjectElement && element.renderObject is RenderAbstractViewport) { |
|||
this._depth += 1; |
|||
} |
|||
|
|||
return base.visitAncestor(element); |
|||
} |
|||
|
|||
protected override void debugFillDescription(List<string> description) { |
|||
base.debugFillDescription(description); |
|||
description.Add(string.Format("depth: {0} ({1})", |
|||
this._depth, this._depth == 0 ? "local" : "remote")); |
|||
} |
|||
} |
|||
{% endmacro %} |
|||
|
|||
{{ ViewportNotificationMixin('Notification') }} |
|||
|
|||
{{ ViewportNotificationMixin('LayoutChangedNotification') }} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 50050e438a664e30957959a7a1da310c |
|||
timeCreated: 1536583983 |
|
|||
using System; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.gestures; |
|||
using UIWidgets.physics; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
public class ScrollPhysics { |
|||
public ScrollPhysics(ScrollPhysics parent) { |
|||
this.parent = parent; |
|||
} |
|||
|
|||
public readonly ScrollPhysics parent; |
|||
|
|||
protected ScrollPhysics buildParent(ScrollPhysics ancestor) { |
|||
if (this.parent == null) { |
|||
return ancestor; |
|||
} |
|||
|
|||
return this.parent.applyTo(ancestor) ?? ancestor; |
|||
} |
|||
|
|||
public virtual ScrollPhysics applyTo(ScrollPhysics ancestor) { |
|||
return new ScrollPhysics(parent: this.buildParent(ancestor)); |
|||
} |
|||
|
|||
public virtual double applyPhysicsToUserOffset(ScrollMetrics position, double offset) { |
|||
if (this.parent == null) { |
|||
return offset; |
|||
} |
|||
|
|||
return this.parent.applyPhysicsToUserOffset(position, offset); |
|||
} |
|||
|
|||
public virtual bool shouldAcceptUserOffset(ScrollMetrics position) { |
|||
if (this.parent == null) { |
|||
return position.pixels != 0.0 || position.minScrollExtent != position.maxScrollExtent; |
|||
} |
|||
|
|||
return this.parent.shouldAcceptUserOffset(position); |
|||
} |
|||
|
|||
public virtual double applyBoundaryConditions(ScrollMetrics position, double value) { |
|||
if (this.parent == null) { |
|||
return 0.0; |
|||
} |
|||
|
|||
return this.parent.applyBoundaryConditions(position, value); |
|||
} |
|||
|
|||
public virtual Simulation createBallisticSimulation(ScrollMetrics position, double velocity) { |
|||
if (parent == null) { |
|||
return null; |
|||
} |
|||
|
|||
return this.parent.createBallisticSimulation(position, velocity); |
|||
} |
|||
|
|||
static readonly SpringDescription _kDefaultSpring = SpringDescription.withDampingRatio( |
|||
mass: 0.5, |
|||
stiffness: 100.0, |
|||
ratio: 1.1 |
|||
); |
|||
|
|||
public virtual SpringDescription spring { |
|||
get { |
|||
if (this.parent == null) { |
|||
return ScrollPhysics._kDefaultSpring; |
|||
} |
|||
|
|||
return this.parent.spring ?? _kDefaultSpring; |
|||
} |
|||
} |
|||
|
|||
// todo: Handle the case of the device pixel ratio changing. use 1 as devicePixelRatio for now.
|
|||
static readonly Tolerance _kDefaultTolerance = new Tolerance( |
|||
velocity: 1.0 / (0.050 * 1), |
|||
distance: 1.0 / 1 |
|||
); |
|||
|
|||
public virtual Tolerance tolerance { |
|||
get { |
|||
if (this.parent == null) { |
|||
return _kDefaultTolerance; |
|||
} |
|||
|
|||
return this.parent.tolerance ?? _kDefaultTolerance; |
|||
} |
|||
} |
|||
|
|||
public virtual double minFlingDistance { |
|||
get { |
|||
if (this.parent == null) { |
|||
return Constants.kTouchSlop; |
|||
} |
|||
|
|||
return this.parent.minFlingDistance; |
|||
} |
|||
} |
|||
|
|||
public virtual double carriedMomentum(double existingVelocity) { |
|||
if (this.parent == null) { |
|||
return 0.0; |
|||
} |
|||
|
|||
return this.parent.carriedMomentum(existingVelocity); |
|||
} |
|||
|
|||
public virtual double minFlingVelocity { |
|||
get { |
|||
if (this.parent == null) { |
|||
return Constants.kMinFlingVelocity; |
|||
} |
|||
|
|||
return this.parent.minFlingVelocity; |
|||
} |
|||
} |
|||
|
|||
public virtual double maxFlingVelocity { |
|||
get { |
|||
if (this.parent == null) { |
|||
return Constants.kMaxFlingVelocity; |
|||
} |
|||
|
|||
return this.parent.maxFlingVelocity; |
|||
} |
|||
} |
|||
|
|||
public virtual double dragStartDistanceMotionThreshold { |
|||
get { |
|||
if (this.parent == null) { |
|||
return 0.0; |
|||
} |
|||
|
|||
return this.parent.dragStartDistanceMotionThreshold; |
|||
} |
|||
} |
|||
|
|||
public virtual bool allowImplicitScrolling { |
|||
get { return true; } |
|||
} |
|||
|
|||
public override string ToString() { |
|||
if (this.parent == null) { |
|||
return string.Format("{0}", this.GetType()); |
|||
} |
|||
|
|||
return string.Format("{0} -> {1}", this.GetType(), this.parent); |
|||
} |
|||
} |
|||
|
|||
|
|||
public class BouncingScrollPhysics : ScrollPhysics { |
|||
public BouncingScrollPhysics(ScrollPhysics parent = null) : base(parent: parent) { |
|||
} |
|||
|
|||
public override ScrollPhysics applyTo(ScrollPhysics ancestor) { |
|||
return new BouncingScrollPhysics(parent: this.buildParent(ancestor)); |
|||
} |
|||
|
|||
public double frictionFactor(double overscrollFraction) { |
|||
return 0.52 * Math.Pow(1 - overscrollFraction, 2); |
|||
} |
|||
|
|||
public override double applyPhysicsToUserOffset(ScrollMetrics position, double offset) { |
|||
D.assert(position.minScrollExtent <= position.maxScrollExtent); |
|||
|
|||
if (!position.outOfRange()) { |
|||
return offset; |
|||
} |
|||
|
|||
double overscrollPastStart = Math.Max(position.minScrollExtent - position.pixels, 0.0); |
|||
double overscrollPastEnd = Math.Max(position.pixels - position.maxScrollExtent, 0.0); |
|||
double overscrollPast = Math.Max(overscrollPastStart, overscrollPastEnd); |
|||
bool easing = (overscrollPastStart > 0.0 && offset < 0.0) || (overscrollPastEnd > 0.0 && offset > 0.0); |
|||
|
|||
double friction = easing |
|||
? this.frictionFactor((overscrollPast - offset.abs()) / position.viewportDimension) |
|||
: this.frictionFactor(overscrollPast / position.viewportDimension); |
|||
double direction = offset.sign(); |
|||
|
|||
return direction * _applyFriction(overscrollPast, offset.abs(), friction); |
|||
} |
|||
|
|||
static double _applyFriction(double extentOutside, double absDelta, double gamma) { |
|||
D.assert(absDelta > 0); |
|||
double total = 0.0; |
|||
if (extentOutside > 0) { |
|||
double deltaToLimit = extentOutside / gamma; |
|||
if (absDelta < deltaToLimit) { |
|||
return absDelta * gamma; |
|||
} |
|||
|
|||
total += extentOutside; |
|||
absDelta -= deltaToLimit; |
|||
} |
|||
|
|||
return total + absDelta; |
|||
} |
|||
|
|||
public override double applyBoundaryConditions(ScrollMetrics position, double value) { |
|||
return 0.0; |
|||
} |
|||
|
|||
public override Simulation createBallisticSimulation(ScrollMetrics position, double velocity) { |
|||
Tolerance tolerance = this.tolerance; |
|||
if (velocity.abs() >= tolerance.velocity || position.outOfRange()) { |
|||
return new BouncingScrollSimulation( |
|||
spring: spring, |
|||
position: position.pixels, |
|||
velocity: velocity * 0.91, |
|||
leadingExtent: position.minScrollExtent, |
|||
trailingExtent: position.maxScrollExtent, |
|||
tolerance: tolerance |
|||
); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public override double minFlingVelocity { |
|||
get { return Constants.kMinFlingVelocity * 2.0; } |
|||
} |
|||
|
|||
public override double carriedMomentum(double existingVelocity) { |
|||
return existingVelocity.sign() * Math.Min(0.000816 * Math.Pow(existingVelocity.abs(), 1.967), 40000.0); |
|||
} |
|||
|
|||
public override double dragStartDistanceMotionThreshold { |
|||
get { return 3.5; } |
|||
} |
|||
} |
|||
|
|||
|
|||
public class ClampingScrollPhysics : ScrollPhysics { |
|||
public ClampingScrollPhysics(ScrollPhysics parent = null) : base(parent: parent) { |
|||
} |
|||
|
|||
public override ScrollPhysics applyTo(ScrollPhysics ancestor) { |
|||
return new ClampingScrollPhysics(parent: this.buildParent(ancestor)); |
|||
} |
|||
|
|||
public override double applyBoundaryConditions(ScrollMetrics position, double value) { |
|||
D.assert(() => { |
|||
if (value == position.pixels) { |
|||
throw new UIWidgetsError( |
|||
string.Format( |
|||
"{0}.applyBoundaryConditions() was called redundantly.\n" + |
|||
"The proposed new position, {1}, is exactly equal to the current position of the " + |
|||
"given {2}, {3}.\n" + |
|||
"The applyBoundaryConditions method should only be called when the value is " + |
|||
"going to actually change the pixels, otherwise it is redundant.\n" + |
|||
"The physics object in question was:\n" + |
|||
" {4}\n" + |
|||
"The position object in question was:\n" + |
|||
" {5}\n", |
|||
this.GetType(), value, position.GetType(), position.pixels, this, position)); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
if (value < position.pixels && position.pixels <= position.minScrollExtent) { |
|||
return value - position.pixels; |
|||
} |
|||
|
|||
if (position.maxScrollExtent <= position.pixels && position.pixels < value) { |
|||
return value - position.pixels; |
|||
} |
|||
|
|||
if (value < position.minScrollExtent && position.minScrollExtent < position.pixels) { |
|||
return value - position.minScrollExtent; |
|||
} |
|||
|
|||
if (position.pixels < position.maxScrollExtent && position.maxScrollExtent < value) { |
|||
return value - position.maxScrollExtent; |
|||
} |
|||
|
|||
return 0.0; |
|||
} |
|||
|
|||
public override Simulation createBallisticSimulation(ScrollMetrics position, double velocity) { |
|||
Tolerance tolerance = this.tolerance; |
|||
if (position.outOfRange()) { |
|||
double? end = null; |
|||
if (position.pixels > position.maxScrollExtent) { |
|||
end = position.maxScrollExtent; |
|||
} |
|||
|
|||
if (position.pixels < position.minScrollExtent) { |
|||
end = position.minScrollExtent; |
|||
} |
|||
|
|||
D.assert(end != null); |
|||
return new ScrollSpringSimulation( |
|||
this.spring, |
|||
position.pixels, |
|||
position.maxScrollExtent, |
|||
Math.Min(0.0, velocity), |
|||
tolerance: tolerance |
|||
); |
|||
} |
|||
|
|||
if (velocity.abs() < tolerance.velocity) { |
|||
return null; |
|||
} |
|||
|
|||
if (velocity > 0.0 && position.pixels >= position.maxScrollExtent) { |
|||
return null; |
|||
} |
|||
|
|||
if (velocity < 0.0 && position.pixels <= position.minScrollExtent) { |
|||
return null; |
|||
} |
|||
|
|||
return new ClampingScrollSimulation( |
|||
position: position.pixels, |
|||
velocity: velocity, |
|||
tolerance: tolerance |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class AlwaysScrollableScrollPhysics : ScrollPhysics { |
|||
public AlwaysScrollableScrollPhysics(ScrollPhysics parent = null) : base(parent: parent) { |
|||
} |
|||
|
|||
public override ScrollPhysics applyTo(ScrollPhysics ancestor) { |
|||
return new AlwaysScrollableScrollPhysics(parent: this.buildParent(ancestor)); |
|||
} |
|||
|
|||
public override bool shouldAcceptUserOffset(ScrollMetrics position) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
public class NeverScrollableScrollPhysics : ScrollPhysics { |
|||
public NeverScrollableScrollPhysics(ScrollPhysics parent = null) : base(parent: parent) { |
|||
} |
|||
|
|||
public override ScrollPhysics applyTo(ScrollPhysics ancestor) { |
|||
return new NeverScrollableScrollPhysics(parent: this.buildParent(ancestor)); |
|||
} |
|||
|
|||
public override bool shouldAcceptUserOffset(ScrollMetrics position) { |
|||
return false; |
|||
} |
|||
|
|||
public override bool allowImplicitScrolling { |
|||
get { return false; } |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f58c175eda22408f95d902db1c4eec03 |
|||
timeCreated: 1536563659 |
|
|||
using UIWidgets.rendering; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
// public abstract class ScrollPosition : ViewportOffset, ScrollMetrics {
|
|||
//
|
|||
// }
|
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d1ce64af14b4434b8850b299aae20240 |
|||
timeCreated: 1536563588 |
|
|||
using System; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.physics; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
public class BouncingScrollSimulation : Simulation { |
|||
public BouncingScrollSimulation( |
|||
double position, |
|||
double velocity, |
|||
double leadingExtent, |
|||
double trailingExtent, |
|||
SpringDescription spring, |
|||
Tolerance tolerance = null |
|||
) : base(tolerance: tolerance) { |
|||
D.assert(leadingExtent <= trailingExtent); |
|||
D.assert(spring != null); |
|||
|
|||
this.leadingExtent = leadingExtent; |
|||
this.trailingExtent = trailingExtent; |
|||
this.spring = spring; |
|||
|
|||
if (position < leadingExtent) { |
|||
this._springSimulation = this._underscrollSimulation(position, velocity); |
|||
this._springTime = double.NegativeInfinity; |
|||
} else if (position > trailingExtent) { |
|||
this._springSimulation = this._overscrollSimulation(position, velocity); |
|||
this._springTime = double.NegativeInfinity; |
|||
} else { |
|||
this._frictionSimulation = new FrictionSimulation(0.135, position, velocity); |
|||
double finalX = this._frictionSimulation.finalX; |
|||
if (velocity > 0.0 && finalX > trailingExtent) { |
|||
this._springTime = this._frictionSimulation.timeAtX(trailingExtent); |
|||
this._springSimulation = this._overscrollSimulation( |
|||
trailingExtent, |
|||
Math.Min(this._frictionSimulation.dx(this._springTime), maxSpringTransferVelocity) |
|||
); |
|||
D.assert(this._springTime.isFinite()); |
|||
} else if (velocity < 0.0 && finalX < leadingExtent) { |
|||
this._springTime = this._frictionSimulation.timeAtX(leadingExtent); |
|||
this._springSimulation = this._underscrollSimulation( |
|||
leadingExtent, |
|||
Math.Min(this._frictionSimulation.dx(this._springTime), maxSpringTransferVelocity) |
|||
); |
|||
D.assert(this._springTime.isFinite()); |
|||
} else { |
|||
this._springTime = double.PositiveInfinity; |
|||
} |
|||
} |
|||
} |
|||
|
|||
const double maxSpringTransferVelocity = 5000.0; |
|||
|
|||
public readonly double leadingExtent; |
|||
|
|||
public readonly double trailingExtent; |
|||
|
|||
public readonly SpringDescription spring; |
|||
|
|||
readonly FrictionSimulation _frictionSimulation; |
|||
readonly Simulation _springSimulation; |
|||
readonly double _springTime; |
|||
double _timeOffset = 0.0; |
|||
|
|||
Simulation _underscrollSimulation(double x, double dx) { |
|||
return new ScrollSpringSimulation(this.spring, x, this.leadingExtent, dx); |
|||
} |
|||
|
|||
Simulation _overscrollSimulation(double x, double dx) { |
|||
return new ScrollSpringSimulation(this.spring, x, this.trailingExtent, dx); |
|||
} |
|||
|
|||
Simulation _simulation(double time) { |
|||
Simulation simulation; |
|||
if (time > this._springTime) { |
|||
this._timeOffset = this._springTime.isFinite() ? this._springTime : 0.0; |
|||
simulation = this._springSimulation; |
|||
} else { |
|||
this._timeOffset = 0.0; |
|||
simulation = this._frictionSimulation; |
|||
} |
|||
|
|||
simulation.tolerance = this.tolerance; |
|||
return simulation; |
|||
} |
|||
|
|||
public override double x(double time) { |
|||
return this._simulation(time).x(time - this._timeOffset); |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
return this._simulation(time).dx(time - this._timeOffset); |
|||
} |
|||
|
|||
public override bool isDone(double time) { |
|||
return this._simulation(time).isDone(time - this._timeOffset); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}(leadingExtent: {1}, trailingExtent: {2})", |
|||
this.GetType(), this.leadingExtent, this.trailingExtent); |
|||
} |
|||
} |
|||
|
|||
public class ClampingScrollSimulation : Simulation { |
|||
public ClampingScrollSimulation( |
|||
double position, |
|||
double velocity, |
|||
double friction = 0.015, |
|||
Tolerance tolerance = null |
|||
) : base(tolerance: tolerance) { |
|||
D.assert(_flingVelocityPenetration(0.0) == _initialVelocityPenetration); |
|||
this.position = position; |
|||
this.velocity = velocity; |
|||
this.friction = friction; |
|||
|
|||
this._duration = this._flingDuration(velocity); |
|||
this._distance = (velocity * this._duration / _initialVelocityPenetration).abs(); |
|||
} |
|||
|
|||
public readonly double position; |
|||
|
|||
public readonly double velocity; |
|||
|
|||
public readonly double friction; |
|||
|
|||
readonly double _duration; |
|||
|
|||
readonly double _distance; |
|||
|
|||
static readonly double _kDecelerationRate = Math.Log(0.78) / Math.Log(0.9); |
|||
|
|||
static double _decelerationForFriction(double friction) { |
|||
return friction * 61774.04968; |
|||
} |
|||
|
|||
double _flingDuration(double velocity) { |
|||
double scaledFriction = this.friction * _decelerationForFriction(0.84); |
|||
|
|||
double deceleration = Math.Log(0.35 * velocity.abs() / scaledFriction); |
|||
|
|||
return Math.Exp(deceleration / (_kDecelerationRate - 1.0)); |
|||
} |
|||
|
|||
const double _initialVelocityPenetration = 3.065; |
|||
|
|||
static double _flingDistancePenetration(double t) { |
|||
return (1.2 * t * t * t) - (3.27 * t * t) + (_initialVelocityPenetration * t); |
|||
} |
|||
|
|||
static double _flingVelocityPenetration(double t) { |
|||
return (3.6 * t * t) - (6.54 * t) + _initialVelocityPenetration; |
|||
} |
|||
|
|||
public override double x(double time) { |
|||
double t = (time / this._duration).clamp(0.0, 1.0); |
|||
return this.position + this._distance * _flingDistancePenetration(t) * this.velocity.sign(); |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
double t = (time / this._duration).clamp(0.0, 1.0); |
|||
return this._distance * _flingVelocityPenetration(t) * this.velocity.sign() / this._duration; |
|||
} |
|||
|
|||
public override bool isDone(double time) { |
|||
return time >= this._duration; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c2459448f9d744ec8e3240a0e1a88754 |
|||
timeCreated: 1536573658 |
|
|||
namespace UIWidgets.animation { |
|||
public abstract class Curve { |
|||
} |
|||
} |
|
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.physics { |
|||
public class ClampedSimulation : Simulation { |
|||
public ClampedSimulation(Simulation simulation, |
|||
double xMin = double.NegativeInfinity, |
|||
double xMax = double.PositiveInfinity, |
|||
double dxMin = double.NegativeInfinity, |
|||
double dxMax = double.PositiveInfinity |
|||
) { |
|||
D.assert(simulation != null); |
|||
D.assert(xMax >= xMin); |
|||
D.assert(dxMax >= dxMin); |
|||
|
|||
this.simulation = simulation; |
|||
this.xMin = xMin; |
|||
this.dxMin = dxMin; |
|||
this.dxMax = dxMax; |
|||
} |
|||
|
|||
public readonly Simulation simulation; |
|||
|
|||
public readonly double xMin; |
|||
|
|||
public readonly double xMax; |
|||
|
|||
public readonly double dxMin; |
|||
|
|||
public readonly double dxMax; |
|||
|
|||
public override double x(double time) { |
|||
return this.simulation.x(time).clamp(this.xMin, this.xMax); |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
return this.simulation.dx(time).clamp(this.dxMin, this.dxMax); |
|||
} |
|||
|
|||
public override bool isDone(double time) { |
|||
return this.simulation.isDone(time); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e1b026c0820446e69cc5ec78354b9418 |
|||
timeCreated: 1536564505 |
|
|||
using System; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.physics { |
|||
public class FrictionSimulation : Simulation { |
|||
public FrictionSimulation( |
|||
double drag, double position, double velocity, |
|||
Tolerance tolerance = null |
|||
) : base(tolerance: tolerance) { |
|||
this._drag = drag; |
|||
this._dragLog = Math.Log(drag); |
|||
this._x = position; |
|||
this._v = velocity; |
|||
} |
|||
|
|||
public static FrictionSimulation through(double startPosition, double endPosition, double startVelocity, |
|||
double endVelocity) { |
|||
D.assert(startVelocity == 0.0 || endVelocity == 0.0 || startVelocity.sign() == endVelocity.sign()); |
|||
D.assert(startVelocity.abs() >= endVelocity.abs()); |
|||
D.assert((endPosition - startPosition).sign() == startVelocity.sign()); |
|||
|
|||
return new FrictionSimulation( |
|||
FrictionSimulation._dragFor(startPosition, endPosition, startVelocity, endVelocity), |
|||
startPosition, |
|||
startVelocity, |
|||
tolerance: new Tolerance(velocity: endVelocity.abs()) |
|||
); |
|||
} |
|||
|
|||
readonly double _drag; |
|||
readonly double _dragLog; |
|||
readonly double _x; |
|||
readonly double _v; |
|||
|
|||
static double _dragFor(double startPosition, double endPosition, double startVelocity, double endVelocity) { |
|||
return Math.Pow(Math.E, (startVelocity - endVelocity) / (startPosition - endPosition)); |
|||
} |
|||
|
|||
public override double x(double time) { |
|||
return this._x + this._v * Math.Pow(this._drag, time) / this._dragLog - this._v / this._dragLog; |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
return this._v * Math.Pow(this._drag, time); |
|||
} |
|||
|
|||
public double finalX { |
|||
get { return this._x - this._v / this._dragLog; } |
|||
} |
|||
|
|||
public double timeAtX(double x) { |
|||
if (x == this._x) { |
|||
return 0.0; |
|||
} |
|||
|
|||
if (this._v == 0.0 || (this._v > 0 ? (x < this._x || x > this.finalX) : (x > this._x || x < this.finalX))) { |
|||
return double.PositiveInfinity; |
|||
} |
|||
|
|||
return Math.Log(this._dragLog * (x - this._x) / this._v + 1.0) / this._dragLog; |
|||
} |
|||
|
|||
public override bool isDone(double time) { |
|||
return this.dx(time).abs() < this.tolerance.velocity; |
|||
} |
|||
} |
|||
|
|||
public class BoundedFrictionSimulation : FrictionSimulation { |
|||
BoundedFrictionSimulation( |
|||
double drag, |
|||
double position, |
|||
double velocity, |
|||
double _minX, |
|||
double _maxX |
|||
) : base(drag, position, velocity) { |
|||
D.assert(position.clamp(_minX, _maxX) == position); |
|||
this._minX = _minX; |
|||
this._maxX = _maxX; |
|||
} |
|||
|
|||
readonly double _minX; |
|||
|
|||
readonly double _maxX; |
|||
|
|||
public override double x(double time) { |
|||
return base.x(time).clamp(this._minX, this._maxX); |
|||
} |
|||
|
|||
public override bool isDone(double time) { |
|||
return base.isDone(time) || |
|||
(this.x(time) - this._minX).abs() < this.tolerance.distance || |
|||
(this.x(time) - this._maxX).abs() < this.tolerance.distance; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1d5938e637654fddb90f71c0d24bb3c2 |
|||
timeCreated: 1536564777 |
|
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.physics { |
|||
public class GravitySimulation : Simulation { |
|||
public GravitySimulation( |
|||
double acceleration, |
|||
double distance, |
|||
double endDistance, |
|||
double velocity |
|||
) { |
|||
D.assert(endDistance >= 0); |
|||
this._a = acceleration; |
|||
this._x = distance; |
|||
this._v = velocity; |
|||
this._end = endDistance; |
|||
} |
|||
|
|||
readonly double _x; |
|||
readonly double _v; |
|||
readonly double _a; |
|||
readonly double _end; |
|||
|
|||
public override double x(double time) { |
|||
return this._x + this._v * time + 0.5 * this._a * time * time; |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
return this._v + time * this._a; |
|||
} |
|||
|
|||
public override bool isDone(double time) { |
|||
return this.x(time).abs() >= this._end; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f56308b79b45489b9cac8421a70c6795 |
|||
timeCreated: 1536566201 |
|
|||
namespace UIWidgets.physics { |
|||
public abstract class Simulation { |
|||
protected Simulation(Tolerance tolerance = null) { |
|||
this.tolerance = tolerance ?? Tolerance.defaultTolerance; |
|||
} |
|||
|
|||
public abstract double x(double time); |
|||
|
|||
public abstract double dx(double time); |
|||
|
|||
public abstract bool isDone(double time); |
|||
|
|||
public Tolerance tolerance; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2856e502c3bc04fd6b143e53f228f788 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UIWidgets.foundation; |
|||
|
|||
namespace UIWidgets.physics { |
|||
public class SpringDescription { |
|||
public SpringDescription( |
|||
double mass, |
|||
double stiffness, |
|||
double damping |
|||
) { |
|||
this.mass = mass; |
|||
this.stiffness = stiffness; |
|||
this.damping = damping; |
|||
} |
|||
|
|||
public static SpringDescription withDampingRatio( |
|||
double mass, |
|||
double stiffness, |
|||
double ratio = 1.0 |
|||
) { |
|||
var damping = ratio * 2.0 * Math.Sqrt(mass * stiffness); |
|||
return new SpringDescription(mass, stiffness, damping); |
|||
} |
|||
|
|||
public readonly double mass; |
|||
|
|||
public readonly double stiffness; |
|||
|
|||
public readonly double damping; |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}(mass {1:F1}, stiffness: {2:F1}, damping: {3:F1})", |
|||
this.GetType(), this.mass, this.stiffness, this.damping); |
|||
} |
|||
} |
|||
|
|||
public enum SpringType { |
|||
criticallyDamped, |
|||
underDamped, |
|||
overDamped, |
|||
} |
|||
|
|||
public class SpringSimulation : Simulation { |
|||
public SpringSimulation( |
|||
SpringDescription spring, |
|||
double start, |
|||
double end, |
|||
double velocity, |
|||
Tolerance tolerance = null |
|||
) : base(tolerance: tolerance) { |
|||
this._endPosition = end; |
|||
this._solution = _SpringSolution.create(spring, start - end, velocity); |
|||
} |
|||
|
|||
protected readonly double _endPosition; |
|||
readonly _SpringSolution _solution; |
|||
|
|||
public SpringType type { |
|||
get { return this._solution.type; } |
|||
} |
|||
|
|||
public override double x(double time) { |
|||
return this._endPosition + this._solution.x(time); |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
return this._solution.dx(time); |
|||
} |
|||
|
|||
public override bool isDone(double time) { |
|||
return PhysicsUtils.nearZero(this._solution.x(time), this.tolerance.distance) && |
|||
PhysicsUtils.nearZero(this._solution.dx(time), this.tolerance.velocity); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}(end: {1}, {2}", this.GetType(), this._endPosition, this.type); |
|||
} |
|||
} |
|||
|
|||
public class ScrollSpringSimulation : SpringSimulation { |
|||
public ScrollSpringSimulation( |
|||
SpringDescription spring, |
|||
double start, |
|||
double end, |
|||
double velocity, |
|||
Tolerance tolerance = null |
|||
) : base(spring, start, end, velocity, tolerance: tolerance) { |
|||
} |
|||
|
|||
public double x(double time) { |
|||
return this.isDone(time) ? this._endPosition : base.x(time); |
|||
} |
|||
} |
|||
|
|||
abstract class _SpringSolution { |
|||
public static _SpringSolution create( |
|||
SpringDescription spring, |
|||
double initialPosition, |
|||
double initialVelocity |
|||
) { |
|||
D.assert(spring != null); |
|||
double cmk = spring.damping * spring.damping - 4 * spring.mass * spring.stiffness; |
|||
|
|||
if (cmk == 0.0) { |
|||
return _CriticalSolution.create(spring, initialPosition, initialVelocity); |
|||
} |
|||
|
|||
if (cmk > 0.0) { |
|||
return _OverdampedSolution.create(spring, initialPosition, initialVelocity); |
|||
} |
|||
|
|||
return _UnderdampedSolution.create(spring, initialPosition, initialVelocity); |
|||
} |
|||
|
|||
public abstract double x(double time); |
|||
public abstract double dx(double time); |
|||
public abstract SpringType type { get; } |
|||
} |
|||
|
|||
class _CriticalSolution : _SpringSolution { |
|||
internal static _CriticalSolution create( |
|||
SpringDescription spring, |
|||
double distance, |
|||
double velocity |
|||
) { |
|||
double r = -spring.damping / (2.0 * spring.mass); |
|||
double c1 = distance; |
|||
double c2 = velocity / (r * distance); |
|||
return new _CriticalSolution(r, c1, c2); |
|||
} |
|||
|
|||
private _CriticalSolution( |
|||
double r, double c1, double c2 |
|||
) { |
|||
this._r = r; |
|||
this._c1 = c1; |
|||
this._c2 = c2; |
|||
} |
|||
|
|||
readonly double _r, _c1, _c2; |
|||
|
|||
public override double x(double time) { |
|||
return (this._c1 + this._c2 * time) * Math.Pow(Math.E, this._r * time); |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
double power = Math.Pow(Math.E, this._r * time); |
|||
return this._r * (this._c1 + this._c2 * time) * power + this._c2 * power; |
|||
} |
|||
|
|||
public override SpringType type { |
|||
get { return SpringType.criticallyDamped; } |
|||
} |
|||
} |
|||
|
|||
class _OverdampedSolution : _SpringSolution { |
|||
internal static _OverdampedSolution create( |
|||
SpringDescription spring, |
|||
double distance, |
|||
double velocity |
|||
) { |
|||
double cmk = spring.damping * spring.damping - 4 * spring.mass * spring.stiffness; |
|||
double r1 = (-spring.damping - Math.Sqrt(cmk)) / (2.0 * spring.mass); |
|||
double r2 = (-spring.damping + Math.Sqrt(cmk)) / (2.0 * spring.mass); |
|||
double c2 = (velocity - r1 * distance) / (r2 - r1); |
|||
double c1 = distance - c2; |
|||
return new _OverdampedSolution(r1, r2, c1, c2); |
|||
} |
|||
|
|||
private _OverdampedSolution( |
|||
double r1, double r2, double c1, double c2 |
|||
) { |
|||
this._r1 = r1; |
|||
this._r2 = r2; |
|||
this._c1 = c1; |
|||
this._c2 = c2; |
|||
} |
|||
|
|||
readonly double _r1, _r2, _c1, _c2; |
|||
|
|||
public override double x(double time) { |
|||
return this._c1 * Math.Pow(Math.E, this._r1 * time) + |
|||
this._c2 * Math.Pow(Math.E, this._r2 * time); |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
return this._c1 * this._r1 * Math.Pow(Math.E, this._r1 * time) + |
|||
this._c2 * this._r2 * Math.Pow(Math.E, this._r2 * time); |
|||
} |
|||
|
|||
public override SpringType type { |
|||
get { return SpringType.overDamped; } |
|||
} |
|||
} |
|||
|
|||
class _UnderdampedSolution : _SpringSolution { |
|||
internal static _UnderdampedSolution create( |
|||
SpringDescription spring, |
|||
double distance, |
|||
double velocity |
|||
) { |
|||
double w = Math.Sqrt(4.0 * spring.mass * spring.stiffness - |
|||
spring.damping * spring.damping) / (2.0 * spring.mass); |
|||
double r = -(spring.damping / 2.0 * spring.mass); |
|||
double c1 = distance; |
|||
double c2 = (velocity - r * distance) / w; |
|||
return new _UnderdampedSolution(w, r, c1, c2); |
|||
} |
|||
|
|||
private _UnderdampedSolution( |
|||
double w, double r, double c1, double c2 |
|||
) { |
|||
this._w = w; |
|||
this._r = r; |
|||
this._c1 = c1; |
|||
this._c2 = c2; |
|||
} |
|||
|
|||
readonly double _w, _r, _c1, _c2; |
|||
|
|||
public override double x(double time) { |
|||
return Math.Pow(Math.E, this._r * time) * |
|||
(this._c1 * Math.Cos(this._w * time) + this._c2 * Math.Sin(this._w * time)); |
|||
} |
|||
|
|||
public override double dx(double time) { |
|||
double power = Math.Pow(Math.E, this._r * time); |
|||
double cosine = Math.Cos(this._w * time); |
|||
double sine = Math.Sin(this._w * time); |
|||
return power * (this._c2 * this._w * cosine - this._c1 * this._w * sine) + |
|||
this._r * power * (this._c2 * sine + this._c1 * cosine); |
|||
} |
|||
|
|||
public override SpringType type { |
|||
get { return SpringType.underDamped; } |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8ed83c6d32a548d08ba79900e173dd53 |
|||
timeCreated: 1536566442 |
|
|||
namespace UIWidgets.physics { |
|||
public class Tolerance { |
|||
public Tolerance( |
|||
double distance = _epsilonDefault, |
|||
double time = _epsilonDefault, |
|||
double velocity = _epsilonDefault |
|||
) { |
|||
this.distance = distance; |
|||
this.time = time; |
|||
this.velocity = velocity; |
|||
} |
|||
|
|||
const double _epsilonDefault = 1e-3; |
|||
|
|||
public static readonly Tolerance defaultTolerance = new Tolerance(); |
|||
|
|||
public readonly double distance; |
|||
|
|||
public readonly double time; |
|||
|
|||
public readonly double velocity; |
|||
|
|||
public override string ToString() { |
|||
return string.Format("Tolerance(distance: ±{0}, time: ±{1}, velocity: ±{2})", |
|||
this.distance, this.time, this.velocity); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 24153b761064430a8482c0388fd41746 |
|||
timeCreated: 1536564124 |
|
|||
using UIWidgets.foundation; |
|||
|
|||
namespace UIWidgets.physics { |
|||
public class PhysicsUtils { |
|||
public static bool nearEqual(double a, double b, double epsilon) { |
|||
D.assert(epsilon >= 0.0); |
|||
return (a > (b - epsilon)) && (a < (b + epsilon)) || a == b; |
|||
} |
|||
|
|||
public static bool nearZero(double a, double epsilon) { |
|||
return nearEqual(a, 0.0, epsilon); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e65d36fdcaac4e92a77c930023bfd62f |
|||
timeCreated: 1536570487 |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgets.ui |
|||
{ |
|||
|
|||
public class FontManager |
|||
{ |
|||
private List<Font> _fonts = new List<Font>(); |
|||
|
|||
public static readonly FontManager instance = new FontManager(); |
|||
|
|||
public Font getOrCreate(string[] names, int fontSize) |
|||
{ |
|||
var founded = _fonts.Find((font) => |
|||
( |
|||
font.fontSize == fontSize && |
|||
(names == font.fontNames || (names != null && names.SequenceEqual(font.fontNames))))); |
|||
if (founded != null) |
|||
{ |
|||
return founded; |
|||
} |
|||
|
|||
Debug.Log(string.Format("Create new Font names={0}, size={1}", names, fontSize)); |
|||
var newFont = Font.CreateDynamicFontFromOSFont(names, |
|||
fontSize); |
|||
_fonts.Add(newFont); |
|||
return newFont; |
|||
} |
|||
|
|||
public Font getOrCreate(string name, int fontSize) |
|||
{ |
|||
return getOrCreate(new []{name}, fontSize); |
|||
} |
|||
} |
|||
} |
|
|||
using UIWidgets.ui.txt; |
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgets.ui.painting.txt |
|||
{ |
|||
public static class MeshGenrator |
|||
{ |
|||
public static Mesh generateMesh(TextBlob textBlob, double x, double y) |
|||
{ |
|||
var style = textBlob.style; |
|||
var font = FontManager.instance.getOrCreate(style.safeFontFamily, style.UnityFontSize); |
|||
var length = textBlob.end - textBlob.start; |
|||
var vertices = new Vector3[length * 4]; |
|||
var triangles = new int[length * 6]; |
|||
var uv = new Vector2[length * 4]; |
|||
var text = textBlob.text; |
|||
|
|||
var offset = new Vector3((float)Utils.PixelCorrectRound(x), (float)Utils.PixelCorrectRound(y), 0); |
|||
font.RequestCharactersInTexture(textBlob.text.Substring(textBlob.start, textBlob.end - textBlob.start), |
|||
style.UnityFontSize, style.UnityFontStyle); |
|||
for (int charIndex = 0; charIndex < length; ++charIndex) |
|||
{ |
|||
var ch = text[charIndex + textBlob.start]; |
|||
var position = textBlob.positions[charIndex + textBlob.start]; |
|||
|
|||
CharacterInfo charInfo = new CharacterInfo(); |
|||
if (Paragraph.isWordSpace(ch) || Paragraph.isLineEndSpace(ch) || ch== '\t') |
|||
{ |
|||
|
|||
vertices[4 * charIndex + 0] = vertices[4 * charIndex + 1] = |
|||
vertices[4 * charIndex + 2] = vertices[4 * charIndex + 3] = offset; |
|||
|
|||
uv[4 * charIndex + 0] = Vector2.zero; |
|||
uv[4 * charIndex + 1] = Vector2.zero; |
|||
uv[4 * charIndex + 2] = Vector2.zero; |
|||
uv[4 * charIndex + 3] = Vector2.zero; |
|||
} |
|||
else |
|||
{ |
|||
font.GetCharacterInfo(ch, out charInfo, style.UnityFontSize, style.UnityFontStyle); |
|||
vertices[4 * charIndex + 0] = offset + new Vector3((float)(position.x + charInfo.minX), |
|||
(float)(position.y - charInfo.maxY), 0); |
|||
vertices[4 * charIndex + 1] = offset + new Vector3((float)(position.x + charInfo.maxX), |
|||
(float)(position.y - charInfo.maxY), 0); |
|||
vertices[4 * charIndex + 2] = offset + new Vector3( |
|||
(float)(position.x + charInfo.maxX), (float)(position.y - charInfo.minY), 0); |
|||
vertices[4 * charIndex + 3] = offset + new Vector3( |
|||
(float)(position.x + charInfo.minX), (float)(position.y - charInfo.minY), 0); |
|||
|
|||
uv[4 * charIndex + 0] = charInfo.uvTopLeft; |
|||
uv[4 * charIndex + 1] = charInfo.uvTopRight; |
|||
uv[4 * charIndex + 2] = charInfo.uvBottomRight; |
|||
uv[4 * charIndex + 3] = charInfo.uvBottomLeft; |
|||
} |
|||
|
|||
triangles[6 * charIndex + 0] = 4 * charIndex + 0; |
|||
triangles[6 * charIndex + 1] = 4 * charIndex + 1; |
|||
triangles[6 * charIndex + 2] = 4 * charIndex + 2; |
|||
|
|||
triangles[6 * charIndex + 3] = 4 * charIndex + 0; |
|||
triangles[6 * charIndex + 4] = 4 * charIndex + 2; |
|||
triangles[6 * charIndex + 5] = 4 * charIndex + 3; |
|||
} |
|||
|
|||
var mesh = new Mesh() |
|||
{ |
|||
vertices = vertices, |
|||
triangles = triangles, |
|||
uv = uv |
|||
}; |
|||
var colors = new UnityEngine.Color[vertices.Length]; |
|||
for (var i = 0; i < colors.Length; i++) |
|||
{ |
|||
colors[i] = style.UnityColor; |
|||
} |
|||
mesh.colors = colors; |
|||
return mesh; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 79c7ef33071e4ec9b28b196b3e265bfa |
|||
timeCreated: 1536301684 |
|
|||
using System; |
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgets.ui.txt |
|||
{ |
|||
public class TextBlob |
|||
{ |
|||
public TextBlob(string text, int start, int end, Vector2d[] positions, TextStyle style, Rect bounds) |
|||
{ |
|||
Debug.Assert(start < end); |
|||
this.text = text; |
|||
this.start = start; |
|||
this.end = end; |
|||
this.positions = positions; |
|||
this.style = style; |
|||
this.bounds = bounds; |
|||
} |
|||
|
|||
public Rect boundsInText |
|||
{ |
|||
get { return bounds.shift(new Offset(positions[start].x, positions[start].y)); } |
|||
} |
|||
|
|||
public readonly string text; |
|||
public readonly int start; |
|||
public readonly int end; |
|||
public readonly Vector2d[] positions; |
|||
public readonly TextStyle style; |
|||
public readonly Rect bounds; // bounds with positions[start] as origin
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8fc95fa5caea426a80f19b2d0f99955f |
|||
timeCreated: 1536299888 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgets.ui |
|||
{ |
|||
public class FontEntry |
|||
{ |
|||
public readonly Font font; |
|||
private int _textureBuildVersion = 0; |
|||
|
|||
public FontEntry(Font font) |
|||
{ |
|||
this.font = font; |
|||
|
|||
} |
|||
|
|||
public int textureBuildVersion |
|||
{ |
|||
get { return _textureBuildVersion; } |
|||
} |
|||
|
|||
internal void onFontTextureRebuild() |
|||
{ |
|||
_textureBuildVersion++; |
|||
} |
|||
} |
|||
|
|||
public class FontManager |
|||
{ |
|||
private List<FontEntry> _fonts = new List<FontEntry>(); |
|||
|
|||
public static readonly FontManager instance = new FontManager(); |
|||
|
|||
private FontManager() |
|||
{ |
|||
Font.textureRebuilt += this.onFontTextureRebuilt; |
|||
} |
|||
|
|||
public FontEntry getOrCreate(string[] names, int fontSize) |
|||
{ |
|||
var founded = _fonts.Find((font) => |
|||
( |
|||
font.font.fontSize == fontSize && |
|||
(names == font.font.fontNames || (names != null && names.SequenceEqual(font.font.fontNames))))); |
|||
if (founded != null) |
|||
{ |
|||
return founded; |
|||
} |
|||
|
|||
Debug.Log(string.Format("Create new Font names={0}, size={1}", names, fontSize)); |
|||
var newFont = new FontEntry(Font.CreateDynamicFontFromOSFont(names, |
|||
fontSize)); |
|||
_fonts.Add(newFont); |
|||
return newFont; |
|||
} |
|||
|
|||
public FontEntry getOrCreate(string name, int fontSize) |
|||
{ |
|||
return getOrCreate(new []{name}, fontSize); |
|||
} |
|||
|
|||
private void onFontTextureRebuilt(Font font) |
|||
{ |
|||
var entry = _fonts.Find((f) => f.font == font); |
|||
if (entry != null) |
|||
{ |
|||
entry.onFontTextureRebuild(); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgets.ui |
|||
{ |
|||
public class TextMesh: IMesh |
|||
{ |
|||
private Mesh _mesh; |
|||
private FontEntry _fontEntry; |
|||
private string _text; |
|||
private StyledRuns.Run _run; |
|||
private int _textureVersion; |
|||
|
|||
public TextMesh(Vector2d pos, string text, Vector2d[] _characterPositions, FontEntry fontEntry, StyledRuns.Run run) |
|||
{ |
|||
_fontEntry = fontEntry; |
|||
_text = text; |
|||
this._run = run; |
|||
|
|||
var vertices = new Vector3[_text.Length * 4]; |
|||
var triangles = new int[_text.Length * 6]; |
|||
var font = fontEntry.font; |
|||
var offset = new Vector3((float)Utils.PixelCorrectRound(pos.x), (float)Utils.PixelCorrectRound(pos.y), 0); |
|||
font.RequestCharactersInTexture(_text.Substring(_run.start, _run.end - _run.start), |
|||
_run.style.UnityFontSize, _run.style.UnityFontStyle); |
|||
for (int charIndex = _run.start; charIndex < _run.end; ++charIndex) |
|||
{ |
|||
CharacterInfo charInfo = new CharacterInfo(); |
|||
if (_text[charIndex] != '\n' && _text[charIndex] != '\t') |
|||
{ |
|||
Debug.Assert(font.GetCharacterInfo(_text[charIndex], out charInfo, _run.style.UnityFontSize, _run.style.UnityFontStyle)); |
|||
var position = _characterPositions[charIndex]; |
|||
vertices[4 * charIndex + 0] = offset + new Vector3((float)(position.x + charInfo.minX), |
|||
(float)(position.y - charInfo.maxY), 0); |
|||
vertices[4 * charIndex + 1] = offset + new Vector3((float)(position.x + charInfo.maxX), |
|||
(float)(position.y - charInfo.maxY), 0); |
|||
vertices[4 * charIndex + 2] = offset + new Vector3( |
|||
(float)(position.x + charInfo.maxX), (float)(position.y - charInfo.minY), 0); |
|||
vertices[4 * charIndex + 3] = offset + new Vector3( |
|||
(float)(position.x + charInfo.minX), (float)(position.y - charInfo.minY), 0); |
|||
} |
|||
else |
|||
{ |
|||
vertices[4 * charIndex + 0] = vertices[4 * charIndex + 1] = |
|||
vertices[4 * charIndex + 2] = vertices[4 * charIndex + 3] = offset; |
|||
} |
|||
|
|||
triangles[6 * charIndex + 0] = 4 * charIndex + 0; |
|||
triangles[6 * charIndex + 1] = 4 * charIndex + 1; |
|||
triangles[6 * charIndex + 2] = 4 * charIndex + 2; |
|||
|
|||
triangles[6 * charIndex + 3] = 4 * charIndex + 0; |
|||
triangles[6 * charIndex + 4] = 4 * charIndex + 2; |
|||
triangles[6 * charIndex + 5] = 4 * charIndex + 3; |
|||
} |
|||
|
|||
var uv = getTextureUV(); |
|||
var mesh = new Mesh() |
|||
{ |
|||
vertices = vertices, |
|||
triangles = triangles, |
|||
uv = uv |
|||
}; |
|||
var colors = new UnityEngine.Color[vertices.Length]; |
|||
for (var i = 0; i < colors.Length; i++) |
|||
{ |
|||
colors[i] = _run.style.UnityColor; |
|||
} |
|||
|
|||
mesh.colors = colors; |
|||
_textureVersion = _fontEntry.textureBuildVersion; |
|||
_mesh = mesh; |
|||
} |
|||
|
|||
public void syncTextureUV() |
|||
{ |
|||
if (_fontEntry.textureBuildVersion != _textureVersion) // texture has been rebuilt, update the texture uv
|
|||
{ |
|||
_mesh.uv = getTextureUV(); |
|||
} |
|||
} |
|||
|
|||
public Mesh mesh |
|||
{ |
|||
get { return _mesh; } |
|||
} |
|||
|
|||
private Vector2[] getTextureUV() |
|||
{ |
|||
var font = _fontEntry.font; |
|||
var uv = _mesh == null ? new Vector2[_text.Length * 4] : _mesh.uv; |
|||
|
|||
for (int charIndex = _run.start; charIndex < _run.end; ++charIndex) |
|||
{ |
|||
CharacterInfo charInfo = new CharacterInfo(); |
|||
if (_text[charIndex] != '\n' && _text[charIndex] != '\t') |
|||
{ |
|||
font.GetCharacterInfo(_text[charIndex], out charInfo, _run.style.UnityFontSize, |
|||
_run.style.UnityFontStyle); |
|||
} |
|||
|
|||
if (Paragraph.isWordSpace(_text[charIndex]) || Paragraph.isLineEndSpace(_text[charIndex]) || _text[charIndex] == '\t') |
|||
{ |
|||
uv[4 * charIndex + 0] = Vector2.zero; |
|||
uv[4 * charIndex + 1] = Vector2.zero; |
|||
uv[4 * charIndex + 2] = Vector2.zero; |
|||
uv[4 * charIndex + 3] = Vector2.zero; |
|||
} else |
|||
{ |
|||
uv[4 * charIndex + 0] = charInfo.uvTopLeft; |
|||
uv[4 * charIndex + 1] = charInfo.uvTopRight; |
|||
uv[4 * charIndex + 2] = charInfo.uvBottomRight; |
|||
uv[4 * charIndex + 3] = charInfo.uvBottomLeft; |
|||
} |
|||
} |
|||
|
|||
return uv; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 96ec1d4b2b7d4bf59d4b2db221323ae9 |
|||
timeCreated: 1536283931 |
撰写
预览
正在加载...
取消
保存
Reference in new issue