@quenty/camera 9.15.0 → 9.16.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 +2 -2
- package/src/Client/CameraStackService.lua +5 -1
- package/src/Client/CameraState.lua +4 -0
- package/src/Client/Effects/DefaultCamera.lua +81 -6
- package/src/Client/Effects/HeartbeatCamera.lua +1 -1
- package/src/Client/Effects/ImpulseCamera.lua +1 -1
- package/src/Client/Effects/OverrideDefaultCameraToo.lua +69 -0
- package/src/Client/Utility/CameraStateTweener.lua +11 -13
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
|
+
# [9.16.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/camera@9.15.0...@quenty/camera@9.16.0) (2023-06-18)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Better interopability between Roblox and camera stack system ([1916352](https://github.com/Quenty/NevermoreEngine/commit/1916352394a777ec6ab01e869cc7d0cfe92bae76))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# [9.15.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/camera@9.14.0...@quenty/camera@9.15.0) (2023-06-17)
|
|
7
18
|
|
|
8
19
|
**Note:** Version bump only for package @quenty/camera
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/camera",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.16.0",
|
|
4
4
|
"description": "Quenty's camera system for Roblox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"publishConfig": {
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "2e4b57d56175186261d4f80a334816e03d63f80e"
|
|
47
47
|
}
|
|
@@ -48,10 +48,14 @@ function CameraStackService:Init(serviceBag)
|
|
|
48
48
|
debug.profilebegin("camerastackservice")
|
|
49
49
|
|
|
50
50
|
local state = self:GetTopState()
|
|
51
|
+
|
|
52
|
+
self._rawDefaultCamera:SetLastSetCameraFrame(state.CameraFrame)
|
|
53
|
+
|
|
51
54
|
if state then
|
|
52
55
|
state:Set(Workspace.CurrentCamera)
|
|
53
56
|
end
|
|
54
57
|
|
|
58
|
+
|
|
55
59
|
debug.profileend()
|
|
56
60
|
end)
|
|
57
61
|
|
|
@@ -72,7 +76,7 @@ function CameraStackService:Start()
|
|
|
72
76
|
Workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
|
|
73
77
|
end)
|
|
74
78
|
else
|
|
75
|
-
self._rawDefaultCamera:BindToRenderStep()
|
|
79
|
+
self._maid:GiveTask(self._rawDefaultCamera:BindToRenderStep())
|
|
76
80
|
end
|
|
77
81
|
end
|
|
78
82
|
|
|
@@ -54,6 +54,10 @@ function CameraState:__index(index)
|
|
|
54
54
|
return self.CameraFrame.CFrame
|
|
55
55
|
elseif index == "Position" then
|
|
56
56
|
return self.CameraFrame.Position
|
|
57
|
+
elseif index == "CameraFrame" then
|
|
58
|
+
return rawget(self, "CameraFrame")
|
|
59
|
+
elseif index == "CameraFrameDerivative" then
|
|
60
|
+
return rawget(self, "CameraFrameDerivative")
|
|
57
61
|
elseif index == "Velocity" then
|
|
58
62
|
return self.CameraFrameDerivative.Position
|
|
59
63
|
elseif index == "FieldOfView" then
|
|
@@ -14,6 +14,11 @@ local HttpService = game:GetService("HttpService")
|
|
|
14
14
|
|
|
15
15
|
local CameraState = require("CameraState")
|
|
16
16
|
local SummedCamera = require("SummedCamera")
|
|
17
|
+
local Maid = require("Maid")
|
|
18
|
+
local CFrameUtils = require("CFrameUtils")
|
|
19
|
+
local CameraFrame = require("CameraFrame")
|
|
20
|
+
|
|
21
|
+
local EPSILON = 0.001
|
|
17
22
|
|
|
18
23
|
local DefaultCamera = {}
|
|
19
24
|
DefaultCamera.ClassName = "DefaultCamera"
|
|
@@ -27,6 +32,7 @@ function DefaultCamera.new()
|
|
|
27
32
|
local self = setmetatable({}, DefaultCamera)
|
|
28
33
|
|
|
29
34
|
self._key = HttpService:GenerateGUID(false)
|
|
35
|
+
self._maid = Maid.new()
|
|
30
36
|
self._cameraState = CameraState.new(Workspace.CurrentCamera)
|
|
31
37
|
|
|
32
38
|
return self
|
|
@@ -40,14 +46,52 @@ end
|
|
|
40
46
|
Overrides the global field of view in the cached camera state
|
|
41
47
|
@param fieldOfView number
|
|
42
48
|
]=]
|
|
43
|
-
function DefaultCamera:
|
|
49
|
+
function DefaultCamera:SetRobloxFieldOfView(fieldOfView)
|
|
44
50
|
self._cameraState.FieldOfView = fieldOfView
|
|
45
51
|
end
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
-- Back compat
|
|
54
|
+
DefaultCamera.OverrideGlobalFieldOfView = DefaultCamera.SetRobloxFieldOfView
|
|
55
|
+
|
|
56
|
+
--[=[
|
|
57
|
+
Sets the Roblox camera state to look at things
|
|
58
|
+
|
|
59
|
+
@param cameraState CameraState
|
|
60
|
+
]=]
|
|
61
|
+
function DefaultCamera:SetRobloxCameraState(cameraState)
|
|
48
62
|
self._cameraState = cameraState or error("No CameraState")
|
|
49
63
|
end
|
|
50
64
|
|
|
65
|
+
-- Back compat
|
|
66
|
+
DefaultCamera.OverrideCameraState = DefaultCamera.SetRobloxCameraState
|
|
67
|
+
|
|
68
|
+
--[=[
|
|
69
|
+
Sets the CFrame of the Roblox Camera
|
|
70
|
+
|
|
71
|
+
@param cframe CFrame
|
|
72
|
+
]=]
|
|
73
|
+
function DefaultCamera:SetRobloxCFrame(cframe)
|
|
74
|
+
self._cameraState.CFrame = cframe
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
--[=[
|
|
78
|
+
Gets the current Roblox camera state, free of any influence
|
|
79
|
+
|
|
80
|
+
@return CameraState
|
|
81
|
+
]=]
|
|
82
|
+
function DefaultCamera:GetRobloxCameraState()
|
|
83
|
+
return self._cameraState
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
--[=[
|
|
87
|
+
Sets the camera state different
|
|
88
|
+
|
|
89
|
+
@param cameraFrame CameraState | nil
|
|
90
|
+
]=]
|
|
91
|
+
function DefaultCamera:SetLastSetCameraFrame(cameraFrame)
|
|
92
|
+
self._lastCameraFrame = CameraFrame.new(cameraFrame.QFrame, cameraFrame.FieldOfView)
|
|
93
|
+
end
|
|
94
|
+
|
|
51
95
|
--[=[
|
|
52
96
|
Binds the camera to RunService RenderStepped event.
|
|
53
97
|
|
|
@@ -56,30 +100,59 @@ end
|
|
|
56
100
|
:::
|
|
57
101
|
]=]
|
|
58
102
|
function DefaultCamera:BindToRenderStep()
|
|
103
|
+
local maid = Maid.new()
|
|
104
|
+
|
|
59
105
|
RunService:BindToRenderStep("DefaultCamera_Preupdate" .. self._key, Enum.RenderPriority.Camera.Value-2, function()
|
|
60
|
-
|
|
106
|
+
local camera = Workspace.CurrentCamera
|
|
107
|
+
|
|
108
|
+
if self._lastCameraFrame then
|
|
109
|
+
-- Assume something wrote these values and so we should
|
|
110
|
+
-- pass these through to Roblox's camera
|
|
111
|
+
|
|
112
|
+
if not CFrameUtils.areClose(self._lastCameraFrame.CFrame, camera.CFrame, EPSILON) then
|
|
113
|
+
self._cameraState.CFrame = camera.CFrame
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
if math.abs(self._lastCameraFrame.FieldOfView - camera.FieldOfView) > EPSILON then
|
|
117
|
+
self._cameraState.FieldOfView = camera.FieldOfView
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
self._lastCameraFrame = nil
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
-- Restore our state
|
|
124
|
+
self._cameraState:Set(camera)
|
|
61
125
|
end)
|
|
62
126
|
|
|
63
127
|
RunService:BindToRenderStep("DefaultCamera_PostUpdate" .. self._key, Enum.RenderPriority.Camera.Value+2, function()
|
|
128
|
+
-- Capture
|
|
64
129
|
self._cameraState = CameraState.new(Workspace.CurrentCamera)
|
|
65
130
|
end)
|
|
66
131
|
|
|
132
|
+
maid:GiveTask(function()
|
|
133
|
+
RunService:UnbindFromRenderStep("DefaultCamera_Preupdate" .. self._key)
|
|
134
|
+
RunService:UnbindFromRenderStep("DefaultCamera_PostUpdate" .. self._key)
|
|
135
|
+
end)
|
|
136
|
+
|
|
67
137
|
self._cameraState = CameraState.new(Workspace.CurrentCamera)
|
|
138
|
+
|
|
139
|
+
self._maid._binding = maid
|
|
140
|
+
|
|
141
|
+
return maid
|
|
68
142
|
end
|
|
69
143
|
|
|
70
144
|
--[=[
|
|
71
145
|
Unbinds the camera from the RunService
|
|
72
146
|
]=]
|
|
73
147
|
function DefaultCamera:UnbindFromRenderStep()
|
|
74
|
-
|
|
75
|
-
RunService:UnbindFromRenderStep("DefaultCamera_PostUpdate" .. self._key)
|
|
148
|
+
self._maid._binding = nil
|
|
76
149
|
end
|
|
77
150
|
|
|
78
151
|
--[=[
|
|
79
152
|
Cleans up the binding
|
|
80
153
|
]=]
|
|
81
154
|
function DefaultCamera:Destroy()
|
|
82
|
-
self:
|
|
155
|
+
self._maid:DoCleaning()
|
|
83
156
|
end
|
|
84
157
|
|
|
85
158
|
--[=[
|
|
@@ -91,6 +164,8 @@ end
|
|
|
91
164
|
function DefaultCamera:__index(index)
|
|
92
165
|
if index == "CameraState" then
|
|
93
166
|
return rawget(self, "_cameraState")
|
|
167
|
+
elseif index == "_maid" or index == "_lastCameraFrame" or index == "_key" then
|
|
168
|
+
return rawget(self, index)
|
|
94
169
|
else
|
|
95
170
|
return DefaultCamera[index]
|
|
96
171
|
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Allows you to override the default camera with this cameras
|
|
3
|
+
information. Useful for custom camera controls that the user
|
|
4
|
+
controls.
|
|
5
|
+
|
|
6
|
+
```lua
|
|
7
|
+
local combiner = OverrideDefaultCameraToo.new(effect, self._cameraStackService:GetRawDefaultCamera())
|
|
8
|
+
combiner.Predicate = function()
|
|
9
|
+
return self._cameraStateTweener:IsFinishedShowing()
|
|
10
|
+
end
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
@class OverrideDefaultCameraToo
|
|
14
|
+
]=]
|
|
15
|
+
|
|
16
|
+
local require = require(script.Parent.loader).load(script)
|
|
17
|
+
|
|
18
|
+
local SummedCamera = require("SummedCamera")
|
|
19
|
+
|
|
20
|
+
local OverrideDefaultCameraToo = {}
|
|
21
|
+
OverrideDefaultCameraToo.ClassName = "OverrideDefaultCameraToo"
|
|
22
|
+
|
|
23
|
+
--[=[
|
|
24
|
+
Initializes a new OverrideDefaultCameraToo
|
|
25
|
+
|
|
26
|
+
@param baseCamera Camera
|
|
27
|
+
@param defaultCamera DefaultCamera
|
|
28
|
+
@param predicate Filter on whether to override or not
|
|
29
|
+
]=]
|
|
30
|
+
function OverrideDefaultCameraToo.new(baseCamera, defaultCamera, predicate)
|
|
31
|
+
local self = setmetatable({}, OverrideDefaultCameraToo)
|
|
32
|
+
|
|
33
|
+
self.BaseCamera = assert(baseCamera, "No baseCamera")
|
|
34
|
+
self.DefaultCamera = assert(defaultCamera, "No defaultCamera")
|
|
35
|
+
self.Predicate = predicate
|
|
36
|
+
|
|
37
|
+
return self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
function OverrideDefaultCameraToo:__add(other)
|
|
41
|
+
return SummedCamera.new(self, other)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
function OverrideDefaultCameraToo:__newindex(index, value)
|
|
45
|
+
if index == "BaseCamera" or index == "DefaultCamera" or index == "Predicate" then
|
|
46
|
+
rawset(self, index, value)
|
|
47
|
+
else
|
|
48
|
+
error(index .. " is not a valid member of OverrideDefaultCameraToo")
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
function OverrideDefaultCameraToo:__index(index)
|
|
53
|
+
if index == "CameraState" then
|
|
54
|
+
local result = self.BaseCamera.CameraState
|
|
55
|
+
|
|
56
|
+
local predicate = self.Predicate
|
|
57
|
+
if not predicate or predicate(result) then
|
|
58
|
+
self.DefaultCamera:SetRobloxCFrame(result.CFrame)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
return result
|
|
62
|
+
elseif index == "BaseCamera" or index == "DefaultCamera" or index == "Predicate" then
|
|
63
|
+
return rawget(self, index)
|
|
64
|
+
else
|
|
65
|
+
return OverrideDefaultCameraToo[index]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
return OverrideDefaultCameraToo
|
|
@@ -10,10 +10,10 @@ local require = require(script.Parent.loader).load(script)
|
|
|
10
10
|
|
|
11
11
|
local CameraStackService = require("CameraStackService")
|
|
12
12
|
local FadeBetweenCamera3 = require("FadeBetweenCamera3")
|
|
13
|
-
local Maid = require("Maid")
|
|
14
13
|
local ServiceBag = require("ServiceBag")
|
|
14
|
+
local BaseObject = require("BaseObject")
|
|
15
15
|
|
|
16
|
-
local CameraStateTweener = {}
|
|
16
|
+
local CameraStateTweener = setmetatable({}, BaseObject)
|
|
17
17
|
CameraStateTweener.ClassName = "CameraStateTweener"
|
|
18
18
|
CameraStateTweener.__index = CameraStateTweener
|
|
19
19
|
|
|
@@ -26,13 +26,11 @@ CameraStateTweener.__index = CameraStateTweener
|
|
|
26
26
|
@return CameraStateTweener
|
|
27
27
|
]=]
|
|
28
28
|
function CameraStateTweener.new(serviceBag, cameraEffect, speed)
|
|
29
|
-
local self = setmetatable(
|
|
29
|
+
local self = setmetatable(BaseObject.new(), CameraStateTweener)
|
|
30
30
|
|
|
31
31
|
assert(ServiceBag.isServiceBag(serviceBag), "No serviceBag")
|
|
32
32
|
assert(cameraEffect, "No cameraEffect")
|
|
33
33
|
|
|
34
|
-
self._maid = Maid.new()
|
|
35
|
-
|
|
36
34
|
self._cameraStackService = serviceBag:GetService(CameraStackService)
|
|
37
35
|
local cameraBelow, assign = self._cameraStackService:GetNewStateBelow()
|
|
38
36
|
|
|
@@ -86,6 +84,14 @@ function CameraStateTweener:IsFinishedHiding()
|
|
|
86
84
|
return self._fadeBetween.HasReachedTarget and self._fadeBetween.Target == 0
|
|
87
85
|
end
|
|
88
86
|
|
|
87
|
+
--[=[
|
|
88
|
+
Returns true if we're done showing
|
|
89
|
+
@return boolean
|
|
90
|
+
]=]
|
|
91
|
+
function CameraStateTweener:IsFinishedShowing()
|
|
92
|
+
return self._fadeBetween.HasReachedTarget and self._fadeBetween.Target == 1
|
|
93
|
+
end
|
|
94
|
+
|
|
89
95
|
--[=[
|
|
90
96
|
Hides the tweener, and invokes the callback once the tweener
|
|
91
97
|
is finished hiding.
|
|
@@ -172,12 +178,4 @@ function CameraStateTweener:GetFader()
|
|
|
172
178
|
return self._fadeBetween
|
|
173
179
|
end
|
|
174
180
|
|
|
175
|
-
--[=[
|
|
176
|
-
Cleans up the fader, preventing any animation at all
|
|
177
|
-
]=]
|
|
178
|
-
function CameraStateTweener:Destroy()
|
|
179
|
-
self._maid:DoCleaning()
|
|
180
|
-
setmetatable(self, nil)
|
|
181
|
-
end
|
|
182
|
-
|
|
183
181
|
return CameraStateTweener
|