#include "scene.hpp" #include "ecs.hpp" #include "pk.h" #include "serialization.hpp" #include "game-settings.hpp" #include #include #include struct pke_scene_master { pk_bkt_arr_t bc; } scene_mstr; void pke_scene_master_init() { new (&scene_mstr.bc) pk_bkt_arr_t{ pk_bkt_arr_handle_MAX_constexpr }; } void pke_scene_master_teardown() { scene_mstr.bc.~pk_bkt_arr_t(); } 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; 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(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); }