parent
eae1436cbb
commit
a79189b18e
@ -1,242 +0,0 @@ |
||||
#ifndef COMMON_H |
||||
#define COMMON_H |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#include "num_types.h" |
||||
|
||||
#ifdef GAME_LIB |
||||
extern struct Platform_Api* platform; |
||||
#endif |
||||
|
||||
#ifdef GAME |
||||
extern struct Game_Api game; |
||||
#endif |
||||
|
||||
struct Window; |
||||
struct Hashmap; |
||||
struct Sound_Source_Buffer; |
||||
|
||||
//Physics Decls
|
||||
typedef void* Rigidbody; |
||||
typedef void* Collision_Shape; |
||||
typedef void (*RigidbodyMoveCB)(Rigidbody); |
||||
typedef void (*RigidbodyColCB)(Rigidbody, Rigidbody); |
||||
|
||||
// Function Pointer decls
|
||||
typedef void (*Keyboard_Event_Func) (int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt); |
||||
typedef void (*Mousebutton_Event_Func) (int button, int state, int x, int y, int8 num_clicks); |
||||
typedef void (*Mousemotion_Event_Func) (int x, int y, int xrel, int yrel); |
||||
typedef void (*Mousewheel_Event_Func) (int x, int y); |
||||
typedef void (*Windowresize_Event_Func) (int x, int y); |
||||
typedef void (*Textinput_Event_Func) (const char* text); |
||||
|
||||
enum Directory_Type |
||||
{ |
||||
DIRT_USER, /* User directory or preferences directory */ |
||||
DIRT_INSTALL, /* Directory where the game's assets are, usually alongside the game's executable where the game is installed */ |
||||
DIRT_EXECUTABLE, /* Directory where the game's executable is located */ |
||||
DIRT_COUNT |
||||
}; |
||||
|
||||
enum Sound_Source_Type |
||||
{ |
||||
ST_WAV = 0, |
||||
ST_WAV_STREAM |
||||
}; |
||||
|
||||
enum Sound_Attenuation_Type |
||||
{ |
||||
SA_NONE = 0, // No attenuation
|
||||
SA_INVERSE, // Inverse distance attenuation model
|
||||
SA_LINEAR, // Linear distance attenuation model
|
||||
SA_EXPONENTIAL // Exponential distance attenuation model
|
||||
}; |
||||
|
||||
enum Collision_Shape_Type |
||||
{ |
||||
CST_BOX = 0, |
||||
CST_SPHERE, |
||||
CST_CYLINDER, |
||||
CST_CAPSULE, |
||||
CST_PLANE, |
||||
CST_TRIMESH, |
||||
CST_UNKNOWN |
||||
}; |
||||
|
||||
struct Raycast_Hit |
||||
{ |
||||
int entity_id; |
||||
float normal_x, normal_y, normal_z; |
||||
}; |
||||
|
||||
struct Physics_Api |
||||
{ |
||||
void (*init)(void); |
||||
void (*cleanup)(void); |
||||
void (*step)(float); |
||||
void (*gravity_set)(float x, float y, float z); |
||||
void (*gravity_get)(float* x, float* y, float* z); |
||||
|
||||
void (*cs_remove)(Collision_Shape shape); |
||||
void (*cs_data_set)(Collision_Shape shape, void* data); |
||||
void* (*cs_data_get)(Collision_Shape shape); |
||||
int (*cs_type_get)(Collision_Shape shape); |
||||
|
||||
Collision_Shape (*cs_plane_create)(float a, float b, float c, float d); |
||||
void (*cs_plane_params_set)(Collision_Shape shape, float a, float b, float c, float d); |
||||
void (*cs_plane_params_get)(Collision_Shape shape, float* a, float* b, float* c, float* d); |
||||
|
||||
Collision_Shape (*cs_box_create)(float x, float y, float z); |
||||
void (*cs_box_params_set)(Collision_Shape shape, float x, float y, float z); |
||||
void (*cs_box_params_get)(Collision_Shape shape, float* x, float* y, float* z); |
||||
|
||||
Collision_Shape (*cs_sphere_create)(float radius); |
||||
void (*cs_shpere_radius_set)(Collision_Shape shape, float radius); |
||||
float (*cs_sphere_radius_get)(Collision_Shape shape); |
||||
|
||||
Collision_Shape (*cs_capsule_create)(float radius, float length); |
||||
void (*cs_capsule_params_set)(Collision_Shape shape, float radius, float length); |
||||
void (*cs_capsule_params_get)(Collision_Shape shape, float* radius, float* length); |
||||
|
||||
Collision_Shape (*cs_ray_create)(float length, bool first_contact, bool backface_cull); |
||||
bool (*cs_ray_cast)(Collision_Shape ray,
|
||||
struct Raycast_Hit* out_rayhit,
|
||||
float pos_x, float pos_y, float pos_z,
|
||||
float dir_x, float dir_y, float dir_z); |
||||
|
||||
void (*cs_position_set)(Collision_Shape shape, float x, float y, float z); |
||||
void (*cs_position_get)(Collision_Shape shape, float* x, float* y, float* z); |
||||
void (*cs_rotation_set)(Collision_Shape shape, float x, float y, float z, float w); |
||||
void (*cs_rotation_get)(Collision_Shape shape, float* x, float* y, float* z, float* w); |
||||
|
||||
void (*body_remove)(Rigidbody body); |
||||
Rigidbody (*body_box_create)(float length, float width, float height); |
||||
Rigidbody (*body_sphere_create)(float radius); |
||||
Rigidbody (*body_capsule_create)(float radius, float height); |
||||
Collision_Shape (*body_cs_get)(Rigidbody body); |
||||
void (*body_cs_set)(Rigidbody body, Collision_Shape shape); |
||||
void (*body_position_set)(Rigidbody body, float x, float y, float z); |
||||
void (*body_position_get)(Rigidbody body, float* x, float* y, float* z); |
||||
void (*body_rotation_set)(Rigidbody body, float x, float y, float z, float w); |
||||
void (*body_rotation_get)(Rigidbody body, float* x, float* y, float* z, float* w); |
||||
void (*body_set_moved_callback)(RigidbodyMoveCB callback); |
||||
void (*body_set_collision_callback)(RigidbodyColCB callback); |
||||
void (*body_kinematic_set)(Rigidbody body); |
||||
void (*body_mass_set)(Rigidbody body, float mass); |
||||
float (*body_mass_get)(Rigidbody body); |
||||
void* (*body_data_get)(Rigidbody body); |
||||
void (*body_data_set)(Rigidbody body, void* data); |
||||
void (*body_force_add)(Rigidbody body, float fx, float fy, float fz); |
||||
}; |
||||
|
||||
struct Sound_Api |
||||
{ |
||||
void (*update_3d)(void); |
||||
void (*volume_set)(float volume); |
||||
void (*listener_update)(float apos_x, float apos_y, float apos_z, |
||||
float afwd_x, float afwd_y, float afwd_z, |
||||
float aup_x, float aup_y, float aup_z); |
||||
|
||||
void (*source_instance_update_position)(uint source_instance, float apos_x, float apos_y, float apos_z); |
||||
uint (*source_instance_create)(struct Sound_Source_Buffer* source, bool is3d); |
||||
void (*source_instance_destroy)(uint source_instance); |
||||
void (*source_instance_volume_set)(uint source_instance, float volume); |
||||
void (*source_instance_loop_set)(uint source_instance, bool loop); |
||||
void (*source_instance_play)(uint source_instance); |
||||
void (*source_instance_pause)(uint source_instance); |
||||
void (*source_instance_rewind)(uint source_instance); |
||||
void (*source_instance_stop)(uint source_instance); |
||||
void (*source_instance_min_max_distance_set)(uint source_instance, float min_distance, float max_distance); |
||||
void (*source_instance_attenuation_set)(uint source_instance, int attenuation_type, float rolloff_factor); |
||||
float (*source_instance_volume_get)(uint source_instance); |
||||
bool (*source_instance_loop_get)(uint source_instance); |
||||
bool (*source_instance_is_paused)(uint source_instance); |
||||
|
||||
struct Sound_Source_Buffer* (*source_create)(const char* filename, int type); |
||||
struct Sound_Source_Buffer* (*source_get)(const char* name); |
||||
void (*source_destroy)(const char* buffer_name); |
||||
void (*source_volume_set)(struct Sound_Source_Buffer* source, float volume); |
||||
void (*source_loop_set)(struct Sound_Source_Buffer* source, bool loop); |
||||
void (*source_stop_all)(struct Sound_Source_Buffer* source); |
||||
void (*source_min_max_distance_set)(struct Sound_Source_Buffer* source, float min_distance, float max_distance); |
||||
}; |
||||
|
||||
struct Window_Api |
||||
{ |
||||
struct Window* (*create)(const char* title, int width, int height, int msaa, int msaa_levels); |
||||
void (*destroy)(struct Window* window); |
||||
void (*show)(struct Window* window); |
||||
void (*hide)(struct Window* window); |
||||
void (*raise)(struct Window* window); |
||||
void (*make_context_current)(struct Window* window); |
||||
void (*set_size)(struct Window* window, int width, int height); |
||||
void (*get_size)(struct Window* window, int* out_width, int* out_height); |
||||
void (*get_drawable_size)(struct Window* window, int* out_width, int* out_height); |
||||
void (*swap_buffers)(struct Window* window); |
||||
int (*fullscreen_set)(struct Window* window, int fullscreen); |
||||
}; |
||||
|
||||
struct File_Api |
||||
{ |
||||
char* (*read)(const int directory_type, const char* path, const char* mode, long* file_size); |
||||
FILE* (*open)(const int directory_type, const char* path, const char* mode); |
||||
bool (*copy)(const int directory_type, const char* source, const char* destination); |
||||
bool (*delete)(const int directory_type, const char* filename); |
||||
}; |
||||
|
||||
struct Config_Api |
||||
{ |
||||
bool (*load)(const char* filename, int directory_type); |
||||
bool (*save)(const char* filename, int directory_types); |
||||
struct Hashmap* (*get)(void); |
||||
}; |
||||
|
||||
struct Log_Api |
||||
{ |
||||
FILE* (*file_handle_get)(void); |
||||
}; |
||||
|
||||
struct Platform_Api |
||||
{ |
||||
// General platform api
|
||||
void (*poll_events)(bool* out_quit); |
||||
void (*keyboard_callback_set)(Keyboard_Event_Func func); |
||||
void (*mousebutton_callback_set)(Mousebutton_Event_Func func); |
||||
void (*mousemotion_callback_set)(Mousemotion_Event_Func func); |
||||
void (*mousewheel_callback_set)(Mousewheel_Event_Func func); |
||||
void (*windowresize_callback_set)(Windowresize_Event_Func func); |
||||
void (*textinput_callback_set)(Textinput_Event_Func func); |
||||
int (*is_key_pressed)(int key); |
||||
int (*mousebutton_state_get)(uint button); |
||||
void (*mouse_position_get)(int* x, int* y); |
||||
void (*mouse_delta_get)(int* x, int* y); |
||||
void (*mouse_position_set)(struct Window* window, int x, int y); |
||||
void (*mouse_global_position_set)(int x, int y); |
||||
void (*mouse_relative_mode_set)(int relative_mode); |
||||
int (*mouse_relative_mode_get)(void); |
||||
uint32 (*ticks_get)(void); |
||||
char* (*install_directory_get)(void); |
||||
char* (*user_directory_get)(const char* organization, const char* application); |
||||
void (*clipboard_text_set)(const char* text); |
||||
char* (*clipboard_text_get)(void); |
||||
int (*key_from_name)(const char* key_name); |
||||
const char* (*key_name_get)(int key); |
||||
void* (*load_function_gl)(const char* name); |
||||
void (*reload_game_lib)(void); |
||||
|
||||
struct Window_Api window; |
||||
struct Sound_Api sound; |
||||
struct File_Api file; |
||||
struct Config_Api config; |
||||
struct Log_Api log; |
||||
struct Physics_Api physics; |
||||
}; |
||||
|
||||
struct Game_Api |
||||
{ |
||||
bool (*init)(struct Window*, struct Platform_Api* platform_api); |
||||
void (*cleanup)(void); |
||||
}; |
||||
|
||||
#endif |
@ -1,323 +0,0 @@ |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "../common/log.h" |
||||
#include "sound.h" |
||||
#include "platform.h" |
||||
#include "physics.h" |
||||
#include "file_io.h" |
||||
#include "config_vars.h" |
||||
#include "../common/hashmap.h" |
||||
#include "../common/common.h" |
||||
|
||||
static struct Platform_Api platform_api; |
||||
static struct Window* window = NULL; |
||||
static bool reload_game = false; |
||||
#if defined(_MSC_VER) |
||||
static const char* lib_name = "Symmetry_Game.dll"; |
||||
static const char* lib_copy_name = "Symmetry_Game.copy.dll"; |
||||
#elif defined(__MINGW32__) || defined(__MINGW64__) |
||||
static const char* lib_name = "Symmetry_Game.dll"; |
||||
static const char* lib_copy_name = "Symmetry_Game.copy.dll"; |
||||
#endif |
||||
|
||||
void* game_lib_handle = NULL; |
||||
struct Game_Api game; |
||||
|
||||
bool init(void); |
||||
void cleanup(void); |
||||
bool game_lib_load(void); |
||||
void game_lib_reload(void); |
||||
|
||||
int main(int argc, char** args) |
||||
{ |
||||
if(!init()) |
||||
{ |
||||
log_to_stdout("ERR:(Main) Could not initialize"); |
||||
} |
||||
else |
||||
{ |
||||
platform_api = (struct Platform_Api) |
||||
{ |
||||
.poll_events = &platform_poll_events, |
||||
.keyboard_callback_set = &platform_keyboard_callback_set, |
||||
.mousebutton_callback_set = &platform_mousebutton_callback_set, |
||||
.mousemotion_callback_set = &platform_mousemotion_callback_set, |
||||
.mousewheel_callback_set = &platform_mousewheel_callback_set, |
||||
.windowresize_callback_set = &platform_windowresize_callback_set, |
||||
.textinput_callback_set = &platform_textinput_callback_set, |
||||
.is_key_pressed = &platform_is_key_pressed, |
||||
.mousebutton_state_get = &platform_mousebutton_state_get, |
||||
.mouse_position_get = &platform_mouse_position_get, |
||||
.mouse_delta_get = &platform_mouse_delta_get, |
||||
.mouse_position_set = &platform_mouse_position_set, |
||||
.mouse_global_position_set = &platform_mouse_global_position_set, |
||||
.mouse_relative_mode_set = &platform_mouse_relative_mode_set, |
||||
.mouse_relative_mode_get = &platform_mouse_relative_mode_get, |
||||
.ticks_get = &platform_ticks_get, |
||||
.install_directory_get = &platform_install_directory_get, |
||||
.user_directory_get = &platform_user_directory_get, |
||||
.clipboard_text_set = &platform_clipboard_text_set, |
||||
.clipboard_text_get = &platform_clipboard_text_get, |
||||
.key_from_name = &platform_key_from_name, |
||||
.key_name_get = &platform_key_name_get, |
||||
.load_function_gl = &platform_load_function_gl, |
||||
.reload_game_lib = &game_lib_reload, |
||||
.sound = |
||||
{ |
||||
.update_3d = &sound_update_3d, |
||||
.volume_set = &sound_volume_set, |
||||
.listener_update = &sound_listener_update, |
||||
.source_instance_update_position = &sound_source_instance_update_position, |
||||
.source_instance_create = &sound_source_instance_create, |
||||
.source_instance_destroy = &sound_source_instance_destroy, |
||||
.source_instance_volume_set = &sound_source_instance_volume_set, |
||||
.source_instance_loop_set = &sound_source_instance_loop_set, |
||||
.source_instance_play = &sound_source_instance_play, |
||||
.source_instance_pause = &sound_source_instance_pause, |
||||
.source_instance_rewind = &sound_source_instance_rewind, |
||||
.source_instance_stop = &sound_source_instance_stop, |
||||
.source_instance_min_max_distance_set = &sound_source_instance_min_max_distance_set, |
||||
.source_instance_attenuation_set = &sound_source_instance_attenuation_set, |
||||
.source_instance_volume_get = &sound_source_instance_volume_get, |
||||
.source_instance_loop_get = &sound_source_instance_loop_get, |
||||
.source_instance_is_paused = &sound_source_instance_is_paused, |
||||
.source_create = &sound_source_create, |
||||
.source_get = &sound_source_get, |
||||
.source_destroy = &sound_source_destroy, |
||||
.source_volume_set = &sound_source_volume_set, |
||||
.source_loop_set = &sound_source_loop_set, |
||||
.source_stop_all = &sound_source_stop_all, |
||||
.source_min_max_distance_set = &sound_source_min_max_distance_set |
||||
}, |
||||
.window = |
||||
{ |
||||
.create = &window_create, |
||||
.destroy = &window_destroy, |
||||
.show = &window_show, |
||||
.raise = &window_raise, |
||||
.make_context_current = &window_make_context_current, |
||||
.set_size = &window_set_size, |
||||
.get_size = &window_get_size, |
||||
.get_drawable_size = &window_get_drawable_size, |
||||
.swap_buffers = &window_swap_buffers, |
||||
.fullscreen_set = &window_fullscreen_set |
||||
}, |
||||
.file = |
||||
{ |
||||
.read = &io_file_read, |
||||
.open = &io_file_open, |
||||
.copy = &io_file_copy, |
||||
.delete = &io_file_delete |
||||
}, |
||||
.config = |
||||
{ |
||||
.load = &config_vars_load, |
||||
.save = &config_vars_save, |
||||
.get = &config_vars_get |
||||
}, |
||||
.log = |
||||
{ |
||||
.file_handle_get = &log_file_handle_get |
||||
}, |
||||
.physics =
|
||||
{ |
||||
.init = &physics_init, |
||||
.cleanup = &physics_cleanup, |
||||
.step = &physics_step, |
||||
.gravity_set = &physics_gravity_set, |
||||
.gravity_get = &physics_gravity_get, |
||||
|
||||
.body_position_set = &physics_body_position_set, |
||||
.body_position_get = &physics_body_position_get, |
||||
.body_rotation_set = &physics_body_rotation_set, |
||||
.body_rotation_get = &physics_body_rotation_get, |
||||
.body_kinematic_set = &physics_body_kinematic_set, |
||||
.body_mass_set = &physics_body_mass_set, |
||||
.body_mass_get = &physics_body_mass_get, |
||||
.body_data_set = &physics_body_data_set, |
||||
.body_data_get = &physics_body_data_get, |
||||
.body_set_moved_callback = &physics_body_set_moved_callback, |
||||
.body_set_collision_callback = &physics_body_set_collision_callback, |
||||
.body_force_add = &physics_body_force_add, |
||||
.body_box_create = &physics_body_box_create, |
||||
.body_sphere_create = &physics_body_sphere_create, |
||||
.body_capsule_create = &physics_body_capsule_create, |
||||
.body_remove = &physics_body_remove, |
||||
.body_cs_set = &physics_body_cs_set, |
||||
.body_cs_get = &physics_body_cs_get, |
||||
|
||||
.cs_box_create = &physics_cs_box_create, |
||||
.cs_plane_create = &physics_cs_plane_create, |
||||
.cs_sphere_create = &physics_cs_sphere_create, |
||||
.cs_capsule_create = &physics_cs_capsule_create, |
||||
.cs_remove = &physics_cs_remove, |
||||
.cs_position_set = &physics_cs_position_set, |
||||
.cs_position_get = &physics_cs_position_get, |
||||
.cs_rotation_set = &physics_cs_rotation_set, |
||||
.cs_rotation_get = &physics_cs_rotation_get, |
||||
.cs_type_get = &physics_cs_type_get, |
||||
.cs_data_set = &physics_cs_data_set, |
||||
.cs_data_get = &physics_cs_data_get, |
||||
.cs_plane_params_get = &physics_cs_plane_params_get, |
||||
.cs_capsule_params_get = &physics_cs_capsule_params_get, |
||||
.cs_box_params_get = &physics_cs_box_params_get, |
||||
.cs_sphere_radius_get = &physics_cs_sphere_radius_get, |
||||
.cs_plane_params_set = &physics_cs_plane_params_set, |
||||
.cs_capsule_params_set = &physics_cs_capsule_params_set, |
||||
.cs_box_params_set = &physics_cs_box_params_set, |
||||
.cs_shpere_radius_set = &physics_cs_sphere_radius_set, |
||||
.cs_ray_create = &physics_cs_ray_create, |
||||
.cs_ray_cast = &physics_cs_ray_cast |
||||
} |
||||
}; |
||||
|
||||
if(!game_lib_load()) |
||||
log_error("main", "Failed to load game library"); |
||||
else |
||||
{ |
||||
bool done = false; |
||||
while(!done) |
||||
{ |
||||
bool game_init_status = game.init(window, &platform_api); |
||||
if(!game_init_status) |
||||
{ |
||||
log_error("main", "Game init failed"); |
||||
} |
||||
|
||||
if(reload_game) |
||||
{ |
||||
reload_game = false; |
||||
if(game_lib_handle) |
||||
{ |
||||
if(game.cleanup) game.cleanup(); |
||||
platform_unload_library(game_lib_handle); |
||||
game_lib_handle = NULL; |
||||
game.cleanup = NULL; |
||||
game.init = NULL; |
||||
#if defined(_MSC_VER) |
||||
if(!io_file_delete(DIRT_EXECUTABLE, lib_copy_name)) |
||||
{ |
||||
done = true; |
||||
continue; |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
if(!game_lib_load()) |
||||
{ |
||||
log_error("main", "Failed to load game library"); |
||||
done = true; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
done = true; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
exit(EXIT_SUCCESS); |
||||
} |
||||
|
||||
bool init(void) |
||||
{ |
||||
if(atexit(cleanup) != 0) |
||||
{ |
||||
log_to_stdout("ERR: (main:init) Could not register cleanup func with atexit"); |
||||
return false; |
||||
} |
||||
|
||||
config_vars_init(); |
||||
if(!platform_init()) return false; |
||||
|
||||
char* install_path = platform_install_directory_get(); |
||||
char* user_path = platform_user_directory_get("SS_Games", "Symmetry"); |
||||
log_init("Log.txt", user_path); |
||||
io_file_init(install_path, user_path); |
||||
free(install_path); |
||||
free(user_path); |
||||
if(!config_vars_load("config.symtres", DIRT_USER)) |
||||
{ |
||||
log_error("main:init", "Could not load config, reverting to defaults"); |
||||
config_vars_save("config.symtres", DIRT_USER); |
||||
} |
||||
|
||||
if(!platform_init_video()) return false; |
||||
|
||||
if(!platform_load_gl(NULL)) |
||||
{ |
||||
log_error("main:init", "Initializing OpenGL failed"); |
||||
return false; |
||||
} |
||||
|
||||
struct Hashmap* cvars = config_vars_get(); |
||||
int width = hashmap_int_get(cvars, "render_width"); |
||||
int height = hashmap_int_get(cvars, "render_height"); |
||||
int msaa = hashmap_bool_get(cvars, "msaa_enabled"); |
||||
int msaa_levels = hashmap_int_get(cvars, "msaa_levels"); |
||||
window = window_create("Symmetry", width, height, msaa, msaa_levels); |
||||
if(!window) |
||||
{ |
||||
log_error("main:init", "Window creation failed"); |
||||
return false; |
||||
} |
||||
|
||||
if(!sound_init()) |
||||
{ |
||||
log_error("main:init", "Failed to initialize sound"); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
void cleanup(void) |
||||
{ |
||||
if(game.cleanup) game.cleanup(); |
||||
if(game_lib_handle) platform_unload_library(game_lib_handle); |
||||
if(window) window_destroy(window); |
||||
log_reset_all_callbacks(); // Now that the game library has been unloaded, reset all callbacks to stubs so we don't crash on exit
|
||||
sound_cleanup(); |
||||
platform_unload_gl(); |
||||
platform_cleanup(); |
||||
config_vars_cleanup(); |
||||
io_file_cleanup(); |
||||
log_message("Program exiting!"); |
||||
log_cleanup(); |
||||
} |
||||
|
||||
void game_lib_reload(void) |
||||
{ |
||||
reload_game = true; |
||||
} |
||||
|
||||
bool game_lib_load(void) |
||||
{ |
||||
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) |
||||
if(!io_file_copy(DIRT_EXECUTABLE, lib_name, lib_copy_name)) |
||||
{ |
||||
log_error("main:game_lib_load", "Failed to copy dll"); |
||||
return false; |
||||
} |
||||
|
||||
game_lib_handle = platform_load_library("Symmetry_Game.copy"); |
||||
#else |
||||
game_lib_handle = platform_load_library("Symmetry_Game"); |
||||
#endif |
||||
if(!game_lib_handle) |
||||
{ |
||||
log_error("main:game_lib_load", "Failed to load game library"); |
||||
return false; |
||||
} |
||||
|
||||
log_message("Game library loaded"); |
||||
game.init = platform_load_function(game_lib_handle, "game_init"); |
||||
game.cleanup = platform_load_function(game_lib_handle, "game_cleanup"); |
||||
if(!game.init && !game.cleanup) |
||||
return false; |
||||
|
||||
log_message("Game api loaded"); |
||||
return true; |
||||
} |
@ -0,0 +1,710 @@ |
||||
#include "scene.h" |
||||
#include "../common/array.h" |
||||
#include "entity.h" |
||||
#include "../common/log.h" |
||||
#include "transform.h" |
||||
#include "camera.h" |
||||
#include "../common/parser.h" |
||||
#include "model.h" |
||||
#include "light.h" |
||||
#include "player.h" |
||||
#include "game.h" |
||||
#include "bounding_volumes.h" |
||||
#include "geometry.h" |
||||
#include "editor.h" |
||||
#include "../system/sound.h" |
||||
#include "../system/physics.h" |
||||
|
||||
#include <assert.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
|
||||
void scene_init(struct Scene* scene) |
||||
{ |
||||
assert(scene); |
||||
//Initialize the root entity
|
||||
entity_init(&scene->root_entity, "ROOT_ENTITY", NULL); |
||||
scene->root_entity.active = true; |
||||
scene->root_entity.id = 0; |
||||
scene->root_entity.type = ET_ROOT; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) entity_reset(&scene->entities[i], i); |
||||
for(int i = 0; i < MAX_LIGHTS; i++) |
||||
{ |
||||
entity_reset(&scene->lights[i], i); |
||||
scene->lights[i].type = ET_LIGHT; |
||||
} |
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) |
||||
{ |
||||
entity_reset(&scene->static_meshes[i], i); |
||||
struct Static_Mesh* mesh = &scene->static_meshes[i]; |
||||
mesh->collision.collision_shape = NULL; |
||||
mesh->collision.rigidbody = NULL; |
||||
mesh->collision.on_collision = NULL; |
||||
mesh->model.geometry_index = -1; |
||||
mesh->model.material = NULL; |
||||
} |
||||
for(int i = 0; i < MAX_SOUND_SOURCES; i++) entity_reset(&scene->sound_sources[i], i); |
||||
for(int i = 0; i < MAX_CAMERAS; i++) |
||||
{ |
||||
entity_init(&scene->cameras[i], NULL, &scene->root_entity); |
||||
camera_init(&scene->cameras[i], 1024, 768); |
||||
scene->cameras[i].base.id = i; |
||||
} |
||||
|
||||
player_init(&scene->player, scene); |
||||
editor_init_camera(); |
||||
|
||||
scene->active_camera_index = game_state_get()->game_mode == GAME_MODE_GAME ? CAM_GAME : CAM_EDITOR; |
||||
} |
||||
|
||||
bool scene_load(struct Scene* scene, const char* filename, int dir_type) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
bool scene_save(struct Scene* scene, const char* filename, int dir_type) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
void scene_destroy(struct Scene* scene) |
||||
{ |
||||
assert(scene); |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) scene_entity_remove(scene, &scene->entities[i]); |
||||
for(int i = 0; i < MAX_CAMERAS; i++) scene_camera_remove(scene, &scene->cameras[i]); |
||||
for(int i = 0; i < MAX_LIGHTS; i++) scene_light_remove(scene, &scene->lights[i]); |
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]); |
||||
for(int i = 0; i < MAX_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]); |
||||
player_destroy(&scene->player); |
||||
entity_reset(&scene->root_entity, 0); |
||||
scene->root_entity.active = false; |
||||
} |
||||
|
||||
void scene_update(struct Scene* scene, float dt) |
||||
{ |
||||
if(game_state_get()->game_mode == GAME_MODE_GAME) player_update(&scene->player, scene, dt); |
||||
} |
||||
|
||||
void scene_post_update(struct Scene* scene) |
||||
{ |
||||
assert(scene); |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
struct Entity* entity = &scene->entities[i]; |
||||
if(!entity->active) continue; |
||||
|
||||
if(entity->marked_for_deletion) |
||||
{ |
||||
scene_entity_remove(scene, entity); |
||||
continue; |
||||
} |
||||
|
||||
if(entity->transform.is_modified) entity->transform.is_modified = false; |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_CAMERAS; i++) |
||||
{ |
||||
struct Camera* camera = &scene->cameras[i]; |
||||
if(!camera->base.active) continue; |
||||
|
||||
if(camera->base.marked_for_deletion) |
||||
{ |
||||
scene_camera_remove(scene, camera); |
||||
continue; |
||||
} |
||||
|
||||
if(camera->base.transform.is_modified) |
||||
{ |
||||
camera_update_view(camera); |
||||
camera->base.transform.is_modified = false; |
||||
} |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_SOUND_SOURCES; i++) |
||||
{ |
||||
struct Sound_Source* sound_source = &scene->sound_sources[i]; |
||||
if(!sound_source->base.active) continue; |
||||
|
||||
if(sound_source->base.marked_for_deletion) |
||||
{ |
||||
scene_sound_source_remove(scene, sound_source); |
||||
continue; |
||||
} |
||||
|
||||
if(sound_source->base.transform.is_modified) |
||||
{ |
||||
vec3 abs_pos = { 0.f, 0.f, 0.f }; |
||||
transform_get_absolute_position(&sound_source->base, &abs_pos); |
||||
sound_source_instance_update_position(sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z); |
||||
sound_source->base.transform.is_modified = false; |
||||
} |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) |
||||
{ |
||||
struct Static_Mesh* static_mesh = &scene->static_meshes[i]; |
||||
if(!static_mesh->base.active) continue; |
||||
|
||||
if(static_mesh->base.marked_for_deletion) |
||||
{ |
||||
scene_static_mesh_remove(scene, static_mesh); |
||||
continue; |
||||
} |
||||
|
||||
if(static_mesh->base.transform.is_modified) |
||||
{ |
||||
if(static_mesh->collision.rigidbody && static_mesh->base.transform.sync_physics) |
||||
{ |
||||
quat abs_rot = { 0.f, 0.f, 0.f, 1.f }; |
||||
vec3 abs_pos = { 0.f, 0.f, 0.f }; |
||||
transform_get_absolute_rot(&static_mesh->base, &abs_rot); |
||||
transform_get_absolute_position(&static_mesh->base, &abs_pos); |
||||
physics_body_rotation_set(static_mesh->collision.rigidbody, abs_rot.x, abs_rot.y, abs_rot.z, abs_rot.w); |
||||
physics_body_position_set(static_mesh->collision.rigidbody, abs_pos.x, abs_pos.y, abs_pos.z); |
||||
} |
||||
static_mesh->base.transform.sync_physics = false; |
||||
static_mesh->base.transform.is_modified = false; |
||||
} |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_LIGHTS; i++) |
||||
{ |
||||
struct Light* light = &scene->lights[i]; |
||||
if(!light->base.active) continue; |
||||
|
||||
if(light->base.marked_for_deletion) |
||||
{ |
||||
scene_light_remove(scene, light); |
||||
continue; |
||||
} |
||||
|
||||
if(light->base.transform.is_modified) light->base.transform.is_modified = false; |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
struct Entity* entity = &scene->entities[i]; |
||||
if(!entity->active) continue; |
||||
} |
||||
|
||||
if(scene->player.base.transform.is_modified) |
||||
{ |
||||
vec3 abs_pos = { 0.f, 0.f, 0.f }; |
||||
vec3 abs_fwd = { 0.f, 0.f, -1.f }; |
||||
vec3 abs_up = { 0.f, 1.f, 0.f }; |
||||
transform_get_absolute_position(&scene->player, &abs_pos); |
||||
transform_get_absolute_forward(&scene->player, &abs_fwd); |
||||
transform_get_absolute_up(&scene->player, &abs_up); |
||||
|
||||
sound_listener_update(abs_pos.x, abs_pos.y, abs_pos.z, |
||||
abs_fwd.x, abs_fwd.y, abs_fwd.z, |
||||
abs_up.x, abs_up.y, abs_up.z); |
||||
scene->player.base.transform.is_modified = false; |
||||
} |
||||
} |
||||
|
||||
struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent) |
||||
{ |
||||
assert(scene); |
||||
|
||||
struct Entity* new_entity = NULL; |
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
struct Entity* entity = &scene->entities[i]; |
||||
if(!entity->active) |
||||
{ |
||||
new_entity = entity; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_entity) |
||||
{ |
||||
if(!parent) |
||||
parent = &scene->root_entity; |
||||
entity_init(new_entity, name, parent); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:entity_create", "Max entity limit reached!"); |
||||
} |
||||
|
||||
return new_entity; |
||||
} |
||||
|
||||
struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type) |
||||
{ |
||||
assert(scene); |
||||
struct Light* new_light = NULL; |
||||
for(int i = 0; i < MAX_LIGHTS; i++) |
||||
{ |
||||
struct Light* light = &scene->lights[i]; |
||||
if(!light->base.active) |
||||
{ |
||||
new_light = light; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_light) |
||||
{ |
||||
entity_init(&new_light->base, name, parent ? parent : &scene->root_entity); |
||||
new_light->base.type = ET_LIGHT; |
||||
light_init(new_light, light_type); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:light_create", "Max light limit reached!"); |
||||
} |
||||
|
||||
return new_light; |
||||
} |
||||
|
||||
struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height) |
||||
{ |
||||
assert(scene); |
||||
struct Camera* new_camera = NULL; |
||||
for(int i = 0; i < MAX_CAMERAS; i++) |
||||
{ |
||||
struct Camera* camera = &scene->cameras[i]; |
||||
if(!camera->base.active) |
||||
{ |
||||
new_camera = camera; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_camera) |
||||
{ |
||||
entity_init(&new_camera->base, name, parent ? parent : &scene->root_entity); |
||||
new_camera->base.type = ET_CAMERA; |
||||
camera_init(new_camera, width, height); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:camera_create", "Max camera limit reached!"); |
||||
} |
||||
|
||||
return new_camera; |
||||
} |
||||
|
||||
struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* name, struct Entity* parent, const char* geometry_name, int material_type) |
||||
{ |
||||
assert(scene); |
||||
struct Static_Mesh* new_static_mesh = NULL; |
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) |
||||
{ |
||||
struct Static_Mesh* static_mesh = &scene->static_meshes[i]; |
||||
if(!static_mesh->base.active) |
||||
{ |
||||
new_static_mesh = static_mesh; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_static_mesh) |
||||
{ |
||||
entity_init(&new_static_mesh->base, name, parent ? parent : &scene->root_entity); |
||||
new_static_mesh->base.type = ET_STATIC_MESH; |
||||
model_init(&new_static_mesh->model, new_static_mesh, geometry_name, material_type); |
||||
// TODO: handle creating collision mesh for the model at creation
|
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:model_create", "Max model limit reached!"); |
||||
} |
||||
|
||||
return new_static_mesh; |
||||
} |
||||
|
||||
struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play) |
||||
{ |
||||
assert(scene && filename); |
||||
struct Sound_Source* new_sound_source = NULL; |
||||
for(int i = 0; i < MAX_SOUND_SOURCES; i++) |
||||
{ |
||||
struct Sound_Source* sound_source = &scene->static_meshes[i]; |
||||
if(!sound_source->base.active) |
||||
{ |
||||
new_sound_source = sound_source; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_sound_source) |
||||
{ |
||||
entity_init(&new_sound_source->base, name, parent ? parent : &scene->root_entity); |
||||
new_sound_source->base.type = ET_SOUND_SOURCE; |
||||
struct Entity* entity = &new_sound_source->base; |
||||
|
||||
new_sound_source->source_buffer = sound_source_create(filename, type); |
||||
if(!new_sound_source->source_buffer) |
||||
{ |
||||
log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", filename, entity->name); |
||||
new_sound_source->source_instance = 0; |
||||
return new_sound_source; |
||||
} |
||||
|
||||
new_sound_source->source_instance = sound_source_instance_create(new_sound_source->source_buffer, true); |
||||
vec3 abs_pos = { 0.f, 0.f, 0.f }; |
||||
vec3 abs_fwd = { 0.f, 0.f, -1.f }; |
||||
vec3 abs_up = { 0.f, 1.f, 0.f }; |
||||
transform_get_absolute_position(entity, &abs_pos); |
||||
transform_get_absolute_forward(entity, &abs_fwd); |
||||
transform_get_absolute_up(entity, &abs_up); |
||||
sound_source_instance_update_position(new_sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z); |
||||
|
||||
new_sound_source->loop = loop; |
||||
new_sound_source->min_distance = 0.f; |
||||
new_sound_source->max_distance = 10.f; |
||||
new_sound_source->playing = play; |
||||
new_sound_source->attenuation_type = SA_INVERSE; |
||||
new_sound_source->rolloff_factor = 0.95f; |
||||
new_sound_source->volume = 1.f; |
||||
new_sound_source->type = type; |
||||
|
||||
sound_source_instance_loop_set(new_sound_source->source_instance, new_sound_source->loop); |
||||
sound_source_instance_min_max_distance_set(new_sound_source->source_instance, new_sound_source->min_distance, new_sound_source->max_distance); |
||||
sound_source_instance_attenuation_set(new_sound_source->source_instance, new_sound_source->attenuation_type, new_sound_source->rolloff_factor); |
||||
sound_source_instance_volume_set(new_sound_source->source_instance, new_sound_source->volume); |
||||
|
||||
sound_update_3d(); |
||||
if(new_sound_source->playing) sound_source_instance_play(new_sound_source->source_instance); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:sound_source_create", "Max sound source limit reached!"); |
||||
} |
||||
|
||||
return new_sound_source; |
||||
} |
||||
|
||||
void scene_entity_remove(struct Scene* scene, struct Entity* entity) |
||||
{ |
||||
assert(scene && entity && entity->id >= 0); |
||||
|
||||
if(!entity->active) return; |
||||
|
||||
transform_destroy(entity); |
||||
entity->active = false; |
||||
entity->editor_selected = false; |
||||
entity->marked_for_deletion = false; |
||||
memset(entity->name, '\0', MAX_ENTITY_NAME_LEN); |
||||
} |
||||
|
||||
void scene_light_remove(struct Scene* scene, struct Light* light) |
||||
{ |
||||
assert(scene && light); |
||||
scene_entity_remove(scene, &light->base); |
||||
} |
||||
|
||||
void scene_camera_remove(struct Scene* scene, struct Camera* camera) |
||||
{ |
||||
assert(scene && camera); |
||||
scene_entity_remove(scene, &camera->base); |
||||
} |
||||
|
||||
void scene_static_mesh_remove(struct Scene* scene, struct Static_Mesh* mesh) |
||||
{ |
||||
assert(scene && mesh); |
||||
|
||||
mesh->collision.on_collision = NULL; |
||||
if(mesh->collision.collision_shape) physics_cs_remove(mesh->collision.collision_shape); |
||||
if(mesh->collision.rigidbody) physics_body_remove(mesh->collision.rigidbody); |
||||
|
||||
model_reset(&mesh->model, mesh); |
||||
scene_entity_remove(scene, &mesh->base); |
||||
} |
||||
|
||||
void scene_sound_source_remove(struct Scene* scene, struct Sound_Source* source) |
||||
{ |
||||
assert(scene && source); |
||||
|
||||
sound_source_instance_destroy(source->source_instance); |
||||
source->source_instance = 0; |
||||
scene_entity_remove(scene, &source->base); |
||||
} |
||||
|
||||
struct Entity* scene_entity_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Entity* entity = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->entities[i].name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
entity = &scene->entities[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
struct Light* scene_light_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Light* light = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->lights[i].base.name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
light = &scene->lights[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return light; |
||||
} |
||||
|
||||
struct Camera* scene_camera_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Camera* camera = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->cameras[i].base.name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
camera = &scene->cameras[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return camera; |
||||
} |
||||
|
||||
struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Static_Mesh* static_mesh = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->static_meshes[i].base.name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
static_mesh = &scene->static_meshes[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return static_mesh; |
||||
} |
||||
|
||||
struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Sound_Source* sound_source = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->sound_sources[i].base.name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
sound_source = &scene->sound_sources[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return sound_source; |
||||
} |
||||
|
||||
struct Entity* scene_base_entity_get(struct Scene* scene, int id, int type) |
||||
{ |
||||
assert(scene && id != -1 && type < ET_MAX); |
||||
|
||||
struct Entity* entity = NULL; |
||||
|
||||
switch(type) |
||||
{ |
||||
case ET_DEFAULT: entity = &scene->entities[id]; break; |
||||
case ET_CAMERA: entity = &scene->cameras[id]; break; |
||||
case ET_LIGHT: entity = &scene->lights[id]; break; |
||||
case ET_STATIC_MESH: entity = &scene->static_meshes[id]; break; |
||||
case ET_SOUND_SOURCE: entity = &scene->sound_sources[id]; break; |
||||
case ET_PLAYER: entity = &scene->player; break; |
||||
case ET_ROOT: entity = &scene->root_entity; break; |
||||
} |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
void* scene_find(struct Scene* scene, const char* name) |
||||
{ |
||||
void* entity = NULL; |
||||
|
||||
entity = scene_entity_find(scene, name); |
||||
if(entity) return entity; |
||||
|
||||
entity = scene_light_find(scene, name); |
||||
if(entity) return entity; |
||||
|
||||
entity = scene_camera_find(scene, name); |
||||
if(entity) return entity; |
||||
|
||||
entity = scene_static_mesh_find(scene, name); |
||||
if(entity) return entity; |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity) |
||||
{ |
||||
assert(scene && entity); |
||||
transform_parent_set(entity, &scene->root_entity, true); |
||||
} |
||||
|
||||
void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent) |
||||
{ |
||||
assert(scene && entity && parent); |
||||
transform_parent_set(entity, parent, true); |
||||
} |
||||
|
||||
void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results) |
||||
{ |
||||
assert(out_results); |
||||
|
||||
memset(&out_results[0], '\0', sizeof(struct Entity*) * MAX_RAYCAST_ENTITIES_INTERSECT); |
||||
out_results->num_entities_intersected = 0; |
||||
|
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) |
||||
{ |
||||
struct Static_Mesh* mesh = &scene->static_meshes[i]; |
||||
if(!mesh->base.active) continue; |
||||
vec3 abs_pos = { 0.f }; |
||||
transform_get_absolute_position(mesh, &abs_pos); |
||||
|
||||
struct Geometry* geometry = geom_get(mesh->model.geometry_index); |
||||
if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, ray)) |
||||
{ |
||||
out_results->entities_intersected[out_results->num_entities_intersected] = &mesh->base; |
||||
out_results->num_entities_intersected++; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool scene_load_(const char* filename, int directory_type) |
||||
{ |
||||
// FILE* entity_file = platform->file.open(directory_type, filename, "r");
|
||||
//if(!entity_file)
|
||||
//{
|
||||
// log_error("scene:load", "Failed to open scenefile %s for reading", filename);
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//int count = 0;
|
||||
//int eof_char = -1;
|
||||
//while(!feof(entity_file))
|
||||
//{
|
||||
// if(eof_char != -1) ungetc(eof_char, entity_file);
|
||||
// struct Entity* new_entity = NULL;
|
||||
// new_entity = entity_read(entity_file);
|
||||
// if(!new_entity)
|
||||
// {
|
||||
// log_error("scene:load", "Error reading entity");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log_message("Loaded %s", new_entity->name);
|
||||
// count++;
|
||||
// }
|
||||
// eof_char = fgetc(entity_file);
|
||||
// /* To check end of file, we get the next character and before beginning
|
||||
// loop we check if eof occured, feof only returns true if the last read
|
||||
// was an eof. If it wasn't eof then we return the character back to the
|
||||
// stream and carry on. */
|
||||
//}
|
||||
|
||||
//log_message("%d entites loaded from %s", count, filename);
|
||||
//fclose(entity_file);
|
||||
return entity_load(filename, directory_type); |
||||
} |
||||
|
||||
bool scene_save_(const char* filename, int directory_type) |
||||
{ |
||||
bool success = false; |
||||
/*FILE* scene_file = platform->file.open(directory_type, filename, "w");
|
||||
if(!scene_file) |
||||
{ |
||||
log_error("scene:save", "Failed to create scenefile %s for writing", filename); |
||||
return false; |
||||
} |
||||
|
||||
struct Parser* parser = parser_new(); |
||||
if(!parser) |
||||
{ |
||||
log_error("scene:save", "Could not create Parser"); |
||||
fclose(scene_file); |
||||
return false; |
||||
} |
||||
|
||||
int* entities_to_write = array_new(int); |
||||
array_push(entities_to_write, root_node, int); |
||||
|
||||
bool done = false; |
||||
int count = 0; |
||||
while(!done) |
||||
{ |
||||
struct Entity* entity = entity_get(entities_to_write[0]); |
||||
struct Parser_Object* object = parser_object_new(parser, PO_ENTITY); |
||||
if(!object) |
||||
{ |
||||
log_error("scene:save", "Failed to create parser object for %s", entity->name); |
||||
continue; |
||||
} |
||||
|
||||
if(!entity_write(entity, object)) |
||||
{ |
||||
log_error("scene:save", "Failed to write '%s' into parser object", entity->name); |
||||
continue; |
||||
} |
||||
|
||||
log_message("Entity '%s' written to file", entity->name); |
||||
count++; |
||||
for(int i = 0; i < array_len(entity->transform.children); i++) |
||||
array_push(entities_to_write, entity->transform.children[i], int); |
||||
|
||||
array_remove_at(entities_to_write, 0); |
||||
if(array_len(entities_to_write) == 0) done = true; |
||||
} |
||||
|
||||
if(parser_write_objects(parser, scene_file, filename)) |
||||
{ |
||||
log_message("%d entities written to %s", count, filename); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:save", "Failed to write scene to %s", filename); |
||||
success = false; |
||||
} |
||||
|
||||
array_free(entities_to_write); |
||||
parser_free(parser); |
||||
fclose(scene_file);*/ |
||||
|
||||
return success; |
||||
} |
@ -1,709 +0,0 @@ |
||||
#include "scene.h" |
||||
#include "../common/array.h" |
||||
#include "entity.h" |
||||
#include "../common/log.h" |
||||
#include "transform.h" |
||||
#include "camera.h" |
||||
#include "../common/common.h" |
||||
#include "../common/parser.h" |
||||
#include "model.h" |
||||
#include "light.h" |
||||
#include "player.h" |
||||
#include "game.h" |
||||
#include "bounding_volumes.h" |
||||
#include "geometry.h" |
||||
#include "editor.h" |
||||
|
||||
#include <assert.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
|
||||
void scene_init(struct Scene* scene) |
||||
{ |
||||
assert(scene); |
||||
//Initialize the root entity
|
||||
entity_init(&scene->root_entity, "ROOT_ENTITY", NULL); |
||||
scene->root_entity.active = true; |
||||
scene->root_entity.id = 0; |
||||
scene->root_entity.type = ET_ROOT; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) entity_reset(&scene->entities[i], i); |
||||
for(int i = 0; i < MAX_LIGHTS; i++)
|
||||
{ |
||||
entity_reset(&scene->lights[i], i); |
||||
scene->lights[i].type = ET_LIGHT; |
||||
} |
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++)
|
||||
{ |
||||
entity_reset(&scene->static_meshes[i], i); |
||||
struct Static_Mesh* mesh = &scene->static_meshes[i]; |
||||
mesh->collision.collision_shape = NULL; |
||||
mesh->collision.rigidbody = NULL; |
||||
mesh->collision.on_collision = NULL; |
||||
mesh->model.geometry_index = -1; |
||||
mesh->model.material = NULL; |
||||
} |
||||
for(int i = 0; i < MAX_SOUND_SOURCES; i++) entity_reset(&scene->sound_sources[i], i); |
||||
for(int i = 0; i < MAX_CAMERAS; i++)
|
||||
{ |
||||
entity_init(&scene->cameras[i], NULL, &scene->root_entity); |
||||
camera_init(&scene->cameras[i], 1024, 768); |
||||
scene->cameras[i].base.id = i; |
||||
} |
||||
|
||||
player_init(&scene->player, scene); |
||||
editor_init_camera(); |
||||
|
||||
scene->active_camera_index = game_state_get()->game_mode == GAME_MODE_GAME ? CAM_GAME : CAM_EDITOR; |
||||
} |
||||
|
||||
bool scene_load(struct Scene* scene, const char* filename, int dir_type) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
bool scene_save(struct Scene* scene, const char* filename, int dir_type) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
void scene_destroy(struct Scene* scene) |
||||
{ |
||||
assert(scene); |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) scene_entity_remove(scene, &scene->entities[i]); |
||||
for(int i = 0; i < MAX_CAMERAS; i++) scene_camera_remove(scene, &scene->cameras[i]); |
||||
for(int i = 0; i < MAX_LIGHTS; i++) scene_light_remove(scene, &scene->lights[i]); |
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]); |
||||
for(int i = 0; i < MAX_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]); |
||||
player_destroy(&scene->player); |
||||
entity_reset(&scene->root_entity, 0); |
||||
scene->root_entity.active = false; |
||||
} |
||||
|
||||
void scene_update(struct Scene* scene, float dt) |
||||
{ |
||||
if(game_state_get()->game_mode == GAME_MODE_GAME) player_update(&scene->player, scene, dt); |
||||
} |
||||
|
||||
void scene_post_update(struct Scene* scene) |
||||
{ |
||||
assert(scene); |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
struct Entity* entity = &scene->entities[i]; |
||||
if(!entity->active) continue; |
||||
|
||||
if(entity->marked_for_deletion) |
||||
{ |
||||
scene_entity_remove(scene, entity); |
||||
continue; |
||||
} |
||||
|
||||
if(entity->transform.is_modified) entity->transform.is_modified = false; |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_CAMERAS; i++) |
||||
{ |
||||
struct Camera* camera = &scene->cameras[i]; |
||||
if(!camera->base.active) continue; |
||||
|
||||
if(camera->base.marked_for_deletion) |
||||
{ |
||||
scene_camera_remove(scene, camera); |
||||
continue; |
||||
} |
||||
|
||||
if(camera->base.transform.is_modified) |
||||
{ |
||||
camera_update_view(camera); |
||||
camera->base.transform.is_modified = false; |
||||
} |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_SOUND_SOURCES; i++) |
||||
{ |
||||
struct Sound_Source* sound_source = &scene->sound_sources[i]; |
||||
if(!sound_source->base.active) continue; |
||||
|
||||
if(sound_source->base.marked_for_deletion) |
||||
{ |
||||
scene_sound_source_remove(scene, sound_source); |
||||
continue; |
||||
} |
||||
|
||||
if(sound_source->base.transform.is_modified) |
||||
{ |
||||
vec3 abs_pos = {0.f, 0.f, 0.f}; |
||||
transform_get_absolute_position(&sound_source->base, &abs_pos); |
||||
platform->sound.source_instance_update_position(sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z); |
||||
sound_source->base.transform.is_modified = false; |
||||
} |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) |
||||
{ |
||||
struct Static_Mesh* static_mesh = &scene->static_meshes[i]; |
||||
if(!static_mesh->base.active) continue; |
||||
|
||||
if(static_mesh->base.marked_for_deletion) |
||||
{ |
||||
scene_static_mesh_remove(scene, static_mesh); |
||||
continue; |
||||
} |
||||
|
||||
if(static_mesh->base.transform.is_modified) |
||||
{ |
||||
if(static_mesh->collision.rigidbody && static_mesh->base.transform.sync_physics) |
||||
{ |
||||
quat abs_rot = { 0.f, 0.f, 0.f, 1.f }; |
||||
vec3 abs_pos = {0.f, 0.f, 0.f}; |
||||
transform_get_absolute_rot(&static_mesh->base, &abs_rot); |
||||
transform_get_absolute_position(&static_mesh->base, &abs_pos); |
||||
platform->physics.body_rotation_set(static_mesh->collision.rigidbody, abs_rot.x, abs_rot.y, abs_rot.z, abs_rot.w); |
||||
platform->physics.body_position_set(static_mesh->collision.rigidbody, abs_pos.x, abs_pos.y, abs_pos.z); |
||||
} |
||||
static_mesh->base.transform.sync_physics = false; |
||||
static_mesh->base.transform.is_modified = false; |
||||
} |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_LIGHTS; i++) |
||||
{ |
||||
struct Light* light = &scene->lights[i]; |
||||
if(!light->base.active) continue; |
||||
|
||||
if(light->base.marked_for_deletion) |
||||
{ |
||||
scene_light_remove(scene, light); |
||||
continue; |
||||
} |
||||
|
||||
if(light->base.transform.is_modified) light->base.transform.is_modified = false; |
||||
} |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
struct Entity* entity = &scene->entities[i]; |
||||
if(!entity->active) continue; |
||||
} |
||||
|
||||
if(scene->player.base.transform.is_modified) |
||||
{ |
||||
vec3 abs_pos = {0.f, 0.f, 0.f}; |
||||
vec3 abs_fwd = {0.f, 0.f, -1.f}; |
||||
vec3 abs_up = {0.f, 1.f, 0.f}; |
||||
transform_get_absolute_position(&scene->player, &abs_pos); |
||||
transform_get_absolute_forward(&scene->player, &abs_fwd); |
||||
transform_get_absolute_up(&scene->player, &abs_up); |
||||
|
||||
platform->sound.listener_update(abs_pos.x, abs_pos.y, abs_pos.z, |
||||
abs_fwd.x, abs_fwd.y, abs_fwd.z, |
||||
abs_up.x, abs_up.y, abs_up.z); |
||||
scene->player.base.transform.is_modified = false; |
||||
} |
||||
} |
||||
|
||||
struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent) |
||||
{ |
||||
assert(scene); |
||||
|
||||
struct Entity* new_entity = NULL; |
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
struct Entity* entity = &scene->entities[i]; |
||||
if(!entity->active) |
||||
{ |
||||
new_entity = entity; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_entity) |
||||
{ |
||||
if(!parent) |
||||
parent = &scene->root_entity; |
||||
entity_init(new_entity, name, parent); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:entity_create", "Max entity limit reached!"); |
||||
} |
||||
|
||||
return new_entity; |
||||
} |
||||
|
||||
struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type) |
||||
{ |
||||
assert(scene); |
||||
struct Light* new_light = NULL; |
||||
for(int i = 0; i < MAX_LIGHTS; i++) |
||||
{ |
||||
struct Light* light = &scene->lights[i]; |
||||
if(!light->base.active) |
||||
{ |
||||
new_light = light; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_light) |
||||
{ |
||||
entity_init(&new_light->base, name, parent ? parent : &scene->root_entity); |
||||
new_light->base.type = ET_LIGHT; |
||||
light_init(new_light, light_type); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:light_create", "Max light limit reached!"); |
||||
} |
||||
|
||||
return new_light; |
||||
} |
||||
|
||||
struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height) |
||||
{ |
||||
assert(scene); |
||||
struct Camera* new_camera = NULL; |
||||
for(int i = 0; i < MAX_CAMERAS; i++) |
||||
{ |
||||
struct Camera* camera = &scene->cameras[i]; |
||||
if(!camera->base.active) |
||||
{ |
||||
new_camera = camera; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_camera) |
||||
{ |
||||
entity_init(&new_camera->base, name, parent ? parent : &scene->root_entity); |
||||
new_camera->base.type = ET_CAMERA; |
||||
camera_init(new_camera, width, height); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:camera_create", "Max camera limit reached!"); |
||||
} |
||||
|
||||
return new_camera; |
||||
} |
||||
|
||||
struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* name, struct Entity* parent, const char* geometry_name, int material_type) |
||||
{ |
||||
assert(scene); |
||||
struct Static_Mesh* new_static_mesh = NULL; |
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) |
||||
{ |
||||
struct Static_Mesh* static_mesh = &scene->static_meshes[i]; |
||||
if(!static_mesh->base.active) |
||||
{ |
||||
new_static_mesh = static_mesh; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_static_mesh) |
||||
{ |
||||
entity_init(&new_static_mesh->base, name, parent ? parent : &scene->root_entity); |
||||
new_static_mesh->base.type = ET_STATIC_MESH; |
||||
model_init(&new_static_mesh->model, new_static_mesh, geometry_name, material_type); |
||||
// TODO: handle creating collision mesh for the model at creation
|
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:model_create", "Max model limit reached!"); |
||||
} |
||||
|
||||
return new_static_mesh; |
||||
} |
||||
|
||||
struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play) |
||||
{ |
||||
assert(scene && filename); |
||||
struct Sound_Source* new_sound_source = NULL; |
||||
for(int i = 0; i < MAX_SOUND_SOURCES; i++) |
||||
{ |
||||
struct Sound_Source* sound_source = &scene->static_meshes[i]; |
||||
if(!sound_source->base.active) |
||||
{ |
||||
new_sound_source = sound_source; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(new_sound_source) |
||||
{ |
||||
entity_init(&new_sound_source->base, name, parent ? parent : &scene->root_entity); |
||||
new_sound_source->base.type = ET_SOUND_SOURCE; |
||||
struct Entity* entity = &new_sound_source->base; |
||||
|
||||
new_sound_source->source_buffer = platform->sound.source_create(filename, type); |
||||
if(!new_sound_source->source_buffer) |
||||
{ |
||||
log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", filename, entity->name); |
||||
new_sound_source->source_instance = 0; |
||||
return new_sound_source; |
||||
} |
||||
|
||||
new_sound_source->source_instance = platform->sound.source_instance_create(new_sound_source->source_buffer, true); |
||||
vec3 abs_pos = {0.f, 0.f, 0.f}; |
||||
vec3 abs_fwd = {0.f, 0.f, -1.f}; |
||||
vec3 abs_up = {0.f, 1.f, 0.f}; |
||||
transform_get_absolute_position(entity, &abs_pos); |
||||
transform_get_absolute_forward(entity, &abs_fwd); |
||||
transform_get_absolute_up(entity, &abs_up); |
||||
platform->sound.source_instance_update_position(new_sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z); |
||||
|
||||
new_sound_source->loop = loop; |
||||
new_sound_source->min_distance = 0.f; |
||||
new_sound_source->max_distance = 10.f; |
||||
new_sound_source->playing = play; |
||||
new_sound_source->attenuation_type = SA_INVERSE; |
||||
new_sound_source->rolloff_factor = 0.95f; |
||||
new_sound_source->volume = 1.f; |
||||
new_sound_source->type = type; |
||||
|
||||
platform->sound.source_instance_loop_set(new_sound_source->source_instance, new_sound_source->loop); |
||||
platform->sound.source_instance_min_max_distance_set(new_sound_source->source_instance, new_sound_source->min_distance, new_sound_source->max_distance); |
||||
platform->sound.source_instance_attenuation_set(new_sound_source->source_instance, new_sound_source->attenuation_type, new_sound_source->rolloff_factor); |
||||
platform->sound.source_instance_volume_set(new_sound_source->source_instance, new_sound_source->volume); |
||||
|
||||
platform->sound.update_3d(); |
||||
if(new_sound_source->playing) platform->sound.source_instance_play(new_sound_source->source_instance); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:sound_source_create", "Max sound source limit reached!"); |
||||
} |
||||
|
||||
return new_sound_source; |
||||
} |
||||
|
||||
void scene_entity_remove(struct Scene* scene, struct Entity* entity) |
||||
{ |
||||
assert(scene && entity && entity->id >= 0); |
||||
|
||||
if(!entity->active) return; |
||||
|
||||
transform_destroy(entity); |
||||
entity->active = false; |
||||
entity->editor_selected = false; |
||||
entity->marked_for_deletion = false; |
||||
memset(entity->name, '\0', MAX_ENTITY_NAME_LEN); |
||||
} |
||||
|
||||
void scene_light_remove(struct Scene* scene, struct Light* light) |
||||
{ |
||||
assert(scene && light); |
||||
scene_entity_remove(scene, &light->base); |
||||
} |
||||
|
||||
void scene_camera_remove(struct Scene* scene, struct Camera* camera) |
||||
{ |
||||
assert(scene && camera); |
||||
scene_entity_remove(scene, &camera->base); |
||||
} |
||||
|
||||
void scene_static_mesh_remove(struct Scene* scene, struct Static_Mesh* mesh) |
||||
{ |
||||
assert(scene && mesh); |
||||
|
||||
mesh->collision.on_collision = NULL; |
||||
if(mesh->collision.collision_shape) platform->physics.cs_remove(mesh->collision.collision_shape); |
||||
if(mesh->collision.rigidbody) platform->physics.body_remove(mesh->collision.rigidbody); |
||||
|
||||
model_reset(&mesh->model, mesh); |
||||
scene_entity_remove(scene, &mesh->base); |
||||
} |
||||
|
||||
void scene_sound_source_remove(struct Scene* scene, struct Sound_Source* source) |
||||
{ |
||||
assert(scene && source); |
||||
|
||||
platform->sound.source_instance_destroy(source->source_instance); |
||||
source->source_instance = 0; |
||||
scene_entity_remove(scene, &source->base); |
||||
} |
||||
|
||||
struct Entity* scene_entity_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Entity* entity = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->entities[i].name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
entity = &scene->entities[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
struct Light* scene_light_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Light* light = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->lights[i].base.name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
light = &scene->lights[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return light; |
||||
} |
||||
|
||||
struct Camera* scene_camera_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Camera* camera = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->cameras[i].base.name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
camera = &scene->cameras[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return camera; |
||||
} |
||||
|
||||
struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Static_Mesh* static_mesh = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->static_meshes[i].base.name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
static_mesh = &scene->static_meshes[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return static_mesh; |
||||
} |
||||
|
||||
struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* name) |
||||
{ |
||||
assert(scene && name); |
||||
struct Sound_Source* sound_source = NULL; |
||||
|
||||
for(int i = 0; i < MAX_ENTITIES; i++) |
||||
{ |
||||
if(strncmp(name, scene->sound_sources[i].base.name, MAX_ENTITY_NAME_LEN) == 0) |
||||
{ |
||||
sound_source = &scene->sound_sources[i]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return sound_source; |
||||
} |
||||
|
||||
struct Entity* scene_base_entity_get(struct Scene* scene, int id, int type) |
||||
{ |
||||
assert(scene && id != -1 && type < ET_MAX); |
||||
|
||||
struct Entity* entity = NULL; |
||||
|
||||
switch(type) |
||||
{ |
||||
case ET_DEFAULT: entity = &scene->entities[id]; break; |
||||
case ET_CAMERA: entity = &scene->cameras[id]; break; |
||||
case ET_LIGHT: entity = &scene->lights[id]; break; |
||||
case ET_STATIC_MESH: entity = &scene->static_meshes[id]; break; |
||||
case ET_SOUND_SOURCE: entity = &scene->sound_sources[id]; break; |
||||
case ET_PLAYER: entity = &scene->player; break; |
||||
case ET_ROOT: entity = &scene->root_entity; break; |
||||
} |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
void* scene_find(struct Scene* scene, const char* name) |
||||
{ |
||||
void* entity = NULL; |
||||
|
||||
entity = scene_entity_find(scene, name); |
||||
if(entity) return entity; |
||||
|
||||
entity = scene_light_find(scene, name); |
||||
if(entity) return entity; |
||||
|
||||
entity = scene_camera_find(scene, name); |
||||
if(entity) return entity; |
||||
|
||||
entity = scene_static_mesh_find(scene, name); |
||||
if(entity) return entity; |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity) |
||||
{ |
||||
assert(scene && entity); |
||||
transform_parent_set(entity, &scene->root_entity, true); |
||||
} |
||||
|
||||
void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent) |
||||
{ |
||||
assert(scene && entity && parent); |
||||
transform_parent_set(entity, parent, true); |
||||
} |
||||
|
||||
void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results) |
||||
{ |
||||
assert(out_results); |
||||
|
||||
memset(&out_results[0], '\0', sizeof(struct Entity*) * MAX_RAYCAST_ENTITIES_INTERSECT); |
||||
out_results->num_entities_intersected = 0; |
||||
|
||||
for(int i = 0; i < MAX_STATIC_MESHES; i++) |
||||
{ |
||||
struct Static_Mesh* mesh = &scene->static_meshes[i]; |
||||
if(!mesh->base.active) continue; |
||||
vec3 abs_pos = {0.f}; |
||||
transform_get_absolute_position(mesh, &abs_pos); |
||||
|
||||
struct Geometry* geometry = geom_get(mesh->model.geometry_index); |
||||
if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, ray)) |
||||
{ |
||||
out_results->entities_intersected[out_results->num_entities_intersected] = &mesh->base; |
||||
out_results->num_entities_intersected++; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool scene_load_(const char* filename, int directory_type) |
||||
{ |
||||
// FILE* entity_file = platform->file.open(directory_type, filename, "r");
|
||||
//if(!entity_file)
|
||||
//{
|
||||
// log_error("scene:load", "Failed to open scenefile %s for reading", filename);
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//int count = 0;
|
||||
//int eof_char = -1;
|
||||
//while(!feof(entity_file))
|
||||
//{
|
||||
// if(eof_char != -1) ungetc(eof_char, entity_file);
|
||||
// struct Entity* new_entity = NULL;
|
||||
// new_entity = entity_read(entity_file);
|
||||
// if(!new_entity)
|
||||
// {
|
||||
// log_error("scene:load", "Error reading entity");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log_message("Loaded %s", new_entity->name);
|
||||
// count++;
|
||||
// }
|
||||
// eof_char = fgetc(entity_file);
|
||||
// /* To check end of file, we get the next character and before beginning
|
||||
// loop we check if eof occured, feof only returns true if the last read
|
||||
// was an eof. If it wasn't eof then we return the character back to the
|
||||
// stream and carry on. */
|
||||
//}
|
||||
|
||||
//log_message("%d entites loaded from %s", count, filename);
|
||||
//fclose(entity_file);
|
||||
return entity_load(filename, directory_type); |
||||
} |
||||
|
||||
bool scene_save_(const char* filename, int directory_type) |
||||
{ |
||||
bool success = false; |
||||
/*FILE* scene_file = platform->file.open(directory_type, filename, "w");
|
||||
if(!scene_file) |
||||
{ |
||||
log_error("scene:save", "Failed to create scenefile %s for writing", filename); |
||||
return false; |
||||
} |
||||
|
||||
struct Parser* parser = parser_new(); |
||||
if(!parser) |
||||
{ |
||||
log_error("scene:save", "Could not create Parser"); |
||||
fclose(scene_file); |
||||
return false; |
||||
} |
||||
|
||||
int* entities_to_write = array_new(int); |
||||
array_push(entities_to_write, root_node, int); |
||||
|
||||
bool done = false; |
||||
int count = 0; |
||||
while(!done) |
||||
{ |
||||
struct Entity* entity = entity_get(entities_to_write[0]); |
||||
struct Parser_Object* object = parser_object_new(parser, PO_ENTITY); |
||||
if(!object) |
||||
{ |
||||
log_error("scene:save", "Failed to create parser object for %s", entity->name); |
||||
continue; |
||||
} |
||||
|
||||
if(!entity_write(entity, object)) |
||||
{ |
||||
log_error("scene:save", "Failed to write '%s' into parser object", entity->name); |
||||
continue; |
||||
} |
||||
|
||||
log_message("Entity '%s' written to file", entity->name); |
||||
count++; |
||||
for(int i = 0; i < array_len(entity->transform.children); i++) |
||||
array_push(entities_to_write, entity->transform.children[i], int); |
||||
|
||||
array_remove_at(entities_to_write, 0); |
||||
if(array_len(entities_to_write) == 0) done = true; |
||||
} |
||||
|
||||
if(parser_write_objects(parser, scene_file, filename)) |
||||
{ |
||||
log_message("%d entities written to %s", count, filename); |
||||
} |
||||
else |
||||
{ |
||||
log_error("scene:save", "Failed to write scene to %s", filename); |
||||
success = false; |
||||
} |
||||
|
||||
array_free(entities_to_write); |
||||
parser_free(parser); |
||||
fclose(scene_file);*/ |
||||
|
||||
return success; |
||||
} |
@ -1,7 +1,16 @@ |
||||
#ifndef FILE_IO_H |
||||
#define FILE_IO_H |
||||
|
||||
#include "../common/common.h" |
||||
#include <stdbool.h> |
||||
#include <stdio.h> |
||||
|
||||
enum Directory_Type |
||||
{ |
||||
DIRT_USER, /* User directory or preferences directory */ |
||||
DIRT_INSTALL, /* Directory where the game's assets are, usually alongside the game's executable where the game is installed */ |
||||
DIRT_EXECUTABLE, /* Directory where the game's executable is located */ |
||||
DIRT_COUNT |
||||
}; |
||||
|
||||
void io_file_init(const char* install_dir, const char* user_dir); |
||||
void io_file_cleanup(void); |
@ -0,0 +1,109 @@ |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "../common/log.h" |
||||
#include "sound.h" |
||||
#include "platform.h" |
||||
#include "physics.h" |
||||
#include "file_io.h" |
||||
#include "config_vars.h" |
||||
#include "../common/hashmap.h" |
||||
#include "../game/game.h" |
||||
|
||||
struct Wndow; |
||||
static struct Window* window; |
||||
|
||||
bool init(void); |
||||
void cleanup(void); |
||||
|
||||
int main(int argc, char** args) |
||||
{ |
||||
if(!init(window)) |
||||
{ |
||||
log_to_stdout("ERR:(Main) Could not initialize"); |
||||
} |
||||
else |
||||
{ |
||||
bool done = false; |
||||
while(!done) |
||||
{ |
||||
bool game_init_status = game_init(window); |
||||
if(!game_init_status) |
||||
{ |
||||
log_error("main", "Game init failed"); |
||||
} |
||||
else |
||||
{ |
||||
done = game_run(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
exit(EXIT_SUCCESS); |
||||
} |
||||
|
||||
bool init(void) |
||||
{ |
||||
if(atexit(cleanup) != 0) |
||||
{ |
||||
log_to_stdout("ERR: (main:init) Could not register cleanup func with atexit"); |
||||
return false; |
||||
} |
||||
|
||||
config_vars_init(); |
||||
if(!platform_init()) return false; |
||||
|
||||
char* install_path = platform_install_directory_get(); |
||||
char* user_path = platform_user_directory_get("SS_Games", "Symmetry"); |
||||
log_init("Log.txt", user_path); |
||||
io_file_init(install_path, user_path); |
||||
free(install_path); |
||||
free(user_path); |
||||
if(!config_vars_load("config.symtres", DIRT_USER)) |
||||
{ |
||||
log_error("main:init", "Could not load config, reverting to defaults"); |
||||
config_vars_save("config.symtres", DIRT_USER); |
||||
} |
||||
|
||||
if(!platform_init_video()) return false; |
||||
|
||||
if(!platform_load_gl(NULL)) |
||||
{ |
||||
log_error("main:init", "Initializing OpenGL failed"); |
||||
return false; |
||||
} |
||||
|
||||
struct Hashmap* cvars = config_vars_get(); |
||||
int width = hashmap_int_get(cvars, "render_width"); |
||||
int height = hashmap_int_get(cvars, "render_height"); |
||||
int msaa = hashmap_bool_get(cvars, "msaa_enabled"); |
||||
int msaa_levels = hashmap_int_get(cvars, "msaa_levels"); |
||||
window = window_create("Symmetry", width, height, msaa, msaa_levels); |
||||
if(!window) |
||||
{ |
||||
log_error("main:init", "Window creation failed"); |
||||
return false; |
||||
} |
||||
|
||||
if(!sound_init()) |
||||
{ |
||||
log_error("main:init", "Failed to initialize sound"); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
void cleanup(void) |
||||
{ |
||||
game_cleanup(); |
||||
if(window) window_destroy(window); |
||||
log_reset_all_callbacks(); // Now that the game library has been unloaded, reset all callbacks to stubs so we don't crash on exit
|
||||
sound_cleanup(); |
||||
platform_unload_gl(); |
||||
platform_cleanup(); |
||||
config_vars_cleanup(); |
||||
io_file_cleanup(); |
||||
log_message("Program exiting!"); |
||||
log_cleanup(); |
||||
} |
@ -1,7 +1,30 @@ |
||||
#ifndef PHYSICS_H |
||||
#define PHYSICS_H |
||||
|
||||
#include "../common/common.h" |
||||
#include <stdbool.h> |
||||
|
||||
typedef void* Rigidbody; |
||||
typedef void* Collision_Shape; |
||||
typedef void(*RigidbodyMoveCB)(Rigidbody); |
||||
typedef void(*RigidbodyColCB)(Rigidbody, Rigidbody); |
||||
|
||||
enum Collision_Shape_Type |
||||
{ |
||||
CST_BOX = 0, |
||||
CST_SPHERE, |
||||
CST_CYLINDER, |
||||
CST_CAPSULE, |
||||
CST_PLANE, |
||||
CST_TRIMESH, |
||||
CST_UNKNOWN |
||||
}; |
||||
|
||||
struct Raycast_Hit |
||||
{ |
||||
int entity_id; |
||||
float normal_x, normal_y, normal_z; |
||||
}; |
||||
|
||||
|
||||
void physics_init(void); |
||||
void physics_cleanup(void); |
Loading…
Reference in new issue