#load "../renderer/directional_light.jai"; #load "particles.jai"; #placeholder Entity_Storage; MAX_CACHED_PILES :: 8; Scene :: struct { name: string; entities : [..] *Entity; particle_systems : Bucket_Array(Particle_System, 64); bullet_impact_particle_systems : [..] *Particle_System; by_type : Entity_Storage; pool : Flat_Pool; allocator : Allocator; camera : Camera; directional_light : Directional_Light; } Entity_File_Info :: struct { id: s64; full_path: string; } visitor :: (info : *File_Visit_Info, files: *[..] Entity_File_Info) { if info.is_directory return; path, basename, ext := path_decomp (info.full_name); // Entity text files if ext == "ent" && basename != "cam" { file_info : Entity_File_Info; file_info.id = cast(s32)string_to_int(basename); file_info.full_path = copy_temporary_string(info.full_name); array_add(files, file_info); } } load_scene :: (path: string) -> *Scene { scene := create_scene("", 1024); files : [..] Entity_File_Info; files.allocator = temp; visit_files(path, true, *files, visitor); for file: files { deserialize_entity(scene, file.full_path); } return scene; } save_scene :: (scene: *Scene, path: string) { scene.camera = game_state.camera; builder : String_Builder; builder.allocator = temp; full_path := tprint("%/%", path, scene.name); make_directory_if_it_does_not_exist(full_path); for scene.entities { if it.flags & .DONT_SAVE continue; serialize_entity(it, full_path); } // Save camera //print_to_builder(*builder, "Camera: % % % % %\n", scene.camera.position.x, scene.camera.position.y, scene.camera.position.z, scene.camera.rotation.yaw, scene.camera.rotation.pitch); //write_entire_file(path, builder_to_string(*builder)); } unload_scene :: (scene: *Scene) { for e: scene.entities { destroy_entity(e, false); } fini(*scene.pool); free(scene); } create_scene :: (name: string, max_entities: s64 = 256) -> *Scene { scene := New(Scene); scene.name = copy_string(name); // Setup allocator scene.pool = .{}; scene.allocator.data = *scene.pool; scene.allocator.proc = flat_pool_allocator_proc; // Assign allocator to everything that needs allocations scene.entities.allocator = scene.allocator; scene.particle_systems.allocator = scene.allocator; scene.bullet_impact_particle_systems.allocator = scene.allocator; array_reserve(*scene.entities, max_entities); scene.directional_light.color_and_intensity = .{1,1,1,1}; scene.directional_light.direction = to_v4(normalize(Vector3.{0.3, -0.3, 0.5})); dir_light_data : Directional_Light_Buffer_Data; dir_light_data.color_and_intensity = scene.directional_light.color_and_intensity; dir_light_data.direction = scene.directional_light.direction; upload_data_to_buffer(renderer, directional_light_buffer, *dir_light_data, size_of(Directional_Light_Buffer_Data)); array_resize(*scene.bullet_impact_particle_systems, 32); for 0..31 { scene.bullet_impact_particle_systems[it] = create_particle_system(particle_pipeline, on_update_bullet_hit_particles, null, scene); } return scene; } register_entity :: (scene: *Scene, entity: *Entity) { entity.scene = scene; entity.id = next_entity_id; array_add(*scene.entities, entity); next_entity_id += 1; if net_data.net_mode == { case .LISTEN_SERVER; #through; case .DEDICATED_SERVER; { //net_spawn_entity(entity); } } } unregister_entity :: (scene: *Scene, entity: *Entity) { array_unordered_remove_by_value(*scene.entities, entity); } #scope_file next_entity_id: Entity_Id;