fzhangtj
6 年前
当前提交
a3aea510
共有 25 个文件被更改,包括 2670 次插入 和 712 次删除
-
9Runtime/animation/tween.cs
-
30Runtime/engine/WidgetCanvas.cs
-
6Runtime/promise/Promise.cs
-
250Runtime/rendering/proxy_box.cs
-
213Runtime/widgets/app.cs
-
63Runtime/widgets/basic.cs
-
5Runtime/widgets/binding.cs
-
2Runtime/widgets/focus_manager.cs
-
940Runtime/widgets/navigator.cs
-
157Runtime/widgets/overlay.cs
-
6Runtime/widgets/page_storage.cs
-
9Runtime/widgets/widget_inspector.cs
-
7Samples/UIWidgetSample/TextInputCanvas.cs
-
48Runtime/widgets/modal_barrier.cs
-
11Runtime/widgets/modal_barrier.cs.meta
-
89Runtime/widgets/pages.cs
-
11Runtime/widgets/pages.cs.meta
-
757Runtime/widgets/routes.cs
-
11Runtime/widgets/routes.cs.meta
-
133Runtime/widgets/transitions.cs
-
11Runtime/widgets/transitions.cs.meta
-
502Samples/UIWidgetSample/Navigation.unity
-
7Samples/UIWidgetSample/Navigation.unity.meta
-
94Samples/UIWidgetSample/NavigationCanvas.cs
-
11Samples/UIWidgetSample/NavigationCanvas.cs.meta
|
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace Unity.UIWidgets.widgets { |
|||
public class ModalBarrier : StatelessWidget { |
|||
public readonly Color color; |
|||
public readonly bool dismissible; |
|||
|
|||
public ModalBarrier(Key key = null, Color color = null, bool dismissible = true) : base(key) { |
|||
this.color = color; |
|||
this.dismissible = dismissible; |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
//retur
|
|||
|
|||
return new GestureDetector( |
|||
onTapDown: details => { |
|||
if (this.dismissible) |
|||
Navigator.maybePop(context); |
|||
}, |
|||
behavior: HitTestBehavior.opaque, |
|||
child: new ConstrainedBox( |
|||
constraints: BoxConstraints.expand(), |
|||
child: this.color == null ? null : new DecoratedBox(decoration: new BoxDecoration(this.color)) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class AnimatedModalBarrier : AnimatedWidget { |
|||
public readonly bool dismissible; |
|||
|
|||
public AnimatedModalBarrier(Key key = null, Animation<Color> color = null, |
|||
bool dismissible = true) : base(key, color) { |
|||
this.dismissible = dismissible; |
|||
} |
|||
|
|||
public Animation<Color> color => (Animation<Color>)this.listenable; |
|||
|
|||
protected internal override Widget build(BuildContext context) { |
|||
return new ModalBarrier(color: this.color?.value, dismissible: this.dismissible); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 57f0a2412eaef4c9496cca93496c44e4 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace Unity.UIWidgets.widgets { |
|||
|
|||
public abstract class PageRoute : ModalRoute { |
|||
public readonly bool fullscreenDialog; |
|||
|
|||
public PageRoute(RouteSettings settings, bool fullscreenDialog = false) : base(settings) { |
|||
this.fullscreenDialog = fullscreenDialog; |
|||
} |
|||
|
|||
public override bool opaque => false; |
|||
|
|||
public override bool barrierDismissible => false; |
|||
|
|||
public override bool canTransitionTo(TransitionRoute nextRoute) { |
|||
return nextRoute is PageRoute; |
|||
} |
|||
|
|||
public override bool canTransitionFrom(TransitionRoute previousRoute) { |
|||
return previousRoute is PageRoute; |
|||
} |
|||
|
|||
public override AnimationController createAnimationController() { |
|||
var controller = base.createAnimationController(); |
|||
if (this.settings.isInitialRoute) |
|||
controller.setValue(1.0); |
|||
return controller; |
|||
} |
|||
} |
|||
|
|||
public class PageRouteBuilder : PageRoute { |
|||
public readonly RoutePageBuilder pageBuilder; |
|||
|
|||
public readonly RouteTransitionsBuilder transitionsBuilder; |
|||
|
|||
public PageRouteBuilder( |
|||
RouteSettings settings = null, |
|||
RoutePageBuilder pageBuilder = null, |
|||
RouteTransitionsBuilder transitionsBuilder = null, |
|||
TimeSpan? transitionDuration = null, |
|||
bool opaque = true, |
|||
bool barrierDismissible = false, |
|||
Color barrierColor = null, |
|||
string barrierLabel = null, |
|||
bool maintainState = true |
|||
) : base(settings) { |
|||
D.assert(pageBuilder != null); |
|||
this.opaque = opaque; |
|||
this.pageBuilder = pageBuilder; |
|||
this.transitionsBuilder = transitionsBuilder??this._defaultTransitionsBuilder; |
|||
this.transitionDuration = transitionDuration ?? TimeSpan.FromMilliseconds(300); |
|||
this.barrierColor = barrierColor; |
|||
this.maintainState = maintainState; |
|||
this.barrierLabel = barrierLabel; |
|||
this.barrierDismissible = barrierDismissible; |
|||
} |
|||
|
|||
public override TimeSpan transitionDuration { get; } |
|||
|
|||
public override bool opaque { get; } |
|||
|
|||
public override bool barrierDismissible { get; } |
|||
|
|||
public override Color barrierColor { get; } |
|||
|
|||
public override string barrierLabel { get; } |
|||
|
|||
public override bool maintainState { get; } |
|||
|
|||
Widget _defaultTransitionsBuilder(BuildContext context, Animation<double> |
|||
animation, Animation<double> secondaryAnimation, Widget child) { |
|||
return child; |
|||
} |
|||
|
|||
public override Widget buildPage(BuildContext context, Animation<double> animation, |
|||
Animation<double> secondaryAnimation) { |
|||
return this.pageBuilder(context, animation, secondaryAnimation); |
|||
} |
|||
|
|||
public override Widget buildTransitions(BuildContext context, Animation<double> animation, |
|||
Animation<double> secondaryAnimation, Widget child) { |
|||
return this.transitionsBuilder(context, animation, secondaryAnimation, child); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b42abffbabbf94d6c92274cfbc74eec0 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using RSG; |
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.scheduler; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace Unity.UIWidgets.widgets { |
|||
public abstract class OverlayRoute : Route { |
|||
readonly List<OverlayEntry> _overlayEntries = new List<OverlayEntry>(); |
|||
|
|||
public OverlayRoute( |
|||
RouteSettings settings = null |
|||
) : base(settings) { |
|||
} |
|||
|
|||
public override List<OverlayEntry> overlayEntries => this._overlayEntries; |
|||
|
|||
protected virtual bool finishedWhenPopped => true; |
|||
|
|||
public abstract ICollection<OverlayEntry> createOverlayEntries(); |
|||
|
|||
protected internal override void install(OverlayEntry insertionPoint) { |
|||
D.assert(this._overlayEntries.isEmpty()); |
|||
this._overlayEntries.AddRange(this.createOverlayEntries()); |
|||
this.navigator.overlay?.insertAll(this._overlayEntries, insertionPoint); |
|||
base.install(insertionPoint); |
|||
} |
|||
|
|||
protected internal override bool didPop(object result) { |
|||
var returnValue = base.didPop(result); |
|||
D.assert(returnValue); |
|||
if (this.finishedWhenPopped) this.navigator.finalizeRoute(this); |
|||
return returnValue; |
|||
} |
|||
|
|||
protected internal override void dispose() { |
|||
foreach (var entry in this._overlayEntries) entry.remove(); |
|||
|
|||
this._overlayEntries.Clear(); |
|||
base.dispose(); |
|||
} |
|||
} |
|||
|
|||
public abstract class TransitionRoute : OverlayRoute { |
|||
public TransitionRoute( |
|||
RouteSettings settings = null |
|||
) : base(settings) { |
|||
} |
|||
|
|||
public IPromise<object> completed { |
|||
get { return this._transitionCompleter; } |
|||
} |
|||
|
|||
internal readonly Promise<object> _transitionCompleter = new Promise<object>(); |
|||
|
|||
public virtual TimeSpan transitionDuration { get; } |
|||
|
|||
public virtual bool opaque { get; } |
|||
|
|||
|
|||
protected override bool finishedWhenPopped => this.controller.status == AnimationStatus.dismissed; |
|||
|
|||
public virtual Animation<double> animation { |
|||
get { return this._animation; } |
|||
} |
|||
|
|||
internal Animation<double> _animation; |
|||
|
|||
public AnimationController controller { |
|||
get { return this._controller; } |
|||
} |
|||
|
|||
internal AnimationController _controller; |
|||
|
|||
public virtual AnimationController createAnimationController() { |
|||
D.assert(this._transitionCompleter.CurState == PromiseState.Pending, |
|||
$"Cannot reuse a {this.GetType()} after disposing it."); |
|||
TimeSpan duration = this.transitionDuration; |
|||
D.assert(duration >= TimeSpan.Zero); |
|||
return new AnimationController( |
|||
duration: duration, |
|||
debugLabel: this.debugLabel, |
|||
vsync: this.navigator |
|||
); |
|||
} |
|||
|
|||
public virtual Animation<double> createAnimation() { |
|||
D.assert(this._transitionCompleter.CurState == PromiseState.Pending, |
|||
$"Cannot reuse a {this.GetType()} after disposing it."); |
|||
D.assert(this._controller != null); |
|||
return this._controller.view; |
|||
} |
|||
|
|||
object _result; |
|||
|
|||
internal void _handleStatusChanged(AnimationStatus status) { |
|||
switch (status) { |
|||
case AnimationStatus.completed: |
|||
if (this.overlayEntries.isNotEmpty()) |
|||
this.overlayEntries.first().opaque = this.opaque; |
|||
break; |
|||
case AnimationStatus.forward: |
|||
case AnimationStatus.reverse: |
|||
if (this.overlayEntries.isNotEmpty()) |
|||
this.overlayEntries.first().opaque = false; |
|||
break; |
|||
case AnimationStatus.dismissed: |
|||
D.assert(!this.overlayEntries.first().opaque); |
|||
// We might still be the current route if a subclass is controlling the
|
|||
// the transition and hits the dismissed status. For example, the iOS
|
|||
// back gesture drives this animation to the dismissed status before
|
|||
// popping the navigator.
|
|||
if (!this.isCurrent) { |
|||
this.navigator.finalizeRoute(this); |
|||
D.assert(this.overlayEntries.isEmpty()); |
|||
} |
|||
|
|||
break; |
|||
} |
|||
|
|||
this.changedInternalState(); |
|||
} |
|||
|
|||
public virtual Animation<double> secondaryAnimation { |
|||
get { return this._secondaryAnimation; } |
|||
} |
|||
|
|||
readonly ProxyAnimation _secondaryAnimation = new ProxyAnimation(Animations.kAlwaysDismissedAnimation); |
|||
|
|||
protected internal override void install(OverlayEntry insertionPoint) { |
|||
D.assert(!this._transitionCompleter.isCompleted, $"Cannot install a {this.GetType()} after disposing it."); |
|||
this._controller = this.createAnimationController(); |
|||
D.assert(this._controller != null, $"{this.GetType()}.createAnimationController() returned null."); |
|||
this._animation = this.createAnimation(); |
|||
D.assert(this._animation != null, $"{this.GetType()}.createAnimation() returned null."); |
|||
base.install(insertionPoint); |
|||
} |
|||
|
|||
protected internal override TickerFuture didPush() { |
|||
D.assert(this._controller != null, |
|||
$"{this.GetType()}.didPush called before calling install() or after calling dispose()."); |
|||
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it."); |
|||
this._animation.addStatusListener(this._handleStatusChanged); |
|||
return this._controller.forward(); |
|||
} |
|||
|
|||
protected internal override void didReplace(Route oldRoute) { |
|||
D.assert(this._controller != null, |
|||
$"{this.GetType()}.didReplace called before calling install() or after calling dispose()."); |
|||
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it."); |
|||
if (oldRoute is TransitionRoute route) |
|||
this._controller.setValue(route._controller.value); |
|||
this._animation.addStatusListener(this._handleStatusChanged); |
|||
base.didReplace(oldRoute); |
|||
} |
|||
|
|||
protected internal override bool didPop(object result) { |
|||
D.assert(this._controller != null, |
|||
$"{this.GetType()}.didPop called before calling install() or after calling dispose()."); |
|||
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it."); |
|||
this._result = result; |
|||
this._controller.reverse(); |
|||
return base.didPop(result); |
|||
} |
|||
|
|||
protected internal override void didPopNext(Route nextRoute) { |
|||
D.assert(this._controller != null, |
|||
$"{this.GetType()}.didPopNext called before calling install() or after calling dispose()."); |
|||
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it."); |
|||
this._updateSecondaryAnimation(nextRoute); |
|||
base.didPopNext(nextRoute); |
|||
} |
|||
|
|||
protected internal override void didChangeNext(Route nextRoute) { |
|||
D.assert(this._controller != null, |
|||
$"{this.GetType()}.didChangeNext called before calling install() or after calling dispose()."); |
|||
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it."); |
|||
this._updateSecondaryAnimation(nextRoute); |
|||
base.didChangeNext(nextRoute); |
|||
} |
|||
|
|||
void _updateSecondaryAnimation(Route nextRoute) { |
|||
if (nextRoute is TransitionRoute && this.canTransitionTo((TransitionRoute) nextRoute) && |
|||
((TransitionRoute) nextRoute).canTransitionFrom(this)) { |
|||
Animation<double> current = this._secondaryAnimation.parent; |
|||
if (current != null) { |
|||
if (current is TrainHoppingAnimation) { |
|||
TrainHoppingAnimation newAnimation = null; |
|||
newAnimation = new TrainHoppingAnimation( |
|||
((TrainHoppingAnimation) current).currentTrain, |
|||
((TransitionRoute) nextRoute)._animation, |
|||
onSwitchedTrain: () => { |
|||
D.assert(this._secondaryAnimation.parent == newAnimation); |
|||
D.assert(newAnimation.currentTrain == ((TransitionRoute) nextRoute)._animation); |
|||
this._secondaryAnimation.parent = newAnimation.currentTrain; |
|||
newAnimation.dispose(); |
|||
} |
|||
); |
|||
this._secondaryAnimation.parent = newAnimation; |
|||
((TrainHoppingAnimation) current).dispose(); |
|||
} |
|||
else { |
|||
this._secondaryAnimation.parent = |
|||
new TrainHoppingAnimation(current, ((TransitionRoute) nextRoute)._animation); |
|||
} |
|||
} |
|||
else { |
|||
this._secondaryAnimation.parent = ((TransitionRoute) nextRoute)._animation; |
|||
} |
|||
} |
|||
else { |
|||
this._secondaryAnimation.parent = Animations.kAlwaysDismissedAnimation; |
|||
} |
|||
} |
|||
|
|||
|
|||
public virtual bool canTransitionTo(TransitionRoute nextRoute) => true; |
|||
|
|||
public virtual bool canTransitionFrom(TransitionRoute previousRoute) => true; |
|||
|
|||
protected internal override void dispose() { |
|||
D.assert(!this._transitionCompleter.isCompleted, $"Cannot dispose a {this.GetType()} twice."); |
|||
this._controller?.dispose(); |
|||
this._transitionCompleter.Resolve(this._result); |
|||
base.dispose(); |
|||
} |
|||
|
|||
public string debugLabel => $"{this.GetType()}"; |
|||
|
|||
public override string ToString() { |
|||
return $"{this.GetType()}(animation: {this._controller}"; |
|||
} |
|||
} |
|||
|
|||
public class LocalHistoryEntry { |
|||
public LocalHistoryEntry(VoidCallback onRemove = null) { |
|||
this.onRemove = onRemove; |
|||
} |
|||
|
|||
public readonly VoidCallback onRemove; |
|||
|
|||
internal LocalHistoryRoute _owner; |
|||
|
|||
public void remove() { |
|||
this._owner.removeLocalHistoryEntry(this); |
|||
D.assert(this._owner == null); |
|||
} |
|||
|
|||
internal void _notifyRemoved() { |
|||
this.onRemove?.Invoke(); |
|||
} |
|||
} |
|||
|
|||
|
|||
public interface LocalHistoryRoute { |
|||
void addLocalHistoryEntry(LocalHistoryEntry entry); |
|||
void removeLocalHistoryEntry(LocalHistoryEntry entry); |
|||
|
|||
Route route { get; } |
|||
} |
|||
|
|||
// todo make it to mixin
|
|||
public abstract class LocalHistoryRouteTransitionRoute : TransitionRoute, LocalHistoryRoute { |
|||
List<LocalHistoryEntry> _localHistory; |
|||
|
|||
protected LocalHistoryRouteTransitionRoute(RouteSettings settings = null) : base(settings: settings) { |
|||
} |
|||
|
|||
public void addLocalHistoryEntry(LocalHistoryEntry entry) { |
|||
D.assert(entry._owner == null); |
|||
entry._owner = this; |
|||
this._localHistory = this._localHistory ?? new List<LocalHistoryEntry>(); |
|||
var wasEmpty = this._localHistory.isEmpty(); |
|||
this._localHistory.Add(entry); |
|||
if (wasEmpty) |
|||
this.changedInternalState(); |
|||
} |
|||
|
|||
public void removeLocalHistoryEntry(LocalHistoryEntry entry) { |
|||
D.assert(entry != null); |
|||
D.assert(entry._owner == this); |
|||
D.assert(this._localHistory.Contains(entry)); |
|||
this._localHistory.Remove(entry); |
|||
entry._owner = null; |
|||
entry._notifyRemoved(); |
|||
if (this._localHistory.isEmpty()) this.changedInternalState(); |
|||
} |
|||
|
|||
public override IPromise<RoutePopDisposition> willPop() { |
|||
if (this.willHandlePopInternally) |
|||
return Promise<RoutePopDisposition>.Resolved(RoutePopDisposition.pop); |
|||
return base.willPop(); |
|||
} |
|||
|
|||
protected internal override bool didPop(object result) { |
|||
if (this._localHistory != null && this._localHistory.isNotEmpty()) { |
|||
var entry = this._localHistory.removeLast(); |
|||
D.assert(entry._owner == this); |
|||
entry._owner = null; |
|||
entry._notifyRemoved(); |
|||
if (this._localHistory.isEmpty()) |
|||
this.changedInternalState(); |
|||
return false; |
|||
} |
|||
|
|||
return base.didPop(result); |
|||
} |
|||
|
|||
public override bool willHandlePopInternally => this._localHistory != null && this._localHistory.isNotEmpty(); |
|||
public Route route => this; |
|||
} |
|||
|
|||
|
|||
public class _ModalScopeStatus : InheritedWidget { |
|||
public _ModalScopeStatus(Key key = null, bool isCurrent = false, |
|||
bool canPop = false, Route route = null, Widget child = null) : base(key: key, child: child) { |
|||
D.assert(route != null); |
|||
D.assert(child != null); |
|||
|
|||
this.isCurrent = isCurrent; |
|||
this.canPop = canPop; |
|||
this.route = route; |
|||
} |
|||
|
|||
public readonly bool isCurrent; |
|||
public readonly bool canPop; |
|||
public readonly Route route; |
|||
|
|||
public override bool updateShouldNotify(InheritedWidget oldWidget) { |
|||
return this.isCurrent != ((_ModalScopeStatus) oldWidget).isCurrent || |
|||
this.canPop != ((_ModalScopeStatus) oldWidget).canPop || |
|||
this.route != ((_ModalScopeStatus) oldWidget).route; |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder description) { |
|||
base.debugFillProperties(description); |
|||
description.add(new FlagProperty("isCurrent", value: this.isCurrent, ifTrue: "active", ifFalse: "inactive")); |
|||
description.add(new FlagProperty("canPop", value: this.canPop, ifTrue: "can pop")); |
|||
} |
|||
} |
|||
|
|||
public class _ModalScope : StatefulWidget { |
|||
public _ModalScope(Key key = null, ModalRoute route = null) : base(key) { |
|||
this.route = route; |
|||
} |
|||
|
|||
public readonly ModalRoute route; |
|||
|
|||
public override State createState() { |
|||
return new _ModalScopeState(); |
|||
} |
|||
} |
|||
|
|||
public class _ModalScopeState : State<_ModalScope> { |
|||
Widget _page; |
|||
|
|||
Listenable _listenable; |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
var animations = new List<Listenable> { }; |
|||
if (this.widget.route.animation != null) |
|||
animations.Add(this.widget.route.animation); |
|||
if (this.widget.route.secondaryAnimation != null) |
|||
animations.Add(this.widget.route.secondaryAnimation); |
|||
this._listenable = ListenableUtils.merge(animations); |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|||
base.didUpdateWidget(oldWidget); |
|||
D.assert(this.widget.route == ((_ModalScope) oldWidget).route); |
|||
} |
|||
|
|||
public override void didChangeDependencies() { |
|||
base.didChangeDependencies(); |
|||
this._page = null; |
|||
} |
|||
|
|||
internal void _forceRebuildPage() { |
|||
this.setState(() => { this._page = null; }); |
|||
} |
|||
|
|||
internal void _routeSetState(VoidCallback fn) { |
|||
this.setState(fn); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
this._page = this._page ?? new RepaintBoundary( |
|||
key: this.widget.route._subtreeKey, // immutable
|
|||
child: new Builder( |
|||
builder: (BuildContext _context) => this.widget.route.buildPage( |
|||
_context, |
|||
this.widget.route.animation, |
|||
this.widget.route.secondaryAnimation |
|||
)) |
|||
); |
|||
|
|||
return new _ModalScopeStatus( |
|||
route: this.widget.route, |
|||
isCurrent: this.widget.route.isCurrent, |
|||
canPop: this.widget.route.canPop, |
|||
child: new Offstage( |
|||
offstage: this.widget.route.offstage, |
|||
child: new PageStorage( |
|||
bucket: this.widget.route._storageBucket, |
|||
child: new FocusScope( |
|||
node: this.widget.route.focusScopeNode, |
|||
child: new RepaintBoundary( |
|||
child: new AnimatedBuilder( |
|||
animation: this._listenable, // immutable
|
|||
builder: (BuildContext _context, Widget child) => |
|||
this.widget.route.buildTransitions( |
|||
_context, |
|||
this.widget.route.animation, |
|||
this.widget.route.secondaryAnimation, |
|||
new IgnorePointer( |
|||
ignoring: this.widget.route.animation?.status == |
|||
AnimationStatus.reverse, |
|||
child: child |
|||
) |
|||
), |
|||
child: this._page |
|||
) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public abstract class ModalRoute : LocalHistoryRouteTransitionRoute { |
|||
protected ModalRoute(RouteSettings settings) : base(settings) { |
|||
} |
|||
|
|||
public static Color _kTransparent = new Color(0x00000000); |
|||
|
|||
public static ModalRoute of(BuildContext context) { |
|||
_ModalScopeStatus widget = |
|||
(_ModalScopeStatus) context.inheritFromWidgetOfExactType(typeof(_ModalScopeStatus)); |
|||
return (ModalRoute) widget?.route; |
|||
} |
|||
|
|||
protected virtual void setState(VoidCallback fn) { |
|||
if (this._scopeKey.currentState != null) { |
|||
this._scopeKey.currentState._routeSetState(fn); |
|||
} |
|||
else { |
|||
// The route isn't currently visible, so we don't have to call its setState
|
|||
// method, but we do still need to call the fn callback, otherwise the state
|
|||
// in the route won't be updated!
|
|||
fn(); |
|||
} |
|||
} |
|||
|
|||
public RoutePredicate withName(String name) { |
|||
return (Route route) => !route.willHandlePopInternally |
|||
&& route is ModalRoute |
|||
&& route.settings.name == name; |
|||
} |
|||
|
|||
public abstract Widget buildPage(BuildContext context, Animation<double> animation, |
|||
Animation<double> secondaryAnimation); |
|||
|
|||
public virtual Widget buildTransitions( |
|||
BuildContext context, |
|||
Animation<double> animation, |
|||
Animation<double> secondaryAnimation, |
|||
Widget child |
|||
) { |
|||
return child; |
|||
} |
|||
|
|||
public readonly FocusScopeNode focusScopeNode = new FocusScopeNode(); |
|||
|
|||
protected internal override void install(OverlayEntry insertionPoint) { |
|||
base.install(insertionPoint); |
|||
this._animationProxy = new ProxyAnimation(base.animation); |
|||
this._secondaryAnimationProxy = new ProxyAnimation(base.secondaryAnimation); |
|||
} |
|||
|
|||
protected internal override TickerFuture didPush() { |
|||
this.navigator.focusScopeNode.setFirstFocus(this.focusScopeNode); |
|||
return base.didPush(); |
|||
} |
|||
|
|||
protected internal override void dispose() { |
|||
this.focusScopeNode.detach(); |
|||
base.dispose(); |
|||
} |
|||
|
|||
public virtual bool barrierDismissible { get; } |
|||
|
|||
|
|||
public virtual Color barrierColor { get; } |
|||
|
|||
|
|||
public virtual string barrierLabel { get; } |
|||
|
|||
public virtual bool maintainState { get; } |
|||
|
|||
public bool offstage { |
|||
get => this._offstage; |
|||
set { |
|||
if (this._offstage == value) |
|||
return; |
|||
this.setState(() => { this._offstage = value; }); |
|||
this._animationProxy.parent = this._offstage ? Animations.kAlwaysCompleteAnimation : base.animation; |
|||
this._secondaryAnimationProxy.parent = this._offstage ? Animations.kAlwaysDismissedAnimation : base.secondaryAnimation; |
|||
} |
|||
} |
|||
|
|||
bool _offstage = false; |
|||
|
|||
public BuildContext subtreeContext => this._subtreeKey.currentContext; |
|||
|
|||
public override Animation<double> animation => this._animationProxy; |
|||
ProxyAnimation _animationProxy; |
|||
|
|||
public override Animation<double> secondaryAnimation => this._secondaryAnimationProxy; |
|||
ProxyAnimation _secondaryAnimationProxy; |
|||
|
|||
readonly List<WillPopCallback> _willPopCallbacks = new List<WillPopCallback>(); |
|||
|
|||
public override IPromise<RoutePopDisposition> willPop() { |
|||
_ModalScopeState scope = this._scopeKey.currentState; |
|||
D.assert(scope != null); |
|||
|
|||
var callbacks = new List<WillPopCallback>(this._willPopCallbacks); |
|||
Promise<RoutePopDisposition> result = new Promise<RoutePopDisposition>(); |
|||
Action<int> fn = null; |
|||
fn = (int index) => { |
|||
if (index < callbacks.Count) { |
|||
callbacks[index]().Then((pop) => { |
|||
if (!pop) { |
|||
result.Resolve(RoutePopDisposition.doNotPop); |
|||
} |
|||
else { |
|||
fn(index + 1); |
|||
} |
|||
}); |
|||
} |
|||
else { |
|||
base.willPop().Then((pop) => result.Resolve(pop)); |
|||
} |
|||
}; |
|||
fn(0); |
|||
return result; |
|||
} |
|||
|
|||
public void addScopedWillPopCallback(WillPopCallback callback) { |
|||
D.assert(this._scopeKey.currentState != null, |
|||
"Tried to add a willPop callback to a route that is not currently in the tree."); |
|||
this._willPopCallbacks.Add(callback); |
|||
} |
|||
|
|||
public void removeScopedWillPopCallback(WillPopCallback callback) { |
|||
D.assert(this._scopeKey.currentState != null, |
|||
"Tried to remove a willPop callback from a route that is not currently in the tree."); |
|||
this._willPopCallbacks.Remove(callback); |
|||
} |
|||
|
|||
protected bool hasScopedWillPopCallback => this._willPopCallbacks.isNotEmpty(); |
|||
|
|||
protected internal override void didChangePrevious(Route previousRoute) { |
|||
base.didChangePrevious(previousRoute); |
|||
this.changedInternalState(); |
|||
} |
|||
|
|||
protected internal override void changedInternalState() { |
|||
base.changedInternalState(); |
|||
this.setState(() => { }); |
|||
this._modalBarrier.markNeedsBuild(); |
|||
} |
|||
|
|||
protected internal override void changedExternalState() { |
|||
base.changedExternalState(); |
|||
this._scopeKey.currentState?._forceRebuildPage(); |
|||
} |
|||
|
|||
public bool canPop => !this.isFirst || this.willHandlePopInternally; |
|||
|
|||
|
|||
readonly GlobalKey<_ModalScopeState> _scopeKey = new LabeledGlobalKey<_ModalScopeState>(); |
|||
internal readonly GlobalKey _subtreeKey = new LabeledGlobalKey<_ModalScopeState>(); |
|||
internal readonly PageStorageBucket _storageBucket = new PageStorageBucket(); |
|||
|
|||
static readonly Animatable<double> _easeCurveTween = new CurveTween(curve: Curves.ease); |
|||
OverlayEntry _modalBarrier; |
|||
|
|||
Widget _buildModalBarrier(BuildContext context) { |
|||
Widget barrier; |
|||
if (this.barrierColor != null && !this.offstage) { |
|||
// changedInternalState is called if these update
|
|||
D.assert(this.barrierColor != _kTransparent); |
|||
Animation<Color> color = |
|||
new ColorTween( |
|||
begin: _kTransparent, |
|||
end: this.barrierColor // changedInternalState is called if this updates
|
|||
).chain(_easeCurveTween).animate(this.animation); |
|||
barrier = new AnimatedModalBarrier( |
|||
color: color, |
|||
dismissible: this.barrierDismissible |
|||
); |
|||
} |
|||
else { |
|||
barrier = new ModalBarrier( |
|||
dismissible: this.barrierDismissible |
|||
); |
|||
} |
|||
|
|||
return new IgnorePointer( |
|||
ignoring: this.animation.status == AnimationStatus.reverse || this.animation.status == AnimationStatus.dismissed, |
|||
child: barrier |
|||
); |
|||
} |
|||
|
|||
Widget _modalScopeCache; |
|||
|
|||
Widget _buildModalScope(BuildContext context) { |
|||
return this._modalScopeCache = this._modalScopeCache ?? new _ModalScope( |
|||
key: this._scopeKey, |
|||
route: this |
|||
// _ModalScope calls buildTransitions() and buildChild(), defined above
|
|||
); |
|||
} |
|||
|
|||
public override ICollection<OverlayEntry> createOverlayEntries() { |
|||
this._modalBarrier = new OverlayEntry(builder: this._buildModalBarrier); |
|||
var content = new OverlayEntry( |
|||
builder: this._buildModalScope, maintainState: this.maintainState |
|||
); |
|||
return new List<OverlayEntry> {this._modalBarrier, content}; |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return $"{this.GetType()}({this.settings}, animation: {this._animation})"; |
|||
} |
|||
} |
|||
|
|||
abstract class PopupRoute : ModalRoute { |
|||
protected PopupRoute( |
|||
RouteSettings settings = null |
|||
) : base(settings: settings) { |
|||
} |
|||
|
|||
public override bool opaque => false; |
|||
|
|||
public override bool maintainState => true; |
|||
} |
|||
|
|||
public class RouteObserve<R> : NavigatorObserver where R : Route { |
|||
readonly Dictionary<R, HashSet<RouteAware>> _listeners = new Dictionary<R, HashSet<RouteAware>>(); |
|||
|
|||
public void subscribe(RouteAware routeAware, R route) { |
|||
D.assert(routeAware != null); |
|||
D.assert(route != null); |
|||
HashSet<RouteAware> subscribers = this._listeners.putIfAbsent(route, () => new HashSet<RouteAware>()); |
|||
if (subscribers.Add(routeAware)) { |
|||
routeAware.didPush(); |
|||
} |
|||
} |
|||
|
|||
public void unsubscribe(RouteAware routeAware) { |
|||
D.assert(routeAware != null); |
|||
foreach (R route in this._listeners.Keys) { |
|||
HashSet<RouteAware> subscribers = this._listeners[route]; |
|||
subscribers?.Remove(routeAware); |
|||
} |
|||
} |
|||
|
|||
public override void didPop(Route route, Route previousRoute) { |
|||
if (route is R && previousRoute is R) { |
|||
var previousSubscribers = this._listeners.getOrDefault((R) previousRoute); |
|||
|
|||
if (previousSubscribers != null) { |
|||
foreach (RouteAware routeAware in previousSubscribers) { |
|||
routeAware.didPopNext(); |
|||
} |
|||
} |
|||
|
|||
var subscribers = this._listeners.getOrDefault((R) route); |
|||
|
|||
if (subscribers != null) { |
|||
foreach (RouteAware routeAware in subscribers) { |
|||
routeAware.didPop(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public override void didPush(Route route, Route previousRoute) { |
|||
if (route is R && previousRoute is R) { |
|||
var previousSubscribers = this._listeners.getOrDefault((R) previousRoute); |
|||
|
|||
if (previousSubscribers != null) { |
|||
foreach (RouteAware routeAware in previousSubscribers) { |
|||
routeAware.didPushNext(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public interface RouteAware { |
|||
void didPopNext(); |
|||
|
|||
void didPush(); |
|||
|
|||
void didPop(); |
|||
|
|||
void didPushNext(); |
|||
} |
|||
|
|||
internal class _DialogRoute : PopupRoute { |
|||
internal _DialogRoute(RoutePageBuilder pageBuilder = null, bool barrierDismissible = true, |
|||
string barrierLabel = null, |
|||
Color barrierColor = null, |
|||
TimeSpan? transitionDuration = null, |
|||
RouteTransitionsBuilder transitionBuilder = null, |
|||
RouteSettings setting = null) : base(settings: setting) { |
|||
this._pageBuilder = pageBuilder; |
|||
this.barrierDismissible = barrierDismissible; |
|||
this.barrierLabel = barrierLabel; |
|||
this.barrierColor = barrierColor ?? new Color(0x80000000); |
|||
this.transitionDuration = transitionDuration ?? TimeSpan.FromMilliseconds(200); |
|||
this._transitionBuilder = transitionBuilder; |
|||
} |
|||
|
|||
readonly RoutePageBuilder _pageBuilder; |
|||
|
|||
public override bool barrierDismissible { get; } |
|||
|
|||
public override string barrierLabel { get; } |
|||
|
|||
public override Color barrierColor { get; } |
|||
|
|||
public override TimeSpan transitionDuration { get; } |
|||
|
|||
readonly RouteTransitionsBuilder _transitionBuilder; |
|||
|
|||
public override Widget buildPage(BuildContext context, Animation<double> animation, |
|||
Animation<double> secondaryAnimation) { |
|||
return this._pageBuilder(context, animation, secondaryAnimation); |
|||
} |
|||
} |
|||
|
|||
|
|||
public delegate Widget RoutePageBuilder(BuildContext context, Animation<double> animation, |
|||
Animation<double> secondaryAnimation); |
|||
|
|||
public delegate Widget RouteTransitionsBuilder(BuildContext context, Animation<double> animation, |
|||
Animation<double> secondaryAnimation, Widget child); |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3b5bef8a47dcb49babf3a770d5a3420d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace Unity.UIWidgets.widgets { |
|||
public abstract class AnimatedWidget : StatefulWidget { |
|||
public readonly Listenable listenable; |
|||
|
|||
protected AnimatedWidget(Key key = null, Listenable listenable = null) : base(key) { |
|||
D.assert(listenable != null); |
|||
this.listenable = listenable; |
|||
} |
|||
|
|||
protected internal abstract Widget build(BuildContext context); |
|||
|
|||
public override State createState() { |
|||
return new _AnimatedState(); |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|||
base.debugFillProperties(properties); |
|||
properties.add(new DiagnosticsProperty<Listenable>("animation", this.listenable)); |
|||
} |
|||
} |
|||
|
|||
public class _AnimatedState : State<AnimatedWidget> { |
|||
public override void initState() { |
|||
base.initState(); |
|||
this.widget.listenable.addListener(this._handleChange); |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|||
base.didUpdateWidget(oldWidget); |
|||
if (this.widget.listenable != ((AnimatedWidget) oldWidget).listenable) { |
|||
((AnimatedWidget) oldWidget).listenable.removeListener(this._handleChange); |
|||
this.widget.listenable.addListener(this._handleChange); |
|||
} |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this.widget.listenable.removeListener(this._handleChange); |
|||
base.dispose(); |
|||
} |
|||
|
|||
void _handleChange() { |
|||
this.setState(() => { |
|||
// The listenable's state is our build state, and it changed already.
|
|||
}); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return this.widget.build(context); |
|||
} |
|||
} |
|||
|
|||
public class SlideTransition : AnimatedWidget { |
|||
|
|||
public SlideTransition(Key key = null, |
|||
Animation<Offset> position = null, |
|||
bool transformHitTests = true, |
|||
TextDirection? textDirection = null, |
|||
Widget child = null): base(key: key, listenable: position) { |
|||
|
|||
D.assert(position != null); |
|||
this.transformHitTests = transformHitTests; |
|||
this.textDirection = textDirection; |
|||
this.child = child; |
|||
} |
|||
|
|||
public Animation<Offset> position => (Animation<Offset>)this.listenable; |
|||
|
|||
public readonly TextDirection? textDirection; |
|||
|
|||
public readonly bool transformHitTests; |
|||
|
|||
public readonly Widget child; |
|||
|
|||
protected internal override Widget build(BuildContext context) { |
|||
var offset = this.position.value; |
|||
if (this.textDirection == TextDirection.rtl) |
|||
offset = new Offset(-offset.dx, offset.dy); |
|||
return new FractionalTranslation( |
|||
translation: offset, |
|||
transformHitTests: this.transformHitTests, |
|||
child: this.child |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class FadeTransition : SingleChildRenderObjectWidget { |
|||
public FadeTransition(Key key = null, Animation<double> opacity = null, |
|||
Widget child = null): base(key: key, child: child) { |
|||
this.opacity = opacity; |
|||
} |
|||
|
|||
public readonly Animation<double> opacity; |
|||
|
|||
public override RenderObject createRenderObject(BuildContext context) { |
|||
return new RenderAnimatedOpacity( |
|||
opacity: this.opacity |
|||
); |
|||
} |
|||
|
|||
public override void updateRenderObject(BuildContext context, RenderObject renderObject) { |
|||
((RenderAnimatedOpacity) renderObject).opacity = this.opacity; |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|||
base.debugFillProperties(properties); |
|||
properties.add(new DiagnosticsProperty<Animation<double>>("opacity", this.opacity)); |
|||
} |
|||
} |
|||
|
|||
|
|||
public class AnimatedBuilder : AnimatedWidget { |
|||
public readonly TransitionBuilder builder; |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public AnimatedBuilder(Key key = null, Listenable animation = null, TransitionBuilder builder = null, |
|||
Widget child = null) : |
|||
base(key, animation) { |
|||
D.assert(builder != null); |
|||
this.builder = builder; |
|||
this.child = child; |
|||
} |
|||
|
|||
protected internal override Widget build(BuildContext context) { |
|||
return this.builder(context, this.child); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3df6a337dc40c448881ec2d0454362f5 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!29 &1 |
|||
OcclusionCullingSettings: |
|||
m_ObjectHideFlags: 0 |
|||
serializedVersion: 2 |
|||
m_OcclusionBakeSettings: |
|||
smallestOccluder: 5 |
|||
smallestHole: 0.25 |
|||
backfaceThreshold: 100 |
|||
m_SceneGUID: 00000000000000000000000000000000 |
|||
m_OcclusionCullingData: {fileID: 0} |
|||
--- !u!104 &2 |
|||
RenderSettings: |
|||
m_ObjectHideFlags: 0 |
|||
serializedVersion: 9 |
|||
m_Fog: 0 |
|||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} |
|||
m_FogMode: 3 |
|||
m_FogDensity: 0.01 |
|||
m_LinearFogStart: 0 |
|||
m_LinearFogEnd: 300 |
|||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} |
|||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} |
|||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} |
|||
m_AmbientIntensity: 1 |
|||
m_AmbientMode: 0 |
|||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} |
|||
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} |
|||
m_HaloStrength: 0.5 |
|||
m_FlareStrength: 1 |
|||
m_FlareFadeSpeed: 3 |
|||
m_HaloTexture: {fileID: 0} |
|||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} |
|||
m_DefaultReflectionMode: 0 |
|||
m_DefaultReflectionResolution: 128 |
|||
m_ReflectionBounces: 1 |
|||
m_ReflectionIntensity: 1 |
|||
m_CustomReflection: {fileID: 0} |
|||
m_Sun: {fileID: 0} |
|||
m_IndirectSpecularColor: {r: 0.44657892, g: 0.4964127, b: 0.5748172, a: 1} |
|||
m_UseRadianceAmbientProbe: 0 |
|||
--- !u!157 &3 |
|||
LightmapSettings: |
|||
m_ObjectHideFlags: 0 |
|||
serializedVersion: 11 |
|||
m_GIWorkflowMode: 0 |
|||
m_GISettings: |
|||
serializedVersion: 2 |
|||
m_BounceScale: 1 |
|||
m_IndirectOutputScale: 1 |
|||
m_AlbedoBoost: 1 |
|||
m_EnvironmentLightingMode: 0 |
|||
m_EnableBakedLightmaps: 1 |
|||
m_EnableRealtimeLightmaps: 1 |
|||
m_LightmapEditorSettings: |
|||
serializedVersion: 10 |
|||
m_Resolution: 2 |
|||
m_BakeResolution: 40 |
|||
m_AtlasSize: 1024 |
|||
m_AO: 0 |
|||
m_AOMaxDistance: 1 |
|||
m_CompAOExponent: 1 |
|||
m_CompAOExponentDirect: 0 |
|||
m_Padding: 2 |
|||
m_LightmapParameters: {fileID: 0} |
|||
m_LightmapsBakeMode: 1 |
|||
m_TextureCompression: 1 |
|||
m_FinalGather: 0 |
|||
m_FinalGatherFiltering: 1 |
|||
m_FinalGatherRayCount: 256 |
|||
m_ReflectionCompression: 2 |
|||
m_MixedBakeMode: 2 |
|||
m_BakeBackend: 1 |
|||
m_PVRSampling: 1 |
|||
m_PVRDirectSampleCount: 32 |
|||
m_PVRSampleCount: 500 |
|||
m_PVRBounces: 2 |
|||
m_PVRFilterTypeDirect: 0 |
|||
m_PVRFilterTypeIndirect: 0 |
|||
m_PVRFilterTypeAO: 0 |
|||
m_PVRFilteringMode: 1 |
|||
m_PVRCulling: 1 |
|||
m_PVRFilteringGaussRadiusDirect: 1 |
|||
m_PVRFilteringGaussRadiusIndirect: 5 |
|||
m_PVRFilteringGaussRadiusAO: 2 |
|||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5 |
|||
m_PVRFilteringAtrousPositionSigmaIndirect: 2 |
|||
m_PVRFilteringAtrousPositionSigmaAO: 1 |
|||
m_ShowResolutionOverlay: 1 |
|||
m_LightingDataAsset: {fileID: 0} |
|||
m_UseShadowmask: 1 |
|||
--- !u!196 &4 |
|||
NavMeshSettings: |
|||
serializedVersion: 2 |
|||
m_ObjectHideFlags: 0 |
|||
m_BuildSettings: |
|||
serializedVersion: 2 |
|||
agentTypeID: 0 |
|||
agentRadius: 0.5 |
|||
agentHeight: 2 |
|||
agentSlope: 45 |
|||
agentClimb: 0.4 |
|||
ledgeDropHeight: 0 |
|||
maxJumpAcrossDistance: 0 |
|||
minRegionArea: 2 |
|||
manualCellSize: 0 |
|||
cellSize: 0.16666667 |
|||
manualTileSize: 0 |
|||
tileSize: 256 |
|||
accuratePlacement: 0 |
|||
debug: |
|||
m_Flags: 0 |
|||
m_NavMeshData: {fileID: 0} |
|||
--- !u!1 &4286172 |
|||
GameObject: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
serializedVersion: 6 |
|||
m_Component: |
|||
- component: {fileID: 4286176} |
|||
- component: {fileID: 4286175} |
|||
- component: {fileID: 4286174} |
|||
- component: {fileID: 4286173} |
|||
m_Layer: 5 |
|||
m_Name: Canvas |
|||
m_TagString: Untagged |
|||
m_Icon: {fileID: 0} |
|||
m_NavMeshLayer: 0 |
|||
m_StaticEditorFlags: 0 |
|||
m_IsActive: 1 |
|||
--- !u!114 &4286173 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 4286172} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} |
|||
m_Name: |
|||
m_EditorClassIdentifier: |
|||
m_IgnoreReversedGraphics: 1 |
|||
m_BlockingObjects: 0 |
|||
m_BlockingMask: |
|||
serializedVersion: 2 |
|||
m_Bits: 4294967295 |
|||
--- !u!114 &4286174 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 4286172} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} |
|||
m_Name: |
|||
m_EditorClassIdentifier: |
|||
m_UiScaleMode: 0 |
|||
m_ReferencePixelsPerUnit: 100 |
|||
m_ScaleFactor: 1 |
|||
m_ReferenceResolution: {x: 800, y: 600} |
|||
m_ScreenMatchMode: 0 |
|||
m_MatchWidthOrHeight: 0 |
|||
m_PhysicalUnit: 3 |
|||
m_FallbackScreenDPI: 96 |
|||
m_DefaultSpriteDPI: 96 |
|||
m_DynamicPixelsPerUnit: 1 |
|||
--- !u!223 &4286175 |
|||
Canvas: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 4286172} |
|||
m_Enabled: 1 |
|||
serializedVersion: 3 |
|||
m_RenderMode: 0 |
|||
m_Camera: {fileID: 0} |
|||
m_PlaneDistance: 100 |
|||
m_PixelPerfect: 0 |
|||
m_ReceivesEvents: 1 |
|||
m_OverrideSorting: 0 |
|||
m_OverridePixelPerfect: 0 |
|||
m_SortingBucketNormalizedSize: 0 |
|||
m_AdditionalShaderChannelsFlag: 0 |
|||
m_SortingLayerID: 0 |
|||
m_SortingOrder: 0 |
|||
m_TargetDisplay: 0 |
|||
--- !u!224 &4286176 |
|||
RectTransform: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 4286172} |
|||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} |
|||
m_LocalPosition: {x: 0, y: 0, z: 0} |
|||
m_LocalScale: {x: 0, y: 0, z: 0} |
|||
m_Children: |
|||
- {fileID: 927824195} |
|||
m_Father: {fileID: 0} |
|||
m_RootOrder: 2 |
|||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
|||
m_AnchorMin: {x: 0, y: 0} |
|||
m_AnchorMax: {x: 0, y: 0} |
|||
m_AnchoredPosition: {x: 0, y: 0} |
|||
m_SizeDelta: {x: 0, y: 0} |
|||
m_Pivot: {x: 0, y: 0} |
|||
--- !u!1 &26611619 |
|||
GameObject: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
serializedVersion: 6 |
|||
m_Component: |
|||
- component: {fileID: 26611622} |
|||
- component: {fileID: 26611621} |
|||
- component: {fileID: 26611620} |
|||
m_Layer: 0 |
|||
m_Name: Main Camera |
|||
m_TagString: MainCamera |
|||
m_Icon: {fileID: 0} |
|||
m_NavMeshLayer: 0 |
|||
m_StaticEditorFlags: 0 |
|||
m_IsActive: 1 |
|||
--- !u!81 &26611620 |
|||
AudioListener: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 26611619} |
|||
m_Enabled: 1 |
|||
--- !u!20 &26611621 |
|||
Camera: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 26611619} |
|||
m_Enabled: 1 |
|||
serializedVersion: 2 |
|||
m_ClearFlags: 1 |
|||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} |
|||
m_projectionMatrixMode: 1 |
|||
m_SensorSize: {x: 36, y: 24} |
|||
m_LensShift: {x: 0, y: 0} |
|||
m_GateFitMode: 2 |
|||
m_FocalLength: 50 |
|||
m_NormalizedViewPortRect: |
|||
serializedVersion: 2 |
|||
x: 0 |
|||
y: 0 |
|||
width: 1 |
|||
height: 1 |
|||
near clip plane: 0.3 |
|||
far clip plane: 1000 |
|||
field of view: 60 |
|||
orthographic: 0 |
|||
orthographic size: 5 |
|||
m_Depth: -1 |
|||
m_CullingMask: |
|||
serializedVersion: 2 |
|||
m_Bits: 4294967295 |
|||
m_RenderingPath: -1 |
|||
m_TargetTexture: {fileID: 0} |
|||
m_TargetDisplay: 0 |
|||
m_TargetEye: 3 |
|||
m_HDR: 1 |
|||
m_AllowMSAA: 1 |
|||
m_AllowDynamicResolution: 0 |
|||
m_ForceIntoRT: 0 |
|||
m_OcclusionCulling: 1 |
|||
m_StereoConvergence: 10 |
|||
m_StereoSeparation: 0.022 |
|||
--- !u!4 &26611622 |
|||
Transform: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 26611619} |
|||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} |
|||
m_LocalPosition: {x: 0, y: 1, z: -10} |
|||
m_LocalScale: {x: 1, y: 1, z: 1} |
|||
m_Children: [] |
|||
m_Father: {fileID: 0} |
|||
m_RootOrder: 0 |
|||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
|||
--- !u!1 &897547349 |
|||
GameObject: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
serializedVersion: 6 |
|||
m_Component: |
|||
- component: {fileID: 897547351} |
|||
- component: {fileID: 897547350} |
|||
m_Layer: 0 |
|||
m_Name: Directional Light |
|||
m_TagString: Untagged |
|||
m_Icon: {fileID: 0} |
|||
m_NavMeshLayer: 0 |
|||
m_StaticEditorFlags: 0 |
|||
m_IsActive: 1 |
|||
--- !u!108 &897547350 |
|||
Light: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 897547349} |
|||
m_Enabled: 1 |
|||
serializedVersion: 8 |
|||
m_Type: 1 |
|||
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} |
|||
m_Intensity: 1 |
|||
m_Range: 10 |
|||
m_SpotAngle: 30 |
|||
m_CookieSize: 10 |
|||
m_Shadows: |
|||
m_Type: 2 |
|||
m_Resolution: -1 |
|||
m_CustomResolution: -1 |
|||
m_Strength: 1 |
|||
m_Bias: 0.05 |
|||
m_NormalBias: 0.4 |
|||
m_NearPlane: 0.2 |
|||
m_Cookie: {fileID: 0} |
|||
m_DrawHalo: 0 |
|||
m_Flare: {fileID: 0} |
|||
m_RenderMode: 0 |
|||
m_CullingMask: |
|||
serializedVersion: 2 |
|||
m_Bits: 4294967295 |
|||
m_Lightmapping: 4 |
|||
m_LightShadowCasterMode: 0 |
|||
m_AreaSize: {x: 1, y: 1} |
|||
m_BounceIntensity: 1 |
|||
m_ColorTemperature: 6570 |
|||
m_UseColorTemperature: 0 |
|||
m_ShadowRadius: 0 |
|||
m_ShadowAngle: 0 |
|||
--- !u!4 &897547351 |
|||
Transform: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 897547349} |
|||
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} |
|||
m_LocalPosition: {x: 0, y: 3, z: 0} |
|||
m_LocalScale: {x: 1, y: 1, z: 1} |
|||
m_Children: [] |
|||
m_Father: {fileID: 0} |
|||
m_RootOrder: 1 |
|||
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} |
|||
--- !u!1 &927824194 |
|||
GameObject: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
serializedVersion: 6 |
|||
m_Component: |
|||
- component: {fileID: 927824195} |
|||
- component: {fileID: 927824197} |
|||
- component: {fileID: 927824196} |
|||
m_Layer: 5 |
|||
m_Name: Navigation |
|||
m_TagString: Untagged |
|||
m_Icon: {fileID: 0} |
|||
m_NavMeshLayer: 0 |
|||
m_StaticEditorFlags: 0 |
|||
m_IsActive: 1 |
|||
--- !u!224 &927824195 |
|||
RectTransform: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 927824194} |
|||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} |
|||
m_LocalPosition: {x: 0, y: 0, z: 0} |
|||
m_LocalScale: {x: 1, y: 1, z: 1} |
|||
m_Children: [] |
|||
m_Father: {fileID: 4286176} |
|||
m_RootOrder: 0 |
|||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
|||
m_AnchorMin: {x: 0, y: 0} |
|||
m_AnchorMax: {x: 1, y: 1} |
|||
m_AnchoredPosition: {x: 0, y: 0} |
|||
m_SizeDelta: {x: 0, y: 0} |
|||
m_Pivot: {x: 0.5, y: 0.5} |
|||
--- !u!114 &927824196 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 927824194} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 11500000, guid: 020016dfbbaef41b496f4e5be17d098c, type: 3} |
|||
m_Name: |
|||
m_EditorClassIdentifier: |
|||
m_Material: {fileID: 0} |
|||
m_Color: {r: 1, g: 1, b: 1, a: 1} |
|||
m_RaycastTarget: 1 |
|||
m_OnCullStateChanged: |
|||
m_PersistentCalls: |
|||
m_Calls: [] |
|||
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, |
|||
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null |
|||
m_Texture: {fileID: 0} |
|||
m_UVRect: |
|||
serializedVersion: 2 |
|||
x: 0 |
|||
y: 0 |
|||
width: 1 |
|||
height: 1 |
|||
--- !u!222 &927824197 |
|||
CanvasRenderer: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 927824194} |
|||
m_CullTransparentMesh: 0 |
|||
--- !u!1 &1838283857 |
|||
GameObject: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
serializedVersion: 6 |
|||
m_Component: |
|||
- component: {fileID: 1838283860} |
|||
- component: {fileID: 1838283859} |
|||
- component: {fileID: 1838283858} |
|||
m_Layer: 0 |
|||
m_Name: EventSystem |
|||
m_TagString: Untagged |
|||
m_Icon: {fileID: 0} |
|||
m_NavMeshLayer: 0 |
|||
m_StaticEditorFlags: 0 |
|||
m_IsActive: 1 |
|||
--- !u!114 &1838283858 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 1838283857} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} |
|||
m_Name: |
|||
m_EditorClassIdentifier: |
|||
m_HorizontalAxis: Horizontal |
|||
m_VerticalAxis: Vertical |
|||
m_SubmitButton: Submit |
|||
m_CancelButton: Cancel |
|||
m_InputActionsPerSecond: 10 |
|||
m_RepeatDelay: 0.5 |
|||
m_ForceModuleActive: 0 |
|||
--- !u!114 &1838283859 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 1838283857} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} |
|||
m_Name: |
|||
m_EditorClassIdentifier: |
|||
m_FirstSelected: {fileID: 0} |
|||
m_sendNavigationEvents: 1 |
|||
m_DragThreshold: 10 |
|||
--- !u!4 &1838283860 |
|||
Transform: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 1838283857} |
|||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} |
|||
m_LocalPosition: {x: 0, y: 0, z: 0} |
|||
m_LocalScale: {x: 1, y: 1, z: 1} |
|||
m_Children: [] |
|||
m_Father: {fileID: 0} |
|||
m_RootOrder: 3 |
|||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
|
|||
fileFormatVersion: 2 |
|||
guid: 48300882e985d484880e16569661a93c |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.engine; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using Color = Unity.UIWidgets.ui.Color; |
|||
|
|||
namespace UIWidgetsSample { |
|||
|
|||
public class NavigationCanvas : WidgetCanvas { |
|||
|
|||
protected override string initialRoute => "/"; |
|||
|
|||
protected override Dictionary<string, WidgetBuilder> routes => new Dictionary<string, WidgetBuilder> { |
|||
{"/", (context) => new HomeScreen()}, |
|||
{"/detail", (context) => new DetailScreen()} |
|||
}; |
|||
|
|||
protected override Widget getWidget() { |
|||
return null; |
|||
} |
|||
|
|||
protected override PageRouteFactory pageRouteBuilder => (RouteSettings settings, WidgetBuilder builder) => |
|||
new PageRouteBuilder( |
|||
settings: settings, |
|||
pageBuilder: (BuildContext context, Unity.UIWidgets.animation.Animation<double> animation, |
|||
Unity.UIWidgets.animation.Animation<double> secondaryAnimation) => builder(context), |
|||
transitionsBuilder: (BuildContext context, Animation<double> |
|||
animation, Animation<double> secondaryAnimation, Widget child) => new _FadeUpwardsPageTransition( |
|||
routeAnimation: animation, |
|||
child: child |
|||
) |
|||
); |
|||
} |
|||
|
|||
class HomeScreen : StatelessWidget { |
|||
public override Widget build(BuildContext context) { |
|||
return new Container( |
|||
color: new Color(0xFF888888), |
|||
child: new Center(child: new CustomButton(onPressed: () => { |
|||
Navigator.pushName(context, "/detail"); |
|||
}, child: new Text("Go to Detail")) |
|||
)); |
|||
|
|||
} |
|||
} |
|||
|
|||
class DetailScreen : StatelessWidget { |
|||
public override Widget build(BuildContext context) { |
|||
return new Container( |
|||
color: new Color(0xFF1389FD), |
|||
child: new Center(child: new CustomButton(onPressed: () => { |
|||
Navigator.pop(context); |
|||
}, child: new Text("Back")) |
|||
)); |
|||
} |
|||
} |
|||
|
|||
class _FadeUpwardsPageTransition : StatelessWidget { |
|||
|
|||
internal _FadeUpwardsPageTransition( |
|||
Key key = null, |
|||
Animation<double> routeAnimation = null, // The route's linear 0.0 - 1.0 animation.
|
|||
Widget child = null |
|||
) :base(key: key) { |
|||
this._positionAnimation = _bottomUpTween.chain(_fastOutSlowInTween).animate(routeAnimation); |
|||
this._opacityAnimation = _easeInTween.animate(routeAnimation); |
|||
this.child = child; |
|||
} |
|||
|
|||
static Tween<Offset> _bottomUpTween = new OffsetTween( |
|||
begin: new Offset(0.0, 0.25), |
|||
end: Offset.zero |
|||
); |
|||
|
|||
static Animatable<double> _fastOutSlowInTween = new CurveTween(curve: Curves.fastOutSlowIn); |
|||
static Animatable<double> _easeInTween = new CurveTween(curve: Curves.easeIn); |
|||
|
|||
readonly Animation<Offset> _positionAnimation; |
|||
readonly Animation<double> _opacityAnimation; |
|||
public readonly Widget child; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new SlideTransition( |
|||
position: this._positionAnimation, |
|||
child: new FadeTransition( |
|||
opacity: this._opacityAnimation, |
|||
child: this.child |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 020016dfbbaef41b496f4e5be17d098c |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue