浏览代码

Merge branch 'dragdrop_new' into 'master'

dragdrop codes: fix Axis.none, add drag_utils and format problems

See merge request upm-packages/ui-widgets/com.unity.uiwidgets!18
/main
Shenhua Gu 6 年前
当前提交
7d789cc4
共有 13 个文件被更改,包括 1304 次插入5 次删除
  1. 17
      Runtime/rendering/proxy_box.cs
  2. 33
      Runtime/widgets/basic.cs
  3. 104
      Samples/UIWidgetSample/UIWidgetSample.unity
  4. 398
      Runtime/gestures/multidrag.cs
  5. 11
      Runtime/gestures/multidrag.cs.meta
  6. 8
      Runtime/utils.meta
  7. 545
      Runtime/widgets/drag_target.cs
  8. 11
      Runtime/widgets/drag_target.cs.meta
  9. 149
      Samples/UIWidgetSample/DragDropCanvas.cs
  10. 11
      Samples/UIWidgetSample/DragDropCanvas.cs.meta
  11. 11
      Runtime/utils/drag_utils.cs
  12. 11
      Runtime/utils/drag_utils.cs.meta

17
Runtime/rendering/proxy_box.cs


properties.add(new DiagnosticsProperty<bool>("absorbing", this.absorbing));
}
}
public class RenderMetaData : RenderProxyBoxWithHitTestBehavior {
public RenderMetaData(
object metaData,
HitTestBehavior behavior = HitTestBehavior.deferToChild,
RenderBox child = null
) : base(behavior, child) {
this.metaData = metaData;
}
public object metaData;
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<object>("metaData", this.metaData));
}
}
}

33
Runtime/widgets/basic.cs


properties.add(new DiagnosticsProperty<bool>("absorbing", this.absorbing));
}
}
public class MetaData : SingleChildRenderObjectWidget {
public MetaData(
object metaData,
Key key = null,
HitTestBehavior behavior = HitTestBehavior.deferToChild,
Widget child = null) : base(key: key, child: child) {
this.metaData = metaData;
this.behavior = behavior;
}
public readonly object metaData;
public readonly HitTestBehavior behavior;
public override RenderObject createRenderObject(BuildContext context) {
return new RenderMetaData(
metaData: this.metaData,
behavior: this.behavior);
}
public override void updateRenderObject(BuildContext context, RenderObject renderObject) {
var renderObj = (RenderMetaData) renderObject;
renderObj.metaData = this.metaData;
renderObj.behavior = this.behavior;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new EnumProperty<HitTestBehavior>("behavior", this.behavior));
properties.add(new DiagnosticsProperty<object>("metaData", this.metaData));
}
}
public class Builder : StatelessWidget {
public Builder(

104
Samples/UIWidgetSample/UIWidgetSample.unity


m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.3731196, g: 0.38074002, b: 0.35872707, a: 1}
m_IndirectSpecularColor: {r: 0.37311953, g: 0.38074, b: 0.35872698, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:

- {fileID: 1628409007}
- {fileID: 895510406}
- {fileID: 1399904531}
- {fileID: 432951246}
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}

m_AnchoredPosition: {x: -5, y: 0}
m_SizeDelta: {x: -20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &432951245
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 432951246}
- component: {fileID: 432951248}
- component: {fileID: 432951247}
m_Layer: 5
m_Name: DragDrop
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &432951246
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 432951245}
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: 304189374}
m_RootOrder: 4
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: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &432951247
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 432951245}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d01ae8029ff2f4e54a5e9c1a9672e5dc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!222 &432951248
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 432951245}
m_CullTransparentMesh: 0
--- !u!1 &484983222
GameObject:
m_ObjectHideFlags: 0

m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!222 &895510408
CanvasRenderer:
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

m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!222 &1387978529
CanvasRenderer:
m_ObjectHideFlags: 0

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

m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!222 &1628409009
CanvasRenderer:
m_ObjectHideFlags: 0

m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 10, y: 0}
m_Pivot: {x: 0.5, y: 0.5}

398
Runtime/gestures/multidrag.cs


using System;
using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.gestures {
public delegate Drag GestureMultiDragStartCallback(Offset position);
public abstract class MultiDragPointerState {
public MultiDragPointerState(
Offset initialPosition = null) {
D.assert(initialPosition != null);
this.initialPosition = initialPosition;
}
public readonly Offset initialPosition;
readonly VelocityTracker _velocityTracker = new VelocityTracker();
Drag _client;
public Offset pendingDelta => this._pendingDelta;
public Offset _pendingDelta = Offset.zero;
TimeSpan? _lastPendingEventTimestamp;
GestureArenaEntry _arenaEntry;
public void _setArenaEntry(GestureArenaEntry entry) {
D.assert(this._arenaEntry == null);
D.assert(this.pendingDelta != null);
D.assert(this._client == null);
this._arenaEntry = entry;
}
protected void resolve(GestureDisposition disposition) {
this._arenaEntry.resolve(disposition);
}
public void _move(PointerMoveEvent pEvent) {
D.assert(this._arenaEntry != null);
if (!pEvent.synthesized)
this._velocityTracker.addPosition(pEvent.timeStamp, pEvent.position);
if (this._client != null) {
D.assert(this.pendingDelta == null);
this._client.update(new DragUpdateDetails(
sourceTimeStamp: pEvent.timeStamp,
delta: pEvent.delta,
globalPosition: pEvent.position
));
}
else {
D.assert(this.pendingDelta != null);
this._pendingDelta += pEvent.delta;
this._lastPendingEventTimestamp = pEvent.timeStamp;
this.checkForResolutionAfterMove();
}
}
public virtual void checkForResolutionAfterMove() {
}
public abstract void accepted(GestureMultiDragStartCallback starter);
public void rejected() {
D.assert(this._arenaEntry != null);
D.assert(this._client == null);
D.assert(this.pendingDelta != null);
this._pendingDelta = null;
this._lastPendingEventTimestamp = null;
this._arenaEntry = null;
}
public void _startDrag(Drag client) {
D.assert(this._arenaEntry != null);
D.assert(this._client == null);
D.assert(client != null);
D.assert(this.pendingDelta != null);
this._client = client;
DragUpdateDetails details = new DragUpdateDetails(
sourceTimeStamp: this._lastPendingEventTimestamp ?? TimeSpan.Zero,
this.pendingDelta,
globalPosition: this.initialPosition
);
this._pendingDelta = null;
this._lastPendingEventTimestamp = null;
this._client.update(details);
}
public void _up() {
D.assert(this._arenaEntry != null);
if (this._client != null) {
D.assert(this.pendingDelta == null);
DragEndDetails details = new DragEndDetails(velocity: this._velocityTracker.getVelocity());
Drag client = this._client;
this._client = null;
client.end(details);
}
else {
D.assert(this.pendingDelta != null);
this._pendingDelta = null;
this._lastPendingEventTimestamp = null;
}
}
public void _cancel() {
D.assert(this._arenaEntry != null);
if (this._client != null) {
D.assert(this.pendingDelta == null);
Drag client = this._client;
this._client = null;
client.cancel();
}
else {
D.assert(this.pendingDelta != null);
this._pendingDelta = null;
this._lastPendingEventTimestamp = null;
}
}
public virtual void dispose() {
this._arenaEntry?.resolve(GestureDisposition.rejected);
this._arenaEntry = null;
D.assert(() => {
this._pendingDelta = null;
return true;
});
}
}
public abstract class MultiDragGestureRecognizer<T> : GestureRecognizer where T : MultiDragPointerState {
protected MultiDragGestureRecognizer(
object debugOwner) : base(debugOwner: debugOwner) {
}
public GestureMultiDragStartCallback onStart;
Dictionary<int, T> _pointers = new Dictionary<int, T>();
public override void addPointer(PointerDownEvent pEvent) {
D.assert(this._pointers != null);
D.assert(pEvent.pointer != null);
D.assert(pEvent.position != null);
D.assert(!this._pointers.ContainsKey(pEvent.pointer));
T state = this.createNewPointerState(pEvent);
this._pointers[pEvent.pointer] = state;
GestureBinding.instance.pointerRouter.addRoute(pEvent.pointer, this._handleEvent);
state._setArenaEntry(GestureBinding.instance.gestureArena.add(pEvent.pointer, this));
}
public abstract T createNewPointerState(PointerDownEvent pEvent);
void _handleEvent(PointerEvent pEvent) {
D.assert(this._pointers != null);
D.assert(pEvent.pointer != null);
D.assert(pEvent.timeStamp != null);
D.assert(pEvent.position != null);
D.assert(this._pointers.ContainsKey(pEvent.pointer));
T state = this._pointers[pEvent.pointer];
if (pEvent is PointerMoveEvent) {
state._move((PointerMoveEvent) pEvent);
}
else if (pEvent is PointerUpEvent) {
D.assert(pEvent.delta == Offset.zero);
state._up();
this._removeState(pEvent.pointer);
}
else if (pEvent is PointerCancelEvent) {
D.assert(pEvent.delta == Offset.zero);
state._cancel();
this._removeState(pEvent.pointer);
}
else if (!(pEvent is PointerDownEvent)) {
D.assert(false);
}
}
public override void acceptGesture(int pointer) {
D.assert(this._pointers != null);
T state = this._pointers[pointer];
if (state == null)
return;
state.accepted((Offset initialPosition) => this._startDrag(initialPosition, pointer));
}
Drag _startDrag(Offset initialPosition, int pointer) {
D.assert(this._pointers != null);
T state = this._pointers[pointer];
D.assert(state != null);
D.assert(state._pendingDelta != null);
Drag drag = null;
if (this.onStart != null)
drag = this.invokeCallback("onStart", () => this.onStart(initialPosition));
if (drag != null)
state._startDrag(drag);
else
this._removeState(pointer);
return drag;
}
public override void rejectGesture(int pointer) {
D.assert(this._pointers != null);
if (this._pointers.ContainsKey(pointer)) {
T state = this._pointers[pointer];
D.assert(state != null);
state.rejected();
this._removeState(pointer);
}
}
void _removeState(int pointer) {
if (this._pointers == null)
return;
D.assert(this._pointers.ContainsKey(pointer));
GestureBinding.instance.pointerRouter.removeRoute(pointer, this._handleEvent);
this._pointers[pointer].dispose();
this._pointers.Remove(pointer);
}
public override void dispose() {
this._pointers.Keys.ToList().ForEach(this._removeState);
D.assert(this._pointers.isEmpty);
this._pointers = null;
base.dispose();
}
}
public class _ImmediatePointerState : MultiDragPointerState {
public _ImmediatePointerState(Offset initialPosition) : base(initialPosition) {
}
public override void checkForResolutionAfterMove() {
D.assert(this.pendingDelta != null);
if (this.pendingDelta.distance > Constants.kTouchSlop)
this.resolve(GestureDisposition.accepted);
}
public override void accepted(GestureMultiDragStartCallback starter) {
starter(this.initialPosition);
}
}
public class ImmediateMultiDragGestureRecognizer : MultiDragGestureRecognizer<_ImmediatePointerState> {
public ImmediateMultiDragGestureRecognizer(object debugOwner) : base(debugOwner: debugOwner) {
}
public override _ImmediatePointerState createNewPointerState(PointerDownEvent pEvent) {
return new _ImmediatePointerState(pEvent.position);
}
public override string debugDescription => "multidrag";
}
public class _HorizontalPointerState : MultiDragPointerState {
public _HorizontalPointerState(Offset initialPosition) : base(initialPosition) {
}
public override void checkForResolutionAfterMove() {
D.assert(this.pendingDelta != null);
if (this.pendingDelta.dx.abs() > Constants.kTouchSlop)
this.resolve(GestureDisposition.accepted);
}
public override void accepted(GestureMultiDragStartCallback starter) {
starter(this.initialPosition);
}
}
public class HorizontalMultiDragGestureRecognizer : MultiDragGestureRecognizer<_HorizontalPointerState> {
public HorizontalMultiDragGestureRecognizer(object debugOwner) : base(debugOwner: debugOwner) {
}
public override _HorizontalPointerState createNewPointerState(PointerDownEvent pEvent) {
return new _HorizontalPointerState(pEvent.position);
}
public override string debugDescription => "horizontal multidrag";
}
public class _VerticalPointerState : MultiDragPointerState {
public _VerticalPointerState(Offset initialPosition) : base(initialPosition) {
}
public override void checkForResolutionAfterMove() {
D.assert(this.pendingDelta != null);
if (this.pendingDelta.dy.abs() > Constants.kTouchSlop)
this.resolve(GestureDisposition.accepted);
}
public override void accepted(GestureMultiDragStartCallback starter) {
starter(this.initialPosition);
}
}
public class VerticalMultiDragGestureRecognizer : MultiDragGestureRecognizer<_VerticalPointerState> {
public VerticalMultiDragGestureRecognizer(object debugOwner) : base(debugOwner: debugOwner) {
}
public override _VerticalPointerState createNewPointerState(PointerDownEvent pEvent) {
return new _VerticalPointerState(pEvent.position);
}
public override string debugDescription => "vertical multidrag";
}
public class _DelayedPointerState : MultiDragPointerState {
public _DelayedPointerState(
Offset initialPosition = null,
TimeSpan? delay = null)
: base(initialPosition) {
D.assert(delay != null);
this._timer = Window.instance.run(delay ?? Constants.kLongPressTimeout, this._delayPassed, true);
}
Timer _timer;
GestureMultiDragStartCallback _starter;
void _delayPassed() {
D.assert(this._timer != null);
D.assert(this.pendingDelta != null);
D.assert(this.pendingDelta.distance <= Constants.kTouchSlop);
this._timer = null;
if (this._starter != null) {
this._starter(this.initialPosition);
this._starter = null;
}
else {
this.resolve(GestureDisposition.accepted);
}
D.assert(this._starter == null);
}
void _ensureTimerStopped() {
this._timer?.cancel();
this._timer = null;
}
public override void accepted(GestureMultiDragStartCallback starter) {
D.assert(this._starter == null);
if (this._timer == null)
starter(this.initialPosition);
else
this._starter = starter;
}
public override void checkForResolutionAfterMove() {
if (this._timer == null) {
D.assert(this._starter != null);
return;
}
D.assert(this.pendingDelta != null);
if (this.pendingDelta.distance > Constants.kTouchSlop) {
this.resolve(GestureDisposition.rejected);
this._ensureTimerStopped();
}
}
public override void dispose() {
this._ensureTimerStopped();
base.dispose();
}
}
public class DelayedMultiDragGestureRecognizer : MultiDragGestureRecognizer<_DelayedPointerState> {
public DelayedMultiDragGestureRecognizer(
TimeSpan? delay = null,
object debugOwner = null) : base(debugOwner: debugOwner) {
if (delay == null)
delay = Constants.kLongPressTimeout;
this.delay = delay;
}
readonly TimeSpan? delay;
public override _DelayedPointerState createNewPointerState(PointerDownEvent pEvent) {
return new _DelayedPointerState(pEvent.position, this.delay);
}
public override string debugDescription => "long multidrag";
}
}

11
Runtime/gestures/multidrag.cs.meta


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

8
Runtime/utils.meta


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

545
Runtime/widgets/drag_target.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.utils;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.widgets {
public delegate bool DragTargetWillAccept<T>(T data);
public delegate void DragTargetAccept<T>(T data);
public delegate Widget DragTargetBuilder<T>(BuildContext context, List<T> candidateData, List<T> rejectedData);
public delegate void DraggableCanceledCallback(Velocity velocity, Offset offset);
public delegate void DragEndCallback(DraggableDetails details);
public delegate void DragTargetLeave<T>(T data);
public enum DragAnchor {
child,
pointer
}
public class Draggable<T> : StatefulWidget {
public Draggable(
T data,
Widget child,
Widget feedback,
Key key = null,
Axis? axis = null,
Widget childWhenDragging = null,
Offset feedbackOffset = null,
DragAnchor dragAnchor = DragAnchor.child,
Axis? affinity = null,
int? maxSimultaneousDrags = null,
VoidCallback onDragStarted = null,
DraggableCanceledCallback onDraggableCanceled = null,
DragEndCallback onDragEnd = null,
VoidCallback onDragCompleted = null) : base(key) {
D.assert(child != null);
D.assert(feedback != null);
D.assert(maxSimultaneousDrags == null || maxSimultaneousDrags >= 0);
this.child = child;
this.feedback = feedback;
this.data = data;
this.axis = axis;
this.childWhenDragging = childWhenDragging;
if (feedbackOffset == null)
feedbackOffset = Offset.zero;
this.feedbackOffset = feedbackOffset;
this.dragAnchor = dragAnchor;
this.affinity = affinity;
this.maxSimultaneousDrags = maxSimultaneousDrags;
this.onDragStarted = onDragStarted;
this.onDraggableCanceled = onDraggableCanceled;
this.onDragEnd = onDragEnd;
this.onDragCompleted = onDragCompleted;
}
public readonly T data;
public readonly Axis? axis;
public readonly Widget child;
public readonly Widget childWhenDragging;
public readonly Widget feedback;
public readonly Offset feedbackOffset;
public readonly DragAnchor dragAnchor;
readonly Axis? affinity;
public readonly int? maxSimultaneousDrags;
public readonly VoidCallback onDragStarted;
public readonly DraggableCanceledCallback onDraggableCanceled;
public readonly VoidCallback onDragCompleted;
public readonly DragEndCallback onDragEnd;
public virtual GestureRecognizer createRecognizer(GestureMultiDragStartCallback onStart) {
switch (this.affinity) {
case Axis.horizontal: {
return new HorizontalMultiDragGestureRecognizer(this) {onStart = onStart};
}
case Axis.vertical: {
return new VerticalMultiDragGestureRecognizer(this) {onStart = onStart};
}
}
return new ImmediateMultiDragGestureRecognizer(this) {onStart = onStart};
}
public override State createState() {
return new _DraggableState<T>();
}
}
public class LongPressDraggable<T> : Draggable<T> {
readonly bool hapticFeedbackOnStart;
public LongPressDraggable(
T data,
Widget child,
Widget feedback,
Axis? axis = null,
Key key = null,
Widget childWhenDragging = null,
Offset feedbackOffset = null,
DragAnchor dragAnchor = DragAnchor.child,
int? maxSimultaneousDrags = null,
VoidCallback onDragStarted = null,
DraggableCanceledCallback onDraggableCanceled = null,
DragEndCallback onDragEnd = null,
VoidCallback onDragCompleted = null,
bool hapticFeedbackOnStart = true
) : base(
key: key,
child: child,
feedback: feedback,
data: data,
axis: axis,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags,
onDragStarted: onDragStarted,
onDraggableCanceled: onDraggableCanceled,
onDragEnd: onDragEnd,
onDragCompleted: onDragCompleted
) {
this.hapticFeedbackOnStart = hapticFeedbackOnStart;
}
public override GestureRecognizer createRecognizer(GestureMultiDragStartCallback onStart) {
return new DelayedMultiDragGestureRecognizer(Constants.kLongPressTimeout) {
onStart = (Offset position) => {
Drag result = onStart(position);
if (result != null && this.hapticFeedbackOnStart) {
//HapticFeedback.selectionClick();
}
return result;
}
};
}
}
public class _DraggableState<T> : State<Draggable<T>> {
public override void initState() {
base.initState();
this._recognizer = this.widget.createRecognizer(this._startDrag);
}
public override void dispose() {
this._disposeRecognizerIfInactive();
base.dispose();
}
GestureRecognizer _recognizer;
int _activeCount;
void _disposeRecognizerIfInactive() {
if (this._activeCount > 0)
return;
this._recognizer.dispose();
this._recognizer = null;
}
void _routePointer(PointerEvent pEvent) {
if (this.widget.maxSimultaneousDrags != null &&
this._activeCount >= this.widget.maxSimultaneousDrags)
return;
if (pEvent is PointerDownEvent)
this._recognizer.addPointer((PointerDownEvent) pEvent);
}
_DragAvatar<T> _startDrag(Offset position) {
if (this.widget.maxSimultaneousDrags != null &&
this._activeCount >= this.widget.maxSimultaneousDrags)
return null;
var dragStartPoint = Offset.zero;
switch (this.widget.dragAnchor) {
case DragAnchor.child:
RenderBox renderObject = this.context.findRenderObject() as RenderBox;
dragStartPoint = renderObject.globalToLocal(position);
break;
case DragAnchor.pointer:
dragStartPoint = Offset.zero;
break;
}
this.setState(() => { this._activeCount += 1; });
_DragAvatar<T> avatar = new _DragAvatar<T>(
overlayState: Overlay.of(this.context, debugRequiredFor: this.widget),
data: this.widget.data,
axis: this.widget.axis,
initialPosition: position,
dragStartPoint: dragStartPoint,
feedback: this.widget.feedback,
feedbackOffset: this.widget.feedbackOffset,
onDragEnd: (Velocity velocity, Offset offset, bool wasAccepted) => {
if (this.mounted) {
this.setState(() => { this._activeCount -= 1; });
}
else {
this._activeCount -= 1;
this._disposeRecognizerIfInactive();
}
if (this.mounted && this.widget.onDragEnd != null)
this.widget.onDragEnd(new DraggableDetails(
wasAccepted: wasAccepted,
velocity: velocity,
offset: offset
));
if (wasAccepted && this.widget.onDragCompleted != null)
this.widget.onDragCompleted();
if (!wasAccepted && this.widget.onDraggableCanceled != null)
this.widget.onDraggableCanceled(velocity, offset);
}
);
if (this.widget.onDragStarted != null)
this.widget.onDragStarted();
return avatar;
}
public override Widget build(BuildContext context) {
D.assert(Overlay.of(context, debugRequiredFor: this.widget) != null);
bool canDrag = this.widget.maxSimultaneousDrags == null ||
this._activeCount < this.widget.maxSimultaneousDrags;
bool showChild = this._activeCount == 0 || this.widget.childWhenDragging == null;
if (canDrag)
return new Listener(
onPointerDown: this._routePointer,
child: showChild ? this.widget.child : this.widget.childWhenDragging
);
return new Listener(
child: showChild ? this.widget.child : this.widget.childWhenDragging);
}
}
public class DraggableDetails {
public DraggableDetails(
Velocity velocity,
Offset offset,
bool wasAccepted = false
) {
D.assert(velocity != null);
D.assert(offset != null);
this.wasAccepted = wasAccepted;
this.velocity = velocity;
this.offset = offset;
}
public bool wasAccepted;
public Velocity velocity;
public Offset offset;
}
public class DragTarget<T> : StatefulWidget {
public DragTarget(
DragTargetBuilder<T> builder,
Key key = null,
DragTargetWillAccept<T> onWillAccept = null,
DragTargetAccept<T> onAccept = null,
DragTargetLeave<T> onLeave = null
) : base(key) {
this.builder = builder;
this.onWillAccept = onWillAccept;
this.onAccept = onAccept;
this.onLeave = onLeave;
}
public DragTargetBuilder<T> builder;
public DragTargetWillAccept<T> onWillAccept;
public DragTargetAccept<T> onAccept;
public DragTargetLeave<T> onLeave;
public override State createState() {
return new _DragTargetState<T>();
}
}
public class _DragTargetState<T> : State<DragTarget<T>> {
readonly List<_DragAvatar<T>> _candidateAvatars = new List<_DragAvatar<T>>();
readonly List<_DragAvatar<T>> _rejectedAvatars = new List<_DragAvatar<T>>();
public bool didEnter(_DragAvatar<T> avatar) {
D.assert(!this._candidateAvatars.Contains(avatar));
D.assert(!this._rejectedAvatars.Contains(avatar));
if (avatar.data is T && (this.widget.onWillAccept == null || this.widget.onWillAccept(avatar.data))) {
this.setState(() => { this._candidateAvatars.Add(avatar); });
return true;
}
this._rejectedAvatars.Add(avatar);
return false;
}
public void didLeave(_DragAvatar<T> avatar) {
D.assert(this._candidateAvatars.Contains(avatar) || this._rejectedAvatars.Contains(avatar));
if (!this.mounted)
return;
this.setState(() => {
this._candidateAvatars.Remove(avatar);
this._rejectedAvatars.Remove(avatar);
});
if (this.widget.onLeave != null)
this.widget.onLeave(avatar.data);
}
public void didDrop(_DragAvatar<T> avatar) {
D.assert(this._candidateAvatars.Contains(avatar));
if (!this.mounted)
return;
this.setState(() => { this._candidateAvatars.Remove(avatar); });
if (this.widget.onAccept != null)
this.widget.onAccept(avatar.data);
}
public override Widget build(BuildContext context) {
D.assert(this.widget.builder != null);
return new MetaData(
metaData: this,
behavior: HitTestBehavior.translucent,
child: this.widget.builder(context, DragUtils._mapAvatarsToData(this._candidateAvatars),
DragUtils._mapAvatarsToData(this._rejectedAvatars)));
}
}
public enum _DragEndKind {
dropped,
canceled
}
public delegate void _OnDragEnd(Velocity velocity, Offset offset, bool wasAccepted);
public class _DragAvatar<T> : Drag {
public _DragAvatar(
T data,
OverlayState overlayState,
Axis? axis = null,
Offset initialPosition = null,
Offset dragStartPoint = null,
Widget feedback = null,
Offset feedbackOffset = null,
_OnDragEnd onDragEnd = null
) {
if (initialPosition == null)
initialPosition = Offset.zero;
if (dragStartPoint == null)
dragStartPoint = Offset.zero;
if (feedbackOffset == null)
feedbackOffset = Offset.zero;
D.assert(overlayState != null);
this.overlayState = overlayState;
this.data = data;
this.axis = axis;
this.dragStartPoint = dragStartPoint;
this.feedback = feedback;
this.feedbackOffset = feedbackOffset;
this.onDragEnd = onDragEnd;
this._entry = new OverlayEntry(this._build);
this.overlayState.insert(this._entry);
this._position = initialPosition;
this.updateDrag(initialPosition);
}
public readonly T data;
readonly Axis? axis;
readonly Offset dragStartPoint;
readonly Widget feedback;
readonly Offset feedbackOffset;
readonly _OnDragEnd onDragEnd;
readonly OverlayState overlayState;
_DragTargetState<T> _activeTarget;
readonly List<_DragTargetState<T>> _enteredTargets = new List<_DragTargetState<T>>();
OverlayEntry _entry;
Offset _lastOffset;
Offset _position;
public void update(DragUpdateDetails details) {
this._position += this._restrictAxis(details.delta);
this.updateDrag(this._position);
}
public void end(DragEndDetails details) {
this.finishDrag(_DragEndKind.dropped, this._restrictVelocityAxis(details.velocity));
}
public void cancel() {
this.finishDrag(_DragEndKind.canceled);
}
void updateDrag(Offset globalPosition) {
this._lastOffset = globalPosition - this.dragStartPoint;
this._entry.markNeedsBuild();
HitTestResult result = new HitTestResult();
WidgetsBinding.instance.hitTest(result, globalPosition + this.feedbackOffset);
List<_DragTargetState<T>> targets = this._getDragTargets(result.path.ToList());
bool listsMatch = false;
if (targets.Count >= this._enteredTargets.Count && this._enteredTargets.isNotEmpty()) {
listsMatch = true;
List<_DragTargetState<T>>.Enumerator iterator = targets.GetEnumerator();
for (int i = 0; i < this._enteredTargets.Count; i++) {
iterator.MoveNext();
if (iterator.Current != this._enteredTargets[i]) {
listsMatch = false;
break;
}
}
}
if (listsMatch)
return;
this._leaveAllEntered();
_DragTargetState<T> newTarget = null;
foreach (var target in targets) {
this._enteredTargets.Add(target);
if (target.didEnter(this)) {
newTarget = target;
break;
}
}
this._activeTarget = newTarget;
}
List<_DragTargetState<T>> _getDragTargets(List<HitTestEntry> path) {
List<_DragTargetState<T>> ret = new List<_DragTargetState<T>>();
foreach (HitTestEntry entry in path)
if (entry.target is RenderMetaData) {
RenderMetaData renderMetaData = (RenderMetaData) entry.target;
if (renderMetaData.metaData is _DragTargetState<T>)
ret.Add((_DragTargetState<T>) renderMetaData.metaData);
}
return ret;
}
void _leaveAllEntered() {
for (int i = 0; i < this._enteredTargets.Count; i++)
this._enteredTargets[i].didLeave(this);
this._enteredTargets.Clear();
}
void finishDrag(_DragEndKind endKind, Velocity velocity = null) {
bool wasAccepted = false;
if (endKind == _DragEndKind.dropped && this._activeTarget != null) {
this._activeTarget.didDrop(this);
wasAccepted = true;
this._enteredTargets.Remove(this._activeTarget);
}
this._leaveAllEntered();
this._activeTarget = null;
this._entry.remove();
this._entry = null;
if (this.onDragEnd != null)
this.onDragEnd(velocity == null ? Velocity.zero : velocity, this._lastOffset, wasAccepted);
}
public Widget _build(BuildContext context) {
RenderBox box = (RenderBox) this.overlayState.context.findRenderObject();
Offset overlayTopLeft = box.localToGlobal(Offset.zero);
return new Positioned(
left: this._lastOffset.dx - overlayTopLeft.dx,
top: this._lastOffset.dy - overlayTopLeft.dy,
child: new IgnorePointer(
child: this.feedback
)
);
}
Velocity _restrictVelocityAxis(Velocity velocity) {
if (this.axis == null) {
return velocity;
}
return new Velocity(
this._restrictAxis(velocity.pixelsPerSecond));
}
Offset _restrictAxis(Offset offset) {
if (this.axis == null) {
return offset;
}
if (this.axis == Axis.horizontal) {
return new Offset(offset.dx, 0.0);
}
return new Offset(0.0, offset.dy);
}
}
}

11
Runtime/widgets/drag_target.cs.meta


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

149
Samples/UIWidgetSample/DragDropCanvas.cs


using System.Collections.Generic;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
namespace UIWidgetsSample {
public class DragDropCanvas : WidgetCanvas {
protected override Widget getWidget() {
return new DragDropApp();
}
class DragDropApp : StatefulWidget {
public DragDropApp(Key key = null) : base(key) {
}
public override State createState() {
return new DragDropState();
}
}
class DragTargetWidget : StatefulWidget {
public DragTargetWidget(Key key = null) : base(key) {
}
public override State createState() {
return new DragTargetWidgetState();
}
}
class DragTargetWidgetState : State<DragTargetWidget> {
int value;
public override Widget build(BuildContext context) {
return new Positioned(
left: 40.0,
bottom: 40.0,
child: new DragTarget<int>(
onAccept: obj => {
Debug.Log("ON ACCEPTED ..." + obj);
this.setState(() => { this.value += obj; });
},
builder: (inner_context2, accepted, rejected) => {
return new Container(
width: 40.0,
height: 40.0,
constraints: BoxConstraints.tight(new Size(40, 40)),
color: AsScreenCanvas.CLColors.red,
child: new Center(child: new Text("" + this.value))
);
}
)
);
}
}
class DragDropState : State<DragDropApp> {
public override Widget build(BuildContext context) {
var entries = new List<OverlayEntry>();
var entry_bg = new OverlayEntry(
inner_context => new Container(
color: AsScreenCanvas.CLColors.white
));
var entry = new OverlayEntry(
inner_context => new Positioned(
left: 0.0,
bottom: 0.0,
child: new GestureDetector(
onTap: () => { },
child: new Draggable<int>(
5,
child: new Container(
color: AsScreenCanvas.CLColors.blue,
width: 30.0,
height: 30.0,
constraints: BoxConstraints.tight(new Size(30, 30)),
child: new Center(child: new Text("5"))
),
feedback: new Container(
color: AsScreenCanvas.CLColors.green,
width: 30.0,
height: 30.0),
//maxSimultaneousDrags: 1,
childWhenDragging: new Container(
color: AsScreenCanvas.CLColors.black,
width: 30.0,
height: 30.0,
constraints: BoxConstraints.tight(new Size(30, 30))
)
)
)
)
);
var entry3 = new OverlayEntry(
inner_context => new Positioned(
left: 0.0,
bottom: 40.0,
child: new GestureDetector(
onTap: () => { },
child:
new Draggable<int>(
8,
child: new Container(
color: AsScreenCanvas.CLColors.background4,
width: 30.0,
height: 30.0,
constraints: BoxConstraints.tight(new Size(30, 30)),
child: new Center(child: new Text("8")))
,
feedback: new Container(
color: AsScreenCanvas.CLColors.green,
width: 30.0,
height: 30.0),
maxSimultaneousDrags: 1,
childWhenDragging: new Container(
color: AsScreenCanvas.CLColors.black,
width: 30.0,
height: 30.0,
constraints: BoxConstraints.tight(new Size(30, 30))
)
)
)
)
);
var entry2 = new OverlayEntry(
inner_context => new DragTargetWidget()
);
entries.Add(entry_bg);
entries.Add(entry);
entries.Add(entry2);
entries.Add(entry3);
return new Container(
color: AsScreenCanvas.CLColors.white,
child: new Overlay(
initialEntries: entries
)
);
}
}
}
}

11
Samples/UIWidgetSample/DragDropCanvas.cs.meta


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

11
Runtime/utils/drag_utils.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.utils {
public class DragUtils {
public static List<T> _mapAvatarsToData<T>(List<_DragAvatar<T>> avatars) {
return avatars.Select(avatar => avatar.data).ToList();
}
}
}

11
Runtime/utils/drag_utils.cs.meta


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