Search Issue Tracker
By Design
Votes
0
Found in [Package]
1.0.0-preview.17
Issue ID
1364977
Regression
No
[UIToolkit] OnPointerDown is not called after clicking child TextField
Reproduction steps:
1. Open the user's attached "UIToolkitCapturePointerIssue-2021.2.zip" project
2. Open the "SampleScene" Scene
3. Enter the Play mode
4. Click on the green rectangle and drag it around the Scene
5. Click on the "text field" Text Field
6. Try to drag and drop the green rectangle
Expected result: The green rectangle moves
Actual result: The green rectangle doesn't move
Reproducible with: 1.0.0-preview.15, 1.0.0-preview.16, 1.0.0-preview.17 (2020.3.19f1, 2021.1.22f1), 2021.2.0b13, 2022.1.0a9
Couldn't test with: 2019.4.30f1 (No UI Toolkit package available)
Notes:
1. To reproduce on 2020.3.19f1 import UI Toolkit and UI Builder packages and recreate UIDocument object
2. To reproduce on 2021.1.22f1, had to create a new project, import UI Toolkit, and UI Builder packages create UIDocument object and attach uxml template and script from the original project (UI Toolkit isn't shown in the Hierarchy after downgrade).
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- "IndexOutOfRangeException" and "NullReferenceException" are thrown and Element disappears from UI Builder when undoing rename of element in "Open Instance in Context" menu
- Select Scriptable Object window freezes and becomes unresponsive when currently opened UXML Template is selected for binding's Data Source
- [Linux] “ReleaseButton expects buttonId >= 0” error is thrown when importing Assets via drag and drop
- Asset gets unselected and added Subgraphs list item is not undone when performing Undo in Heatmap with Default Values asset Inspector
- Black square “shadow” artifacts visible when using Screen Space Reflections without maximum smoothing
Resolution Note:
Pointer down was called, but the internal state in the user's code was not reset when PointerCapture was lost.
Here is a fixed version of the user manipulator:
class WindowDragManipulator : PointerManipulator
{
private bool enabled;
private Vector2 startLayoutPosition;
private Vector3 startPointerPosition;
protected override void RegisterCallbacksOnTarget()
{
this.target.RegisterCallback<PointerDownEvent>(OnPointerDown);
this.target.RegisterCallback<PointerMoveEvent>(OnPointerMove);
this.target.RegisterCallback<PointerUpEvent>(OnPointerUp);
this.target.RegisterCallback<PointerCaptureOutEvent>(OnPointerCaptureOut);
}
protected override void UnregisterCallbacksFromTarget()
{
this.target.UnregisterCallback<PointerDownEvent>(OnPointerDown);
this.target.UnregisterCallback<PointerMoveEvent>(OnPointerMove);
this.target.UnregisterCallback<PointerUpEvent>(OnPointerUp);
this.target.UnregisterCallback<PointerCaptureOutEvent>(OnPointerCaptureOut);
}
private void OnPointerDown(PointerDownEvent e)
{
DebugEvent(e, e.pointerId);
if (this.enabled)
{
e.StopImmediatePropagation();
return;
}
this.startLayoutPosition = this.target.transform.position;
this.startPointerPosition = e.position;
this.target.CapturePointer(e.pointerId);
e.StopPropagation();
this.enabled = true;
}
private void OnPointerMove(PointerMoveEvent e)
{
DebugEvent(e, e.pointerId);
if (!this.enabled || !this.target.HasPointerCapture(e.pointerId))
{
return;
}
var pointerDelta = e.position - this.startPointerPosition;
var margin = this.target.layout.size * 0.5f;
var newPosition = new Vector2(Mathf.Clamp(this.startLayoutPosition.x + pointerDelta.x, -margin.x, this.target.panel.visualTree.worldBound.width - margin.x),
Mathf.Clamp(this.startLayoutPosition.y + pointerDelta.y, -margin.y, this.target.panel.visualTree.worldBound.height - margin.y));
this.target.transform.position = newPosition;
e.StopPropagation();
}
private void OnPointerUp(PointerUpEvent e)
{
DebugEvent(e, e.pointerId);
if (!this.enabled || !this.target.HasPointerCapture(e.pointerId))
{
return;
}
this.target.ReleasePointer(e.pointerId);
this.enabled = false;
}
private void OnPointerCaptureOut(PointerCaptureOutEvent e)
{
DebugEvent(e, e.pointerId);
this.enabled = false;
}
void DebugEvent(EventBase evt, int pointerId)
{
Debug.Log($"{evt.GetType().Name}: enabled: {this.enabled} pointerCapture:{this.target.HasPointerCapture(pointerId)}");
}
}