/
GameScalingUtils.lua
141 lines (122 loc) · 3.54 KB
/
GameScalingUtils.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
--[=[
Scale ratios for the UI on different devices
@class GameScalingUtils
]=]
local require = require(script.Parent.loader).load(script)
local GuiService = game:GetService("GuiService")
local Blend = require("Blend")
local Rx = require("Rx")
local RxInstanceUtils = require("RxInstanceUtils")
local GameScalingUtils = {}
--[=[
Given an screenAbsoluteSize, get a good UI scale to use for fixed offset
assuming general UI scales built for 720p monitors.
@param screenAbsoluteSize Vector2
@return number
]=]
function GameScalingUtils.getUIScale(screenAbsoluteSize)
assert(typeof(screenAbsoluteSize) == "Vector2", "Bad screenAbsoluteSize")
local smallestAxis = math.min(screenAbsoluteSize.x, screenAbsoluteSize.y)
local height = screenAbsoluteSize.y
if GuiService:IsTenFootInterface() then
return 2
elseif smallestAxis >= 900 then
return 1.5
elseif smallestAxis >= 700 then
return 1.25
elseif height >= 500 then
return 1
elseif height >= 325 then
return 0.75
else
return 0.6
end
end
--[=[
Observes a smoothed out UI scale for a given screenGui
@param screenGui ScreenGui
@return Observable<number>
]=]
function GameScalingUtils.observeUIScale(screenGui)
return Blend.Spring(RxInstanceUtils.observeProperty(screenGui, "AbsoluteSize")
:Pipe({
Rx.map(GameScalingUtils.getUIScale)
}), 30)
end
--[=[
Observes a smoothed out UI scale for a given screenGui
@param child Instance
@return Observable<number>
]=]
function GameScalingUtils.observeUIScaleForChild(child)
return RxInstanceUtils.observeFirstAncestor(child, "ScreenGui"):Pipe({
Rx.switchMap(function(screenGui)
if screenGui then
return GameScalingUtils.observeUIScale(screenGui)
else
return Rx.EMPTY
end
end)
})
end
--[=[
Blend equivalent of rendering a UI Scale
@param props { Parent: Instance?, ScreenGui: ScreenGui }
@return Observable<number>
]=]
function GameScalingUtils.renderUIScale(props)
assert(props.ScreenGui, "No screenGui")
return Blend.New "UIScale" {
Parent = props.Parent;
Scale = GameScalingUtils.observeUIScale(props.ScreenGui)
}
end
--[=[
Blend equivalent of rendering the dialog padding
@param props { Parent: Instance?, ScreenGui: ScreenGui }
@return Observable<number>
]=]
function GameScalingUtils.renderDialogPadding(props)
assert(props.ScreenGui, "No screenGui")
return Blend.New "UIPadding" {
Parent = props.Parent;
PaddingTop = GameScalingUtils.observeDialogPadding(props.ScreenGui);
PaddingBottom = GameScalingUtils.observeDialogPadding(props.ScreenGui);
PaddingLeft = GameScalingUtils.observeDialogPadding(props.ScreenGui);
PaddingRight = GameScalingUtils.observeDialogPadding(props.ScreenGui);
}
end
--[=[
Observes a smoothed out UI scale for a given screenGui
@param screenGui ScreenGui
@return Observable<number>
]=]
function GameScalingUtils.observeDialogPadding(screenGui)
return Blend.Spring(RxInstanceUtils.observeProperty(screenGui, "AbsoluteSize")
:Pipe({
Rx.map(GameScalingUtils.getDialogPadding)
}), 30):Pipe({
Rx.map(function(padding)
return UDim.new(0, padding)
end);
})
end
--[=[
Computes a reasonable dialog padding for a given absolute screen size
@param screenAbsoluteSize Vector2
@return number
]=]
function GameScalingUtils.getDialogPadding(screenAbsoluteSize)
assert(typeof(screenAbsoluteSize) == "Vector2", "Bad screenAbsoluteSize")
local smallestAxis = math.min(screenAbsoluteSize.x, screenAbsoluteSize.y)
if smallestAxis <= 300 then
return 5
elseif smallestAxis <= 500 then
return 10
elseif smallestAxis <= 700 then
return 25
else
return 50
end
end
return GameScalingUtils