@quenty/spring 2.2.0 → 3.0.1-canary.238.2c4d310.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 CHANGED
@@ -3,6 +3,25 @@
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
+ ## [3.0.1-canary.238.2c4d310.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/spring@3.0.0...@quenty/spring@3.0.1-canary.238.2c4d310.0) (2021-12-29)
7
+
8
+ **Note:** Version bump only for package @quenty/spring
9
+
10
+
11
+
12
+
13
+
14
+ # [3.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/spring@2.2.0...@quenty/spring@3.0.0) (2021-12-22)
15
+
16
+
17
+ ### Features
18
+
19
+ * Add spring support for UDim2 and UDim and Vector2 ([d1763d7](https://github.com/Quenty/NevermoreEngine/commit/d1763d7cdc65ad5df4bbe38897cd9a446bb61bb1))
20
+
21
+
22
+
23
+
24
+
6
25
  # [2.2.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/spring@2.1.0...@quenty/spring@2.2.0) (2021-12-18)
7
26
 
8
27
 
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  ## Spring
2
2
  <div align="center">
3
- <a href="http://quenty.github.io/api/">
3
+ <a href="http://quenty.github.io/NevermoreEngine/">
4
4
  <img src="https://img.shields.io/badge/docs-website-green.svg" alt="Documentation" />
5
5
  </a>
6
6
  <a href="https://discord.gg/mhtGUS8">
7
- <img src="https://img.shields.io/badge/discord-nevermore-blue.svg" alt="Discord" />
7
+ <img src="https://img.shields.io/discord/385151591524597761?color=5865F2&label=discord&logo=discord&logoColor=white" alt="Discord" />
8
8
  </a>
9
9
  <a href="https://github.com/Quenty/NevermoreEngine/actions">
10
10
  <img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/build.yml/badge.svg" alt="Build and release status" />
@@ -19,40 +19,5 @@ upon index making this model good for lazy applications
19
19
  npm install @quenty/spring --save
20
20
  ```
21
21
 
22
-
23
- ## API
24
-
25
- `Spring = Spring.new(number position)`
26
- Creates a new spring in 1D
27
- `Spring = Spring.new(Vector3 position)`
28
- Creates a new spring in 3D
29
-
30
- `Spring.Position`
31
- Returns the current position
32
- `Spring.Velocity`
33
- Returns the current velocity
34
- `Spring.Target`
35
- Returns the target
36
- `Spring.Damper`
37
- Returns the damper
38
- `Spring.Speed`
39
- Returns the speed
40
-
41
- `Spring.Target = number/Vector3`
42
- Sets the target
43
- `Spring.Position = number/Vector3`
44
- Sets the position
45
- `Spring.Velocity = number/Vector3`
46
- Sets the velocity
47
- `Spring.Damper = number [0, 1]`
48
- Sets the spring damper, defaults to 1
49
- `Spring.Speed = number [0, infinity)`
50
- Sets the spring speed, defaults to 1
51
-
52
- `Spring:TimeSkip(number DeltaTime)`
53
- Instantly skips the spring forwards by that amount of now
54
- `Spring:Impulse(number/Vector3 velocity)`
55
- Impulses the spring, increasing velocity by the amount given
56
-
57
22
  ## Visualization
58
23
  by Defaultio: https://www.desmos.com/calculator/hn2i9shxbz
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/spring",
3
- "version": "2.2.0",
3
+ "version": "3.0.1-canary.238.2c4d310.0",
4
4
  "description": "Spring implementation for Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -29,7 +29,7 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@quenty/loader": "^3.1.1"
32
+ "@quenty/loader": "3.1.2-canary.238.2c4d310.0"
33
33
  },
34
- "gitHead": "6eb398e9fb81191f0815885f807ab0cb3bb9bad1"
34
+ "gitHead": "2c4d310b84afd0570d89667dc5d4aa69a0ef304a"
35
35
  }
@@ -1,11 +1,19 @@
1
- ---
2
- -- @classmod LinearValue
3
- -- @author Quenty
1
+ --[=[
2
+ Represents a value that can operate in linear space
4
3
 
4
+ @class LinearValue
5
+ ]=]
5
6
  local LinearValue = {}
6
7
  LinearValue.ClassName = "LinearValue"
7
8
  LinearValue.__index = LinearValue
8
9
 
10
+ --[=[
11
+ Constructs a new LinearValue object.
12
+
13
+ @param constructor (number ...) -> T
14
+ @param values ({ number })
15
+ @return LinearValue<T>
16
+ ]=]
9
17
  function LinearValue.new(constructor, values)
10
18
  return setmetatable({
11
19
  _constructor = constructor;
@@ -13,10 +21,21 @@ function LinearValue.new(constructor, values)
13
21
  }, LinearValue)
14
22
  end
15
23
 
24
+ --[=[
25
+ Returns whether or not a value is a LinearValue object.
26
+
27
+ @param value any -- A value to check
28
+ @return boolean -- True if a linear value, false otherwise
29
+ ]=]
16
30
  function LinearValue.isLinear(value)
17
31
  return type(value) == "table" and getmetatable(value) == LinearValue
18
32
  end
19
33
 
34
+ --[=[
35
+ Converts the value back to the base value
36
+
37
+ @return T
38
+ ]=]
20
39
  function LinearValue:ToBaseValue()
21
40
  return self._constructor(unpack(self._values))
22
41
  end
@@ -57,6 +76,11 @@ local function operation(func)
57
76
  end
58
77
  end
59
78
 
79
+ --[=[
80
+ Returns the magnitude of the linear value.
81
+
82
+ @return number -- The magnitude of the linear value.
83
+ ]=]
60
84
  function LinearValue:GetMagnitude()
61
85
  local dot = 0
62
86
  for i=1, #self._values do
@@ -66,6 +90,13 @@ function LinearValue:GetMagnitude()
66
90
  return math.sqrt(dot)
67
91
  end
68
92
 
93
+ --[=[
94
+ Returns the magnitude of the linear value.
95
+
96
+ @prop magnitude number
97
+ @readonly
98
+ @within LinearValue
99
+ ]=]
69
100
  function LinearValue:__index(key)
70
101
  if LinearValue[key] then
71
102
  return LinearValue[key]
@@ -92,5 +123,23 @@ LinearValue.__div = operation(function(a, b)
92
123
  return a / b
93
124
  end)
94
125
 
126
+ function LinearValue:__eq(a, b)
127
+ if LinearValue.isLinear(a) and LinearValue.isLinear(b) then
128
+ if #a._values ~= #b._values then
129
+ return false
130
+ end
131
+
132
+ for i=1, #a._values do
133
+ if a._values[i] ~= b._values[i] then
134
+ return false
135
+ end
136
+ end
137
+
138
+ return true
139
+ else
140
+ return false
141
+ end
142
+ end
143
+
95
144
 
96
145
  return LinearValue
@@ -1,53 +1,51 @@
1
- --[[
2
- class Spring
3
-
4
- Description:
5
- A physical model of a spring, useful in many applications. Properties only evaluate
6
- upon index making this model good for lazy applications
7
-
8
- API:
9
- Spring = Spring.new(number position)
10
- Creates a new spring in 1D
11
- Spring = Spring.new(Vector3 position)
12
- Creates a new spring in 3D
13
-
14
- Spring.Position
15
- Returns the current position
16
- Spring.Velocity
17
- Returns the current velocity
18
- Spring.Target
19
- Returns the target
20
- Spring.Damper
21
- Returns the damper
22
- Spring.Speed
23
- Returns the speed
24
-
25
- Spring.Target = number/Vector3
26
- Sets the target
27
- Spring.Position = number/Vector3
28
- Sets the position
29
- Spring.Velocity = number/Vector3
30
- Sets the velocity
31
- Spring.Damper = number [-infinity, infinity]
32
- Sets the spring damper, defaults to 1
33
- Spring.Speed = number [0, infinity)
34
- Sets the spring speed, defaults to 1
35
-
36
- Spring:TimeSkip(number DeltaTime)
37
- Instantly skips the spring forwards by that amount of now
38
- Spring:Impulse(number/Vector3 velocity)
39
- Impulses the spring, increasing velocity by the amount given
40
-
41
- Visualization (by Defaultio):
42
- https://www.desmos.com/calculator/hn2i9shxbz
43
- ]]
1
+ --[=[
2
+ A physical model of a spring, useful in many applications.
3
+
4
+ A spring is an object that will compute based upon Hooke's law. Properties only evaluate
5
+ upon index making this model good for lazy applications.
6
+
7
+ ```lua
8
+ local RunService = game:GetService("RunService")
9
+ local UserInputService = game:GetService("UserInputService")
10
+
11
+ local spring = Spring.new(Vector3.new(0, 0, 0))
44
12
 
13
+ RunService.RenderStepped:Connect(function()
14
+ if UserInputService:IsKeyDown(Enum.KeyCode.W) then
15
+ spring.Target = Vector3.new(0, 0, 1)
16
+ else
17
+ spring.Target = Vector3.new(0, 0, 0)
18
+ end
19
+
20
+ print(spring.Position) -- A smoothed out version of the input keycode W
21
+ end)
22
+ ```
23
+
24
+ A good visualization can be fond here, provided by Defaultio:
25
+ https://www.desmos.com/calculator/hn2i9shxbz
45
26
 
27
+ @class Spring
28
+ ]=]
46
29
  local Spring = {}
47
30
 
48
- --- Creates a new spring
49
- -- @param initial A number or Vector3 (anything with * number and addition/subtraction defined)
50
- -- @param[opt=os.clock] clock function to use to update spring
31
+ --[=[
32
+ Constructs a new Spring at the position and target specified, of type T.
33
+
34
+ ```lua
35
+ -- Linear spring
36
+ local linearSpring = Spring.new(0)
37
+
38
+ -- Vector2 spring
39
+ local vector2Spring = Spring.new(Vector2.new(0, 0))
40
+
41
+ -- Vector3 spring
42
+ local vector3Spring = Spring.new(Vector3.new(0, 0, 0))
43
+ ```
44
+
45
+ @param initial T -- The initial parameter is a number or Vector3 (anything with * number and addition/subtraction).
46
+ @param clock? () -> number -- The clock function is option, and is used to update the spring
47
+ @return Spring<T>
48
+ ]=]
51
49
  function Spring.new(initial, clock)
52
50
  local target = initial or 0
53
51
  clock = clock or os.clock
@@ -62,14 +60,22 @@ function Spring.new(initial, clock)
62
60
  }, Spring)
63
61
  end
64
62
 
65
- --- Impulse the spring with a change in velocity
66
- -- @param velocity The velocity to impulse with
63
+ --[=[
64
+ Impulses the spring, increasing velocity by the amount given. This is useful to make something shake,
65
+ like a Mac password box failing.
66
+
67
+ @param velocity T -- The velocity to impulse with
68
+ @return ()
69
+ ]=]
67
70
  function Spring:Impulse(velocity)
68
71
  self.Velocity = self.Velocity + velocity
69
72
  end
70
73
 
71
- --- Skip forwards in now
72
- -- @param delta now to skip forwards
74
+ --[=[
75
+ Instantly skips the spring forwards by that amount time
76
+ @param delta number-- Time to skip forwards
77
+ @return ()
78
+ ]=]
73
79
  function Spring:TimeSkip(delta)
74
80
  local now = self._clock()
75
81
  local position, velocity = self:_positionVelocity(now+delta)
@@ -78,6 +84,87 @@ function Spring:TimeSkip(delta)
78
84
  self._time0 = now
79
85
  end
80
86
 
87
+ --[=[
88
+ The current position at the given clock time. Assigning the position will change the spring to have that position.
89
+
90
+ ```lua
91
+ local spring = Spring.new(0)
92
+ print(spring.Position) --> 0
93
+ ```
94
+
95
+ @prop Position T
96
+ @within Spring
97
+ ]=]
98
+ --[=[
99
+ Alias for [Spring.Position](/api/Spring#Position)
100
+
101
+ @prop p T
102
+ @within Spring
103
+ ]=]
104
+ --[=[
105
+ The current velocity. Assigning the velocity will change the spring to have that velocity.
106
+
107
+ ```lua
108
+ local spring = Spring.new(0)
109
+ print(spring.Velocity) --> 0
110
+ ```
111
+
112
+ @prop Velocity T
113
+ @within Spring
114
+ ]=]
115
+ --[=[
116
+ Alias for [Spring.Velocity](/api/Spring#Velocity)
117
+
118
+ @prop v T
119
+ @within Spring
120
+ ]=]
121
+ --[=[
122
+ The current target. Assigning the target will change the spring to have that target.
123
+
124
+ ```lua
125
+ local spring = Spring.new(0)
126
+ print(spring.Target) --> 0
127
+ ```
128
+
129
+ @prop Target T
130
+ @within Spring
131
+ ]=]
132
+ --[=[
133
+ Alias for [Spring.Target](/api/Spring#Target)
134
+ @prop t T
135
+ @within Spring
136
+ ]=]
137
+ --[=[
138
+ The current damper, defaults to 1. At 1 the spring is critically damped. At less than 1, it
139
+ will be underdamped, and thus, bounce, and at over 1, it will be critically damped.
140
+
141
+ @prop Damper number
142
+ @within Spring
143
+ ]=]
144
+ --[=[
145
+ Alias for [Spring.Damper](/api/Spring#Damper)
146
+
147
+ @prop d number
148
+ @within Spring
149
+ ]=]
150
+ --[=[
151
+ The speed, defaults to 1, but should be between [0, infinity)
152
+
153
+ @prop Speed number
154
+ @within Spring
155
+ ]=]
156
+ --[=[
157
+ Alias for [Spring.Speed](/api/Spring#Speed)
158
+
159
+ @prop s number
160
+ @within Spring
161
+ ]=]
162
+ --[=[
163
+ The current clock object to syncronize the spring against.
164
+
165
+ @prop Clock () -> number
166
+ @within Spring
167
+ ]=]
81
168
  function Spring:__index(index)
82
169
  if Spring[index] then
83
170
  return Spring[index]
@@ -181,4 +268,4 @@ function Spring:_positionVelocity(now)
181
268
  b0*p0 + b1*p1 + b2*v0
182
269
  end
183
270
 
184
- return Spring
271
+ return Spring
@@ -1,6 +1,7 @@
1
- ---
2
- -- @module SpringUtils
3
- -- @author Quenty
1
+ --[=[
2
+ Utility functions that are related to the Spring object
3
+ @class SpringUtils
4
+ ]=]
4
5
 
5
6
  local EPSILON = 1e-6
6
7
 
@@ -9,6 +10,15 @@ local LinearValue = require("LinearValue")
9
10
 
10
11
  local SpringUtils = {}
11
12
 
13
+ --[=[
14
+ Utility function that returns whether or not a spring is animating based upon
15
+ velocity and closeness to target, and as the second value, the value that should be
16
+ used.
17
+
18
+ @param spring Spring<T>
19
+ @param epsilon number? -- Optional epsilon
20
+ @return boolean, T
21
+ ]=]
12
22
  function SpringUtils.animating(spring, epsilon)
13
23
  epsilon = epsilon or EPSILON
14
24
 
@@ -19,11 +29,14 @@ function SpringUtils.animating(spring, epsilon)
19
29
  if type(target) == "number" then
20
30
  animating = math.abs(spring.Position - spring.Target) > epsilon
21
31
  or math.abs(spring.Velocity) > epsilon
22
- elseif typeof(target) == "Vector3" or LinearValue.isLinear(target) then
23
- animating = (spring.Position - spring.Target).magnitude > epsilon
24
- or spring.Velocity.magnitude > epsilon
25
32
  else
26
- error("Unknown type")
33
+ local rbxtype = typeof(target)
34
+ if rbxtype == "Vector3" or rbxtype == "Vector2" or LinearValue.isLinear(target) then
35
+ animating = (spring.Position - spring.Target).magnitude > epsilon
36
+ or spring.Velocity.magnitude > epsilon
37
+ else
38
+ error("Unknown type")
39
+ end
27
40
  end
28
41
 
29
42
  if animating then
@@ -34,7 +47,14 @@ function SpringUtils.animating(spring, epsilon)
34
47
  end
35
48
  end
36
49
 
37
- -- Add to spring position to adjust for velocity of target. May have to set clock to time().
50
+ --[=[
51
+ Add to spring position to adjust for velocity of target. May have to set clock to time().
52
+
53
+ @param velocity T
54
+ @param dampen number
55
+ @param speed number
56
+ @return T
57
+ ]=]
38
58
  function SpringUtils.getVelocityAdjustment(velocity, dampen, speed)
39
59
  assert(velocity, "Bad velocity")
40
60
  assert(dampen, "Bad dampen")
@@ -43,14 +63,31 @@ function SpringUtils.getVelocityAdjustment(velocity, dampen, speed)
43
63
  return velocity*(2*dampen/speed)
44
64
  end
45
65
 
66
+ --[=[
67
+ Converts an arbitrary value to a LinearValue if Roblox has not defined this value
68
+ for multiplication and addition.
69
+
70
+ @param value T
71
+ @return LinearValue<T> | T
72
+ ]=]
46
73
  function SpringUtils.toLinearIfNeeded(value)
47
74
  if typeof(value) == "Color3" then
48
75
  return LinearValue.new(Color3.new, {value.r, value.g, value.b})
76
+ elseif typeof(value) == "UDim2" then
77
+ return LinearValue.new(UDim2.new, {value.x.scale, value.x.offset, value.y.scale, value.y.offset})
78
+ elseif typeof(value) == "UDim" then
79
+ return LinearValue.new(UDim.new, {value.scale, value.offset})
49
80
  else
50
81
  return value
51
82
  end
52
83
  end
53
84
 
85
+ --[=[
86
+ Extracts the base value out of a packed linear value if needed.
87
+
88
+ @param value LinearValue<T> | any
89
+ @return T | any
90
+ ]=]
54
91
  function SpringUtils.fromLinearIfNeeded(value)
55
92
  if LinearValue.isLinear(value) then
56
93
  return value:ToBaseValue()