@rbxts/vfx-forge 2.2.2-ts.1
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/forge-vfx/effects/beam.luau +312 -0
- package/out/forge-vfx/effects/bezier.luau +392 -0
- package/out/forge-vfx/effects/camera_shake.luau +200 -0
- package/out/forge-vfx/effects/lightning.luau +1183 -0
- package/out/forge-vfx/effects/mesh.luau +466 -0
- package/out/forge-vfx/effects/particle.luau +64 -0
- package/out/forge-vfx/effects/randomizer.luau +110 -0
- package/out/forge-vfx/effects/screen.luau +61 -0
- package/out/forge-vfx/effects/shockwave_debris.luau +277 -0
- package/out/forge-vfx/effects/shockwave_line.luau +356 -0
- package/out/forge-vfx/effects/shockwave_ring.luau +252 -0
- package/out/forge-vfx/effects/sound.luau +311 -0
- package/out/forge-vfx/effects/spin.luau +88 -0
- package/out/forge-vfx/effects/tweener.luau +122 -0
- package/out/forge-vfx/emitters.luau +387 -0
- package/out/forge-vfx/index.d.ts +356 -0
- package/out/forge-vfx/init.luau +279 -0
- package/out/forge-vfx/mod/attributes.luau +227 -0
- package/out/forge-vfx/mod/color/Oklab.luau +93 -0
- package/out/forge-vfx/mod/color/sRGB.luau +71 -0
- package/out/forge-vfx/mod/common/bezier.luau +372 -0
- package/out/forge-vfx/mod/common/flipbook.luau +102 -0
- package/out/forge-vfx/mod/lerp.luau +210 -0
- package/out/forge-vfx/mod/logger.luau +20 -0
- package/out/forge-vfx/mod/shape.luau +207 -0
- package/out/forge-vfx/mod/tween.luau +161 -0
- package/out/forge-vfx/mod/utility.luau +707 -0
- package/out/forge-vfx/obj/Bezier.luau +268 -0
- package/out/forge-vfx/obj/ObjectCache.luau +289 -0
- package/out/forge-vfx/services/caches.luau +62 -0
- package/out/forge-vfx/services/effects.luau +234 -0
- package/out/forge-vfx/services/enabled_effects.luau +120 -0
- package/out/forge-vfx/services/texture_loader.luau +174 -0
- package/out/forge-vfx/types.luau +43 -0
- package/out/index.d.ts +3 -0
- package/out/init.luau +5 -0
- package/out/shake.d.ts +2 -0
- package/out/shake.luau +6 -0
- package/out/tsconfig.tsbuildinfo +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
local TS = _G[script.Parent.Parent.Parent]
|
|
2
|
+
local types = require(script.Parent.Parent.types)
|
|
3
|
+
local logger = require(script.Parent.Parent.mod.logger)
|
|
4
|
+
local utility = require(script.Parent.Parent.mod.utility)
|
|
5
|
+
local emitters = require(script.Parent.Parent.emitters)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
local EffectSelectors = table.concat({
|
|
9
|
+
"Beam",
|
|
10
|
+
"Trail",
|
|
11
|
+
"Sound",
|
|
12
|
+
"ParticleEmitter",
|
|
13
|
+
|
|
14
|
+
-- Beziers
|
|
15
|
+
`.{utility.BEZIER_TAG}`,
|
|
16
|
+
|
|
17
|
+
-- Lightning bolts
|
|
18
|
+
`.{utility.LIGHTNING_TAG}`,
|
|
19
|
+
|
|
20
|
+
-- Spin models
|
|
21
|
+
"Model",
|
|
22
|
+
|
|
23
|
+
-- Camera shakes
|
|
24
|
+
"RayValue",
|
|
25
|
+
|
|
26
|
+
-- Screen effects
|
|
27
|
+
"BasePart[$Enabled=true]",
|
|
28
|
+
|
|
29
|
+
-- Shockwave effects
|
|
30
|
+
"#Rings > Part",
|
|
31
|
+
"#Lines > Part",
|
|
32
|
+
"#Debris > Part",
|
|
33
|
+
}, ",")
|
|
34
|
+
|
|
35
|
+
local effects = {}
|
|
36
|
+
|
|
37
|
+
local api_ref: types.Api?
|
|
38
|
+
|
|
39
|
+
function effects.init(api: types.Api)
|
|
40
|
+
api_ref = api
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
function effects.deinit()
|
|
44
|
+
api_ref = nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
function effects.emit(depth: number, ...: Instance): types.EmitEnv
|
|
48
|
+
if not api_ref or not api_ref.setup then
|
|
49
|
+
logger.error("effects service not initialized")
|
|
50
|
+
return { Finished = TS.Promise.resolve() }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
local sharedUncMap: { [Instance]: number } = {}
|
|
54
|
+
local sharedRefMap: { [Instance]: Instance } = {}
|
|
55
|
+
|
|
56
|
+
local legacyScale = 1
|
|
57
|
+
|
|
58
|
+
local list = { ... }
|
|
59
|
+
local rootPromises = {}
|
|
60
|
+
|
|
61
|
+
local function queryAndEmitDescendants(obj: Instance, baseDepth: number): { any }
|
|
62
|
+
local allDesc = obj:QueryDescendants(EffectSelectors)
|
|
63
|
+
local totalDesc = #allDesc
|
|
64
|
+
|
|
65
|
+
if totalDesc == 0 then
|
|
66
|
+
return {}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
local promises = table.create(totalDesc)
|
|
70
|
+
|
|
71
|
+
local skipCache: { [Instance]: boolean } = {}
|
|
72
|
+
local depthCache: { [Instance]: number } = {}
|
|
73
|
+
|
|
74
|
+
skipCache[obj] = false
|
|
75
|
+
depthCache[obj] = baseDepth
|
|
76
|
+
|
|
77
|
+
for _, desc in allDesc do
|
|
78
|
+
local ancestors = {}
|
|
79
|
+
local current = desc.Parent
|
|
80
|
+
|
|
81
|
+
while depthCache[current] == nil do
|
|
82
|
+
table.insert(ancestors, current)
|
|
83
|
+
current = current.Parent
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
local shouldSkip = skipCache[current]
|
|
87
|
+
local currentDepth = depthCache[current]
|
|
88
|
+
|
|
89
|
+
for i = #ancestors, 1, -1 do
|
|
90
|
+
local ancestor = ancestors[i]
|
|
91
|
+
|
|
92
|
+
currentDepth += 1
|
|
93
|
+
depthCache[ancestor] = currentDepth
|
|
94
|
+
|
|
95
|
+
if not shouldSkip then
|
|
96
|
+
shouldSkip = utility.shouldSkipNested(ancestor) or ancestor:HasTag(utility.EMIT_EXCLUDE_TAG)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
skipCache[ancestor] = shouldSkip
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
if not shouldSkip then
|
|
103
|
+
table.insert(
|
|
104
|
+
promises,
|
|
105
|
+
utility.createEmitPromise(effects, desc, depthCache[desc.Parent], function(scope)
|
|
106
|
+
emitters.dispatch(desc, scope, sharedUncMap, sharedRefMap, api_ref.caches.shared_part, legacyScale)
|
|
107
|
+
end)
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
return promises
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
for _, obj in list do
|
|
116
|
+
-- screen effects
|
|
117
|
+
if
|
|
118
|
+
obj:IsA("BasePart")
|
|
119
|
+
and obj:GetAttribute("Enabled")
|
|
120
|
+
and not utility.findFirstClassWithTag(obj, "Attachment", utility.SHOCKWAVE_TAG)
|
|
121
|
+
then
|
|
122
|
+
if utility.lock(obj) then
|
|
123
|
+
continue
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
local anc = obj:FindFirstAncestorOfClass("Model")
|
|
127
|
+
|
|
128
|
+
if anc and not utility.isSpinModelStatic(anc) then
|
|
129
|
+
continue
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
local lockThread = coroutine.running()
|
|
133
|
+
|
|
134
|
+
local scope = {}
|
|
135
|
+
scope.depth = depth
|
|
136
|
+
scope.effects = effects
|
|
137
|
+
|
|
138
|
+
local await = emitters.screen(obj, scope)
|
|
139
|
+
|
|
140
|
+
if await then
|
|
141
|
+
local innerPromises = queryAndEmitDescendants(obj, depth + 1)
|
|
142
|
+
|
|
143
|
+
if #innerPromises > 0 then
|
|
144
|
+
table.insert(
|
|
145
|
+
rootPromises,
|
|
146
|
+
TS.Promise.all(innerPromises):finally(function()
|
|
147
|
+
utility.unlock(obj, lockThread)
|
|
148
|
+
utility.cleanupScope(scope)
|
|
149
|
+
end)
|
|
150
|
+
)
|
|
151
|
+
else
|
|
152
|
+
utility.unlock(obj, lockThread)
|
|
153
|
+
utility.cleanupScope(scope)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
-- other effects
|
|
157
|
+
else
|
|
158
|
+
table.insert(
|
|
159
|
+
rootPromises,
|
|
160
|
+
utility.createEmitPromise(effects, obj, depth, function(scope)
|
|
161
|
+
emitters.dispatch(obj, scope, sharedUncMap, sharedRefMap, api_ref.caches.shared_part, legacyScale)
|
|
162
|
+
end)
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if not utility.shouldSkipNested(obj) then
|
|
166
|
+
local descendantPromises = queryAndEmitDescendants(obj, depth + 1)
|
|
167
|
+
|
|
168
|
+
for _, promise in descendantPromises do
|
|
169
|
+
table.insert(rootPromises, promise)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
local env = {
|
|
176
|
+
Finished = TS.Promise.all(rootPromises),
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return env
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
function effects.prepareEmitFolder(obj: Instance, folderName: string, scope: types.scope): Folder?
|
|
183
|
+
local folder = obj:FindFirstChild(folderName)
|
|
184
|
+
|
|
185
|
+
if folder and folder:IsA("Folder") then
|
|
186
|
+
folder.Parent = nil
|
|
187
|
+
table.insert(scope, folder)
|
|
188
|
+
return folder
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
return nil
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
function effects.prepareEmitOnFinish(obj: Instance, scope: types.scope): Folder?
|
|
195
|
+
return effects.prepareEmitFolder(obj, "EmitOnFinish", scope)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
function effects.emitNested(part: Instance, depth: number): types.EmitEnv
|
|
199
|
+
if not api_ref or not api_ref.setup then
|
|
200
|
+
return { Finished = TS.Promise.resolve() }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
local children = part:GetChildren()
|
|
204
|
+
|
|
205
|
+
if #children == 0 then
|
|
206
|
+
return { Finished = TS.Promise.resolve() }
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
return effects.emit(depth, table.unpack(children))
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
function effects.emitFromFolder(folder: Folder?, targetParent: Instance, depth: number): types.EmitEnv
|
|
213
|
+
if not folder then
|
|
214
|
+
return { Finished = TS.Promise.resolve() }
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
local children = folder:GetChildren()
|
|
218
|
+
|
|
219
|
+
if #children == 0 then
|
|
220
|
+
return { Finished = TS.Promise.resolve() }
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
for _, child in children do
|
|
224
|
+
child.Parent = targetParent
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
return effects.emit(depth, table.unpack(children))
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
function effects.emitOnFinish(emitOnFinish: Folder?, targetParent: Instance, depth: number): types.EmitEnv
|
|
231
|
+
return effects.emitFromFolder(emitOnFinish, targetParent, depth)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
return effects
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
local RunService = game:GetService("RunService")
|
|
2
|
+
local CollectionService = game:GetService("CollectionService")
|
|
3
|
+
|
|
4
|
+
local attr = require(script.Parent.Parent.mod.attributes)
|
|
5
|
+
local types = require(script.Parent.Parent.types)
|
|
6
|
+
local utility = require(script.Parent.Parent.mod.utility)
|
|
7
|
+
local emitters = require(script.Parent.Parent.emitters)
|
|
8
|
+
|
|
9
|
+
local enabled_effects = {}
|
|
10
|
+
|
|
11
|
+
function enabled_effects.init(scope: types.scope, shared_part_cache: any, effects_service: any)
|
|
12
|
+
local enabledScopes = {}
|
|
13
|
+
|
|
14
|
+
local function removeEnabledEffect(obj: Instance)
|
|
15
|
+
local effectScope = enabledScopes[obj]
|
|
16
|
+
|
|
17
|
+
if effectScope then
|
|
18
|
+
utility.cleanupScope(effectScope)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
enabledScopes[obj] = nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
local function addEnabledEffect(obj: Instance)
|
|
25
|
+
-- Find which effect type this object is
|
|
26
|
+
local effectConfig
|
|
27
|
+
|
|
28
|
+
for _, config in emitters.enabled_registry do
|
|
29
|
+
if config.check(obj) then
|
|
30
|
+
effectConfig = config
|
|
31
|
+
break
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if not effectConfig then
|
|
36
|
+
return
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
local tempScope = {} :: { any }
|
|
40
|
+
local preEffectScope = {} :: { any }
|
|
41
|
+
|
|
42
|
+
table.insert(preEffectScope, tempScope)
|
|
43
|
+
|
|
44
|
+
enabledScopes[obj] = preEffectScope
|
|
45
|
+
|
|
46
|
+
table.insert(
|
|
47
|
+
preEffectScope,
|
|
48
|
+
obj.AncestryChanged:Connect(function()
|
|
49
|
+
if obj:IsDescendantOf(workspace) or (obj.Parent and obj.Parent:HasTag("AllowEmitting")) then
|
|
50
|
+
if not enabledScopes[obj] then
|
|
51
|
+
addEnabledEffect(obj)
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
removeEnabledEffect(obj)
|
|
55
|
+
end
|
|
56
|
+
end)
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
if not obj:IsDescendantOf(workspace) and (if obj.Parent then not obj.Parent:HasTag("AllowEmitting") else false) then
|
|
60
|
+
return
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
local function onEnabled(enabled: boolean?)
|
|
64
|
+
if enabled == nil then
|
|
65
|
+
enabled = attr.get(obj, "Enabled", true)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if enabled then
|
|
69
|
+
local last = 0
|
|
70
|
+
|
|
71
|
+
table.insert(
|
|
72
|
+
tempScope,
|
|
73
|
+
RunService.RenderStepped:Connect(function()
|
|
74
|
+
local rate = attr.get(obj, "Rate", 5)
|
|
75
|
+
local speed = attr.getState(obj, "SpeedOverride", 1)
|
|
76
|
+
|
|
77
|
+
if speed == 0 then
|
|
78
|
+
return
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if os.clock() - last <= (1 / rate) / speed then
|
|
82
|
+
return
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
last = os.clock()
|
|
86
|
+
|
|
87
|
+
local emitScope = {}
|
|
88
|
+
emitScope.depth = 0
|
|
89
|
+
emitScope.effects = effects_service
|
|
90
|
+
|
|
91
|
+
effectConfig.emit(obj, emitScope, shared_part_cache)
|
|
92
|
+
|
|
93
|
+
utility.cleanupScope(emitScope)
|
|
94
|
+
end)
|
|
95
|
+
)
|
|
96
|
+
else
|
|
97
|
+
utility.cleanupScope(tempScope)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
table.insert(preEffectScope, attr.hook(obj, "Enabled", onEnabled))
|
|
102
|
+
|
|
103
|
+
onEnabled()
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
for _, obj in CollectionService:GetTagged(utility.ENABLED_VFX_TAG) do
|
|
107
|
+
addEnabledEffect(obj)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
CollectionService:GetInstanceAddedSignal(utility.ENABLED_VFX_TAG):Connect(addEnabledEffect)
|
|
111
|
+
CollectionService:GetInstanceRemovedSignal(utility.ENABLED_VFX_TAG):Connect(removeEnabledEffect)
|
|
112
|
+
|
|
113
|
+
table.insert(scope, function()
|
|
114
|
+
for _, effectScope in enabledScopes do
|
|
115
|
+
utility.cleanupScope(effectScope)
|
|
116
|
+
end
|
|
117
|
+
end)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
return enabled_effects
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
local CollectionService = game:GetService("CollectionService")
|
|
2
|
+
|
|
3
|
+
local ObjectCache = require(script.Parent.Parent.obj.ObjectCache)
|
|
4
|
+
|
|
5
|
+
local types = require(script.Parent.Parent.types)
|
|
6
|
+
local utility = require(script.Parent.Parent.mod.utility)
|
|
7
|
+
local flipbook_common = require(script.Parent.Parent.mod.common.flipbook)
|
|
8
|
+
|
|
9
|
+
local texture_loader = {}
|
|
10
|
+
|
|
11
|
+
function texture_loader.init(scope: types.scope)
|
|
12
|
+
local template = Instance.new("Decal")
|
|
13
|
+
|
|
14
|
+
local parent = Instance.new("Part")
|
|
15
|
+
parent.Name = "DO_NOT_REMOVE_ForgeTextureCache"
|
|
16
|
+
parent.Transparency = 1
|
|
17
|
+
parent.Size = Vector3.zero
|
|
18
|
+
parent.Archivable = false
|
|
19
|
+
parent.Anchored = true
|
|
20
|
+
parent.CanCollide = false
|
|
21
|
+
parent.CanQuery = false
|
|
22
|
+
parent.Locked = true
|
|
23
|
+
parent.Parent = workspace.Terrain
|
|
24
|
+
|
|
25
|
+
utility.protectParent(scope, parent)
|
|
26
|
+
|
|
27
|
+
local texture_cache = ObjectCache.new(template, parent, {
|
|
28
|
+
size = 360,
|
|
29
|
+
on_free = function(item)
|
|
30
|
+
item.value.Texture = ""
|
|
31
|
+
end,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
local preloadScopes = {}
|
|
35
|
+
|
|
36
|
+
local function createLoader(
|
|
37
|
+
ref: Instance,
|
|
38
|
+
collectTextures: (add: (tex: string) -> ()) -> (),
|
|
39
|
+
conns: ((run: () -> ()) -> { RBXScriptConnection })?
|
|
40
|
+
)
|
|
41
|
+
local loadScope = {} :: { any }
|
|
42
|
+
local snapshotScope = {} :: { any }
|
|
43
|
+
|
|
44
|
+
table.insert(loadScope, snapshotScope)
|
|
45
|
+
|
|
46
|
+
local function refresh()
|
|
47
|
+
utility.cleanupScope(snapshotScope)
|
|
48
|
+
|
|
49
|
+
local function add(tex: string)
|
|
50
|
+
if tex == "" then
|
|
51
|
+
return
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
local d = texture_cache:get(tex)
|
|
55
|
+
d.Texture = tex
|
|
56
|
+
|
|
57
|
+
table.insert(snapshotScope, function()
|
|
58
|
+
texture_cache:free(tex)
|
|
59
|
+
end)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
collectTextures(add)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
refresh()
|
|
66
|
+
|
|
67
|
+
if utility.PLUGIN_CONTEXT and conns then
|
|
68
|
+
local run = utility.reboundfn(1, refresh)
|
|
69
|
+
|
|
70
|
+
for _, connection in conns(run) do
|
|
71
|
+
table.insert(loadScope, connection)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
preloadScopes[ref] = loadScope
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
local function loadTextures(ref: Instance)
|
|
79
|
+
if ref:IsDescendantOf(workspace.Terrain) then
|
|
80
|
+
return
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
if utility.isMeshVFX(ref) then
|
|
84
|
+
local obj = ref:FindFirstChild("Start")
|
|
85
|
+
|
|
86
|
+
if not obj or not obj:IsA("BasePart") then
|
|
87
|
+
return
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
createLoader(ref, function(add)
|
|
91
|
+
local decals, flipbooks = utility.getMeshDecals(ref :: Model, obj)
|
|
92
|
+
|
|
93
|
+
for _, d in decals do
|
|
94
|
+
add(typeof(d) ~= "string" and d.Texture or d)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
for v, list in flipbooks do
|
|
98
|
+
local prefix = flipbook_common.getTexturePrefix(ref)
|
|
99
|
+
|
|
100
|
+
for _, id in list do
|
|
101
|
+
add(`{prefix}{id}`)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end, function(run)
|
|
105
|
+
return {
|
|
106
|
+
obj.DescendantAdded:Connect(run),
|
|
107
|
+
obj.DescendantRemoving:Connect(run),
|
|
108
|
+
}
|
|
109
|
+
end)
|
|
110
|
+
elseif ref:IsA("Beam") then
|
|
111
|
+
createLoader(ref, function(add)
|
|
112
|
+
add(ref.Texture)
|
|
113
|
+
|
|
114
|
+
local flipbook = flipbook_common.getFlipbookData(ref)
|
|
115
|
+
|
|
116
|
+
if flipbook then
|
|
117
|
+
local prefix = flipbook_common.getTexturePrefix(ref)
|
|
118
|
+
|
|
119
|
+
for _, id in flipbook do
|
|
120
|
+
add(`{prefix}{id}`)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end, function(run)
|
|
124
|
+
return {
|
|
125
|
+
ref:GetPropertyChangedSignal("Texture"):Connect(run),
|
|
126
|
+
ref.AttributeChanged:Connect(run),
|
|
127
|
+
}
|
|
128
|
+
end)
|
|
129
|
+
else
|
|
130
|
+
createLoader(ref, function(add)
|
|
131
|
+
local function check(obj: Instance)
|
|
132
|
+
if obj:IsA("ParticleEmitter") then
|
|
133
|
+
add(obj.Texture)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
check(ref)
|
|
138
|
+
|
|
139
|
+
for _, obj in ref:GetDescendants() do
|
|
140
|
+
check(obj)
|
|
141
|
+
end
|
|
142
|
+
end, function(run)
|
|
143
|
+
return {
|
|
144
|
+
ref.DescendantAdded:Connect(run),
|
|
145
|
+
ref.DescendantRemoving:Connect(run),
|
|
146
|
+
}
|
|
147
|
+
end)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
for _, ref in CollectionService:GetTagged(utility.TEXTURE_LOAD_TAG) do
|
|
152
|
+
loadTextures(ref)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
CollectionService:GetInstanceAddedSignal(utility.TEXTURE_LOAD_TAG):Connect(loadTextures)
|
|
156
|
+
CollectionService:GetInstanceRemovedSignal(utility.TEXTURE_LOAD_TAG):Connect(function(ref)
|
|
157
|
+
local loadScope = preloadScopes[ref]
|
|
158
|
+
|
|
159
|
+
if loadScope then
|
|
160
|
+
utility.cleanupScope(loadScope)
|
|
161
|
+
preloadScopes[ref] = nil
|
|
162
|
+
end
|
|
163
|
+
end)
|
|
164
|
+
|
|
165
|
+
table.insert(scope, function()
|
|
166
|
+
texture_cache:destroy()
|
|
167
|
+
|
|
168
|
+
for _, loadScope in preloadScopes do
|
|
169
|
+
utility.cleanupScope(loadScope)
|
|
170
|
+
end
|
|
171
|
+
end)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
return texture_loader
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
local TS = _G[script.Parent.Parent]
|
|
2
|
+
local ObjectCache = require(script.Parent.obj.ObjectCache)
|
|
3
|
+
|
|
4
|
+
export type scope = { any } & {
|
|
5
|
+
depth: number,
|
|
6
|
+
effects: EffectsService,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type EmitEnv = {
|
|
10
|
+
Finished: typeof(TS.Promise.resolve()),
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type ApiCaches = {
|
|
14
|
+
shared_part: ObjectCache.ObjectCache,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type EffectsService = {
|
|
18
|
+
init: (api: Api) -> (),
|
|
19
|
+
deinit: () -> (),
|
|
20
|
+
|
|
21
|
+
emit: (depth: number,...Instance) -> EmitEnv,
|
|
22
|
+
emitNested: (part: Instance, depth: number) -> EmitEnv,
|
|
23
|
+
emitFromFolder: (folder: Folder?, targetParent: Instance, depth: number) -> EmitEnv,
|
|
24
|
+
emitOnFinish: (emitOnFinish: Folder?, targetParent: Instance, depth: number) -> EmitEnv,
|
|
25
|
+
|
|
26
|
+
prepareEmitFolder: (obj: Instance, folderName: string, scope: scope) -> Folder?,
|
|
27
|
+
prepareEmitOnFinish: (obj: Instance, scope: scope) -> Folder?,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type Api = {
|
|
31
|
+
setup: boolean,
|
|
32
|
+
|
|
33
|
+
scope: { unknown },
|
|
34
|
+
caches: ApiCaches,
|
|
35
|
+
|
|
36
|
+
init: (params: any?) -> (),
|
|
37
|
+
deinit: () -> (),
|
|
38
|
+
|
|
39
|
+
emit: (vfxOrScale: number | Instance,...Instance) -> EmitEnv,
|
|
40
|
+
emitWithDepth: (depth: number,...Instance) -> EmitEnv,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {}
|
package/out/index.d.ts
ADDED
package/out/init.luau
ADDED
package/out/shake.d.ts
ADDED
package/out/shake.luau
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"program":{"fileNames":["../node_modules/.pnpm/@rbxutil+shake@1.1.0/node_modules/@rbxutil/shake/index.d.ts","../src/shake.ts","../src/forge-vfx/index.d.ts","../src/index.ts","../node_modules/.pnpm/@rbxts+types@1.0.912/node_modules/@rbxts/types/include/generated/enums.d.ts","../node_modules/.pnpm/@rbxts+types@1.0.912/node_modules/@rbxts/types/include/generated/None.d.ts","../node_modules/.pnpm/@rbxts+types@1.0.912/node_modules/@rbxts/types/include/lua.d.ts","../node_modules/.pnpm/@rbxts+types@1.0.912/node_modules/@rbxts/types/include/macro_math.d.ts","../node_modules/.pnpm/@rbxts+types@1.0.912/node_modules/@rbxts/types/include/roblox.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/Array.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/callMacros.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/Iterable.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/Map.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/Promise.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/Set.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/String.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/Symbol.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/typeUtils.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/eslintIgnore.d.ts","../node_modules/.pnpm/@rbxts+compiler-types@3.0.0-types.0/node_modules/@rbxts/compiler-types/types/core.d.ts"],"fileInfos":[{"version":"ca61c369380ae62f35f853f74328b9cfe996ead598a3262cdbafbda2af89f58b","signature":false},{"version":"cbe78cd1c02149af16f4ab6bf5cac88566c4785121c7037c926c5e719cbe9eb5","signature":false},{"version":"f76a8520e9fd930fabef4e08c764fe0fe5f371689a360a9b5074a781fd093df0","signature":false},{"version":"089ad8ad349eadb7ea239de39a33b40923b28336a66b9852d4c633bb613bc367","signature":false},{"version":"b894746d2fad9eb66a5d910dc02975890ec2be47f63bf76272ecad5222ddf59b","signature":false,"affectsGlobalScope":true},{"version":"78119391a6663e30a44c3423a18eae406994ac151c3c6c06c9208929fe53939c","signature":false,"affectsGlobalScope":true},{"version":"3dd752ad3f31ffe145169124ffb797f1508a1056cf434ef9c21d2deda31cdd2e","signature":false,"affectsGlobalScope":true},{"version":"6743ea019a68ca9a1f823b29bb3a96ccbfb85a21ad04399dcd3d1a3ad055be0e","signature":false,"affectsGlobalScope":true},{"version":"f6ecdcdc6bd04ac142c41ba97ecc3a4691ee69354c2e34c6e453b4b918601ef5","signature":false,"affectsGlobalScope":true},{"version":"bdcbc6cfb00c9e7a55f19dc4d3fb383f35b6398fc4ca90da69c5e98e6fab7419","signature":false,"affectsGlobalScope":true},{"version":"e77eae92a8b9e0788ace926d3a0a7e8333c5229f62f16d806a4200be1054a195","signature":false,"affectsGlobalScope":true},{"version":"5d6b3a91c4181c3e36d5316882813f200e3e5e4fdc5061c88e74bdf3b0d56368","signature":false,"affectsGlobalScope":true},{"version":"2a3185f41eeb83ae859d89f6d89e0957e8d82f6cd5f11abb6a23821cb84a1b8a","signature":false,"affectsGlobalScope":true},{"version":"003ed63e8912f921b1754794fd6aa89e9444fb9d8d64001e11decad16be7d9de","signature":false,"affectsGlobalScope":true},{"version":"e0fb3b752bbdfb9f8bbf39bf24bb6d8e0d34f37ae7d2dfc7a4f27dfcdce147f1","signature":false,"affectsGlobalScope":true},{"version":"e15f401bce6a2302ae6c44299996d121063f21f984b2bef50540ff4b84f18653","signature":false,"affectsGlobalScope":true},{"version":"373bd4da5c2c86c487207e1cad00eb467b70d59d2682a8078e48f7a8e3b6ad0c","signature":false,"affectsGlobalScope":true},{"version":"38dca44de00fb527935e5f9168a18f73fa2e0e482d932a7fc87dda28b12d8547","signature":false,"affectsGlobalScope":true},{"version":"fbe3fe3565bba1ae3430c1d182560ddce591f8945391c59ca4107440b04aa2e4","signature":false,"affectsGlobalScope":true},{"version":"24cec90bd9a41b352abeb4ff6c1a0967739892bcaca7edc4470f543b4820e1a7","signature":false,"affectsGlobalScope":true}],"root":[[2,4]],"options":{"allowSyntheticDefaultImports":true,"allowUnreachableCode":false,"declaration":true,"downlevelIteration":true,"exactOptionalPropertyTypes":true,"experimentalDecorators":true,"jsx":2,"module":1,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noImplicitReturns":true,"noPropertyAccessFromIndexSignature":true,"noUncheckedIndexedAccess":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"strict":true,"target":99,"tsBuildInfoFile":"./tsconfig.tsbuildinfo","useUnknownInCatchVariables":true},"fileIdsList":[[9],[9,10,11,12,13,14,15,16,17,18,19],[5,9],[6,20],[5,6,7,8,20],[2,3],[1]],"referencedMap":[[10,1],[12,1],[13,1],[14,1],[15,1],[16,1],[17,1],[11,1],[20,2],[19,1],[18,1],[6,3],[5,1],[7,4],[9,5],[4,6],[2,7]],"semanticDiagnosticsPerFile":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]},"version":"5.5.3"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rbxts/vfx-forge",
|
|
3
|
+
"version": "2.2.2-ts.1",
|
|
4
|
+
"description": "The official emit module from the VFX Forge plugin used to emit visual effects in-game.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"rbxts",
|
|
7
|
+
"roblox",
|
|
8
|
+
"vfx",
|
|
9
|
+
"effects",
|
|
10
|
+
"particles",
|
|
11
|
+
"forge",
|
|
12
|
+
"plugin"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://docs.zilibobi.dev/vfx-forge/",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/christopher-buss/forge-vfx/issues"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/christopher-buss/forge-vfx.git"
|
|
21
|
+
},
|
|
22
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
23
|
+
"author": "zilibobi",
|
|
24
|
+
"contributors": [
|
|
25
|
+
{
|
|
26
|
+
"name": "Christopher Buss",
|
|
27
|
+
"email": "christopher.buss@pm.me",
|
|
28
|
+
"url": "https://github.com/christopher-buss"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"type": "module",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./out/index.d.ts",
|
|
35
|
+
"import": "./out/init.luau",
|
|
36
|
+
"default": "./out/init.luau"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"types": "out/index.d.ts",
|
|
40
|
+
"files": [
|
|
41
|
+
"out"
|
|
42
|
+
],
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@rbxutil/shake": "^1.1.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@isentinel/eslint-config": "^5.0.0-beta.8",
|
|
48
|
+
"@isentinel/tsconfig": "^1.2.0",
|
|
49
|
+
"@rbxts/compiler-types": "3.0.0-types.0",
|
|
50
|
+
"@rbxts/types": "^1.0.903",
|
|
51
|
+
"bumpp": "^10.4.0",
|
|
52
|
+
"eslint": "^9.39.2",
|
|
53
|
+
"jiti": "^2.6.1",
|
|
54
|
+
"roblox-ts": "^3.0.0",
|
|
55
|
+
"typescript": "^5.9.3"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "lune run process",
|
|
59
|
+
"lint": "eslint --cache",
|
|
60
|
+
"lint:ci": "eslint --cache --cache-strategy content",
|
|
61
|
+
"release": "bumpp"
|
|
62
|
+
}
|
|
63
|
+
}
|