@quenty/soundplayer 7.19.3 → 7.19.4-canary.11a5dcf.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 +20 -20
- package/src/Client/Loops/Layered/LayeredLoopedSoundPlayer.lua +25 -26
- package/src/Client/Loops/Layered/LayeredLoopedSoundPlayer.story.lua +76 -80
- package/src/Client/Loops/LoopedSoundPlayer.lua +65 -47
- package/src/Client/Loops/LoopedSoundPlayer.story.lua +55 -53
- package/src/Client/Loops/SimpleLoopedSoundPlayer.lua +7 -8
- package/src/Client/Loops/SimpleLoopedSoundPlayer.story.lua +25 -26
- package/src/Client/Schedule/SoundLoopScheduleUtils.lua +23 -15
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.19.4-canary.11a5dcf.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/soundplayer@7.19.3...@quenty/soundplayer@7.19.4-canary.11a5dcf.0) (2025-05-10)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add even more types ([b31717d](https://github.com/Quenty/NevermoreEngine/commit/b31717d8c9f7620c457f5018a2affa760a65334a))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## [7.19.3](https://github.com/Quenty/NevermoreEngine/compare/@quenty/soundplayer@7.19.2...@quenty/soundplayer@7.19.3) (2025-04-10)
|
|
7
18
|
|
|
8
19
|
**Note:** Version bump only for package @quenty/soundplayer
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/soundplayer",
|
|
3
|
-
"version": "7.19.
|
|
3
|
+
"version": "7.19.4-canary.11a5dcf.0",
|
|
4
4
|
"description": "Sound playback helper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -25,28 +25,28 @@
|
|
|
25
25
|
"Quenty"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@quenty/adorneeutils": "
|
|
29
|
-
"@quenty/baseobject": "
|
|
30
|
-
"@quenty/blend": "
|
|
31
|
-
"@quenty/brio": "
|
|
32
|
-
"@quenty/instanceutils": "
|
|
33
|
-
"@quenty/loader": "
|
|
34
|
-
"@quenty/maid": "
|
|
35
|
-
"@quenty/numberrangeutils": "
|
|
36
|
-
"@quenty/promise": "
|
|
37
|
-
"@quenty/promisemaid": "
|
|
38
|
-
"@quenty/randomutils": "
|
|
39
|
-
"@quenty/rbxasset": "
|
|
40
|
-
"@quenty/rx": "
|
|
41
|
-
"@quenty/signal": "
|
|
42
|
-
"@quenty/sounds": "
|
|
43
|
-
"@quenty/table": "
|
|
44
|
-
"@quenty/transitionmodel": "
|
|
45
|
-
"@quenty/valueobject": "
|
|
28
|
+
"@quenty/adorneeutils": "3.3.3",
|
|
29
|
+
"@quenty/baseobject": "10.8.4-canary.11a5dcf.0",
|
|
30
|
+
"@quenty/blend": "12.18.4-canary.11a5dcf.0",
|
|
31
|
+
"@quenty/brio": "14.17.4-canary.11a5dcf.0",
|
|
32
|
+
"@quenty/instanceutils": "13.17.4-canary.11a5dcf.0",
|
|
33
|
+
"@quenty/loader": "10.8.4-canary.11a5dcf.0",
|
|
34
|
+
"@quenty/maid": "3.4.4-canary.11a5dcf.0",
|
|
35
|
+
"@quenty/numberrangeutils": "3.1.1",
|
|
36
|
+
"@quenty/promise": "10.10.5-canary.11a5dcf.0",
|
|
37
|
+
"@quenty/promisemaid": "5.10.5-canary.11a5dcf.0",
|
|
38
|
+
"@quenty/randomutils": "6.10.4-canary.11a5dcf.0",
|
|
39
|
+
"@quenty/rbxasset": "5.8.4-canary.11a5dcf.0",
|
|
40
|
+
"@quenty/rx": "13.17.4-canary.11a5dcf.0",
|
|
41
|
+
"@quenty/signal": "7.10.4-canary.11a5dcf.0",
|
|
42
|
+
"@quenty/sounds": "10.10.5-canary.11a5dcf.0",
|
|
43
|
+
"@quenty/table": "3.7.5-canary.11a5dcf.0",
|
|
44
|
+
"@quenty/transitionmodel": "7.19.4-canary.11a5dcf.0",
|
|
45
|
+
"@quenty/valueobject": "13.17.4-canary.11a5dcf.0",
|
|
46
46
|
"@quentystudios/t": "^3.0.0"
|
|
47
47
|
},
|
|
48
48
|
"publishConfig": {
|
|
49
49
|
"access": "public"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "11a5dcf7d4c7a0bfbf3337e97d30e8346ea09d3f"
|
|
52
52
|
}
|
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
local require = require(script.Parent.loader).load(script)
|
|
6
6
|
|
|
7
|
-
local SpringTransitionModel = require("SpringTransitionModel")
|
|
8
|
-
local ValueObject = require("ValueObject")
|
|
9
7
|
local LoopedSoundPlayer = require("LoopedSoundPlayer")
|
|
10
8
|
local Maid = require("Maid")
|
|
11
9
|
local Rx = require("Rx")
|
|
12
|
-
local SoundUtils = require("SoundUtils")
|
|
13
10
|
local SoundLoopScheduleUtils = require("SoundLoopScheduleUtils")
|
|
11
|
+
local SoundUtils = require("SoundUtils")
|
|
12
|
+
local SpringTransitionModel = require("SpringTransitionModel")
|
|
13
|
+
local ValueObject = require("ValueObject")
|
|
14
|
+
local t = require("t")
|
|
14
15
|
|
|
15
16
|
local LayeredLoopedSoundPlayer = setmetatable({}, SpringTransitionModel)
|
|
16
17
|
LayeredLoopedSoundPlayer.ClassName = "LayeredLoopedSoundPlayer"
|
|
@@ -21,9 +22,9 @@ function LayeredLoopedSoundPlayer.new(soundParent)
|
|
|
21
22
|
|
|
22
23
|
self._layerMaid = self._maid:Add(Maid.new())
|
|
23
24
|
|
|
24
|
-
self._soundParent = self._maid:Add(ValueObject.new(nil))
|
|
25
|
-
self._soundGroup = self._maid:Add(ValueObject.new(nil))
|
|
26
|
-
self._bpm = self._maid:Add(ValueObject.new(nil))
|
|
25
|
+
self._soundParent = self._maid:Add(ValueObject.new(nil, t.optional(t.Instance)))
|
|
26
|
+
self._soundGroup = self._maid:Add(ValueObject.new(nil, t.optional(t.Instance)))
|
|
27
|
+
self._bpm = self._maid:Add(ValueObject.new(nil, t.optional(t.number)))
|
|
27
28
|
self._defaultCrossFadeTime = self._maid:Add(ValueObject.new(0.5, "number"))
|
|
28
29
|
self._volumeMultiplier = self._maid:Add(ValueObject.new(1, "number"))
|
|
29
30
|
|
|
@@ -36,32 +37,30 @@ function LayeredLoopedSoundPlayer.new(soundParent)
|
|
|
36
37
|
return self
|
|
37
38
|
end
|
|
38
39
|
|
|
39
|
-
function LayeredLoopedSoundPlayer:SetDefaultCrossFadeTime(crossFadeTime)
|
|
40
|
+
function LayeredLoopedSoundPlayer:SetDefaultCrossFadeTime(crossFadeTime: ValueObject.Mountable<number>)
|
|
40
41
|
return self._defaultCrossFadeTime:Mount(crossFadeTime)
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
function LayeredLoopedSoundPlayer:SetVolumeMultiplier(volumeMultiplier)
|
|
44
|
-
self._volumeMultiplier
|
|
44
|
+
function LayeredLoopedSoundPlayer:SetVolumeMultiplier(volumeMultiplier: ValueObject.Mountable<number>)
|
|
45
|
+
return self._volumeMultiplier:Mount(volumeMultiplier)
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
function LayeredLoopedSoundPlayer:SetBPM(bpm)
|
|
48
|
-
assert(type(bpm) == "number" or bpm == nil, "Bad bpm")
|
|
49
|
-
|
|
48
|
+
function LayeredLoopedSoundPlayer:SetBPM(bpm: ValueObject.Mountable<number?>)
|
|
50
49
|
self._bpm.Value = bpm
|
|
51
50
|
end
|
|
52
51
|
|
|
53
|
-
function LayeredLoopedSoundPlayer:SetSoundParent(soundParent)
|
|
52
|
+
function LayeredLoopedSoundPlayer:SetSoundParent(soundParent: Instance?)
|
|
54
53
|
assert(typeof(soundParent) == "Instance" or soundParent == nil, "Bad soundParent")
|
|
55
54
|
|
|
56
55
|
self._soundParent.Value = soundParent
|
|
57
56
|
end
|
|
58
57
|
|
|
59
|
-
function LayeredLoopedSoundPlayer:SetSoundGroup(soundGroup)
|
|
58
|
+
function LayeredLoopedSoundPlayer:SetSoundGroup(soundGroup: SoundGroup?)
|
|
60
59
|
return self._soundGroup:Mount(soundGroup)
|
|
61
60
|
end
|
|
62
61
|
|
|
63
|
-
function LayeredLoopedSoundPlayer:Swap(layerId, soundId, scheduleOptions)
|
|
64
|
-
assert(type(layerId) == "string",
|
|
62
|
+
function LayeredLoopedSoundPlayer:Swap(layerId: string, soundId, scheduleOptions)
|
|
63
|
+
assert(type(layerId) == "string", "Bad layerId")
|
|
65
64
|
assert(SoundUtils.isConvertableToRbxAsset(soundId) or soundId == nil, "Bad soundId")
|
|
66
65
|
assert(SoundLoopScheduleUtils.isLoopedSchedule(scheduleOptions) or scheduleOptions == nil, "Bad scheduleOptions")
|
|
67
66
|
|
|
@@ -70,7 +69,7 @@ function LayeredLoopedSoundPlayer:Swap(layerId, soundId, scheduleOptions)
|
|
|
70
69
|
end
|
|
71
70
|
|
|
72
71
|
function LayeredLoopedSoundPlayer:SwapOnLoop(layerId, soundId, scheduleOptions)
|
|
73
|
-
assert(type(layerId) == "string",
|
|
72
|
+
assert(type(layerId) == "string", "Bad layerId")
|
|
74
73
|
assert(SoundUtils.isConvertableToRbxAsset(soundId) or soundId == nil, "Bad soundId")
|
|
75
74
|
|
|
76
75
|
local layer = self:_getOrCreateLayer(layerId)
|
|
@@ -78,7 +77,7 @@ function LayeredLoopedSoundPlayer:SwapOnLoop(layerId, soundId, scheduleOptions)
|
|
|
78
77
|
end
|
|
79
78
|
|
|
80
79
|
function LayeredLoopedSoundPlayer:SwapToSamples(layerId, soundId, scheduleOptions)
|
|
81
|
-
assert(type(layerId) == "string",
|
|
80
|
+
assert(type(layerId) == "string", "Bad layerId")
|
|
82
81
|
assert(SoundUtils.isConvertableToRbxAsset(soundId) or soundId == nil, "Bad soundId")
|
|
83
82
|
assert(SoundLoopScheduleUtils.isLoopedSchedule(scheduleOptions) or scheduleOptions == nil, "Bad scheduleOptions")
|
|
84
83
|
|
|
@@ -87,7 +86,7 @@ function LayeredLoopedSoundPlayer:SwapToSamples(layerId, soundId, scheduleOption
|
|
|
87
86
|
end
|
|
88
87
|
|
|
89
88
|
function LayeredLoopedSoundPlayer:SwapToChoice(layerId, soundIdList, scheduleOptions)
|
|
90
|
-
assert(type(layerId) == "string",
|
|
89
|
+
assert(type(layerId) == "string", "Bad layerId")
|
|
91
90
|
assert(type(soundIdList) == "table", "Bad soundIdList")
|
|
92
91
|
assert(SoundLoopScheduleUtils.isLoopedSchedule(scheduleOptions) or scheduleOptions == nil, "Bad scheduleOptions")
|
|
93
92
|
|
|
@@ -96,7 +95,7 @@ function LayeredLoopedSoundPlayer:SwapToChoice(layerId, soundIdList, scheduleOpt
|
|
|
96
95
|
end
|
|
97
96
|
|
|
98
97
|
function LayeredLoopedSoundPlayer:PlayOnce(layerId, soundIdList, scheduleOptions)
|
|
99
|
-
assert(type(layerId) == "string",
|
|
98
|
+
assert(type(layerId) == "string", "Bad layerId")
|
|
100
99
|
assert(type(soundIdList) == "table", "Bad soundIdList")
|
|
101
100
|
assert(SoundLoopScheduleUtils.isLoopedSchedule(scheduleOptions) or scheduleOptions == nil, "Bad scheduleOptions")
|
|
102
101
|
|
|
@@ -105,14 +104,14 @@ function LayeredLoopedSoundPlayer:PlayOnce(layerId, soundIdList, scheduleOptions
|
|
|
105
104
|
end
|
|
106
105
|
|
|
107
106
|
function LayeredLoopedSoundPlayer:PlayOnceOnLoop(layerId, soundId, scheduleOptions)
|
|
108
|
-
assert(type(layerId) == "string",
|
|
107
|
+
assert(type(layerId) == "string", "Bad layerId")
|
|
109
108
|
|
|
110
109
|
local layer = self:_getOrCreateLayer(layerId)
|
|
111
110
|
layer:PlayOnceOnLoop(soundId, scheduleOptions)
|
|
112
111
|
end
|
|
113
112
|
|
|
114
113
|
function LayeredLoopedSoundPlayer:_getOrCreateLayer(layerId)
|
|
115
|
-
if
|
|
114
|
+
if self._layers[layerId] then
|
|
116
115
|
return self._layers[layerId]
|
|
117
116
|
end
|
|
118
117
|
|
|
@@ -140,10 +139,10 @@ function LayeredLoopedSoundPlayer:_getOrCreateLayer(layerId)
|
|
|
140
139
|
end))
|
|
141
140
|
|
|
142
141
|
maid:GiveTask(Rx.combineLatest({
|
|
143
|
-
visible = self:ObserveRenderStepped()
|
|
144
|
-
multiplier = self._volumeMultiplier:Observe()
|
|
142
|
+
visible = self:ObserveRenderStepped(),
|
|
143
|
+
multiplier = self._volumeMultiplier:Observe(),
|
|
145
144
|
}):Subscribe(function(state)
|
|
146
|
-
layer:SetVolumeMultiplier(state.multiplier*state.visible)
|
|
145
|
+
layer:SetVolumeMultiplier(state.multiplier * state.visible)
|
|
147
146
|
end))
|
|
148
147
|
|
|
149
148
|
self._layers[layerId] = layer
|
|
@@ -168,4 +167,4 @@ function LayeredLoopedSoundPlayer:StopAll()
|
|
|
168
167
|
self._layerMaid:DoCleaning()
|
|
169
168
|
end
|
|
170
169
|
|
|
171
|
-
return LayeredLoopedSoundPlayer
|
|
170
|
+
return LayeredLoopedSoundPlayer
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
@class LayeredLoopedSoundPlayer.story
|
|
3
3
|
]]
|
|
4
4
|
|
|
5
|
-
local require =
|
|
5
|
+
local require =
|
|
6
|
+
require(game:GetService("ServerScriptService"):FindFirstChild("LoaderUtils", true).Parent).bootstrapStory(script)
|
|
6
7
|
|
|
7
|
-
local Maid = require("Maid")
|
|
8
|
-
local LayeredLoopedSoundPlayer = require("LayeredLoopedSoundPlayer")
|
|
9
8
|
local Blend = require("Blend")
|
|
9
|
+
local LayeredLoopedSoundPlayer = require("LayeredLoopedSoundPlayer")
|
|
10
|
+
local Maid = require("Maid")
|
|
10
11
|
|
|
11
12
|
return function(target)
|
|
12
13
|
local maid = Maid.new()
|
|
@@ -19,23 +20,23 @@ return function(target)
|
|
|
19
20
|
local function initial()
|
|
20
21
|
layeredLoopedSoundPlayer:SwapToChoice("drums", {
|
|
21
22
|
{
|
|
22
|
-
SoundId = "rbxassetid://14478151709"
|
|
23
|
-
Volume = 0.1
|
|
24
|
-
}
|
|
23
|
+
SoundId = "rbxassetid://14478151709",
|
|
24
|
+
Volume = 0.1,
|
|
25
|
+
},
|
|
25
26
|
{
|
|
26
|
-
SoundId = "rbxassetid://14478738244"
|
|
27
|
-
Volume = 0.1
|
|
28
|
-
}
|
|
27
|
+
SoundId = "rbxassetid://14478738244",
|
|
28
|
+
Volume = 0.1,
|
|
29
|
+
},
|
|
29
30
|
})
|
|
30
31
|
layeredLoopedSoundPlayer:SwapToChoice("rifts", {
|
|
31
32
|
{
|
|
32
|
-
SoundId = "rbxassetid://14478152812"
|
|
33
|
-
Volume = 0.2
|
|
34
|
-
}
|
|
33
|
+
SoundId = "rbxassetid://14478152812",
|
|
34
|
+
Volume = 0.2,
|
|
35
|
+
},
|
|
35
36
|
{
|
|
36
|
-
SoundId = "rbxassetid://14478729478"
|
|
37
|
-
Volume = 0.015
|
|
38
|
-
}
|
|
37
|
+
SoundId = "rbxassetid://14478729478",
|
|
38
|
+
Volume = 0.015,
|
|
39
|
+
},
|
|
39
40
|
})
|
|
40
41
|
end
|
|
41
42
|
initial()
|
|
@@ -44,117 +45,112 @@ return function(target)
|
|
|
44
45
|
|
|
45
46
|
local function button(props)
|
|
46
47
|
return Blend.New "TextButton" {
|
|
47
|
-
Text = props.Text
|
|
48
|
-
AutoButtonColor = true
|
|
49
|
-
Font = Enum.Font.FredokaOne
|
|
50
|
-
Size = UDim2.new(0, 100, 0, 30)
|
|
51
|
-
|
|
52
|
-
Blend.New "UICorner" {
|
|
48
|
+
Text = props.Text,
|
|
49
|
+
AutoButtonColor = true,
|
|
50
|
+
Font = Enum.Font.FredokaOne,
|
|
51
|
+
Size = UDim2.new(0, 100, 0, 30),
|
|
53
52
|
|
|
54
|
-
}
|
|
53
|
+
Blend.New "UICorner" {},
|
|
55
54
|
|
|
56
55
|
[Blend.OnEvent "Activated"] = function()
|
|
57
|
-
props.OnActivated()
|
|
58
|
-
end
|
|
59
|
-
}
|
|
56
|
+
props.OnActivated()
|
|
57
|
+
end,
|
|
58
|
+
}
|
|
60
59
|
end
|
|
61
60
|
|
|
62
61
|
maid:GiveTask(Blend.mount(target, {
|
|
63
62
|
Blend.New "Frame" {
|
|
64
|
-
Name = "ButtonContainer"
|
|
65
|
-
BackgroundTransparency = 1
|
|
66
|
-
Position = UDim2.new(0.5, 0, 0, 5)
|
|
67
|
-
AnchorPoint = Vector2.new(0.5, 0)
|
|
68
|
-
Size = UDim2.new(1, 0, 0, 30)
|
|
63
|
+
Name = "ButtonContainer",
|
|
64
|
+
BackgroundTransparency = 1,
|
|
65
|
+
Position = UDim2.new(0.5, 0, 0, 5),
|
|
66
|
+
AnchorPoint = Vector2.new(0.5, 0),
|
|
67
|
+
Size = UDim2.new(1, 0, 0, 30),
|
|
69
68
|
|
|
70
69
|
Blend.New "UIListLayout" {
|
|
71
|
-
FillDirection = Enum.FillDirection.Horizontal
|
|
72
|
-
Padding = UDim.new(0, 5)
|
|
73
|
-
HorizontalAlignment = Enum.HorizontalAlignment.Center
|
|
74
|
-
}
|
|
70
|
+
FillDirection = Enum.FillDirection.Horizontal,
|
|
71
|
+
Padding = UDim.new(0, 5),
|
|
72
|
+
HorizontalAlignment = Enum.HorizontalAlignment.Center,
|
|
73
|
+
},
|
|
75
74
|
|
|
76
75
|
button({
|
|
77
|
-
Text = "Toggle"
|
|
76
|
+
Text = "Toggle",
|
|
78
77
|
OnActivated = function()
|
|
79
78
|
layeredLoopedSoundPlayer:Toggle()
|
|
80
|
-
end
|
|
81
|
-
})
|
|
79
|
+
end,
|
|
80
|
+
}),
|
|
82
81
|
|
|
83
82
|
button({
|
|
84
|
-
Text = "Reset"
|
|
83
|
+
Text = "Reset",
|
|
85
84
|
OnActivated = function()
|
|
86
85
|
initial()
|
|
87
|
-
end
|
|
88
|
-
})
|
|
86
|
+
end,
|
|
87
|
+
}),
|
|
89
88
|
|
|
90
89
|
button({
|
|
91
|
-
Text = "Combat equip"
|
|
90
|
+
Text = "Combat equip",
|
|
92
91
|
OnActivated = function()
|
|
93
92
|
layeredLoopedSoundPlayer:SwapToChoice("drums", {
|
|
94
|
-
"rbxassetid://14478154829"
|
|
95
|
-
"rbxassetid://14478714545"
|
|
96
|
-
"rbxassetid://14478772830"
|
|
97
|
-
"rbxassetid://14478897865"
|
|
93
|
+
"rbxassetid://14478154829",
|
|
94
|
+
"rbxassetid://14478714545",
|
|
95
|
+
"rbxassetid://14478772830",
|
|
96
|
+
"rbxassetid://14478897865",
|
|
98
97
|
})
|
|
99
98
|
layeredLoopedSoundPlayer:PlayOnceOnLoop("rifts", nil)
|
|
100
|
-
end
|
|
101
|
-
})
|
|
99
|
+
end,
|
|
100
|
+
}),
|
|
102
101
|
|
|
103
102
|
button({
|
|
104
|
-
Text = "On target lock"
|
|
103
|
+
Text = "On target lock",
|
|
105
104
|
OnActivated = function()
|
|
106
105
|
layeredLoopedSoundPlayer:SwapToChoice("drums", {
|
|
107
106
|
{
|
|
108
|
-
SoundId = "rbxassetid://14478150956"
|
|
109
|
-
Volume = 0.1
|
|
110
|
-
}
|
|
107
|
+
SoundId = "rbxassetid://14478150956",
|
|
108
|
+
Volume = 0.1,
|
|
109
|
+
},
|
|
111
110
|
{
|
|
112
|
-
SoundId = "rbxassetid://14478721669"
|
|
113
|
-
Volume = 0.2
|
|
114
|
-
}
|
|
115
|
-
"rbxassetid://14478154829"
|
|
116
|
-
"rbxassetid://14478764914"
|
|
111
|
+
SoundId = "rbxassetid://14478721669",
|
|
112
|
+
Volume = 0.2,
|
|
113
|
+
},
|
|
114
|
+
"rbxassetid://14478154829",
|
|
115
|
+
"rbxassetid://14478764914",
|
|
117
116
|
})
|
|
118
117
|
|
|
119
118
|
layeredLoopedSoundPlayer:SwapToChoice("rifts", {
|
|
120
|
-
"rbxassetid://14478145963"
|
|
121
|
-
"rbxassetid://14478156714"
|
|
119
|
+
"rbxassetid://14478145963",
|
|
120
|
+
"rbxassetid://14478156714",
|
|
122
121
|
{
|
|
123
|
-
SoundId = "rbxassetid://14478777472"
|
|
124
|
-
Volume = 0.1
|
|
125
|
-
}
|
|
122
|
+
SoundId = "rbxassetid://14478777472",
|
|
123
|
+
Volume = 0.1,
|
|
124
|
+
},
|
|
126
125
|
{
|
|
127
|
-
SoundId = "rbxassetid://14478793045"
|
|
128
|
-
Volume = 0.1
|
|
129
|
-
}
|
|
126
|
+
SoundId = "rbxassetid://14478793045",
|
|
127
|
+
Volume = 0.1,
|
|
128
|
+
},
|
|
130
129
|
})
|
|
131
|
-
end
|
|
132
|
-
})
|
|
130
|
+
end,
|
|
131
|
+
}),
|
|
133
132
|
|
|
134
133
|
button({
|
|
135
|
-
Text = "On low health"
|
|
134
|
+
Text = "On low health",
|
|
136
135
|
OnActivated = function()
|
|
137
136
|
layeredLoopedSoundPlayer:SwapToChoice("drums", {
|
|
138
|
-
"rbxassetid://14478746326"
|
|
139
|
-
"rbxassetid://14478767498"
|
|
140
|
-
"rbxassetid://14478797936"
|
|
137
|
+
"rbxassetid://14478746326",
|
|
138
|
+
"rbxassetid://14478767498",
|
|
139
|
+
"rbxassetid://14478797936", -- record scratch
|
|
141
140
|
})
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
});
|
|
145
|
-
|
|
141
|
+
end,
|
|
142
|
+
}),
|
|
146
143
|
|
|
147
144
|
button({
|
|
148
|
-
Text = "Target drop"
|
|
145
|
+
Text = "Target drop",
|
|
149
146
|
OnActivated = function()
|
|
150
147
|
layeredLoopedSoundPlayer:PlayOnceOnLoop("rifts", "rbxassetid://14478158396")
|
|
151
|
-
end
|
|
152
|
-
})
|
|
153
|
-
}
|
|
148
|
+
end,
|
|
149
|
+
}),
|
|
150
|
+
},
|
|
154
151
|
}))
|
|
155
152
|
|
|
156
|
-
|
|
157
153
|
return function()
|
|
158
154
|
maid:DoCleaning()
|
|
159
155
|
end
|
|
160
|
-
end
|
|
156
|
+
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
@class LoopedSoundPlayer
|
|
3
4
|
]=]
|
|
@@ -25,13 +26,31 @@ local LoopedSoundPlayer = setmetatable({}, SpringTransitionModel)
|
|
|
25
26
|
LoopedSoundPlayer.ClassName = "LoopedSoundPlayer"
|
|
26
27
|
LoopedSoundPlayer.__index = LoopedSoundPlayer
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
export type LoopedSoundPlayer = typeof(setmetatable(
|
|
30
|
+
{} :: {
|
|
31
|
+
_currentSoundLooped: Signal.Signal<()>,
|
|
32
|
+
_currentSoundLoopedAfterDelay: Signal.Signal<()>,
|
|
33
|
+
_bpm: ValueObject.ValueObject<number?>,
|
|
34
|
+
_soundParent: ValueObject.ValueObject<Instance?>,
|
|
35
|
+
_soundGroup: ValueObject.ValueObject<SoundGroup?>,
|
|
36
|
+
_crossFadeTime: ValueObject.ValueObject<number>,
|
|
37
|
+
_volumeMultiplier: ValueObject.ValueObject<number>,
|
|
38
|
+
_doSyncSoundPlayback: ValueObject.ValueObject<boolean>,
|
|
39
|
+
_currentActiveSound: ValueObject.ValueObject<Sound?>,
|
|
40
|
+
_currentSoundId: ValueObject.ValueObject<(string | number)?>,
|
|
41
|
+
_defaultScheduleOptions: SoundLoopScheduleUtils.SoundLoopSchedule,
|
|
42
|
+
_currentLoopSchedule: ValueObject.ValueObject<SoundLoopScheduleUtils.SoundLoopSchedule>,
|
|
43
|
+
},
|
|
44
|
+
{} :: typeof({ __index = LoopedSoundPlayer })
|
|
45
|
+
)) & SpringTransitionModel.SpringTransitionModel<number>
|
|
46
|
+
|
|
47
|
+
function LoopedSoundPlayer.new(soundId: (string | number)?, soundParent: Instance?)
|
|
48
|
+
assert(soundId == nil or SoundUtils.isConvertableToRbxAsset(soundId), "Bad soundId")
|
|
49
|
+
|
|
50
|
+
local self: LoopedSoundPlayer = setmetatable(SpringTransitionModel.new() :: any, LoopedSoundPlayer)
|
|
51
|
+
|
|
52
|
+
self._currentSoundLooped = self._maid:Add(Signal.new() :: any)
|
|
53
|
+
self._currentSoundLoopedAfterDelay = self._maid:Add(Signal.new() :: any)
|
|
35
54
|
|
|
36
55
|
self:SetSpeed(10)
|
|
37
56
|
|
|
@@ -60,29 +79,29 @@ function LoopedSoundPlayer.new(soundId, soundParent: Instance?)
|
|
|
60
79
|
return self
|
|
61
80
|
end
|
|
62
81
|
|
|
63
|
-
function LoopedSoundPlayer
|
|
82
|
+
function LoopedSoundPlayer.SetCrossFadeTime(self: LoopedSoundPlayer, crossFadeTime: number)
|
|
64
83
|
return self._crossFadeTime:Mount(crossFadeTime)
|
|
65
84
|
end
|
|
66
85
|
|
|
67
|
-
function LoopedSoundPlayer
|
|
86
|
+
function LoopedSoundPlayer.SetVolumeMultiplier(self: LoopedSoundPlayer, volume: number)
|
|
68
87
|
self._volumeMultiplier.Value = volume
|
|
69
88
|
end
|
|
70
89
|
|
|
71
|
-
function LoopedSoundPlayer
|
|
90
|
+
function LoopedSoundPlayer.SetSoundGroup(self: LoopedSoundPlayer, soundGroup: SoundGroup?)
|
|
72
91
|
return self._soundGroup:Mount(soundGroup)
|
|
73
92
|
end
|
|
74
93
|
|
|
75
|
-
function LoopedSoundPlayer
|
|
94
|
+
function LoopedSoundPlayer.SetBPM(self: LoopedSoundPlayer, bpm: number?)
|
|
76
95
|
assert(type(bpm) == "number" or bpm == nil, "Bad bpm")
|
|
77
96
|
|
|
78
97
|
self._bpm.Value = bpm
|
|
79
98
|
end
|
|
80
99
|
|
|
81
|
-
function LoopedSoundPlayer
|
|
100
|
+
function LoopedSoundPlayer.SetSoundParent(self: LoopedSoundPlayer, parent: Instance?)
|
|
82
101
|
self._soundParent.Value = parent
|
|
83
102
|
end
|
|
84
103
|
|
|
85
|
-
function LoopedSoundPlayer
|
|
104
|
+
function LoopedSoundPlayer.Swap(self: LoopedSoundPlayer, soundId, loopSchedule)
|
|
86
105
|
assert(SoundUtils.isConvertableToRbxAsset(soundId) or soundId == nil, "Bad soundId")
|
|
87
106
|
loopSchedule = self:_convertToLoopedSchedule(loopSchedule)
|
|
88
107
|
|
|
@@ -96,11 +115,11 @@ function LoopedSoundPlayer:Swap(soundId, loopSchedule)
|
|
|
96
115
|
self._maid._swappingTo = maid
|
|
97
116
|
end
|
|
98
117
|
|
|
99
|
-
function LoopedSoundPlayer
|
|
118
|
+
function LoopedSoundPlayer.SetDoSyncSoundPlayback(self: LoopedSoundPlayer, doSyncSoundPlayback: boolean)
|
|
100
119
|
self._doSyncSoundPlayback.Value = doSyncSoundPlayback
|
|
101
120
|
end
|
|
102
121
|
|
|
103
|
-
function LoopedSoundPlayer
|
|
122
|
+
function LoopedSoundPlayer._setupRender(self: LoopedSoundPlayer)
|
|
104
123
|
self._maid:GiveTask(self._currentSoundId
|
|
105
124
|
:ObserveBrio(function(value)
|
|
106
125
|
return value ~= nil
|
|
@@ -117,7 +136,7 @@ function LoopedSoundPlayer:_setupRender()
|
|
|
117
136
|
end))
|
|
118
137
|
end
|
|
119
138
|
|
|
120
|
-
function LoopedSoundPlayer
|
|
139
|
+
function LoopedSoundPlayer._renderSoundPlayer(self: LoopedSoundPlayer, soundId)
|
|
121
140
|
local maid = Maid.new()
|
|
122
141
|
|
|
123
142
|
local renderMaid = Maid.new()
|
|
@@ -133,7 +152,7 @@ function LoopedSoundPlayer:_renderSoundPlayer(soundId)
|
|
|
133
152
|
isLoaded = Rx.fromPromise(SoundPromiseUtils.promiseLoaded(soundPlayer.Sound)),
|
|
134
153
|
doSyncSoundPlayback = self._doSyncSoundPlayback:Observe(),
|
|
135
154
|
timeLength = RxInstanceUtils.observeProperty(soundPlayer.Sound, "TimeLength"),
|
|
136
|
-
}):Subscribe(function(state)
|
|
155
|
+
}):Subscribe(function(state: any)
|
|
137
156
|
local syncMaid = Maid.new()
|
|
138
157
|
|
|
139
158
|
if state.doSyncSoundPlayback then
|
|
@@ -197,7 +216,7 @@ function LoopedSoundPlayer:_renderSoundPlayer(soundId)
|
|
|
197
216
|
maid:GiveTask(Rx.combineLatest({
|
|
198
217
|
visible = self:ObserveRenderStepped(),
|
|
199
218
|
multiplier = self._volumeMultiplier:Observe(),
|
|
200
|
-
}):Subscribe(function(state)
|
|
219
|
+
}):Subscribe(function(state: any)
|
|
201
220
|
soundPlayer:SetVolumeMultiplier(state.multiplier * state.visible)
|
|
202
221
|
end))
|
|
203
222
|
|
|
@@ -214,7 +233,7 @@ function LoopedSoundPlayer:_renderSoundPlayer(soundId)
|
|
|
214
233
|
return maid
|
|
215
234
|
end
|
|
216
235
|
|
|
217
|
-
function LoopedSoundPlayer
|
|
236
|
+
function LoopedSoundPlayer._setupLoopScheduling(self: LoopedSoundPlayer, soundPlayer, loopSchedule)
|
|
218
237
|
local maid = Maid.new()
|
|
219
238
|
|
|
220
239
|
if loopSchedule.maxLoops then
|
|
@@ -249,7 +268,7 @@ function LoopedSoundPlayer:_setupLoopScheduling(soundPlayer, loopSchedule)
|
|
|
249
268
|
return maid
|
|
250
269
|
end
|
|
251
270
|
|
|
252
|
-
function LoopedSoundPlayer
|
|
271
|
+
function LoopedSoundPlayer.SwapToSamples(self: LoopedSoundPlayer, soundIdList, loopSchedule)
|
|
253
272
|
assert(type(soundIdList) == "table", "Bad soundIdList")
|
|
254
273
|
loopSchedule = self:_convertToLoopedSchedule(loopSchedule)
|
|
255
274
|
|
|
@@ -268,7 +287,7 @@ function LoopedSoundPlayer:SwapToSamples(soundIdList, loopSchedule)
|
|
|
268
287
|
self._maid._swappingTo = loopMaid
|
|
269
288
|
end
|
|
270
289
|
|
|
271
|
-
function LoopedSoundPlayer
|
|
290
|
+
function LoopedSoundPlayer.SwapToChoice(self: LoopedSoundPlayer, soundIdList, loopSchedule)
|
|
272
291
|
assert(type(soundIdList) == "table", "Bad soundIdList")
|
|
273
292
|
loopSchedule = self:_convertToLoopedSchedule(loopSchedule)
|
|
274
293
|
|
|
@@ -286,39 +305,39 @@ function LoopedSoundPlayer:SwapToChoice(soundIdList, loopSchedule)
|
|
|
286
305
|
self._maid._swappingTo = loopMaid
|
|
287
306
|
end
|
|
288
307
|
|
|
289
|
-
function LoopedSoundPlayer
|
|
308
|
+
function LoopedSoundPlayer.PlayOnce(self: LoopedSoundPlayer, soundId, loopSchedule)
|
|
290
309
|
assert(SoundUtils.isConvertableToRbxAsset(soundId) or soundId == nil, "Bad soundId")
|
|
291
310
|
loopSchedule = self:_convertToLoopedSchedule(loopSchedule)
|
|
292
311
|
|
|
293
312
|
self:Swap(soundId, SoundLoopScheduleUtils.maxLoops(1, loopSchedule))
|
|
294
313
|
end
|
|
295
314
|
|
|
296
|
-
function LoopedSoundPlayer
|
|
315
|
+
function LoopedSoundPlayer.SwapOnLoop(self: LoopedSoundPlayer, soundId, loopSchedule)
|
|
297
316
|
assert(SoundUtils.isConvertableToRbxAsset(soundId) or soundId == nil, "Bad soundId")
|
|
298
317
|
loopSchedule = self:_convertToLoopedSchedule(loopSchedule)
|
|
299
318
|
|
|
300
319
|
self:Swap(soundId, SoundLoopScheduleUtils.onNextLoop(loopSchedule))
|
|
301
320
|
end
|
|
302
321
|
|
|
303
|
-
function LoopedSoundPlayer
|
|
322
|
+
function LoopedSoundPlayer.PlayOnceOnLoop(self: LoopedSoundPlayer, soundId, loopSchedule)
|
|
304
323
|
assert(SoundUtils.isConvertableToRbxAsset(soundId) or soundId == nil, "Bad soundId")
|
|
305
324
|
loopSchedule = self:_convertToLoopedSchedule(loopSchedule)
|
|
306
325
|
|
|
307
326
|
self:PlayOnce(soundId, SoundLoopScheduleUtils.onNextLoop(loopSchedule))
|
|
308
327
|
end
|
|
309
328
|
|
|
310
|
-
function LoopedSoundPlayer
|
|
329
|
+
function LoopedSoundPlayer._convertToLoopedSchedule(self: LoopedSoundPlayer, loopSchedule)
|
|
311
330
|
assert(SoundLoopScheduleUtils.isLoopedSchedule(loopSchedule) or loopSchedule == nil, "Bad loopSchedule")
|
|
312
331
|
return loopSchedule or self._defaultScheduleOptions
|
|
313
332
|
end
|
|
314
333
|
|
|
315
|
-
function LoopedSoundPlayer
|
|
334
|
+
function LoopedSoundPlayer._scheduleFirstPlay(self: LoopedSoundPlayer, loopSchedule, callback)
|
|
316
335
|
assert(SoundLoopScheduleUtils.isLoopedSchedule(loopSchedule), "Bad loopSchedule")
|
|
317
336
|
assert(type(callback) == "function", "Bad callback")
|
|
318
337
|
|
|
319
338
|
local maid = Maid.new()
|
|
320
339
|
|
|
321
|
-
local observable = Rx.of(true)
|
|
340
|
+
local observable: any = Rx.of(true)
|
|
322
341
|
if loopSchedule.playOnNextLoop then
|
|
323
342
|
observable = observable:Pipe({
|
|
324
343
|
Rx.switchMap(function()
|
|
@@ -328,15 +347,15 @@ function LoopedSoundPlayer:_scheduleFirstPlay(loopSchedule, callback)
|
|
|
328
347
|
end
|
|
329
348
|
|
|
330
349
|
return self:_observeActiveSoundFinishLoop(waitTime)
|
|
331
|
-
end),
|
|
350
|
+
end) :: any,
|
|
332
351
|
})
|
|
333
352
|
end
|
|
334
353
|
|
|
335
354
|
if loopSchedule.initialDelay then
|
|
336
355
|
observable = observable:Pipe({
|
|
337
356
|
Rx.switchMap(function()
|
|
338
|
-
return Rx.delayed(SoundLoopScheduleUtils.getWaitTimeSeconds(loopSchedule.initialDelay))
|
|
339
|
-
end),
|
|
357
|
+
return Rx.delayed(SoundLoopScheduleUtils.getWaitTimeSeconds(loopSchedule.initialDelay)) :: any
|
|
358
|
+
end) :: any,
|
|
340
359
|
})
|
|
341
360
|
end
|
|
342
361
|
|
|
@@ -353,7 +372,7 @@ function LoopedSoundPlayer:_scheduleFirstPlay(loopSchedule, callback)
|
|
|
353
372
|
return maid
|
|
354
373
|
end
|
|
355
374
|
|
|
356
|
-
function LoopedSoundPlayer
|
|
375
|
+
function LoopedSoundPlayer.StopAfterLoop(self: LoopedSoundPlayer)
|
|
357
376
|
local swapMaid = Maid.new()
|
|
358
377
|
|
|
359
378
|
swapMaid:GiveTask(self._currentSoundLooped:Connect(function()
|
|
@@ -365,22 +384,22 @@ function LoopedSoundPlayer:StopAfterLoop()
|
|
|
365
384
|
self._maid._swappingTo = swapMaid
|
|
366
385
|
end
|
|
367
386
|
|
|
368
|
-
function LoopedSoundPlayer
|
|
387
|
+
function LoopedSoundPlayer._observeActiveSoundFinishLoop(self: LoopedSoundPlayer, maxWaitTime)
|
|
369
388
|
local startTime = os.clock()
|
|
370
389
|
|
|
371
390
|
return self._currentActiveSound:Observe():Pipe({
|
|
372
|
-
Rx.throttleDefer()
|
|
373
|
-
Rx.switchMap(function(sound)
|
|
391
|
+
Rx.throttleDefer() :: any,
|
|
392
|
+
Rx.switchMap(function(sound): any
|
|
374
393
|
if not sound then
|
|
375
394
|
return Rx.of(true)
|
|
376
395
|
end
|
|
377
396
|
|
|
378
397
|
return Rx.combineLatest({
|
|
379
|
-
timeLength = RxInstanceUtils.observeProperty(sound, "TimeLength")
|
|
380
|
-
timePosition = RxInstanceUtils.observeProperty(sound, "TimePosition")
|
|
381
|
-
crossFadeTime = self._crossFadeTime:Observe()
|
|
398
|
+
timeLength = RxInstanceUtils.observeProperty(sound, "TimeLength"),
|
|
399
|
+
timePosition = RxInstanceUtils.observeProperty(sound, "TimePosition"),
|
|
400
|
+
crossFadeTime = self._crossFadeTime:Observe(),
|
|
382
401
|
}):Pipe({
|
|
383
|
-
Rx.switchMap(function(state)
|
|
402
|
+
Rx.switchMap(function(state: any): any
|
|
384
403
|
local timeElapsed = os.clock() - startTime
|
|
385
404
|
local timeRemaining
|
|
386
405
|
if maxWaitTime then
|
|
@@ -403,13 +422,13 @@ function LoopedSoundPlayer:_observeActiveSoundFinishLoop(maxWaitTime)
|
|
|
403
422
|
end
|
|
404
423
|
|
|
405
424
|
return Rx.delayed(waitTime)
|
|
406
|
-
end)
|
|
425
|
+
end) :: any,
|
|
407
426
|
})
|
|
408
|
-
end)
|
|
409
|
-
})
|
|
427
|
+
end) :: any,
|
|
428
|
+
}) :: any
|
|
410
429
|
end
|
|
411
430
|
|
|
412
|
-
function LoopedSoundPlayer
|
|
431
|
+
function LoopedSoundPlayer.PromiseLoopDone(self: LoopedSoundPlayer): Promise.Promise<()>
|
|
413
432
|
local promise = self._maid:GivePromise(Promise.new())
|
|
414
433
|
|
|
415
434
|
PromiseMaidUtils.whilePromise(promise, function(maid)
|
|
@@ -421,14 +440,13 @@ function LoopedSoundPlayer:PromiseLoopDone()
|
|
|
421
440
|
return promise
|
|
422
441
|
end
|
|
423
442
|
|
|
424
|
-
function LoopedSoundPlayer
|
|
443
|
+
function LoopedSoundPlayer.PromiseSustain(_self: LoopedSoundPlayer): Promise.Promise<()>
|
|
425
444
|
-- Never resolve (?)
|
|
426
445
|
return Promise.new()
|
|
427
446
|
end
|
|
428
447
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
return self._sound
|
|
448
|
+
function LoopedSoundPlayer.GetSound(self: LoopedSoundPlayer): Sound?
|
|
449
|
+
return self._currentActiveSound.Value
|
|
432
450
|
end
|
|
433
451
|
|
|
434
|
-
return LoopedSoundPlayer
|
|
452
|
+
return LoopedSoundPlayer
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
@class LoopedSoundPlayer.story
|
|
3
3
|
]]
|
|
4
4
|
|
|
5
|
-
local require =
|
|
5
|
+
local require =
|
|
6
|
+
require(game:GetService("ServerScriptService"):FindFirstChild("LoaderUtils", true).Parent).bootstrapStory(script)
|
|
6
7
|
|
|
7
|
-
local Maid = require("Maid")
|
|
8
|
-
local LoopedSoundPlayer = require("LoopedSoundPlayer")
|
|
9
|
-
local RandomUtils = require("RandomUtils")
|
|
10
8
|
local Blend = require("Blend")
|
|
9
|
+
local LoopedSoundPlayer = require("LoopedSoundPlayer")
|
|
11
10
|
local LoopedSoundScheduleUtils = require("LoopedSoundScheduleUtils")
|
|
11
|
+
local Maid = require("Maid")
|
|
12
|
+
local RandomUtils = require("RandomUtils")
|
|
12
13
|
|
|
13
14
|
return function(target)
|
|
14
15
|
local maid = Maid.new()
|
|
@@ -22,7 +23,7 @@ return function(target)
|
|
|
22
23
|
loopedSoundPlayer:SetSoundParent(target)
|
|
23
24
|
|
|
24
25
|
local OPTIONS = {
|
|
25
|
-
"rbxassetid://14477453689"
|
|
26
|
+
"rbxassetid://14477453689",
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
maid:GiveTask(task.spawn(function()
|
|
@@ -36,89 +37,90 @@ return function(target)
|
|
|
36
37
|
|
|
37
38
|
local function button(props)
|
|
38
39
|
return Blend.New "TextButton" {
|
|
39
|
-
Text = props.Text
|
|
40
|
-
AutoButtonColor = true
|
|
41
|
-
Font = Enum.Font.FredokaOne
|
|
42
|
-
Size = UDim2.new(0, 100, 0, 30)
|
|
43
|
-
|
|
44
|
-
Blend.New "UICorner" {
|
|
40
|
+
Text = props.Text,
|
|
41
|
+
AutoButtonColor = true,
|
|
42
|
+
Font = Enum.Font.FredokaOne,
|
|
43
|
+
Size = UDim2.new(0, 100, 0, 30),
|
|
45
44
|
|
|
46
|
-
}
|
|
45
|
+
Blend.New "UICorner" {},
|
|
47
46
|
|
|
48
47
|
[Blend.OnEvent "Activated"] = function()
|
|
49
|
-
props.OnActivated()
|
|
50
|
-
end
|
|
51
|
-
}
|
|
48
|
+
props.OnActivated()
|
|
49
|
+
end,
|
|
50
|
+
}
|
|
52
51
|
end
|
|
53
52
|
|
|
54
53
|
maid:GiveTask(Blend.mount(target, {
|
|
55
54
|
Blend.New "Frame" {
|
|
56
|
-
Name = "ButtonContainer"
|
|
57
|
-
BackgroundTransparency = 1
|
|
58
|
-
Position = UDim2.new(0.5, 0, 0, 5)
|
|
59
|
-
AnchorPoint = Vector2.new(0.5, 0)
|
|
60
|
-
Size = UDim2.new(1, 0, 0, 30)
|
|
55
|
+
Name = "ButtonContainer",
|
|
56
|
+
BackgroundTransparency = 1,
|
|
57
|
+
Position = UDim2.new(0.5, 0, 0, 5),
|
|
58
|
+
AnchorPoint = Vector2.new(0.5, 0),
|
|
59
|
+
Size = UDim2.new(1, 0, 0, 30),
|
|
61
60
|
|
|
62
61
|
Blend.New "UIListLayout" {
|
|
63
|
-
FillDirection = Enum.FillDirection.Horizontal
|
|
64
|
-
Padding = UDim.new(0, 5)
|
|
65
|
-
HorizontalAlignment = Enum.HorizontalAlignment.Center
|
|
66
|
-
}
|
|
62
|
+
FillDirection = Enum.FillDirection.Horizontal,
|
|
63
|
+
Padding = UDim.new(0, 5),
|
|
64
|
+
HorizontalAlignment = Enum.HorizontalAlignment.Center,
|
|
65
|
+
},
|
|
67
66
|
|
|
68
67
|
button({
|
|
69
|
-
Text = "Toggle"
|
|
68
|
+
Text = "Toggle",
|
|
70
69
|
OnActivated = function()
|
|
71
70
|
loopedSoundPlayer:Toggle()
|
|
72
|
-
end
|
|
73
|
-
})
|
|
71
|
+
end,
|
|
72
|
+
}),
|
|
74
73
|
|
|
75
74
|
button({
|
|
76
|
-
Text = "Reset"
|
|
75
|
+
Text = "Reset",
|
|
77
76
|
OnActivated = function()
|
|
78
77
|
loopedSoundPlayer:Swap(ORIGINAL)
|
|
79
|
-
end
|
|
80
|
-
})
|
|
78
|
+
end,
|
|
79
|
+
}),
|
|
81
80
|
|
|
82
81
|
button({
|
|
83
|
-
Text = "Swap sample"
|
|
82
|
+
Text = "Swap sample",
|
|
84
83
|
OnActivated = function()
|
|
85
84
|
loopedSoundPlayer:SwapToSamples({
|
|
86
|
-
"rbxassetid://14478670277"
|
|
87
|
-
"rbxassetid://14478671494"
|
|
88
|
-
"rbxassetid://14478672676"
|
|
85
|
+
"rbxassetid://14478670277",
|
|
86
|
+
"rbxassetid://14478671494",
|
|
87
|
+
"rbxassetid://14478672676",
|
|
89
88
|
})
|
|
90
|
-
end
|
|
91
|
-
})
|
|
89
|
+
end,
|
|
90
|
+
}),
|
|
92
91
|
|
|
93
92
|
button({
|
|
94
|
-
Text = "Play once"
|
|
93
|
+
Text = "Play once",
|
|
95
94
|
OnActivated = function()
|
|
96
95
|
loopedSoundPlayer:PlayOnce("rbxassetid://14478764914")
|
|
97
|
-
end
|
|
98
|
-
})
|
|
96
|
+
end,
|
|
97
|
+
}),
|
|
99
98
|
|
|
100
99
|
button({
|
|
101
|
-
Text = "Play delayed loop"
|
|
100
|
+
Text = "Play delayed loop",
|
|
102
101
|
OnActivated = function()
|
|
103
|
-
loopedSoundPlayer:Swap(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
loopedSoundPlayer:Swap(
|
|
103
|
+
{
|
|
104
|
+
SoundId = "rbxassetid://6052547865",
|
|
105
|
+
Volume = 3,
|
|
106
|
+
},
|
|
107
|
+
LoopedSoundScheduleUtils.schedule({
|
|
108
|
+
loopDelay = NumberRange.new(0.25, 1),
|
|
109
|
+
})
|
|
110
|
+
)
|
|
111
|
+
end,
|
|
112
|
+
}),
|
|
111
113
|
|
|
112
114
|
button({
|
|
113
|
-
Text = "Swap on loop"
|
|
115
|
+
Text = "Swap on loop",
|
|
114
116
|
OnActivated = function()
|
|
115
117
|
loopedSoundPlayer:SwapOnLoop(RandomUtils.choice(OPTIONS))
|
|
116
|
-
end
|
|
117
|
-
})
|
|
118
|
-
}
|
|
118
|
+
end,
|
|
119
|
+
}),
|
|
120
|
+
},
|
|
119
121
|
}))
|
|
120
122
|
|
|
121
123
|
return function()
|
|
122
124
|
maid:DoCleaning()
|
|
123
125
|
end
|
|
124
|
-
end
|
|
126
|
+
end
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
local require = require(script.Parent.loader).load(script)
|
|
6
6
|
|
|
7
|
-
local
|
|
7
|
+
local Promise = require("Promise")
|
|
8
8
|
local Rx = require("Rx")
|
|
9
|
-
local SoundUtils = require("SoundUtils")
|
|
10
9
|
local SoundPromiseUtils = require("SoundPromiseUtils")
|
|
11
|
-
local
|
|
10
|
+
local SoundUtils = require("SoundUtils")
|
|
11
|
+
local TimedTransitionModel = require("TimedTransitionModel")
|
|
12
12
|
local ValueObject = require("ValueObject")
|
|
13
13
|
|
|
14
14
|
local SimpleLoopedSoundPlayer = setmetatable({}, TimedTransitionModel)
|
|
@@ -29,10 +29,10 @@ function SimpleLoopedSoundPlayer.new(soundId)
|
|
|
29
29
|
self._maxVolume = self.Sound.Volume
|
|
30
30
|
|
|
31
31
|
self._maid:GiveTask(Rx.combineLatest({
|
|
32
|
-
visible = self:ObserveRenderStepped()
|
|
33
|
-
multiplier = self._volumeMultiplier:Observe()
|
|
32
|
+
visible = self:ObserveRenderStepped(),
|
|
33
|
+
multiplier = self._volumeMultiplier:Observe(),
|
|
34
34
|
}):Subscribe(function(state)
|
|
35
|
-
self.Sound.Volume = state.visible*self._maxVolume*state.multiplier
|
|
35
|
+
self.Sound.Volume = state.visible * self._maxVolume * state.multiplier
|
|
36
36
|
end))
|
|
37
37
|
|
|
38
38
|
self._maid:GiveTask(self.VisibleChanged:Connect(function(isVisible)
|
|
@@ -63,5 +63,4 @@ function SimpleLoopedSoundPlayer:PromiseLoopDone()
|
|
|
63
63
|
return SoundPromiseUtils.promiseLooped(self.Sound)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
return SimpleLoopedSoundPlayer
|
|
66
|
+
return SimpleLoopedSoundPlayer
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
@class SimpleLoopedSoundPlayer.story
|
|
3
3
|
]]
|
|
4
4
|
|
|
5
|
-
local require =
|
|
5
|
+
local require =
|
|
6
|
+
require(game:GetService("ServerScriptService"):FindFirstChild("LoaderUtils", true).Parent).bootstrapStory(script)
|
|
6
7
|
|
|
8
|
+
local Blend = require("Blend")
|
|
7
9
|
local Maid = require("Maid")
|
|
8
10
|
local SimpleLoopedSoundPlayer = require("SimpleLoopedSoundPlayer")
|
|
9
|
-
local Blend = require("Blend")
|
|
10
11
|
|
|
11
12
|
return function(target)
|
|
12
13
|
local maid = Maid.new()
|
|
@@ -20,45 +21,43 @@ return function(target)
|
|
|
20
21
|
|
|
21
22
|
local function button(props)
|
|
22
23
|
return Blend.New "TextButton" {
|
|
23
|
-
Text = props.Text
|
|
24
|
-
AutoButtonColor = true
|
|
25
|
-
Font = Enum.Font.FredokaOne
|
|
26
|
-
Size = UDim2.new(0, 100, 0, 30)
|
|
27
|
-
|
|
28
|
-
Blend.New "UICorner" {
|
|
24
|
+
Text = props.Text,
|
|
25
|
+
AutoButtonColor = true,
|
|
26
|
+
Font = Enum.Font.FredokaOne,
|
|
27
|
+
Size = UDim2.new(0, 100, 0, 30),
|
|
29
28
|
|
|
30
|
-
}
|
|
29
|
+
Blend.New "UICorner" {},
|
|
31
30
|
|
|
32
31
|
[Blend.OnEvent "Activated"] = function()
|
|
33
|
-
props.OnActivated()
|
|
34
|
-
end
|
|
35
|
-
}
|
|
32
|
+
props.OnActivated()
|
|
33
|
+
end,
|
|
34
|
+
}
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
maid:GiveTask(Blend.mount(target, {
|
|
39
38
|
Blend.New "Frame" {
|
|
40
|
-
Name = "ButtonContainer"
|
|
41
|
-
BackgroundTransparency = 1
|
|
42
|
-
Position = UDim2.new(0.5, 0, 0, 5)
|
|
43
|
-
AnchorPoint = Vector2.new(0.5, 0)
|
|
44
|
-
Size = UDim2.new(1, 0, 0, 30)
|
|
39
|
+
Name = "ButtonContainer",
|
|
40
|
+
BackgroundTransparency = 1,
|
|
41
|
+
Position = UDim2.new(0.5, 0, 0, 5),
|
|
42
|
+
AnchorPoint = Vector2.new(0.5, 0),
|
|
43
|
+
Size = UDim2.new(1, 0, 0, 30),
|
|
45
44
|
|
|
46
45
|
Blend.New "UIListLayout" {
|
|
47
|
-
FillDirection = Enum.FillDirection.Horizontal
|
|
48
|
-
Padding = UDim.new(0, 5)
|
|
49
|
-
HorizontalAlignment = Enum.HorizontalAlignment.Center
|
|
50
|
-
}
|
|
46
|
+
FillDirection = Enum.FillDirection.Horizontal,
|
|
47
|
+
Padding = UDim.new(0, 5),
|
|
48
|
+
HorizontalAlignment = Enum.HorizontalAlignment.Center,
|
|
49
|
+
},
|
|
51
50
|
|
|
52
51
|
button({
|
|
53
|
-
Text = "Toggle"
|
|
52
|
+
Text = "Toggle",
|
|
54
53
|
OnActivated = function()
|
|
55
54
|
simpleLoopedSoundPlayer:Toggle()
|
|
56
|
-
end
|
|
57
|
-
})
|
|
58
|
-
}
|
|
55
|
+
end,
|
|
56
|
+
}),
|
|
57
|
+
},
|
|
59
58
|
}))
|
|
60
59
|
|
|
61
60
|
return function()
|
|
62
61
|
maid:DoCleaning()
|
|
63
62
|
end
|
|
64
|
-
end
|
|
63
|
+
end
|
|
@@ -4,52 +4,60 @@
|
|
|
4
4
|
|
|
5
5
|
local require = require(script.Parent.loader).load(script)
|
|
6
6
|
|
|
7
|
-
local t = require("t")
|
|
8
7
|
local NumberRangeUtils = require("NumberRangeUtils")
|
|
9
8
|
local Table = require("Table")
|
|
9
|
+
local t = require("t")
|
|
10
10
|
|
|
11
11
|
local SoundLoopScheduleUtils = {}
|
|
12
12
|
|
|
13
|
-
function SoundLoopScheduleUtils.schedule(loopedSchedule)
|
|
13
|
+
function SoundLoopScheduleUtils.schedule(loopedSchedule: SoundLoopSchedule): SoundLoopSchedule
|
|
14
14
|
assert(SoundLoopScheduleUtils.isLoopedSchedule(loopedSchedule))
|
|
15
15
|
|
|
16
16
|
return table.freeze(loopedSchedule)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
function SoundLoopScheduleUtils.onNextLoop(loopedSchedule)
|
|
20
|
-
assert(SoundLoopScheduleUtils.isLoopedSchedule(loopedSchedule) or loopedSchedule == nil, "Bad loopedSchedule")
|
|
19
|
+
function SoundLoopScheduleUtils.onNextLoop(loopedSchedule: SoundLoopSchedule): SoundLoopSchedule
|
|
20
|
+
assert(SoundLoopScheduleUtils.isLoopedSchedule(loopedSchedule) or loopedSchedule == nil, "Bad loopedSchedule")
|
|
21
21
|
|
|
22
22
|
loopedSchedule = loopedSchedule or {}
|
|
23
23
|
return SoundLoopScheduleUtils.schedule(Table.merge(loopedSchedule, {
|
|
24
|
-
playOnNextLoop = true
|
|
24
|
+
playOnNextLoop = true,
|
|
25
25
|
}))
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
function SoundLoopScheduleUtils.maxLoops(maxLoops, loopedSchedule)
|
|
28
|
+
function SoundLoopScheduleUtils.maxLoops(maxLoops: number, loopedSchedule: SoundLoopSchedule): SoundLoopSchedule
|
|
29
29
|
assert(type(maxLoops) == "number", "Bad maxLoops")
|
|
30
30
|
assert(SoundLoopScheduleUtils.isLoopedSchedule(loopedSchedule) or loopedSchedule == nil, "Bad loopedSchedule")
|
|
31
31
|
|
|
32
32
|
loopedSchedule = loopedSchedule or {}
|
|
33
33
|
return SoundLoopScheduleUtils.schedule(Table.merge(loopedSchedule, {
|
|
34
|
-
maxLoops = maxLoops
|
|
34
|
+
maxLoops = maxLoops,
|
|
35
35
|
}))
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
function SoundLoopScheduleUtils.default()
|
|
38
|
+
function SoundLoopScheduleUtils.default(): SoundLoopSchedule
|
|
39
39
|
return SoundLoopScheduleUtils.schedule({})
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
SoundLoopScheduleUtils.isWaitTimeSeconds = t.union(t.number, t.NumberRange)
|
|
43
43
|
|
|
44
44
|
SoundLoopScheduleUtils.isLoopedSchedule = t.interface({
|
|
45
|
-
playOnNextLoop = t.optional(t.boolean)
|
|
46
|
-
maxLoops = t.optional(t.number)
|
|
47
|
-
initialDelay = t.optional(SoundLoopScheduleUtils.isWaitTimeSeconds)
|
|
48
|
-
loopDelay = t.optional(SoundLoopScheduleUtils.isWaitTimeSeconds)
|
|
49
|
-
maxInitialWaitTimeForNextLoop = t.optional(SoundLoopScheduleUtils.isWaitTimeSeconds)
|
|
45
|
+
playOnNextLoop = t.optional(t.boolean),
|
|
46
|
+
maxLoops = t.optional(t.number),
|
|
47
|
+
initialDelay = t.optional(SoundLoopScheduleUtils.isWaitTimeSeconds),
|
|
48
|
+
loopDelay = t.optional(SoundLoopScheduleUtils.isWaitTimeSeconds),
|
|
49
|
+
maxInitialWaitTimeForNextLoop = t.optional(SoundLoopScheduleUtils.isWaitTimeSeconds),
|
|
50
50
|
})
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
export type SoundLoopSchedule = {
|
|
53
|
+
playOnNextLoop: boolean?,
|
|
54
|
+
maxLoops: number?,
|
|
55
|
+
initialDelay: number | NumberRange?,
|
|
56
|
+
loopDelay: number | NumberRange?,
|
|
57
|
+
maxInitialWaitTimeForNextLoop: number | NumberRange?,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function SoundLoopScheduleUtils.getWaitTimeSeconds(waitTime: number | NumberRange): number
|
|
53
61
|
assert(SoundLoopScheduleUtils.isWaitTimeSeconds(waitTime))
|
|
54
62
|
|
|
55
63
|
if type(waitTime) == "number" then
|
|
@@ -61,4 +69,4 @@ function SoundLoopScheduleUtils.getWaitTimeSeconds(waitTime)
|
|
|
61
69
|
end
|
|
62
70
|
end
|
|
63
71
|
|
|
64
|
-
return SoundLoopScheduleUtils
|
|
72
|
+
return SoundLoopScheduleUtils
|