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
121
122
123
124
125
126
127
128
129
130
131
|
#include "scene.hpp"
#include "ecs.hpp"
#include "pk.h"
#include "serialization.hpp"
#include "game-settings.hpp"
#include <fstream>
#include <string.h>
#include <filesystem>
struct pke_scene_master {
pk_membucket *bkt;
pk_bkt_arr_t<pke_scene> bc;
} scene_mstr;
void pke_scene_master_init() {
scene_mstr.bkt = pk_mem_bucket_create("pk_bkt_arr scene", 1024 * 1024, PK_MEMBUCKET_FLAG_NONE);
new (&scene_mstr.bc) pk_bkt_arr_t<pke_scene>{ pk_bkt_arr_handle_MAX_constexpr, scene_mstr.bkt, scene_mstr.bkt };
}
void pke_scene_master_teardown() {
scene_mstr.bc.~pk_bkt_arr_t<pke_scene>();
pk_mem_bucket_destroy(scene_mstr.bkt);
}
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{ pk_bkt_arr_new_handle(&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[scene_handle];
new (scene) pke_scene{};
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[scene_handle];
}
// 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.game_transient);
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);
using SceneFindFn = pk_tmpln_2<bool, const struct pke_scene *, const struct pke_scene *, const void *, const void *>;
SceneFindFn scene_find_cb{};
scene_find_cb.func = [&safe_name](const struct pke_scene *user_obj_data, const struct pke_scene *arr_obj_data) {
(void)user_obj_data;
return memcmp(safe_name, arr_obj_data->name, PK_MIN(strlen(safe_name), SCENE_NAME_MAX_LEN)) == 0;
};
SceneHandle handle { pk_bkt_arr_find_first_handle(&scene_mstr.bc, &SceneFindFn::invoke, &scene_find_cb, NULL) };
if (handle == SceneHandle_MAX) return nullptr;
return &scene_mstr.bc[handle];
}
pk_bkt_arr *pke_scene_get_scenes() {
return &scene_mstr.bc;
}
void pke_scene_remove(SceneHandle handle) {
uint32_t i;
pke_scene *scn = &scene_mstr.bc[handle];
assert(scn != nullptr && "[pke_scene_remove] Failed to find scene by requested SceneHandle");
ECS_MarkForRemoval(scn);
for (i = 0; i < scn->cameras.next; ++i) {
PkeCamera_Destroy(scn->cameras[i]);
}
for (i = 0; i < scn->input_handles.next; ++i) {
pke_input_deactivate_set(scn->input_handles[i]);
pke_input_unregister_set(scn->input_handles[i]);
}
if (scn->file_path.reserved > 0) {
pk_delete_arr<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);
pk_arr_reset(&scn->input_handles);
pk_bkt_arr_free_handle(&scene_mstr.bc, handle);
}
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);
}
void pke_scene_register_input_action_set(SceneHandle scene_handle, pke_input_action_set_handle handle) {
assert(scene_handle != SceneHandle_MAX);
assert(handle != pke_input_action_set_handle_MAX);
pke_scene *scene = pke_scene_get_by_handle(scene_handle);
assert(scene != nullptr && "Failed to find scene by requested SceneHandle");
pk_arr_append_t(&scene->input_handles, handle);
}
|