small racing game im working on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
extends Object
class_name Thumbnail

@warning_ignore("shadowed_global_identifier")
static func _load(p: String, hash: PackedByteArray, error_if_hash_mismatch := true) -> Image:
	if FileAccess.file_exists(p):
		var f := FileAccess.open(p, FileAccess.READ)
		var img := Image.new()
		var buf := f.get_buffer(f.get_length())
		if buf:
			var dict: Dictionary = bytes_to_var(buf)
			var e := img.load_png_from_buffer(dict.b)
			if e != OK:
				push_error("error: ", e)
				return null
			if dict.h != hash:
				if error_if_hash_mismatch:
					push_error("error loading thumbnail %s: hash (thumbnail hash) %s != (file hash) %s" % [p, dict.h.hex_encode(), hash.hex_encode()])
				return null
			return img
	return null

static func hash_f(p: String) -> PackedByteArray:
	var file := FileAccess.open(p, FileAccess.READ)
	return hash_b(file.get_buffer(file.get_length()))

static func hash_b(b: PackedByteArray) -> PackedByteArray:
	var h := HashingContext.new()
	h.start(HashingContext.HASH_SHA1)
	h.update(b)
	return h.finish()

static func create_thumb(parent: Node, node: Node3D, size := Vector2i(64, 64), world := World3D.new()) -> Image:
	var port := SubViewport.new()
	port.size = size
	port.msaa_3d = Viewport.MSAA_4X
	port.screen_space_aa = Viewport.SCREEN_SPACE_AA_FXAA
	port.own_world_3d = true
	port.world_3d = world
	parent.add_child(port)
	port.add_child(node)
	port.render_target_update_mode = SubViewport.UPDATE_ONCE
	await RenderingServer.frame_post_draw
	var img: Image = port.get_texture().get_image()
	port.queue_free()
	return img

@warning_ignore("shadowed_global_identifier")
static func save(img: Image, p: String, hash: PackedByteArray) -> Error:
	if !DirAccess.dir_exists_absolute(p.get_base_dir()):
		DirAccess.make_dir_recursive_absolute(p.get_base_dir())
	var file := FileAccess.open(p, FileAccess.WRITE)
	if file == null:
		return FileAccess.get_open_error()
	file.store_buffer(var_to_bytes({ b = img.save_png_to_buffer(), h = hash }))
	return OK