summaryrefslogtreecommitdiff
path: root/src/scene.cpp
blob: 7c383853b43e4f91d69027c1ad8a1be10b7119aa (plain)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

#include "scene.hpp"
#include "bucketed-array.hpp"
#include "ecs.hpp"
#include "serialization.hpp"
#include "game-settings.hpp"

#include <fstream>
#include <string.h>

#include <filesystem>

struct pke_scene_master {
	BucketContainer<pke_scene, SceneHandle> bc;
} scene_mstr;

void pke_scene_master_init() {
	Buckets_Init(scene_mstr.bc);
}

void pke_scene_master_teardown() {
	Buckets_Destroy(scene_mstr.bc);
}

pke_scene *pke_scene_create(const char *scene_name) {
	NULL_CHAR_ARR(safe_scene_name, SCENE_NAME_MAX_LEN);
	size_t offset;
	std::filesystem::path p(scene_name);
	sprintf(safe_scene_name, "%.15s", p.stem().c_str());
	struct pke_scene *scene = pke_scene_get_by_name(safe_scene_name);
	if (scene != nullptr) {
		fprintf(stderr, "[pke_scene_create] failed to create scene: pke_scene::name already in use.");
		return nullptr;
	}
	SceneHandle scene_handle = Buckets_NewHandle(scene_mstr.bc);
	if (scene_handle == SceneHandle_MAX) {
		fprintf(stderr, "[pke_scene_create] failed to get new scene handle from BucketContainer.");
		return nullptr;
	}
	scene = &scene_mstr.bc.buckets[scene_handle.bucketIndex][scene_handle.itemIndex];
	ECS_CreateEntity(scene);

	scene->scene_handle = scene_handle;
	offset = (strlen(safe_scene_name) > SCENE_NAME_MAX_LEN ? strlen(safe_scene_name) - SCENE_NAME_MAX_LEN : 0);
	for (int i = 0; i < SCENE_NAME_MAX_LEN; ++i) {
		scene->name[i] = safe_scene_name[i + offset];
	}
	return scene;
}

struct pke_scene *pke_scene_get_by_handle(SceneHandle scene_handle) {
	return &scene_mstr.bc.buckets[scene_handle.bucketIndex][scene_handle.itemIndex];
}

	// TODO remove me? Need to decide if we always read from files or if we should have a serialized representation of a scene
struct pke_scene *pke_scene_get_by_path(const char *file_path) {
	std::ifstream f(file_path);
	if (!f.is_open()) {
		fprintf(stderr, "[pke_scene_get_by_name] Scene not found in memory nor filesystem: '%s'\n", file_path);
		return nullptr;
	}
	srlztn_deserialize_helper *h = pke_deserialize_init(pkeSettings.mem.bkt);
	h->scene = pke_scene_create(file_path);
	pke_deserialize_scene_from_stream(f, h);
	pke_deserialize_teardown(h);
	return h->scene;
}

struct pke_scene *pke_scene_get_by_name(const char *scene_name) {
	assert(scene_name != nullptr);
	NULL_CHAR_ARR(safe_name, SCENE_NAME_MAX_LEN + 1);
	strncpy(safe_name, scene_name, SCENE_NAME_MAX_LEN + 1);
	pk_handle_bucket_index_T b;
	pk_handle_item_index_T i, ii;
	for (b = 0; b < scene_mstr.bc.pkeHandle.bucketIndex + 1; ++b) {
		ii = scene_mstr.bc.pkeHandle.bucketIndex == b ? scene_mstr.bc.pkeHandle.itemIndex : scene_mstr.bc.limits.itemIndex;
		for (i = 0; i < ii; ++i) {
			if (memcmp(safe_name, scene_mstr.bc.buckets[b][i].name, PK_MIN(strlen(safe_name), SCENE_NAME_MAX_LEN)) == 0) {
				return &scene_mstr.bc.buckets[b][i];
			}
		}
	}
	return nullptr;
}

pk_handle_bucket_index_T pke_scene_get_bucket_count() {
	return scene_mstr.bc.pkeHandle.bucketIndex + 1;
}

struct pke_scene *pke_scene_get_scenes(pk_handle_bucket_index_T bucket_index, pk_handle_item_index_T *item_count) {
	assert(bucket_index <= scene_mstr.bc.pkeHandle.bucketIndex);
	assert(item_count != nullptr);
	*item_count = bucket_index == scene_mstr.bc.pkeHandle.bucketIndex ? scene_mstr.bc.pkeHandle.itemIndex : scene_mstr.bc.limits.itemIndex;
	return scene_mstr.bc.buckets[bucket_index];
}

void pke_scene_remove(SceneHandle handle) {
	pke_scene *scn = pke_scene_get_by_handle(handle);
	assert(scn != nullptr && "[pke_scene_remove] Failed to find scene by requested SceneHandle");
	// TODO mark bucket slot as open
	ECS_MarkForRemoval(scn);
	for (long i = 0; i < scn->cameras.next; ++i) {
		PkeCamera_Destroy(scn->cameras[i]);
	}
	if (scn->file_path.reserved > 0) {
		pk_delete<char>(scn->file_path.val, scn->file_path.reserved);
	}
	scn->file_path = {};
	scn->name[0] = '\0';
	scn->scene_handle = SceneHandle_MAX;
	pk_arr_reset(&scn->cameras);
}

void pke_scene_register_camera(SceneHandle scene_handle, CameraHandle cameraHandle) {
	assert(scene_handle != SceneHandle_MAX);
	assert(cameraHandle != CameraHandle_MAX);
	pke_scene *scene = pke_scene_get_by_handle(scene_handle);
	assert(scene != nullptr && "Failed to find scene by requested SceneHandle");
	pk_arr_append(&scene->cameras, &cameraHandle);
}