Skip to content
This repository was archived by the owner on Apr 29, 2021. It is now read-only.

Commit d8b1506

Browse files
authored
Merge pull request #366 from IIzzaya/dev_raycast
[Feature] UIWidgetsRaycastablePanel
2 parents ddfde83 + e5b9bd5 commit d8b1506

8 files changed

+320
-4
lines changed

Runtime/engine/UIWidgetsPanel.cs

+8-4
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ void _handleViewMetricsChanged(string method, List<JSONNode> args) {
138138
this._displayMetrics.onViewMetricsChanged();
139139
}
140140

141+
protected virtual void InitWindowAdapter() {
142+
D.assert(this._windowAdapter == null);
143+
this._windowAdapter = new UIWidgetWindowAdapter(this);
144+
145+
this._windowAdapter.OnEnable();
146+
}
147+
141148
protected override void OnEnable() {
142149
base.OnEnable();
143150

@@ -153,10 +160,7 @@ protected override void OnEnable() {
153160
_repaintEvent = new Event {type = EventType.Repaint};
154161
}
155162

156-
D.assert(this._windowAdapter == null);
157-
this._windowAdapter = new UIWidgetWindowAdapter(this);
158-
159-
this._windowAdapter.OnEnable();
163+
this.InitWindowAdapter();
160164

161165
Widget root;
162166
using (this._windowAdapter.getScope()) {

Runtime/engine/raycastable.meta

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using System.Collections.Generic;
2+
using Unity.UIWidgets.foundation;
3+
using Unity.UIWidgets.ui;
4+
using UnityEngine;
5+
6+
namespace Unity.UIWidgets.engine.raycast {
7+
public class RaycastableRect {
8+
bool _isDirty = true;
9+
10+
public bool isDirty {
11+
get { return this._isDirty; }
12+
}
13+
14+
public float left;
15+
public float right;
16+
public float top;
17+
public float bottom;
18+
19+
public void MarkDirty() {
20+
this._isDirty = true;
21+
}
22+
23+
public void UnmarkDirty() {
24+
this._isDirty = false;
25+
}
26+
27+
public void UpdateRect(float left, float top, float width, float height) {
28+
this.left = left;
29+
this.right = left + width;
30+
this.top = top;
31+
this.bottom = top + height;
32+
}
33+
34+
public bool CheckInRect(Vector2 pos) {
35+
return pos.x >= this.left &&
36+
pos.x < this.right &&
37+
pos.y >= this.top &&
38+
pos.y < this.bottom;
39+
}
40+
}
41+
42+
public class RaycastManager {
43+
static RaycastManager _instance;
44+
45+
public static RaycastManager instance {
46+
get {
47+
if (_instance == null) {
48+
_instance = new RaycastManager();
49+
}
50+
51+
return _instance;
52+
}
53+
}
54+
55+
public readonly Dictionary<int, Dictionary<int, RaycastableRect>> raycastHandlerMap =
56+
new Dictionary<int, Dictionary<int, RaycastableRect>>();
57+
58+
public static void NewWindow(int windowHashCode) {
59+
if (!instance.raycastHandlerMap.ContainsKey(windowHashCode)) {
60+
instance.raycastHandlerMap.Add(windowHashCode, new Dictionary<int, RaycastableRect>());
61+
}
62+
}
63+
64+
public static void DisposeWindow(int windowHashCode) {
65+
if (instance.raycastHandlerMap.ContainsKey(windowHashCode)) {
66+
instance.raycastHandlerMap.Remove(windowHashCode);
67+
}
68+
}
69+
70+
public static void AddToList(int widgetHashCode, int windowHashCode) {
71+
D.assert(instance.raycastHandlerMap.ContainsKey(windowHashCode), () =>
72+
$"Raycast Handler Map doesn't contain Window {windowHashCode}, " +
73+
$"Make sure using UIWidgetsRaycastablePanel instead of UIWidgetsPanel " +
74+
$"while using RaycastableContainer.");
75+
D.assert(!instance.raycastHandlerMap[windowHashCode].ContainsKey(widgetHashCode), () =>
76+
$"Raycast Handler Map already contains Widget {widgetHashCode} at Window {windowHashCode}");
77+
78+
instance.raycastHandlerMap[windowHashCode][widgetHashCode] = new RaycastableRect();
79+
}
80+
81+
public static void MarkDirty(int widgetHashCode, int windowHashCode) {
82+
D.assert(instance.raycastHandlerMap.ContainsKey(windowHashCode), () =>
83+
$"Raycast Handler Map doesn't contain Window {windowHashCode}");
84+
D.assert(instance.raycastHandlerMap[windowHashCode].ContainsKey(widgetHashCode), () =>
85+
$"Raycast Handler Map doesn't contain Widget {widgetHashCode} at Window {windowHashCode}");
86+
87+
instance.raycastHandlerMap[windowHashCode][widgetHashCode].MarkDirty();
88+
}
89+
90+
public static void UpdateSizeOffset(int widgetHashCode, int windowHashCode, Size size, Offset offset) {
91+
D.assert(instance.raycastHandlerMap.ContainsKey(windowHashCode), () =>
92+
$"Raycast Handler Map doesn't contain Window {windowHashCode}");
93+
D.assert(instance.raycastHandlerMap[windowHashCode].ContainsKey(widgetHashCode), () =>
94+
$"Raycast Handler Map doesn't contain Widget {widgetHashCode} at Window {windowHashCode}");
95+
96+
if (instance.raycastHandlerMap[windowHashCode][widgetHashCode].isDirty) {
97+
instance.raycastHandlerMap[windowHashCode][widgetHashCode]
98+
.UpdateRect(offset.dx, offset.dy, size.width, size.height);
99+
instance.raycastHandlerMap[windowHashCode][widgetHashCode].UnmarkDirty();
100+
}
101+
}
102+
103+
public static void RemoveFromList(int widgetHashCode, int windowHashCode) {
104+
D.assert(instance.raycastHandlerMap.ContainsKey(windowHashCode), () =>
105+
$"Raycast Handler Map doesn't contain Window {windowHashCode}");
106+
D.assert(instance.raycastHandlerMap[windowHashCode].ContainsKey(widgetHashCode), () =>
107+
$"Raycast Handler Map doesn't contain Widget {widgetHashCode} at Window {windowHashCode}");
108+
109+
instance.raycastHandlerMap[windowHashCode].Remove(widgetHashCode);
110+
}
111+
112+
public static bool CheckCastThrough(int windowHashCode, Vector2 pos) {
113+
D.assert(instance.raycastHandlerMap.ContainsKey(windowHashCode), () =>
114+
$"Raycast Handler Map doesn't contain Window {windowHashCode}");
115+
116+
foreach (var item in instance.raycastHandlerMap[windowHashCode]) {
117+
if (item.Value.CheckInRect(pos)) {
118+
return false;
119+
}
120+
}
121+
122+
return true;
123+
}
124+
}
125+
}

Runtime/engine/raycastable/RaycastManager.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using Unity.UIWidgets.foundation;
2+
using Unity.UIWidgets.rendering;
3+
using Unity.UIWidgets.ui;
4+
using Unity.UIWidgets.widgets;
5+
6+
namespace Unity.UIWidgets.engine.raycast {
7+
class RaycastableBox : SingleChildRenderObjectWidget {
8+
public RaycastableBox(
9+
Key key = null,
10+
Widget child = null
11+
) : base(key, child) {
12+
this.windowHashCode = Window.instance.GetHashCode();
13+
}
14+
15+
readonly int windowHashCode;
16+
17+
public override RenderObject createRenderObject(BuildContext context) {
18+
return new RenderRaycastableBox(
19+
windowHashCode: this.windowHashCode,
20+
widget: this
21+
);
22+
}
23+
24+
public override Element createElement() {
25+
return new _RaycastableBoxRenderElement(windowHashCode: this.windowHashCode, widget: this);
26+
}
27+
}
28+
29+
class RenderRaycastableBox : RenderProxyBox {
30+
public RenderRaycastableBox(
31+
int windowHashCode,
32+
RaycastableBox widget
33+
) {
34+
this.widgetHashCode = widget.GetHashCode();
35+
this.windowHashCode = windowHashCode;
36+
}
37+
38+
readonly int widgetHashCode;
39+
readonly int windowHashCode;
40+
41+
public override void paint(PaintingContext context, Offset offset) {
42+
RaycastManager.UpdateSizeOffset(this.widgetHashCode, this.windowHashCode, this.size, offset);
43+
44+
base.paint(context, offset);
45+
}
46+
}
47+
48+
class _RaycastableBoxRenderElement : SingleChildRenderObjectElement {
49+
public _RaycastableBoxRenderElement(
50+
int windowHashCode,
51+
RaycastableBox widget
52+
) : base(widget) {
53+
this.windowHashCode = windowHashCode;
54+
}
55+
56+
public new RaycastableBox widget {
57+
get { return base.widget as RaycastableBox; }
58+
}
59+
60+
int widgetHashCode;
61+
int windowHashCode;
62+
63+
public override void mount(Element parent, object newSlot) {
64+
this.widgetHashCode = this.widget.GetHashCode();
65+
RaycastManager.AddToList(this.widgetHashCode, this.windowHashCode);
66+
base.mount(parent, newSlot);
67+
}
68+
69+
public override void update(Widget newWidget) {
70+
RaycastManager.MarkDirty(this.widgetHashCode, this.windowHashCode);
71+
base.update(newWidget);
72+
}
73+
74+
public override void unmount() {
75+
RaycastManager.RemoveFromList(this.widgetHashCode, this.windowHashCode);
76+
base.unmount();
77+
}
78+
}
79+
80+
public class RaycastableContainer : StatelessWidget {
81+
public RaycastableContainer(
82+
Widget child = null,
83+
Key key = null
84+
) : base(key) {
85+
this.child = child;
86+
}
87+
88+
public readonly Widget child;
89+
90+
public override Widget build(BuildContext context) {
91+
Widget current = this.child;
92+
93+
if (this.child == null) {
94+
current = new LimitedBox(
95+
maxWidth: 0.0f,
96+
maxHeight: 0.0f,
97+
child: new ConstrainedBox(constraints: BoxConstraints.expand())
98+
);
99+
}
100+
101+
current = new RaycastableBox(child: current);
102+
103+
return current;
104+
}
105+
}
106+
}

Runtime/engine/raycastable/RaycastableContainer.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Unity.UIWidgets.engine;
2+
using UnityEngine;
3+
4+
namespace Unity.UIWidgets.engine.raycast {
5+
[RequireComponent(typeof(RectTransform))]
6+
public class UIWidgetsRaycastablePanel : UIWidgetsPanel, ICanvasRaycastFilter {
7+
int windowHashCode;
8+
9+
protected override void InitWindowAdapter() {
10+
base.InitWindowAdapter();
11+
this.windowHashCode = this.window.GetHashCode();
12+
RaycastManager.NewWindow(this.windowHashCode);
13+
}
14+
15+
protected override void OnDisable() {
16+
base.OnDisable();
17+
RaycastManager.DisposeWindow(this.windowHashCode);
18+
}
19+
20+
public bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) {
21+
if (!this.enabled) {
22+
return true;
23+
}
24+
25+
Vector2 local;
26+
RectTransformUtility.ScreenPointToLocalPointInRectangle(this.rectTransform, screenPoint, eventCamera,
27+
out local);
28+
29+
Rect rect = this.rectTransform.rect;
30+
31+
// Convert top left corner as reference origin point.
32+
local.x += this.rectTransform.pivot.x * rect.width;
33+
local.y -= this.rectTransform.pivot.y * rect.height;
34+
local.x = local.x / this.devicePixelRatio;
35+
local.y = -local.y / this.devicePixelRatio;
36+
37+
return !RaycastManager.CheckCastThrough(this.windowHashCode, local);
38+
}
39+
}
40+
}

Runtime/engine/raycastable/UIWidgetsRaycastablePanel.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)