浏览代码

Merge branch 'master' into 'master'

redux sample

See merge request upm-packages/ui-widgets/com.unity.uiwidgets!3
/main
Shenhua Gu 6 年前
当前提交
57c62572
共有 43 个文件被更改,包括 2509 次插入91 次删除
  1. 2
      Runtime/editor/editor_window.cs
  2. 22
      Runtime/engine/WidgetCanvas.cs
  3. 11
      Runtime/painting/box_decoration.cs
  4. 6
      Runtime/ui/window.cs
  5. 28
      Runtime/widgets/app.cs
  6. 184
      Runtime/widgets/editable_text.cs
  7. 3
      Samples/UIWidgetSample/TextInputCanvas.cs
  8. 4
      Tests/Editor/Widgets.cs
  9. 8
      Samples/ReduxSample.meta
  10. 5
      Samples/ReduxSample/.sample.json
  11. 8
      Samples/ReduxSample/CounterApp.meta
  12. 495
      Samples/ReduxSample/CounterApp/CounterApp.unity
  13. 7
      Samples/ReduxSample/CounterApp/CounterApp.unity.meta
  14. 110
      Samples/ReduxSample/CounterApp/CounterAppCanvas.cs
  15. 11
      Samples/ReduxSample/CounterApp/CounterAppCanvas.cs.meta
  16. 8
      Samples/ReduxSample/ObjectFinder.meta
  17. 26
      Samples/ReduxSample/ObjectFinder/FinderGameObject.cs
  18. 11
      Samples/ReduxSample/ObjectFinder/FinderGameObject.cs.meta
  19. 30
      Samples/ReduxSample/ObjectFinder/Middleware.cs
  20. 11
      Samples/ReduxSample/ObjectFinder/Middleware.cs.meta
  21. 178
      Samples/ReduxSample/ObjectFinder/ObjectFinderApp.cs
  22. 11
      Samples/ReduxSample/ObjectFinder/ObjectFinderApp.cs.meta
  23. 1001
      Samples/ReduxSample/ObjectFinder/ObjectFinderScene.unity
  24. 7
      Samples/ReduxSample/ObjectFinder/ObjectFinderScene.unity.meta
  25. 62
      Samples/ReduxSample/ObjectFinder/Reducer.cs
  26. 11
      Samples/ReduxSample/ObjectFinder/Reducer.cs.meta
  27. 36
      Samples/ReduxSample/ObjectFinder/StoreProvider.cs
  28. 11
      Samples/ReduxSample/ObjectFinder/StoreProvider.cs.meta
  29. 6
      Samples/ReduxSample/ReduxSample.asmdef
  30. 7
      Samples/ReduxSample/ReduxSample.asmdef.meta
  31. 8
      Samples/ReduxSample/redux.meta
  32. 50
      Samples/ReduxSample/redux/store.cs
  33. 11
      Samples/ReduxSample/redux/store.cs.meta
  34. 162
      Samples/ReduxSample/redux/widget_redux.cs
  35. 11
      Samples/ReduxSample/redux/widget_redux.cs.meta
  36. 8
      Samples/ReduxSample/redux_logging.meta
  37. 19
      Samples/ReduxSample/redux_logging/redux_logging.cs
  38. 11
      Samples/ReduxSample/redux_logging/redux_logging.cs.meta

2
Runtime/editor/editor_window.cs


}
}
public void OnGUI() {
public virtual void OnGUI() {
using (this.getScope()) {
bool dirty = false;

22
Runtime/engine/WidgetCanvas.cs


public class UIWidgetWindowAdapter : WindowAdapter
{
private WidgetCanvas _widgetCanvas;
private bool _needsPaint;
public override void scheduleFrame(bool regenerateLayerTree = true) {
base.scheduleFrame(regenerateLayerTree);
_needsPaint = true;
}
}
public override void OnGUI()
{
if (Event.current.type == EventType.Repaint)
{
if (!_needsPaint)
{
return;
}
_needsPaint = false;
}
base.OnGUI();
}
protected override Surface createSurface()

}
_windowAdapter.OnEnable();
var root = new WidgetsApp(null, getWidget());
var root = new WidgetsApp(null, getWidget(), _windowAdapter);
_windowAdapter.attachRootWidget(root);
_lastMouseMove = Input.mousePosition;

11
Runtime/painting/box_decoration.cs


public static bool operator !=(BoxDecoration a, BoxDecoration b) {
return !(a == b);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.emptyBodyDescription = "<no decorations specified>";
properties.add(new DiagnosticsProperty<Color>("color", color, defaultValue: null));
properties.add(new DiagnosticsProperty<DecorationImage>("image", image, defaultValue: null));
properties.add(new DiagnosticsProperty<Border>("border", border, defaultValue: null));
properties.add(new DiagnosticsProperty<BorderRadius>("borderRadius", borderRadius, defaultValue: null));
//properties.add(new IterableProperty<BoxShadow>("boxShadow", boxShadow, defaultValue: null, style: DiagnosticsTreeStyle.whitespace));
properties.add(new DiagnosticsProperty<Gradient>("gradient", gradient, defaultValue: null));
}
}

6
Runtime/ui/window.cs


}
}
public static bool hasInstance {
get {
return _instance != null;
}
}
static Window _instance;
public double devicePixelRatio {

28
Runtime/widgets/app.cs


{
public readonly Widget child;
public readonly Window window;
public WidgetsApp(Key key, Widget child) : base(key)
public WidgetsApp(Key key, Widget child, Window window) : base(key)
D.assert(window != null);
this.window = window;
}

}
}
public class WindowProvider : InheritedWidget {
readonly Window _window;
public WindowProvider(Window window, Widget child, Key key = null) : base(key: key, child: child) {
D.assert(window != null);
_window = window;
}
public static Window of(BuildContext context) {
WindowProvider provider = context.inheritFromWidgetOfExactType(typeof(WindowProvider)) as WindowProvider;
if (provider == null) {
throw new UIWidgetsError("WindowProvider is missing");
}
return provider._window;
}
public override bool updateShouldNotify(InheritedWidget oldWidget) {
D.assert(_window == ((WindowProvider)oldWidget)._window);
return false;
}
}
class _WidgetsAppState : State<WidgetsApp>
{

public override Widget build(BuildContext context)
{
Widget result = widget.child;
result = new WindowProvider(widget.window, result);
D.assert(() =>
{
if (WidgetInspectorService.instance.debugShowInspector)

184
Runtime/widgets/editable_text.cs


using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Color = Unity.UIWidgets.ui.Color;

bool autofocus = false, Color selectionColor = null, ValueChanged<string> onChanged = null,
ValueChanged<string> onSubmitted = null, SelectionChangedCallback onSelectionChanged = null,
List<TextInputFormatter> inputFormatters = null, bool rendererIgnoresPointer = false,
EdgeInsets scrollPadding = null,
Key key = null) : base(key)
{
D.assert(controller != null);

this.scrollPadding = scrollPadding ?? EdgeInsets.all(20.0);
this.controller = controller;
this.focusNode = focusNode;
this.obscureText = obscureText;

this.inputFormatters = inputFormatters;
}
}
public readonly EdgeInsets scrollPadding;
public override State createState()
{

_textInputConnection.setEditingState(localValue);
}
// Calculate the new scroll offset so the cursor remains visible.
double _getScrollOffsetForCaret(Rect caretRect)
{
double caretStart = _isMultiline ? caretRect.top : caretRect.left;
double caretEnd = _isMultiline ? caretRect.bottom : caretRect.right;
double scrollOffset = _scrollController.offset;
double viewportExtent = _scrollController.position.viewportDimension;
if (caretStart < 0.0)
{
scrollOffset += caretStart;
} else if (caretEnd >= viewportExtent)
{
scrollOffset += caretEnd - viewportExtent;
}
return scrollOffset;
}
// Calculates where the `caretRect` would be if `_scrollController.offset` is set to `scrollOffset`.
Rect _getCaretRectAtScrollOffset(Rect caretRect, double scrollOffset) {
double offsetDiff = _scrollController.offset - scrollOffset;
return _isMultiline ? caretRect.translate(0.0, offsetDiff) : caretRect.translate(offsetDiff, 0.0);
}
bool _hasInputConnection
{
get { return _textInputConnection != null && _textInputConnection.attached; }

}
}
Rect _currentCaretRect;
_currentCaretRect = caretRect;
// If the caret location has changed due to an update to the text or
// selection, then scroll the caret into view.
// scheduleMicrotask(() { // todo
// _scrollController.animateTo(
// _getScrollOffsetForCaret(caretRect),
// curve: Curves.fastOutSlowIn,
// duration: const Duration(milliseconds: 50),
// );
// });
_showCaretOnScreen();
// Animation configuration for scrolling the caret back on screen.
static readonly TimeSpan _caretAnimationDuration = TimeSpan.FromMilliseconds(100);
static readonly Curve _caretAnimationCurve = Curves.fastOutSlowIn;
bool _showCaretOnScreenScheduled = false;
void _showCaretOnScreen()
{
if (_showCaretOnScreenScheduled)
{
return;
}
_showCaretOnScreenScheduled = true;
SchedulerBinding.instance.addPostFrameCallback(_ =>
{
_showCaretOnScreenScheduled = false;
if (_currentCaretRect == null || !_scrollController.hasClients)
{
return;
}
double scrollOffsetForCaret = _getScrollOffsetForCaret(_currentCaretRect);
_scrollController.animateTo(scrollOffsetForCaret, duration: _caretAnimationDuration,
curve: _caretAnimationCurve);
Rect newCaretRect = _getCaretRectAtScrollOffset(_currentCaretRect, scrollOffsetForCaret);
// Enlarge newCaretRect by scrollPadding to ensure that caret is not positioned directly at the edge after scrolling.
Rect inflatedRect = Rect.fromLTRB(
newCaretRect.left - widget.scrollPadding.left,
newCaretRect.top - widget.scrollPadding.top,
newCaretRect.right + widget.scrollPadding.right,
newCaretRect.bottom + widget.scrollPadding.bottom
);
_editableKey.currentContext.findRenderObject().showOnScreen(
rect: inflatedRect,
duration: _caretAnimationDuration,
curve: _caretAnimationCurve
);
});
}
private void _formatAndSetValue(TextEditingValue value)
{
var textChanged = (_value == null ? null : _value.text) != (value == null ? null : value.text);

FocusScope.of(context).reparentIfNeeded(widget.focusNode);
base.build(context); // See AutomaticKeepAliveClientMixin.
// return new Scrollable(
// axisDirection: _isMultiline ? AxisDirection.down : AxisDirection.right
// // controller: _sc
// );
return new _Editable(
key: _editableKey,
textSpan: buildTextSpan(),
value: _value,
cursorColor: widget.cursorColor,
showCursor: _showCursor,
hasFocus: _hasFocus,
maxLines: widget.maxLines,
selectionColor: widget.selectionColor,
textScaleFactor: 1.0, // todo widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
textAlign: widget.textAlign,
textDirection: _textDirection,
obscureText: widget.obscureText,
autocorrect: widget.autocorrect,
offset: new _FixedViewportOffset(0.0),
onSelectionChanged: _handleSelectionChanged,
onCaretChanged: _handleCaretChanged,
rendererIgnoresPointer: widget.rendererIgnoresPointer
);
return new Scrollable(
axisDirection: _isMultiline ? AxisDirection.down : AxisDirection.right,
controller: _scrollController,
physics: new ClampingScrollPhysics(),
viewportBuilder: (BuildContext _context, ViewportOffset offset) =>
new _Editable(
key: _editableKey,
textSpan: buildTextSpan(),
value: _value,
cursorColor: widget.cursorColor,
showCursor: _showCursor,
hasFocus: _hasFocus,
maxLines: widget.maxLines,
selectionColor: widget.selectionColor,
textScaleFactor: Window.instance.devicePixelRatio, // todo widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
textAlign: widget.textAlign,
textDirection: _textDirection,
obscureText: widget.obscureText,
autocorrect: widget.autocorrect,
offset: offset,
onSelectionChanged: _handleSelectionChanged,
onCaretChanged: _handleCaretChanged,
rendererIgnoresPointer: widget.rendererIgnoresPointer
)
);
}
public TextSpan buildTextSpan()

edit.onCaretChanged = onCaretChanged;
edit.ignorePointer = rendererIgnoresPointer;
edit.obscureText = obscureText;
}
}
class _FixedViewportOffset : ViewportOffset
{
internal _FixedViewportOffset(double _pixels)
{
this._pixels = _pixels;
}
internal new static _FixedViewportOffset zero()
{
return new _FixedViewportOffset(0.0);
}
double _pixels;
public override double pixels
{
get { return this._pixels; }
}
public override bool applyViewportDimension(double viewportDimension)
{
return true;
}
public override bool applyContentDimensions(double minScrollExtent, double maxScrollExtent)
{
return true;
}
public override void correctBy(double correction)
{
this._pixels += correction;
}
public override void jumpTo(double pixels)
{
}
public override IPromise animateTo(double to, TimeSpan duration, Curve curve)
{
return Promise.Resolved();
}
public override ScrollDirection userScrollDirection
{
get { return ScrollDirection.idle; }
}
public override bool allowImplicitScrolling
{
get { return false; }
}
}
}

3
Samples/UIWidgetSample/TextInputCanvas.cs


{
new SizedBox(width:100, child: new Text("Description")),
new Flexible(child: new Container(
height: 200,
child: new EditableText(maxLines: 1,
child: new EditableText(maxLines: 200,
controller: descController,
focusNode: new FocusNode(),
style: new TextStyle(

4
Tests/Editor/Widgets.cs


}
Widget asPage() {
return new WidgetsApp(null, new AsScreen());
return new WidgetsApp(null, new AsScreen(), windowAdapter);
return new WidgetsApp(null, new MouseHoverWidget(null));
return new WidgetsApp(null, new MouseHoverWidget(null), windowAdapter);
}
}

8
Samples/ReduxSample.meta


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

5
Samples/ReduxSample/.sample.json


{
"displayName":"Redux Sample",
"description": "Sample usage of Redux & UIWidgets",
"createSeparatePackage": false
}

8
Samples/ReduxSample/CounterApp.meta


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

495
Samples/ReduxSample/CounterApp/CounterApp.unity


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657892, g: 0.4964127, b: 0.5748172, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 11
m_GIWorkflowMode: 0
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 1
m_LightmapEditorSettings:
serializedVersion: 10
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 500
m_PVRBounces: 2
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVRFilteringMode: 1
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ShowResolutionOverlay: 1
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &147477927
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 147477931}
- component: {fileID: 147477930}
- component: {fileID: 147477929}
- component: {fileID: 147477928}
m_Layer: 5
m_Name: Canvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &147477928
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 147477927}
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 &147477929
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 147477927}
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 &147477930
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 147477927}
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 &147477931
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 147477927}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_Children:
- {fileID: 1059242950}
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!1 &148280213
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 148280216}
- component: {fileID: 148280215}
- component: {fileID: 148280214}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &148280214
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 148280213}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
--- !u!114 &148280215
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 148280213}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!4 &148280216
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 148280213}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1059242949
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1059242950}
- component: {fileID: 1059242952}
- component: {fileID: 1059242951}
m_Layer: 5
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1059242950
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1059242949}
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: 147477931}
m_RootOrder: 0
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_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 200, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1059242951
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1059242949}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1df7452b5a8dd478ca8988b48502efe1, 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
--- !u!222 &1059242952
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1059242949}
m_CullTransparentMesh: 0
--- !u!1 &1660260751
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1660260753}
- component: {fileID: 1660260752}
m_Layer: 0
m_Name: Directional Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &1660260752
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1660260751}
m_Enabled: 1
serializedVersion: 8
m_Type: 1
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_CookieSize: 10
m_Shadows:
m_Type: 2
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &1660260753
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1660260751}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &1941984212
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1941984215}
- component: {fileID: 1941984214}
- component: {fileID: 1941984213}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &1941984213
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1941984212}
m_Enabled: 1
--- !u!20 &1941984214
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1941984212}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_GateFitMode: 2
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &1941984215
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1941984212}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

7
Samples/ReduxSample/CounterApp/CounterApp.unity.meta


fileFormatVersion: 2
guid: b223e0fe089d54420b281da7ec2b7420
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

110
Samples/ReduxSample/CounterApp/CounterAppCanvas.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.Sample.Redux {
public class CounterAppCanvas : WidgetCanvas {
protected override Widget getWidget() {
return new CounterApp();
}
}
[Serializable]
public class CouterState {
public int count;
public CouterState(int count = 0) {
this.count = count;
}
}
[Serializable]
public class CounterIncAction {
public int amount;
}
public class CounterApp : StatelessWidget {
public override Widget build(BuildContext context) {
var store = new Store<CouterState>(reduce, new CouterState(), ReduxLogging.Create<CouterState>());
return new StoreProvider<CouterState>(store, createWidget());
}
public static CouterState reduce(CouterState state, object action) {
var inc = action as CounterIncAction;
if (inc == null) {
return state;
}
return new CouterState(inc.amount + state.count);
}
private Widget createWidget() {
return new Container(
height: 200.0,
padding: EdgeInsets.all(10),
decoration: new BoxDecoration(
color: new ui.Color(0xFF7F7F7F),
border: Border.all(color: ui.Color.fromARGB(255, 255, 0, 0), width: 5),
borderRadius: BorderRadius.all(2)),
child: new Column(
children: new List<Widget>(){
new StoreConnector<CouterState, string>(
converter: (state, dispatch) => string.Format("Count:{0}", state.count),
builder: (context, countText) => new Text(countText, style: new painting.TextStyle(
fontSize: 20, fontWeight: FontWeight.w700
))
),
new StoreConnector<CouterState, Action>(
converter: (state, dispatch) => () => {dispatch(new CounterIncAction() {amount = 1});},
builder: (context, onPress) => new CustomButton(
backgroundColor: Color.fromARGB(255, 0, 204, 204),
padding: EdgeInsets.all(10),
child: new Text("Add", style: new painting.TextStyle(
fontSize: 16, color: Color.fromARGB(255, 255, 255, 255)
)), onPressed: () =>
{
onPress();
})
),
}
)
);
}
}
public class CustomButton : StatelessWidget {
public CustomButton(
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.0);
this.backgroundColor = backgroundColor;
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,
decoration: new BoxDecoration(color: this.backgroundColor),
child: this.child
)
);
}
}
}

11
Samples/ReduxSample/CounterApp/CounterAppCanvas.cs.meta


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

8
Samples/ReduxSample/ObjectFinder.meta


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

26
Samples/ReduxSample/ObjectFinder/FinderGameObject.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Unity.UIWidgets.Sample.Redux.ObjectFinder {
public class FinderGameObject : MonoBehaviour {
// Start is called before the first frame update
void Start() {
GetComponent<MeshRenderer>().material.color = new Color(1.0f, 0, 0, 1.0f);
}
// Update is called once per frame
void Update() {
var selectedId = StoreProvider.store.state.selected;
if (selectedId == GetInstanceID()) {
GetComponent<MeshRenderer>().material.color = new Color(1.0f, 0, 0, 1.0f);
} else {
GetComponent<MeshRenderer>().material.color = new Color(1.0f, 1.0f, 1.0f, 1.0f);
}
}
void OnMouseDown() {
StoreProvider.store.Dispatch(new SelectObjectAction(){id = GetInstanceID()});
}
}
}

11
Samples/ReduxSample/ObjectFinder/FinderGameObject.cs.meta


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

30
Samples/ReduxSample/ObjectFinder/Middleware.cs


using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.widgets;
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 = GameObject.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);
};
}
}
}

11
Samples/ReduxSample/ObjectFinder/Middleware.cs.meta


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

178
Samples/ReduxSample/ObjectFinder/ObjectFinderApp.cs


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
namespace Unity.UIWidgets.Sample.Redux.ObjectFinder {
public class ObjectFinderApp : WidgetCanvas {
public ObjectFinderApp() {
}
protected override Widget getWidget() {
return new StoreProvider<FinderAppState>(StoreProvider.store, createWidget());
}
private Widget createWidget() {
return new StoreConnector<FinderAppState, ObjectFinderAppWidgetModel>(
(context, viewModel) => new ObjectFinderAppWidget(
viewModel,
gameObject.name
),
(state, dispacher) => new ObjectFinderAppWidgetModel() {
objects = state.objects,
selected = state.selected,
doSearch = (text) => dispacher(new SearchAction() { keyword = text }),
onSelect = (id) => dispacher(new SelectObjectAction() { id = id })
}
);
}
}
public delegate void onFindCallback(string keyword);
public class ObjectFinderAppWidgetModel {
public int selected;
public List<GameObjectInfo> objects;
public Action<string> doSearch;
public Action<int> onSelect;
}
public class ObjectFinderAppWidget : StatefulWidget {
public readonly List<GameObjectInfo> objectInfos;
public readonly int selected;
public readonly Action<string> doSearch;
public readonly Action<int> onSelect;
public readonly string title;
public ObjectFinderAppWidget(ObjectFinderAppWidgetModel model, string title, Key key = null) : base(key) {
this.objectInfos = model.objects;
this.selected = model.selected;
this.doSearch = model.doSearch;
this.onSelect = model.onSelect;
this.title = title;
}
public override State createState() {
return new _ObjectFinderAppWidgetState();
}
}
public class _ObjectFinderAppWidgetState : State<ObjectFinderAppWidget> {
private TextEditingController _controller;
private FocusNode _focusNode;
public override void initState() {
base.initState();
_controller = new TextEditingController("");
_focusNode = new FocusNode();
if (widget.doSearch != null) {
//scheduler.SchedulerBinding.instance.scheduleFrameCallback
Window.instance.scheduleMicrotask(() => widget.doSearch(""));
}
_controller.addListener(this.textChange);
}
public override void dispose() {
_focusNode.dispose();
_controller.removeListener(this.textChange);
base.dispose();
}
public override Widget build(BuildContext context) {
return new Container(
padding: EdgeInsets.all(10),
decoration: new BoxDecoration(color: new ui.Color(0x4FFFFFFF), border: Border.all(color: ui.Color.fromARGB(255, 255, 0, 0), width: 5),
borderRadius: BorderRadius.all(2)),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: new List<Widget>(){
_buildTitle(),
_buildSearchInput(),
_buildResultCount(),
_buildResults(),
}
)
);
}
private void textChange() {
if (widget.doSearch != null) {
widget.doSearch(_controller.text);
}
}
Widget _buildTitle() {
return new Text(widget.title, textAlign: TextAlign.center,
style: new painting.TextStyle(fontSize: 20, height: 1.5));
}
Widget _buildSearchInput() {
return new Row(
children: new List<Widget>{
new Text("Search:"),
new Flexible(child:
new Container(
margin: EdgeInsets.only(left: 8),
decoration: new BoxDecoration(border: Border.all(new ui.Color(0xFF000000), 1)),
padding: EdgeInsets.only(left: 8, right: 8),
child: new EditableText(
controller: _controller,
focusNode: _focusNode,
style: new painting.TextStyle(
fontSize: 18,
height: 1.5f
),
cursorColor: ui.Color.fromARGB(255, 0, 0, 0)
)
)
)
}
);
}
Widget _buildResultItem(GameObjectInfo obj) {
return new GestureDetector(child:
new Container(
key: new ValueKey<int>(obj.id),
child: new Text(obj.name),
padding: EdgeInsets.all(8),
color: widget.selected == obj.id ? new ui.Color(0xFFFF0000) : null
), onTap: () => {
if (widget.onSelect != null) {
widget.onSelect(obj.id);
}
});
}
Widget _buildResultCount() {
return new Text(string.Format("Total Results:{0}", widget.objectInfos.Count),
style: new painting.TextStyle(height: 3.0, fontSize: 12));
}
Widget _buildResults() {
List<Widget> rows = new List<Widget>();
widget.objectInfos.ForEach(obj => {
rows.Add(_buildResultItem(obj));
});
return new Flexible(
child: new ListView(
children: rows,
physics: new AlwaysScrollableScrollPhysics())
);
}
}
}

11
Samples/ReduxSample/ObjectFinder/ObjectFinderApp.cs.meta


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

1001
Samples/ReduxSample/ObjectFinder/ObjectFinderScene.unity
文件差异内容过多而无法显示
查看文件

7
Samples/ReduxSample/ObjectFinder/ObjectFinderScene.unity.meta


fileFormatVersion: 2
guid: 27efec1d60b5b47ea892e8d510fb47e3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

62
Samples/ReduxSample/ObjectFinder/Reducer.cs


using System;
using System.Collections.Generic;
namespace Unity.UIWidgets.Sample.Redux.ObjectFinder {
[Serializable]
public class GameObjectInfo{
public int id;
public string name;
}
public class FinderAppState {
public int selected;
public List<GameObjectInfo> objects;
public FinderAppState() {
this.selected = 0;
objects = new List<GameObjectInfo>();
}
}
public class SearchAction {
public string keyword;
}
[Serializable]
public class SearchResultAction {
public string keyword;
public List<GameObjectInfo> results;
}
[Serializable]
public class SelectObjectAction {
public int id;
}
public class ObjectFinderReducer {
public static FinderAppState Reduce(FinderAppState state, object action) {
if (action is SearchResultAction) {
var resultAction = (SearchResultAction)action;
var selected = state.selected;
if (selected != null) {
var obj = resultAction.results.Find(o => o.id == selected);
if (obj == null) {
selected = 0;
}
}
return new FinderAppState() {
objects = resultAction.results,
selected = state.selected,
};
}
if (action is SelectObjectAction) {
return new FinderAppState() {
objects = state.objects,
selected = ((SelectObjectAction)action).id,
};
}
return state;
}
}
}

11
Samples/ReduxSample/ObjectFinder/Reducer.cs.meta


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

36
Samples/ReduxSample/ObjectFinder/StoreProvider.cs


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
namespace Unity.UIWidgets.Sample.Redux.ObjectFinder {
public static class StoreProvider {
private static Store<FinderAppState> _store;
public static Store<FinderAppState> store {
get {
if (_store != null) {
return _store;
}
var middlewares = new Middleware<FinderAppState>[] {
ReduxLogging.Create<FinderAppState>(),
GameFinderMiddleware.Create(),
};
_store = new Store<FinderAppState>(ObjectFinderReducer.Reduce,
new FinderAppState(),
middlewares
);
return _store;
}
}
}
}

11
Samples/ReduxSample/ObjectFinder/StoreProvider.cs.meta


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

6
Samples/ReduxSample/ReduxSample.asmdef


{
"name": "ReduxSample",
"references": ["Unity.UIWidgets"],
"includePlatforms": [],
"excludePlatforms": []
}

7
Samples/ReduxSample/ReduxSample.asmdef.meta


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

8
Samples/ReduxSample/redux.meta


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

50
Samples/ReduxSample/redux/store.cs


using System.Collections.Generic;
using System.Linq;
using System;
namespace Unity.UIWidgets.Sample.Redux {
public delegate object Dispatcher(object 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;
private State _state;
private readonly Dispatcher _dispatcher;
private readonly Reducer<State> _reducer;
public Store(Reducer<State> reducer, State initialState = default(State), params Middleware<State>[] middlewares) {
_reducer = reducer;
_dispatcher = ApplyMiddlewares(middlewares);
_state = initialState;
}
public object Dispatch(object action) {
return _dispatcher(action);
}
public State state {
get {
return _state;
}
}
private Dispatcher ApplyMiddlewares(params Middleware<State>[] middlewares) {
return middlewares.Reverse().Aggregate<Middleware<State>, Dispatcher>(
InnerDispatch, (current, middleware) => middleware(this)(current));
}
private object InnerDispatch(object action) {
_state = _reducer(_state, action);
if (stateChanged != null) {
stateChanged(_state);
}
return action;
}
}
}

11
Samples/ReduxSample/redux/store.cs.meta


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

162
Samples/ReduxSample/redux/widget_redux.cs


using System;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.Sample.Redux {
public class StoreProvider<State> : InheritedWidget {
readonly Store<State> _store;
public StoreProvider(Store<State> store, Widget child, Key key = null) : base(key: key, child: child) {
D.assert(store != null);
D.assert(child != null);
_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 !object.Equals(_store, ((StoreProvider<State>)old)._store);
}
}
public delegate Widget ViewModelBuilder<ViewModel>(BuildContext context, ViewModel vm);
public delegate ViewModel StoreConverter<State, ViewModel>(State state, Dispatcher dispatcher);
public delegate bool ShouldRebuildCallback<ViewModel>(ViewModel pre, 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 distinct;
public StoreConnector(ViewModelBuilder<ViewModel> builder, StoreConverter<State, ViewModel> converter,
bool distinct = false, ShouldRebuildCallback<ViewModel> shouldRebuild = null,
Key key = null) : base(key) {
D.assert(builder != null);
D.assert(converter != null);
this.distinct = distinct;
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: builder,
converter: converter,
distinct: distinct,
shouldRebuild: 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 distinct;
public _StoreListener(ViewModelBuilder<ViewModel> builder = null,
StoreConverter<State, ViewModel> converter = null,
Store<State> store = null,
bool distinct = 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.distinct = distinct;
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();
_init();
}
public override void dispose() {
widget.store.stateChanged -= this._handleStateChanged;
base.dispose();
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
var oldStore = ((_StoreListener<State, ViewModel>)oldWidget).store;
if (widget.store != oldStore) {
oldStore.stateChanged -= this._handleStateChanged;
_init();
}
base.didUpdateWidget(oldWidget);
}
void _init() {
widget.store.stateChanged += this._handleStateChanged;
latestValue = widget.converter(widget.store.state, widget.store.Dispatch);
}
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 = latestValue;
latestValue = this.widget.converter(widget.store.state, widget.store.Dispatch);
if (widget.shouldRebuild != null) {
if (!widget.shouldRebuild(preValue, latestValue)) {
return;
}
} else if (widget.distinct) {
if (object.Equals(preValue, latestValue)) {
return;
}
}
setState(() => {
});
}
public override Widget build(BuildContext context) {
return widget.builder(context, latestValue);
}
}
}

11
Samples/ReduxSample/redux/widget_redux.cs.meta


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

8
Samples/ReduxSample/redux_logging.meta


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

19
Samples/ReduxSample/redux_logging/redux_logging.cs


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

11
Samples/ReduxSample/redux_logging/redux_logging.cs.meta


fileFormatVersion: 2
guid: 66d5d5237e5f84f7f870b6e8d2b87815
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存