@rbxts/vfx-forge 2.2.2
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/LICENSE +82 -0
- package/README.md +39 -0
- package/out/effects/beam.luau +312 -0
- package/out/effects/bezier.luau +392 -0
- package/out/effects/camera_shake.luau +200 -0
- package/out/effects/lightning.luau +1183 -0
- package/out/effects/mesh.luau +466 -0
- package/out/effects/particle.luau +64 -0
- package/out/effects/randomizer.luau +110 -0
- package/out/effects/screen.luau +61 -0
- package/out/effects/shockwave_debris.luau +277 -0
- package/out/effects/shockwave_line.luau +356 -0
- package/out/effects/shockwave_ring.luau +252 -0
- package/out/effects/sound.luau +311 -0
- package/out/effects/spin.luau +88 -0
- package/out/effects/tweener.luau +122 -0
- package/out/emitters.luau +387 -0
- package/out/index.d.ts +341 -0
- package/out/init.luau +279 -0
- package/out/mod/attributes.luau +227 -0
- package/out/mod/color/Oklab.luau +93 -0
- package/out/mod/color/sRGB.luau +71 -0
- package/out/mod/common/bezier.luau +372 -0
- package/out/mod/common/flipbook.luau +102 -0
- package/out/mod/lerp.luau +210 -0
- package/out/mod/logger.luau +20 -0
- package/out/mod/shape.luau +207 -0
- package/out/mod/tween.luau +161 -0
- package/out/mod/utility.luau +707 -0
- package/out/obj/Bezier.luau +268 -0
- package/out/obj/ObjectCache.luau +289 -0
- package/out/services/caches.luau +62 -0
- package/out/services/effects.luau +234 -0
- package/out/services/enabled_effects.luau +120 -0
- package/out/services/texture_loader.luau +174 -0
- package/out/tsconfig.tsbuildinfo +1 -0
- package/out/types.luau +43 -0
- package/package.json +63 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
local RunService = game:GetService("RunService")
|
|
2
|
+
|
|
3
|
+
local logger = require("./logger")
|
|
4
|
+
|
|
5
|
+
local IS_SERVER = RunService:IsServer()
|
|
6
|
+
local ATTR_CACHE_ID = "U"
|
|
7
|
+
|
|
8
|
+
type AttrCache = {
|
|
9
|
+
[number]: {
|
|
10
|
+
[string]: any,
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type AttrHooks = {
|
|
15
|
+
[Instance]: {
|
|
16
|
+
[string]: { (v: any) -> never },
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type RuntimeState = {
|
|
21
|
+
[Instance]: {
|
|
22
|
+
[string]: any,
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
local Cache: AttrCache = {}
|
|
27
|
+
local Hooks: AttrHooks = {}
|
|
28
|
+
local State: RuntimeState = {}
|
|
29
|
+
|
|
30
|
+
local LastRefId = 0
|
|
31
|
+
|
|
32
|
+
local attr = {}
|
|
33
|
+
|
|
34
|
+
function attr.cache(obj: Instance)
|
|
35
|
+
local attributes = obj:GetAttributes()
|
|
36
|
+
|
|
37
|
+
if next(attributes) == nil then
|
|
38
|
+
return
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
LastRefId += 1
|
|
42
|
+
|
|
43
|
+
local id = LastRefId
|
|
44
|
+
local map = {}
|
|
45
|
+
|
|
46
|
+
for k, v in attributes do
|
|
47
|
+
if k == ATTR_CACHE_ID then
|
|
48
|
+
continue
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
map[k] = v
|
|
52
|
+
obj:SetAttribute(k, nil)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Cache[id] = map
|
|
56
|
+
|
|
57
|
+
obj:SetAttribute(ATTR_CACHE_ID, id)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
function attr.restore(obj: Instance)
|
|
61
|
+
local id = obj:GetAttribute(ATTR_CACHE_ID)
|
|
62
|
+
|
|
63
|
+
local cache = Cache[id]
|
|
64
|
+
|
|
65
|
+
if not cache then
|
|
66
|
+
logger.error(`{obj} with cache id '{id}' doesn't have any cached attributes`)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
for k, v in cache do
|
|
70
|
+
obj:SetAttribute(k, v)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
obj:SetAttribute(ATTR_CACHE_ID, nil)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
function attr.get<T>(obj: Instance, key: string, default: T, soft: boolean?, validate: ((v: unknown) -> T)?): T
|
|
77
|
+
local id = obj:GetAttribute(ATTR_CACHE_ID)
|
|
78
|
+
|
|
79
|
+
local cache = Cache[id]
|
|
80
|
+
local value = cache and cache[key]
|
|
81
|
+
|
|
82
|
+
if value ~= nil then
|
|
83
|
+
return if validate then validate(value) else if value == nil then default else value
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
value = obj:GetAttribute(key)
|
|
87
|
+
|
|
88
|
+
if validate then
|
|
89
|
+
value = validate(value)
|
|
90
|
+
elseif value == nil then
|
|
91
|
+
value = default
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if not soft and IS_SERVER then
|
|
95
|
+
obj:SetAttribute(key, value)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
return value
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
function attr.getRange(obj: Instance, key: string, default: NumberRange, clamp: NumberRange?, soft: boolean?)
|
|
102
|
+
return attr.get(obj, key, default, soft, function(v)
|
|
103
|
+
if typeof(v) ~= "NumberRange" then
|
|
104
|
+
return default
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
if clamp then
|
|
108
|
+
-- stylua: ignore
|
|
109
|
+
return NumberRange.new(
|
|
110
|
+
math.clamp(v.Min, clamp.Min, clamp.Max),
|
|
111
|
+
math.clamp(v.Max, clamp.Min, clamp.Max)
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
return v
|
|
116
|
+
end)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
function attr.getEnum<T>(obj: Instance, key: string, default: T, enums: { T }, soft: boolean?): T
|
|
120
|
+
return attr.get(obj, key, default, soft, function(v)
|
|
121
|
+
if v == nil or not table.find(enums, v) then
|
|
122
|
+
return default
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
return v
|
|
126
|
+
end)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
function attr.set<T>(obj: Instance, key: string, value: T)
|
|
130
|
+
local id = obj:GetAttribute(ATTR_CACHE_ID)
|
|
131
|
+
|
|
132
|
+
local cache = Cache[id]
|
|
133
|
+
|
|
134
|
+
if cache then
|
|
135
|
+
cache[key] = value
|
|
136
|
+
else
|
|
137
|
+
obj:SetAttribute(key, value)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
function attr.isCached(obj: Instance): boolean
|
|
142
|
+
return obj:GetAttribute(ATTR_CACHE_ID) ~= nil
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
function attr.getState<T>(obj: Instance, key: string, default: T): T
|
|
146
|
+
local state = State[obj]
|
|
147
|
+
local value = state and state[key]
|
|
148
|
+
|
|
149
|
+
return if value ~= nil then value else default
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
function attr.setState<T>(obj: Instance, key: string, value: T)
|
|
153
|
+
local state = State[obj]
|
|
154
|
+
|
|
155
|
+
if not state then
|
|
156
|
+
state = {}
|
|
157
|
+
State[obj] = state
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
state[key] = value
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
function attr.clearState(obj: Instance)
|
|
164
|
+
State[obj] = nil
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
function attr.trigger<T>(obj: Instance, key: string, value: T)
|
|
168
|
+
local hooks = Hooks[obj]
|
|
169
|
+
local callbacks = hooks and hooks[key]
|
|
170
|
+
|
|
171
|
+
if not callbacks then
|
|
172
|
+
return
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
for _, callback in callbacks do
|
|
176
|
+
callback(value)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
function attr.hook<T>(obj: Instance, key: string, callback: (v: T) -> never)
|
|
181
|
+
local hooks = Hooks[obj]
|
|
182
|
+
|
|
183
|
+
if not hooks then
|
|
184
|
+
hooks = {}
|
|
185
|
+
Hooks[obj] = hooks
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
local callbacks = hooks[key]
|
|
189
|
+
|
|
190
|
+
if not callbacks then
|
|
191
|
+
callbacks = {}
|
|
192
|
+
hooks[key] = callbacks
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
table.insert(callbacks, callback)
|
|
196
|
+
|
|
197
|
+
local connection
|
|
198
|
+
|
|
199
|
+
if not attr.isCached(obj) then
|
|
200
|
+
connection = obj:GetAttributeChangedSignal(key):Connect(function()
|
|
201
|
+
local value = obj:GetAttribute(key)
|
|
202
|
+
callback(value)
|
|
203
|
+
end)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
return function()
|
|
207
|
+
if connection then
|
|
208
|
+
connection:Disconnect()
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
local index = table.find(callbacks, callback)
|
|
212
|
+
|
|
213
|
+
if index then
|
|
214
|
+
table.remove(callbacks, index)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
if #callbacks == 0 then
|
|
218
|
+
hooks[key] = nil
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
if next(hooks) == nil then
|
|
222
|
+
Hooks[obj] = nil
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
return attr
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
--[[
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Daniel P H Fox
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
]]
|
|
24
|
+
|
|
25
|
+
--!strict
|
|
26
|
+
--!nolint LocalUnused
|
|
27
|
+
--!nolint LocalShadow
|
|
28
|
+
local task = nil -- Disable usage of Roblox's task scheduler
|
|
29
|
+
|
|
30
|
+
--[[
|
|
31
|
+
Provides functions for converting Color3s into Oklab space, for more
|
|
32
|
+
perceptually uniform colour blending.
|
|
33
|
+
|
|
34
|
+
See: https://bottosson.github.io/posts/oklab/
|
|
35
|
+
]]
|
|
36
|
+
|
|
37
|
+
local sRGB = require("@mod/color/sRGB")
|
|
38
|
+
|
|
39
|
+
local Oklab = {}
|
|
40
|
+
|
|
41
|
+
-- Converts a Color3 in linear RGB space to a Vector3 in Oklab space.
|
|
42
|
+
function Oklab.fromLinear(rgb: Color3): Vector3
|
|
43
|
+
local l = rgb.R * 0.4122214708 + rgb.G * 0.5363325363 + rgb.B * 0.0514459929
|
|
44
|
+
local m = rgb.R * 0.2119034982 + rgb.G * 0.6806995451 + rgb.B * 0.1073969566
|
|
45
|
+
local s = rgb.R * 0.0883024619 + rgb.G * 0.2817188376 + rgb.B * 0.6299787005
|
|
46
|
+
|
|
47
|
+
local lRoot = l ^ (1 / 3)
|
|
48
|
+
local mRoot = m ^ (1 / 3)
|
|
49
|
+
local sRoot = s ^ (1 / 3)
|
|
50
|
+
|
|
51
|
+
return Vector3.new(
|
|
52
|
+
lRoot * 0.2104542553 + mRoot * 0.7936177850 - sRoot * 0.0040720468,
|
|
53
|
+
lRoot * 1.9779984951 - mRoot * 2.4285922050 + sRoot * 0.4505937099,
|
|
54
|
+
lRoot * 0.0259040371 + mRoot * 0.7827717662 - sRoot * 0.8086757660
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
-- Converts a Color3 in sRGB space to a Vector3 in Oklab space.
|
|
59
|
+
function Oklab.fromSRGB(srgb: Color3): Vector3
|
|
60
|
+
return Oklab.fromLinear(sRGB.toLinear(srgb))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
-- Converts a Vector3 in Oklab space to a Color3 in linear RGB space.
|
|
64
|
+
-- The Color3 will be clamped by default unless specified otherwise.
|
|
65
|
+
function Oklab.toLinear(lab: Vector3, unclamped: boolean?): Color3
|
|
66
|
+
local lRoot = lab.X + lab.Y * 0.3963377774 + lab.Z * 0.2158037573
|
|
67
|
+
local mRoot = lab.X - lab.Y * 0.1055613458 - lab.Z * 0.0638541728
|
|
68
|
+
local sRoot = lab.X - lab.Y * 0.0894841775 - lab.Z * 1.2914855480
|
|
69
|
+
|
|
70
|
+
local l = lRoot ^ 3
|
|
71
|
+
local m = mRoot ^ 3
|
|
72
|
+
local s = sRoot ^ 3
|
|
73
|
+
|
|
74
|
+
local red = l * 4.0767416621 - m * 3.3077115913 + s * 0.2309699292
|
|
75
|
+
local green = l * -1.2684380046 + m * 2.6097574011 - s * 0.3413193965
|
|
76
|
+
local blue = l * -0.0041960863 - m * 0.7034186147 + s * 1.7076147010
|
|
77
|
+
|
|
78
|
+
if not unclamped then
|
|
79
|
+
red = math.clamp(red, 0, 1)
|
|
80
|
+
green = math.clamp(green, 0, 1)
|
|
81
|
+
blue = math.clamp(blue, 0, 1)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
return Color3.new(red, green, blue)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
-- Converts a Vector3 in Oklab space to a Color3 in sRGB space.
|
|
88
|
+
-- The Color3 will be clamped by default unless specified otherwise.
|
|
89
|
+
function Oklab.toSRGB(lab: Vector3, unclamped: boolean?): Color3
|
|
90
|
+
return sRGB.fromLinear(Oklab.toLinear(lab, unclamped))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
return Oklab
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
--[[
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Daniel P H Fox
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
]]
|
|
24
|
+
|
|
25
|
+
--!strict
|
|
26
|
+
--!nolint LocalUnused
|
|
27
|
+
--!nolint LocalShadow
|
|
28
|
+
local task = nil -- Disable usage of Roblox's task scheduler
|
|
29
|
+
|
|
30
|
+
--[[
|
|
31
|
+
Provides transformation functions for converting linear RGB values
|
|
32
|
+
into sRGB values.
|
|
33
|
+
|
|
34
|
+
RGB color channel transformations are outlined here:
|
|
35
|
+
https://bottosson.github.io/posts/colorwrong/#what-can-we-do%3F
|
|
36
|
+
]]
|
|
37
|
+
|
|
38
|
+
local sRGB = {}
|
|
39
|
+
|
|
40
|
+
-- Equivalent to f_inv. Takes a linear sRGB channel and returns
|
|
41
|
+
-- the sRGB channel
|
|
42
|
+
local function transform(channel: number): number
|
|
43
|
+
if channel < 0.04045 then
|
|
44
|
+
return channel / 12.92
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
return ((channel + 0.055) / 1.055) ^ 2.4
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
-- Equivalent to f. Takes an sRGB channel and returns
|
|
51
|
+
-- the linear sRGB channel
|
|
52
|
+
local function inverse(channel: number): number
|
|
53
|
+
if channel < 0.0031308 then
|
|
54
|
+
return 12.92 * channel
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
return (1.055 * channel ^ (1 / 2.4)) - 0.055
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
-- Uses a transformation to convert linear RGB into sRGB.
|
|
61
|
+
function sRGB.fromLinear(rgb: Color3): Color3
|
|
62
|
+
return Color3.new(inverse(rgb.R), inverse(rgb.G), inverse(rgb.B))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
-- Converts an sRGB into linear RGB using a
|
|
66
|
+
-- (The inverse of sRGB.fromLinear).
|
|
67
|
+
function sRGB.toLinear(srgb: Color3): Color3
|
|
68
|
+
return Color3.new(transform(srgb.R), transform(srgb.G), transform(srgb.B))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
return sRGB
|