aboutsummaryrefslogtreecommitdiff
path: root/client/player
diff options
context:
space:
mode:
Diffstat (limited to 'client/player')
-rw-r--r--client/player/camera_recorder.gd92
-rw-r--r--client/player/camera_recorder.gd.uid1
-rw-r--r--client/player/follow_camera.tscn6
3 files changed, 98 insertions, 1 deletions
diff --git a/client/player/camera_recorder.gd b/client/player/camera_recorder.gd
new file mode 100644
index 00000000..8f398c2b
--- /dev/null
+++ b/client/player/camera_recorder.gd
@@ -0,0 +1,92 @@
+# Hurry Curry! - a game about cooking
+# Copyright (C) 2025 Hurry Curry! contributors
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+extends Node
+
+@export var record: bool = false
+@export var replay: bool = false
+@export_file var recording_path: String = ""
+
+@onready var camera: Camera3D = $".."
+
+var time = 0.
+var keyframes = [] # Array<[float, Transform3D]>
+
+func _ready() -> void:
+ if record and replay: return push_error("concurrent ecord and replay is not supported")
+ if replay: load_recording()
+
+func _exit_tree() -> void:
+ if record: save_recording()
+
+func load_recording():
+ print("Loading replay...")
+ var file := FileAccess.open(recording_path, FileAccess.READ)
+ var text := file.get_as_text()
+ keyframes.clear()
+ for line in text.split("\n"):
+ if line == "": continue
+ var toks = line.split(",")
+ var time2 = float(toks[0])
+ var transform = parse_transform(toks[1])
+ var fov = float(toks[2])
+ keyframes.push_back([time2, transform, fov])
+ print("Done")
+
+func save_recording():
+ print("Saving replay...")
+ var file := FileAccess.open(recording_path, FileAccess.WRITE)
+ var out = ""
+ for k in keyframes:
+ out += "%f,%s,%f\n" % [k[0], serialize_transform(k[1]), k[2]]
+ file.store_string(out)
+ print("Done")
+
+func serialize_transform(t: Transform3D) -> String:
+ return "%f|%f|%f|%f|%f|%f|%f|%f|%f|%f|%f|%f" % [
+ t.basis.x.x, t.basis.y.x, t.basis.z.x, t.origin.x,
+ t.basis.x.y, t.basis.y.y, t.basis.z.y, t.origin.y,
+ t.basis.x.z, t.basis.y.z, t.basis.z.z, t.origin.z,
+ ]
+
+func parse_transform(s: String) -> Transform3D:
+ var c := s.split("|")
+ var t := Transform3D.IDENTITY
+ t.basis.x.x = float(c[0])
+ t.basis.y.x = float(c[1])
+ t.basis.z.x = float(c[2])
+ t.origin.x = float(c[3])
+ t.basis.x.y = float(c[4])
+ t.basis.y.y = float(c[5])
+ t.basis.z.y = float(c[6])
+ t.origin.y = float(c[7])
+ t.basis.x.z = float(c[8])
+ t.basis.y.z = float(c[9])
+ t.basis.z.z = float(c[10])
+ t.origin.z = float(c[11])
+ return t
+
+func _process(dt: float):
+ if Global.game_paused: return
+ time += dt
+ if record: keyframes.push_back([time, camera.global_transform, camera.fov])
+ if replay:
+ var index = keyframes.bsearch_custom([time], func (a, b): return a[0] < b[0])
+ if index >= keyframes.size(): return
+ var from = keyframes[max(0, index - 1)]
+ var to = keyframes[index]
+ var t = (time - from[0]) / (to[0] - from[0])
+ camera.global_transform = from[1].interpolate_with(to[1], t)
+ camera.fov = from[2] * (1. - t) + to[2] * t
diff --git a/client/player/camera_recorder.gd.uid b/client/player/camera_recorder.gd.uid
new file mode 100644
index 00000000..8d312732
--- /dev/null
+++ b/client/player/camera_recorder.gd.uid
@@ -0,0 +1 @@
+uid://b7wqp72o1bxvu
diff --git a/client/player/follow_camera.tscn b/client/player/follow_camera.tscn
index f753aad0..ac0040c9 100644
--- a/client/player/follow_camera.tscn
+++ b/client/player/follow_camera.tscn
@@ -1,7 +1,11 @@
-[gd_scene load_steps=2 format=3 uid="uid://b31mlnao6ybt8"]
+[gd_scene load_steps=3 format=3 uid="uid://b31mlnao6ybt8"]
[ext_resource type="Script" uid="uid://eieoab04mpqc" path="res://player/follow_camera.gd" id="1_qipju"]
+[ext_resource type="Script" uid="uid://b7wqp72o1bxvu" path="res://player/camera_recorder.gd" id="2_12um7"]
[node name="FollowCamera" type="Camera3D"]
fov = 45.0
script = ExtResource("1_qipju")
+
+[node name="CameraRecorder" type="Node" parent="."]
+script = ExtResource("2_12um7")