@quenty/textserviceutils 7.5.0 → 7.6.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 +11 -0
- package/package.json +3 -2
- package/src/Shared/TextServiceUtils.lua +141 -5
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
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
|
+
# [7.6.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/textserviceutils@7.5.0...@quenty/textserviceutils@7.6.0) (2022-12-27)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add TextServiceUtils.promiseTextBounds with a workaround for Roblox cancelling certain calls in weird ways. ([9f91df0](https://github.com/Quenty/NevermoreEngine/commit/9f91df0ddf8edcac7c68945b22772a964621a5fa))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# [7.5.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/textserviceutils@7.4.0...@quenty/textserviceutils@7.5.0) (2022-12-05)
|
|
7
18
|
|
|
8
19
|
**Note:** Version bump only for package @quenty/textserviceutils
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/textserviceutils",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.6.0",
|
|
4
4
|
"description": "Holds utilities involving the Roblox TextService and text fitting to size.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@quenty/blend": "^6.5.0",
|
|
34
34
|
"@quenty/loader": "^6.0.1",
|
|
35
|
+
"@quenty/promise": "^6.0.1",
|
|
35
36
|
"@quenty/rx": "^7.2.0"
|
|
36
37
|
},
|
|
37
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "a4f99aa40c45080db30be7117cada229572f1574"
|
|
38
39
|
}
|
|
@@ -7,9 +7,23 @@ local TextService = game:GetService("TextService")
|
|
|
7
7
|
local require = require(script.Parent.loader).load(script)
|
|
8
8
|
|
|
9
9
|
local Blend = require("Blend")
|
|
10
|
+
local Promise = require("Promise")
|
|
11
|
+
local Rx = require("Rx")
|
|
10
12
|
|
|
11
13
|
local TextServiceUtils = {}
|
|
12
14
|
|
|
15
|
+
--[=[
|
|
16
|
+
Gets the size for the label using legacy API surface.
|
|
17
|
+
|
|
18
|
+
:::warning
|
|
19
|
+
This will not handle new font faces well.
|
|
20
|
+
:::
|
|
21
|
+
|
|
22
|
+
@param textLabel TextLabel
|
|
23
|
+
@param text string
|
|
24
|
+
@param maxWidth number
|
|
25
|
+
@return Promise<Vector2>
|
|
26
|
+
]=]
|
|
13
27
|
function TextServiceUtils.getSizeForLabel(textLabel, text, maxWidth)
|
|
14
28
|
assert(typeof(textLabel) == "Instance", "Bad textLabel")
|
|
15
29
|
assert(type(text) == "string", "Bad text")
|
|
@@ -20,17 +34,139 @@ function TextServiceUtils.getSizeForLabel(textLabel, text, maxWidth)
|
|
|
20
34
|
return TextService:GetTextSize(text, textLabel.TextSize, textLabel.Font, Vector2.new(maxWidth, 1e6))
|
|
21
35
|
end
|
|
22
36
|
|
|
37
|
+
local lastPromise = nil
|
|
38
|
+
|
|
39
|
+
--[=[
|
|
40
|
+
Promises the text bounds for the given parameters
|
|
41
|
+
|
|
42
|
+
@param params GetTextBoundsParams
|
|
43
|
+
@return Promise<Vector2>
|
|
44
|
+
]=]
|
|
45
|
+
function TextServiceUtils.promiseTextBounds(params)
|
|
46
|
+
assert(typeof(params) == "Instance" and params:IsA("GetTextBoundsParams"), "Bad params")
|
|
47
|
+
|
|
48
|
+
-- https://devforum.roblox.com/t/calling-textservicegettextboundsasync-multiple-times-leads-to-requests-never-completing-thread-leaks/2083178
|
|
49
|
+
-- This is a hack to work around a Roblox bug.
|
|
50
|
+
local promise
|
|
51
|
+
if lastPromise then
|
|
52
|
+
promise = lastPromise:Finally(function()
|
|
53
|
+
return Promise.defer(function(resolve, reject)
|
|
54
|
+
resolve(TextServiceUtils._promiseTextBounds(params))
|
|
55
|
+
|
|
56
|
+
-- We don't want everything breaking
|
|
57
|
+
task.delay(5, function()
|
|
58
|
+
reject("Timed out")
|
|
59
|
+
end)
|
|
60
|
+
end)
|
|
61
|
+
end)
|
|
62
|
+
else
|
|
63
|
+
promise = TextServiceUtils._promiseTextBounds(params)
|
|
64
|
+
|
|
65
|
+
-- We don't want everything breaking
|
|
66
|
+
task.delay(5, function()
|
|
67
|
+
promise:Reject("Timed out")
|
|
68
|
+
end)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
-- Store this so we act as a queue :)
|
|
73
|
+
lastPromise = promise
|
|
74
|
+
|
|
75
|
+
-- Clean up
|
|
76
|
+
promise:Finally(function()
|
|
77
|
+
task.defer(function()
|
|
78
|
+
if lastPromise == promise then
|
|
79
|
+
lastPromise = nil
|
|
80
|
+
end
|
|
81
|
+
end)
|
|
82
|
+
end)
|
|
83
|
+
|
|
84
|
+
return promise
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
function TextServiceUtils._promiseTextBounds(params)
|
|
88
|
+
assert(typeof(params) == "Instance" and params:IsA("GetTextBoundsParams"), "Bad params")
|
|
89
|
+
|
|
90
|
+
return Promise.spawn(function(resolve, reject)
|
|
91
|
+
local size
|
|
92
|
+
local ok, err = pcall(function()
|
|
93
|
+
size = TextService:GetTextBoundsAsync(params)
|
|
94
|
+
end)
|
|
95
|
+
|
|
96
|
+
if not ok then
|
|
97
|
+
return reject(err)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
return resolve(size)
|
|
101
|
+
end)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
--[=[
|
|
105
|
+
Observes the current size for the current props. The properties
|
|
106
|
+
can be anything [Blend] would accept as an input. If FontFace is defined,
|
|
107
|
+
it will be used before Font. The following properties are available:
|
|
108
|
+
|
|
109
|
+
* `Text` - string
|
|
110
|
+
* `TextSize` - number
|
|
111
|
+
* `Font` - [Enum.Font]
|
|
112
|
+
* `FontFace` [Font]
|
|
113
|
+
* `MaxSize` - [Vector2]
|
|
114
|
+
* `LineHeight` - number
|
|
115
|
+
|
|
116
|
+
```lua
|
|
117
|
+
local stringValue = Instance.new("StringValue")
|
|
118
|
+
stringValue.Text = "Hello"
|
|
119
|
+
|
|
120
|
+
local observe = TextServiceUtils.observeSizeForLabelProps({
|
|
121
|
+
Text = stringValue;
|
|
122
|
+
Font = Enum.Font.;
|
|
123
|
+
MaxSize = Vector2.new(250, 100);
|
|
124
|
+
TextSize = 24;
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
-- Be sure to clean up the subscription
|
|
128
|
+
observe:Subscribe(function(size)
|
|
129
|
+
print(size)
|
|
130
|
+
end)
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
@param props table
|
|
135
|
+
@return Observable<Vector2> -- The text bounds reported
|
|
136
|
+
]=]
|
|
23
137
|
function TextServiceUtils.observeSizeForLabelProps(props)
|
|
24
138
|
assert(props.Text, "Bad props.Text")
|
|
25
139
|
assert(props.TextSize, "Bad props.TextSize")
|
|
26
|
-
assert(props.Font, "Bad props.Font")
|
|
27
140
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
141
|
+
if not (props.Font or props.FontFace) then
|
|
142
|
+
error("Bad props.Font or props.FontFace")
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
return Rx.combineLatest({
|
|
146
|
+
Text = Blend.toPropertyObservable(props.Text) or props.Text,
|
|
147
|
+
TextSize = Blend.toPropertyObservable(props.TextSize) or props.TextSize,
|
|
148
|
+
Font = Blend.toPropertyObservable(props.Font) or props.Font,
|
|
149
|
+
FontFace = Blend.toPropertyObservable(props.FontFace) or props.FontFace,
|
|
150
|
+
MaxSize = Blend.toPropertyObservable(props.MaxSize) or props.MaxSize or Vector2.new(1e6, 1e6),
|
|
151
|
+
LineHeight = Blend.toPropertyObservable(props.LineHeight) or 1,
|
|
152
|
+
}):Pipe({
|
|
153
|
+
Rx.switchMap(function(state)
|
|
154
|
+
if typeof(state.FontFace) == "Font" then
|
|
155
|
+
-- Yes, our font may have to stream in
|
|
156
|
+
local params = Instance.new("GetTextBoundsParams")
|
|
157
|
+
params.Text = state.Text
|
|
158
|
+
params.Size = state.TextSize
|
|
159
|
+
params.Font = state.Font
|
|
160
|
+
params.Width = state.MaxSize.x
|
|
161
|
+
|
|
162
|
+
return Rx.fromPromise(TextServiceUtils.promiseTextBounds(params))
|
|
163
|
+
elseif typeof(state.Font) == "EnumItem" then
|
|
164
|
+
local size = TextService:GetTextSize(state.Text, state.TextSize, state.Font, state.MaxSize)
|
|
31
165
|
|
|
32
|
-
|
|
166
|
+
return Rx.of(Vector2.new(size.x, state.LineHeight*size.y))
|
|
167
|
+
end
|
|
33
168
|
end)
|
|
169
|
+
})
|
|
34
170
|
end
|
|
35
171
|
|
|
36
172
|
return TextServiceUtils
|