@quenty/uiobjectutils 6.10.1 → 6.10.2-canary.513.656b9b5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [6.10.2-canary.513.656b9b5.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/uiobjectutils@6.10.1...@quenty/uiobjectutils@6.10.2-canary.513.656b9b5.0) (2024-11-06)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * clip state computes zero for unparented items ([8d355c1](https://github.com/Quenty/NevermoreEngine/commit/8d355c18fc228290ae2587d62586c0a9fb2f1c78))
12
+
13
+
14
+ ### Features
15
+
16
+ * Add RxClippedRectUtils.observeClippedRect(gui) ([26d5933](https://github.com/Quenty/NevermoreEngine/commit/26d593345b0f8f9af90042da826a7cc656c67713))
17
+
18
+
19
+
20
+
21
+
6
22
  ## [6.10.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/uiobjectutils@6.10.0...@quenty/uiobjectutils@6.10.1) (2024-11-04)
7
23
 
8
24
  **Note:** Version bump only for package @quenty/uiobjectutils
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/uiobjectutils",
3
- "version": "6.10.1",
3
+ "version": "6.10.2-canary.513.656b9b5.0",
4
4
  "description": "UI object utils library for Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -28,11 +28,11 @@
28
28
  "access": "public"
29
29
  },
30
30
  "dependencies": {
31
- "@quenty/brio": "^14.11.1",
32
- "@quenty/enumutils": "^3.3.0",
33
- "@quenty/instanceutils": "^13.11.1",
34
- "@quenty/loader": "^10.7.1",
35
- "@quenty/rx": "^13.11.1"
31
+ "@quenty/brio": "14.11.2-canary.513.656b9b5.0",
32
+ "@quenty/enumutils": "3.3.0",
33
+ "@quenty/instanceutils": "13.11.2-canary.513.656b9b5.0",
34
+ "@quenty/loader": "10.7.1",
35
+ "@quenty/rx": "13.11.2-canary.513.656b9b5.0"
36
36
  },
37
- "gitHead": "01c43a0ddd3c5e0cb2d9027313dbfa9852eedef1"
37
+ "gitHead": "656b9b54fcaf9beec7a43b5453d3596ee3c550e1"
38
38
  }
@@ -0,0 +1,146 @@
1
+ --[=[
2
+ Helper functions to observe parts of a Gui that are clipped or not
3
+
4
+ @class RxClippedRectUtils
5
+ ]=]
6
+
7
+ local require = require(script.Parent.loader).load(script)
8
+
9
+ local Rx = require("Rx")
10
+ local RxInstanceUtils = require("RxInstanceUtils")
11
+
12
+ local RxClippedRectUtils = {}
13
+
14
+
15
+ --[=[
16
+ Observes the clipped rect for the given Gui
17
+
18
+ @param gui Gui
19
+ @return Observable<Rect>
20
+ ]=]
21
+ function RxClippedRectUtils.observeClippedRect(gui)
22
+ assert(typeof(gui) == "Instance" and gui:IsA("GuiObject"), "Bad GuiBase2d")
23
+
24
+ -- At least use our object's size here...
25
+ return Rx.combineLatest({
26
+ absolutePosition = RxInstanceUtils.observeProperty(gui, "AbsolutePosition");
27
+ absoluteSize = RxInstanceUtils.observeProperty(gui, "AbsoluteSize");
28
+ parentRect = RxClippedRectUtils._observeParentClippedRect(gui);
29
+ }):Pipe({
30
+ Rx.map(function(state)
31
+ if state.parentRect then
32
+ return RxClippedRectUtils._computeClippedRect(state)
33
+ else
34
+ return Rect.new(Vector2.zero, Vector2.zero)
35
+ end
36
+ end);
37
+ Rx.distinct();
38
+ })
39
+ end
40
+
41
+ local function clampVector2(value)
42
+ return Vector2.new(math.clamp(value.x, 0, 1), math.clamp(value.y, 0, 1))
43
+ end
44
+
45
+ function RxClippedRectUtils.observeClippedRectInScale(gui)
46
+ assert(typeof(gui) == "Instance" and gui:IsA("GuiObject"), "Bad GuiBase2d")
47
+
48
+ return Rx.combineLatest({
49
+ absolutePosition = RxInstanceUtils.observeProperty(gui, "AbsolutePosition");
50
+ absoluteSize = RxInstanceUtils.observeProperty(gui, "AbsoluteSize");
51
+ visibleRect = RxClippedRectUtils.observeClippedRect(gui);
52
+ }):Pipe({
53
+ Rx.map(function(state)
54
+ if state.absoluteSize.x == 0 or state.absoluteSize.y == 0 then
55
+ return Rect.new(Vector2.zero, Vector2.zero)
56
+ end
57
+
58
+ local ourMin = state.absolutePosition
59
+ local ourSize = state.absoluteSize
60
+
61
+ local visibleMin = state.visibleRect.Min
62
+ local visibleSize = state.visibleRect.Max - visibleMin
63
+
64
+ local topLeft = clampVector2((visibleMin - ourMin)/ourSize)
65
+ local size = clampVector2(visibleSize/ourSize)
66
+ local bottomRight = topLeft + size
67
+ return Rect.new(topLeft, bottomRight)
68
+ end);
69
+ Rx.distinct();
70
+ })
71
+ end
72
+
73
+ function RxClippedRectUtils._observeClippedRectImpl(gui)
74
+ if gui:IsA("GuiObject") then
75
+ return RxInstanceUtils.observeProperty(gui, "ClipsDescendants"):Pipe({
76
+ Rx.switchMap(function(clipDescendants)
77
+ if not clipDescendants then
78
+ return RxClippedRectUtils._observeParentClippedRect(gui)
79
+ end
80
+
81
+ return Rx.combineLatest({
82
+ absolutePosition = RxInstanceUtils.observeProperty(gui, "AbsolutePosition");
83
+ absoluteSize = RxInstanceUtils.observeProperty(gui, "AbsoluteSize");
84
+ parentRect = RxClippedRectUtils._observeParentClippedRect(gui);
85
+ }):Pipe({
86
+ Rx.map(function(state)
87
+ return RxClippedRectUtils._computeClippedRect(state)
88
+ end);
89
+ })
90
+ end)
91
+ })
92
+ else
93
+ if not gui:IsA("LayerCollector") then
94
+ warn(string.format("[RxClippedRectUtils._observeClippedRectImpl] - Unknown gui instance type behind GuiBase2d of class %s - treating as layer collector. Please patch this method.", tostring(gui.ClassName)))
95
+ end
96
+
97
+ return Rx.combineLatest({
98
+ absolutePosition = RxInstanceUtils.observeProperty(gui, "AbsolutePosition");
99
+ absoluteSize = RxInstanceUtils.observeProperty(gui, "AbsoluteSize");
100
+ parentRect = RxClippedRectUtils._observeParentClippedRect(gui);
101
+ }):Pipe({
102
+ Rx.map(function(state)
103
+ return RxClippedRectUtils._computeClippedRect(state)
104
+ end);
105
+ })
106
+ end
107
+ end
108
+
109
+ function RxClippedRectUtils._computeClippedRect(state)
110
+ if not state.parentRect then
111
+ return Rect.new(state.absolutePosition, state.absolutePosition + state.absoluteSize)
112
+ end
113
+
114
+ local topLeft = state.absolutePosition
115
+ local bottomRight = state.absolutePosition + state.absoluteSize
116
+
117
+ local parentMin = state.parentRect.Min
118
+ local parentMax = state.parentRect.Max
119
+ local topLeftX = math.max(topLeft.x, parentMin.x)
120
+ local topLeftY = math.max(topLeft.y, parentMin.y)
121
+
122
+ local bottomRightX = math.min(bottomRight.x, parentMax.x)
123
+ local bottomRightY = math.min(bottomRight.y, parentMax.y)
124
+
125
+ -- negative sizes not allowed...
126
+ local sizeX = math.max(0, bottomRightX - topLeftX)
127
+ local sizeY = math.max(0, bottomRightY - topLeftY)
128
+
129
+ return Rect.new(topLeftX, topLeftY, topLeftX + sizeX, topLeftY + sizeY)
130
+ end
131
+
132
+ function RxClippedRectUtils._observeParentClippedRect(gui)
133
+ assert(typeof(gui) == "Instance" and gui:IsA("GuiBase2d"), "Bad GuiBase2d")
134
+
135
+ return RxInstanceUtils.observeFirstAncestor(gui, "GuiObject"):Pipe({
136
+ Rx.switchMap(function(parent)
137
+ if parent then
138
+ return RxClippedRectUtils._observeClippedRectImpl(parent)
139
+ else
140
+ return Rx.of(nil);
141
+ end
142
+ end);
143
+ });
144
+ end
145
+
146
+ return RxClippedRectUtils