@quenty/animations 1.0.1-canary.385.c37a0ad.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 ADDED
@@ -0,0 +1,11 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## 1.0.1-canary.385.c37a0ad.0 (2023-07-10)
7
+
8
+
9
+ ### Features
10
+
11
+ * Add utility package to play back animations easily ([46c33ea](https://github.com/Quenty/NevermoreEngine/commit/46c33ea401987b14ba9c674280e56cd5d4cfe530))
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2014-2023 James Onnen (Quenty)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,23 @@
1
+ ## Animations
2
+
3
+ <div align="center">
4
+ <a href="http://quenty.github.io/NevermoreEngine/">
5
+ <img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/docs.yml/badge.svg" alt="Documentation status" />
6
+ </a>
7
+ <a href="https://discord.gg/mhtGUS8">
8
+ <img src="https://img.shields.io/discord/385151591524597761?color=5865F2&label=discord&logo=discord&logoColor=white" alt="Discord" />
9
+ </a>
10
+ <a href="https://github.com/Quenty/NevermoreEngine/actions">
11
+ <img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/build.yml/badge.svg" alt="Build and release status" />
12
+ </a>
13
+ </div>
14
+
15
+ Utility methods for playing back animations on Roblox
16
+
17
+ <div align="center"><a href="https://quenty.github.io/NevermoreEngine/api/AnimationsUtils">View docs →</a></div>
18
+
19
+ ## Installation
20
+
21
+ ```
22
+ npm install @quenty/animations --save
23
+ ```
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "animations",
3
+ "tree": {
4
+ "$path": "src"
5
+ }
6
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@quenty/animations",
3
+ "version": "1.0.1-canary.385.c37a0ad.0",
4
+ "description": "Utility methods for playing back animations on Roblox",
5
+ "keywords": [
6
+ "Roblox",
7
+ "Nevermore",
8
+ "Lua",
9
+ "animations"
10
+ ],
11
+ "bugs": {
12
+ "url": "https://github.com/Quenty/NevermoreEngine/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/Quenty/NevermoreEngine.git",
17
+ "directory": "src/animations/"
18
+ },
19
+ "funding": {
20
+ "type": "patreon",
21
+ "url": "https://www.patreon.com/quenty"
22
+ },
23
+ "license": "MIT",
24
+ "contributors": [
25
+ "Quenty"
26
+ ],
27
+ "dependencies": {
28
+ "@quenty/enumutils": "3.1.0",
29
+ "@quenty/humanoidanimatorutils": "2.1.2-canary.385.c37a0ad.0",
30
+ "@quenty/loader": "6.2.1",
31
+ "@quenty/promisemaid": "1.1.0",
32
+ "@quenty/rbxasset": "1.0.1-canary.385.c37a0ad.0"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "gitHead": "c37a0ad3981a0e27d4d9db436a0f21e675b12bf0"
38
+ }
@@ -0,0 +1,32 @@
1
+ --[=[
2
+ @class AnimationPromiseUtils
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local Promise = require("Promise")
8
+ local PromiseMaidUtils = require("PromiseMaidUtils")
9
+
10
+ local AnimationPromiseUtils = {}
11
+
12
+ function AnimationPromiseUtils.promiseFinished(animationTrack)
13
+ local promise = Promise.new()
14
+
15
+ PromiseMaidUtils.whilePromise(promise, function(maid)
16
+ maid:GiveTask(animationTrack.Ended:Connect(function()
17
+ promise:Resolve()
18
+ end))
19
+
20
+ maid:GiveTask(animationTrack.Stopped:Connect(function()
21
+ promise:Resolve()
22
+ end))
23
+
24
+ maid:GiveTask(animationTrack.Destroying:Connect(function()
25
+ promise:Resolve()
26
+ end))
27
+ end)
28
+
29
+ return promise
30
+ end
31
+
32
+ return AnimationPromiseUtils
@@ -0,0 +1,212 @@
1
+ --[=[
2
+ @class AnimationUtils
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local RbxAssetUtils = require("RbxAssetUtils")
8
+ local HumanoidAnimatorUtils = require("HumanoidAnimatorUtils")
9
+ local EnumUtils = require("EnumUtils")
10
+
11
+ local AnimationUtils = {}
12
+
13
+ --[=[
14
+ Plays the animation on the target instance.
15
+
16
+ @return AnimationTrack?
17
+ ]=]
18
+ function AnimationUtils.playAnimation(
19
+ target: Animator | Player | Model | AnimationController,
20
+ id: string | number,
21
+ fadeTime: number?,
22
+ weight: number?,
23
+ speed: number?,
24
+ priority: AnimationPriority?): AnimationTrack?
25
+ assert(typeof(target) == "Instance", "Bad target")
26
+ assert(RbxAssetUtils.isConvertableToRbxAsset(id), "Bad id")
27
+ assert(type(fadeTime) == "number" or fadeTime == nil, "Bad fadeTime")
28
+ assert(type(weight) == "number" or weight == nil, "Bad weight")
29
+ assert(type(speed) == "number" or speed == nil, "Bad speed")
30
+ assert(EnumUtils.isOfType(Enum.AnimationPriority, priority) or priority == nil, "Bad priority")
31
+
32
+ local animationTrack = AnimationUtils.getOrCreateAnimationTrack(target, id, priority)
33
+
34
+ if animationTrack then
35
+ animationTrack:Play(fadeTime, weight, speed)
36
+
37
+ if priority then
38
+ animationTrack.Priority = priority
39
+ end
40
+ else
41
+ warn(string.format("[AnimationUtils] - Failed to play animationTrack %q", tostring(id)))
42
+ end
43
+
44
+ return animationTrack
45
+ end
46
+
47
+ --[=[
48
+ Stops the animation on the target instance.
49
+ ]=]
50
+ function AnimationUtils.stopAnimation(target: Animator | Player | Model | AnimationController, id: string | number, fadeTime: number?): AnimationTrack?
51
+ assert(typeof(target) == "Instance", "Bad target")
52
+ assert(RbxAssetUtils.isConvertableToRbxAsset(id), "Bad id")
53
+ assert(type(fadeTime) == "number" or fadeTime == nil, "Bad fadeTime")
54
+
55
+ local animationTrack = AnimationUtils.findAnimationTrack(target, id)
56
+
57
+ if animationTrack then
58
+ animationTrack:Stop(fadeTime)
59
+ end
60
+
61
+ return animationTrack
62
+ end
63
+
64
+ --[=[
65
+ Gets or creates an animation track for the player
66
+ ]=]
67
+ function AnimationUtils.getOrCreateAnimationTrack(
68
+ target: Animator | Player | Model | AnimationController,
69
+ id: string | number,
70
+ priority: AnimationPriority?): AnimationTrack?
71
+ assert(typeof(target) == "Instance", "Bad target")
72
+ assert(RbxAssetUtils.isConvertableToRbxAsset(id), "Bad id")
73
+ assert(EnumUtils.isOfType(Enum.AnimationPriority, priority) or priority == nil, "Bad priority")
74
+
75
+ local animator = AnimationUtils.getOrCreateAnimator(target)
76
+ if not animator then
77
+ return nil
78
+ end
79
+
80
+ assert(typeof(animator) == "Instance" and animator:IsA("Animator"), "Bad animator")
81
+
82
+ local foundAnimationTrack = AnimationUtils.findAnimationTrackInAnimator(animator, id)
83
+ if foundAnimationTrack then
84
+ return foundAnimationTrack
85
+ end
86
+
87
+ local animation = AnimationUtils.getOrCreateAnimationFromIdInAnimator(animator, id)
88
+
89
+ local animationTrack
90
+ local ok, err = pcall(function()
91
+ animationTrack = animator:LoadAnimation(animation)
92
+ end)
93
+ if not ok then
94
+ warn(string.format("[AnimationUtils] - Failed to load animation with id %q due to %q", tostring(id), tostring(err)))
95
+ return nil
96
+ end
97
+
98
+ return animationTrack
99
+ end
100
+
101
+ function AnimationUtils.getOrCreateAnimationFromIdInAnimator(animator: Animator, id: string | number)
102
+ assert(typeof(animator) == "Instance" and animator:IsA("Animator"), "Bad animator")
103
+ assert(RbxAssetUtils.isConvertableToRbxAsset(id), "Bad id")
104
+
105
+ local animationId = RbxAssetUtils.toRbxAssetId(id)
106
+ for _, animation in pairs(animator:GetChildren()) do
107
+ if animation:IsA("Animation") then
108
+ if animation.AnimationId == animationId then
109
+ return animation
110
+ end
111
+ end
112
+ end
113
+
114
+ local animation = AnimationUtils.createAnimationFromId(id)
115
+ animation.Parent = animator
116
+
117
+ return animation
118
+ end
119
+
120
+ function AnimationUtils.findAnimationTrack(
121
+ target: Animator | Player | Model | AnimationController,
122
+ id: string | number)
123
+ assert(typeof(target) == "Instance", "Bad target")
124
+ assert(RbxAssetUtils.isConvertableToRbxAsset(id), "Bad id")
125
+
126
+ local animator = AnimationUtils.getOrCreateAnimator(target)
127
+ if not animator then
128
+ return nil
129
+ end
130
+
131
+ return AnimationUtils.findAnimationTrackInAnimator(animator, id)
132
+ end
133
+
134
+ function AnimationUtils.findAnimationTrackInAnimator(animator: Animator, id: string | number)
135
+ assert(typeof(animator) == "Instance" and animator:IsA("Animator"), "Bad animator")
136
+ assert(RbxAssetUtils.isConvertableToRbxAsset(id), "Bad id")
137
+
138
+ local animationId = RbxAssetUtils.toRbxAssetId(id)
139
+
140
+ for _, animationTrack in pairs(animator:GetPlayingAnimationTracks()) do
141
+ local animation = animationTrack.Animation
142
+ if animation and animation.AnimationId == animationId then
143
+ return animationTrack
144
+ end
145
+ end
146
+
147
+ return nil
148
+ end
149
+
150
+ --[=[
151
+ Finds an animator for the current instance
152
+ ]=]
153
+ function AnimationUtils.getOrCreateAnimator(target: Animator | Player | Model | AnimationController)
154
+ assert(typeof(target) == "Instance", "Bad target")
155
+
156
+ if target:IsA("Animator") then
157
+ return target
158
+ elseif target:IsA("Humanoid") then
159
+ return HumanoidAnimatorUtils.getOrCreateAnimator(target)
160
+ elseif target:IsA("AnimationController") then
161
+ return HumanoidAnimatorUtils.getOrCreateAnimator(target)
162
+ elseif target:IsA("Player") then
163
+ local character = target.Character
164
+ if not character then
165
+ return nil
166
+ end
167
+
168
+ local humanoid = character:FindFirstChildWhichIsA("Humanoid")
169
+ if not humanoid then
170
+ return nil
171
+ end
172
+
173
+ return HumanoidAnimatorUtils.getOrCreateAnimator(humanoid)
174
+ elseif target:IsA("Model") then
175
+ local humanoid = target:FindFirstChildWhichIsA("Humanoid")
176
+ if humanoid then
177
+ return HumanoidAnimatorUtils.getOrCreateAnimator(humanoid)
178
+ end
179
+
180
+ local animationController = target:FindFirstChildWhichIsA("AnimationController")
181
+ if animationController then
182
+ return HumanoidAnimatorUtils.getOrCreateAnimator(animationController)
183
+ end
184
+
185
+ return nil
186
+ else
187
+ return nil
188
+ end
189
+ end
190
+
191
+ function AnimationUtils.getAnimationId(animationId)
192
+ return string.format("Animation_%s", animationId)
193
+ end
194
+
195
+ --[=[
196
+ Creates a new animation object from the given id
197
+ ]=]
198
+ function AnimationUtils.createAnimationFromId(id: string | number): Animation
199
+ assert(RbxAssetUtils.isConvertableToRbxAsset(id), "Bad id")
200
+
201
+ local animationId = RbxAssetUtils.toRbxAssetId(id)
202
+ assert(type(animationId) == "string", "Bad id")
203
+
204
+ local animation = Instance.new("Animation")
205
+ animation.Name = AnimationUtils.getAnimationId(animationId)
206
+ animation.AnimationId = animationId
207
+ animation.Archivable = false
208
+
209
+ return animation
210
+ end
211
+
212
+ return AnimationUtils
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "node_modules",
3
+ "globIgnorePaths": [ "**/.package-lock.json" ],
4
+ "tree": {
5
+ "$path": { "optional": "../node_modules" }
6
+ }
7
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "AnimationTest",
3
+ "tree": {
4
+ "$className": "DataModel",
5
+ "ServerScriptService": {
6
+ "animations": {
7
+ "$path": ".."
8
+ },
9
+ "Script": {
10
+ "$path": "scripts/Server"
11
+ }
12
+ },
13
+ "StarterPlayer": {
14
+ "StarterPlayerScripts": {
15
+ "Main": {
16
+ "$path": "scripts/Client"
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,14 @@
1
+ --[[
2
+ @class ClientMain
3
+ ]]
4
+ local packages = game:GetService("ReplicatedStorage"):WaitForChild("Packages")
5
+
6
+ local Players = game:GetService("Players")
7
+
8
+ local AnimationUtils = require(packages:WaitForChild("AnimationUtils"))
9
+
10
+ game.UserInputService.InputBegan:Connect(function(inputObject)
11
+ if inputObject.KeyCode == Enum.KeyCode.Q then
12
+ AnimationUtils.playAnimation(Players.LocalPlayer, "rbxassetid://14012074834", nil, nil, 1, Enum.AnimationPriority.Action3)
13
+ end
14
+ end)
@@ -0,0 +1,8 @@
1
+ --[[
2
+ @class ServerMain
3
+ ]]
4
+ local ServerScriptService = game:GetService("ServerScriptService")
5
+
6
+ local loader = ServerScriptService:FindFirstChild("LoaderUtils", true).Parent
7
+ require(loader).bootstrapGame(ServerScriptService.animations)
8
+