浏览代码

Merge remote-tracking branch 'upstream/master'

/main
fzhangtj 6 年前
当前提交
1a40fc57
共有 100 个文件被更改,包括 2882 次插入782 次删除
  1. 16
      README.md
  2. 5
      Runtime/debugger/inspector_service.cs
  3. 17
      Runtime/debugger/inspector_window.cs
  4. 35
      Runtime/editor/editor_window.cs
  5. 2
      Runtime/editor/rasterizer.cs
  6. 2
      Runtime/engine/UIWidgetsPanel.cs
  7. 29
      Runtime/flow/compositor_context.cs
  8. 2
      Runtime/flow/layer.cs
  9. 4
      Runtime/flow/layer_tree.cs
  10. 55
      Runtime/flow/performance_overlay_layer.cs
  11. 4
      Runtime/foundation/basic_types.cs
  12. 11
      Runtime/foundation/debug.cs
  13. 2
      Runtime/foundation/node.cs
  14. 4
      Runtime/foundation/node.mixin.gen.cs
  15. 2
      Runtime/foundation/node.mixin.njk
  16. 129
      Runtime/material/input_decorator.cs
  17. 108
      Runtime/material/text_selection.cs
  18. 2
      Runtime/material/toggleable.cs
  19. 37
      Runtime/painting/text_style.cs
  20. 3
      Runtime/rendering/binding.cs
  21. 61
      Runtime/rendering/editable.cs
  22. 35
      Runtime/rendering/flex.cs
  23. 7
      Runtime/rendering/shifted_box.cs
  24. 47
      Runtime/service/keyboard.cs
  25. 50
      Runtime/service/raw_keyboard.cs
  26. 27
      Runtime/service/text_formatter.cs
  27. 9
      Runtime/service/text_input.cs
  28. 2
      Runtime/ui/painting/canvas_impl.cs
  29. 7
      Runtime/ui/painting/path.cs
  30. 63
      Runtime/ui/painting/txt/font_manager.cs
  31. 29
      Runtime/ui/painting/txt/mesh_generator.cs
  32. 23
      Runtime/ui/painting/txt/text_blob.cs
  33. 39
      Runtime/ui/text.cs
  34. 12
      Runtime/ui/txt/layout.cs
  35. 17
      Runtime/ui/txt/linebreaker.cs
  36. 2
      Runtime/ui/txt/paint_record.cs
  37. 87
      Runtime/ui/txt/paragraph.cs
  38. 12
      Runtime/ui/txt/paragraph_builder.cs
  39. 6
      Runtime/ui/txt/styled_runs.cs
  40. 2
      Runtime/ui/txt/word_separate.cs
  41. 2
      Runtime/ui/txt/wordbreaker.cs
  42. 17
      Runtime/ui/window.cs
  43. 2
      Runtime/widgets/automatic_keep_alive.cs
  44. 43
      Runtime/widgets/basic.cs
  45. 38
      Runtime/widgets/editable_text.cs
  46. 2
      Runtime/widgets/framework.cs
  47. 4
      Runtime/widgets/navigator.cs
  48. 2
      Runtime/widgets/text.cs
  49. 4
      Runtime/widgets/ticker_provider.cs
  50. 20
      Samples/ReduxSample/CounterApp/CounterAppSample.cs
  51. 4
      Samples/ReduxSample/ObjectFinder/FinderGameObject.cs
  52. 73
      Samples/ReduxSample/ObjectFinder/ObjectFinderApp.cs
  53. 95
      Samples/ReduxSample/ObjectFinder/Reducer.cs
  54. 6
      Samples/ReduxSample/ObjectFinder/StoreProvider.cs
  55. 24
      Samples/UIWidgetSample/MaterialSample.cs
  56. 150
      Samples/UIWidgetSample/UIWidgetSample.unity
  57. 5
      Samples/UIWidgetSample/txt/FontWeightStyle.cs
  58. 4
      Samples/UIWidgetsGallery/Editor/GalleryMainEditor.cs
  59. 5
      Samples/UIWidgetsGallery/GalleryMain.cs
  60. 3
      Samples/UIWidgetsGallery/gallery/app.cs
  61. 14
      Samples/UIWidgetsTheatre/UIWidgetsTheatre.cs
  62. 116
      Samples/UIWidgetsTheatre/UIWidgetsTheatre.unity
  63. 11
      Tests/Editor/CanvasAndLayers.cs
  64. 4
      Tests/Editor/Widgets.cs
  65. 2
      Runtime/flow/instrumentation.cs.meta
  66. 2
      Runtime/redux/redux_thunk.cs.meta
  67. 4
      .DS_Store
  68. 223
      README-ZH.md
  69. 7
      README-ZH.md.meta
  70. 113
      Runtime/flow/instrumentation.cs
  71. 311
      Runtime/material/checkbox.cs
  72. 3
      Runtime/material/checkbox.cs.meta
  73. 444
      Runtime/material/text_field.cs
  74. 11
      Runtime/material/text_field.cs.meta
  75. 8
      Runtime/redux.meta
  76. 275
      Runtime/rendering/debug_overflow_indicator.cs
  77. 11
      Runtime/rendering/debug_overflow_indicator.cs.meta
  78. 66
      Samples/UIWidgetSample/txt/TextFieldSample.cs
  79. 11
      Samples/UIWidgetSample/txt/TextFieldSample.cs.meta
  80. 43
      Samples/UIWidgetSample/txt/TextStyleSample.cs
  81. 11
      Samples/UIWidgetSample/txt/TextStyleSample.cs.meta
  82. 9
      Samples/UIWidgetsTheatre/UIWidgetsTheatre.asmdef
  83. 7
      Samples/UIWidgetsTheatre/UIWidgetsTheatre.asmdef.meta
  84. 8
      scripts/node_modules.meta
  85. 19
      Runtime/redux/redux_logging.cs
  86. 32
      Runtime/redux/redux_thunk.cs
  87. 81
      Runtime/redux/store.cs
  88. 171
      Runtime/redux/widget_redux.cs
  89. 98
      Runtime/service/performance_utils.cs
  90. 24
      Samples/ReduxSample/ObjectFinder/Middleware.cs
  91. 8
      Samples/ReduxSample/redux.meta
  92. 8
      Samples/ReduxSample/redux_logging.meta
  93. 0
      /Runtime/flow/instrumentation.cs.meta
  94. 0
      /Runtime/redux/redux_thunk.cs.meta
  95. 0
      /Runtime/redux/store.cs.meta
  96. 0
      /Runtime/redux/widget_redux.cs.meta
  97. 0
      /Runtime/redux/redux_logging.cs.meta

16
README.md


# UIWidgets
[中文](README-ZH.md)
## Introduction

UIWidgets is mainly derived from Flutter @https://github.com/flutter/flutter. However, taking advantage of
UIWidgets is mainly derived from [Flutter](https://github.com/flutter/flutter). However, taking advantage of
the powerful Unity Engine, it offers developers many new features to improve their Apps
as well as the develop workflow significantly.

First of all, please open or create a Unity Project and open it with Unity Editor.
And then open Project Settings, go to Player section and add "UIWidgets_DEBUG" to the Scripting Debug Symbols field.
And then open Project Settings, go to Player section and **add "UIWidgets_DEBUG" to the Scripting Define Symbols field.**
This enables the debug mode of UIWidgets for your development. Remove this for your release build afterwards.
#### ii. Scene Build

namespace UIWidgetsSample {
public class UIWidgetsExample : UIWidgetsPanel {
protected override void Awake() {
base.Awake();
protected override void OnEnable() {
// Application.targetFrameRate = 60; // or higher if you want a smoother scrolling experience.
// if you want to use your own font or font icons.

// add material icons, familyName must be "Material Icons"
// FontManager.instance.addFont(Resources.Load<Font>(path: "path to material icons"), "Material Icons");
base.OnEnable();
}
protected override Widget createWidget() {

## Learn
#### Samples
You can find many UIWidgets App samples in the UIWidgets package in the **Samples** folder.
You can find many UIWidgets App samples in the UIWidgets package in the **Samples** folder.
To get started, the UIWidgetsTheatre scene provides you
a list of carefully selected samples to start with.
You can also try UIWidgets-based Editor windows by clicking **UIWidgetsTest** on the main menu
and open one of the dropdown samples.

you can refer to Flutter Wiki to access detailed descriptions of UIWidgets APIs
from those of their Flutter counterparts.
Meanwhile, you can join the discussion channel at (https://connect.unity.com/g/uiwidgets)
#### FAQ

5
Runtime/debugger/inspector_service.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.editor;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.debugger {

public bool active {
get { return this.window.alive; }
}
public bool debugEnabled {
get { return D.debugEnabled; }
}
public void close() {

17
Runtime/debugger/inspector_window.cs


bool m_DebugPaintLayer;
bool m_ShowDebugPaintToggles;
GUIStyle m_MessageStyle;
readonly List<InspectorPanel> m_Panels = new List<InspectorPanel>();
Rect m_DebugPaintTogglesRect;

this.DoSelectDropDown();
bool needDebugPaintUpdate = false;
if (this.m_InspectorService != null) {
if (this.m_InspectorService != null && this.m_InspectorService.debugEnabled) {
if (GUILayout.Button("Refersh", EditorStyles.toolbarButton)) {
foreach (var panel in this.m_Panels) {
panel.MarkNeedReload();

EditorGUILayout.Space();
if (this.m_InspectorService != null) {
if (this.m_InspectorService != null && this.m_InspectorService .debugEnabled) {
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, GUILayout.ExpandWidth(false));
this.m_Panels.Each((pannel, index) => {
if (GUILayout.Toggle(this.m_PanelIndex == index, pannel.title, EditorStyles.toolbarButton,

if (shouldHandleGUI) {
this.m_Panels[this.m_PanelIndex].OnGUI();
}
} else if (this.m_InspectorService != null) { // debug not enabled
if (this.m_MessageStyle == null) {
this.m_MessageStyle = new GUIStyle(GUI.skin.label);
this.m_MessageStyle.fontSize = 16;
this.m_MessageStyle.alignment = TextAnchor.MiddleCenter;
this.m_MessageStyle.padding = new RectOffset(20, 20, 40, 0);
}
GUILayout.Label("You're not in UIWidgets Debug Mode.\nPlease define UIWidgets_DEBUG " +
"symbols at \"Player Settings => Scripting Define Symbols\".",
this.m_MessageStyle, GUILayout.ExpandWidth(true));
}
if (this.m_ShowDebugPaintToggles) {

35
Runtime/editor/editor_window.cs


using System;
using System.Collections.Generic;
using System.Diagnostics;
using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.rendering;

public UIWidgetsEditorWindow() {
this.wantsMouseMove = true;
this.wantsMouseEnterLeaveWindow = true;
}
protected virtual void Awake() {
}
protected virtual void OnEnable() {

protected override Vector2 queryWindowSize() {
return this.editorWindow.position.size;
}
protected override TimeSpan getTime() {
return TimeSpan.FromSeconds(EditorApplication.timeSinceStartup);
}
float? _lastUpdateTime;
protected override float getUnscaledDeltaTime() {
if (this._lastUpdateTime == null) {
this._lastUpdateTime = (float) EditorApplication.timeSinceStartup;
}
float deltaTime = (float) EditorApplication.timeSinceStartup - this._lastUpdateTime.Value;
this._lastUpdateTime = (float) EditorApplication.timeSinceStartup;
return deltaTime;
}
}
#endif

float _lastWindowWidth;
float _lastWindowHeight;
readonly TimeSpan _epoch = new TimeSpan(Stopwatch.GetTimestamp());
bool _regenerateLayerTree;
Surface _surface;

get { return this._alive; }
}
protected virtual TimeSpan getTime() {
return TimeSpan.FromSeconds(Time.time);
}
protected virtual float getUnscaledDeltaTime() {
return Time.unscaledDeltaTime;
}
protected virtual void updateSafeArea() {
}

return new EditorWindowSurface();
}
this.onBeginFrame(new TimeSpan(Stopwatch.GetTimestamp()) - this._epoch);
this.onBeginFrame(this.getTime());
}
this.flushMicrotasks();

}
public void Update() {
this.updateDeltaTime(this.getUnscaledDeltaTime());
Timer.update();
bool hasFocus = this.hasFocus();

2
Runtime/editor/rasterizer.cs


var canvas = frame.getCanvas();
using (var compositorFrame = this._compositorContext.acquireFrame(canvas)) {
using (var compositorFrame = this._compositorContext.acquireFrame(canvas, true)) {
if (compositorFrame != null && compositorFrame.raster(layerTree, false)) {
frame.submit();
this._fireNextFrameCallbackIfPresent();

2
Runtime/engine/UIWidgetsPanel.cs


using Unity.UIWidgets.async;
using Unity.UIWidgets.editor;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;

}
protected virtual void Update() {
PerformanceUtils.instance.updateDeltaTime(Time.unscaledDeltaTime);
this._displayMetrics.Update();
UIWidgetsMessageManager.ensureUIWidgetsMessageManagerIfNeeded();

29
Runtime/flow/compositor_context.cs


public class ScopedFrame : IDisposable {
readonly CompositorContext _context;
readonly Canvas _canvas;
readonly bool _instrumentation_enabled;
public ScopedFrame(CompositorContext context, Canvas canvas) {
public ScopedFrame(CompositorContext context, Canvas canvas, bool instrumentation_enabled) {
this._context._beginFrame(this);
this._instrumentation_enabled = instrumentation_enabled;
this._context._beginFrame(this, this._instrumentation_enabled);
}
public CompositorContext context() {

}
public void Dispose() {
this._context._endFrame(this);
this._context._endFrame(this, this._instrumentation_enabled);
readonly Stopwatch _frameTime;
this._frameTime = new Stopwatch();
public ScopedFrame acquireFrame(Canvas canvas) {
return new ScopedFrame(this, canvas);
public ScopedFrame acquireFrame(Canvas canvas, bool instrumentation_enabled) {
return new ScopedFrame(this, canvas, instrumentation_enabled);
}
public void onGrContextCreated(Surface surface) {

return this._rasterCache;
}
void _beginFrame(ScopedFrame frame) {
public Stopwatch frameTime() {
return this._frameTime;
void _endFrame(ScopedFrame frame) {
void _beginFrame(ScopedFrame frame, bool enable_instrumentation) {
if (enable_instrumentation) {
this._frameTime.start();
}
}
void _endFrame(ScopedFrame frame, bool enable_instrumentation) {
if (enable_instrumentation) {
this._frameTime.stop();
}
}
}
}

2
Runtime/flow/layer.cs


public RasterCache rasterCache;
public float devicePixelRatio;
public Rect cullRect;
public Stopwatch frameTime;
public Stopwatch frameTime;
}
public abstract class Layer {

4
Runtime/flow/layer_tree.cs


}
static readonly Matrix3 _identityMatrix = Matrix3.I();
frameTime = frame.context().frameTime()
};
this._rootLayer.preroll(prerollContext, _identityMatrix);

var paintContext = new PaintContext {
canvas = frame.canvas(),
rasterCache = ignoreRasterCache ? null : frame.context().rasterCache(),
frameTime = frame.context().frameTime()
};
if (this._rootLayer.needsPainting) {

55
Runtime/flow/performance_overlay_layer.cs


using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.service;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Rect = Unity.UIWidgets.ui.Rect;
namespace Unity.UIWidgets.flow {
public class PerformanceOverlayLayer : Layer {

this._drawFPS(canvas, x, y);
if ((this._options & (int) PerformanceOverlayOption.drawFrameCost) == 1) {
this._drawFrameCost(canvas, x, y + fpsHeight, width, height - padding - fpsHeight);
context.frameTime.visualize(canvas,
Rect.fromLTWH(x, y + fpsHeight, width, height - padding - fpsHeight));
}
canvas.restore();

void _drawFPS(Canvas canvas, float x, float y) {
var pb = new ParagraphBuilder(new ParagraphStyle { });
pb.addText("FPS = " + PerformanceUtils.instance.getFPS());
pb.addText("FPS = " + Window.instance.getFPS());
}
void _drawFrameCost(Canvas canvas, float x, float y, float width, float height) {
Rect visualizationRect = Rect.fromLTWH(x, y, width, height);
Paint paint = new Paint {color = Colors.blue};
Paint paint2 = new Paint {color = Colors.red};
Paint paint3 = new Paint {color = Colors.green};
Paint paint4 = new Paint {color = Colors.white70};
float[] costFrames = PerformanceUtils.instance.getFrames();
int curFrame = PerformanceUtils.instance.getCurFrame();
float barWidth = Mathf.Max(1, width / costFrames.Length);
float perHeight = height / 32.0f;
canvas.drawRect(visualizationRect, paint4);
canvas.drawRect(Rect.fromLTWH(x, y + perHeight * 16.0f, width, 1), paint3);
float cur_x = x;
Path barPath = new Path();
for (var i = 0; i < costFrames.Length; i++) {
if (costFrames[i] != 0) {
float curHeight = Mathf.Min(perHeight * costFrames[i], height);
Rect barRect = Rect.fromLTWH(cur_x, y + height - curHeight, barWidth, curHeight);
barPath.addRect(barRect);
}
cur_x += barWidth;
}
canvas.drawPath(barPath, paint);
if (curFrame >= 0 && curFrame < costFrames.Length && costFrames[curFrame] != 0) {
float curHeight = Mathf.Min(perHeight * costFrames[curFrame], height);
Rect barRect = Rect.fromLTWH(x + barWidth * curFrame, y + height - curHeight, barWidth, curHeight);
canvas.drawRect(barRect, paint2);
var pb = new ParagraphBuilder(new ParagraphStyle { });
pb.addText("Frame Cost: " + costFrames[curFrame] + "ms");
var paragraph = pb.build();
paragraph.layout(new ParagraphConstraints(width: 300));
canvas.drawParagraph(paragraph, new Offset(x, y + height - 12));
}
}
}
}

4
Runtime/foundation/basic_types.cs


return true;
}
if (ReferenceEquals(it, list)) {
return true;
}
if (it == null || list == null) {
return false;
}

11
Runtime/foundation/debug.cs


public static void logError(string message, Exception ex = null) {
Debug.LogException(new AssertionError(message, ex));
}
public static bool debugEnabled {
get {
#if UIWidgets_DEBUG
return true;
#else
return false;
#endif
}
}
[Conditional("UIWidgets_DEBUG")]
public static void assert(Func<bool> result, string message = null) {
if (!result()) {

2
Runtime/foundation/node.cs


foreach (var field in fields) {
if (!field.IsInitOnly) {
throw new UIWidgetsError(
type + " should be immutable. All public fields need to be readonly. " +
type + " is pure and should be immutable. All public fields need to be readonly. " +
field + " is not readonly.");
}
}

4
Runtime/foundation/node.mixin.gen.cs


static readonly Dictionary<_DependencyList, WeakReference> _canonicalObjects =
new Dictionary<_DependencyList, WeakReference>();
public bool alwaysUpdate { get; set; } = true; // if canonicalEquals should not be used.
public bool pure { get; set; } // pure = false, if canonicalEquals should not be used.
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {

return false;
}
if (this.alwaysUpdate) {
if (!this.pure) {
return ReferenceEquals(this, obj);
} else {
return ReferenceEquals(this._getCanonical(), ((CanonicalMixinDiagnosticableTree) obj)._getCanonical());

2
Runtime/foundation/node.mixin.njk


return false;
}
if (this.alwaysUpdate) {
if (!this.pure) {
return ReferenceEquals(this, obj);
} else {
return ReferenceEquals(this._getCanonical(), ((CanonicalMixin{{with}}) obj)._getCanonical());

129
Runtime/material/input_decorator.cs


}
class _InputBorderGap : ChangeNotifier {
class _InputBorderGap : ChangeNotifier, IEquatable<_InputBorderGap> {
float _start;
public float start {

}
}
public static bool operator ==(_InputBorderGap left, _InputBorderGap right) {
return left.Equals(right);
}
public bool Equals(_InputBorderGap other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
public static bool operator !=(_InputBorderGap left, _InputBorderGap other) {
return left.start != other.start || left.extent != other.extent;
return this.start == other.start && this.extent == other._extent;
public bool Equals(_InputBorderGap other) {
return this.start == other.start && this.extent == other.extent;
}
return (this.start.GetHashCode() * 397) ^ this.extent.GetHashCode();
return (this._start.GetHashCode() * 397) ^ this._extent.GetHashCode();
}
public static bool operator ==(_InputBorderGap left, _InputBorderGap right) {
return Equals(left, right);
}
public static bool operator !=(_InputBorderGap left, _InputBorderGap right) {
return !Equals(left, right);
}
}

container
}
class _Decoration {
class _Decoration : IEquatable<_Decoration> {
public _Decoration(
EdgeInsets contentPadding,
bool isCollapsed,

public readonly Widget counter;
public readonly Widget container;
public static bool operator ==(_Decoration left, _Decoration right) {
return left.Equals(right);
}
public bool Equals(_Decoration other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
public static bool operator !=(_Decoration left, _Decoration right) {
return !left.Equals(right);
return Equals(this.contentPadding, other.contentPadding) && this.isCollapsed == other.isCollapsed &&
this.floatingLabelHeight.Equals(other.floatingLabelHeight) &&
this.floatingLabelProgress.Equals(other.floatingLabelProgress) &&
Equals(this.border, other.border) && Equals(this.borderGap, other.borderGap) &&
Equals(this.icon, other.icon) && Equals(this.input, other.input) &&
Equals(this.label, other.label) && Equals(this.hint, other.hint) &&
Equals(this.prefix, other.prefix) && Equals(this.suffix, other.suffix) &&
Equals(this.prefixIcon, other.prefixIcon) && Equals(this.suffixIcon, other.suffixIcon) &&
Equals(this.helperError, other.helperError) && Equals(this.counter, other.counter) &&
Equals(this.container, other.container);
public bool Equals(_Decoration other) {
return this.contentPadding == other.contentPadding
&& this.floatingLabelHeight == other.floatingLabelHeight
&& this.floatingLabelProgress == other.floatingLabelProgress
&& this.border == other.border
&& this.borderGap == other.borderGap
&& this.icon == other.icon
&& this.input == other.input
&& this.label == other.label
&& this.hint == other.hint
&& this.prefix == other.prefix
&& this.suffix == other.suffix
&& this.prefixIcon == other.prefixIcon
&& this.suffixIcon == other.suffixIcon
&& this.helperError == other.helperError
&& this.counter == other.counter
&& this.container == other.container;
}
var hashCode = this.contentPadding.GetHashCode();
var hashCode = (this.contentPadding != null ? this.contentPadding.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ this.isCollapsed.GetHashCode();
hashCode = (hashCode * 397) ^ this.border.GetHashCode();
hashCode = (hashCode * 397) ^ this.borderGap.GetHashCode();
hashCode = (hashCode * 397) ^ this.icon.GetHashCode();
hashCode = (hashCode * 397) ^ this.input.GetHashCode();
hashCode = (hashCode * 397) ^ this.label.GetHashCode();
hashCode = (hashCode * 397) ^ this.hint.GetHashCode();
hashCode = (hashCode * 397) ^ this.prefix.GetHashCode();
hashCode = (hashCode * 397) ^ this.suffix.GetHashCode();
hashCode = (hashCode * 397) ^ this.prefixIcon.GetHashCode();
hashCode = (hashCode * 397) ^ this.suffixIcon.GetHashCode();
hashCode = (hashCode * 397) ^ this.helperError.GetHashCode();
hashCode = (hashCode * 397) ^ this.counter.GetHashCode();
hashCode = (hashCode * 397) ^ this.container.GetHashCode();
hashCode = (hashCode * 397) ^ (this.border != null ? this.border.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.borderGap != null ? this.borderGap.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.icon != null ? this.icon.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.input != null ? this.input.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.label != null ? this.label.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.hint != null ? this.hint.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.prefix != null ? this.prefix.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.suffix != null ? this.suffix.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.prefixIcon != null ? this.prefixIcon.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.suffixIcon != null ? this.suffixIcon.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.helperError != null ? this.helperError.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.counter != null ? this.counter.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.container != null ? this.container.GetHashCode() : 0);
public static bool operator ==(_Decoration left, _Decoration right) {
return Equals(left, right);
}
public static bool operator !=(_Decoration left, _Decoration right) {
return !Equals(left, right);
}
}
class _RenderDecorationLayout {

}
void _mountChild(Widget widget, _DecorationSlot slot) {
Element oldChild = this.slotToChild[slot];
Element oldChild = this.slotToChild.getOrDefault(slot);
Element newChild = this.updateChild(oldChild, widget, slot);
if (oldChild != null) {
this.slotToChild.Remove(slot);

}
void _updateChild(Widget widget, _DecorationSlot slot) {
Element oldChild = this.slotToChild[slot];
Element newChild = this.updateChild(oldChild, this.widget, slot);
Element oldChild = this.slotToChild.getOrDefault(slot);
Element newChild = this.updateChild(oldChild, widget, slot);
if (oldChild != null) {
this.childToSlot.Remove(oldChild);
this.slotToChild.Remove(slot);

return new _InputDecoratorState();
}
static RenderBox containerOf(BuildContext context) {
internal static RenderBox containerOf(BuildContext context) {
_RenderDecoration result =
(_RenderDecoration) context.ancestorRenderObjectOfType(new TypeMatcher<_RenderDecoration>());
return result?.container;

}
public static bool operator ==(InputDecoration left, InputDecoration right) {
return left.Equals(right);
return Equals(left, right);
return !left.Equals(right);
return !Equals(left, right);
}
public bool Equals(InputDecoration other) {

108
Runtime/material/text_selection.cs


using Rect = Unity.UIWidgets.ui.Rect;
using Transform = Unity.UIWidgets.widgets.Transform;
// todo using material components: FlatButton & Material ...
}
static class _TextSelectionUtils {
public _TextSelectionToolbar(Key key = null, Action handleCut = null,
Action handleCopy = null, Action handlePaste = null, Action handleSelectAll = null) : base(key: key) {
public _TextSelectionToolbar(Key key = null, VoidCallback handleCut = null,
VoidCallback handleCopy = null, VoidCallback handlePaste = null, VoidCallback handleSelectAll = null) : base(key: key) {
this.handleCut = handleCut;
this.handleCopy = handleCopy;
this.handlePaste = handlePaste;

public readonly Action handleCut;
public readonly Action handleCopy;
public readonly Action handlePaste;
public readonly Action handleSelectAll;
public readonly VoidCallback handleCut;
public readonly VoidCallback handleCopy;
public readonly VoidCallback handlePaste;
public readonly VoidCallback handleSelectAll;
MaterialLocalizations localizations = MaterialLocalizations.of(context);
items.Add(new _TempButton(onPressed: () => this.handleCut(), child: new Text("Cut")));
items.Add(new FlatButton(child: new Text(localizations.cutButtonLabel), onPressed: this.handleCut));
items.Add(new _TempButton(onPressed: () => this.handleCopy(), child: new Text("Copy")));
items.Add(new FlatButton(child: new Text(localizations.copyButtonLabel), onPressed: this.handleCopy));
items.Add(new _TempButton(onPressed: () => this.handlePaste(), child: new Text("Past")));
items.Add(new FlatButton(child: new Text(localizations.pasteButtonLabel), onPressed: this.handlePaste));
items.Add(new _TempButton(onPressed: () => this.handleSelectAll(), child: new Text("Select All")));
items.Add(new FlatButton(child: new Text(localizations.selectAllButtonLabel),
onPressed: this.handleSelectAll));
return new Container(
color: new Color(0xFFEFEFEF),
height: 44.0f, child: new Row(mainAxisSize: MainAxisSize.min, children: items));
return new Material(
elevation: 1.0f,
child: new Container(
color: new Color(0xFFEFEFEF),
height: 44.0f, child: new Row(mainAxisSize: MainAxisSize.min, children: items))
);
}
}

float x = globalPosition.dx - childSize.width / 2.0f;
float y = globalPosition.dy - childSize.height;
if (x < _TextSelectionUtils._kToolbarScreenPadding) {
x = _TextSelectionUtils._kToolbarScreenPadding;
if (x < MaterialUtils._kToolbarScreenPadding) {
x = MaterialUtils._kToolbarScreenPadding;
else if (x + childSize.width > this.screenSize.width - _TextSelectionUtils._kToolbarScreenPadding) {
x = this.screenSize.width - childSize.width - _TextSelectionUtils._kToolbarScreenPadding;
else if (x + childSize.width > this.screenSize.width - MaterialUtils._kToolbarScreenPadding) {
x = this.screenSize.width - childSize.width - MaterialUtils._kToolbarScreenPadding;
if (y < _TextSelectionUtils._kToolbarScreenPadding) {
y = _TextSelectionUtils._kToolbarScreenPadding;
if (y < MaterialUtils._kToolbarScreenPadding) {
y = MaterialUtils._kToolbarScreenPadding;
else if (y + childSize.height > this.screenSize.height - _TextSelectionUtils._kToolbarScreenPadding) {
y = this.screenSize.height - childSize.height - _TextSelectionUtils._kToolbarScreenPadding;
else if (y + childSize.height > this.screenSize.height - MaterialUtils._kToolbarScreenPadding) {
y = this.screenSize.height - childSize.height - MaterialUtils._kToolbarScreenPadding;
}
return new Offset(x, y);

class _MaterialTextSelectionControls : TextSelectionControls {
public override Size handleSize {
get {
return new Size(_TextSelectionUtils._kHandleSize,
_TextSelectionUtils._kHandleSize);
return new Size(MaterialUtils._kHandleSize,
MaterialUtils._kHandleSize);
}
}

child: new _TextSelectionToolbar(
handleCut: this.canCut(selectionDelegate)
? () => this.handleCut(selectionDelegate)
: (Action) null,
: (VoidCallback) null,
: (Action) null,
: (VoidCallback) null,
: (Action) null,
: (VoidCallback) null,
: (Action) null
: (VoidCallback) null
)
)
);

Widget handle = new Padding(
padding: EdgeInsets.only(right: 26.0f, bottom: 26.0f),
child: new SizedBox(
width: 20,
height: 20,
width: MaterialUtils._kHandleSize,
height: MaterialUtils._kHandleSize,
color: new Color(0xFFFF0000)
color: Theme.of(context).textSelectionHandleColor
)
)
)

}
return null;
}
}
public class _TempButton : StatelessWidget {
public _TempButton(
Key key = null,
GestureTapCallback onPressed = null,
EdgeInsets padding = null,
Color backgroundColor = null,
Widget child = null
) : base(key: key) {
this.onPressed = onPressed;
this.padding = padding ?? EdgeInsets.all(8.0f);
this.backgroundColor = backgroundColor ?? new Color(0);
this.child = child;
}
public readonly GestureTapCallback onPressed;
public readonly EdgeInsets padding;
public readonly Widget child;
public readonly Color backgroundColor;
public override Widget build(BuildContext context) {
return new GestureDetector(
onTap: this.onPressed,
child: new Container(
padding: this.padding,
color: this.backgroundColor,
child: this.child
)
);
}
}
}

2
Runtime/material/toggleable.cs


TickerProvider _vsync;
public bool? value {
public virtual bool? value {
get { return this._value; }
set {
D.assert(this.tristate || value != null);

37
Runtime/painting/text_style.cs


using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.painting {
public class TextStyle : Diagnosticable, IEquatable<TextStyle>, ParagraphBuilder.ITextStyleProvider {
public class TextStyle : Diagnosticable, IEquatable<TextStyle> {
public static readonly float _defaultFontSize = 14.0f;
public readonly bool inherit;
public readonly Color color;

this.fontFamily = fontFamily;
this.debugLabel = debugLabel;
this.background = background;
}
public ui.TextStyle getTextStyle(ui.TextStyle currentStyle = null, float textScaleFactor = 1.0f) {
if (currentStyle != null) {
return new ui.TextStyle(
color: this.color ?? currentStyle.color,
fontSize: this.fontSize != null ? this.fontSize * textScaleFactor : currentStyle.fontSize,
fontWeight: this.fontWeight ?? currentStyle.fontWeight,
fontStyle: this.fontStyle ?? currentStyle.fontStyle,
letterSpacing: this.letterSpacing ?? currentStyle.letterSpacing,
wordSpacing: this.wordSpacing ?? currentStyle.wordSpacing,
textBaseline: this.textBaseline ?? currentStyle.textBaseline,
height: this.height ?? currentStyle.height,
decoration: this.decoration ?? currentStyle.decoration,
decorationColor: this.decorationColor ?? currentStyle.decorationColor,
fontFamily: this.fontFamily ?? currentStyle.fontFamily,
background: this.background ?? currentStyle.background
);
}
return new ui.TextStyle(
color: this.color,
fontSize: this.fontSize * textScaleFactor,
fontWeight: this.fontWeight,
fontStyle: this.fontStyle,
letterSpacing: this.letterSpacing,
wordSpacing: this.wordSpacing,
textBaseline: this.textBaseline,
height: this.height,
decoration: this.decoration,
decorationColor: this.decorationColor,
fontFamily: this.fontFamily,
background: this.background
);
}
public RenderComparison compareTo(TextStyle other) {

decoration: other.decoration,
decorationColor: other.decorationColor,
decorationStyle: other.decorationStyle,
background: other.background,
debugLabel: mergedDebugLabel
);
}

3
Runtime/rendering/binding.cs


using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.rendering {

}
protected virtual void drawFrame() {
PerformanceUtils.instance.startProfile();
PerformanceUtils.instance.endProfile();
}
public override void hitTest(HitTestResult result, Offset position) {

61
Runtime/rendering/editable.cs


public static readonly char obscuringCharacter = '•';
static readonly float _kCaretGap = 1.0f;
static readonly float _kCaretHeightOffset = 2.0f;
static readonly float _kCaretWidth = 1.0f;
TextPainter _textPainter;
Color _cursorColor;

bool? hasFocus = null, int? maxLines = 1, Color selectionColor = null,
TextSelection selection = null, bool obscureText = false, SelectionChangedHandler onSelectionChanged = null,
CaretChangedHandler onCaretChanged = null, bool ignorePointer = false,
float cursorWidth = 1.0f,
Radius cursorRadius = null,
bool enableInteractiveSelection = true,
TextSelectionDelegate textSelectionDelegate = null) {
D.assert(textSelectionDelegate != null);
this._textPainter = new TextPainter(text: text, textAlign: textAlign, textDirection: textDirection,

this._selection = selection;
this._obscureText = obscureText;
this._offset = offset;
this._cursorWidth = cursorWidth;
this._cursorRadius = cursorRadius;
this._enableInteractiveSelection = enableInteractiveSelection;
this.ignorePointer = ignorePointer;
this.onCaretChanged = onCaretChanged;
this.onSelectionChanged = onSelectionChanged;

bool vKey = pressedKeyCode == KeyCode.V;
bool cKey = pressedKeyCode == KeyCode.C;
bool del = pressedKeyCode == KeyCode.Delete;
bool backDel = pressedKeyCode == KeyCode.Backspace;
if (keyEvent is RawKeyCommandEvent) { // editor case
this._handleShortcuts(((RawKeyCommandEvent)keyEvent).command);
return;
}
if ((ctrl || (isMac && cmd)) && (xKey || vKey || cKey || aKey)) { // runtime case
if (xKey) {
this._handleShortcuts(KeyCommand.Cut);
} else if (aKey) {
this._handleShortcuts(KeyCommand.SelectAll);
} else if (vKey) {
this._handleShortcuts(KeyCommand.Paste);
} else if (cKey) {
this._handleShortcuts(KeyCommand.Copy);
}
return;
}
if (arrow) {
int newOffset = this._extentOffset;

newOffset = this._handleShift(rightArrow, leftArrow, shift, newOffset);
this._extentOffset = newOffset;
} else if ((ctrl || (isMac && cmd)) && (xKey || vKey || cKey || aKey)) {
this._handleShortcuts(pressedKeyCode);
if (del || backDel) {
this._handleDelete(backDel);
if (del) {
this._handleDelete();
}
}

return newOffset;
}
void _handleShortcuts(KeyCode pressedKeyCode) {
switch (pressedKeyCode) {
case KeyCode.C:
void _handleShortcuts(KeyCommand cmd) {
switch (cmd) {
case KeyCommand.Copy:
case KeyCode.X:
case KeyCommand.Cut:
if (!this.selection.isCollapsed) {
Clipboard.setData(
new ClipboardData(text: this.selection.textInside(this.text.text)));

);
}
break;
case KeyCode.V:
case KeyCommand.Paste:
TextEditingValue value = this.textSelectionDelegate.textEditingValue;
Clipboard.getData(Clipboard.kTextPlain).Then(data => {
if (data != null) {

});
break;
case KeyCode.A:
case KeyCommand.SelectAll:
this._baseOffset = 0;
this._extentOffset = this.textSelectionDelegate.textEditingValue.text.Length;
this.onSelectionChanged(

}
}
void _handleDelete(bool backDel) {
void _handleDelete() {
if (backDel && selection.isCollapsed) {
if (selection.start <= 0) {
return;
}
selection = TextSelection.collapsed(selection.start - 1, selection.affinity);
}
if (selection.textAfter(this.text.text).isNotEmpty()) {
this.textSelectionDelegate.textEditingValue = new TextEditingValue(
text: selection.textBefore(this.text.text)

public Rect getLocalRectForCaret(TextPosition caretPosition) {
this._layoutText(this.constraints.maxWidth);
var caretOffset = this._textPainter.getOffsetForCaret(caretPosition, this._caretPrototype);
return Rect.fromLTWH(0.0f, 0.0f, _kCaretWidth, this.preferredLineHeight)
return Rect.fromLTWH(0.0f, 0.0f, this.cursorWidth, this.preferredLineHeight)
.shift(caretOffset + this._paintOffset);
}

}
}
void handleTapDown(TapDownDetails details) {
public void handleTapDown(TapDownDetails details) {
this._lastTapDownPosition = details.globalPosition + - this._paintOffset;
if (!Application.isMobilePlatform) {
this.selectPosition(SelectionChangedCause.tap);

return;
}
var caretMargin = _kCaretGap + _kCaretWidth;
var caretMargin = _kCaretGap + this.cursorWidth;
var avialableWidth = Mathf.Max(0.0f, constraintWidth - caretMargin);
var maxWidth = this._isMultiline ? avialableWidth : float.PositiveInfinity;
this._textPainter.layout(minWidth: avialableWidth, maxWidth: maxWidth);

protected override void performLayout() {
this._layoutText(this.constraints.maxWidth);
this._caretPrototype = Rect.fromLTWH(0.0f, _kCaretHeightOffset, _kCaretWidth,
this._caretPrototype = Rect.fromLTWH(0.0f, _kCaretHeightOffset, this.cursorWidth,
this.preferredLineHeight - 2.0f * _kCaretHeightOffset);
this._selectionRects = null;

var contentSize = new Size(textPainterSize.width + _kCaretGap + _kCaretWidth,
var contentSize = new Size(textPainterSize.width + _kCaretGap + this.cursorWidth,
textPainterSize.height);
var _maxScrollExtent = this._getMaxScrollExtend(contentSize);
this._hasVisualOverflow = _maxScrollExtent > 0.0;

35
Runtime/rendering/flex.cs


using System;
using System.Collections.Generic;
using UIWidgets.Runtime.rendering;
using Unity.UIWidgets.foundation;
using Rect = Unity.UIWidgets.ui.Rect;
namespace Unity.UIWidgets.rendering {
public enum FlexFit {

}
context.pushClipRect(this.needsCompositing, offset, Offset.zero & this.size, this.defaultPaint);
D.assert(() => {
string debugOverflowHints =
$"The overflowing {this.GetType()} has an orientation of {this._direction}.\n" +
$"The edge of the {this.GetType()} that is overflowing has been marked " +
"in the rendering with a yellow and black striped pattern. This is " +
$"usually caused by the contents being too big for the {this.GetType()}. " +
"Consider applying a flex factor (e.g. using an Expanded widget) to " +
$"force the children of the {this.GetType()} to fit within the available " +
"space instead of being sized to their natural size.\n" +
"This is considered an error condition because it indicates that there " +
"is content that cannot be seen. If the content is legitimately bigger " +
"than the available space, consider clipping it with a ClipRect widget " +
"before putting it in the flex, or using a scrollable container rather " +
"than a Flex, like a ListView.";
Rect overflowChildRect;
switch (this._direction) {
case Axis.horizontal:
overflowChildRect = Rect.fromLTWH(0.0f, 0.0f, this.size.width + this._overflow, 0.0f);
break;
case Axis.vertical:
overflowChildRect = Rect.fromLTWH(0.0f, 0.0f, 0.0f, this.size.height + this._overflow);
break;
default:
throw new Exception("Unknown direction: " + this._direction);
}
DebugOverflowIndicatorMixin.paintOverflowIndicator(this, context, offset, Offset.zero & this.size,
overflowChildRect, overflowHints: debugOverflowHints);
return true;
});
}
protected override bool hitTestChildren(HitTestResult result, Offset position = null) {

7
Runtime/rendering/shifted_box.cs


using Unity.UIWidgets.foundation;
using UIWidgets.Runtime.rendering;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;

}
context.pushClipRect(this.needsCompositing, offset, Offset.zero & this.size, base.paint);
D.assert(() => {
DebugOverflowIndicatorMixin.paintOverflowIndicator(this, context, offset, this._overflowContainerRect, this._overflowChildRect);
return true;
});
}
}

47
Runtime/service/keyboard.cs


namespace Unity.UIWidgets.service {
interface KeyboardDelegate: IDisposable {
void show();
void hide();

class DefaultKeyboardDelegate : KeyboardDelegate, TextInputOnGUIListener {
int _client;
string _lastCompositionString;
TextEditingValue _value;
public void show() {

if (this._client == 0) {
return;
}
var oldValue = this._value;
if (currentEvent.keyCode == KeyCode.Return) {
Window.instance.run(() => { TextInput._performAction(this._client, TextInputAction.newline); });
}
if (currentEvent.character != '\0') {
if (currentEvent.keyCode == KeyCode.Backspace) {
if (this._value.selection.isValid) {
this._value = this._value.deleteSelection(true);
}
} else if (currentEvent.character != '\0') {
this._value = this._value.clearCompose();
this._value = this._value.clearCompose();
if (ch == '\n') {
Window.instance.run(() => { TextInput._performAction(this._client, TextInputAction.newline); });
}
}
Window.instance.run(() => { TextInput._updateEditingState(this._client, this._value); });
}
} else if (!string.IsNullOrEmpty(Input.compositionString)) {
this._value = this._value.compose(Input.compositionString);
if (!string.IsNullOrEmpty(Input.compositionString) &&
this._lastCompositionString != Input.compositionString) {
this._value = this._value.compose(Input.compositionString);
if (this._value != oldValue) {
}
this._lastCompositionString = Input.compositionString;
}
}
public void Dispose() {

}
abstract class AbstractUIWidgetsKeyboardDelegate : KeyboardDelegate {
UIWidgetsMessageManager.instance.AddChannelMessageDelegate("TextInput", this._handleMethodCall);
UIWidgetsMessageManager.instance.
AddChannelMessageDelegate("TextInput", this._handleMethodCall);
UIWidgetsMessageManager.instance.RemoveChannelMessageDelegate("TextInput", this._handleMethodCall);
UIWidgetsMessageManager.instance.
RemoveChannelMessageDelegate("TextInput", this._handleMethodCall);
}
public abstract void show();

50
Runtime/service/raw_keyboard.cs


return;
}
var keyboardEvent = RawKeyEvent.fromEvent(evt);
var keyboardEvent = RawKeyEvent.processGUIEvent(evt);
foreach (var listener in new List<ValueChanged<RawKeyEvent>>(this._listeners)) {
if (this._listeners.Contains(listener)) {
listener(keyboardEvent);

this.data = data;
}
public static RawKeyEvent fromEvent(Event evt) {
public static RawKeyEvent processGUIEvent(Event evt) {
if (evt.type == EventType.ValidateCommand) {
var cmd = toKeyCommand(evt.commandName);
if (cmd != null) {
evt.Use();
return null;
}
} else if (evt.type == EventType.ExecuteCommand) { // Validate/ExecuteCommand is editor only
var cmd = toKeyCommand(evt.commandName);
if (cmd != null) {
return new RawKeyCommandEvent(new RawKeyEventData(evt), cmd.Value);
}
}
if (evt.type == EventType.KeyDown) {
return new RawKeyDownEvent(new RawKeyEventData(evt));
} else if (evt.type == EventType.KeyUp) {

}
public readonly RawKeyEventData data;
static KeyCommand? toKeyCommand(string commandName) {
switch (commandName) {
case "Paste":
return KeyCommand.Paste;
case "Copy":
return KeyCommand.Copy;
case "SelectAll":
return KeyCommand.SelectAll;
case "Cut":
return KeyCommand.Cut;
}
return null;
}
}
public class RawKeyDownEvent: RawKeyEvent {

}
}
public class RawKeyCommandEvent : RawKeyEvent {
public readonly KeyCommand command;
public RawKeyCommandEvent(RawKeyEventData data, KeyCommand command) : base(data) {
this.command = command;
}
}
public enum KeyCommand {
Copy,
Cut,
Paste,
SelectAll,
}
public class RawKeyEventData {
public readonly Event unityEvent;

27
Runtime/service/text_formatter.cs


(substring) => this.blacklistedPattern.Replace(substring, this.replacementString));
}
}
public class LengthLimitingTextInputFormatter : TextInputFormatter {
public LengthLimitingTextInputFormatter(int? maxLength) {
D.assert(maxLength == null || maxLength > 0);
this.maxLength = maxLength;
}
public readonly int? maxLength;
public override TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
if (this.maxLength != null && newValue.text.Length > this.maxLength) {
TextSelection newSelection = newValue.selection.copyWith(
baseOffset: Math.Min(newValue.selection.start, this.maxLength.Value),
extentOffset: Math.Min(newValue.selection.end, this.maxLength.Value)
);
string truncated = newValue.text.Substring(0, this.maxLength.Value);
return new TextEditingValue(
text: truncated,
selection: newSelection,
composing: TextRange.empty
);
}
return newValue;
}
}
static class Util {
internal static TextEditingValue _selectionAwareTextManipulation(TextEditingValue value,

9
Runtime/service/text_input.cs


return this.copyWith(
text: this.text.Substring(0, this.selection.start - 1) + this.selection.textAfter(this.text),
selection: TextSelection.collapsed(this.selection.start - 1));
selection: TextSelection.collapsed(this.selection.start - 1),
composing: TextRange.empty);
}
if (this.selection.start >= this.text.Length) {

return this.copyWith(text: this.text.Substring(0, this.selection.start) +
this.text.Substring(this.selection.start + 1));
this.text.Substring(this.selection.start + 1),
composing: TextRange.empty);
return this.copyWith(text: newText, selection: TextSelection.collapsed(this.selection.start));
return this.copyWith(text: newText, selection: TextSelection.collapsed(this.selection.start),
composing: TextRange.empty);
}
}

2
Runtime/ui/painting/canvas_impl.cs


var font = FontManager.instance.getOrCreate(textBlob.style.fontFamily, style.fontWeight, style.fontStyle).font;
var fontSizeToLoad = Mathf.CeilToInt(style.UnityFontSize * scale);
var subText = textBlob.text.Substring(textBlob.textOffset, textBlob.textSize);
font.RequestCharactersInTexture(subText, fontSizeToLoad, style.UnityFontStyle);
font.RequestCharactersInTextureSafe(subText, fontSizeToLoad, style.UnityFontStyle);
var tex = font.material.mainTexture;

7
Runtime/ui/painting/path.cs


var cmd = (PathCommand) commands[i];
switch (cmd) {
case PathCommand.moveTo:
this._commandx = commands[i + 1];
this._commandy = commands[i + 2];
i += 3;
break;
this._expandBounds(this._commandx, this._commandy);
this._expandBounds(commands[i + 1], commands[i + 2]);
this._commandx = commands[i + 1];
this._commandy = commands[i + 2];

this._expandBounds(this._commandx, this._commandy);
this._expandBounds(commands[i + 1], commands[i + 2]);
this._expandBounds(commands[i + 3], commands[i + 4]);
this._expandBounds(commands[i + 5], commands[i + 6]);

void _addPoint(PathPoint point) {
if (this._paths.Count == 0) {
this.addPath();
this.addPoint(0, 0, PointFlags.corner);
}
var path = this._paths.Last();

63
Runtime/ui/painting/txt/font_manager.cs


}
class GlyphInfo {
public static GlyphInfo empty = new GlyphInfo(Rect.zero,0, 0, new Vector2(0, 0),
new Vector2(0, 0), new Vector2(0, 0), new Vector2(0, 0));
public readonly Rect rect;
public readonly float advance;
public readonly float glyphHeight;
public readonly Vector2 uvTopLeft;
public readonly Vector2 uvTopRight;
public readonly Vector2 uvBottomLeft;
public readonly Vector2 uvBottomRight;
public GlyphInfo(CharacterInfo info) {
this.rect = Rect.fromLTRB(info.minX, -info.maxY, info.maxX, -info.minY);
this.advance = info.advance;
this.glyphHeight = info.glyphHeight;
this.uvTopLeft = info.uvTopLeft;
this.uvTopRight = info.uvTopRight;
this.uvBottomLeft = info.uvBottomLeft;
this.uvBottomRight = info.uvBottomRight;
}
public GlyphInfo(Rect rect, float advance, float glyphHeight,
Vector2 uvTopLeft, Vector2 uvTopRight, Vector2 uvBottomLeft, Vector2 uvBottomRight) {
this.rect = rect;
this.advance = advance;
this.glyphHeight = glyphHeight;
this.uvTopLeft = uvTopLeft;
this.uvTopRight = uvTopRight;
this.uvBottomLeft = uvBottomLeft;
this.uvBottomRight = uvBottomRight;
}
}
{
public static CharacterInfo getCharacterInfo(this Font font, char ch, int fontSize, UnityEngine.FontStyle fontStyle)
{
{
internal static GlyphInfo getGlyphInfo(this Font font, char ch, int fontSize, UnityEngine.FontStyle fontStyle) {
if (fontSize <= 0) {
return GlyphInfo.empty;
}
if (!success) {
Debug.LogWarning($"character info not found from the given font: character '{ch}' (code{(int)ch}) font: ${font.name}");
if (!success) {
if (!char.IsControl(ch)) {
Debug.LogWarning($"character info not found from the given font: character '{ch}' (code{(int)ch}) font: ${font.name}");
}
return GlyphInfo.empty;
}
return new GlyphInfo(info);
}
internal static void RequestCharactersInTextureSafe(this Font font, string text, int fontSize,
UnityEngine.FontStyle fontStyle = UnityEngine.FontStyle.Normal) {
if (fontSize <= 0) {
return;
return info;
font.RequestCharactersInTexture(text, fontSize, fontStyle);
}
}
}

29
Runtime/ui/painting/txt/mesh_generator.cs


continue;
}
CharacterInfo charInfo = font.getCharacterInfo(ch, fontSizeToLoad, style.UnityFontStyle);
var minX = charInfo.minX / this._scale;
var maxX = charInfo.maxX / this._scale;
var minY = charInfo.minY / this._scale;
var maxY = charInfo.maxY / this._scale;
if (fontSizeToLoad == 0) {
continue;
}
var glyphInfo = font.getGlyphInfo(ch, fontSizeToLoad, style.UnityFontStyle);
var minX = glyphInfo.rect.left / this._scale;
var maxX = glyphInfo.rect.right / this._scale;
var minY = glyphInfo.rect.top / this._scale;
var maxY = glyphInfo.rect.bottom / this._scale;
vertices.Add(new Vector3((position.x + minX), (position.y - maxY), 0));
vertices.Add(new Vector3((position.x + maxX), (position.y - maxY), 0));
vertices.Add(new Vector3((position.x + maxX), (position.y - minY), 0));
vertices.Add(new Vector3((position.x + minX), (position.y - minY), 0));
vertices.Add(new Vector3((position.x + minX), (position.y + minY), 0));
vertices.Add(new Vector3((position.x + maxX), (position.y + minY), 0));
vertices.Add(new Vector3((position.x + maxX), (position.y + maxY), 0));
vertices.Add(new Vector3((position.x + minX), (position.y + maxY), 0));
triangles.Add(baseIndex);
triangles.Add(baseIndex + 1);

triangles.Add(baseIndex + 3);
uv.Add(charInfo.uvTopLeft);
uv.Add(charInfo.uvTopRight);
uv.Add(charInfo.uvBottomRight);
uv.Add(charInfo.uvBottomLeft);
uv.Add(glyphInfo.uvTopLeft);
uv.Add(glyphInfo.uvTopRight);
uv.Add(glyphInfo.uvBottomRight);
uv.Add(glyphInfo.uvBottomLeft);
}
if (vertices.Count == 0) {

23
Runtime/ui/painting/txt/text_blob.cs


namespace Unity.UIWidgets.ui {
public class TextBlob {
public TextBlob(string text, int textOffset, int textSize, Vector2d[] positions, Rect bounds, TextStyle style) {
internal TextBlob(string text, int textOffset, int textSize, Vector2d[] positions, Rect bounds, TextStyle style) {
this.instanceId = ++_nextInstanceId;
this.positions = positions;
this.text = text;

}
static long _nextInstanceId = 0;
public readonly long instanceId;
public readonly string text;
public readonly int textOffset;
public readonly int textSize;
public readonly Vector2d[] positions;
public readonly TextStyle style;
public readonly Rect bounds; // bounds with positions[start] as origin
internal readonly long instanceId;
internal readonly string text;
internal readonly int textOffset;
internal readonly int textSize;
internal readonly Vector2d[] positions;
internal readonly TextStyle style;
internal readonly Rect bounds; // bounds with positions[start] as origin
}
public class TextBlobBuilder {

int _size;
Rect _bounds;
public void allocRunPos(TextStyle style, string text, int offset, int size) {
public void allocRunPos(painting.TextStyle style, string text, int offset, int size, float textScaleFactor = 1.0f) {
this.allocRunPos(TextStyle.applyStyle(null, style, textScaleFactor), text, offset, size);
}
internal void allocRunPos(TextStyle style, string text, int offset, int size) {
this._style = style;
this._text = text;
this._textOffset = offset;

39
Runtime/ui/text.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.ui {
public enum FontStyle {

}
}
public class TextStyle : IEquatable<TextStyle> {
internal class TextStyle : IEquatable<TextStyle> {
public readonly Color color = Color.fromARGB(255, 0, 0, 0);
public readonly float fontSize = 14.0f;
public readonly FontWeight fontWeight = FontWeight.w400;

internal int UnityFontSize {
get { return (int) this.fontSize; }
}
public static TextStyle applyStyle(TextStyle currentStyle, painting.TextStyle style, float textScaleFactor) {
if (currentStyle != null) {
return new ui.TextStyle(
color: style.color ?? currentStyle.color,
fontSize: style.fontSize != null ? style.fontSize * textScaleFactor : currentStyle.fontSize,
fontWeight: style.fontWeight ?? currentStyle.fontWeight,
fontStyle: style.fontStyle ?? currentStyle.fontStyle,
letterSpacing: style.letterSpacing ?? currentStyle.letterSpacing,
wordSpacing: style.wordSpacing ?? currentStyle.wordSpacing,
textBaseline: style.textBaseline ?? currentStyle.textBaseline,
height: style.height ?? currentStyle.height,
decoration: style.decoration ?? currentStyle.decoration,
decorationColor: style.decorationColor ?? currentStyle.decorationColor,
fontFamily: style.fontFamily ?? currentStyle.fontFamily,
background: style.background ?? currentStyle.background
);
}
return new ui.TextStyle(
color: style.color,
fontSize: style.fontSize * textScaleFactor,
fontWeight: style.fontWeight,
fontStyle: style.fontStyle,
letterSpacing: style.letterSpacing,
wordSpacing: style.wordSpacing,
textBaseline: style.textBaseline,
height: style.height,
decoration: style.decoration,
decorationColor: style.decorationColor,
fontFamily: style.fontFamily,
background: style.background
);
}
public bool Equals(TextStyle other) {

}
}
public TextStyle getTextStyle() {
internal TextStyle getTextStyle() {
return new TextStyle(
fontWeight: this.fontWeight,
fontStyle: this.fontStyle,

12
Runtime/ui/txt/layout.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
public class Layout {
class Layout {
int _start;
int _count;
List<float> _advances = new List<float>();

this._positions.Clear();
this._count = count;
var font = FontManager.instance.getOrCreate(style.fontFamily, style.fontWeight, style.fontStyle).font;
font.RequestCharactersInTexture(this._text.Substring(start, count),
font.RequestCharactersInTextureSafe(this._text.Substring(start, count),
style.UnityFontSize,
style.UnityFontStyle);

int charIndex = start + i;
var ch = text[charIndex];
CharacterInfo characterInfo = font.getCharacterInfo(ch, style.UnityFontSize, style.UnityFontStyle);
var glyphInfo = font.getGlyphInfo(ch, style.UnityFontSize, style.UnityFontStyle);
var rect = Rect.fromLTRB(characterInfo.minX, -characterInfo.maxY, characterInfo.maxX,
-characterInfo.minY);
var rect = glyphInfo.rect;
rect = rect.translate(this._advance, 0);
if (this._bounds == null || this._bounds.isEmpty) {
this._bounds = rect;

}
this._positions.Add(this._advance);
float advance = characterInfo.advance;
float advance = glyphInfo.advance;
if (ch == '\t') {
advance = this._tabStops.nextTab((this._advance + offset)) - this._advance;
}

17
Runtime/ui/txt/linebreaker.cs


using System.Collections.Generic;
using System;
using System.Collections.Generic;
public class TabStops {
class TabStops {
int _tabWidth = int.MaxValue;
Font _font;

}
if (this._tabWidth == int.MaxValue) {
this._font.RequestCharactersInTexture(" ", this._fontSize);
CharacterInfo characterInfo = this._font.getCharacterInfo(' ', this._fontSize, UnityEngine.FontStyle.Normal);
this._tabWidth = characterInfo.advance * kTabSpaceCount;
this._font.RequestCharactersInTextureSafe(" ", this._fontSize);
if (this._fontSize > 0) {
var glyphInfo = this._font.getGlyphInfo(' ', this._fontSize, UnityEngine.FontStyle.Normal);
this._tabWidth = (int)Math.Round(glyphInfo.advance * kTabSpaceCount);
}
}
if (this._tabWidth == 0) {

}
}
public class Candidate {
class Candidate {
public int offset;
public int pre;
public float preBreak;

public int postSpaceCount;
}
public class LineBreaker {
class LineBreaker {
const float ScoreInfty = float.MaxValue;
const float ScoreDesperate = 1e10f;

2
Runtime/ui/txt/paint_record.cs


namespace Unity.UIWidgets.ui {
public class PaintRecord {
class PaintRecord {
public PaintRecord(TextStyle style, Offset offset, TextBlob _text,
FontMetrics metrics,
int line, float runWidth) {

87
Runtime/ui/txt/paragraph.cs


}
}
public class CodeUnitRun {
class CodeUnitRun {
public readonly int lineNumber;
public readonly TextDirection direction;
public readonly Range<int> codeUnits;

}
public class FontMetrics {
class FontMetrics {
public readonly float ascent;
public readonly float leading = 0.0f;
public readonly float descent;

public static FontMetrics fromFont(Font font, int fontSize) {
var ascent = -font.ascent * fontSize / font.fontSize;
var descent = (font.lineHeight - font.ascent) * fontSize / font.fontSize;
float? fxHeight = null;
font.RequestCharactersInTexture("x", fontSize);
CharacterInfo charInfo;
if (font.GetCharacterInfo('x', out charInfo, fontSize)) {
fxHeight = charInfo.glyphHeight;
}
font.RequestCharactersInTextureSafe("x", fontSize, UnityEngine.FontStyle.Normal);
var glyphInfo = font.getGlyphInfo('x', fontSize, UnityEngine.FontStyle.Normal);
float fxHeight = glyphInfo.glyphHeight;
public class LineStyleRun {
class LineStyleRun {
public readonly int start;
public readonly int end;
public readonly TextStyle style;

}
}
public class PositionWithAffinity {
class PositionWithAffinity {
public readonly int position;
public readonly TextAffinity affinity;

}
}
public class GlyphPosition {
class GlyphPosition {
public readonly Range<float> xPos;
public readonly Range<int> codeUnits;

}
}
public class Range<T> : IEquatable<Range<T>> {
class Range<T> : IEquatable<Range<T>> {
public Range(T start, T end) {
this.start = start;
this.end = end;

public readonly T start, end;
}
public static class RangeUtils {
static class RangeUtils {
public static Range<float> shift(Range<float> value, float shift) {
return new Range<float>(value.start + shift, value.end + shift);
}

public class GlyphLine {
class GlyphLine {
public readonly List<GlyphPosition> positions;
public readonly int totalCountUnits;

}
public void paint(Canvas canvas, Offset offset) {
foreach (var paintRecord in this._paintRecords) {
this.paintBackground(canvas, paintRecord, offset);
}
foreach (var paintRecord in this._paintRecords) {
var paint = new Paint {
filterMode = FilterMode.Bilinear,

List<PaintRecord> paintRecords = new List<PaintRecord>();
for (int i = 0; i < lineRuns.Count; ++i) {
var run = lineRuns[i];
string text = this._text;
layout.doLayout(runXOffset, this._text, textStart, textCount, run.style);
string ellipsis = this._paragraphStyle.ellipsis;
if (!string.IsNullOrEmpty(ellipsis) && !this._width.isInfinite() && !lineRange.hardBreak
&& i == lineRuns.Count - 1 && (lineNumber == lineLimit - 1 || this._paragraphStyle.maxLines == null)) {
float ellipsisWidth = Layout.measureText(runXOffset, ellipsis, 0,
ellipsis.Length, run.style, null, 0, this._tabStops);
List<float> textAdvances = new List<float>(textCount);
for (int index = 0; index < textCount;++index) {
textAdvances.Add(0);
}
float textWidth = Layout.measureText(runXOffset, this._text, textStart, textCount,
run.style, textAdvances, 0, this._tabStops);
int truncateCount = 0;
while (truncateCount < textCount &&
runXOffset + textWidth + ellipsisWidth > this._width) {
textWidth -= textAdvances[textCount - truncateCount - 1];
truncateCount++;
}
var ellipsizedText = this._text.Substring(textStart, textCount - truncateCount) + ellipsis;
textStart = 0;
textCount = ellipsizedText.Length;
text = ellipsizedText;
if (this._paragraphStyle.maxLines == null) {
lineLimit = lineNumber + 1;
this._didExceedMaxLines = true;
}
}
layout.doLayout(runXOffset, text, textStart, textCount, run.style);
if (layout.nGlyphs() == 0) {
continue;
}

builder.allocRunPos(run.style, this._text, textStart, textCount);
builder.allocRunPos(run.style, text, textStart, textCount);
builder.setBounds(layout.getBounds());
glyphPositions.Clear();

}
public void setText(string text, StyledRuns runs) {
internal void setText(string text, StyledRuns runs) {
this._text = text;
this._runs = runs;
this._needsLayout = true;

return TextBox.fromLTBD(0, top, 0, bottom, TextDirection.ltr);
}
public PositionWithAffinity getGlyphPositionAtCoordinate(float dx, float dy) {
internal PositionWithAffinity getGlyphPositionAtCoordinate(float dx, float dy) {
if (this._lineHeights.Count == 0) {
return new PositionWithAffinity(0, TextAffinity.downstream);
}

return Mathf.Max(lineCount - 1, 0);
}
public LineRange getLineRange(int lineIndex) {
internal LineRange getLineRange(int lineIndex) {
public Range<int> getWordBoundary(int offset) {
internal Range<int> getWordBoundary(int offset) {
WordSeparate s = new WordSeparate(this._text);
return s.findWordRange(offset);
}

}
}
void paintBackground(Canvas canvas, PaintRecord record, Offset baseOffset) {
if (record.style.background == null) {
return;
}
var metrics = record.metrics;
Rect rect = Rect.fromLTRB(0, metrics.ascent, record.runWidth, metrics.descent);
rect = rect.shift(baseOffset + record.offset);
canvas.drawRect(rect, record.style.background);
}
float getLineXOffset(float lineTotalAdvance) {
if (this._width.isInfinite()) {
return 0;

}
}
public class SplayTree<TKey, TValue> : IDictionary<TKey, TValue> where TKey : IComparable<TKey> {
class SplayTree<TKey, TValue> : IDictionary<TKey, TValue> where TKey : IComparable<TKey> {
SplayTreeNode root;
int count;
int version = 0;

12
Runtime/ui/txt/paragraph_builder.cs


List<int> _styleStack = new List<int>();
int _paragraph_style_index;
public interface ITextStyleProvider {
TextStyle getTextStyle(TextStyle current = null, float textScaleFactor = 1.0f);
}
public ParagraphBuilder(ParagraphStyle style) {
this.setParagraphStyle(style);
}

return paragraph;
}
public void pushStyle(ITextStyleProvider style, float textScaleFactor) {
var newStyle = style.getTextStyle(this.peekStyle(), textScaleFactor: textScaleFactor);
public void pushStyle(painting.TextStyle style, float textScaleFactor) {
var newStyle = TextStyle.applyStyle(this.peekStyle(), style, textScaleFactor: textScaleFactor);
public void pushStyle(TextStyle style) {
internal void pushStyle(TextStyle style) {
var styleIndex = this._runs.addStyle(style);
this._styleStack.Add(styleIndex);
this._runs.startRun(styleIndex, this._text.Length);

this._text.Append(text);
}
public TextStyle peekStyle() {
internal TextStyle peekStyle() {
return this._runs.getStyle(this.peekStyleIndex());
}

6
Runtime/ui/txt/styled_runs.cs


using System.Collections.Generic;
namespace Unity.UIWidgets.ui {
public class StyledRuns {
class StyledRuns {
readonly List<TextStyle> styles = new List<TextStyle>();
readonly List<IndexedRun> runs = new List<IndexedRun>();

}
}
public class Run {
internal class Run {
public readonly TextStyle style;
public readonly int start;
public readonly int end;

}
}
public class IndexedRun {
internal class IndexedRun {
public readonly int styleIndex = 0;
public readonly int start;
public int end;

2
Runtime/ui/txt/word_separate.cs


namespace Unity.UIWidgets.ui {
public class WordSeparate {
class WordSeparate {
enum Direction {
Forward,
Backward,

2
Runtime/ui/txt/wordbreaker.cs


namespace Unity.UIWidgets.ui {
public class WordBreaker {
class WordBreaker {
public const uint U16_SURROGATE_OFFSET = ((0xd800 << 10) + 0xdc00 - 0x10000);
string _text;
int _offset;

17
Runtime/ui/window.cs


using System.Collections.Generic;
using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.service;
namespace Unity.UIWidgets.ui {
public delegate void VoidCallback();

if (value == null) {
D.assert(_instance != null, "Window.instance is already cleared.");
_instance = null;
} else {
}
else {
D.assert(_instance == null, "Window.instance is already assigned.");
_instance = value;
}

public abstract Timer runInMain(Action callback);
public abstract IDisposable getScope();
float deltaTime;
public void updateDeltaTime(float unscaledDeltaTime) {
this.deltaTime += (unscaledDeltaTime - this.deltaTime) * 0.1f;
}
public float getFPS() {
return 1.0f / this.deltaTime;
}
}
}

2
Runtime/widgets/automatic_keep_alive.cs


this.GetType() +
" created a Ticker via its TickerProviderStateMixin, but at the time " +
"dispose() was called on the mixin, that Ticker was still active. All Tickers must " +
"be disposed before calling super.dispose(). Tickers used by AnimationControllers " +
"be disposed before calling base.dispose(). Tickers used by AnimationControllers " +
"should be disposed by calling dispose() on the AnimationController itself. " +
"Otherwise, the ticker will leak.\n" +
"The offending ticker was: " + ticker.toString(debugIncludeStack: true)

43
Runtime/widgets/basic.cs


}
}
public class UnconstrainedBox : SingleChildRenderObjectWidget {
public UnconstrainedBox(
Key key = null,
Widget child = null,
Alignment alignment = null,
Axis? constrainedAxis = null
) : base(key: key, child: child) {
this.alignment = alignment ?? Alignment.center;
this.constrainedAxis = constrainedAxis;
}
public readonly Alignment alignment;
public readonly Axis? constrainedAxis;
public override void updateRenderObject(BuildContext context, RenderObject _renderObject) {
RenderUnconstrainedBox renderObject = _renderObject as RenderUnconstrainedBox;
renderObject.alignment = this.alignment;
renderObject.constrainedAxis = this.constrainedAxis;
}
public override RenderObject createRenderObject(BuildContext context) {
return new RenderUnconstrainedBox(
alignment: this.alignment,
constrainedAxis: this.constrainedAxis
);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<Alignment>("alignment", this.alignment));
properties.add(new DiagnosticsProperty<Axis>("constrainedAxis", null));
}
}
public class SliverToBoxAdapter : SingleChildRenderObjectWidget {
public SliverToBoxAdapter(
Key key = null,

((RenderFlex) renderObject).verticalDirection = this.verticalDirection;
((RenderFlex) renderObject).textBaseline = this.textBaseline ?? TextBaseline.alphabetic;
}
properties.add(new EnumProperty<MainAxisSize>("mainAxisSize", this.mainAxisSize, defaultValue: MainAxisSize.max));
properties.add(new EnumProperty<MainAxisSize>("mainAxisSize", this.mainAxisSize,
defaultValue: MainAxisSize.max));
properties.add(new EnumProperty<VerticalDirection>("verticalDirection", this.verticalDirection, defaultValue: VerticalDirection.down));
properties.add(new EnumProperty<VerticalDirection>("verticalDirection", this.verticalDirection,
defaultValue: VerticalDirection.down));
properties.add(new EnumProperty<TextBaseline?>("textBaseline", this.textBaseline, defaultValue: null));
}
}

38
Runtime/widgets/editable_text.cs


public delegate void SelectionChangedCallback(TextSelection selection, SelectionChangedCause cause);
public class TextEditingController : ValueNotifier<TextEditingValue> {
public TextEditingController(string text) : base(text == null
public TextEditingController(string text = null) : base(text == null
? TextEditingValue.empty
: new TextEditingValue(text)) {
}

public TextEditingController fromValue(TextEditingValue value) {
public static TextEditingController fromValue(TextEditingValue value) {
return new TextEditingController(value);
}

ValueChanged<string> onSubmitted = null, SelectionChangedCallback onSelectionChanged = null,
List<TextInputFormatter> inputFormatters = null, bool rendererIgnoresPointer = false,
EdgeInsets scrollPadding = null, bool unityTouchKeyboard = false,
Key key = null) : base(key) {
Key key = null, float? cursorWidth = 2.0f, Radius cursorRadius = null, Brightness? keyboardAppearance = Brightness.light,
bool enableInteractiveSelection = true
) : base(key) {
D.assert(controller != null);
D.assert(focusNode != null);
D.assert(style != null);

else {
this.inputFormatters = inputFormatters;
}
this.cursorWidth = cursorWidth;
this.cursorRadius = cursorRadius;
this.keyboardAppearance = keyboardAppearance;
this.enableInteractiveSelection = enableInteractiveSelection;
public readonly float? cursorWidth;
public readonly Radius cursorRadius;
public readonly Brightness? keyboardAppearance;
public readonly bool enableInteractiveSelection;
public override State createState() {
return new EditableTextState();
}

? TextInputAction.newline
: TextInputAction.done),
textCapitalization: this.widget.textCapitalization,
keyboardAppearance: this.widget.keyboardAppearance??Brightness.light,
unityTouchKeyboard: this.widget.unityTouchKeyboard
));

onSelectionChanged: this._handleSelectionChanged,
onCaretChanged: this._handleCaretChanged,
rendererIgnoresPointer: this.widget.rendererIgnoresPointer,
cursorWidth: this.widget.cursorWidth,
cursorRadius: this.widget.cursorRadius,
enableInteractiveSelection: this.widget.enableInteractiveSelection,
textSelectionDelegate: this
)
)

public readonly SelectionChangedHandler onSelectionChanged;
public readonly CaretChangedHandler onCaretChanged;
public readonly bool rendererIgnoresPointer;
public readonly float? cursorWidth;
public readonly Radius cursorRadius;
public readonly bool enableInteractiveSelection;
public readonly TextSelectionDelegate textSelectionDelegate;

TextDirection? textDirection = null, bool obscureText = false, TextAlign textAlign = TextAlign.left,
bool autocorrect = false, ViewportOffset offset = null, SelectionChangedHandler onSelectionChanged = null,
CaretChangedHandler onCaretChanged = null, bool rendererIgnoresPointer = false,
Key key = null, TextSelectionDelegate textSelectionDelegate = null) : base(key) {
Key key = null, TextSelectionDelegate textSelectionDelegate = null, float? cursorWidth = null,
Radius cursorRadius = null, bool enableInteractiveSelection = true) : base(key) {
this.textSpan = textSpan;
this.value = value;
this.cursorColor = cursorColor;

this.onCaretChanged = onCaretChanged;
this.rendererIgnoresPointer = rendererIgnoresPointer;
this.textSelectionDelegate = textSelectionDelegate;
this.cursorWidth = cursorWidth;
this.cursorRadius = cursorRadius;
this.enableInteractiveSelection = enableInteractiveSelection;
}
public override RenderObject createRenderObject(BuildContext context) {

onSelectionChanged: this.onSelectionChanged,
onCaretChanged: this.onCaretChanged,
ignorePointer: this.rendererIgnoresPointer,
cursorWidth: this.cursorWidth??1.0f,
cursorRadius: this.cursorRadius,
enableInteractiveSelection: this.enableInteractiveSelection,
textSelectionDelegate: this.textSelectionDelegate
);
}

edit.ignorePointer = this.rendererIgnoresPointer;
edit.obscureText = this.obscureText;
edit.textSelectionDelegate = this.textSelectionDelegate;
edit.cursorWidth = this.cursorWidth ?? 1.0f;
edit.cursorRadius = this.cursorRadius;
edit.enableInteractiveSelection = this.enableInteractiveSelection;
}
}
}

2
Runtime/widgets/framework.cs


}
throw new UIWidgetsError(
this._state.GetType() + ".dispose failed to call super.dispose.\n" +
this._state.GetType() + ".dispose failed to call base.dispose.\n" +
"dispose() implementations must always call their superclass dispose() method, to ensure " +
"that all the resources used by the widget are fully released.");
});

4
Runtime/widgets/navigator.cs


key: this._overlayKey,
initialEntries: this._initialOverlayEntries
)
) {
alwaysUpdate = true,
}
)
)
);
}

2
Runtime/widgets/text.cs


textAlign: this.textAlign ?? defaultTextStyle.textAlign ?? TextAlign.left,
softWrap: this.softWrap ?? defaultTextStyle.softWrap,
overflow: this.overflow ?? defaultTextStyle.overflow,
textScaleFactor: this.textScaleFactor ?? 1.0f, // MediaQuery.textScaleFactorOf(context), todo
textScaleFactor: this.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
maxLines: this.maxLines ?? defaultTextStyle.maxLines,
text: new TextSpan(
style: effectiveTextStyle,

4
Runtime/widgets/ticker_provider.cs


this + " was disposed with an active Ticker.\n" +
this.GetType() + " created a Ticker via its SingleTickerProviderStateMixin, but at the time " +
"dispose() was called on the mixin, that Ticker was still active. The Ticker must " +
"be disposed before calling super.dispose(). Tickers used by AnimationControllers " +
"be disposed before calling base.dispose(). Tickers used by AnimationControllers " +
"should be disposed by calling dispose() on the AnimationController itself. " +
"Otherwise, the ticker will leak.\n" +
"The offending ticker was: " + this._ticker.toString(debugIncludeStack: true)

this.GetType() +
" created a Ticker via its TickerProviderStateMixin, but at the time " +
"dispose() was called on the mixin, that Ticker was still active. All Tickers must " +
"be disposed before calling super.dispose(). Tickers used by AnimationControllers " +
"be disposed before calling base.dispose(). Tickers used by AnimationControllers " +
"should be disposed by calling dispose() on the AnimationController itself. " +
"Otherwise, the ticker will leak.\n" +
"The offending ticker was: " + ticker.toString(debugIncludeStack: true)

20
Samples/ReduxSample/CounterApp/CounterAppSample.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.Redux;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using TextStyle = Unity.UIWidgets.painting.TextStyle;

public class CounterApp : StatelessWidget {
public override Widget build(BuildContext context) {
var store = new Store<CouterState>(reduce, new CouterState(),
ReduxLogging.Create<CouterState>());
ReduxLogging.create<CouterState>());
return new StoreProvider<CouterState>(store, this.createWidget());
}

child: new Column(
children: new List<Widget>() {
new StoreConnector<CouterState, string>(
converter: (state, dispatch) => $"Count:{state.count}",
builder: (context, countText) => new Text(countText, style: new TextStyle(
converter: (state) => $"Count:{state.count}",
builder: (context, countText, dispatcher) => new Text(countText, style: new TextStyle(
))
)),
pure: true
new StoreConnector<CouterState, Action>(
converter: (state, dispatch) => () => { dispatch(new CounterIncAction() {amount = 1}); },
builder: (context, onPress) => new CustomButton(
new StoreConnector<CouterState, object>(
converter: (state) => null,
builder: (context, _, dispatcher) => new CustomButton(
)), onPressed: () => { onPress(); })
)), onPressed: () => { dispatcher.dispatch(new CounterIncAction() {amount = 1}); }),
pure: true
),
}
)

4
Samples/ReduxSample/ObjectFinder/FinderGameObject.cs


// Update is called once per frame
void Update() {
var selectedId = StoreProvider.store.state.selected;
var selectedId = StoreProvider.store.getState().selected;
if (selectedId == this.GetInstanceID()) {
this.GetComponent<MeshRenderer>().material.color = new Color(1.0f, 0, 0, 1.0f);
}

}
void OnMouseDown() {
StoreProvider.store.Dispatch(new SelectObjectAction() {id = this.GetInstanceID()});
StoreProvider.store.dispatcher.dispatch(new SelectObjectAction() {id = this.GetInstanceID()});
}
}
}

73
Samples/ReduxSample/ObjectFinder/ObjectFinderApp.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.Redux;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
namespace Unity.UIWidgets.Sample.Redux.ObjectFinder {

Widget createRootWidget() {
return new StoreConnector<FinderAppState, ObjectFinderAppWidgetModel>(
(context, viewModel) => new ObjectFinderAppWidget(
viewModel, this.gameObject.name
pure: true,
builder: (context, viewModel, dispatcher) => new ObjectFinderAppWidget(
model: viewModel,
doSearch: (text) => dispatcher.dispatch(SearchAction.create(text)),
onSelect: (id) => dispatcher.dispatch(new SelectObjectAction() {id = id}),
title: this.gameObject.name
(state, dispacher) => new ObjectFinderAppWidgetModel() {
converter: (state) => new ObjectFinderAppWidgetModel() {
doSearch = (text) => dispacher(new SearchAction() {keyword = text}),
onSelect = (id) => dispacher(new SelectObjectAction() {id = id})
}
);
}

public delegate void onFindCallback(string keyword);
public class ObjectFinderAppWidgetModel {
public class ObjectFinderAppWidgetModel : IEquatable<ObjectFinderAppWidgetModel> {
public Action<string> doSearch;
public Action<int> onSelect;
public bool Equals(ObjectFinderAppWidgetModel other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return this.selected == other.selected && this.objects.equalsList(other.objects);
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return this.Equals((ObjectFinderAppWidgetModel) obj);
}
public override int GetHashCode() {
unchecked {
return (this.selected * 397) ^ this.objects.hashList();
}
}
public static bool operator ==(ObjectFinderAppWidgetModel left, ObjectFinderAppWidgetModel right) {
return Equals(left, right);
}
public static bool operator !=(ObjectFinderAppWidgetModel left, ObjectFinderAppWidgetModel right) {
return !Equals(left, right);
}
}
public class ObjectFinderAppWidget : StatefulWidget {

public readonly string title;
public ObjectFinderAppWidget(ObjectFinderAppWidgetModel model, string title, Key key = null) : base(key) {
public ObjectFinderAppWidget(
ObjectFinderAppWidgetModel model = null,
Action<string> doSearch = null,
Action<int> onSelect = null,
string title = null,
Key key = null) : base(key) {
this.doSearch = model.doSearch;
this.onSelect = model.onSelect;
this.doSearch = doSearch;
this.onSelect = onSelect;
this.title = title;
}

this._controller = new TextEditingController("");
this._focusNode = new FocusNode();
if (this.widget.doSearch != null) {
//scheduler.SchedulerBinding.instance.scheduleFrameCallback
Window.instance.scheduleMicrotask(() => this.widget.doSearch(""));
}

base.dispose();
}
public override Widget build(BuildContext context) {
public override Widget build(BuildContext context) {
Debug.Log("build ObjectFinderAppWidget");
return new Container(
padding: EdgeInsets.all(10),
decoration: new BoxDecoration(color: new Color(0x4FFFFFFF),

95
Samples/ReduxSample/ObjectFinder/Reducer.cs


using System;
using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.Redux;
public class GameObjectInfo {
public class GameObjectInfo : IEquatable<GameObjectInfo> {
public bool Equals(GameObjectInfo other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return this.id == other.id && string.Equals(this.name, other.name);
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return this.Equals((GameObjectInfo) obj);
}
public override int GetHashCode() {
unchecked {
return (this.id * 397) ^ (this.name != null ? this.name.GetHashCode() : 0);
}
}
public static bool operator ==(GameObjectInfo left, GameObjectInfo right) {
return Equals(left, right);
}
public static bool operator !=(GameObjectInfo left, GameObjectInfo right) {
return !Equals(left, right);
}
public class FinderAppState {
public class FinderAppState : IEquatable<FinderAppState> {
public int selected;
public List<GameObjectInfo> objects;

}
public bool Equals(FinderAppState other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return this.selected == other.selected && Equals(this.objects, other.objects);
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return this.Equals((FinderAppState) obj);
}
public override int GetHashCode() {
unchecked {
return (this.selected * 397) ^ (this.objects != null ? this.objects.GetHashCode() : 0);
}
}
public static bool operator ==(FinderAppState left, FinderAppState right) {
return Equals(left, right);
}
public static bool operator !=(FinderAppState left, FinderAppState right) {
return !Equals(left, right);
}
public class SearchAction {
public string keyword;
public static class SearchAction {
public static ThunkAction<FinderAppState> create(string keyword) {
return new ThunkAction<FinderAppState>(
displayName: "SearchAction",
action: (dispatcher, getState) => {
var objects = UnityEngine.Object.FindObjectsOfType(typeof(FinderGameObject)).Where(
obj => keyword == "" || obj.name.ToUpper().Contains(keyword.ToUpper())).Select(
obj => new GameObjectInfo {id = obj.GetInstanceID(), name = obj.name}).ToList();
dispatcher.dispatch(new SearchResultAction {keyword = keyword, results = objects});
return null;
});
}
}
[Serializable]

6
Samples/ReduxSample/ObjectFinder/StoreProvider.cs


using Unity.UIWidgets.Redux;
namespace Unity.UIWidgets.Sample.Redux.ObjectFinder {
public static class StoreProvider {
static Store<FinderAppState> _store;

}
var middlewares = new Middleware<FinderAppState>[] {
ReduxLogging.Create<FinderAppState>(),
GameFinderMiddleware.Create(),
ReduxLogging.create<FinderAppState>(),
ReduxThunk.create<FinderAppState>(),
};
_store = new Store<FinderAppState>(ObjectFinderReducer.Reduce,
new FinderAppState(),

24
Samples/UIWidgetSample/MaterialSample.cs


home: this.testCases[this.testCaseId]);
}
protected override void Awake() {
base.Awake();
protected override void OnEnable() {
base.OnEnable();
class BottomAppBarWidget : StatelessWidget {
public class BottomAppBarWidget : StatelessWidget {
public BottomAppBarWidget(Key key = null) : base(key) {
}

}
class TableWidget : StatelessWidget {
public class TableWidget : StatelessWidget {
public TableWidget(Key key = null) : base(key) {
}

}
class MaterialTabBarWidget : StatefulWidget {
public class MaterialTabBarWidget : StatefulWidget {
public MaterialTabBarWidget(Key key = null) : base(key) {
}

}
class MaterialTabBarWidgetState : SingleTickerProviderStateMixin<MaterialTabBarWidget> {
public class MaterialTabBarWidgetState : SingleTickerProviderStateMixin<MaterialTabBarWidget> {
TabController _tabController;
public override void initState() {

}
}
class MaterialAppBarWidget : StatefulWidget {
public class MaterialAppBarWidget : StatefulWidget {
public MaterialAppBarWidget(Key key = null) : base(key) {
}

}
class MaterialAppBarWidgetState : State<MaterialAppBarWidget> {
public class MaterialAppBarWidgetState : State<MaterialAppBarWidget> {
Choice _selectedChoice = Choice.choices[0];
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>.key();

}
}
class MaterialInkWellWidget : StatefulWidget {
public class MaterialInkWellWidget : StatefulWidget {
public MaterialInkWellWidget(Key key = null) : base(key) {
}

}
class MaterialInkWidgetState : State<MaterialInkWellWidget> {
public class MaterialInkWidgetState : State<MaterialInkWellWidget> {
public override Widget build(BuildContext context) {
return new Material(
//color: Colors.blue,

}
}
class MaterialButtonWidget : StatefulWidget {
public class MaterialButtonWidget : StatefulWidget {
public MaterialButtonWidget(Key key = null) : base(key) {
}

}
class MaterialButtonWidgetState : State<MaterialButtonWidget> {
public class MaterialButtonWidgetState : State<MaterialButtonWidget> {
public override Widget build(BuildContext context) {
return new Stack(
children: new List<Widget> {

150
Samples/UIWidgetSample/UIWidgetSample.unity


m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
m_IsActive: 1
--- !u!114 &304189371
MonoBehaviour:
m_ObjectHideFlags: 0

m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
m_IsActive: 1
--- !u!224 &552752111
RectTransform:
m_ObjectHideFlags: 0

m_Father: {fileID: 304189374}
m_RootOrder: 5
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_SizeDelta: {x: 100, y: 100}
m_SizeDelta: {x: -20, y: -20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &552752112
MonoBehaviour:

m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 552752110}
m_CullTransparentMesh: 0
m_CullTransparentMesh: 1
--- !u!1 &554372217
GameObject:
m_ObjectHideFlags: 0

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1148735784}
m_CullTransparentMesh: 0
--- !u!1 &1155767695
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1155767701}
- component: {fileID: 1155767700}
- component: {fileID: 1155767699}
- component: {fileID: 1155767698}
- component: {fileID: 1155767697}
- component: {fileID: 1155767696}
m_Layer: 5
m_Name: Canvas2
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1155767696
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1155767695}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d7c3be43dd8b94a349f26e3e7173c3f6, 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
devicePixelRatioOverride: 0
--- !u!222 &1155767697
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1155767695}
m_CullTransparentMesh: 0
--- !u!114 &1155767698
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1155767695}
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 &1155767699
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1155767695}
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 &1155767700
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1155767695}
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 &1155767701
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1155767695}
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: []
m_Father: {fileID: 0}
m_RootOrder: 4
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 &1199742531
GameObject:
m_ObjectHideFlags: 0

m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!224 &1387978527
RectTransform:
m_ObjectHideFlags: 0

5
Samples/UIWidgetSample/txt/FontWeightStyle.cs


namespace UIWidgetsSample {
public class FontWeightStyle : UIWidgetsSamplePanel {
protected override void Awake() {
base.Awake();
protected override void OnEnable() {
// To run this sample, you need to download Roboto fonts and place them under Resources/Fonts folder
// Roboto fonts could be downloaded from google website
// https://fonts.google.com/specimen/Roboto?selection.family=Roboto

FontWeight.w100);
FontManager.instance.addFont(Resources.Load<Font>(path: "Fonts/Roboto-ThinItalic"), "Roboto",
FontWeight.w100, FontStyle.italic);
base.OnEnable();
}
protected override Widget createWidget() {

4
Samples/UIWidgetsGallery/Editor/GalleryMainEditor.cs


return new GalleryApp();
}
protected override void Awake() {
base.Awake();
protected override void OnEnable() {
base.OnEnable();
}
}
}

5
Samples/UIWidgetsGallery/GalleryMain.cs


return new GalleryApp();
}
protected override void Awake() {
base.Awake();
protected override void OnEnable() {
base.OnEnable();
}
}
}

3
Samples/UIWidgetsGallery/gallery/app.cs


theme: GalleryTheme.kLightGalleryTheme,
textScaleFactor: GalleryTextScaleValue.kAllGalleryTextScaleValues[0],
timeDilation: SchedulerBinding.instance.timeDilation,
platform: Application.platform
platform: Application.platform,
showPerformanceOverlay: this.widget.enablePerformanceOverlay
);
}

14
Samples/UIWidgetsTheatre/UIWidgetsTheatre.cs


using System.Collections.Generic;
using UIWidgetsGallery.gallery;
using UIWidgetsSample;
using Unity.UIWidgets.material;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;

using UnityEngine;
namespace UIWidgetsSample {
namespace UIWidgetsTheatre {
class TheatreEntry {
public string entryName;

class UIWidgetsTheatre : UIWidgetsSamplePanel {
static readonly List<TheatreEntry> entries = new List<TheatreEntry> {
new TheatreEntry{entryName = "UIWidget Gallery", entryWidget = new GalleryApp()},
new TheatreEntry{entryName = "Material Tab Bar" , entryWidget = new MaterialTabBarWidget()}
new TheatreEntry{entryName = "Material Tab Bar" , entryWidget = new MaterialTabBarWidget()},
new TheatreEntry{entryName = "Asset Store", entryWidget = new AsScreenSample.AsScreenWidget()},
new TheatreEntry{entryName = "ToDo App", entryWidget = new ToDoAppSample.ToDoListApp()}
};
public static string[] entryKeys {

home: entries[this.testCaseId].entryWidget);
}
protected override void Awake() {
base.Awake();
protected override void OnEnable() {
FontManager.instance.addFont(Resources.Load<Font>("GalleryIcons"), "GalleryIcons");
base.OnEnable();
}
}

116
Samples/UIWidgetsTheatre/UIWidgetsTheatre.unity


- component: {fileID: 314914772}
- component: {fileID: 314914771}
- component: {fileID: 314914770}
- component: {fileID: 314914775}
- component: {fileID: 314914774}
m_Layer: 5
m_Name: Canvas
m_TagString: Untagged

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: []
m_Children:
- {fileID: 1344738457}
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!114 &314914774
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 314914769}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3ace0d3c7f55946559f1497f0fbf6025, 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
devicePixelRatioOverride: 0
testCaseId: 0
--- !u!222 &314914775
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 314914769}
m_CullTransparentMesh: 0
--- !u!1 &1040325770
GameObject:
m_ObjectHideFlags: 0

m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &1344738456
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1344738457}
- component: {fileID: 1344738459}
- component: {fileID: 1344738458}
m_Layer: 5
m_Name: TheatrePanel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1344738457
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1344738456}
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: 314914773}
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 &1344738458
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1344738456}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3ace0d3c7f55946559f1497f0fbf6025, 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
devicePixelRatioOverride: 0
testCaseId: 2
--- !u!222 &1344738459
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1344738456}
m_CullTransparentMesh: 0
--- !u!1 &1814350050
GameObject:
m_ObjectHideFlags: 0

11
Tests/Editor/CanvasAndLayers.cs


using Gradient = Unity.UIWidgets.ui.Gradient;
using Material = UnityEngine.Material;
using Rect = UnityEngine.Rect;
using TextStyle = Unity.UIWidgets.ui.TextStyle;
namespace UIWidgets.Tests {
public class CanvasAndLayers : EditorWindow {

paint);
canvas.scale(3);
TextBlob textBlob = new TextBlob("This is a text blob", 0, 19, new Vector2d[] {
TextBlobBuilder builder = new TextBlobBuilder();
string text = "This is a text blob";
builder.allocRunPos(new TextStyle(), text, 0, text.Length);
builder.setBounds(Unity.UIWidgets.ui.Rect.fromLTWH(0, 0, 200, 50));
builder.positions = new Vector2d[] {
new Vector2d(10, 0),
new Vector2d(20, 0),
new Vector2d(30, 0),

new Vector2d(170, 0),
new Vector2d(180, 0),
new Vector2d(190, 0),
}, Unity.UIWidgets.ui.Rect.fromLTWH(0, 0, 200, 50), new TextStyle());
};
canvas.drawTextBlob(textBlob, new Offset(100, 100), paint);
canvas.drawTextBlob(builder.make(), new Offset(100, 100), paint);
canvas.drawLine(
new Offset(10, 30),

4
Tests/Editor/Widgets.cs


this.windowAdapter.Update();
}
void Awake() {
void OnEnable() {
}
void OnEnable() {
this.windowAdapter = new EditorWindowAdapter(this);
this.windowAdapter.OnEnable();
}

2
Runtime/flow/instrumentation.cs.meta


fileFormatVersion: 2
guid: 819a2117a730b431bb069817e3ed8cd7
guid: 89eef64f138164ea0a407cf8e65f8186
MonoImporter:
externalObjects: {}
serializedVersion: 2

2
Runtime/redux/redux_thunk.cs.meta


fileFormatVersion: 2
guid: d80e14622d3da4c6eaa3f72c29fa1fd3
guid: f837de040a3fa4a3fb3e6c344153e1eb
MonoImporter:
externalObjects: {}
serializedVersion: 2

4
.DS_Store


Bud1  d.batIl  @� @� @� @ build.batIlocblob;(������build.bat.metaIlocblob�(������build.shIlocblob(������ build.sh.metaIlocblob�(������ CHANGELOG.mdIlocblob�(������CHANGELOG.md.metaIlocblob;�������CONTRIBUTING.mdIlocblob��������CONTRIBUTING.md.metaIlocblob�������Documentation~Ilocblob��������EditorIlocblob�������� Editor.metaIlocblob;������
LICENSE.mdIlocblob�������LICENSE.md.metaIlocblob������ package.jsonIlocblob�������package.json.metaIlocblob������� QAReport.mdIlocblob;x������QAReport.md.metaIlocblob�x������ README-ZH.mdIlocblob7������� README.mdIlocblobx������README.md.metaIlocblob�x������RuntimeIlocblob�x������ Runtime.metaIlocblob;�������SamplesIlocblob�������� Samples.metaIlocblob�������scriptsIlocblob�������� scripts.metaIlocblob��������TestsIlocblob;X������
Tests.metaIlocblob�X������Third Party Notices.mdIlocblobX������Third Party Notices.md.metaIlocblob�X������!UIWidgetCleanupPlugin.DotSettingsIlocblob�X������&UIWidgetCleanupPlugin.DotSettings.metaIlocblob;������� E DSDB `� @� @� @lesIlocblob�������� Samples.metaIlocblob�������scriptsIlocblob�������� scripts.metaIlocblob��������TestsIlocblob;X������
Tests.metaIlocblob�X������Third Party Notices.mdIlocblobX������Third Party Notices.md.metaIlocblob�X������!UIWidgetCleanupPlugin.DotSettingsIlocblob�X������&UIWidgetCleanupPlugin.DotSettings.metaIlocblob;�������

223
README-ZH.md


# UIWidgets
## 介绍
UIWidgets是Unity编辑器的一个插件包,可帮助开发人员通过Unity引擎来创建、调试和部署高效的跨平台应用。
UIWidgets主要来自[Flutter](https://github.com/flutter/flutter)。但UIWidgets通过使用强大的Unity引擎为开发人员提供了许多新功能,显著地改进他们开发的应用性能和工作流程。
#### 效率
通过使用最新的Unity渲染SDK,UIWidgets应用可以非常快速地运行并且大多数时间保持大于60fps的速度。
#### 跨平台
与任何其他Unity项目一样,UIWidgets应用可以直接部署在各种平台上,包括PC,移动设备和网页等。
#### 多媒体支持
除了基本的2D UI之外,开发人员还能够将3D模型,音频,粒子系统添加到UIWidgets应用中。
#### 开发者友好
开发者可以使用许多高级工具,如CPU/GPU Profiling和FPS Profiling,直接在Unity Editor中调试UIWidgets应用。
### Example
<div style="text-align: center"><table><tr>
<td style="text-align: center">
<img src="https://connect-prd-cdn.unity.com/20190323/p/images/2a27606f-a2cc-4c9f-9e34-bb39ae64d06c_uiwidgets1.gif" width="200"/>
</td>
<td style="text-align: center">
<img src="https://connect-prd-cdn.unity.com/20190323/p/images/097a7c53-19b3-4e0a-ad27-8ec02506905d_uiwidgets2.gif" width="200" />
</td>
<td style="text-align: center">
<img src="https://connect-prd-cdn.unity.com/20190323/p/images/1f03c1d0-758c-4dde-b3a9-2f5f7216b7d9_uiwidgets3.gif" width="200"/>
</td>
<td style="text-align: center">
<img src="https://connect-prd-cdn.unity.com/20190323/p/images/a8884fbd-9e7c-4bd7-af46-0947e01d01fd_uiwidgets4.gif" width="200"/>
</td>
</tr></table></div>
## 使用要求
#### Unity
安装 Unity 2018.3 或更高版本。 你可以从[https://unity3d.com/get-unity/download](https://unity3d.com/get-unity/download)下载最新的Unity。
#### UIWidgets包
访问我们的Github存储库 [https://github.com/UnityTech/UIWidgets](https://github.com/UnityTech/UIWidgets)下载最新的UIWidgets包。
将下载的包文件夹移动到Unity项目的Package文件夹中。
通常,你可以在控制台(或终端)应用程序中输入下面的代码来完成这个操作:
```none
cd <YourProjectPath>/Packages
git clone https://github.com/UnityTech/UIWidgets.git com.unity.uiwidgets
```
## 入门指南
#### 一、 概观
在本教程中,我们将创建一个非常简单的UIWidgets应用。 该应用只包含文本标签和按钮。 文本标签将计算按钮上的点击次数。
首先,请打开或创建Unity项目并使用Unity编辑器打开它。
然后打开Project Settings,转到Player部分并**将“UIWidgets_DEBUG”添加到Scripting Define Symbols字段中。**
这样就启动了UIWidgets的调试模式。 在之后发布版本的时候清空这个字段。
#### 二、 场景构建
UIWidgets应用通常构建在Unity UI Canvas上。 请按照以下步骤在Unity中创建一个
UI Canvas。
1. 选择 File > New Scene来创建一个新场景。
2. 选择 GameObject > UI > Canvas 在场景中创建UI Canvas。
3. 右键单击Canvas并选择UI > Panel,将面板(即面板1)添加到UI Canvas中。 然后删除面板中的 **Image** 组件。
#### 三、创建小部件
UIWidgets应用是用**C#脚本**来编写的。 请按照以下步骤创建应用程序并在Unity编辑器中播放。
1. 创建一个新C#脚本,命名为“UIWidgetsExample.cs”,并将以下代码粘贴到其中。
```none
using System.Collections.Generic;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using FontStyle = Unity.UIWidgets.ui.FontStyle;
namespace UIWidgetsSample {
public class UIWidgetsExample : UIWidgetsPanel {
protected override void OnEnable() {
// Application.targetFrameRate = 60; // or higher if you want a smoother scrolling experience.
// if you want to use your own font or font icons.
// FontManager.instance.addFont(Resources.Load<Font>(path: "path to your font"), "font family name");
// load custom font with weight & style. The font weight & style corresponds to fontWeight, fontStyle of
// a TextStyle object
// FontManager.instance.addFont(Resources.Load<Font>(path: "path to your font"), "Roboto", FontWeight.w500,
// FontStyle.italic);
// add material icons, familyName must be "Material Icons"
// FontManager.instance.addFont(Resources.Load<Font>(path: "path to material icons"), "Material Icons");
base.OnEnable();
}
protected override Widget createWidget() {
return new WidgetsApp(
home: new ExampleApp(),
pageRouteBuilder: (RouteSettings settings, WidgetBuilder builder) =>
new PageRouteBuilder(
settings: settings,
pageBuilder: (BuildContext context, Animation<float> animation,
Animation<float> secondaryAnimation) => builder(context)
)
);
}
class ExampleApp : StatefulWidget {
public ExampleApp(Key key = null) : base(key) {
}
public override State createState() {
return new ExampleState();
}
}
class ExampleState : State<ExampleApp> {
int counter = 0;
public override Widget build(BuildContext context) {
return new Column(
children: new List<Widget> {
new Text("Counter: " + this.counter),
new GestureDetector(
onTap: () => {
this.setState(() => {
this.counter++;
});
},
child: new Container(
padding: EdgeInsets.symmetric(20, 20),
color: Colors.blue,
child: new Text("Click Me")
)
)
}
);
}
}
}
}
```
2. 保存此脚本,并将其附加到Panel 1中作为其组件。
3. 在Unity编辑器中,点击Play按钮来启动应用。
#### 四、构建应用程序
最后,你可以按以下步骤将UIWidgets应用构建成适用于任何特定平台的应用程序包。
1. 选择**File** > **Build Settings...**打开Build Settings面板。
2. 选择目标平台,点击Build。 之后Unity编辑器将自动组装所有相关资源并生成最终的应用程序包。
#### 如何加载图像?
1. 将你的图像文件,如image1.png,放在Resources文件夹中。
2. 你可以在同一文件夹中添加image1@2.png和image1@3.png以支持高清屏幕显示。
3. 使用Image.asset(“image1”)加载图像。 注意:因为是在Unity中,所以不需要添加.png后缀。
UIWidgets也支持Gif!
1. 假设你有一个loading1.gif文件,将其重命名为loading1.gif.bytes并复制到Resources文件夹。
2. 你可以在同一文件夹中添加loading1@2.gif.bytes和loading1@3.gif.bytes以支持高清屏幕显示。
3. 使用Image.asset(“loading1.gif”)加载gif图像。
## 调试UIWidgets应用程序
#### 定义UIWidgets_DEBUG
我们建议在Unity编辑器中定义 UIWidgets_DEBUG 脚本符号,这将打开UIWidgets中的调试断言(debug assertion),有助于更早发现潜在的Bug。
因此选择 **Player Settings** > **Other Settings** > **Configuration** > **Scripting Define Symbols** ,并添加 UIWidgets_DEBUG。
该符号仅供调试使用,请在发布版本中删除它。
#### UIWidgets Inspector
UIWidgets Inspector工具用于可视化和浏览窗口小部件树。 你可以在Unity编辑器的**Window** > **Analysis** > **UIWidget Inspector** 中的找到它。
注意
- 需要定义 UIWidgets_DEBUG 使inspector正常工作。
- Inspector目前仅适用于编辑器的播放模式,目前不支持独立版本的应用程序。
## 学习
#### 示例
你可以在**Samples**文件夹的UIWidgets包中找到一些精心挑选的UIWidgets应用示例,并通过这些示例来开始你的学习。请随意尝试并进行修改以查看结果。
你也可以在支持**UIWidgets**的编辑器中,点击主菜单上的UIWidgets,并在下拉窗口中选择一个示例。
#### Wiki
目前开发团队仍在改进UIWidgets Wiki。 由于UIWidgets主要来源于Flutter,你也可以参考Flutter Wiki中与UIWidgets API对应部分的详细描述。同时,你可以加入我们的讨论组(https://connect.unity.com/g/uiwidgets)。
#### 常问问题解答
| 问题 | 回答 |
| :-----------------------------------------------| ---------------------: |
| 我可以使用UIWidgets创建独立应用吗? | 可以 |
| 我可以使用UIWidgets构建游戏UI吗? | 可以 |
| 我可以使用UIWidgets开发Unity编辑器插件吗? | 可以 |
| UIWidgets是UGUI / NGUI的扩展吗? | 不是 |
| UIWidgets只是Flutter的副本吗? | 不是 |
| 我可以通过简单的拖放操作来创建带有UIWidgets的UI吗? | 不可以 |
| 我是否需要付费使用UIWidgets? | 不需要 |
| 有推荐的适用于UIWidgets的IDE吗? | Rider, VSCode(Open .sln) |
## 如何贡献
请查看[CONTRIBUTING.md](CONTRIBUTING.md)

7
README-ZH.md.meta


fileFormatVersion: 2
guid: 10bb16e0fd5d84445aa576a308664220
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

113
Runtime/flow/instrumentation.cs


using Unity.UIWidgets.material;
using Unity.UIWidgets.ui;
using UnityEditor;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Rect = Unity.UIWidgets.ui.Rect;
namespace Unity.UIWidgets.flow {
static class InstrumentationUtils {
public const int kMaxSamples = 120;
public static float now() {
#if UNITY_EDITOR
return (float) EditorApplication.timeSinceStartup;
#else
return Time.realtimeSinceStartup;
#endif
}
}
public class Stopwatch {
float _start;
float[] _laps;
int _currentSample;
bool _cacheDirty;
public Stopwatch() {
this._start = InstrumentationUtils.now();
this._currentSample = 0;
float delta = 0f;
this._laps = new float[InstrumentationUtils.kMaxSamples];
for (int i = 0; i < this._laps.Length; i++) {
this._laps[i] = delta;
}
this._cacheDirty = true;
}
public void start() {
this._start = InstrumentationUtils.now();
this._currentSample = (this._currentSample + 1) % InstrumentationUtils.kMaxSamples;
}
public void stop() {
this._laps[this._currentSample] = InstrumentationUtils.now() - this._start;
}
public void setLapTime(float delta) {
this._currentSample = (this._currentSample + 1) % InstrumentationUtils.kMaxSamples;
this._laps[this._currentSample] = delta;
}
public float lastLap() {
return this._laps[(this._currentSample - 1) % InstrumentationUtils.kMaxSamples];
}
public float maxDelta() {
float maxDelta = 0f;
for (int i = 0; i < this._laps.Length; i++) {
if (maxDelta < this._laps[i]) {
maxDelta = this._laps[i];
}
}
return maxDelta;
}
public void visualize(Canvas canvas, Rect rect) {
Paint paint = new Paint {color = Colors.blue};
Paint paint2 = new Paint {color = Colors.red};
Paint paint3 = new Paint {color = Colors.green};
Paint paint4 = new Paint {color = Colors.white70};
float[] costFrames = this._laps;
int curFrame = (this._currentSample - 1) % InstrumentationUtils.kMaxSamples;
float barWidth = Mathf.Max(1, rect.width / costFrames.Length);
float perHeight = rect.height / 32.0f;
canvas.drawRect(rect, paint4);
canvas.drawRect(Rect.fromLTWH(rect.left, rect.top + perHeight * 16.0f, rect.width, 1), paint3);
float cur_x = rect.left;
Path barPath = new Path();
for (var i = 0; i < costFrames.Length; i++) {
if (costFrames[i] != 0) {
float curHeight = Mathf.Min(perHeight * costFrames[i] * 1000, rect.height);
Rect barRect = Rect.fromLTWH(cur_x, rect.top + rect.height - curHeight, barWidth, curHeight);
barPath.addRect(barRect);
}
cur_x += barWidth;
}
canvas.drawPath(barPath, paint);
if (curFrame >= 0 && curFrame < costFrames.Length && costFrames[curFrame] != 0) {
float curHeight = Mathf.Min(perHeight * costFrames[curFrame] * 1000, rect.height);
Rect barRect = Rect.fromLTWH(rect.left + barWidth * curFrame, rect.top + rect.height - curHeight,
barWidth, curHeight);
canvas.drawRect(barRect, paint2);
var pb = new ParagraphBuilder(new ParagraphStyle { });
pb.addText("Current Frame Cost: " + costFrames[curFrame] * 1000 + "ms" + " ; Max(in last 120 frames): " + this.maxDelta() * 1000 + "ms");
var paragraph = pb.build();
paragraph.layout(new ParagraphConstraints(width: 800));
canvas.drawParagraph(paragraph, new Offset(rect.left, rect.top + rect.height - 12));
}
}
}
}

311
Runtime/material/checkbox.cs


using System;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Color = Unity.UIWidgets.ui.Color;
using Rect = Unity.UIWidgets.ui.Rect;
namespace Unity.UIWidgets.material {
class CheckboxUtils {
public const float _kEdgeSize = Checkbox.width;
public static readonly Radius _kEdgeRadius = Radius.circular(1.0f);
public const float _kStrokeWidth = 2.0f;
}
public class Checkbox : StatefulWidget {
public Checkbox(
Key key = null,
bool? value = false,
bool tristate = false,
ValueChanged<bool?> onChanged = null,
Color activeColor = null,
Color checkColor = null,
MaterialTapTargetSize? materialTapTargetSize = null
) : base(key: key) {
D.assert(tristate || value != null);
this.value = value;
this.onChanged = onChanged;
this.activeColor = activeColor;
this.checkColor = checkColor;
this.tristate = tristate;
this.materialTapTargetSize = materialTapTargetSize;
}
public readonly bool? value;
public readonly ValueChanged<bool?> onChanged;
public readonly Color activeColor;
public readonly Color checkColor;
public readonly bool tristate;
public readonly MaterialTapTargetSize? materialTapTargetSize;
public const float width = 18.0f;
public override State createState() {
return new _CheckboxState();
}
}
class _CheckboxState : TickerProviderStateMixin<Checkbox> {
public override Widget build(BuildContext context) {
D.assert(MaterialD.debugCheckHasMaterial(context));
ThemeData themeData = Theme.of(context);
Size size;
switch (this.widget.materialTapTargetSize ?? themeData.materialTapTargetSize) {
case MaterialTapTargetSize.padded:
size = new Size(2 * Constants.kRadialReactionRadius + 8.0f,
2 * Constants.kRadialReactionRadius + 8.0f);
break;
case MaterialTapTargetSize.shrinkWrap:
size = new Size(2 * Constants.kRadialReactionRadius, 2 * Constants.kRadialReactionRadius);
break;
default:
throw new Exception("Unknown target size: " + this.widget.materialTapTargetSize);
}
BoxConstraints additionalConstraints = BoxConstraints.tight(size);
return new _CheckboxRenderObjectWidget(
value: this.widget.value,
tristate: this.widget.tristate,
activeColor: this.widget.activeColor ?? themeData.toggleableActiveColor,
checkColor: this.widget.checkColor ?? new Color(0xFFFFFFFF),
inactiveColor: this.widget.onChanged != null
? themeData.unselectedWidgetColor
: themeData.disabledColor,
onChanged: this.widget.onChanged,
additionalConstraints: additionalConstraints,
vsync: this
);
}
}
class _CheckboxRenderObjectWidget : LeafRenderObjectWidget {
public _CheckboxRenderObjectWidget(
Key key = null,
bool? value = null,
bool tristate = false,
Color activeColor = null,
Color checkColor = null,
Color inactiveColor = null,
ValueChanged<bool?> onChanged = null,
TickerProvider vsync = null,
BoxConstraints additionalConstraints = null
) : base(key: key) {
D.assert(tristate != null);
D.assert(tristate || value != null);
D.assert(activeColor != null);
D.assert(inactiveColor != null);
D.assert(vsync != null);
this.value = value;
this.tristate = tristate;
this.activeColor = activeColor;
this.checkColor = checkColor;
this.inactiveColor = inactiveColor;
this.onChanged = onChanged;
this.vsync = vsync;
this.additionalConstraints = additionalConstraints;
}
public readonly bool? value;
public readonly bool tristate;
public readonly Color activeColor;
public readonly Color checkColor;
public readonly Color inactiveColor;
public readonly ValueChanged<bool?> onChanged;
public readonly TickerProvider vsync;
public readonly BoxConstraints additionalConstraints;
public override RenderObject createRenderObject(BuildContext context) {
return new _RenderCheckbox(
value: this.value,
tristate: this.tristate,
activeColor: this.activeColor,
checkColor: this.checkColor,
inactiveColor: this.inactiveColor,
onChanged: this.onChanged,
vsync: this.vsync,
additionalConstraints: this.additionalConstraints
);
}
public override void updateRenderObject(BuildContext context, RenderObject _renderObject) {
_RenderCheckbox renderObject = _renderObject as _RenderCheckbox;
renderObject.value = this.value;
renderObject.tristate = this.tristate;
renderObject.activeColor = this.activeColor;
renderObject.checkColor = this.checkColor;
renderObject.inactiveColor = this.inactiveColor;
renderObject.onChanged = this.onChanged;
renderObject.additionalConstraints = this.additionalConstraints;
renderObject.vsync = this.vsync;
}
}
class _RenderCheckbox : RenderToggleable {
public _RenderCheckbox(
bool? value = null,
bool tristate = false,
Color activeColor = null,
Color checkColor = null,
Color inactiveColor = null,
BoxConstraints additionalConstraints = null,
ValueChanged<bool?> onChanged = null,
TickerProvider vsync = null
) : base(
value: value,
tristate: tristate,
activeColor: activeColor,
inactiveColor: inactiveColor,
onChanged: onChanged,
additionalConstraints: additionalConstraints,
vsync: vsync
) {
this._oldValue = value;
this.checkColor = checkColor;
}
bool? _oldValue;
public Color checkColor;
public override bool? value {
set {
if (value == this.value) {
return;
}
this._oldValue = this.value;
base.value = value;
}
}
RRect _outerRectAt(Offset origin, float t) {
float inset = 1.0f - (t - 0.5f).abs() * 2.0f;
float size = CheckboxUtils._kEdgeSize - inset * CheckboxUtils._kStrokeWidth;
Rect rect = Rect.fromLTWH(origin.dx + inset, origin.dy + inset, size, size);
return RRect.fromRectAndRadius(rect, CheckboxUtils._kEdgeRadius);
}
Color _colorAt(float t) {
return this.onChanged == null
? this.inactiveColor
: (t >= 0.25f ? this.activeColor : Color.lerp(this.inactiveColor, this.activeColor, t * 4.0f));
}
void _initStrokePaint(Paint paint) {
paint.color = this.checkColor;
paint.style = PaintingStyle.stroke;
paint.strokeWidth = CheckboxUtils._kStrokeWidth;
}
void _drawBorder(Canvas canvas, RRect outer, float t, Paint paint) {
D.assert(t >= 0.0f && t <= 0.5f);
float size = outer.width;
RRect inner = outer.deflate(Mathf.Min(size / 2.0f, CheckboxUtils._kStrokeWidth + size * t));
canvas.drawDRRect(outer, inner, paint);
}
void _drawCheck(Canvas canvas, Offset origin, float t, Paint paint) {
D.assert(t >= 0.0f && t <= 1.0f);
Path path = new Path();
Offset start = new Offset(CheckboxUtils._kEdgeSize * 0.15f, CheckboxUtils._kEdgeSize * 0.45f);
Offset mid = new Offset(CheckboxUtils._kEdgeSize * 0.4f, CheckboxUtils._kEdgeSize * 0.7f);
Offset end = new Offset(CheckboxUtils._kEdgeSize * 0.85f, CheckboxUtils._kEdgeSize * 0.25f);
if (t < 0.5f) {
float strokeT = t * 2.0f;
Offset drawMid = Offset.lerp(start, mid, strokeT);
path.moveTo(origin.dx + start.dx, origin.dy + start.dy);
path.lineTo(origin.dx + drawMid.dx, origin.dy + drawMid.dy);
}
else {
float strokeT = (t - 0.5f) * 2.0f;
Offset drawEnd = Offset.lerp(mid, end, strokeT);
path.moveTo(origin.dx + start.dx, origin.dy + start.dy);
path.lineTo(origin.dx + mid.dx, origin.dy + mid.dy);
path.lineTo(origin.dx + drawEnd.dx, origin.dy + drawEnd.dy);
}
canvas.drawPath(path, paint);
}
void _drawDash(Canvas canvas, Offset origin, float t, Paint paint) {
D.assert(t >= 0.0f && t <= 1.0f);
Offset start = new Offset(CheckboxUtils._kEdgeSize * 0.2f, CheckboxUtils._kEdgeSize * 0.5f);
Offset mid = new Offset(CheckboxUtils._kEdgeSize * 0.5f, CheckboxUtils._kEdgeSize * 0.5f);
Offset end = new Offset(CheckboxUtils._kEdgeSize * 0.8f, CheckboxUtils._kEdgeSize * 0.5f);
Offset drawStart = Offset.lerp(start, mid, 1.0f - t);
Offset drawEnd = Offset.lerp(mid, end, t);
canvas.drawLine(origin + drawStart, origin + drawEnd, paint);
}
public override void paint(PaintingContext context, Offset offset) {
Canvas canvas = context.canvas;
this.paintRadialReaction(canvas, offset, this.size.center(Offset.zero));
Offset origin = offset + (this.size / 2.0f - Size.square(CheckboxUtils._kEdgeSize) / 2.0f);
AnimationStatus status = this.position.status;
float tNormalized = status == AnimationStatus.forward || status == AnimationStatus.completed
? this.position.value
: 1.0f - this.position.value;
if (this._oldValue == false || this.value == false) {
float t = this.value == false ? 1.0f - tNormalized : tNormalized;
RRect outer = this._outerRectAt(origin, t);
Paint paint = new Paint();
paint.color = this._colorAt(t);
if (t <= 0.5f) {
this._drawBorder(canvas, outer, t, paint);
}
else {
canvas.drawRRect(outer, paint);
this._initStrokePaint(paint);
float tShrink = (t - 0.5f) * 2.0f;
if (this._oldValue == null || this.value == null) {
this._drawDash(canvas, origin, tShrink, paint);
}
else {
this._drawCheck(canvas, origin, tShrink, paint);
}
}
}
else {
// Two cases: null to true, true to null
RRect outer = this._outerRectAt(origin, 1.0f);
Paint paint = new Paint();
paint.color = this._colorAt(1.0f);
canvas.drawRRect(outer, paint);
this._initStrokePaint(paint);
if (tNormalized <= 0.5f) {
float tShrink = 1.0f - tNormalized * 2.0f;
if (this._oldValue == true) {
this._drawCheck(canvas, origin, tShrink, paint);
}
else {
this._drawDash(canvas, origin, tShrink, paint);
}
}
else {
float tExpand = (tNormalized - 0.5f) * 2.0f;
if (this.value == true) {
this._drawCheck(canvas, origin, tExpand, paint);
}
else {
this._drawDash(canvas, origin, tExpand, paint);
}
}
}
}
}
}

3
Runtime/material/checkbox.cs.meta


fileFormatVersion: 2
guid: 3f506995b69c421cbdd95746b4ca2182
timeCreated: 1554213056

444
Runtime/material/text_field.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
namespace Unity.UIWidgets.material {
public class TextField : StatefulWidget {
public TextField(Key key = null, TextEditingController controller = null, FocusNode focusNode = null,
InputDecoration decoration = null, bool noDecoration = false, TextInputType keyboardType = null,
TextInputAction? textInputAction = null,
TextCapitalization textCapitalization = TextCapitalization.none, TextStyle style = null,
TextAlign textAlign = TextAlign.left, TextDirection textDirection = TextDirection.ltr,
bool autofocus = false, bool obscureText = false, bool autocorrect = false, int? maxLines = 1,
int? maxLength = null, bool maxLengthEnforced = true, ValueChanged<string> onChanged = null,
VoidCallback onEditingComplete = null,
ValueChanged<string> onSubmitted = null, List<TextInputFormatter> inputFormatters = null,
bool? enabled = null, float? cursorWidth = 2.0f, Radius cursorRadius = null, Color cursorColor = null,
Brightness? keyboardAppearance = null, EdgeInsets scrollPadding = null,
bool enableInteractiveSelection = true,
GestureTapCallback onTap = null
) : base(key: key) {
D.assert(maxLines == null || maxLines > 0);
D.assert(maxLength == null || maxLength > 0);
this.controller = controller;
this.focusNode = focusNode;
this.decoration = noDecoration ? null : (decoration ?? new InputDecoration());
this.textInputAction = textInputAction;
this.textCapitalization = textCapitalization;
this.style = style;
this.textAlign = textAlign;
this.textDirection = textDirection;
this.autofocus = autofocus;
this.obscureText = obscureText;
this.autocorrect = autocorrect;
this.maxLines = maxLines;
this.maxLength = maxLength;
this.maxLengthEnforced = maxLengthEnforced;
this.onChanged = onChanged;
this.onEditingComplete = onEditingComplete;
this.onSubmitted = onSubmitted;
this.inputFormatters = inputFormatters;
this.enabled = enabled;
this.cursorWidth = cursorWidth;
this.cursorColor = cursorColor;
this.cursorRadius = cursorRadius;
this.onSubmitted = onSubmitted;
this.keyboardAppearance = keyboardAppearance;
this.enableInteractiveSelection = enableInteractiveSelection;
this.onTap = onTap;
this.keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline);
this.scrollPadding = scrollPadding ?? EdgeInsets.all(20.0f);
}
public readonly TextEditingController controller;
public readonly FocusNode focusNode;
public readonly InputDecoration decoration;
public readonly TextInputType keyboardType;
public readonly TextInputAction? textInputAction;
public readonly TextCapitalization textCapitalization;
public readonly TextStyle style;
public readonly TextAlign textAlign;
public readonly TextDirection textDirection;
public readonly bool autofocus;
public readonly bool obscureText;
public readonly bool autocorrect;
public readonly int? maxLines;
public const long noMaxLength = 9007199254740992; // math.pow(2, 53);
public readonly int? maxLength;
public readonly bool maxLengthEnforced;
public readonly ValueChanged<string> onChanged;
public readonly VoidCallback onEditingComplete;
public readonly ValueChanged<String> onSubmitted;
public readonly List<TextInputFormatter> inputFormatters;
public readonly bool? enabled;
public readonly float? cursorWidth;
public readonly Radius cursorRadius;
public readonly Color cursorColor;
public readonly Brightness? keyboardAppearance;
public readonly EdgeInsets scrollPadding;
public readonly bool enableInteractiveSelection;
public readonly GestureTapCallback onTap;
public override State createState() {
return new _TextFieldState();
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(
new DiagnosticsProperty<TextEditingController>("controller", this.controller, defaultValue: null));
properties.add(new DiagnosticsProperty<FocusNode>("focusNode", this.focusNode, defaultValue: null));
properties.add(new DiagnosticsProperty<bool?>("enabled", this.enabled, defaultValue: null));
properties.add(new DiagnosticsProperty<InputDecoration>("decoration", this.decoration));
properties.add(new DiagnosticsProperty<TextInputType>("keyboardType", this.keyboardType,
defaultValue: TextInputType.text));
properties.add(new DiagnosticsProperty<TextStyle>("style", this.style, defaultValue: null));
properties.add(new DiagnosticsProperty<bool>("autofocus", this.autofocus, defaultValue: false));
properties.add(new DiagnosticsProperty<bool>("obscureText", this.obscureText, defaultValue: false));
properties.add(new DiagnosticsProperty<bool>("autocorrect", this.autocorrect, defaultValue: false));
properties.add(new IntProperty("maxLines", this.maxLines, defaultValue: 1));
properties.add(new IntProperty("maxLength", this.maxLength, defaultValue: null));
properties.add(new FlagProperty("maxLengthEnforced", value: this.maxLengthEnforced,
ifTrue: "max length enforced"));
properties.add(new DiagnosticsProperty<GestureTapCallback>("onTap", this.onTap, defaultValue: null));
}
}
class _TextFieldState : AutomaticKeepAliveClientMixin<TextField> {
readonly GlobalKey<EditableTextState> _editableTextKey = new LabeledGlobalKey<EditableTextState>();
HashSet<InteractiveInkFeature> _splashes;
InteractiveInkFeature _currentSplash;
TextEditingController _controller;
TextEditingController _effectiveController {
get { return this.widget.controller ?? this._controller; }
}
FocusNode _focusNode;
FocusNode _effectiveFocusNode {
get {
if (this.widget.focusNode != null) {
return this.widget.focusNode;
}
if (this._focusNode != null) {
return this._focusNode;
}
this._focusNode = new FocusNode();
return this._focusNode;
}
}
bool needsCounter {
get {
return this.widget.maxLength != null
&& this.widget.decoration != null
&& this.widget.decoration.counterText == null;
}
}
InputDecoration _getEffectiveDecoration() {
MaterialLocalizations localizations = MaterialLocalizations.of(this.context);
InputDecoration effectiveDecoration = (this.widget.decoration ?? new InputDecoration())
.applyDefaults(Theme.of(this.context).inputDecorationTheme)
.copyWith(
enabled: this.widget.enabled
);
if (!this.needsCounter) {
return effectiveDecoration;
}
int currentLength = this._effectiveController.value.text.Length;
string counterText = $"{currentLength}";
if (this.widget.maxLength != TextField.noMaxLength) {
counterText += $"/{this.widget.maxLength}";
}
// Handle length exceeds maxLength
if (this._effectiveController.value.text.Length > this.widget.maxLength) {
ThemeData themeData = Theme.of(this.context);
return effectiveDecoration.copyWith(
errorText: effectiveDecoration.errorText ?? "",
counterStyle: effectiveDecoration.errorStyle
?? themeData.textTheme.caption.copyWith(color: themeData.errorColor),
counterText: counterText
);
}
return effectiveDecoration.copyWith(
counterText: counterText
);
}
public override void initState() {
base.initState();
if (this.widget.controller == null) {
this._controller = new TextEditingController();
}
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
base.didUpdateWidget(oldWidget);
if (this.widget.controller == null && ((TextField) oldWidget).controller != null) {
this._controller = TextEditingController.fromValue(((TextField) oldWidget).controller.value);
}
else if (this.widget.controller != null && ((TextField) oldWidget).controller == null) {
this._controller = null;
}
bool isEnabled = this.widget.enabled ?? this.widget.decoration?.enabled ?? true;
bool wasEnabled = ((TextField) oldWidget).enabled ?? ((TextField) oldWidget).decoration?.enabled ?? true;
if (wasEnabled && !isEnabled) {
this._effectiveFocusNode.unfocus();
}
}
public override void dispose() {
this._focusNode?.dispose();
base.dispose();
}
void _requestKeyboard() {
this._editableTextKey.currentState?.requestKeyboard();
}
void _handleSelectionChanged(TextSelection selection, SelectionChangedCause cause) {
if (cause == SelectionChangedCause.longPress) {
// Feedback.forLongPress(context); todo add feedback
}
}
InteractiveInkFeature _createInkFeature(TapDownDetails details) {
MaterialInkController inkController = Material.of(this.context);
BuildContext editableContext = this._editableTextKey.currentContext;
RenderBox referenceBox =
(RenderBox) (InputDecorator.containerOf(editableContext) ?? editableContext.findRenderObject());
Offset position = referenceBox.globalToLocal(details.globalPosition);
Color color = Theme.of(this.context).splashColor;
InteractiveInkFeature splash = null;
void handleRemoved() {
if (this._splashes != null) {
D.assert(this._splashes.Contains(splash));
this._splashes.Remove(splash);
if (this._currentSplash == splash) this._currentSplash = null;
this.updateKeepAlive();
} // else we're probably in deactivate()
}
splash = Theme.of(this.context).splashFactory.create(
controller: inkController,
referenceBox: referenceBox,
position: position,
color: color,
containedInkWell: true,
borderRadius: BorderRadius.zero,
onRemoved: handleRemoved
);
return splash;
}
RenderEditable _renderEditable {
get {
return this._editableTextKey.currentState.renderEditable;
}
}
void _handleTapDown(TapDownDetails details) {
this._renderEditable.handleTapDown(details);
this._startSplash(details);
}
void _handleTap() {
if (this.widget.enableInteractiveSelection) {
this._renderEditable.handleTap();
}
this._requestKeyboard();
this._confirmCurrentSplash();
if (this.widget.onTap != null) {
this.widget.onTap();
}
}
void _handleTapCancel() {
this._cancelCurrentSplash();
}
void _handleLongPress() {
if (this.widget.enableInteractiveSelection) {
this._renderEditable.handleLongPress();
}
this._confirmCurrentSplash();
}
void _startSplash(TapDownDetails details) {
if (this._effectiveFocusNode.hasFocus) {
return;
}
InteractiveInkFeature splash = this._createInkFeature(details);
this._splashes = this._splashes ?? new HashSet<InteractiveInkFeature>();
this._splashes.Add(splash);
this._currentSplash = splash;
this.updateKeepAlive();
}
void _confirmCurrentSplash() {
this._currentSplash?.confirm();
this._currentSplash = null;
}
void _cancelCurrentSplash() {
this._currentSplash?.cancel();
}
protected override bool wantKeepAlive {
get { return this._splashes != null && this._splashes.isNotEmpty(); }
}
public override void deactivate() {
if (this._splashes != null) {
HashSet<InteractiveInkFeature> splashes = this._splashes;
this._splashes = null;
foreach (InteractiveInkFeature splash in splashes) {
splash.dispose();
}
this._currentSplash = null;
}
D.assert(this._currentSplash == null);
base.deactivate();
}
public override Widget build(BuildContext context) {
base.build(context); // See AutomaticKeepAliveClientMixin.
D.assert(MaterialD.debugCheckHasMaterial(context));
D.assert(WidgetsD.debugCheckHasDirectionality(context));
ThemeData themeData = Theme.of(context);
TextStyle style = this.widget.style ?? themeData.textTheme.subhead;
Brightness keyboardAppearance = this.widget.keyboardAppearance ?? themeData.primaryColorBrightness;
TextEditingController controller = this._effectiveController;
FocusNode focusNode = this._effectiveFocusNode;
List<TextInputFormatter> formatters = this.widget.inputFormatters ?? new List<TextInputFormatter>();
if (this.widget.maxLength != null && this.widget.maxLengthEnforced) {
formatters.Add(new LengthLimitingTextInputFormatter(this.widget.maxLength));
}
Widget child = new RepaintBoundary(
child: new EditableText(
key: this._editableTextKey,
controller: controller,
focusNode: focusNode,
keyboardType: this.widget.keyboardType,
textInputAction: this.widget.textInputAction,
textCapitalization: this.widget.textCapitalization,
style: style,
textAlign: this.widget.textAlign,
textDirection: this.widget.textDirection,
autofocus: this.widget.autofocus,
obscureText: this.widget.obscureText,
autocorrect: this.widget.autocorrect,
maxLines: this.widget.maxLines,
selectionColor: themeData.textSelectionColor,
selectionControls: this.widget.enableInteractiveSelection
? MaterialUtils.materialTextSelectionControls
: null,
onChanged: this.widget.onChanged,
onEditingComplete: this.widget.onEditingComplete,
onSubmitted: this.widget.onSubmitted,
onSelectionChanged: this._handleSelectionChanged,
inputFormatters: formatters,
rendererIgnoresPointer: true,
cursorWidth: this.widget.cursorWidth,
cursorRadius: this.widget.cursorRadius,
cursorColor: this.widget.cursorColor ?? Theme.of(context).cursorColor,
scrollPadding: this.widget.scrollPadding,
keyboardAppearance: keyboardAppearance,
enableInteractiveSelection: this.widget.enableInteractiveSelection
)
);
if (this.widget.decoration != null) {
child = new AnimatedBuilder(
animation: ListenableUtils.merge(new List<Listenable> {focusNode, controller}),
builder:
(_context, _child) => {
return new InputDecorator(
decoration: this._getEffectiveDecoration(),
baseStyle: this.widget.style,
textAlign: this.widget.textAlign,
isFocused: focusNode.hasFocus,
isEmpty: controller.value.text.isEmpty(),
child: _child
);
},
child: child
);
}
return new IgnorePointer(
ignoring: !(this.widget.enabled ?? this.widget.decoration?.enabled ?? true),
child: new GestureDetector(
behavior: HitTestBehavior.translucent,
onTapDown: this._handleTapDown,
onTap: this._handleTap,
onTapCancel: this._handleTapCancel,
onLongPress: this._handleLongPress,
child: child
)
);
}
}
}

11
Runtime/material/text_field.cs.meta


fileFormatVersion: 2
guid: d5a3808be9f564644bca2cd611869d5b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/redux.meta


fileFormatVersion: 2
guid: 3a7bb5e4fb043482e8bf223c2d3fa76c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

275
Runtime/rendering/debug_overflow_indicator.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
using Gradient = Unity.UIWidgets.ui.Gradient;
using Rect = Unity.UIWidgets.ui.Rect;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
namespace UIWidgets.Runtime.rendering {
enum _OverflowSide {
left,
top,
bottom,
right
}
class _OverflowRegionData {
public _OverflowRegionData(
Rect rect = null,
string label = "",
Offset labelOffset = null,
float rotation = 0.0f,
_OverflowSide? side = null
) {
this.rect = rect;
this.label = label;
this.labelOffset = labelOffset ?? Offset.zero;
this.rotation = rotation;
this.side = side;
}
public readonly Rect rect;
public readonly string label;
public readonly Offset labelOffset;
public readonly float rotation;
public readonly _OverflowSide? side;
}
public static class DebugOverflowIndicatorMixin {
static readonly Color _black = new Color(0xBF000000);
static readonly Color _yellow = new Color(0xBFFFFF00);
const float _indicatorFraction = 0.1f;
const float _indicatorFontSizePixels = 7.5f;
const float _indicatorLabelPaddingPixels = 1.0f;
static readonly TextStyle _indicatorTextStyle = new TextStyle(
color: new Color(0xFF900000),
fontSize: _indicatorFontSizePixels,
fontWeight: FontWeight.w800
);
static readonly Paint _indicatorPaint = new Paint();
static readonly Paint _labelBackgroundPaint = new Paint();
static readonly List<TextPainter> _indicatorLabel = new List<TextPainter>(4);
static DebugOverflowIndicatorMixin() {
_indicatorPaint.shader = Gradient.linear(
new Offset(0.0f, 0.0f),
new Offset(10.0f, 10.0f),
new List<Color> {_black, _yellow, _yellow, _black},
new List<float> {0.25f, 0.25f, 0.75f, 0.75f},
TileMode.repeated
);
_labelBackgroundPaint.color = new Color(0xFFFFFFFF);
for (int i = 0; i < 4; i++) {
_indicatorLabel.Add(new TextPainter(new TextSpan(""), textDirection: TextDirection.ltr));
}
}
static readonly Dictionary<RenderObject, bool> _overflowReportNeeded = new Dictionary<RenderObject, Boolean>();
static string _formatPixels(float value) {
D.assert(value > 0.0f);
string pixels;
if (value > 10.0f) {
pixels = value.ToString("0");
}
else if (value > 1.0f) {
pixels = value.ToString("0.0");
}
else {
pixels = value.ToString("0.000");
}
return pixels;
}
static List<_OverflowRegionData> _calculateOverflowRegions(RelativeRect overflow, Rect containerRect) {
List<_OverflowRegionData> regions = new List<_OverflowRegionData> { };
if (overflow.left > 0.0f) {
Rect markerRect = Rect.fromLTWH(
0.0f,
0.0f,
containerRect.width * _indicatorFraction,
containerRect.height
);
regions.Add(new _OverflowRegionData(
rect: markerRect,
label: "LEFT OVERFLOWED BY ${_formatPixels(overflow.left)} PIXELS",
labelOffset: markerRect.centerLeft +
new Offset(_indicatorFontSizePixels + _indicatorLabelPaddingPixels, 0.0f),
rotation: Mathf.PI / 2.0f,
side: _OverflowSide.left
));
}
if (overflow.right > 0.0f) {
Rect markerRect = Rect.fromLTWH(
containerRect.width * (1.0f - _indicatorFraction),
0.0f,
containerRect.width * _indicatorFraction,
containerRect.height
);
regions.Add(new _OverflowRegionData(
rect: markerRect,
label: $"RIGHT OVERFLOWED BY {_formatPixels(overflow.right)} PIXELS",
labelOffset: markerRect.centerRight -
new Offset(_indicatorFontSizePixels + _indicatorLabelPaddingPixels, 0.0f),
rotation: -Mathf.PI / 2.0f,
side: _OverflowSide.right
));
}
if (overflow.top > 0.0f) {
Rect markerRect = Rect.fromLTWH(
0.0f,
0.0f,
containerRect.width,
containerRect.height * _indicatorFraction
);
regions.Add(new _OverflowRegionData(
rect: markerRect,
label: $"TOP OVERFLOWED BY {_formatPixels(overflow.top)} PIXELS",
labelOffset: markerRect.topCenter + new Offset(0.0f, _indicatorLabelPaddingPixels),
rotation: 0.0f,
side: _OverflowSide.top
));
}
if (overflow.bottom > 0.0f) {
Rect markerRect = Rect.fromLTWH(
0.0f,
containerRect.height * (1.0f - _indicatorFraction),
containerRect.width,
containerRect.height * _indicatorFraction
);
regions.Add(new _OverflowRegionData(
rect: markerRect,
label: $"BOTTOM OVERFLOWED BY {_formatPixels(overflow.bottom)} PIXELS",
labelOffset: markerRect.bottomCenter -
new Offset(0.0f, _indicatorFontSizePixels + _indicatorLabelPaddingPixels),
rotation: 0.0f,
side: _OverflowSide.bottom
));
}
return regions;
}
static void _reportOverflow(RenderObject renderObject, RelativeRect overflow, string overflowHints) {
overflowHints = overflowHints ?? $"The edge of the {renderObject.GetType()} that is " +
"overflowing has been marked in the rendering with a yellow and black " +
"striped pattern. This is usually caused by the contents being too big " +
$"for the {renderObject.GetType()}.\n" +
"This is considered an error condition because it indicates that there " +
"is content that cannot be seen. If the content is legitimately bigger " +
"than the available space, consider clipping it with a ClipRect widget " +
$"before putting it in the {renderObject.GetType()}, or using a scrollable " +
"container, like a ListView.";
List<string> overflows = new List<string> { };
if (overflow.left > 0.0f) {
overflows.Add($"{_formatPixels(overflow.left)} pixels on the left");
}
if (overflow.top > 0.0f) {
overflows.Add($"{_formatPixels(overflow.top)} pixels on the top");
}
if (overflow.bottom > 0.0f) {
overflows.Add($"{_formatPixels(overflow.bottom)} pixels on the bottom");
}
if (overflow.right > 0.0f) {
overflows.Add($"{_formatPixels(overflow.right)} pixels on the right");
}
string overflowText = "";
D.assert(overflows.isNotEmpty(),
$"Somehow {renderObject.GetType()} didn't actually overflow like it thought it did.");
switch (overflows.Count) {
case 1:
overflowText = overflows.first();
break;
case 2:
overflowText = $"{overflows.first()} and {overflows.last()}";
break;
default:
overflows[overflows.Count - 1] = $"and {overflows[overflows.Count - 1]}";
overflowText = string.Join(", ", overflow);
break;
}
UIWidgetsError.reportError(
new UIWidgetsErrorDetails(
exception: new Exception($"A {renderObject.GetType()} overflowed by {overflowText}."),
library: "rendering library",
context: "during layout",
informationCollector: (information) => {
information.AppendLine(overflowHints);
information.AppendLine($"The specific {renderObject.GetType()} in question is:");
information.AppendLine($" {renderObject.toStringShallow(joiner: "\n ")}");
information.AppendLine(string.Concat(Enumerable.Repeat("◢◤", 32)));
}
)
);
}
public static void paintOverflowIndicator(
RenderObject renderObject,
PaintingContext context,
Offset offset,
Rect containerRect,
Rect childRect,
string overflowHints = null
) {
RelativeRect overflow = RelativeRect.fromRect(containerRect, childRect);
if (overflow.left <= 0.0f &&
overflow.right <= 0.0f &&
overflow.top <= 0.0f &&
overflow.bottom <= 0.0f) {
return;
}
List<_OverflowRegionData> overflowRegions = _calculateOverflowRegions(overflow, containerRect);
foreach (_OverflowRegionData region in overflowRegions) {
context.canvas.drawRect(region.rect.shift(offset), _indicatorPaint);
if (_indicatorLabel[(int) region.side].text?.text != region.label) {
_indicatorLabel[(int) region.side].text = new TextSpan(
text: region.label,
style: _indicatorTextStyle
);
_indicatorLabel[(int) region.side].layout();
}
Offset labelOffset = region.labelOffset + offset;
Offset centerOffset = new Offset(-_indicatorLabel[(int) region.side].width / 2.0f, 0.0f);
Rect textBackgroundRect = centerOffset & _indicatorLabel[(int) region.side].size;
context.canvas.save();
context.canvas.translate(labelOffset.dx, labelOffset.dy);
context.canvas.rotate(region.rotation);
context.canvas.drawRect(textBackgroundRect, _labelBackgroundPaint);
_indicatorLabel[(int) region.side].paint(context.canvas, centerOffset);
context.canvas.restore();
}
bool containsKey = _overflowReportNeeded.TryGetValue(renderObject, out var overflowReportNeeded);
overflowReportNeeded |= !containsKey;
if (overflowReportNeeded) {
_overflowReportNeeded[renderObject] = false;
_reportOverflow(renderObject, overflow, overflowHints);
}
}
}
}

11
Runtime/rendering/debug_overflow_indicator.cs.meta


fileFormatVersion: 2
guid: 3d9d2d2974274fa39fc3caac8ee159d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

66
Samples/UIWidgetSample/txt/TextFieldSample.cs


using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using DialogUtils = Unity.UIWidgets.material.DialogUtils;
namespace UIWidgetsSample {
public class TextFieldSample : UIWidgetsSamplePanel {
protected override void Awake() {
base.Awake();
FontManager.instance.addFont(Resources.Load<Font>(path: "MaterialIcons-Regular"), "Material Icons");
}
protected override Widget createWidget() {
return new MaterialApp(
title: "Text Fields",
home: new MyCustomForm()
);
}
}
class MyCustomForm : StatefulWidget {
public override State createState() {
return new _MyCustomFormState();
}
}
class _MyCustomFormState : State<MyCustomForm> {
readonly TextEditingController myController = new TextEditingController();
public override void dispose() {
this.myController.dispose();
base.dispose();
}
public override Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Retrieve Text Input")
),
body: new Padding(
padding: EdgeInsets.all(16.0f),
child: new TextField(controller: this.myController)
),
floatingActionButton: new FloatingActionButton(
// When the user presses the button, show an alert dialog with the
// text the user has typed into our text field.
onPressed: () => {
DialogUtils.showDialog(
context: context,
builder: (_context) => {
return new AlertDialog(
// Retrieve the text the user has typed in using our
// TextEditingController
content: new Text(this.myController.text)
);
});
},
tooltip: "Show me the value",
child: new Icon(Icons.search)
)
);
}
}
}

11
Samples/UIWidgetSample/txt/TextFieldSample.cs.meta


fileFormatVersion: 2
guid: 85b678a668e064f5c90ee8a9f7c13f35
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

43
Samples/UIWidgetSample/txt/TextStyleSample.cs


using System.Collections.Generic;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace UIWidgetsSample {
public class TextStyleSample : UIWidgetsSamplePanel {
protected override Widget createWidget() {
return new MaterialApp(
title: "Text Style",
home: new TextStyleSampleWidget()
);
}
}
class TextStyleSampleWidget : StatelessWidget {
public override Widget build(BuildContext context) {
var fontStyleTexts = new List<Widget> {
new Text("text", style: new TextStyle(fontSize: 18)),
new Text("text with font size 0 below", style: new TextStyle(fontSize: 14)),
new Text("font size 0", style: new TextStyle(fontSize: 0)),
new Text("text with font size 0 above", style: new TextStyle(fontSize: 14)),
new Text("text with font size 0.3f", style: new TextStyle(fontSize: 0.3f)),
new Text("Text with background", style: new TextStyle(fontSize: 14, background:
new Paint(){color = new Color(0xFF00FF00)})),
};
return new Scaffold(
appBar: new AppBar(
title: new Text("Text Style")
),
body: new Card(
child: new DefaultTextStyle(
style: new TextStyle(fontSize: 40, fontFamily: "Roboto"),
child: new ListView(children: fontStyleTexts))
)
);
}
}
}

11
Samples/UIWidgetSample/txt/TextStyleSample.cs.meta


fileFormatVersion: 2
guid: 1de691b215926469a959e54492262ff4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
Samples/UIWidgetsTheatre/UIWidgetsTheatre.asmdef


{
"name": "UIWidgetsTheatre",
"references": [
"Unity.UIWidgets",
"UIWidgetsGallery",
"UIWidgetsSample"],
"includePlatforms": [],
"excludePlatforms": []
}

7
Samples/UIWidgetsTheatre/UIWidgetsTheatre.asmdef.meta


fileFormatVersion: 2
guid: ce5674c12e2e24bf6bb350c64744f227
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
scripts/node_modules.meta


fileFormatVersion: 2
guid: 7d78b565ea82c414a9c59aa6ccd9bd2c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

19
Runtime/redux/redux_logging.cs


using UnityEngine;
namespace Unity.UIWidgets.Redux {
public static class ReduxLogging {
public static Middleware<State> create<State>() {
return (store) => (next) => new DispatcherImpl((action) => {
var previousState = store.getState();
var previousStateDump = JsonUtility.ToJson(previousState);
var result = next.dispatch(action);
var afterState = store.getState();
var afterStateDump = JsonUtility.ToJson(afterState);
Debug.LogFormat("Action name={0} data={1}", action.ToString(), JsonUtility.ToJson(action));
Debug.LogFormat("previousState=\n{0}", previousStateDump);
Debug.LogFormat("afterState=\n{0}", afterStateDump);
return result;
});
}
}
}

32
Runtime/redux/redux_thunk.cs


using System;
namespace Unity.UIWidgets.Redux {
public static class ReduxThunk {
public static Middleware<State> create<State>() {
return (store) => (next) => new DispatcherImpl((action) => {
var thunkAction = action as ThunkAction<State>;
if (thunkAction != null && thunkAction.action != null) {
return thunkAction.action(store.dispatcher, store.getState);
}
return next.dispatch(action);
});
}
}
public sealed class ThunkAction<State> {
public readonly Func<Dispatcher, Func<State>, object> action;
public readonly string displayName;
public ThunkAction(
Func<Dispatcher, Func<State>, object> action = null,
string displayName = null) {
this.action = action;
this.displayName = displayName ?? "";
}
public override string ToString() {
return "ThunkAction(" + this.displayName + ")";
}
}
}

81
Runtime/redux/store.cs


using System;
using System.Linq;
namespace Unity.UIWidgets {
public interface Dispatcher {
T dispatch<T>(object action);
object dispatch(object action);
}
public class DispatcherImpl : Dispatcher {
readonly Func<object, object> _impl;
public DispatcherImpl(Func<object, object> impl) {
this._impl = impl;
}
public T dispatch<T>(object action) {
if (this._impl == null) {
return default;
}
return (T) this._impl(action);
}
public object dispatch(object action) {
if (this._impl == null) {
return default;
}
return this._impl(action);
}
}
public delegate State Reducer<State>(State previousState, object action);
public delegate Func<Dispatcher, Dispatcher> Middleware<State>(Store<State> store);
public delegate void StateChangedHandler<State>(State action);
public class Store<State> {
public StateChangedHandler<State> stateChanged;
readonly Dispatcher _dispatcher;
readonly Reducer<State> _reducer;
State _state;
public Store(
Reducer<State> reducer,
State initialState = default,
params Middleware<State>[] middleware) {
this._reducer = reducer;
this._dispatcher = this._applyMiddleware(middleware);
this._state = initialState;
}
public Dispatcher dispatcher {
get { return this._dispatcher; }
}
public State getState() {
return this._state;
}
Dispatcher _applyMiddleware(params Middleware<State>[] middleware) {
return middleware.Reverse().Aggregate<Middleware<State>, Dispatcher>(
new DispatcherImpl(this._innerDispatch),
(current, middlewareItem) => middlewareItem(this)(current));
}
object _innerDispatch(object action) {
this._state = this._reducer(this._state, action);
if (this.stateChanged != null) {
this.stateChanged(this._state);
}
return action;
}
}
}

171
Runtime/redux/widget_redux.cs


using System;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.Redux {
public class StoreProvider<State> : InheritedWidget {
readonly Store<State> _store;
public StoreProvider(
Store<State> store = null,
Widget child = null,
Key key = null) : base(key: key, child: child) {
D.assert(store != null);
D.assert(child != null);
this._store = store;
}
public static Store<State> of(BuildContext context) {
var type = _typeOf<StoreProvider<State>>();
StoreProvider<State> provider = context.inheritFromWidgetOfExactType(type) as StoreProvider<State>;
if (provider == null) {
throw new UIWidgetsError("StoreProvider is missing");
}
return provider._store;
}
static Type _typeOf<T>() {
return typeof(T);
}
public override bool updateShouldNotify(InheritedWidget old) {
return !Equals(this._store, ((StoreProvider<State>) old)._store);
}
}
public delegate Widget ViewModelBuilder<ViewModel>(BuildContext context, ViewModel viewModel, Dispatcher dispatcher);
public delegate ViewModel StoreConverter<State, ViewModel>(State state);
public delegate bool ShouldRebuildCallback<ViewModel>(ViewModel previous, ViewModel current);
public class StoreConnector<State, ViewModel> : StatelessWidget {
public readonly ViewModelBuilder<ViewModel> builder;
public readonly StoreConverter<State, ViewModel> converter;
public readonly ShouldRebuildCallback<ViewModel> shouldRebuild;
public readonly bool pure;
public StoreConnector(
ViewModelBuilder<ViewModel> builder = null,
StoreConverter<State, ViewModel> converter = null,
bool pure = false,
ShouldRebuildCallback<ViewModel> shouldRebuild = null,
Key key = null) : base(key) {
D.assert(builder != null);
D.assert(converter != null);
this.pure = pure;
this.builder = builder;
this.converter = converter;
this.shouldRebuild = shouldRebuild;
}
public override Widget build(BuildContext context) {
return new _StoreListener<State, ViewModel>(
store: StoreProvider<State>.of(context),
builder: this.builder,
converter: this.converter,
pure: this.pure,
shouldRebuild: this.shouldRebuild
);
}
}
public class _StoreListener<State, ViewModel> : StatefulWidget {
public readonly ViewModelBuilder<ViewModel> builder;
public readonly StoreConverter<State, ViewModel> converter;
public readonly Store<State> store;
public readonly ShouldRebuildCallback<ViewModel> shouldRebuild;
public readonly bool pure;
public _StoreListener(
ViewModelBuilder<ViewModel> builder = null,
StoreConverter<State, ViewModel> converter = null,
Store<State> store = null,
bool pure = false,
ShouldRebuildCallback<ViewModel> shouldRebuild = null,
Key key = null) : base(key) {
D.assert(builder != null);
D.assert(converter != null);
D.assert(store != null);
this.store = store;
this.builder = builder;
this.converter = converter;
this.pure = pure;
this.shouldRebuild = shouldRebuild;
}
public override widgets.State createState() {
return new _StoreListenerState<State, ViewModel>();
}
}
class _StoreListenerState<State, ViewModel> : State<_StoreListener<State, ViewModel>> {
ViewModel latestValue;
public override void initState() {
base.initState();
this._init();
}
public override void dispose() {
this.widget.store.stateChanged -= this._handleStateChanged;
base.dispose();
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
var oldStore = ((_StoreListener<State, ViewModel>) oldWidget).store;
if (this.widget.store != oldStore) {
oldStore.stateChanged -= this._handleStateChanged;
this._init();
}
base.didUpdateWidget(oldWidget);
}
void _init() {
this.widget.store.stateChanged += this._handleStateChanged;
this.latestValue = this.widget.converter(this.widget.store.getState());
}
void _handleStateChanged(State state) {
if (Window.hasInstance) {
this._innerStateChanged(state);
}
else {
using (WindowProvider.of(this.context).getScope()) {
this._innerStateChanged(state);
}
}
}
void _innerStateChanged(State state) {
var preValue = this.latestValue;
this.latestValue = this.widget.converter(this.widget.store.getState());
if (this.widget.shouldRebuild != null) {
if (!this.widget.shouldRebuild(preValue, this.latestValue)) {
return;
}
}
else if (this.widget.pure) {
if (Equals(preValue, this.latestValue)) {
return;
}
}
this.setState();
}
public override Widget build(BuildContext context) {
return this.widget.builder(context, this.latestValue, this.widget.store.dispatcher);
}
}
}

98
Runtime/service/performance_utils.cs


using System.Diagnostics;
using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.service {
public class PerformanceUtils {
public static PerformanceUtils instance {
get {
if (_instance != null) {
return _instance;
}
_instance = new PerformanceUtils();
_instance._setup();
return _instance;
}
}
static PerformanceUtils _instance;
const int FrameBufferSize = 200;
float[] _frames;
int _curFrameId;
Stopwatch _stopwatch;
float deltaTime = 0.0f;
bool _enabled;
void _setup() {
this._frames = new float[FrameBufferSize];
this._curFrameId = -1;
this._enabled = false;
}
void _ensureStopWatch() {
if (this._stopwatch == null) {
this._stopwatch = new Stopwatch();
}
}
public void updateDeltaTime(float unscaledDeltaTime) {
this.deltaTime += (unscaledDeltaTime - this.deltaTime) * 0.1f;
}
public float getFPS() {
return 1.0f / this.deltaTime;
}
public void startProfile() {
if (!this._enabled) {
return;
}
this._ensureStopWatch();
if (this._stopwatch.IsRunning) {
D.assert(false, "Try to start the stopwatch when it is already running");
return;
}
this._stopwatch.Start();
}
public void endProfile() {
if (!this._enabled || this._stopwatch == null) {
return;
}
if (!this._stopwatch.IsRunning) {
D.assert(false, "Try to record the stopwatch when it is already stopped");
}
this._stopwatch.Stop();
float frameCost = this._stopwatch.ElapsedMilliseconds;
this._stopwatch.Reset();
if (frameCost == 0) {
return;
}
this._curFrameId = (this._curFrameId + 1) % FrameBufferSize;
this._frames[this._curFrameId] = frameCost;
}
public float[] getFrames() {
if (!this._enabled) {
this._enabled = true;
}
return this._frames;
}
public int getCurFrame() {
return this._curFrameId;
}
}
}

24
Samples/ReduxSample/ObjectFinder/Middleware.cs


using System.Linq;
using UnityEngine;
namespace Unity.UIWidgets.Sample.Redux.ObjectFinder {
public class GameFinderMiddleware {
public static Middleware<FinderAppState> Create() {
return (store) => (next) => (action) => {
if (action is SearchAction) {
var searchAction = (SearchAction) action;
var objects = Object.FindObjectsOfType(typeof(FinderGameObject)).Where((obj) => {
return searchAction.keyword == "" ||
obj.name.ToUpper().Contains(searchAction.keyword.ToUpper());
}).Select(obj => new GameObjectInfo {id = obj.GetInstanceID(), name = obj.name}).ToList();
var result = next(action);
store.Dispatch(new SearchResultAction() {keyword = searchAction.keyword, results = objects});
return result;
}
return next(action);
};
}
}
}

8
Samples/ReduxSample/redux.meta


fileFormatVersion: 2
guid: b6da4bbe4d8914b81a78b7d08ad4c7a4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Samples/ReduxSample/redux_logging.meta


fileFormatVersion: 2
guid: 5efe762e4ce804533b403e22eedb2e3b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

/Runtime/service/performance_utils.cs.meta → /Runtime/flow/instrumentation.cs.meta

/Samples/ReduxSample/ObjectFinder/Middleware.cs.meta → /Runtime/redux/redux_thunk.cs.meta

/Samples/ReduxSample/redux/store.cs.meta → /Runtime/redux/store.cs.meta

/Samples/ReduxSample/redux/widget_redux.cs.meta → /Runtime/redux/widget_redux.cs.meta

/Samples/ReduxSample/redux_logging/redux_logging.cs.meta → /Runtime/redux/redux_logging.cs.meta

正在加载...
取消
保存