diff --git a/CMakeLists.txt b/CMakeLists.txt index 84c3fd7..05789dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,52 +2,31 @@ cmake_minimum_required(VERSION 3.27.0) set(CMAKE_C_STANDARD 11) -project(seika C) +project(seika-framework C) option(IS_CI_BUILD "" OFF) option(SEIKA_STATIC_LIB "Make seika and dependent libs static" OFF) +# Optional Modules +option(SEIKA_ECS "Will enable ecs" ON) +option(SEIKA_INPUT "Will enable input" ON) +option(SEIKA_RENDERING "Will enable rendering" ON) +option(SEIKA_AUDIO "Will enable audio" ON) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -if (CMAKE_C_COMPILER_ID STREQUAL "MSVC") - list(APPEND flags "/W3" "/Zc:preprocessor") -elseif (APPLE) - list(APPEND flags "-Wfatal-errors" "-Wall" "-Wextra" "-Wno-write-strings" "-Wno-deprecated-declarations" - "-Wno-unused-variable" "-Wno-bad-function-cast" "-Wno-unused-parameter" "-Wno-missing-field-initializers") -else () - list(APPEND flags "-std=c11" "-Wfatal-errors" "-Wall" "-Wextra" "-Wno-write-strings" "-Wno-deprecated-declarations" - "-Wno-unused-variable" "-Wno-cast-function-type" "-Wno-unused-parameter" "-Wno-missing-field-initializers") -endif () - -file(GLOB_RECURSE SEIKA_SRC seika/*.c seika/*.h) -add_library(${PROJECT_NAME} STATIC ${SEIKA_SRC}) -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - #--- Dependencies ---# include(Dependencies.cmake) -#--- Link ---# -if (CMAKE_C_COMPILER_ID STREQUAL "MSVC") - target_link_libraries(${PROJECT_NAME} PUBLIC cglm glad stb_image zip miniaudio ${SDL3_LIBRARY} freetype Ws2_32) -elseif (WIN32) - target_link_libraries(${PROJECT_NAME} PUBLIC cglm glad stb_image zip miniaudio -lmingw32 -static-libgcc ${SDL3_LIBRARY} freetype -lws2_32) -elseif (APPLE) - target_link_libraries(${PROJECT_NAME} PUBLIC cglm glad stb_image zip miniaudio -Xlinker ${SDL3_LIBRARY} freetype m) -else () - target_link_libraries(${PROJECT_NAME} PUBLIC cglm glad stb_image zip miniaudio -static-libgcc -Xlinker -export-dynamic ${SDL3_LIBRARY} freetype m) -endif () - -target_compile_options(${PROJECT_NAME} PUBLIC ${flags}) - -# Copy directories over that are needed to test -if (NOT IS_CI_BUILD) - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory - ${PROJECT_SOURCE_DIR}/test - $/test - ) -endif() +add_subdirectory(seika) +target_compile_definitions(seika + PUBLIC + SKA_ECS=$,1,0> + SKA_INPUT=$,1,0> + SKA_RENDERING=$,1,0> + SKA_AUDIO=$,1,0> +) if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") set(SK_IS_MAIN TRUE) @@ -57,6 +36,19 @@ endif() if (SK_IS_MAIN) # Create seika test exe - add_executable(${PROJECT_NAME}_test test/test.c) - target_link_libraries(${PROJECT_NAME}_test ${PROJECT_NAME} unity) + add_executable(seika_test test/test.c) + target_link_libraries(seika_test seika unity) + if (NOT IS_CI_BUILD) + # Copy directories over that are needed to test + add_custom_command(TARGET seika_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${PROJECT_SOURCE_DIR}/test + $/test + ) + if (SEIKA_INPUT OR SEIKA_RENDERING) + # Create test game executable + add_executable(seika_test_game test/game/src/main.c) + target_link_libraries(seika_test_game seika) + endif () + endif() endif() diff --git a/Dependencies.cmake b/Dependencies.cmake index 88c3871..287e113 100644 --- a/Dependencies.cmake +++ b/Dependencies.cmake @@ -1,34 +1,5 @@ include(FetchContent) -# https://github.com/libsdl-org/SDL -if (NOT TARGET SDL3::SDL3-static) - set(SDL_STATIC ${SEIKA_STATIC_LIB}) - set(SDL_SHARED NOT ${SEIKA_STATIC_LIB}) - - FetchContent_Declare( - SDL_content - GIT_REPOSITORY https://github.com/libsdl-org/SDL.git - GIT_TAG cacac6cc341d5856d1857bdcf7390551eed54865 - ) - FetchContent_MakeAvailable(SDL_content) - - if (SEIKA_STATIC_LIB) - SET(SDL3_LIBRARY SDL3::SDL3-static) - else () - SET(SDL3_LIBRARY SDL3::SDL3) - endif () -endif () - -# https://github.com/Dav1dde/glad -if (NOT TARGET glad) - if (SEIKA_STATIC_LIB) - add_library(glad STATIC thirdparty/glad/glad.c) - else () - add_library(glad thirdparty/glad/glad.c) - endif () - target_include_directories(glad PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty") -endif() - # https://github.com/recp/cglm if (NOT TARGET cglm) set(CGLM_STATIC ${SEIKA_STATIC_LIB}) @@ -53,22 +24,6 @@ if (NOT TARGET kuba_zip) FetchContent_MakeAvailable(kuba_zip_content) endif() -# https://github.com/mackron/miniaudio -if (NOT TARGET miniaudio) - add_library(miniaudio INTERFACE thirdparty/miniaudio/miniaudio.h) - target_include_directories(miniaudio INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/miniaudio") -endif() - -# https://github.com/nothings/stb -if (NOT TARGET stb_image) - if (SEIKA_STATIC_LIB) - add_library(stb_image STATIC thirdparty/stb_image/stb_image.c) - else () - add_library(stb_image thirdparty/stb_image/stb_image.c) - endif () - target_include_directories(stb_image PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty") -endif() - # https://github.com/ThrowTheSwitch/Unity if (NOT TARGET unity) add_definitions(-DUNITY_INCLUDE_DOUBLE) @@ -81,16 +36,67 @@ if (NOT TARGET unity) FetchContent_MakeAvailable(unity_content) endif() -# https://github.com/freetype/freetype -if (NOT TARGET freetype) - if (NOT SEIKA_STATIC_LIB) - set(BUILD_SHARED_LIBS ON) +if (SEIKA_INPUT OR SEIKA_RENDERING) + # https://github.com/libsdl-org/SDL + if (NOT TARGET SDL3::SDL3-static) + set(SDL_STATIC ${SEIKA_STATIC_LIB}) + set(SDL_SHARED NOT ${SEIKA_STATIC_LIB}) + + FetchContent_Declare( + SDL_content + GIT_REPOSITORY https://github.com/libsdl-org/SDL.git + GIT_TAG cacac6cc341d5856d1857bdcf7390551eed54865 + ) + FetchContent_MakeAvailable(SDL_content) + + if (SEIKA_STATIC_LIB) + SET(SDL3_LIBRARY SDL3::SDL3-static) + else () + SET(SDL3_LIBRARY SDL3::SDL3) + endif () endif () +endif() - FetchContent_Declare( - freetype_content - GIT_REPOSITORY https://github.com/freetype/freetype.git - GIT_TAG VER-2-13-2 - ) - FetchContent_MakeAvailable(freetype_content) +if (SEIKA_RENDERING) + # https://github.com/Dav1dde/glad + if (NOT TARGET glad) + if (SEIKA_STATIC_LIB) + add_library(glad STATIC thirdparty/glad/glad.c) + else () + add_library(glad thirdparty/glad/glad.c) + endif () + target_include_directories(glad PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty") + endif() + + # https://github.com/nothings/stb + if (NOT TARGET stb_image) + if (SEIKA_STATIC_LIB) + add_library(stb_image STATIC thirdparty/stb_image/stb_image.c) + else () + add_library(stb_image thirdparty/stb_image/stb_image.c) + endif () + target_include_directories(stb_image PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty") + endif() + + # https://github.com/freetype/freetype + if (NOT TARGET freetype) + if (NOT SEIKA_STATIC_LIB) + set(BUILD_SHARED_LIBS ON) + endif () + + FetchContent_Declare( + freetype_content + GIT_REPOSITORY https://github.com/freetype/freetype.git + GIT_TAG VER-2-13-2 + ) + FetchContent_MakeAvailable(freetype_content) + endif() +endif() + +if (SEIKA_AUDIO) + # https://github.com/mackron/miniaudio + if (NOT TARGET miniaudio) + add_library(miniaudio INTERFACE thirdparty/miniaudio/miniaudio.h) + target_include_directories(miniaudio INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/miniaudio") + endif() endif() diff --git a/README.md b/README.md index 735c4de..1d67646 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,15 @@ A framework for windows, macOS, and linux that can be used to make games. ## How to include in a project Seika uses cmake to build. To include in your project, add the following to your CMakeLists.txt: + ```cmake -# Include seika framework as a dependency +# Include old_seika framework as a dependency include(FetchContent) FetchContent_Declare( seika GIT_REPOSITORY https://github.com/Chukobyte/seika.git - GIT_TAG v0.1.0 + GIT_TAG v0.2.0 ) FetchContent_MakeAvailable(seika) @@ -63,15 +64,23 @@ A simple example of creating a window and querying for inputs. #include int main(int argv, char** args) { - ska_init_all("Simple Window", 800, 600, 800, 600); - - while (ska_is_running()) { + ska_window_initialize((SkaWindowProperties){ + .title = "Simple Window", + .windowWidth = 800, + .windowHeight = 600, + .resolutionWidth = 800, + .resolutionHeight = 600, + .maintainAspectRatio = true, + }); + ska_input_initialize(); + + while (true) { + // TODO: Need to update this ska_update(); if (ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_ESCAPE, 0)) { break; } - if (ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_SPACE, 0)) { printf("space just pressed\n"); } @@ -82,10 +91,12 @@ int main(int argv, char** args) { printf("space just released\n"); } - ska_window_render(); + static SkaColor windowBackgroundColor = (SkaColor){ 0.2f, 0.2f, 0.2f, 1.0f }; + ska_window_render(&windowBackgroundColor); } - ska_shutdown_all(); + ska_window_finalize(); + ska_input_finalize(); return 0; } diff --git a/seika/CMakeLists.txt b/seika/CMakeLists.txt new file mode 100644 index 0000000..3dab300 --- /dev/null +++ b/seika/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.27.0) + +set(CMAKE_C_STANDARD 11) + +project(seika C) + +if (CMAKE_C_COMPILER_ID STREQUAL "MSVC") + list(APPEND flags "/W3" "/Zc:preprocessor") +elseif (APPLE) + list(APPEND flags "-Wfatal-errors" "-Wall" "-Wextra" "-Wno-write-strings" "-Wno-deprecated-declarations" + "-Wno-unused-variable" "-Wno-bad-function-cast" "-Wno-unused-parameter" "-Wno-missing-field-initializers") +else () + list(APPEND flags "-std=c11" "-Wfatal-errors" "-Wall" "-Wextra" "-Wno-write-strings" "-Wno-deprecated-declarations" + "-Wno-unused-variable" "-Wno-cast-function-type" "-Wno-unused-parameter" "-Wno-missing-field-initializers") +endif () + +file(GLOB_RECURSE SEIKA_SRC ./*.c ./*.h) +add_library(${PROJECT_NAME} STATIC ${SEIKA_SRC}) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../) + +set(LIBS_TO_LINK "") + +if (SEIKA_RENDERING) + list(APPEND LIBS_TO_LINK glad stb_image freetype) +endif() + +if (SEIKA_AUDIO) + list(APPEND LIBS_TO_LINK miniaudio) +endif() + +if (SEIKA_INPUT) + list(APPEND LIBS_TO_LINK ${SDL3_LIBRARY}) +endif() + +#--- Link ---# +if (CMAKE_C_COMPILER_ID STREQUAL "MSVC") + list(APPEND LIBS_TO_LINK Ws2_32) +elseif (WIN32) + list(APPEND LIBS_TO_LINK -lmingw32 -static-libgcc -lws2_32) +elseif (APPLE) + list(APPEND LIBS_TO_LINK m) +else () + list(APPEND LIBS_TO_LINK -static-libgcc -Xlinker -export-dynamic m) +endif () + +target_link_libraries(${PROJECT_NAME} PUBLIC cglm zip ${LIBS_TO_LINK}) + +target_compile_options(${PROJECT_NAME} PUBLIC ${flags}) diff --git a/seika/assert.c b/seika/assert.c index d9161fe..5ecb4ce 100644 --- a/seika/assert.c +++ b/seika/assert.c @@ -1,14 +1,20 @@ #include "seika/assert.h" +#include +#include +#include + +#include "seika/string.h" + void ska_print_assert_err(const char* fmt, ...) { #define SKA_PRINT_BUFFER_SIZE 496 va_list args; - va_start(args, fmt); + va_start(args, fmt); char str[SKA_PRINT_BUFFER_SIZE]; memset(str, 0, SKA_PRINT_BUFFER_SIZE); ska_strncat(str, fmt, (sizeof(str) - strlen(str) - 1) ); ska_strncat(str, "\n", (sizeof(str) - strlen(str) - 1) ); vfprintf(stderr, str, args); - va_end(args); + va_end(args); #undef SKA_PRINT_BUFFER_SIZE } diff --git a/seika/assert.h b/seika/assert.h index 6392b8f..5042e80 100644 --- a/seika/assert.h +++ b/seika/assert.h @@ -1,16 +1,16 @@ +#pragma once + #ifdef __cplusplus extern "C" { #endif + #include #include -#include -#include #include -#include "defines.h" -#include "platform.h" -#include "seika/string.h" +#include "seika/defines.h" +#include "seika/platform.h" #define SKA_ASSERT_FAIL_EXIT_CODE (-1) diff --git a/seika/asset/asset_file_loader.c b/seika/asset/asset_file_loader.c index 513a8da..9ed6a42 100644 --- a/seika/asset/asset_file_loader.c +++ b/seika/asset/asset_file_loader.c @@ -1,11 +1,15 @@ #include "asset_file_loader.h" +#if SKA_RENDERING #include + +#include "seika/memory.h" +#endif + #include #include "seika/string.h" #include "seika/file_system.h" -#include "seika/memory.h" SkaAssetFileLoaderReadMode globalReadMode = SkaAssetFileLoaderReadMode_DISK; struct zip_t* packageArchive = NULL; @@ -65,27 +69,6 @@ bool ska_asset_file_loader_is_asset_valid(SkaArchiveFileAsset* fileAsset) { return fileAsset != NULL && fileAsset->buffer != NULL; } -SkaAssetFileImageData* ska_asset_file_loader_load_image_data(const char* filePath) { - SkaAssetFileImageData* imageData = NULL; - stbi_set_flip_vertically_on_load(false); - if (globalReadMode == SkaAssetFileLoaderReadMode_DISK) { - imageData = SKA_MEM_ALLOCATE(SkaAssetFileImageData); - imageData->data = stbi_load(filePath, &imageData->width, &imageData->height, &imageData->nrChannels, 0); - } else if (globalReadMode == SkaAssetFileLoaderReadMode_ARCHIVE) { - SkaArchiveFileAsset fileAsset = ska_asset_file_loader_get_asset(filePath); - if (ska_asset_file_loader_is_asset_valid(&fileAsset)) { - imageData = SKA_MEM_ALLOCATE(SkaAssetFileImageData); - imageData->data = stbi_load_from_memory(fileAsset.buffer, (int32)fileAsset.bufferSize, &imageData->width, &imageData->height, &imageData->nrChannels, 0); - } - } - return imageData; -} - -void ska_asset_file_loader_free_image_data(SkaAssetFileImageData* data) { - stbi_image_free(data->data); - SKA_MEM_FREE(data); -} - char* ska_asset_file_loader_read_file_contents_as_string(const char* filePath, usize* size) { char* fileString = NULL; usize len = 0; @@ -126,3 +109,26 @@ char* ska_asset_file_loader_read_file_contents_as_string_without_raw(const char* } return fileString; } + +#if SKA_RENDERING +SkaAssetFileImageData* ska_asset_file_loader_load_image_data(const char* filePath) { + SkaAssetFileImageData* imageData = NULL; + stbi_set_flip_vertically_on_load(false); + if (globalReadMode == SkaAssetFileLoaderReadMode_DISK) { + imageData = SKA_ALLOC(SkaAssetFileImageData); + imageData->data = stbi_load(filePath, &imageData->width, &imageData->height, &imageData->nrChannels, 0); + } else if (globalReadMode == SkaAssetFileLoaderReadMode_ARCHIVE) { + SkaArchiveFileAsset fileAsset = ska_asset_file_loader_get_asset(filePath); + if (ska_asset_file_loader_is_asset_valid(&fileAsset)) { + imageData = SKA_ALLOC(SkaAssetFileImageData); + imageData->data = stbi_load_from_memory(fileAsset.buffer, (int32)fileAsset.bufferSize, &imageData->width, &imageData->height, &imageData->nrChannels, 0); + } + } + return imageData; +} + +void ska_asset_file_loader_free_image_data(SkaAssetFileImageData* data) { + stbi_image_free(data->data); + SKA_FREE(data); +} +#endif // #if SKA_RENDERING diff --git a/seika/asset/asset_file_loader.h b/seika/asset/asset_file_loader.h index 5598427..efeef93 100644 --- a/seika/asset/asset_file_loader.h +++ b/seika/asset/asset_file_loader.h @@ -4,9 +4,6 @@ extern "C" { #endif -#include -#include - #include "seika/defines.h" typedef enum SkaAssetFileLoaderReadMode { @@ -36,11 +33,14 @@ SkaArchiveFileAsset ska_asset_file_loader_load_asset_from_disk(const char* path) bool ska_asset_file_loader_is_asset_valid(SkaArchiveFileAsset* fileAsset); // Asset loading types -SkaAssetFileImageData* ska_asset_file_loader_load_image_data(const char* filePath); -void ska_asset_file_loader_free_image_data(SkaAssetFileImageData* data); char* ska_asset_file_loader_read_file_contents_as_string(const char* filePath, usize* size); char* ska_asset_file_loader_read_file_contents_as_string_without_raw(const char* filePath, usize* size); +#if SKA_RENDERING +SkaAssetFileImageData* ska_asset_file_loader_load_image_data(const char* filePath); +void ska_asset_file_loader_free_image_data(SkaAssetFileImageData* data); +#endif // #if SKA_RENDERING + #ifdef __cplusplus } #endif diff --git a/seika/asset/asset_manager.c b/seika/asset/asset_manager.c index ab739db..e89e2cd 100644 --- a/seika/asset/asset_manager.c +++ b/seika/asset/asset_manager.c @@ -23,13 +23,14 @@ void ska_asset_manager_finalize() { ska_string_hash_map_destroy(audioSourceMap); } +#if SKA_RENDERING // --- Texture --- // SkaTexture* ska_asset_manager_load_texture(const char* fileName, const char* key) { SKA_ASSERT(texturesMap != NULL); SKA_ASSERT_FMT(!ska_string_hash_map_has(texturesMap, fileName), "Already loaded texture at file path '%'s! Has key '%s'.", fileName, key); SkaTexture* texture = ska_texture_create_texture(fileName); ska_string_hash_map_add(texturesMap, key, texture, sizeof(SkaTexture)); - SKA_MEM_FREE(texture); + SKA_FREE(texture); texture = (SkaTexture*) ska_string_hash_map_get(texturesMap, key); return texture; } @@ -44,7 +45,7 @@ SkaTexture* ska_asset_manager_load_texture_ex(const char* fileName, const char* applyNearestNeighbor ); ska_string_hash_map_add(texturesMap, key, texture, sizeof(SkaTexture)); - SKA_MEM_FREE(texture); + SKA_FREE(texture); texture = (SkaTexture*) ska_string_hash_map_get(texturesMap, key); return texture; } @@ -63,7 +64,7 @@ SkaFont* ska_asset_manager_load_font(const char* fileName, const char* key, int SkaFont* font = ska_font_create_font(fileName, size, applyNearestNeighbor); SKA_ASSERT_FMT(font != NULL, "Failed to load font! file_name: '%s', key: '%s', size: '%d'", fileName, key, size); ska_string_hash_map_add(fontMap, key, font, sizeof(SkaFont)); - SKA_MEM_FREE(font); + SKA_FREE(font); font = (SkaFont*) ska_string_hash_map_get(fontMap, key); return font; } @@ -73,7 +74,7 @@ SkaFont* ska_asset_manager_load_font_from_memory(const char* key, void* buffer, SkaFont* font = ska_font_create_font_from_memory(buffer, bufferSize, size, applyNearestNeighbor); SKA_ASSERT_FMT(font != NULL, "Failed to load font! key: '%s', size: '%d'", key, size); ska_string_hash_map_add(fontMap, key, font, sizeof(SkaFont)); - SKA_MEM_FREE(font); + SKA_FREE(font); font = (SkaFont*) ska_string_hash_map_get(fontMap, key); return font; } @@ -86,7 +87,9 @@ SkaFont* ska_asset_manager_get_font(const char* key) { bool ska_asset_manager_has_font(const char* key) { return ska_string_hash_map_has(fontMap, key); } +#endif // #if SKA_RENDERING +#if SKA_AUDIO // --- Audio Source --- // SkaAudioSource* ska_asset_manager_load_audio_source_wav(const char* fileName, const char* key) { SKA_ASSERT(audioSourceMap != NULL); @@ -94,7 +97,7 @@ SkaAudioSource* ska_asset_manager_load_audio_source_wav(const char* fileName, co SkaAudioSource* newAudioSource = ska_audio_load_audio_source_wav(fileName); SKA_ASSERT_FMT(newAudioSource != NULL, "Audio source is null! file_name = '%s', key = '%s'", fileName, key); ska_string_hash_map_add(audioSourceMap, key, newAudioSource, sizeof(SkaAudioSource)); - SKA_MEM_FREE(newAudioSource); + SKA_FREE(newAudioSource); return newAudioSource; } @@ -105,3 +108,4 @@ SkaAudioSource* ska_asset_manager_get_audio_source(const char* key) { bool ska_asset_manager_has_audio_source(const char* key) { return ska_string_hash_map_has(audioSourceMap, key); } +#endif // #if SKA_AUDIO diff --git a/seika/asset/asset_manager.h b/seika/asset/asset_manager.h index c9f1bf2..a10d0d5 100644 --- a/seika/asset/asset_manager.h +++ b/seika/asset/asset_manager.h @@ -8,20 +8,24 @@ extern "C" { void ska_asset_manager_initialize(); void ska_asset_manager_finalize(); -// --- Texture --- // + +#if SKA_RENDERING struct SkaTexture* ska_asset_manager_load_texture(const char* fileName, const char* key); struct SkaTexture* ska_asset_manager_load_texture_ex(const char* fileName, const char* key, const char* wrap_s, const char* wrap_t, bool applyNearestNeighbor); struct SkaTexture* ska_asset_manager_get_texture(const char* key); bool ska_asset_manager_has_texture(const char* key); -// --- Font --- // + struct SkaFont* ska_asset_manager_load_font(const char* fileName, const char* key, int size, bool applyNearestNeighbor); struct SkaFont* ska_asset_manager_load_font_from_memory(const char* key, void* buffer, usize bufferSize, int size, bool applyNearestNeighbor); struct SkaFont* ska_asset_manager_get_font(const char* key); bool ska_asset_manager_has_font(const char* key); -// -- Audio Source --- // +#endif // #if SKA_RENDERING + +#if SKA_AUDIO struct SkaAudioSource* ska_asset_manager_load_audio_source_wav(const char* fileName, const char* key); struct SkaAudioSource* ska_asset_manager_get_audio_source(const char* key); bool ska_asset_manager_has_audio_source(const char* key); +#endif // #if SKA_AUDIO #ifdef __cplusplus } diff --git a/seika/audio/audio.c b/seika/audio/audio.c index 635a1c9..16b7f89 100644 --- a/seika/audio/audio.c +++ b/seika/audio/audio.c @@ -1,3 +1,7 @@ +#include "audio_manager.h" +#include "seika/assert.h" +#if SKA_AUDIO + #include "audio.h" #define MINIAUDIO_IMPLEMENTATION @@ -8,9 +12,23 @@ #include "seika/asset/asset_file_loader.h" static uint32 audioWavSampleRate = SKA_AUDIO_SOURCE_DEFAULT_WAV_SAMPLE_RATE; +static bool isAudioInitialized = false; static bool load_wav_data_from_file(const char* file_path, int32* sample_count, int32* channels, int32* sample_rate, void** samples); +bool ska_audio_initialize() { + SKA_ASSERT(isAudioInitialized == false); + ska_audio_manager_init(SKA_AUDIO_SOURCE_DEFAULT_WAV_SAMPLE_RATE); + isAudioInitialized = true; + return true; +} + +void ska_audio_finalize() { + SKA_ASSERT(isAudioInitialized); + ska_audio_manager_finalize(); + isAudioInitialized = false; +} + void ska_audio_print_audio_source(SkaAudioSource* audioSource) { ska_logger_debug("audio source | channels = %d, sample rate = %d, sample count = %d, samples = %x", audioSource->channels, audioSource->sample_rate, audioSource->sample_count, audioSource->samples); @@ -33,7 +51,7 @@ SkaAudioSource* ska_audio_load_audio_source_wav(const char* fileName) { ska_logger_error("Failed to load audio wav file at '%s'", fileName); return NULL; } - SkaAudioSource* newAudioSource = (SkaAudioSource*)SKA_MEM_ALLOCATE_SIZE(sizeof(SkaAudioSource*) + (sampleCount * sizeof(int16_t*))); + SkaAudioSource* newAudioSource = (SkaAudioSource*)SKA_ALLOC_BYTES(sizeof(SkaAudioSource*) + (sampleCount * sizeof(int16_t*))); newAudioSource->file_path = fileName; newAudioSource->pitch = 1.0; newAudioSource->sample_count = sampleCount; @@ -56,7 +74,7 @@ bool load_wav_data_from_file(const char* file_path, int32_t* sample_count, int32 drwav_uint64 totalPcmFrameCount = 0; *samples = drwav_open_memory_and_read_pcm_frames_s16(file_data, len, (uint32_t*)channels, (uint32_t*)sample_rate, &totalPcmFrameCount, NULL); - SKA_MEM_FREE(file_data); + SKA_FREE(file_data); if (!*samples) { *samples = NULL; @@ -68,3 +86,5 @@ bool load_wav_data_from_file(const char* file_path, int32_t* sample_count, int32 return true; } + +#endif // #if SKA_AUDIO diff --git a/seika/audio/audio.h b/seika/audio/audio.h index 48f0db2..93f7f02 100644 --- a/seika/audio/audio.h +++ b/seika/audio/audio.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_AUDIO + #ifdef __cplusplus extern "C" { #endif @@ -19,6 +21,8 @@ typedef struct SkaAudioSource { int32 sample_count; } SkaAudioSource; +bool ska_audio_initialize(); +void ska_audio_finalize(); void ska_audio_print_audio_source(SkaAudioSource* audioSource); void ska_audio_set_wav_sample_rate(uint32 wavSampleRate); uint32 ska_audio_get_wav_sample_rate(); @@ -27,3 +31,5 @@ SkaAudioSource* ska_audio_load_audio_source_wav(const char* fileName); #ifdef __cplusplus } #endif + +#endif // #if SKA_AUDIO diff --git a/seika/audio/audio_manager.c b/seika/audio/audio_manager.c index 7da5ee4..48d2369 100644 --- a/seika/audio/audio_manager.c +++ b/seika/audio/audio_manager.c @@ -1,3 +1,5 @@ +#if SKA_AUDIO + #include "audio_manager.h" #include @@ -37,7 +39,7 @@ static SkaAudioInstances* audio_instances = NULL; // --- Audio Manager --- // bool ska_audio_manager_init(uint32 wavSampleRate) { - audio_instances = SKA_MEM_ALLOCATE(SkaAudioInstances); + audio_instances = SKA_ALLOC_ZEROED(SkaAudioInstances); pthread_mutex_init(&audio_mutex, NULL); ska_audio_set_wav_sample_rate(wavSampleRate); // Device @@ -51,7 +53,7 @@ bool ska_audio_manager_init(uint32 wavSampleRate) { config.sampleRate = wavSampleRate; config.dataCallback = audio_data_callback; config.pUserData = NULL; - audio_device = SKA_MEM_ALLOCATE(ma_device); + audio_device = SKA_ALLOC(ma_device); if (ma_device_init(NULL, &config, audio_device) != MA_SUCCESS) { ska_logger_error("Failed to initialize miniaudio device!"); return false; @@ -67,10 +69,10 @@ bool ska_audio_manager_init(uint32 wavSampleRate) { void ska_audio_manager_finalize() { ma_device_uninit(audio_device); - SKA_MEM_FREE(audio_device); + SKA_FREE(audio_device); audio_device = NULL; - SKA_MEM_FREE(audio_instances); // TODO: Properly free up all instances + SKA_FREE(audio_instances); // TODO: Properly free up all instances audio_instances = NULL; pthread_mutex_destroy(&audio_mutex); @@ -88,7 +90,7 @@ void ska_audio_manager_play_sound(const char* filePath, bool loops) { pthread_mutex_lock(&audio_mutex); // Create audio instance and add to instances array static unsigned int audioInstanceId = 0; // TODO: temp id for now in case we need to grab a hold of an audio instance for roll back later... - SkaAudioInstance* audioInstance = SKA_MEM_ALLOCATE(SkaAudioInstance); + SkaAudioInstance* audioInstance = SKA_ALLOC(SkaAudioInstance); audioInstance->source = ska_asset_manager_get_audio_source(filePath); audioInstance->id = audioInstanceId++; audioInstance->does_loop = loops; @@ -125,7 +127,7 @@ void audio_data_callback(ma_device* device, void* output, const void* input, ma_ SkaAudioInstance* audioInst = audio_instances->instances[i]; SKA_ASSERT_FMT(audioInst != NULL, "audio instance with index %zu is null!", i); if (!audioInst->is_playing) { - SKA_MEM_FREE(audioInst); + SKA_FREE(audioInst); audio_instances->instances[i] = NULL; removedInstances++; continue; @@ -170,7 +172,7 @@ void audio_data_callback(ma_device* device, void* output, const void* input, ma_ ska_logger_debug("Audio instance with id '%u' is queued for deletion!", audioInst->id); audio_instances->instances[i] = NULL; removedInstances++; - SKA_MEM_FREE(audioInst); + SKA_FREE(audioInst); break; } } @@ -195,3 +197,5 @@ void audio_data_callback(ma_device* device, void* output, const void* input, ma_ } pthread_mutex_unlock(&audio_mutex); } + +#endif // #if SKA_AUDIO diff --git a/seika/audio/audio_manager.h b/seika/audio/audio_manager.h index 8621ded..9ffec71 100644 --- a/seika/audio/audio_manager.h +++ b/seika/audio/audio_manager.h @@ -1,11 +1,11 @@ #pragma once +#if SKA_AUDIO + #ifdef __cplusplus extern "C" { #endif -#include - #include "seika/defines.h" // --- Audio Manager --- // @@ -18,3 +18,5 @@ void ska_audio_manager_stop_sound(const char* filePath); #ifdef __cplusplus } #endif + +#endif // #if SKA_AUDIO diff --git a/seika/command_line_args_util.c b/seika/command_line_args_util.c index caf044a..37f9205 100644 --- a/seika/command_line_args_util.c +++ b/seika/command_line_args_util.c @@ -1,6 +1,5 @@ #include "command_line_args_util.h" -#include #include #include diff --git a/seika/command_line_args_util.h b/seika/command_line_args_util.h index 68c0d61..720a3ad 100644 --- a/seika/command_line_args_util.h +++ b/seika/command_line_args_util.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - #include "seika/defines.h" #define SKA_COMMAND_LINE_ARGS_KEY_LIMIT 8 diff --git a/seika/data_structures/array2d.c b/seika/data_structures/array2d.c index cd7d3ed..75fc6e6 100644 --- a/seika/data_structures/array2d.c +++ b/seika/data_structures/array2d.c @@ -8,10 +8,10 @@ #define SKA_ARRAY2D_IS_COORD_INVALID(ARRAY2D, ROW, COL) ((int32)ROW >= ARRAY2D->size.w || (int32)COL >= ARRAY2D->size.h) SkaArray2D* ska_array2d_create(usize rows, usize cols, usize elementSize) { - SkaArray2D* newArray = SKA_MEM_ALLOCATE(SkaArray2D); - newArray->data = SKA_MEM_ALLOCATE_SIZE(cols * sizeof(void*)); + SkaArray2D* newArray = SKA_ALLOC(SkaArray2D); + newArray->data = SKA_ALLOC_BYTES_ZEROED(cols * sizeof(void*)); for (usize i = 0; i < cols; i++) { - newArray->data[i] = SKA_MEM_ALLOCATE_SIZE(rows * elementSize); + newArray->data[i] = SKA_ALLOC_BYTES_ZEROED(rows * elementSize); } newArray->size = (SkaSize2Di){ .w = (int32)rows, .h = (int32)cols }; newArray->elementSize = elementSize; @@ -20,10 +20,10 @@ SkaArray2D* ska_array2d_create(usize rows, usize cols, usize elementSize) { void ska_array2d_destroy(SkaArray2D* array2d) { for (int32 i = 0; i < array2d->size.h; i++) { - SKA_MEM_FREE(array2d->data[i]); + SKA_FREE(array2d->data[i]); } - SKA_MEM_FREE(array2d->data); - SKA_MEM_FREE(array2d); + SKA_FREE(array2d->data); + SKA_FREE(array2d); } void* ska_array2d_get(SkaArray2D* array2d, usize x, usize y) { @@ -49,11 +49,11 @@ void ska_array2d_resize(SkaArray2D* array2d, usize newX, usize newY) { void** oldData = array2d->data; const SkaSize2Di oldSize = array2d->size; // Allocate data for all columns - array2d->data = SKA_MEM_ALLOCATE_SIZE(newHeight * sizeof(void*)); + array2d->data = SKA_ALLOC_BYTES_ZEROED(newHeight * sizeof(void*)); // Iterate over new rows for (usize i = 0; i < newHeight; i++) { // Allocate data for new row - array2d->data[i] = SKA_MEM_ALLOCATE_SIZE(newX * array2d->elementSize); + array2d->data[i] = SKA_ALLOC_BYTES_ZEROED(newX * array2d->elementSize); if (i < (usize)oldSize.h) { // Now copy old data const usize bytesToCopy = SKA_MATH_MIN((usize)oldSize.w, newWidth) * array2d->elementSize; @@ -68,9 +68,9 @@ void ska_array2d_resize(SkaArray2D* array2d, usize newX, usize newY) { } for (usize i = 0; i < (usize)oldSize.h; i++) { - SKA_MEM_FREE(oldData[i]); + SKA_FREE(oldData[i]); } - SKA_MEM_FREE(oldData); + SKA_FREE(oldData); } void ska_array2d_clear(SkaArray2D* array2d) { diff --git a/seika/data_structures/array_list.c b/seika/data_structures/array_list.c index 0e94f17..37cb680 100644 --- a/seika/data_structures/array_list.c +++ b/seika/data_structures/array_list.c @@ -12,17 +12,18 @@ SkaArrayList* ska_array_list_create_default_capacity(usize valueSize) { } SkaArrayList* ska_array_list_create(usize valueSize, usize initialCapacity) { - SkaArrayList* newList = SKA_MEM_ALLOCATE(SkaArrayList); - newList->data = SKA_MEM_ALLOCATE_SIZE(initialCapacity * valueSize); + SkaArrayList* newList = SKA_ALLOC(SkaArrayList); + newList->data = SKA_ALLOC_BYTES_ZEROED(initialCapacity * valueSize); newList->valueSize = valueSize; newList->capacity = initialCapacity; newList->initialCapacity = initialCapacity; + newList->size = 0; return newList; } void ska_array_list_destroy(SkaArrayList* list) { - SKA_MEM_FREE(list->data); - SKA_MEM_FREE(list); + SKA_FREE(list->data); + SKA_FREE(list); } void ska_array_list_push_back(SkaArrayList* list, const void* value) { @@ -68,7 +69,16 @@ bool ska_array_list_remove_by_index(SkaArrayList* list, usize index) { return false; } -bool ska_array_list_is_empty(SkaArrayList *list) { +bool ska_array_list_has(const SkaArrayList* list, const void* value) { + for (usize i = 0; i < list->size; i++) { + if (memcmp((char*)list->data + i * list->valueSize, value, list->valueSize) == 0) { + return true; + } + } + return false; +} + +bool ska_array_list_is_empty(const SkaArrayList *list) { return list->size == 0; } diff --git a/seika/data_structures/array_list.h b/seika/data_structures/array_list.h index d03a6ff..790521c 100644 --- a/seika/data_structures/array_list.h +++ b/seika/data_structures/array_list.h @@ -26,7 +26,9 @@ void* ska_array_list_get(SkaArrayList* list, usize index); // Removes the first item from the list who is equal to the passed in value bool ska_array_list_remove(SkaArrayList* list, const void* value); bool ska_array_list_remove_by_index(SkaArrayList* list, usize index); +// Returns true if the item exists within the list +bool ska_array_list_has(const SkaArrayList* list, const void* value); // Returns true if the array list size == 0 -bool ska_array_list_is_empty(SkaArrayList *list); +bool ska_array_list_is_empty(const SkaArrayList *list); // Will remove all items from the array list void ska_array_list_clear(SkaArrayList *list); diff --git a/seika/data_structures/array_utils.h b/seika/data_structures/array_utils.h index 0473a8e..14cb3c3 100644 --- a/seika/data_structures/array_utils.h +++ b/seika/data_structures/array_utils.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "seika/defines.h" #define SKA_ARRAY_UTILS_REMOVE_ARRAY_ITEM(ARRAY, ARRAY_SIZE, ELEMENT, EMPTY_VALUE) \ diff --git a/seika/data_structures/hash_map.c b/seika/data_structures/hash_map.c index 3c77f5f..f6d94c1 100644 --- a/seika/data_structures/hash_map.c +++ b/seika/data_structures/hash_map.c @@ -18,7 +18,7 @@ static void hash_map_allocate(SkaHashMap* hashMap, usize capacity); static void hash_map_resize(SkaHashMap* hashMap, usize capacity); SkaHashMap* ska_hash_map_create(usize keySize, usize valueSize, usize capacity) { - SkaHashMap* map = (SkaHashMap*) SKA_MEM_ALLOCATE_SIZE(sizeof(SkaHashMap)); + SkaHashMap* map = (SkaHashMap*) SKA_ALLOC_BYTES(sizeof(SkaHashMap)); map->keySize = keySize; map->valueSize = valueSize; map->size = 0; @@ -29,9 +29,9 @@ SkaHashMap* ska_hash_map_create(usize keySize, usize valueSize, usize capacity) } SkaHashMapNode* hash_map_create_node(SkaHashMap* hashMap, void* key, void* value, SkaHashMapNode* next) { - SkaHashMapNode* node = (SkaHashMapNode*) SKA_MEM_ALLOCATE(SkaHashMapNode); - node->key = SKA_MEM_ALLOCATE_SIZE(hashMap->keySize); - node->value = SKA_MEM_ALLOCATE_SIZE(hashMap->valueSize); + SkaHashMapNode* node = (SkaHashMapNode*) SKA_ALLOC(SkaHashMapNode); + node->key = SKA_ALLOC_BYTES(hashMap->keySize); + node->value = SKA_ALLOC_BYTES(hashMap->valueSize); memcpy(node->key, key, hashMap->keySize); memcpy(node->value, value, hashMap->valueSize); node->next = next; @@ -50,7 +50,7 @@ bool ska_hash_map_destroy(SkaHashMap* hashMap) { } } - SKA_MEM_FREE(hashMap); + SKA_FREE(hashMap); return true; } @@ -147,7 +147,7 @@ void hash_map_shrink_if_needed(SkaHashMap* hashMap) { } void hash_map_allocate(SkaHashMap* hashMap, usize capacity) { - hashMap->nodes = (SkaHashMapNode**)SKA_MEM_ALLOCATE_SIZE(capacity * sizeof(SkaHashMapNode*)); + hashMap->nodes = (SkaHashMapNode**)SKA_ALLOC_BYTES(capacity * sizeof(SkaHashMapNode*)); memset(hashMap->nodes, 0, capacity * sizeof(SkaHashMapNode*)); hashMap->capacity = capacity; @@ -183,7 +183,7 @@ void hash_map_resize(SkaHashMap* hashMap, usize capacity) { hash_map_rehash(hashMap, oldNode, oldCapacity); - SKA_MEM_FREE(oldNode); + SKA_FREE(oldNode); } // --- Iterator --- // @@ -256,9 +256,9 @@ void hash_map_destroy_node(SkaHashMapNode* node) { SKA_ASSERT(node->value != NULL); SKA_ASSERT(node->key != NULL); - SKA_MEM_FREE(node->key); + SKA_FREE(node->key); node->key = NULL; - SKA_MEM_FREE(node->value); + SKA_FREE(node->value); node->value = NULL; - SKA_MEM_FREE(node); + SKA_FREE(node); } diff --git a/seika/data_structures/hash_map.h b/seika/data_structures/hash_map.h index 852c99a..5a50512 100644 --- a/seika/data_structures/hash_map.h +++ b/seika/data_structures/hash_map.h @@ -4,9 +4,6 @@ extern "C" { #endif -#include -#include - #include "seika/defines.h" #define SKA_HASH_MAP_SHRINK_THRESHOLD 0.25f diff --git a/seika/data_structures/hash_map_string.c b/seika/data_structures/hash_map_string.c index f090614..cec1a47 100644 --- a/seika/data_structures/hash_map_string.c +++ b/seika/data_structures/hash_map_string.c @@ -20,12 +20,12 @@ static void string_hash_map_rehash(SkaStringHashMap* hashMap, SkaStringHashMapNo static void string_hash_map_resize(SkaStringHashMap* hashMap, usize newCapacity); SkaStringHashMap* ska_string_hash_map_create(usize capacity) { - SkaStringHashMap* map = (SkaStringHashMap*)SKA_MEM_ALLOCATE(SkaStringHashMap); + SkaStringHashMap* map = (SkaStringHashMap*)SKA_ALLOC(SkaStringHashMap); map->capacity = capacity; map->size = 0; map->hashFunc = ska_default_hash_string; map->compareFunc = ska_default_compare_string; - map->nodes = (SkaStringHashMapNode**) SKA_MEM_ALLOCATE_SIZE(capacity * sizeof(SkaStringHashMapNode*)); + map->nodes = (SkaStringHashMapNode**) SKA_ALLOC_BYTES(capacity * sizeof(SkaStringHashMapNode*)); memset(map->nodes, 0, capacity * sizeof(SkaStringHashMapNode*)); // TODO: fix return map; } @@ -35,9 +35,9 @@ SkaStringHashMap* ska_string_hash_map_create_default_capacity() { } SkaStringHashMapNode* hash_map_create_node_string(SkaStringHashMap* hashMap, const char* key, const void* value, usize valueSize, SkaStringHashMapNode* next) { - SkaStringHashMapNode* node = (SkaStringHashMapNode*) SKA_MEM_ALLOCATE_SIZE(sizeof(SkaStringHashMapNode)); + SkaStringHashMapNode* node = (SkaStringHashMapNode*) SKA_ALLOC_BYTES(sizeof(SkaStringHashMapNode)); node->key = ska_strdup(key); - node->value = SKA_MEM_ALLOCATE_SIZE(valueSize); + node->value = SKA_ALLOC_BYTES(valueSize); memcpy(node->value, value, valueSize); node->valueSize = valueSize; node->next = next; @@ -56,7 +56,7 @@ bool ska_string_hash_map_destroy(SkaStringHashMap* hashMap) { } } - SKA_MEM_FREE(hashMap); + SKA_FREE(hashMap); return true; } @@ -161,7 +161,7 @@ void string_hash_map_shrink_if_needed(SkaStringHashMap* hashMap) { } void string_hash_map_allocate(SkaStringHashMap* hashMap, usize capacity) { - hashMap->nodes = SKA_MEM_ALLOCATE_SIZE(capacity * sizeof(SkaStringHashMapNode*)); + hashMap->nodes = SKA_ALLOC_BYTES(capacity * sizeof(SkaStringHashMapNode*)); memset(hashMap->nodes, 0, capacity * sizeof(SkaStringHashMapNode*)); hashMap->capacity = capacity; @@ -197,7 +197,7 @@ void string_hash_map_resize(SkaStringHashMap* hashMap, usize newCapacity) { string_hash_map_rehash(hashMap, oldNode, oldCapacity); - SKA_MEM_FREE(oldNode); + SKA_FREE(oldNode); } // Int @@ -213,7 +213,7 @@ int32 ska_string_hash_map_get_int(SkaStringHashMap* hashMap, const char* key) { bool ska_string_hash_map_add_string(SkaStringHashMap* hashMap, const char* key, const char* value) { char* stringVal = ska_strdup(value); bool result = ska_string_hash_map_add(hashMap, key, stringVal, strlen(value) + 1); - SKA_MEM_FREE(stringVal); + SKA_FREE(stringVal); return result; } @@ -289,7 +289,7 @@ void hash_map_destroy_node_string(SkaStringHashMapNode* node) { SKA_ASSERT(node != NULL); SKA_ASSERT(node->value != NULL); SKA_ASSERT(node->key != NULL); - SKA_MEM_FREE(node->key); - SKA_MEM_FREE(node->value); - SKA_MEM_FREE(node); + SKA_FREE(node->key); + SKA_FREE(node->value); + SKA_FREE(node); } diff --git a/seika/data_structures/hash_map_string.h b/seika/data_structures/hash_map_string.h index 76207f3..658c336 100644 --- a/seika/data_structures/hash_map_string.h +++ b/seika/data_structures/hash_map_string.h @@ -4,9 +4,6 @@ extern "C" { #endif -#include -#include - #include "seika/defines.h" #define SKA_STRING_HASH_MAP_SHRINK_THRESHOLD 0.25f diff --git a/seika/data_structures/id_queue.c b/seika/data_structures/id_queue.c new file mode 100644 index 0000000..2184a6d --- /dev/null +++ b/seika/data_structures/id_queue.c @@ -0,0 +1,77 @@ +#include "id_queue.h" + +#include "seika/assert.h" +#include "seika/memory.h" + +SkaIdQueue* ska_id_queue_create(usize initialCapacity) { + SkaIdQueue* queue = SKA_ALLOC(SkaIdQueue); + queue->capacity = initialCapacity; + queue->size = initialCapacity; + queue->front = 0; + queue->rear = (SKA_QUEUE_T)initialCapacity - 1; + queue->array = (SKA_QUEUE_T*)SKA_ALLOC_BYTES(queue->capacity * sizeof(SKA_QUEUE_T)); + for (SKA_QUEUE_T i = 0; i < initialCapacity; i++) { + queue->array[i] = i; + } + return queue; +} + +void ska_id_queue_destroy(SkaIdQueue* queue) { + SKA_FREE(queue->array); + SKA_FREE(queue); +} + +bool ska_id_queue_is_full(SkaIdQueue* queue) { + return queue->size == queue->capacity; +} + +bool ska_id_queue_is_empty(SkaIdQueue* queue) { + return queue->size == 0; +} + +bool ska_id_queue_enqueue(SkaIdQueue* queue, SKA_QUEUE_T item) { + if (ska_id_queue_is_full(queue)) { + return false; + } + queue->rear = (queue->rear + 1) % queue->capacity; + queue->array[queue->rear] = item; + queue->size++; + return true; +} + +bool ska_id_queue_dequeue(SkaIdQueue* queue, SKA_QUEUE_T* outId) { + // If id queue is empty recreate data array + if (ska_id_queue_is_empty(queue)) { + SKA_FREE(queue->array); + const usize prevCapacity = queue->capacity; + queue->capacity *= 2; + queue->array = (SKA_QUEUE_T*)SKA_ALLOC_BYTES_ZEROED(queue->capacity * sizeof(SKA_QUEUE_T)); + for (SKA_QUEUE_T i = prevCapacity; i < queue->capacity; i++) { + queue->array[i] = i; + } + + queue->front = prevCapacity; + queue->rear = queue->capacity - 1; + queue->size = prevCapacity; + } + *outId = queue->array[queue->front]; + queue->front = (queue->front + 1) % queue->capacity; + queue->size--; + return true; +} + +bool ska_id_queue_front(SkaIdQueue* queue, SKA_QUEUE_T* outId) { + if (ska_id_queue_is_empty(queue) || outId == NULL) { + return false; + } + *outId = queue->array[queue->front]; + return true; +} + +bool ska_id_queue_rear(SkaIdQueue* queue, SKA_QUEUE_T* outId) { + if (ska_id_queue_is_empty(queue) || outId == NULL) { + return false; + } + *outId = queue->array[queue->rear]; + return true; +} diff --git a/seika/data_structures/id_queue.h b/seika/data_structures/id_queue.h new file mode 100644 index 0000000..2eeaae4 --- /dev/null +++ b/seika/data_structures/id_queue.h @@ -0,0 +1,21 @@ +#pragma once + +#define SKA_QUEUE_T uint32 + +#include "seika/defines.h" + +// Unsigned int queue +typedef struct SkaIdQueue { + usize front, rear, size; + usize capacity; + SKA_QUEUE_T* array; +} SkaIdQueue; + +SkaIdQueue* ska_id_queue_create(usize initialCapacity); +void ska_id_queue_destroy(SkaIdQueue* queue); +bool ska_id_queue_is_full(SkaIdQueue* queue); +bool ska_id_queue_is_empty(SkaIdQueue* queue); +bool ska_id_queue_enqueue(SkaIdQueue* queue, SKA_QUEUE_T item); +bool ska_id_queue_dequeue(SkaIdQueue* queue, SKA_QUEUE_T* outId); +bool ska_id_queue_front(SkaIdQueue* queue, SKA_QUEUE_T* outId); +bool ska_id_queue_rear(SkaIdQueue* queue, SKA_QUEUE_T* outId); diff --git a/seika/data_structures/linked_list.c b/seika/data_structures/linked_list.c deleted file mode 100644 index a774a09..0000000 --- a/seika/data_structures/linked_list.c +++ /dev/null @@ -1,265 +0,0 @@ -#include "linked_list.h" - -#include -#include - -#include "seika/memory.h" -#include "seika/assert.h" - -static inline void linked_list_delete_all_nodes(SkaLinkedList* list); -static inline SkaLinkedListNode* linked_list_create_node(SkaLinkedList* list, void* value, SkaLinkedListNode* next); -static inline void* linked_list_duplicate_node_value(SkaLinkedList* list, SkaLinkedListNode* node); - -// Public functions -SkaLinkedList* ska_linked_list_create(usize valueSize) { - SkaLinkedList* list = SKA_MEM_ALLOCATE(SkaLinkedList); - list->valueSize = valueSize; - return list; -} - -void ska_linked_list_destroy(SkaLinkedList* list) { - linked_list_delete_all_nodes(list); - SKA_MEM_FREE(list); -} - -void ska_linked_list_append(SkaLinkedList* list, void* value) { - SKA_ASSERT(list != NULL); - SKA_ASSERT(value != NULL); - SkaLinkedListNode* prevTail = list->tail; - list->tail = linked_list_create_node(list, value, NULL); - if (prevTail != NULL) { - prevTail->next = list->tail; - } - // If no head, set the head to tail. - if (list->head == NULL) { - list->head = list->tail; - } - list->size++; -} - -void ska_linked_list_prepend(SkaLinkedList* list, void* value) { - SKA_ASSERT(list != NULL); - SKA_ASSERT(value != NULL); - list->head = linked_list_create_node(list, value, list->head); - // If no tail, set the tail to head. - if (list->tail == NULL) { - list->tail = list->head; - } - list->size++; -} - -void ska_linked_list_insert(SkaLinkedList* list, void* value, usize index) { - SKA_ASSERT(list != NULL); - SKA_ASSERT(value != NULL); - // Check if at beginning or end of list, then just call those functions if so... - if (index > list->size) { - // Index is out of bounds, can return error if needed... - return; - } else if (index == 0) { - ska_linked_list_prepend(list, value); - return; - } else if (index == list->size) { - ska_linked_list_append(list, value); - return; - } - // Now we know it's at the middle of the list, iterate through nodes - usize nodeIndex = 1; - SkaLinkedListNode* prevNode = list->head; - SkaLinkedListNode* currentIndexNode = list->head->next; // Get the next value since the head exists and was checked - while (currentIndexNode != NULL) { - // We found the index node, now insert - if (index == nodeIndex) { - SkaLinkedListNode* currentIndexNodeNext = currentIndexNode->next; - prevNode->next = linked_list_create_node(list, value, currentIndexNodeNext); - list->size++; - return; - } - prevNode = currentIndexNode; - currentIndexNode = currentIndexNode->next; - nodeIndex++; - } - SKA_ASSERT_FMT(false, "Error with inserting into array list!"); -} - -void* ska_linked_list_get(SkaLinkedList* list, usize index) { - if (index < list->size) { - usize nodeIndex = 0; - SkaLinkedListNode* node = list->head; - while (node != NULL) { - if (index == nodeIndex) { - return node->value; - } - node = node->next; - nodeIndex++; - } - } - return NULL; -} - -void* ska_linked_list_get_front(SkaLinkedList* list) { - return list->head->value; -} - -void* ska_linked_list_get_back(SkaLinkedList* list) { - return list->tail->value; -} - -void* ska_linked_list_pop(SkaLinkedList* list, usize index) { - if (list->size > 0 && index < list->size) { - if (index == 0) { - return ska_linked_list_pop_front(list); - } else if (index == list->size - 1) { - return ska_linked_list_pop_back(list); - } - - // Search for node - usize nodeIndex = 1; - SkaLinkedListNode* nodeBeforePopped = list->head->next; - while (nodeBeforePopped != NULL) { - if (index - 1 == nodeIndex) { - break; - } - nodeBeforePopped = nodeBeforePopped->next; - nodeIndex++; - } - // Connect the previous node with the node that's being popped's next node - SKA_ASSERT(nodeBeforePopped->next); - SkaLinkedListNode* nodeToPop = nodeBeforePopped->next; - nodeBeforePopped->next = nodeToPop->next; - list->size--; - void* poppedValue = linked_list_duplicate_node_value(list, nodeToPop); - SKA_MEM_FREE(nodeToPop->value); - SKA_MEM_FREE(nodeToPop); - return poppedValue; - } - return NULL; -} - -void* ska_linked_list_pop_front(SkaLinkedList* list) { - if (list->size > 0) { - SkaLinkedListNode* nodeToPop = list->head; - list->head = nodeToPop->next; - list->size--; - if (list->size <= 1) { - list->tail = list->head; - } - void* poppedValue = linked_list_duplicate_node_value(list, nodeToPop); - SKA_MEM_FREE(nodeToPop->value); - SKA_MEM_FREE(nodeToPop); - return poppedValue; - } - return NULL; -} - -void* ska_linked_list_pop_back(SkaLinkedList* list) { - if (list->size == 1) { - return ska_linked_list_pop_front(list); - } else if (list->size == 2) { - SkaLinkedListNode* nodeToPop = list->tail; - list->tail = list->head; - list->size--; - void* poppedValue = linked_list_duplicate_node_value(list, nodeToPop); - SKA_MEM_FREE(nodeToPop); - return poppedValue; - } else if (list->size >= 3) { - SkaLinkedListNode* nodeToPop = list->head->next; - SkaLinkedListNode* nodePrev = list->head; - while (true) { - if (nodeToPop->next == NULL) { - break; - } - nodePrev = nodePrev->next; - nodeToPop = nodeToPop->next; - } - // Now that we have node to pop and previous node, pop it - nodePrev->next = nodeToPop->next; - list->size--; - void* poppedValue = linked_list_duplicate_node_value(list, nodeToPop); - SKA_MEM_FREE(nodeToPop->value); - SKA_MEM_FREE(nodeToPop); - return poppedValue; - } - return NULL; -} - -bool ska_linked_list_remove(SkaLinkedList* list, void* value) { - SkaLinkedListNode* currentNode = list->head; - SkaLinkedListNode* prevNode = NULL; - while (currentNode != NULL) { - if (memcmp(currentNode->value, value, list->valueSize) == 0) { - SkaLinkedListNode* nodeToDelete = currentNode; - // First entry - if (prevNode == NULL) { - list->head = currentNode->next; - if (list->size - 1 == 1) { - list->tail = list->head; - } - } else { - prevNode->next = currentNode->next; - // If at end, set tail - if (prevNode->next == NULL) { - list->tail = prevNode; - } - } - - list->size--; - SKA_MEM_FREE(nodeToDelete->value); - SKA_MEM_FREE(nodeToDelete); - return true; - } - prevNode = currentNode; - currentNode = currentNode->next; - } - return false; -} - -bool ska_linked_list_is_empty(SkaLinkedList* list) { - return list->size == 0; -} - -void ska_linked_list_sort(SkaLinkedList* list, SkaLinkedListIsGreaterThanFunc isGreaterThanFunc) { - if (list->head == NULL) { - return; - } - for (SkaLinkedListNode* current = list->head; current->next != NULL; current = current->next) { - for (SkaLinkedListNode* next = current->next; next != NULL; next = next->next) { - if (isGreaterThanFunc(current->value, next->value)) { - void* temp = current->value; - current->value = next->value; - next->value = temp; - } - } - } -} - -void ska_linked_list_clear(SkaLinkedList* list) { - linked_list_delete_all_nodes(list); -} - -// Private functions -static SkaLinkedListNode* linked_list_create_node(SkaLinkedList* list, void* value, SkaLinkedListNode* next) { - SkaLinkedListNode* node = SKA_MEM_ALLOCATE(SkaLinkedListNode); - node->value = SKA_MEM_ALLOCATE_SIZE(list->valueSize); - memcpy(node->value, value, list->valueSize); - node->next = next; - return node; -} - -static void* linked_list_duplicate_node_value(SkaLinkedList* list, SkaLinkedListNode* node) { - void* dupValue = SKA_MEM_ALLOCATE_SIZE(list->valueSize); - memcpy(dupValue, node->value, list->valueSize); - return dupValue; -} - -static void linked_list_delete_all_nodes(SkaLinkedList* list) { - SkaLinkedListNode* nodeToDelete = list->head; - while (nodeToDelete != NULL) { - SkaLinkedListNode* nextNode = nodeToDelete->next; - SKA_MEM_FREE(nodeToDelete->value); - SKA_MEM_FREE(nodeToDelete); - nodeToDelete = nextNode; - } - list->size = 0; - list->head = NULL; - list->tail = NULL; -} diff --git a/seika/data_structures/linked_list.h b/seika/data_structures/linked_list.h deleted file mode 100644 index cae8c6b..0000000 --- a/seika/data_structures/linked_list.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "seika/defines.h" - -#define SKA_LINKED_LIST_FOR_EACH(list, element) for((element) = (list)->head; (element) != NULL; (element) = (element)->next) - -// Should return whether the array list node is greater than the other -typedef bool (*SkaLinkedListIsGreaterThanFunc) (void*, void*); - -// Seika implementation of a single linked list -typedef struct SkaLinkedListNode { - struct SkaLinkedListNode* next; - void* value; -} SkaLinkedListNode; - -// Generic array list, use 'ska_linked_list_create' to allocate on the heap -typedef struct SkaLinkedList { - usize valueSize; - usize size; - SkaLinkedListNode* head; - SkaLinkedListNode* tail; -} SkaLinkedList; - -// Will create a new array list with all it's element values set to the passed in 'valueSize' -SkaLinkedList* ska_linked_list_create(usize valueSize); -// Will complete destroy the array list freeing up all its memory -void ska_linked_list_destroy(SkaLinkedList* list); - -// Adds an item at the end of the list -void ska_linked_list_append(SkaLinkedList* list, void* value); -// Adds an item at the beginning of the list -void ska_linked_list_prepend(SkaLinkedList* list, void* value); -// Inserts an item at the specified index -void ska_linked_list_insert(SkaLinkedList* list, void* value, usize index); - -// Returns an item from the list from specified index -void* ska_linked_list_get(SkaLinkedList* list, usize index); -// Same as 'ska_linked_list_get' but returns item from index 0 -void* ska_linked_list_get_front(SkaLinkedList* list); -// Same as 'ska_linked_list_get' but returns item from index (size - 1) -void* ska_linked_list_get_back(SkaLinkedList* list); - -// Removes and item and returns from the list from specified index, caller needs to manage memory -void* ska_linked_list_pop(SkaLinkedList* list, usize index); -// Same as 'ska_linked_list_pop' but removes and item from index 0, caller needs to manage memory -void* ska_linked_list_pop_front(SkaLinkedList* list); -// Same as 'ska_linked_list_pop' but removes and item from index (size - 1), caller needs to manage memory -void* ska_linked_list_pop_back(SkaLinkedList* list); -// Removes the first item from the list who is equal to the passed in value -bool ska_linked_list_remove(SkaLinkedList* list, void* value); - -// Returns true if the array list size == 0 -bool ska_linked_list_is_empty(SkaLinkedList* list); -// Will sort the array list, using the passed in 'isGreaterThanFunc' as a comparator for sorting -void ska_linked_list_sort(SkaLinkedList* list, SkaLinkedListIsGreaterThanFunc isGreaterThanFunc); -// Will remove all items from the array list -void ska_linked_list_clear(SkaLinkedList* list); diff --git a/seika/data_structures/queue.c b/seika/data_structures/queue.c deleted file mode 100644 index 9bd2599..0000000 --- a/seika/data_structures/queue.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "queue.h" - -#include "seika/memory.h" - -SkaQueue* ska_queue_create(usize capacity, uint32 invalidValue) { - SkaQueue* queue = SKA_MEM_ALLOCATE(SkaQueue); - queue->capacity = capacity; - queue->invalidValue = invalidValue; - queue->size = 0; - queue->front = 0; - queue->rear = (uint32)capacity - 1; - queue->array = (uint32*)SKA_MEM_ALLOCATE_SIZE(queue->capacity * sizeof(uint32)); - return queue; -} - -void ska_queue_destroy(SkaQueue* queue) { - SKA_MEM_FREE(queue->array); - SKA_MEM_FREE(queue); -} - -bool ska_queue_is_full(SkaQueue* queue) { - return queue->size == queue->capacity; -} - -bool ska_queue_is_empty(SkaQueue* queue) { - return queue->size == 0; -} - -void ska_queue_enqueue(SkaQueue* queue, uint32 item) { - if (ska_queue_is_full(queue)) { - return; - } - queue->rear = (queue->rear + 1) % queue->capacity; - queue->array[queue->rear] = item; - queue->size++; -} - -uint32 ska_queue_dequeue(SkaQueue* queue) { - if (ska_queue_is_empty(queue)) { - return queue->invalidValue; - } - uint32 value = queue->array[queue->front]; - queue->front = (queue->front + 1) % queue->capacity; - queue->size--; - return value; -} - -uint32 ska_queue_front(SkaQueue* queue) { - if (ska_queue_is_empty(queue)) { - return queue->invalidValue; - } - return queue->array[queue->front]; -} - -uint32 ska_queue_rear(SkaQueue* queue) { - if (ska_queue_is_empty(queue)) { - return queue->invalidValue; - } - return queue->array[queue->rear]; -} diff --git a/seika/data_structures/queue.h b/seika/data_structures/queue.h deleted file mode 100644 index 1377368..0000000 --- a/seika/data_structures/queue.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include - -#include "seika/defines.h" - -// TODO: If other types are needed, create a macro to simplify queues by type - -// Unsigned int queue -typedef struct SkaQueue { - uint32 front, rear, size, invalidValue; - usize capacity; - uint32* array; -} SkaQueue; - -SkaQueue* ska_queue_create(usize capacity, uint32 invalidValue); -void ska_queue_destroy(SkaQueue* queue); -bool ska_queue_is_full(SkaQueue* queue); -bool ska_queue_is_empty(SkaQueue* queue); -void ska_queue_enqueue(SkaQueue* queue, uint32 item); -uint32 ska_queue_dequeue(SkaQueue* queue); -uint32 ska_queue_front(SkaQueue* queue); -uint32 ska_queue_rear(SkaQueue* queue); diff --git a/seika/data_structures/queue_template.h b/seika/data_structures/queue_template.h new file mode 100644 index 0000000..bc36d63 --- /dev/null +++ b/seika/data_structures/queue_template.h @@ -0,0 +1,80 @@ +// Test template + +#ifndef SKA_QUEUE_TEMPLATE +#error "SKA_QUEUE_TEMPLATE must be defined before including queue_template.h" +#endif + +#include "seika/defines.h" +#include "seika/memory.h" + +#define SKA_QUEUE_T(Name) SkaQueue_##Name +#define SKA_QUEUE_FUNC(Name, Suffix) ska_queue_##Name##_##Suffix + +// Struct definition +typedef struct SKA_QUEUE_T(SKA_QUEUE_TEMPLATE) { + SKA_QUEUE_TEMPLATE front, rear, size, invalidValue; + usize capacity; + SKA_QUEUE_TEMPLATE* array; +} SKA_QUEUE_T(SKA_QUEUE_TEMPLATE); + +// Function definitions +SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, create)(usize capacity, SKA_QUEUE_TEMPLATE invalidValue) { + SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* queue = SKA_ALLOC(SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)); + queue->capacity = capacity; + queue->invalidValue = invalidValue; + queue->size = 0; + queue->front = 0; + queue->rear = capacity - 1; + queue->array = (SKA_QUEUE_TEMPLATE*)SKA_ALLOC_BYTES(queue->capacity * sizeof(SKA_QUEUE_TEMPLATE)); + return queue; +} + +void SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, destroy)(SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* queue) { + SKA_FREE(queue->array); + SKA_FREE(queue); +} + +bool SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, is_full)(SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* queue) { + return queue->size == queue->capacity; +} + +bool SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, is_empty)(SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* queue) { + return queue->size == 0; +} + +void SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, enqueue)(SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* queue, SKA_QUEUE_TEMPLATE item) { + if (SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, is_full)(queue)) { + return; + } + queue->rear = (queue->rear + 1) % queue->capacity; + queue->array[queue->rear] = item; + queue->size++; +} + +SKA_QUEUE_TEMPLATE SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, dequeue)(SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* queue) { + if (SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, is_empty)(queue)) { + return queue->invalidValue; + } + SKA_QUEUE_TEMPLATE item = queue->array[queue->front]; + queue->front = (queue->front + 1) % queue->capacity; + queue->size--; + return item; +} + +SKA_QUEUE_TEMPLATE SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, front)(SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* queue) { + if (SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, is_empty)(queue)) { + return queue->invalidValue; + } + return queue->array[queue->front]; +} + +SKA_QUEUE_TEMPLATE SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, rear)(SKA_QUEUE_T(SKA_QUEUE_TEMPLATE)* queue) { + if (SKA_QUEUE_FUNC(SKA_QUEUE_TEMPLATE, is_empty)(queue)) { + return queue->invalidValue; + } + return queue->array[queue->rear]; +} + +#undef SKA_QUEUE_T +#undef SKA_QUEUE_FUNC +#undef SKA_QUEUE_TEMPLATE diff --git a/seika/data_structures/spatial_hash_map.c b/seika/data_structures/spatial_hash_map.c index b66a822..a946f07 100644 --- a/seika/data_structures/spatial_hash_map.c +++ b/seika/data_structures/spatial_hash_map.c @@ -25,7 +25,7 @@ static bool collision_result_has_entity(SkaSpatialHashMapCollisionResult* result // Public facing functions SkaSpatialHashMap* ska_spatial_hash_map_create(int32 initialCellSize) { - SkaSpatialHashMap* map = SKA_MEM_ALLOCATE(SkaSpatialHashMap); + SkaSpatialHashMap* map = SKA_ALLOC(SkaSpatialHashMap); map->cellSize = initialCellSize; map->largestObjectSize = initialCellSize; map->gridMap = ska_hash_map_create(sizeof(int32), sizeof(SkaSpatialHashMapGridSpace **), SKA_HASH_MAP_MIN_CAPACITY); @@ -40,18 +40,18 @@ void ska_spatial_hash_map_destroy(SkaSpatialHashMap* hashMap) { SKA_HASH_MAP_FOR_EACH(hashMap->gridMap, iter) { SkaHashMapNode* node = iter.pair; SkaSpatialHashMapGridSpace* gridSpace = (SkaSpatialHashMapGridSpace*) *(SkaSpatialHashMapGridSpace**) node->value; - SKA_MEM_FREE(gridSpace); + SKA_FREE(gridSpace); } ska_hash_map_destroy(hashMap->gridMap); // Grid space Handle Map SKA_HASH_MAP_FOR_EACH(hashMap->objectToGridMap, iter) { SkaHashMapNode* node = iter.pair; SkaSpatialHashMapGridSpacesHandle* handle = (SkaSpatialHashMapGridSpacesHandle*) *(SkaSpatialHashMapGridSpacesHandle**) node->value; - SKA_MEM_FREE(handle); + SKA_FREE(handle); } ska_hash_map_destroy(hashMap->objectToGridMap); // Finally free the hashmap memory - SKA_MEM_FREE(hashMap); + SKA_FREE(hashMap); } // The purpose of this function is to make sure that 'cellSize' is twice as big as the largest object @@ -73,7 +73,7 @@ bool change_cell_size_if_needed(SkaSpatialHashMap* hashMap, SkaRect2* collisionR SkaSpatialHashMapGridSpacesHandle* ska_spatial_hash_map_insert_or_update(SkaSpatialHashMap* hashMap, uint32 entity, SkaRect2* collisionRect) { // Create new object handle if it doesn't exist if (!ska_hash_map_has(hashMap->objectToGridMap, &entity)) { - SkaSpatialHashMapGridSpacesHandle* newHandle = SKA_MEM_ALLOCATE(SkaSpatialHashMapGridSpacesHandle); + SkaSpatialHashMapGridSpacesHandle* newHandle = SKA_ALLOC(SkaSpatialHashMapGridSpacesHandle); newHandle->gridSpaceCount = 0; newHandle->collisionRect = (SkaRect2) { 0.0f, 0.0f, 0.0f, 0.0f @@ -156,7 +156,7 @@ void ska_spatial_hash_map_remove(SkaSpatialHashMap* hashMap, uint32 entity) { hashMap->largestObjectSize = foundLargestObjectSize; } } - SKA_MEM_FREE(objectHandle); + SKA_FREE(objectHandle); } SkaSpatialHashMapGridSpacesHandle* ska_spatial_hash_map_get(SkaSpatialHashMap* hashMap, uint32 entity) { @@ -203,7 +203,7 @@ int32 spatial_hash(SkaSpatialHashMap* hashMap, SkaVector2* position) { SkaSpatialHashMapGridSpace* get_or_create_grid_space(SkaSpatialHashMap* hashMap, int32 positionHash) { if (!ska_hash_map_has(hashMap->gridMap, &positionHash)) { - SkaSpatialHashMapGridSpace* newGridSpace = SKA_MEM_ALLOCATE(SkaSpatialHashMapGridSpace); + SkaSpatialHashMapGridSpace* newGridSpace = SKA_ALLOC(SkaSpatialHashMapGridSpace); newGridSpace->entityCount = 0; ska_hash_map_add(hashMap->gridMap, &positionHash, &newGridSpace); } diff --git a/seika/data_structures/spatial_hash_map.h b/seika/data_structures/spatial_hash_map.h index e28a61e..37acb34 100644 --- a/seika/data_structures/spatial_hash_map.h +++ b/seika/data_structures/spatial_hash_map.h @@ -1,7 +1,7 @@ #pragma once #include "seika/math/math.h" -#include "hash_map.h" +#include "seika/data_structures/hash_map.h" #define SKA_SPATIAL_HASH_GRID_SPACE_ENTITY_LIMIT 32 #define SKA_SPATIAL_HASH_GRID_MAX_COLLISIONS 16 diff --git a/seika/data_structures/static_array.h b/seika/data_structures/static_array.h index 0302ca2..05caa9a 100644 --- a/seika/data_structures/static_array.h +++ b/seika/data_structures/static_array.h @@ -1,8 +1,7 @@ #pragma once -#include - -#include "array_utils.h" +#include "seika/defines.h" +#include "seika/data_structures/array_utils.h" // Helper class for generalized use of static arrays diff --git a/seika/data_structures/tile_map.h b/seika/data_structures/tile_map.h deleted file mode 100644 index 7e7e10a..0000000 --- a/seika/data_structures/tile_map.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "seika/math/math.h" -#include "seika/rendering/texture.h" - -#define SKA_TILE_MAP_MAX_TILES 36 - -typedef struct SkaTile { - SkaVector2 position; -} SkaTile; - -typedef struct SkaTileMap { - SkaTexture* tileSpriteSheet; - SkaVector2 tileSize; - SkaTile tiles[36]; -} SkaTileMap; - -SkaTileMap* ska_tile_map_create(SkaTexture* tileSpriteSheet); -void ska_tile_map_add_tile(SkaTileMap* tileMap, SkaVector2 position); -SkaTile* ska_tile_map_get_tile(SkaTileMap* tileMap, SkaVector2 position); -SkaTile* ska_tile_map_has_tile(SkaTileMap* tileMap, SkaVector2 position); -void ska_tile_map_destroy(SkaTileMap* tileMap); diff --git a/seika/defines.h b/seika/defines.h index 1c4c9e7..705fda8 100644 --- a/seika/defines.h +++ b/seika/defines.h @@ -8,7 +8,7 @@ extern "C" { #include #include -#include "version_info.h" +#include "seika/version_info.h" typedef size_t usize; diff --git a/seika/ecs/component.c b/seika/ecs/component.c index 0aee34a..ee81484 100644 --- a/seika/ecs/component.c +++ b/seika/ecs/component.c @@ -1,11 +1,12 @@ -#include "component.h" +#if SKA_ECS -#include +#include "component.h" #include "seika/string.h" #include "seika/memory.h" #include "seika/assert.h" #include "seika/data_structures/hash_map_string.h" +#include "seika/data_structures/array_list.h" //--- Component ---// static SkaComponentIndex globalComponentIndex = 0; @@ -50,22 +51,9 @@ SkaComponentType ska_ecs_component_get_type_flag(const char* name, usize compone //--- Component Array ---// typedef struct ComponentArray { void* components[SKA_ECS_MAX_COMPONENTS]; + SkaComponentType signature; } ComponentArray; -static ComponentArray* component_array_create() { - ComponentArray* componentArray = SKA_MEM_ALLOCATE(ComponentArray); - for (unsigned int i = 0; i < SKA_ECS_MAX_COMPONENTS; i++) { - componentArray->components[i] = NULL; - } - return componentArray; -} - -static void component_array_initialize(ComponentArray* componentArray) { - for (unsigned int i = 0; i < SKA_ECS_MAX_COMPONENTS; i++) { - componentArray->components[i] = NULL; - } -} - static bool component_array_has_component(ComponentArray* componentArray, SkaComponentIndex index) { return componentArray->components[index] == NULL ? false : true; } @@ -79,7 +67,7 @@ static void component_array_set_component(ComponentArray* componentArray, SkaCom } static void component_array_remove_component(ComponentArray* componentArray, SkaComponentIndex index) { - SKA_MEM_FREE(componentArray->components[index]); + SKA_FREE(componentArray->components[index]); componentArray->components[index] = NULL; } @@ -87,15 +75,15 @@ static void component_array_remove_all_components(ComponentArray* componentArray for (usize i = 0; i < SKA_ECS_MAX_COMPONENTS; i++) { component_array_remove_component(componentArray, (SkaComponentIndex)i); } + componentArray->signature = SKA_ECS_COMPONENT_TYPE_NONE; } //--- Component Manager ---// typedef struct ComponentManager { - ComponentArray entityComponentArrays[SKA_MAX_ENTITIES]; - SkaComponentType entityComponentSignatures[SKA_MAX_ENTITIES]; + SkaArrayList* componentArrays; } ComponentManager; -static ComponentManager* componentManager = NULL; +static ComponentManager componentManager = { .componentArrays = NULL }; static SkaComponentType component_manager_translate_index_to_type(SkaComponentIndex index); @@ -103,8 +91,8 @@ void ska_ecs_component_manager_initialize() { SKA_ASSERT(componentNameToTypeMap == NULL); componentNameToTypeMap = ska_string_hash_map_create_default_capacity(); - SKA_ASSERT_FMT(componentManager == NULL, "Component Manager is not NULL when trying to initialize"); - componentManager = SKA_MEM_ALLOCATE(ComponentManager); + SKA_ASSERT_FMT(componentManager.componentArrays == NULL, "Component Manager's component arrays are not NULL when trying to initialize"); + componentManager.componentArrays = ska_array_list_create(sizeof(ComponentArray), 1000); } // Assumes component data was already deleted previously @@ -114,58 +102,68 @@ void ska_ecs_component_manager_finalize() { SkaStringHashMapNode* node = iter.pair; SkaComponentTypeInfo* typeInfo = (SkaComponentTypeInfo*)node->value; if (typeInfo) { - SKA_MEM_FREE(typeInfo->name); + SKA_FREE(typeInfo->name); } } ska_string_hash_map_destroy(componentNameToTypeMap); componentNameToTypeMap = NULL; globalComponentIndex = 0; - SKA_ASSERT_FMT(componentManager != NULL, "Component Manager is NULL when trying to finalize..."); - SKA_MEM_FREE(componentManager); - componentManager = NULL; + SKA_ASSERT_FMT(componentManager.componentArrays != NULL, "Component Manager is NULL when trying to finalize..."); + ska_array_list_destroy(componentManager.componentArrays); + componentManager.componentArrays = NULL; } void* ska_ecs_component_manager_get_component(SkaEntity entity, SkaComponentIndex index) { - void* component = component_array_get_component(&componentManager->entityComponentArrays[entity], index); + void* component = ska_ecs_component_manager_get_component_unchecked(entity, index); SKA_ASSERT_FMT(component != NULL, "Entity '%d' doesn't have '%s' component!", entity, ska_ecs_component_get_component_data_index_string(index)); return component; } void* ska_ecs_component_manager_get_component_unchecked(SkaEntity entity, SkaComponentIndex index) { - return component_array_get_component(&componentManager->entityComponentArrays[entity], index); + ComponentArray* componentArray = ska_array_list_get(componentManager.componentArrays, (usize)entity); + return component_array_get_component(componentArray, index); } void ska_ecs_component_manager_set_component(SkaEntity entity, SkaComponentIndex index, void* component) { - component_array_set_component(&componentManager->entityComponentArrays[entity], index, component); - // Update signature - SkaComponentType componentSignature = ska_ecs_component_manager_get_component_signature(entity); - componentSignature |= component_manager_translate_index_to_type(index); - ska_ecs_component_manager_set_component_signature(entity, componentSignature); + ska_ecs_component_manager_reserve(entity); + ComponentArray* componentArray = ska_array_list_get(componentManager.componentArrays, (usize)entity); + component_array_set_component(componentArray, index, component); + componentArray->signature |= component_manager_translate_index_to_type(index); } void ska_ecs_component_manager_remove_component(SkaEntity entity, SkaComponentIndex index) { - SkaComponentType componentSignature = ska_ecs_component_manager_get_component_signature(entity); - componentSignature &= component_manager_translate_index_to_type(index); - ska_ecs_component_manager_set_component_signature(entity, componentSignature); - component_array_remove_component(&componentManager->entityComponentArrays[entity], index); + ComponentArray* componentArray = ska_array_list_get(componentManager.componentArrays, (usize)entity); + componentArray->signature &= component_manager_translate_index_to_type(index); + component_array_remove_component(componentArray, index); } void ska_ecs_component_manager_remove_all_components(SkaEntity entity) { - component_array_remove_all_components(&componentManager->entityComponentArrays[entity]); - ska_ecs_component_manager_set_component_signature(entity, SKA_ECS_COMPONENT_TYPE_NONE); + ComponentArray* componentArray = ska_array_list_get(componentManager.componentArrays, (usize)entity); + component_array_remove_all_components(componentArray); } bool ska_ecs_component_manager_has_component(SkaEntity entity, SkaComponentIndex index) { - return component_array_has_component(&componentManager->entityComponentArrays[entity], index); + ComponentArray* componentArray = ska_array_list_get(componentManager.componentArrays, (usize)entity); + return component_array_has_component(componentArray, index); } void ska_ecs_component_manager_set_component_signature(SkaEntity entity, SkaComponentType componentTypeSignature) { - componentManager->entityComponentSignatures[entity] = componentTypeSignature; + ComponentArray* componentArray = ska_array_list_get(componentManager.componentArrays, (usize)entity); + componentArray->signature = componentTypeSignature; } SkaComponentType ska_ecs_component_manager_get_component_signature(SkaEntity entity) { - return componentManager->entityComponentSignatures[entity]; + const ComponentArray* componentArray = ska_array_list_get(componentManager.componentArrays, (usize)entity); + return componentArray->signature; +} + +void ska_ecs_component_manager_reserve(SkaEntity lastEntity) { + // Add to component array if entity exceeds size + const usize newIndex = (usize)lastEntity; + while (componentManager.componentArrays->size <= newIndex) { + ska_array_list_push_back(componentManager.componentArrays, &(ComponentArray){0}); + } } SkaComponentType component_manager_translate_index_to_type(SkaComponentIndex index) { @@ -189,3 +187,5 @@ const char* ska_ecs_component_get_component_data_index_string(SkaComponentIndex } return "INVALID"; } + +#endif // if SKA_ECS diff --git a/seika/ecs/component.h b/seika/ecs/component.h index 881695a..4180227 100644 --- a/seika/ecs/component.h +++ b/seika/ecs/component.h @@ -1,11 +1,12 @@ #pragma once +#if SKA_ECS + #ifdef __cplusplus extern "C" { #endif -#include -#include +#include "seika/defines.h" #include "entity.h" @@ -31,8 +32,6 @@ typedef struct SkaComponentTypeInfo { usize size; } SkaComponentTypeInfo; - - const SkaComponentTypeInfo* ska_ecs_component_register_type(const char* name, usize componentSize); const SkaComponentTypeInfo* ska_ecs_component_get_type_info(const char* name, usize componentSize); const SkaComponentTypeInfo* ska_ecs_component_find_type_info(const char* name); @@ -49,9 +48,12 @@ void ska_ecs_component_manager_remove_all_components(SkaEntity entity); bool ska_ecs_component_manager_has_component(SkaEntity entity, SkaComponentIndex index); void ska_ecs_component_manager_set_component_signature(SkaEntity entity, SkaComponentType componentTypeSignature); SkaComponentType ska_ecs_component_manager_get_component_signature(SkaEntity entity); +void ska_ecs_component_manager_reserve(SkaEntity lastEntity); const char* ska_ecs_component_get_component_data_index_string(SkaComponentIndex index); #ifdef __cplusplus } #endif + +#endif // if SKA_ECS diff --git a/seika/ecs/ec_system.c b/seika/ecs/ec_system.c index f5afd9b..883c158 100644 --- a/seika/ecs/ec_system.c +++ b/seika/ecs/ec_system.c @@ -1,6 +1,6 @@ -#include "ec_system.h" +#if SKA_ECS -#include +#include "ec_system.h" #include "seika/string.h" #include "seika/flag_utils.h" @@ -52,14 +52,14 @@ void ska_ecs_system_finalize() { } SkaECSSystem* ska_ecs_system_create(const char* systemName) { - SkaECSSystem* newSystem = SKA_MEM_ALLOCATE(SkaECSSystem); + SkaECSSystem* newSystem = SKA_ALLOC_ZEROED(SkaECSSystem); newSystem->name = ska_strdup(systemName); + newSystem->entities = ska_array_list_create_default_capacity(sizeof(SkaEntity)); return newSystem; } SkaECSSystem* ska_ecs_system_create_from_template(SkaECSSystemTemplate* systemTemplate) { - SkaECSSystem* newSystem = SKA_MEM_ALLOCATE(SkaECSSystem); - newSystem->name = ska_strdup(systemTemplate->name); + SkaECSSystem* newSystem = ska_ecs_system_create(systemTemplate->name); newSystem->on_ec_system_register = systemTemplate->on_ec_system_register; newSystem->on_ec_system_destroy = systemTemplate->on_ec_system_destroy; newSystem->on_entity_registered_func = systemTemplate->on_entity_registered_func; @@ -127,7 +127,7 @@ void ska_ecs_system_destroy(SkaECSSystem* entitySystem) { if (entitySystem->on_ec_system_destroy) { entitySystem->on_ec_system_destroy(entitySystem); } - SKA_MEM_FREE(entitySystem); + SKA_FREE(entitySystem); } void ska_ecs_system_register(SkaECSSystem* system) { @@ -206,23 +206,9 @@ void ska_ecs_system_event_entity_end(SkaEntity entity) { ecsSystem->on_entity_end_func(ecsSystem, entity); } } -// NodeComponent* nodeComponent = (NodeComponent*)ska_ecs_component_manager_get_component_unchecked(entity, CreComponentDataIndex_NODE); -// if (nodeComponent != NULL) { -// // Note: Node events should not be created during this time -// ska_event_notify_observers(&nodeComponent->onSceneTreeExit, &(SkaSubjectNotifyPayload) { -// .data = &entity -// }); -// } } void ska_ecs_system_event_entity_entered_scene(SkaEntity entity) { - // Notify scene enter observers before calling it on systems -// NodeComponent* nodeComponent = (NodeComponent*) ska_ecs_component_manager_get_component_unchecked(entity, CreComponentDataIndex_NODE); -// if (nodeComponent != NULL) { -// ska_event_notify_observers(&nodeComponent->onSceneTreeEnter, &(SkaSubjectNotifyPayload) { -// .data = &entity -// }); -// } const SkaComponentType entityComponentSignature = ska_ecs_component_manager_get_component_signature(entity); for (usize i = 0; i < entitySystemData.on_entity_entered_scene_systems_count; i++) { SkaECSSystem* ecsSystem = entitySystemData.on_entity_entered_scene_systems[i]; @@ -274,19 +260,21 @@ void ska_ecs_system_event_network_callback(const char* message) { } } -// --- Internal Functions --- // bool ska_ecs_system_has_entity(SkaEntity entity, SkaECSSystem* system) { - for (usize i = 0; i < system->entity_count; i++) { - if (entity == system->entities[i]) { - return true; - } + return ska_array_list_has(system->entities, &entity); +} + +void ska_ecs_system_remove_entity_from_all_systems(SkaEntity entity) { + for (usize i = 0; i < entitySystemData.entity_systems_count; i++) { + ska_ecs_system_remove_entity_from_system(entity, entitySystemData.entity_systems[i]); } - return false; } +// --- Internal Functions --- // + void ska_ecs_system_insert_entity_into_system(SkaEntity entity, SkaECSSystem* system) { if (!ska_ecs_system_has_entity(entity, system)) { - system->entities[system->entity_count++] = entity; + ska_array_list_push_back(system->entities, &entity); if (system->on_entity_registered_func != NULL) { system->on_entity_registered_func(system, entity); } @@ -296,36 +284,7 @@ void ska_ecs_system_insert_entity_into_system(SkaEntity entity, SkaECSSystem* sy } void ska_ecs_system_remove_entity_from_system(SkaEntity entity, SkaECSSystem* system) { - for (usize i = 0; i < system->entity_count; i++) { - if (entity == system->entities[i]) { - // Entity found - if (i + 1 < SKA_MAX_ENTITIES) { - system->entities[i] = SKA_NULL_ENTITY; - } - if (system->on_entity_unregistered_func != NULL) { - system->on_entity_unregistered_func(system, entity); - } - - // Condense array - for (usize newIndex = i; i < system->entity_count; i++) { - if (system->entities[i] == SKA_NULL_ENTITY) { - // Early exit if 2 consecutive nulls - if (system->entities[i + 1] == SKA_NULL_ENTITY) { - break; - } - system->entities[i] = system->entities[i + 1]; - system->entities[i + 1] = SKA_NULL_ENTITY; - } - } - - system->entity_count--; - break; - } - } + ska_array_list_remove(system->entities, &entity); } -void ska_ecs_system_remove_entity_from_all_systems(SkaEntity entity) { - for (usize i = 0; i < entitySystemData.entity_systems_count; i++) { - ska_ecs_system_remove_entity_from_system(entity, entitySystemData.entity_systems[i]); - } -} +#endif // if SKA_ECS diff --git a/seika/ecs/ec_system.h b/seika/ecs/ec_system.h index 98ba3cb..2d4b3c7 100644 --- a/seika/ecs/ec_system.h +++ b/seika/ecs/ec_system.h @@ -1,6 +1,9 @@ #pragma once +#if SKA_ECS + #include "component.h" +#include "seika/data_structures/array_list.h" #define SKA_ECS_SYSTEM_CREATE(NAME, ...) \ ska_ecs_system_create_with_signature_string(NAME, #__VA_ARGS__) @@ -12,6 +15,8 @@ ska_ecs_system_create_from_template_with_signature_string(TEMPLATE, #__VA_ARGS__ #define SKA_ECS_SYSTEM_REGISTER_FROM_TEMPLATE(TEMPLATE, ...) \ ska_ecs_system_register(ska_ecs_system_create_from_template_with_signature_string(TEMPLATE, #__VA_ARGS__)) +#define SKA_ECS_SYSTEM_ENTITIES_FOR(SYSTEM, VALUE) SKA_ARRAY_LIST_FOR_EACH(SYSTEM->entities, SkaEntity, VALUE) + struct SkaECSSystem; typedef void (*OnECSystemRegister) (struct SkaECSSystem*); @@ -45,9 +50,7 @@ typedef struct SkaECSSystem { FixedUpdateFunc fixed_update_func; NetworkCallbackFunc network_callback_func; SkaComponentType component_signature; - usize entity_count; - // Keeps track of entities that match a component signature - SkaEntity entities[SKA_MAX_ENTITIES]; + SkaArrayList* entities; } SkaECSSystem; typedef struct SkaECSSystemTemplate { @@ -108,3 +111,5 @@ void ska_ecs_system_event_post_update_all_systems(); void ska_ecs_system_event_update_systems(f32 deltaTime); void ska_ecs_system_event_fixed_update_systems(f32 deltaTime); void ska_ecs_system_event_network_callback(const char* message); + +#endif // if SKA_ECS diff --git a/seika/ecs/ecs.c b/seika/ecs/ecs.c index e269fe2..472e53a 100644 --- a/seika/ecs/ecs.c +++ b/seika/ecs/ecs.c @@ -1,3 +1,5 @@ +#if SKA_ECS + #include "ecs.h" void ska_ecs_initialize() { @@ -11,3 +13,5 @@ void ska_ecs_finalize() { ska_ecs_component_manager_finalize(); ska_ecs_system_finalize(); } + +#endif // if SKA_ECS diff --git a/seika/ecs/ecs.h b/seika/ecs/ecs.h index 7b7e0a0..ad44c8a 100644 --- a/seika/ecs/ecs.h +++ b/seika/ecs/ecs.h @@ -1,6 +1,11 @@ #pragma once +#if SKA_ECS + +// Including ecs related headers to simplify includes #include "ec_system.h" void ska_ecs_initialize(); void ska_ecs_finalize(); + +#endif // if SKA_ECS \ No newline at end of file diff --git a/seika/ecs/entity.c b/seika/ecs/entity.c index bfb6b04..c857597 100644 --- a/seika/ecs/entity.c +++ b/seika/ecs/entity.c @@ -1,43 +1,42 @@ +#if SKA_ECS + #include "entity.h" -#include "seika/data_structures/queue.h" +#include "seika/data_structures/id_queue.h" #include "seika/assert.h" -static SkaQueue* entityIdQueue = NULL; -static SkaEntity entityIdCounter = 0; +#define SKA_INITIAL_ENTITY_CAPACITY 1000 + +static SkaIdQueue* entityIdQueue = NULL; static usize activeEntityCount = 0; void ska_ecs_entity_initialize() { SKA_ASSERT(entityIdQueue == NULL); - entityIdQueue = ska_queue_create(SKA_MAX_ENTITIES, SKA_NULL_ENTITY); - while (entityIdCounter < 100) { - ska_queue_enqueue(entityIdQueue, entityIdCounter++); - } + entityIdQueue = ska_id_queue_create(SKA_INITIAL_ENTITY_CAPACITY); } void ska_ecs_entity_finalize() { SKA_ASSERT(entityIdQueue); - ska_queue_destroy(entityIdQueue); + ska_id_queue_destroy(entityIdQueue); entityIdQueue = NULL; - entityIdCounter = 0; activeEntityCount = 0; } SkaEntity ska_ecs_entity_create() { SKA_ASSERT(entityIdQueue); - if (ska_queue_is_empty(entityIdQueue)) { - SKA_ASSERT_FMT(entityIdCounter < SKA_MAX_ENTITIES, "Reached maxed entities ids to create, considering increasing SKA_MAX_ENTITIES!"); - ska_queue_enqueue(entityIdQueue, entityIdCounter++); - } + SkaEntity newEntity; + ska_id_queue_dequeue(entityIdQueue, &newEntity); activeEntityCount++; - return ska_queue_dequeue(entityIdQueue); + return newEntity; } void ska_ecs_entity_return(SkaEntity entity) { SKA_ASSERT(entityIdQueue); - ska_queue_enqueue(entityIdQueue,entity); + ska_id_queue_enqueue(entityIdQueue, entity); activeEntityCount--; } usize ska_ecs_entity_get_active_count() { return activeEntityCount; } + +#endif // if SKA_ECS diff --git a/seika/ecs/entity.h b/seika/ecs/entity.h index ec958b0..d372300 100644 --- a/seika/ecs/entity.h +++ b/seika/ecs/entity.h @@ -1,19 +1,12 @@ #pragma once -#include +#if SKA_ECS #include "seika/defines.h" // Entity is defined as a unsigned 32-bit integer - -// Gives a chance for users to set own max entities -#ifndef SKA_MAX_ENTITIES -#define SKA_MAX_ENTITIES 200000 // starting with 200,000 for now -#endif - -#define SKA_NULL_ENTITY UINT32_MAX - typedef uint32 SkaEntity; +#define SKA_NULL_ENTITY (SkaEntity)-1 void ska_ecs_entity_initialize(); void ska_ecs_entity_finalize(); @@ -22,3 +15,5 @@ SkaEntity ska_ecs_entity_create(); // Push entity to the queue void ska_ecs_entity_return(SkaEntity entity); usize ska_ecs_entity_get_active_count(); + +#endif // if SKA_ECS diff --git a/seika/event.c b/seika/event.c index b983a2c..b28dbd8 100644 --- a/seika/event.c +++ b/seika/event.c @@ -7,24 +7,24 @@ //--- Observer ---// SkaObserver* ska_observer_new(SkaObserverOnNotify onNotifyFunc) { SKA_ASSERT(onNotifyFunc != NULL); - SkaObserver* observer = SKA_MEM_ALLOCATE(SkaObserver); + SkaObserver* observer = SKA_ALLOC_ZEROED(SkaObserver); observer->on_notify = onNotifyFunc; return observer; } void ska_observer_delete(SkaObserver* observer) { - SKA_MEM_FREE(observer); + SKA_FREE(observer); } //--- Event ---// SkaEvent* ska_event_new() { - SkaEvent* event = SKA_MEM_ALLOCATE(SkaEvent); + SkaEvent* event = SKA_ALLOC_ZEROED(SkaEvent); event->observerCount = 0; return event; } void ska_event_delete(SkaEvent* event) { - SKA_MEM_FREE(event); + SKA_FREE(event); } bool ska_event_register_observer(SkaEvent* event, SkaObserver* observer) { diff --git a/seika/file_system.c b/seika/file_system.c index 2b11391..d00afff 100644 --- a/seika/file_system.c +++ b/seika/file_system.c @@ -110,7 +110,7 @@ char* ska_fs_read_file_contents(const char* filePath, usize* sz) { if (fp) { readSize = ska_fs_get_file_size(filePath); // Update buffer - buffer = (char*)SKA_MEM_ALLOCATE_SIZE(readSize + 1); + buffer = (char*)SKA_ALLOC_BYTES(readSize + 1); if (buffer != NULL) { fread(buffer, 1, readSize, fp); buffer[readSize] = '\0'; @@ -130,7 +130,7 @@ char* ska_fs_read_file_contents_without_raw(const char* filePath, usize* sz) { if (fp) { readSize = ska_fs_get_file_size(filePath); // Update buffer - buffer = (char*)SKA_MEM_ALLOCATE_SIZE(readSize + 1); + buffer = (char*)SKA_ALLOC_BYTES(readSize + 1); if (buffer != NULL) { usize bytesRead = 0; while (bytesRead < readSize) { diff --git a/seika/input/input.c b/seika/input/input.c index 172e778..884ffbc 100644 --- a/seika/input/input.c +++ b/seika/input/input.c @@ -1,4 +1,10 @@ +#if SKA_INPUT + +#include + #include "input.h" +#include "sdl_input.h" +#include "seika/string.h" #include "seika/assert.h" #include "seika/memory.h" @@ -45,11 +51,45 @@ typedef struct SkaInputState { static SkaInputState inputState = DEFAULT_INPUT_STATE; static SkaMouse globalMouse = {0}; +static bool isInputActive = false; static SkaInputKey get_key_from_2d_axis_key(SkaInputKey axis2DKey, SkaAxisInputValues* axisInputValues, f32 axisValue); static void set_prev_input_axis_value(SkaInputKey key, SkaAxisInputValues* axisInputValues, f32 axisValue); static void update_axis_key_state(SkaInputKey key, SkaInputInteractionStatus interactionStatus, f32 axisValue, SkaInputDeviceIndex deviceIndex); +bool ska_input_initialize() { + SKA_ASSERT(!isInputActive); + const bool isSDLInitialized = SDL_WasInit(0) != 0; + if (isSDLInitialized) { + if (SDL_InitSubSystem( SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) != 0) { + return false; + } + } else { + if (SDL_Init( SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) != 0) { + return false; + } + } + + + if (!ska_sdl_load_gamepad_mappings()) { + return false; + } + + isInputActive = true; + return true; +} + +void ska_input_finalize() { + SKA_ASSERT(isInputActive); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD); + const bool subsystemsStillInitialized = SDL_WasInit(0) != 0; + if (!subsystemsStillInitialized) { + SDL_Quit(); + } + + isInputActive = false; +} + const char* ska_input_key_to_string(SkaInputKey key) { static const char* keyNames[SkaInputKey_NUMBER_OF_KEYS] = { [SkaInputKey_INVALID] = "Invalid", @@ -388,7 +428,7 @@ SkaInputAction* ska_input_get_input_action(SkaInputActionHandle handle, SkaInput bool ska_input_remove_input_action(SkaInputActionHandle handle, SkaInputDeviceIndex deviceIndex) { SkaInputActionData* actionData = &inputState.inputActionData[deviceIndex][handle]; if (actionData->handle != SKA_INPUT_INVALID_INPUT_ACTION_HANDLE) { - SKA_MEM_FREE(actionData->action.name); + SKA_FREE(actionData->action.name); actionData->action.name = NULL; actionData->handle = SKA_INPUT_INVALID_INPUT_ACTION_HANDLE; return true; @@ -565,3 +605,5 @@ void update_axis_key_state(SkaInputKey key, SkaInputInteractionStatus interactio } } } + +#endif // if SKA_INPUT diff --git a/seika/input/input.h b/seika/input/input.h index b293b10..a1ef0cc 100644 --- a/seika/input/input.h +++ b/seika/input/input.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_INPUT + #ifdef __cplusplus extern "C" { #endif @@ -250,6 +252,9 @@ typedef struct SkaInputAction { usize actionValuesCount; } SkaInputAction; +bool ska_input_initialize(); +void ska_input_finalize(); + const char* ska_input_key_to_string(SkaInputKey key); SkaInputKey ska_input_string_to_key(const char* keyName); @@ -290,3 +295,5 @@ void ska_input_reset(SkaInputDeviceIndex deviceIndex); #ifdef __cplusplus } #endif + +#endif // if SKA_INPUT diff --git a/seika/input/sdl_gamepad_db.h b/seika/input/sdl_gamepad_db.h index 1b09484..7b80af6 100644 --- a/seika/input/sdl_gamepad_db.h +++ b/seika/input/sdl_gamepad_db.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_INPUT + const unsigned char SKA_GAMEPAD_DB_HEX[] = { 0x23, 0x20, 0x47, 0x61, 0x6d, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x44, 0x42, 0x20, 0x66, 0x6f, 0x72, @@ -41985,3 +41987,5 @@ const unsigned char SKA_GAMEPAD_DB_HEX[] = { }; #define SKA_GAMEPAD_DB_STR (const char*)SKA_GAMEPAD_DB_HEX const unsigned int SKA_GAMEPAD_DB_SIZE = 503770; + +#endif // if SKA_INPUT diff --git a/seika/input/sdl_input.c b/seika/input/sdl_input.c new file mode 100644 index 0000000..c63e64d --- /dev/null +++ b/seika/input/sdl_input.c @@ -0,0 +1,326 @@ +#if SKA_INPUT + +#include "sdl_input.h" +#include "sdl_gamepad_db.h" + + +typedef struct SkaSDLGamepadData { + SDL_Gamepad* gamepad; + SkaInputDeviceIndex deviceIndex; +} SkaSDLGamepadData; + +static SkaSDLGamepadData gamepadData[SKA_INPUT_MAX_DEVICES]; +static SkaSDLGamepadData gamepadDataByPlayerIndex[SKA_INPUT_MAX_DEVICES]; +static uint32 activeGamepads = 0; + +SkaInputKey ska_sdl_keycode_to_input_key(SDL_GamepadButton keycode) { + switch ((int32)keycode) { + case SDLK_TAB: return SkaInputKey_KEYBOARD_TAB; + case SDLK_LEFT: return SkaInputKey_KEYBOARD_LEFT; + case SDLK_RIGHT: return SkaInputKey_KEYBOARD_RIGHT; + case SDLK_UP: return SkaInputKey_KEYBOARD_UP; + case SDLK_DOWN: return SkaInputKey_KEYBOARD_DOWN; + case SDLK_PAGEDOWN: return SkaInputKey_KEYBOARD_PAGE_DOWN; + case SDLK_PAGEUP: return SkaInputKey_KEYBOARD_PAGE_UP; + case SDLK_HOME: return SkaInputKey_KEYBOARD_HOME; + case SDLK_END: return SkaInputKey_KEYBOARD_END; + case SDLK_INSERT: return SkaInputKey_KEYBOARD_INSERT; + case SDLK_DELETE: return SkaInputKey_KEYBOARD_DELETE; + case SDLK_BACKSPACE: return SkaInputKey_KEYBOARD_BACKSPACE; + case SDLK_SPACE: return SkaInputKey_KEYBOARD_SPACE; + case SDLK_RETURN: return SkaInputKey_KEYBOARD_RETURN; + case SDLK_ESCAPE: return SkaInputKey_KEYBOARD_ESCAPE; + case SDLK_QUOTE: return SkaInputKey_KEYBOARD_QUOTE; + case SDLK_COMMA: return SkaInputKey_KEYBOARD_COMMA; + case SDLK_MINUS: return SkaInputKey_KEYBOARD_MINUS; + case SDLK_PERIOD: return SkaInputKey_KEYBOARD_PERIOD; + case SDLK_SLASH: return SkaInputKey_KEYBOARD_SLASH; + case SDLK_SEMICOLON: return SkaInputKey_KEYBOARD_SEMICOLON; + case SDLK_EQUALS: return SkaInputKey_KEYBOARD_EQUALS; + case SDLK_LEFTBRACKET: return SkaInputKey_KEYBOARD_LEFT_BRACKET; + case SDLK_BACKSLASH: return SkaInputKey_KEYBOARD_BACKSLASH; + case SDLK_RIGHTBRACKET: return SkaInputKey_KEYBOARD_RIGHT_BRACKET; + case SDLK_BACKQUOTE: return SkaInputKey_KEYBOARD_BACKQUOTE; + case SDLK_CAPSLOCK: return SkaInputKey_KEYBOARD_CAPS_LOCK; + case SDLK_SCROLLLOCK: return SkaInputKey_KEYBOARD_SCROLL_LOCK; + case SDLK_NUMLOCKCLEAR: return SkaInputKey_KEYBOARD_NUM_LOCK_CLEAR; + case SDLK_PRINTSCREEN: return SkaInputKey_KEYBOARD_PRINT_SCREEN; + case SDLK_PAUSE: return SkaInputKey_KEYBOARD_PAUSE; + case SDLK_KP_0: return SkaInputKey_KEYBOARD_KEYPAD_0; + case SDLK_KP_1: return SkaInputKey_KEYBOARD_KEYPAD_1; + case SDLK_KP_2: return SkaInputKey_KEYBOARD_KEYPAD_2; + case SDLK_KP_3: return SkaInputKey_KEYBOARD_KEYPAD_3; + case SDLK_KP_4: return SkaInputKey_KEYBOARD_KEYPAD_4; + case SDLK_KP_5: return SkaInputKey_KEYBOARD_KEYPAD_5; + case SDLK_KP_6: return SkaInputKey_KEYBOARD_KEYPAD_6; + case SDLK_KP_7: return SkaInputKey_KEYBOARD_KEYPAD_7; + case SDLK_KP_8: return SkaInputKey_KEYBOARD_KEYPAD_8; + case SDLK_KP_9: return SkaInputKey_KEYBOARD_KEYPAD_9; + case SDLK_KP_PERIOD: return SkaInputKey_KEYBOARD_KEYPAD_PERIOD; + case SDLK_KP_MULTIPLY: return SkaInputKey_KEYBOARD_KEYPAD_MULTIPLY; + case SDLK_KP_MINUS: return SkaInputKey_KEYBOARD_KEYPAD_MINUS; + case SDLK_KP_PLUS: return SkaInputKey_KEYBOARD_KEYPAD_PLUS; + case SDLK_KP_ENTER: return SkaInputKey_KEYBOARD_KEYPAD_ENTER; + case SDLK_KP_EQUALS: return SkaInputKey_KEYBOARD_KEYPAD_EQUALS; + case SDLK_LCTRL: return SkaInputKey_KEYBOARD_LEFT_CONTROL; + case SDLK_LSHIFT: return SkaInputKey_KEYBOARD_LEFT_SHIFT; + case SDLK_LALT: return SkaInputKey_KEYBOARD_LEFT_ALT; + case SDLK_LGUI: return SkaInputKey_KEYBOARD_LEFT_GUI; + case SDLK_RCTRL: return SkaInputKey_KEYBOARD_RIGHT_CONTROL; + case SDLK_RSHIFT: return SkaInputKey_KEYBOARD_RIGHT_SHIFT; + case SDLK_RALT: return SkaInputKey_KEYBOARD_RIGHT_ALT; + case SDLK_RGUI: return SkaInputKey_KEYBOARD_RIGHT_GUI; + case SDLK_APPLICATION: return SkaInputKey_KEYBOARD_APPLICATION; + case SDLK_0: return SkaInputKey_KEYBOARD_NUM_0; + case SDLK_1: return SkaInputKey_KEYBOARD_NUM_1; + case SDLK_2: return SkaInputKey_KEYBOARD_NUM_2; + case SDLK_3: return SkaInputKey_KEYBOARD_NUM_3; + case SDLK_4: return SkaInputKey_KEYBOARD_NUM_4; + case SDLK_5: return SkaInputKey_KEYBOARD_NUM_5; + case SDLK_6: return SkaInputKey_KEYBOARD_NUM_6; + case SDLK_7: return SkaInputKey_KEYBOARD_NUM_7; + case SDLK_8: return SkaInputKey_KEYBOARD_NUM_8; + case SDLK_9: return SkaInputKey_KEYBOARD_NUM_9; + case SDLK_a: return SkaInputKey_KEYBOARD_A; + case SDLK_b: return SkaInputKey_KEYBOARD_B; + case SDLK_c: return SkaInputKey_KEYBOARD_C; + case SDLK_d: return SkaInputKey_KEYBOARD_D; + case SDLK_e: return SkaInputKey_KEYBOARD_E; + case SDLK_f: return SkaInputKey_KEYBOARD_F; + case SDLK_g: return SkaInputKey_KEYBOARD_G; + case SDLK_h: return SkaInputKey_KEYBOARD_H; + case SDLK_i: return SkaInputKey_KEYBOARD_I; + case SDLK_j: return SkaInputKey_KEYBOARD_J; + case SDLK_k: return SkaInputKey_KEYBOARD_K; + case SDLK_l: return SkaInputKey_KEYBOARD_L; + case SDLK_m: return SkaInputKey_KEYBOARD_M; + case SDLK_n: return SkaInputKey_KEYBOARD_N; + case SDLK_o: return SkaInputKey_KEYBOARD_O; + case SDLK_p: return SkaInputKey_KEYBOARD_P; + case SDLK_q: return SkaInputKey_KEYBOARD_Q; + case SDLK_r: return SkaInputKey_KEYBOARD_R; + case SDLK_s: return SkaInputKey_KEYBOARD_S; + case SDLK_t: return SkaInputKey_KEYBOARD_T; + case SDLK_u: return SkaInputKey_KEYBOARD_U; + case SDLK_v: return SkaInputKey_KEYBOARD_V; + case SDLK_w: return SkaInputKey_KEYBOARD_W; + case SDLK_x: return SkaInputKey_KEYBOARD_X; + case SDLK_y: return SkaInputKey_KEYBOARD_Y; + case SDLK_z: return SkaInputKey_KEYBOARD_Z; + case SDLK_F1: return SkaInputKey_KEYBOARD_F1; + case SDLK_F2: return SkaInputKey_KEYBOARD_F2; + case SDLK_F3: return SkaInputKey_KEYBOARD_F3; + case SDLK_F4: return SkaInputKey_KEYBOARD_F4; + case SDLK_F5: return SkaInputKey_KEYBOARD_F5; + case SDLK_F6: return SkaInputKey_KEYBOARD_F6; + case SDLK_F7: return SkaInputKey_KEYBOARD_F7; + case SDLK_F8: return SkaInputKey_KEYBOARD_F8; + case SDLK_F9: return SkaInputKey_KEYBOARD_F9; + case SDLK_F10: return SkaInputKey_KEYBOARD_F10; + case SDLK_F11: return SkaInputKey_KEYBOARD_F11; + case SDLK_F12: return SkaInputKey_KEYBOARD_F12; + case SDLK_F13: return SkaInputKey_KEYBOARD_F13; + case SDLK_F14: return SkaInputKey_KEYBOARD_F14; + case SDLK_F15: return SkaInputKey_KEYBOARD_F15; + case SDLK_F16: return SkaInputKey_KEYBOARD_F16; + case SDLK_F17: return SkaInputKey_KEYBOARD_F17; + case SDLK_F18: return SkaInputKey_KEYBOARD_F18; + case SDLK_F19: return SkaInputKey_KEYBOARD_F19; + case SDLK_F20: return SkaInputKey_KEYBOARD_F20; + case SDLK_F21: return SkaInputKey_KEYBOARD_F21; + case SDLK_F22: return SkaInputKey_KEYBOARD_F22; + case SDLK_F23: return SkaInputKey_KEYBOARD_F23; + case SDLK_F24: return SkaInputKey_KEYBOARD_F24; + case SDLK_AC_BACK: return SkaInputKey_KEYBOARD_APP_BACK; + case SDLK_AC_FORWARD: return SkaInputKey_KEYBOARD_APP_FORWARD; + default: return SkaInputKey_INVALID; + } +} + + +SkaInputKey ska_sdl_mouse_button_to_input_key(SDL_MouseButtonEvent button) { + switch (button.button) { + case SDL_BUTTON_LEFT: return SkaInputKey_MOUSE_BUTTON_LEFT; + case SDL_BUTTON_RIGHT: return SkaInputKey_MOUSE_BUTTON_RIGHT; + case SDL_BUTTON_MIDDLE: return SkaInputKey_MOUSE_BUTTON_MIDDLE; + default: return SkaInputKey_INVALID; + } +} + +SkaInputKey ska_sdl_gamepad_button_to_input_key(SDL_GamepadButton button) { + switch (button) { + case SDL_GAMEPAD_BUTTON_SOUTH: return SkaInputKey_GAMEPAD_FACE_BUTTON_SOUTH; + case SDL_GAMEPAD_BUTTON_EAST: return SkaInputKey_GAMEPAD_FACE_BUTTON_EAST; + case SDL_GAMEPAD_BUTTON_WEST: return SkaInputKey_GAMEPAD_FACE_BUTTON_WEST; + case SDL_GAMEPAD_BUTTON_NORTH: return SkaInputKey_GAMEPAD_FACE_BUTTON_NORTH; + case SDL_GAMEPAD_BUTTON_BACK: return SkaInputKey_GAMEPAD_BACK; + case SDL_GAMEPAD_BUTTON_START: return SkaInputKey_GAMEPAD_START; + case SDL_GAMEPAD_BUTTON_LEFT_STICK: return SkaInputKey_GAMEPAD_LEFT_ANALOG_BUTTON; + case SDL_GAMEPAD_BUTTON_RIGHT_STICK: return SkaInputKey_GAMEPAD_RIGHT_ANALOG_BUTTON; + case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER: return SkaInputKey_GAMEPAD_LEFT_SHOULDER; + case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER: return SkaInputKey_GAMEPAD_RIGHT_SHOULDER; + case SDL_GAMEPAD_BUTTON_DPAD_UP: return SkaInputKey_GAMEPAD_DPAD_UP; + case SDL_GAMEPAD_BUTTON_DPAD_DOWN: return SkaInputKey_GAMEPAD_DPAD_DOWN; + case SDL_GAMEPAD_BUTTON_DPAD_LEFT: return SkaInputKey_GAMEPAD_DPAD_LEFT; + case SDL_GAMEPAD_BUTTON_DPAD_RIGHT: return SkaInputKey_GAMEPAD_DPAD_RIGHT; + default: return SkaInputKey_INVALID; + } +} + +SkaInputKey ska_sdl_gamepad_axis_to_input_key(SDL_GamepadAxis axis) { + switch (axis) { + case SDL_GAMEPAD_AXIS_LEFTX: return SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_X; + case SDL_GAMEPAD_AXIS_LEFTY: return SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_Y; + case SDL_GAMEPAD_AXIS_RIGHTX: return SkaInputKey_GAMEPAD_RIGHT_ANALOG_2D_AXIS_X; + case SDL_GAMEPAD_AXIS_RIGHTY: return SkaInputKey_GAMEPAD_RIGHT_ANALOG_2D_AXIS_Y; + case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: return SkaInputKey_GAMEPAD_LEFT_TRIGGER; + case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: return SkaInputKey_GAMEPAD_RIGHT_TRIGGER; + default: return SkaInputKey_INVALID; + } +} + +bool ska_sdl_load_gamepad_mappings() { + const int loadResult = SDL_AddGamepadMapping(SKA_GAMEPAD_DB_STR); + return loadResult >= 0; +} + +void ska_sdl_notify_input_event(const SkaSDLInputEvent* inputEvent) { + ska_input_register_input_event(inputEvent->sourceType, inputEvent->key, inputEvent->triggerType, inputEvent->deviceIndex, inputEvent->axisMotionValue); +} + +void ska_sdl_process_event(SDL_Event event) { + SkaSDLInputEvent inputEvent = { + .sourceType = SkaInputSourceType_INVALID, + .triggerType = SkaInputTriggerType_INVALID, + .deviceIndex = SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, + .key = SkaInputKey_INVALID, + .axisMotionValue = 0.0f + }; + + switch (event.type) { + // Mouse + case SDL_EVENT_MOUSE_MOTION: { + SkaMouse* mouse = ska_input_get_mouse(); + mouse->position = (SkaVector2){ .x = (f32)event.motion.x, .y = (f32)event.motion.y }; + break; + } + + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: { + inputEvent.sourceType = SkaInputSourceType_MOUSE; + inputEvent.triggerType = event.type == SDL_EVENT_MOUSE_BUTTON_DOWN ? SkaInputTriggerType_PRESSED : SkaInputTriggerType_RELEASED; + inputEvent.key = ska_sdl_mouse_button_to_input_key(event.button); + break; + } + // Keyboard + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: { + inputEvent.sourceType = SkaInputSourceType_KEYBOARD; + inputEvent.triggerType = event.type == SDL_EVENT_KEY_DOWN ? SkaInputTriggerType_PRESSED : SkaInputTriggerType_RELEASED, + inputEvent.key = ska_sdl_keycode_to_input_key(event.key.keysym.sym); + break; + } + // Gamepad + case SDL_EVENT_GAMEPAD_ADDED: { + const SDL_JoystickID deviceIndex = event.gdevice.which; + SDL_Gamepad* newGamepad = SDL_OpenGamepad(deviceIndex); + const int playerIndex = SDL_GetGamepadPlayerIndex(newGamepad); + const SkaSDLGamepadData newGamepadData = { .gamepad = newGamepad, .deviceIndex = playerIndex }; + gamepadData[deviceIndex] = newGamepadData; + gamepadDataByPlayerIndex[playerIndex] = newGamepadData; + activeGamepads++; + + inputEvent.sourceType = SkaInputSourceType_GAMEPAD; + inputEvent.triggerType = SkaInputTriggerType_DEVICE_ADDED; + inputEvent.deviceIndex = playerIndex; + break; + } + case SDL_EVENT_GAMEPAD_REMOVED: { + const SDL_JoystickID deviceIndex = event.gdevice.which; + SDL_Gamepad* removedGamepad = gamepadData[deviceIndex].gamepad; + const SkaInputDeviceIndex playerIndex = gamepadData[deviceIndex].deviceIndex; + SDL_CloseGamepad(removedGamepad); + const SkaSDLGamepadData defaultGamepadData = (SkaSDLGamepadData){ .gamepad = NULL, .deviceIndex = -1 }; + gamepadData[deviceIndex] = defaultGamepadData; + gamepadDataByPlayerIndex[playerIndex] = defaultGamepadData; + activeGamepads--; + + inputEvent.sourceType = SkaInputSourceType_GAMEPAD; + inputEvent.triggerType = SkaInputTriggerType_DEVICE_REMOVED; + inputEvent.deviceIndex = playerIndex; + break; + } + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: { + const SDL_JoystickID deviceIndex = event.jbutton.which; + const SkaInputDeviceIndex playerIndex = gamepadData[deviceIndex].deviceIndex; + const bool isButtonPressed = event.jbutton.state == SDL_PRESSED; + const SDL_GamepadButton buttonValue = event.jbutton.button; + + inputEvent.sourceType = SkaInputSourceType_GAMEPAD; + inputEvent.triggerType = isButtonPressed ? SkaInputTriggerType_PRESSED : SkaInputTriggerType_RELEASED; + inputEvent.deviceIndex = playerIndex; + inputEvent.key = ska_sdl_gamepad_button_to_input_key(buttonValue); + break; + } + default: + break; + } + ska_sdl_notify_input_event(&inputEvent); +} + +// Call after looping through all sdl input events for a frame +void ska_sdl_process_axis_events() { +#define SKA_SDL_GAMEPAD_AXIS_DEAD_ZONE 8000 +#define SKA_MAX_AXIS_VALUES 6 + + static const SDL_GamepadAxis AXIS_KEYS[SKA_MAX_AXIS_VALUES] = { + SDL_GAMEPAD_AXIS_LEFTX, SDL_GAMEPAD_AXIS_LEFTY, + SDL_GAMEPAD_AXIS_RIGHTX, SDL_GAMEPAD_AXIS_RIGHTY, + SDL_GAMEPAD_AXIS_LEFT_TRIGGER, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER + }; + static bool hasGamepadStoppedAxisMotion[SKA_INPUT_MAX_DEVICES][SKA_MAX_AXIS_VALUES] = { + {true, true, true, true, true, true}, + {true, true, true, true, true, true}, + {true, true, true, true, true, true}, + {true, true, true, true, true, true}, + {true, true, true, true, true, true}, + {true, true, true, true, true, true}, + {true, true, true, true, true, true}, + {true, true, true, true, true, true} + }; + + for (uint32 i = 0; i < activeGamepads; i++) { + SkaSDLGamepadData* currentGamepadData = &gamepadDataByPlayerIndex[i]; + for (SDL_GamepadAxis axis = 0; axis < SKA_MAX_AXIS_VALUES; axis++) { + const int16 axisValue = SDL_GetGamepadAxis(currentGamepadData->gamepad, axis); + const SkaInputTriggerType triggerType = + axisValue < SKA_SDL_GAMEPAD_AXIS_DEAD_ZONE && axisValue > -SKA_SDL_GAMEPAD_AXIS_DEAD_ZONE + ? SkaInputTriggerType_AXIS_STOPPED_MOTION : SkaInputTriggerType_AXIS_IN_MOTION; + // Skip sending event if axis motion is already stopped + bool *hasStoppedAxisMotion = &hasGamepadStoppedAxisMotion[i][axis]; + if (triggerType == SkaInputTriggerType_AXIS_STOPPED_MOTION) { + if (*hasStoppedAxisMotion) { + continue; + } else { + *hasStoppedAxisMotion = true; + } + } else { + *hasStoppedAxisMotion = false; + } + const f32 axisValueNormalized = ska_math_map_to_range((f32) axisValue, (f32) INT16_MIN, (f32) INT16_MAX,-1.0f, 1.0f); + const SkaSDLInputEvent inputEvent = { + .sourceType = SkaInputSourceType_GAMEPAD, + .triggerType = triggerType, + .deviceIndex = (SkaInputDeviceIndex)i, + .key = ska_sdl_gamepad_axis_to_input_key(axis), + .axisMotionValue = axisValueNormalized + }; + ska_sdl_notify_input_event(&inputEvent); + } + } + +#undef SKA_MAX_AXIS_VALUES +} + +#endif // #if SKA_INPUT \ No newline at end of file diff --git a/seika/input/sdl_input.h b/seika/input/sdl_input.h index 7001e6a..a9907d5 100644 --- a/seika/input/sdl_input.h +++ b/seika/input/sdl_input.h @@ -1,14 +1,10 @@ #pragma once +#if SKA_INPUT + #include #include "input.h" -#include "sdl_gamepad_db.h" - -typedef struct SkaSDLGamepadData { - SDL_Gamepad* gamepad; - SkaInputDeviceIndex deviceIndex; -} SkaSDLGamepadData; typedef struct SkaSDLInputEvent { SkaInputSourceType sourceType; @@ -18,316 +14,14 @@ typedef struct SkaSDLInputEvent { f32 axisMotionValue; } SkaSDLInputEvent; -static SkaSDLGamepadData gamepadData[SKA_INPUT_MAX_DEVICES]; -static SkaSDLGamepadData gamepadDataByPlayerIndex[SKA_INPUT_MAX_DEVICES]; -static uint32 activeGamepads = 0; - -SkaInputKey ska_sdl_keycode_to_input_key(SDL_GamepadButton keycode) { - switch ((int32)keycode) { - case SDLK_TAB: return SkaInputKey_KEYBOARD_TAB; - case SDLK_LEFT: return SkaInputKey_KEYBOARD_LEFT; - case SDLK_RIGHT: return SkaInputKey_KEYBOARD_RIGHT; - case SDLK_UP: return SkaInputKey_KEYBOARD_UP; - case SDLK_DOWN: return SkaInputKey_KEYBOARD_DOWN; - case SDLK_PAGEDOWN: return SkaInputKey_KEYBOARD_PAGE_DOWN; - case SDLK_PAGEUP: return SkaInputKey_KEYBOARD_PAGE_UP; - case SDLK_HOME: return SkaInputKey_KEYBOARD_HOME; - case SDLK_END: return SkaInputKey_KEYBOARD_END; - case SDLK_INSERT: return SkaInputKey_KEYBOARD_INSERT; - case SDLK_DELETE: return SkaInputKey_KEYBOARD_DELETE; - case SDLK_BACKSPACE: return SkaInputKey_KEYBOARD_BACKSPACE; - case SDLK_SPACE: return SkaInputKey_KEYBOARD_SPACE; - case SDLK_RETURN: return SkaInputKey_KEYBOARD_RETURN; - case SDLK_ESCAPE: return SkaInputKey_KEYBOARD_ESCAPE; - case SDLK_QUOTE: return SkaInputKey_KEYBOARD_QUOTE; - case SDLK_COMMA: return SkaInputKey_KEYBOARD_COMMA; - case SDLK_MINUS: return SkaInputKey_KEYBOARD_MINUS; - case SDLK_PERIOD: return SkaInputKey_KEYBOARD_PERIOD; - case SDLK_SLASH: return SkaInputKey_KEYBOARD_SLASH; - case SDLK_SEMICOLON: return SkaInputKey_KEYBOARD_SEMICOLON; - case SDLK_EQUALS: return SkaInputKey_KEYBOARD_EQUALS; - case SDLK_LEFTBRACKET: return SkaInputKey_KEYBOARD_LEFT_BRACKET; - case SDLK_BACKSLASH: return SkaInputKey_KEYBOARD_BACKSLASH; - case SDLK_RIGHTBRACKET: return SkaInputKey_KEYBOARD_RIGHT_BRACKET; - case SDLK_BACKQUOTE: return SkaInputKey_KEYBOARD_BACKQUOTE; - case SDLK_CAPSLOCK: return SkaInputKey_KEYBOARD_CAPS_LOCK; - case SDLK_SCROLLLOCK: return SkaInputKey_KEYBOARD_SCROLL_LOCK; - case SDLK_NUMLOCKCLEAR: return SkaInputKey_KEYBOARD_NUM_LOCK_CLEAR; - case SDLK_PRINTSCREEN: return SkaInputKey_KEYBOARD_PRINT_SCREEN; - case SDLK_PAUSE: return SkaInputKey_KEYBOARD_PAUSE; - case SDLK_KP_0: return SkaInputKey_KEYBOARD_KEYPAD_0; - case SDLK_KP_1: return SkaInputKey_KEYBOARD_KEYPAD_1; - case SDLK_KP_2: return SkaInputKey_KEYBOARD_KEYPAD_2; - case SDLK_KP_3: return SkaInputKey_KEYBOARD_KEYPAD_3; - case SDLK_KP_4: return SkaInputKey_KEYBOARD_KEYPAD_4; - case SDLK_KP_5: return SkaInputKey_KEYBOARD_KEYPAD_5; - case SDLK_KP_6: return SkaInputKey_KEYBOARD_KEYPAD_6; - case SDLK_KP_7: return SkaInputKey_KEYBOARD_KEYPAD_7; - case SDLK_KP_8: return SkaInputKey_KEYBOARD_KEYPAD_8; - case SDLK_KP_9: return SkaInputKey_KEYBOARD_KEYPAD_9; - case SDLK_KP_PERIOD: return SkaInputKey_KEYBOARD_KEYPAD_PERIOD; - case SDLK_KP_MULTIPLY: return SkaInputKey_KEYBOARD_KEYPAD_MULTIPLY; - case SDLK_KP_MINUS: return SkaInputKey_KEYBOARD_KEYPAD_MINUS; - case SDLK_KP_PLUS: return SkaInputKey_KEYBOARD_KEYPAD_PLUS; - case SDLK_KP_ENTER: return SkaInputKey_KEYBOARD_KEYPAD_ENTER; - case SDLK_KP_EQUALS: return SkaInputKey_KEYBOARD_KEYPAD_EQUALS; - case SDLK_LCTRL: return SkaInputKey_KEYBOARD_LEFT_CONTROL; - case SDLK_LSHIFT: return SkaInputKey_KEYBOARD_LEFT_SHIFT; - case SDLK_LALT: return SkaInputKey_KEYBOARD_LEFT_ALT; - case SDLK_LGUI: return SkaInputKey_KEYBOARD_LEFT_GUI; - case SDLK_RCTRL: return SkaInputKey_KEYBOARD_RIGHT_CONTROL; - case SDLK_RSHIFT: return SkaInputKey_KEYBOARD_RIGHT_SHIFT; - case SDLK_RALT: return SkaInputKey_KEYBOARD_RIGHT_ALT; - case SDLK_RGUI: return SkaInputKey_KEYBOARD_RIGHT_GUI; - case SDLK_APPLICATION: return SkaInputKey_KEYBOARD_APPLICATION; - case SDLK_0: return SkaInputKey_KEYBOARD_NUM_0; - case SDLK_1: return SkaInputKey_KEYBOARD_NUM_1; - case SDLK_2: return SkaInputKey_KEYBOARD_NUM_2; - case SDLK_3: return SkaInputKey_KEYBOARD_NUM_3; - case SDLK_4: return SkaInputKey_KEYBOARD_NUM_4; - case SDLK_5: return SkaInputKey_KEYBOARD_NUM_5; - case SDLK_6: return SkaInputKey_KEYBOARD_NUM_6; - case SDLK_7: return SkaInputKey_KEYBOARD_NUM_7; - case SDLK_8: return SkaInputKey_KEYBOARD_NUM_8; - case SDLK_9: return SkaInputKey_KEYBOARD_NUM_9; - case SDLK_a: return SkaInputKey_KEYBOARD_A; - case SDLK_b: return SkaInputKey_KEYBOARD_B; - case SDLK_c: return SkaInputKey_KEYBOARD_C; - case SDLK_d: return SkaInputKey_KEYBOARD_D; - case SDLK_e: return SkaInputKey_KEYBOARD_E; - case SDLK_f: return SkaInputKey_KEYBOARD_F; - case SDLK_g: return SkaInputKey_KEYBOARD_G; - case SDLK_h: return SkaInputKey_KEYBOARD_H; - case SDLK_i: return SkaInputKey_KEYBOARD_I; - case SDLK_j: return SkaInputKey_KEYBOARD_J; - case SDLK_k: return SkaInputKey_KEYBOARD_K; - case SDLK_l: return SkaInputKey_KEYBOARD_L; - case SDLK_m: return SkaInputKey_KEYBOARD_M; - case SDLK_n: return SkaInputKey_KEYBOARD_N; - case SDLK_o: return SkaInputKey_KEYBOARD_O; - case SDLK_p: return SkaInputKey_KEYBOARD_P; - case SDLK_q: return SkaInputKey_KEYBOARD_Q; - case SDLK_r: return SkaInputKey_KEYBOARD_R; - case SDLK_s: return SkaInputKey_KEYBOARD_S; - case SDLK_t: return SkaInputKey_KEYBOARD_T; - case SDLK_u: return SkaInputKey_KEYBOARD_U; - case SDLK_v: return SkaInputKey_KEYBOARD_V; - case SDLK_w: return SkaInputKey_KEYBOARD_W; - case SDLK_x: return SkaInputKey_KEYBOARD_X; - case SDLK_y: return SkaInputKey_KEYBOARD_Y; - case SDLK_z: return SkaInputKey_KEYBOARD_Z; - case SDLK_F1: return SkaInputKey_KEYBOARD_F1; - case SDLK_F2: return SkaInputKey_KEYBOARD_F2; - case SDLK_F3: return SkaInputKey_KEYBOARD_F3; - case SDLK_F4: return SkaInputKey_KEYBOARD_F4; - case SDLK_F5: return SkaInputKey_KEYBOARD_F5; - case SDLK_F6: return SkaInputKey_KEYBOARD_F6; - case SDLK_F7: return SkaInputKey_KEYBOARD_F7; - case SDLK_F8: return SkaInputKey_KEYBOARD_F8; - case SDLK_F9: return SkaInputKey_KEYBOARD_F9; - case SDLK_F10: return SkaInputKey_KEYBOARD_F10; - case SDLK_F11: return SkaInputKey_KEYBOARD_F11; - case SDLK_F12: return SkaInputKey_KEYBOARD_F12; - case SDLK_F13: return SkaInputKey_KEYBOARD_F13; - case SDLK_F14: return SkaInputKey_KEYBOARD_F14; - case SDLK_F15: return SkaInputKey_KEYBOARD_F15; - case SDLK_F16: return SkaInputKey_KEYBOARD_F16; - case SDLK_F17: return SkaInputKey_KEYBOARD_F17; - case SDLK_F18: return SkaInputKey_KEYBOARD_F18; - case SDLK_F19: return SkaInputKey_KEYBOARD_F19; - case SDLK_F20: return SkaInputKey_KEYBOARD_F20; - case SDLK_F21: return SkaInputKey_KEYBOARD_F21; - case SDLK_F22: return SkaInputKey_KEYBOARD_F22; - case SDLK_F23: return SkaInputKey_KEYBOARD_F23; - case SDLK_F24: return SkaInputKey_KEYBOARD_F24; - case SDLK_AC_BACK: return SkaInputKey_KEYBOARD_APP_BACK; - case SDLK_AC_FORWARD: return SkaInputKey_KEYBOARD_APP_FORWARD; - default: return SkaInputKey_INVALID; - } -} - - -SkaInputKey ska_sdl_mouse_button_to_input_key(SDL_MouseButtonEvent button) { - switch (button.button) { - case SDL_BUTTON_LEFT: return SkaInputKey_MOUSE_BUTTON_LEFT; - case SDL_BUTTON_RIGHT: return SkaInputKey_MOUSE_BUTTON_RIGHT; - case SDL_BUTTON_MIDDLE: return SkaInputKey_MOUSE_BUTTON_MIDDLE; - default: return SkaInputKey_INVALID; - } -} - -SkaInputKey ska_sdl_gamepad_button_to_input_key(SDL_GamepadButton button) { - switch (button) { - case SDL_GAMEPAD_BUTTON_SOUTH: return SkaInputKey_GAMEPAD_FACE_BUTTON_SOUTH; - case SDL_GAMEPAD_BUTTON_EAST: return SkaInputKey_GAMEPAD_FACE_BUTTON_EAST; - case SDL_GAMEPAD_BUTTON_WEST: return SkaInputKey_GAMEPAD_FACE_BUTTON_WEST; - case SDL_GAMEPAD_BUTTON_NORTH: return SkaInputKey_GAMEPAD_FACE_BUTTON_NORTH; - case SDL_GAMEPAD_BUTTON_BACK: return SkaInputKey_GAMEPAD_BACK; - case SDL_GAMEPAD_BUTTON_START: return SkaInputKey_GAMEPAD_START; - case SDL_GAMEPAD_BUTTON_LEFT_STICK: return SkaInputKey_GAMEPAD_LEFT_ANALOG_BUTTON; - case SDL_GAMEPAD_BUTTON_RIGHT_STICK: return SkaInputKey_GAMEPAD_RIGHT_ANALOG_BUTTON; - case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER: return SkaInputKey_GAMEPAD_LEFT_SHOULDER; - case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER: return SkaInputKey_GAMEPAD_RIGHT_SHOULDER; - case SDL_GAMEPAD_BUTTON_DPAD_UP: return SkaInputKey_GAMEPAD_DPAD_UP; - case SDL_GAMEPAD_BUTTON_DPAD_DOWN: return SkaInputKey_GAMEPAD_DPAD_DOWN; - case SDL_GAMEPAD_BUTTON_DPAD_LEFT: return SkaInputKey_GAMEPAD_DPAD_LEFT; - case SDL_GAMEPAD_BUTTON_DPAD_RIGHT: return SkaInputKey_GAMEPAD_DPAD_RIGHT; - default: return SkaInputKey_INVALID; - } -} - -SkaInputKey ska_sdl_gamepad_axis_to_input_key(SDL_GamepadAxis axis) { - switch (axis) { - case SDL_GAMEPAD_AXIS_LEFTX: return SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_X; - case SDL_GAMEPAD_AXIS_LEFTY: return SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_Y; - case SDL_GAMEPAD_AXIS_RIGHTX: return SkaInputKey_GAMEPAD_RIGHT_ANALOG_2D_AXIS_X; - case SDL_GAMEPAD_AXIS_RIGHTY: return SkaInputKey_GAMEPAD_RIGHT_ANALOG_2D_AXIS_Y; - case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: return SkaInputKey_GAMEPAD_LEFT_TRIGGER; - case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: return SkaInputKey_GAMEPAD_RIGHT_TRIGGER; - default: return SkaInputKey_INVALID; - } -} - -bool ska_sdl_load_gamepad_mappings() { - const int loadResult = SDL_AddGamepadMapping(SKA_GAMEPAD_DB_STR); - return loadResult >= 0; -} - -static inline void ska_sdl_notify_input_event(const SkaSDLInputEvent* inputEvent) { - ska_input_register_input_event(inputEvent->sourceType, inputEvent->key, inputEvent->triggerType, inputEvent->deviceIndex, inputEvent->axisMotionValue); -} - -void ska_sdl_process_event(SDL_Event event) { - SkaSDLInputEvent inputEvent = { - .sourceType = SkaInputSourceType_INVALID, - .triggerType = SkaInputTriggerType_INVALID, - .deviceIndex = SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, - .key = SkaInputKey_INVALID, - .axisMotionValue = 0.0f - }; - - switch (event.type) { - // Mouse - case SDL_EVENT_MOUSE_MOTION: { - SkaMouse* mouse = ska_input_get_mouse(); - mouse->position = (SkaVector2){ .x = (f32)event.motion.x, .y = (f32)event.motion.y }; - break; - } - - case SDL_EVENT_MOUSE_BUTTON_DOWN: - case SDL_EVENT_MOUSE_BUTTON_UP: { - inputEvent.sourceType = SkaInputSourceType_MOUSE; - inputEvent.triggerType = event.type == SDL_EVENT_MOUSE_BUTTON_DOWN ? SkaInputTriggerType_PRESSED : SkaInputTriggerType_RELEASED; - inputEvent.key = ska_sdl_mouse_button_to_input_key(event.button); - break; - } - // Keyboard - case SDL_EVENT_KEY_DOWN: - case SDL_EVENT_KEY_UP: { - inputEvent.sourceType = SkaInputSourceType_KEYBOARD; - inputEvent.triggerType = event.type == SDL_EVENT_KEY_DOWN ? SkaInputTriggerType_PRESSED : SkaInputTriggerType_RELEASED, - inputEvent.key = ska_sdl_keycode_to_input_key(event.key.keysym.sym); - break; - } - // Gamepad - case SDL_EVENT_GAMEPAD_ADDED: { - const SDL_JoystickID deviceIndex = event.gdevice.which; - SDL_Gamepad* newGamepad = SDL_OpenGamepad(deviceIndex); - const int playerIndex = SDL_GetGamepadPlayerIndex(newGamepad); - const SkaSDLGamepadData newGamepadData = { .gamepad = newGamepad, .deviceIndex = playerIndex }; - gamepadData[deviceIndex] = newGamepadData; - gamepadDataByPlayerIndex[playerIndex] = newGamepadData; - activeGamepads++; - - inputEvent.sourceType = SkaInputSourceType_GAMEPAD; - inputEvent.triggerType = SkaInputTriggerType_DEVICE_ADDED; - inputEvent.deviceIndex = playerIndex; - break; - } - case SDL_EVENT_GAMEPAD_REMOVED: { - const SDL_JoystickID deviceIndex = event.gdevice.which; - SDL_Gamepad* removedGamepad = gamepadData[deviceIndex].gamepad; - const SkaInputDeviceIndex playerIndex = gamepadData[deviceIndex].deviceIndex; - SDL_CloseGamepad(removedGamepad); - const SkaSDLGamepadData defaultGamepadData = (SkaSDLGamepadData){ .gamepad = NULL, .deviceIndex = -1 }; - gamepadData[deviceIndex] = defaultGamepadData; - gamepadDataByPlayerIndex[playerIndex] = defaultGamepadData; - activeGamepads--; - - inputEvent.sourceType = SkaInputSourceType_GAMEPAD; - inputEvent.triggerType = SkaInputTriggerType_DEVICE_REMOVED; - inputEvent.deviceIndex = playerIndex; - break; - } - case SDL_EVENT_GAMEPAD_BUTTON_DOWN: - case SDL_EVENT_GAMEPAD_BUTTON_UP: { - const SDL_JoystickID deviceIndex = event.jbutton.which; - const SkaInputDeviceIndex playerIndex = gamepadData[deviceIndex].deviceIndex; - const bool isButtonPressed = event.jbutton.state == SDL_PRESSED; - const SDL_GamepadButton buttonValue = event.jbutton.button; - - inputEvent.sourceType = SkaInputSourceType_GAMEPAD; - inputEvent.triggerType = isButtonPressed ? SkaInputTriggerType_PRESSED : SkaInputTriggerType_RELEASED; - inputEvent.deviceIndex = playerIndex; - inputEvent.key = ska_sdl_gamepad_button_to_input_key(buttonValue); - break; - } - default: - break; - } - ska_sdl_notify_input_event(&inputEvent); -} - +SkaInputKey ska_sdl_keycode_to_input_key(SDL_GamepadButton keycode); +SkaInputKey ska_sdl_mouse_button_to_input_key(SDL_MouseButtonEvent button); +SkaInputKey ska_sdl_gamepad_button_to_input_key(SDL_GamepadButton button); +SkaInputKey ska_sdl_gamepad_axis_to_input_key(SDL_GamepadAxis axis); +bool ska_sdl_load_gamepad_mappings(); +void ska_sdl_notify_input_event(const SkaSDLInputEvent* inputEvent); +void ska_sdl_process_event(SDL_Event event); // Call after looping through all sdl input events for a frame -void ska_sdl_process_axis_events() { -#define SKA_SDL_GAMEPAD_AXIS_DEAD_ZONE 8000 -#define SKA_MAX_AXIS_VALUES 6 - - static const SDL_GamepadAxis AXIS_KEYS[SKA_MAX_AXIS_VALUES] = { - SDL_GAMEPAD_AXIS_LEFTX, SDL_GAMEPAD_AXIS_LEFTY, - SDL_GAMEPAD_AXIS_RIGHTX, SDL_GAMEPAD_AXIS_RIGHTY, - SDL_GAMEPAD_AXIS_LEFT_TRIGGER, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER - }; - static bool hasGamepadStoppedAxisMotion[SKA_INPUT_MAX_DEVICES][SKA_MAX_AXIS_VALUES] = { - {true, true, true, true, true, true}, - {true, true, true, true, true, true}, - {true, true, true, true, true, true}, - {true, true, true, true, true, true}, - {true, true, true, true, true, true}, - {true, true, true, true, true, true}, - {true, true, true, true, true, true}, - {true, true, true, true, true, true} - }; - - for (uint32 i = 0; i < activeGamepads; i++) { - SkaSDLGamepadData* currentGamepadData = &gamepadDataByPlayerIndex[i]; - for (SDL_GamepadAxis axis = 0; axis < SKA_MAX_AXIS_VALUES; axis++) { - const int16 axisValue = SDL_GetGamepadAxis(currentGamepadData->gamepad, axis); - const SkaInputTriggerType triggerType = - axisValue < SKA_SDL_GAMEPAD_AXIS_DEAD_ZONE && axisValue > -SKA_SDL_GAMEPAD_AXIS_DEAD_ZONE - ? SkaInputTriggerType_AXIS_STOPPED_MOTION : SkaInputTriggerType_AXIS_IN_MOTION; - // Skip sending event if axis motion is already stopped - bool *hasStoppedAxisMotion = &hasGamepadStoppedAxisMotion[i][axis]; - if (triggerType == SkaInputTriggerType_AXIS_STOPPED_MOTION) { - if (*hasStoppedAxisMotion) { - continue; - } else { - *hasStoppedAxisMotion = true; - } - } else { - *hasStoppedAxisMotion = false; - } - const f32 axisValueNormalized = ska_math_map_to_range((f32) axisValue, (f32) INT16_MIN, (f32) INT16_MAX,-1.0f, 1.0f); - const SkaSDLInputEvent inputEvent = { - .sourceType = SkaInputSourceType_GAMEPAD, - .triggerType = triggerType, - .deviceIndex = (SkaInputDeviceIndex)i, - .key = ska_sdl_gamepad_axis_to_input_key(axis), - .axisMotionValue = axisValueNormalized - }; - ska_sdl_notify_input_event(&inputEvent); - } - } +void ska_sdl_process_axis_events(); -#undef SKA_MAX_AXIS_VALUES -} +#endif // if SKA_INPUT diff --git a/seika/logger.c b/seika/logger.c index 6111a2d..5779866 100644 --- a/seika/logger.c +++ b/seika/logger.c @@ -105,7 +105,7 @@ void ska_logger_internal_queue_message(const char* fmt, ...) { queuedLogMessagesCount++; } // Freeing in case we looped around - SKA_MEM_FREE(queuedLogMessages[currentIndex]); + SKA_FREE(queuedLogMessages[currentIndex]); queuedLogMessages[currentIndex] = ska_strdup(str); } va_end(args); @@ -115,7 +115,7 @@ bool ska_logger_internal_print_queue() { if (queuedLogMessagesCount > 0) { for (usize i = 0; i < queuedLogMessagesCount; i++) { ska_logger_message(queuedLogMessages[i]); - SKA_MEM_FREE(queuedLogMessages[i]); + SKA_FREE(queuedLogMessages[i]); queuedLogMessages[i] = NULL; } queuedLogMessagesCount = 0; diff --git a/seika/logger.h b/seika/logger.h index 32c9abd..437e33e 100644 --- a/seika/logger.h +++ b/seika/logger.h @@ -4,7 +4,7 @@ extern "C" { #endif -#include +#include "seika/defines.h" #ifndef SKA_LOG_BUFFER_SIZE #define SKA_LOG_BUFFER_SIZE 512 diff --git a/seika/math/curve_float.h b/seika/math/curve_float.h index 16ed517..9c5c88a 100644 --- a/seika/math/curve_float.h +++ b/seika/math/curve_float.h @@ -4,9 +4,6 @@ extern "C" { #endif -#include -#include - #include "seika/defines.h" #define SKA_CURVE_MAX_CONTROL_POINTS 16 diff --git a/seika/memory.c b/seika/memory.c index e4e41ef..5592699 100644 --- a/seika/memory.c +++ b/seika/memory.c @@ -1,25 +1,136 @@ #include "seika/memory.h" #include "seika/assert.h" -void* ska_mem_allocate(usize size) { - void* memory = calloc(1, size); - SKA_ASSERT_FMT(memory, "Out of memory or allocate failed!, size = %d", size); +// Internal default allocator implementation + +typedef struct Allocation { + const void* ptr; + usize bytes; + struct Allocation* next; +} Allocation; + +static Allocation* allocationList = NULL; + +static void track_allocation(const void* memory, usize bytes) { + Allocation* newAlloc = (Allocation*)malloc(sizeof(Allocation)); + SKA_ASSERT(newAlloc); + newAlloc->ptr = memory; + newAlloc->bytes = bytes; + newAlloc->next = allocationList; + allocationList = newAlloc; +} + +static void untrack_allocation(const void* memory) { + Allocation* current = allocationList; + Allocation* prev = NULL; + while (current) { + if (current->ptr == memory) { + if (prev) { + prev->next = current->next; + } else { + allocationList = current->next; + } + free(current); + return; + } + prev = current; + current = current->next; + } +} + +static bool isAllocatorValid(const SkaMemAllocator* allocator) { + return allocator->allocate + && allocator->allocate_zeroed + && allocator->reallocate + && allocator->free + && allocator->report_leaks; +} + +static void* internal_mem_allocate(usize bytes) { + void* memory = malloc(bytes); + SKA_ASSERT_FMT(memory, "Out of memory or allocation failed!, size = %d", bytes); + track_allocation(memory, bytes); return memory; } -void* ska_mem_allocate_c(usize blocks, usize size) { - void* memory = calloc(blocks, size); - SKA_ASSERT_FMT(memory, "Out of memory or allocate_c failed!, size = %d", size); +static void* internal_mem_allocate_zeroed(usize bytes) { + void* memory = calloc(1, bytes); + SKA_ASSERT_FMT(memory, "Out of memory or allocation failed!, size = %d", bytes); + track_allocation(memory, bytes); return memory; } -void* ska_mem_reallocate(void* memory, usize size) { - void* reallocatedMemory = realloc(memory, size); - SKA_ASSERT_FMT(reallocatedMemory, "Out of memory or realloc failed!, size = %d", size); +static void* internal_mem_reallocate(void* memory, usize bytes) { + untrack_allocation(memory); + void* reallocatedMemory = realloc(memory, bytes); + SKA_ASSERT_FMT(reallocatedMemory, "Out of memory or realloc failed!, size = %d", bytes); + track_allocation(reallocatedMemory, bytes); return reallocatedMemory; } -void ska_mem_free(void* memory) { +static void internal_mem_free(void* memory) { + untrack_allocation(memory); free(memory); memory = NULL; } + +static bool internal_mem_report_leaks() { + // If there is an allocation list there is a memory leak + return allocationList != NULL; +} + +static const SkaMemAllocator defaultAlloc = { + .allocate = internal_mem_allocate, + .allocate_zeroed = internal_mem_allocate_zeroed, + .reallocate = internal_mem_reallocate, + .free = internal_mem_free, + .report_leaks = internal_mem_report_leaks +}; + +static SkaMemAllocator currentAlloc = { + .allocate = internal_mem_allocate, + .allocate_zeroed = internal_mem_allocate_zeroed, + .reallocate = internal_mem_reallocate, + .free = internal_mem_free, + .report_leaks = internal_mem_report_leaks +}; + + +void ska_set_current_allocator(const SkaMemAllocator allocator) { + SKA_ASSERT_FMT(isAllocatorValid(&allocator), "Must implement all allocator functions before setting"); + currentAlloc = allocator; +} + +const SkaMemAllocator* ska_mem_get_current_allocator() { + return ¤tAlloc; +} + +void ska_reset_to_default_allocator() { + currentAlloc = defaultAlloc; +} + +void* ska_mem_allocate(usize bytes) { + void* memory = currentAlloc.allocate(bytes); + SKA_ASSERT_FMT(memory, "Out of memory or allocation failed!, size = %d", bytes); + return memory; +} + +void* ska_mem_allocate_zeroed(usize bytes) { + void* memory = currentAlloc.allocate_zeroed(bytes); + SKA_ASSERT_FMT(memory, "Out of memory or allocation failed!, size = %d", bytes); + return memory; +} + +void* ska_mem_reallocate(void* memory, usize bytes) { + void* reallocatedMemory = currentAlloc.reallocate(memory, bytes); + SKA_ASSERT_FMT(reallocatedMemory, "Out of memory or realloc failed!, size = %d", bytes); + return reallocatedMemory; +} + +void ska_mem_free(void* memory) { + currentAlloc.free(memory); +} + +bool ska_mem_report_leaks() { + return currentAlloc.report_leaks(); +} diff --git a/seika/memory.h b/seika/memory.h index 677ac41..7c0773f 100644 --- a/seika/memory.h +++ b/seika/memory.h @@ -4,27 +4,43 @@ extern "C" { #endif -#include "defines.h" +#include "seika/defines.h" -#define SKA_MEM_ALLOCATE(DataType) \ +#define SKA_ALLOC(DataType) \ (DataType*) ska_mem_allocate(sizeof(DataType)) -#define SKA_MEM_ALLOCATE_ARRAY(DataType, ArraySize) \ -(DataType*) ska_mem_allocate_c(ArraySize, sizeof(DataType)) +#define SKA_ALLOC_ZEROED(DataType) \ +(DataType*) ska_mem_allocate_zeroed(sizeof(DataType)) -#define SKA_MEM_ALLOCATE_SIZE(Size) \ -ska_mem_allocate(Size) +#define SKA_ALLOC_BYTES(Bytes) \ +ska_mem_allocate(Bytes) -#define SKA_MEM_ALLOCATE_SIZE_ZERO(Blocks, Size) \ -ska_mem_allocate_c(Blocks, Size) +#define SKA_ALLOC_BYTES_ZEROED(Bytes) \ +ska_mem_allocate_zeroed(Bytes) -#define SKA_MEM_FREE(Memory) \ +#define SKA_FREE(Memory) \ ska_mem_free(Memory) -void* ska_mem_allocate(usize size); -void* ska_mem_allocate_c(usize blocks, usize size); -void* ska_mem_reallocate(void* memory, usize size); +typedef struct SkaMemAllocator { + void* (*allocate)(usize bytes); + void* (*allocate_zeroed)(usize bytes); + void* (*reallocate)(void* memory, usize bytes); + void (*free)(void* memory); + bool (*report_leaks)(void); +} SkaMemAllocator; + +void ska_mem_set_current_allocator(const SkaMemAllocator allocator); +const SkaMemAllocator* ska_mem_get_current_allocator(); +void ska_mem_reset_to_default_allocator(); + + +// Calls using the current allocator + +void* ska_mem_allocate(usize bytes); +void* ska_mem_allocate_zeroed(usize bytes); +void* ska_mem_reallocate(void* memory, usize bytes); void ska_mem_free(void* memory); +bool ska_mem_report_leaks(); #ifdef __cplusplus } diff --git a/seika/platform.h b/seika/platform.h index 24b0ac7..a63be05 100644 --- a/seika/platform.h +++ b/seika/platform.h @@ -4,7 +4,7 @@ extern "C" { #endif -#include "stdbool.h" +#include "seika/defines.h" #if defined(_WIN32) || defined(_WIN64) // Windows #define SKA_TRIGGER_BREAKPOINT __debugbreak() diff --git a/seika/profile_code.h b/seika/profile_code.h deleted file mode 100644 index dded8e2..0000000 --- a/seika/profile_code.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include -#include - -#include "seika/defines.h" - -// Experimental file that isn't in use... - -#define SKA_PROFILE_CODE(CodeBlock) \ -do { \ -clock_t start_time, end_time; \ -f32 cpu_time_used; \ -start_time = clock(); \ -CodeBlock \ -end_time = clock(); \ -cpu_time_used = ((f32)(end_time - start_time)) / CLOCKS_PER_SEC; \ -printf("Time taken: %f seconds\n", cpu_time_used); \ -} while (0) - -/* - * // Example - * SKA_PROFILE_CODE( - * for (int i = 0; i < 1000000; i++) {} - * ); - */ - -#define SKA_PROFILE_CODE_WITH_VAR(CpuTimeVar, CodeBlock) \ -do { \ -clock_t start_time, end_time; \ -start_time = clock(); \ -CodeBlock \ -end_time = clock(); \ -(CpuTimeVar) = ((f32)(end_time - start_time)) / CLOCKS_PER_SEC; \ -} while (0) - -/* - * // Example: - * f32 cpu_time_taken; - * SKA_PROFILE_CODE_WITH_VAR( - * cpu_time_taken, - * for (int i = 0; i < 1000000; i++) {} - * ); - * printf("Time taken: %f seconds\n", cpu_time_taken); - */ - - -typedef struct SkaBenchmarkItem { - f32 startTime; - f32 endTime; - f32 elapsedTime; - bool isRunning; -} SkaBenchmarkItem; - -void se_benchmark_start(SkaBenchmarkItem* benchmarkItem) { - benchmarkItem->startTime = (f32)clock() / CLOCKS_PER_SEC; - benchmarkItem->endTime = 0.0f; - benchmarkItem->elapsedTime = 0.0f; - benchmarkItem->isRunning = true; -} - -f32 se_benchmark_stop(SkaBenchmarkItem* benchmarkItem) { - benchmarkItem->endTime = (f32)clock() / CLOCKS_PER_SEC; - benchmarkItem->elapsedTime = benchmarkItem->endTime - benchmarkItem->startTime; - return benchmarkItem->elapsedTime; -} - -/* -// USAGE EXAMPLE -SkaBenchmarkItem benchmarkItem; -se_benchmark_start(&benchmarkItem); -// DO STUFF ... -se_logger_debug("elapsedTime = %f", se_benchmark_stop(&benchmarkItem)); -*/ diff --git a/seika/rendering/font.c b/seika/rendering/font.c index bc95e04..66c1008 100644 --- a/seika/rendering/font.c +++ b/seika/rendering/font.c @@ -1,5 +1,7 @@ #include "font.h" +#if SKA_RENDERING + #include #include FT_FREETYPE_H @@ -13,7 +15,7 @@ static void ska_initialize_font(FT_Face face, SkaFont* font, bool applyNearestNe SkaFont* ska_font_create_font(const char* fileName, int32 size, bool applyNearestNeighbor) { FT_Face face; - SkaFont* font = SKA_MEM_ALLOCATE(SkaFont); + SkaFont* font = SKA_ALLOC(SkaFont); font->size = size; // Failed to create font, exit out early @@ -31,7 +33,7 @@ SkaFont* ska_font_create_font(const char* fileName, int32 size, bool applyNeares SkaFont* ska_font_create_font_from_memory(const void* buffer, usize bufferSize, int32 size, bool applyNearestNeighbor) { FT_Face face; - SkaFont* font = SKA_MEM_ALLOCATE(SkaFont); + SkaFont* font = SKA_ALLOC(SkaFont); font->size = size; // Failed to create font, exit out early @@ -48,7 +50,7 @@ SkaFont* ska_font_create_font_from_memory(const void* buffer, usize bufferSize, } void ska_font_delete(SkaFont* font) { - SKA_MEM_FREE(font); + SKA_FREE(font); } bool ska_generate_new_font_face(const char* fileName, FT_Face* face) { @@ -130,3 +132,5 @@ static void ska_initialize_font(FT_Face face, SkaFont* font, bool applyNearestNe FT_Done_Face(face); } + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/font.h b/seika/rendering/font.h index 05cf742..cf41c1b 100644 --- a/seika/rendering/font.h +++ b/seika/rendering/font.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + #include #include @@ -24,3 +26,5 @@ typedef struct SkaFont { SkaFont* ska_font_create_font(const char* fileName, int32 size, bool applyNearestNeighbor); SkaFont* ska_font_create_font_from_memory(const void* buffer, usize bufferSize, int32 size, bool applyNearestNeighbor); void ska_font_delete(SkaFont* font); + +#endif // #if SKA_RENDERING \ No newline at end of file diff --git a/seika/rendering/frame_buffer.c b/seika/rendering/frame_buffer.c index 7c3866c..7058277 100644 --- a/seika/rendering/frame_buffer.c +++ b/seika/rendering/frame_buffer.c @@ -1,3 +1,5 @@ +#if SKA_RENDERING + #include "frame_buffer.h" #include "shader/shader.h" @@ -179,3 +181,5 @@ void ska_frame_buffer_set_screen_shader(struct SkaShaderInstance *shaderInstance void ska_frame_buffer_reset_to_default_screen_shader() { currentScreenShader = &defaultScreenShader; } + +#endif // #if SKA_RENDERING \ No newline at end of file diff --git a/seika/rendering/frame_buffer.h b/seika/rendering/frame_buffer.h index e4dde6b..0f6fd34 100644 --- a/seika/rendering/frame_buffer.h +++ b/seika/rendering/frame_buffer.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + #ifdef __cplusplus extern "C" { #endif @@ -32,3 +34,5 @@ SkaFrameBufferViewportData* ska_frame_buffer_get_cached_viewport_data(); #ifdef __cplusplus } #endif + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/render_context.c b/seika/rendering/render_context.c index f329c0c..3d63bd6 100644 --- a/seika/rendering/render_context.c +++ b/seika/rendering/render_context.c @@ -1,3 +1,5 @@ +#if SKA_RENDERING + #include "render_context.h" #include @@ -9,15 +11,17 @@ static SkaRenderContext* renderContext = NULL; void ska_render_context_initialize() { SKA_ASSERT_FMT(renderContext == NULL, "Render context is already initialized!"); - renderContext = SKA_MEM_ALLOCATE(SkaRenderContext); + renderContext = SKA_ALLOC(SkaRenderContext); } void ska_render_context_finalize() { SKA_ASSERT_FMT(renderContext != NULL, "Render context is not initialized!"); - SKA_MEM_FREE(renderContext); + SKA_FREE(renderContext); } SkaRenderContext* ska_render_context_get() { SKA_ASSERT_FMT(renderContext != NULL, "Render context is not initialized!"); return renderContext; } + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/render_context.h b/seika/rendering/render_context.h index d34eaea..4864306 100644 --- a/seika/rendering/render_context.h +++ b/seika/rendering/render_context.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + #include #include FT_FREETYPE_H @@ -14,3 +16,5 @@ typedef struct SkaRenderContext { void ska_render_context_initialize(); void ska_render_context_finalize(); SkaRenderContext* ska_render_context_get(); + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/renderer.c b/seika/rendering/renderer.c index 6fd1d7e..79fdea2 100644 --- a/seika/rendering/renderer.c +++ b/seika/rendering/renderer.c @@ -1,3 +1,5 @@ +#if SKA_RENDERING + #include "renderer.h" #include @@ -608,3 +610,5 @@ void renderer_print_opengl_errors() { void ska_renderer_set_global_shader_param_time(f32 timeValue) { globalShaderParamTime = timeValue; } + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/renderer.h b/seika/rendering/renderer.h index 86c6df0..b0a6120 100644 --- a/seika/rendering/renderer.h +++ b/seika/rendering/renderer.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + #ifdef __cplusplus extern "C" { #endif @@ -33,3 +35,5 @@ void ska_renderer_set_global_shader_param_time(f32 timeValue); #ifdef __cplusplus } #endif + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader.c b/seika/rendering/shader/shader.c index 0bffc55..897d274 100644 --- a/seika/rendering/shader/shader.c +++ b/seika/rendering/shader/shader.c @@ -1,3 +1,5 @@ +#if SKA_RENDERING + #include "shader.h" #include "seika/logger.h" @@ -6,7 +8,7 @@ static bool shader_check_compile_errors(uint32 shaderId, const char* type); SkaShader* ska_shader_compile_new_shader(const char* vertexSource, const char* fragmentSource) { - SkaShader* shader = SKA_MEM_ALLOCATE(SkaShader); + SkaShader* shader = SKA_ALLOC(SkaShader); GLuint vertex, fragment; // vertex vertex = glCreateShader(GL_VERTEX_SHADER); @@ -34,7 +36,7 @@ SkaShader* ska_shader_compile_new_shader(const char* vertexSource, const char* f } void ska_shader_destroy(SkaShader* shader) { - SKA_MEM_FREE(shader); + SKA_FREE(shader); } bool shader_check_compile_errors(uint32 shaderId, const char* type) { @@ -87,3 +89,5 @@ void ska_shader_set_vec4_float(SkaShader* shader, const char* name, f32 v1, f32 void ska_shader_set_mat4_float(SkaShader* shader, const char* name, mat4* value) { glUniformMatrix4fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, (f32*)value); } + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader.h b/seika/rendering/shader/shader.h index 15305e6..547cf30 100644 --- a/seika/rendering/shader/shader.h +++ b/seika/rendering/shader/shader.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + #include #include @@ -24,3 +26,5 @@ void ska_shader_set_vec2_float(SkaShader* shader, const char* name, f32 v1, f32 void ska_shader_set_vec3_float(SkaShader* shader, const char* name, f32 v1, f32 v2, f32 v3); void ska_shader_set_vec4_float(SkaShader* shader, const char* name, f32 v1, f32 v2, f32 v3, f32 v4); void ska_shader_set_mat4_float(SkaShader* shader, const char* name, mat4* value); + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader_cache.c b/seika/rendering/shader/shader_cache.c index 7b95ff4..fea201a 100644 --- a/seika/rendering/shader/shader_cache.c +++ b/seika/rendering/shader/shader_cache.c @@ -1,3 +1,5 @@ +#if SKA_RENDERING + #include "shader_cache.h" #include @@ -6,7 +8,7 @@ #include "seika/memory.h" #include "seika/assert.h" #include "seika/asset/asset_file_loader.h" -#include "seika/data_structures/queue.h" +#include "seika/data_structures/id_queue.h" #include "seika/logger.h" // --- Parsed Shader Cache --- // @@ -18,14 +20,14 @@ SkaStringHashMap* parsedShaderCacheMap = NULL; // --- Shader Cache --- // static SkaShaderInstance* instanceCache[SKA_SHADER_INSTANCE_MAX_INSTANCES]; -static SkaQueue* shaderInstanceIdQueue = NULL; +static SkaIdQueue* shaderInstanceIdQueue = NULL; void ska_shader_cache_initialize() { SKA_ASSERT(shaderInstanceIdQueue == NULL); SKA_ASSERT(parsedShaderCacheMap == NULL); - shaderInstanceIdQueue = ska_queue_create(SKA_SHADER_INSTANCE_MAX_INSTANCES, SKA_SHADER_INSTANCE_INVALID_ID); + shaderInstanceIdQueue = ska_id_queue_create(SKA_SHADER_INSTANCE_MAX_INSTANCES); for (uint32_t i = 0; i < SKA_SHADER_INSTANCE_MAX_INSTANCES; i++) { - ska_queue_enqueue(shaderInstanceIdQueue, i); + ska_id_queue_enqueue(shaderInstanceIdQueue, i); instanceCache[i] = NULL; } parsedShaderCacheMap = ska_string_hash_map_create_default_capacity(); @@ -34,7 +36,7 @@ void ska_shader_cache_initialize() { void ska_shader_cache_finalize() { SKA_ASSERT(shaderInstanceIdQueue != NULL); SKA_ASSERT(parsedShaderCacheMap != NULL); - ska_queue_destroy(shaderInstanceIdQueue); + ska_id_queue_destroy(shaderInstanceIdQueue); shaderInstanceIdQueue = NULL; SKA_STRING_HASH_MAP_FOR_EACH(parsedShaderCacheMap, iter) { SkaStringHashMapNode* node = iter.pair; @@ -46,14 +48,16 @@ void ska_shader_cache_finalize() { } SkaShaderInstanceId ska_shader_cache_add_instance(SkaShaderInstance* instance) { - const SkaShaderInstanceId newId = ska_queue_dequeue(shaderInstanceIdQueue); + SkaShaderInstanceId newId; + const bool succes = ska_id_queue_dequeue(shaderInstanceIdQueue, &newId); + SKA_ASSERT(succes); instanceCache[newId] = instance; return newId; } void ska_shader_cache_remove_instance(SkaShaderInstanceId instanceId) { instanceCache[instanceId] = NULL; - ska_queue_enqueue(shaderInstanceIdQueue, instanceId); + ska_id_queue_enqueue(shaderInstanceIdQueue, instanceId); } SkaShaderInstance* ska_shader_cache_get_instance(SkaShaderInstanceId instanceId) { @@ -105,8 +109,8 @@ SkaShaderInstanceId ska_shader_cache_create_instance_and_add_from_raw(const char char* vertexSource = ska_asset_file_loader_read_file_contents_as_string(vertexPath, NULL); char* fragmentSource = ska_asset_file_loader_read_file_contents_as_string(fragmentPath, NULL); const SkaShaderInstanceId newId = ska_shader_cache_create_instance_and_add_from_source(vertexSource, fragmentSource); - SKA_MEM_FREE(vertexSource); - SKA_MEM_FREE(fragmentSource); + SKA_FREE(vertexSource); + SKA_FREE(fragmentSource); return newId; } @@ -115,3 +119,5 @@ SkaShaderInstanceId ska_shader_cache_create_instance_and_add_from_source(const c const SkaShaderInstanceId newId = ska_shader_cache_add_instance(instance); return newId; } + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader_cache.h b/seika/rendering/shader/shader_cache.h index 22e023c..459a7f3 100644 --- a/seika/rendering/shader/shader_cache.h +++ b/seika/rendering/shader/shader_cache.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + #include "shader_instance_minimal.h" #include "shader_instance.h" @@ -17,3 +19,5 @@ SkaShaderInstanceId ska_shader_cache_create_instance_and_add(const char* shaderP // Should be a modification to the base shaders found in 'shader_source.h' SkaShaderInstanceId ska_shader_cache_create_instance_and_add_from_raw(const char* vertexPath, const char* fragmentPath); SkaShaderInstanceId ska_shader_cache_create_instance_and_add_from_source(const char* vertexSource, const char* fragmentSource); + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader_file_parser.c b/seika/rendering/shader/shader_file_parser.c index 679560b..65581a5 100644 --- a/seika/rendering/shader/shader_file_parser.c +++ b/seika/rendering/shader/shader_file_parser.c @@ -1,3 +1,5 @@ +#if SKA_RENDERING + #include "shader_file_parser.h" #include @@ -8,12 +10,12 @@ #define SHADER_FILE_PARSER_ERROR_RETURN(RESULT, SOURCE, MESSAGE) \ ska_strcpy((RESULT).errorMessage, (MESSAGE)); \ -SKA_MEM_FREE((SOURCE)); \ +SKA_FREE((SOURCE)); \ return (RESULT); #define SHADER_FILE_PARSER_ERROR_FMT_RETURN(RESULT, SOURCE, FMT, ...) \ sprintf((RESULT).errorMessage, (FMT), ##__VA_ARGS__); \ -SKA_MEM_FREE((SOURCE)); \ +SKA_FREE((SOURCE)); \ return (RESULT); static char* shader_file_parse_data_get_full_uniforms_source(SkaShaderFileParseData* parseData) { @@ -72,11 +74,11 @@ char* shader_file_parse_data_get_full_functions_source(SkaShaderFileParseData* p } void shader_file_parse_data_delete_internal_memory(SkaShaderFileParseData* parseData) { - SKA_MEM_FREE(parseData->fullVertexSource); - SKA_MEM_FREE(parseData->fullFragmentSource); + SKA_FREE(parseData->fullVertexSource); + SKA_FREE(parseData->fullFragmentSource); for (usize i = 0; i < parseData->functionCount; i++) { - SKA_MEM_FREE(parseData->functions[i].name); - SKA_MEM_FREE(parseData->functions[i].fullFunctionSource); + SKA_FREE(parseData->functions[i].name); + SKA_FREE(parseData->functions[i].fullFunctionSource); } } @@ -462,12 +464,12 @@ SkaShaderFileParseResult ska_shader_file_parser_parse_shader(const char* shaderS // Check for vertex and fragment shader functions if (strcmp(parsedFunction.name, "vertex") == 0) { result.parseData.vertexFunctionSource = shader_file_parse_function_body(parsedFunction.fullFunctionSource); - SKA_MEM_FREE(parsedFunction.name); - SKA_MEM_FREE(parsedFunction.fullFunctionSource); + SKA_FREE(parsedFunction.name); + SKA_FREE(parsedFunction.fullFunctionSource); } else if (strcmp(parsedFunction.name, "fragment") == 0) { result.parseData.fragmentFunctionSource = shader_file_parse_function_body(parsedFunction.fullFunctionSource); - SKA_MEM_FREE(parsedFunction.name); - SKA_MEM_FREE(parsedFunction.fullFunctionSource); + SKA_FREE(parsedFunction.name); + SKA_FREE(parsedFunction.fullFunctionSource); } else { // Add non vertex and fragment functions to our array result.parseData.functions[result.parseData.functionCount++] = parsedFunction; @@ -504,7 +506,7 @@ SkaShaderFileParseResult ska_shader_file_parser_parse_shader(const char* shaderS foundUniformsToken + SHADER_UNIFORMS_REPLACE_TOKEN_LENGTH, strlen(foundUniformsToken + SHADER_UNIFORMS_REPLACE_TOKEN_LENGTH) + 1); memcpy(foundUniformsToken, uniformsSource, uniformsReplaceLength); - SKA_MEM_FREE(uniformsSource); + SKA_FREE(uniformsSource); } // Vertex functions char* foundFunctionsToken = strstr(fullShaderBuffer, SHADER_FUNCTIONS_REPLACE_TOKEN); @@ -518,7 +520,7 @@ SkaShaderFileParseResult ska_shader_file_parser_parse_shader(const char* shaderS foundFunctionsToken + SHADER_FUNCTIONS_REPLACE_TOKEN_LENGTH, strlen(foundFunctionsToken + SHADER_FUNCTIONS_REPLACE_TOKEN_LENGTH) + 1); memcpy(foundFunctionsToken, functionsSource, functionsReplaceLength); - SKA_MEM_FREE(functionsSource); + SKA_FREE(functionsSource); } // Vertex body char* foundVertexToken = strstr(fullShaderBuffer, SHADER_VERTEX_BODY_REPLACE_TOKEN); @@ -549,7 +551,7 @@ SkaShaderFileParseResult ska_shader_file_parser_parse_shader(const char* shaderS foundUniformsToken + SHADER_UNIFORMS_REPLACE_TOKEN_LENGTH, strlen(foundUniformsToken + SHADER_UNIFORMS_REPLACE_TOKEN_LENGTH) + 1); memcpy(foundUniformsToken, uniformsSource, uniformsReplaceLength); - SKA_MEM_FREE(uniformsSource); + SKA_FREE(uniformsSource); } // Fragment functions char* foundFunctionsToken = strstr(fullShaderBuffer, SHADER_FUNCTIONS_REPLACE_TOKEN); @@ -563,7 +565,7 @@ SkaShaderFileParseResult ska_shader_file_parser_parse_shader(const char* shaderS foundFunctionsToken + SHADER_FUNCTIONS_REPLACE_TOKEN_LENGTH, strlen(foundFunctionsToken + SHADER_FUNCTIONS_REPLACE_TOKEN_LENGTH) + 1); memcpy(foundFunctionsToken, functionsSource, functionsReplaceLength); - SKA_MEM_FREE(functionsSource); + SKA_FREE(functionsSource); } // Fragment body char* foundFragmentToken = strstr(fullShaderBuffer, SHADER_FRAGMENT_BODY_REPLACE_TOKEN); @@ -579,29 +581,31 @@ SkaShaderFileParseResult ska_shader_file_parser_parse_shader(const char* shaderS // printf("FULL FRAGMENT SOURCE = \n%s\n", fullShaderBuffer); result.parseData.fullFragmentSource = ska_strdup(fullShaderBuffer); - SKA_MEM_FREE(originalSource); + SKA_FREE(originalSource); return result; } void ska_shader_file_parse_clear_parse_result(SkaShaderFileParseResult* result) { if (result->parseData.fragmentFunctionSource) { - SKA_MEM_FREE(result->parseData.fragmentFunctionSource); + SKA_FREE(result->parseData.fragmentFunctionSource); } if (result->parseData.vertexFunctionSource) { - SKA_MEM_FREE(result->parseData.vertexFunctionSource); + SKA_FREE(result->parseData.vertexFunctionSource); } if (result->parseData.fullVertexSource) { - SKA_MEM_FREE(result->parseData.fullVertexSource); + SKA_FREE(result->parseData.fullVertexSource); } if (result->parseData.fullFragmentSource) { - SKA_MEM_FREE(result->parseData.fullFragmentSource); + SKA_FREE(result->parseData.fullFragmentSource); } for (usize i = 0; i < result->parseData.uniformCount; i++) { - SKA_MEM_FREE(result->parseData.uniforms[i].name); + SKA_FREE(result->parseData.uniforms[i].name); } for (usize i = 0; i < result->parseData.functionCount; i++) { - SKA_MEM_FREE(result->parseData.functions[i].name); - SKA_MEM_FREE(result->parseData.functions[i].fullFunctionSource); + SKA_FREE(result->parseData.functions[i].name); + SKA_FREE(result->parseData.functions[i].fullFunctionSource); } } + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader_file_parser.h b/seika/rendering/shader/shader_file_parser.h index 15cbf7f..b2e3718 100644 --- a/seika/rendering/shader/shader_file_parser.h +++ b/seika/rendering/shader/shader_file_parser.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + #include "shader_instance.h" typedef struct SkaShaderFileParserFunction { @@ -26,3 +28,5 @@ typedef struct SkaShaderFileParseResult { SkaShaderFileParseResult ska_shader_file_parser_parse_shader(const char* shaderSource); void ska_shader_file_parse_clear_parse_result(SkaShaderFileParseResult* result); + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader_instance.c b/seika/rendering/shader/shader_instance.c index 3fefd90..9d44a98 100644 --- a/seika/rendering/shader/shader_instance.c +++ b/seika/rendering/shader/shader_instance.c @@ -1,3 +1,5 @@ +#if SKA_RENDERING + #include "shader_instance.h" #include @@ -14,7 +16,7 @@ SkaShaderInstance* ska_shader_instance_create(const char* vertexSource, const ch if (shader == NULL) { return NULL; } - SkaShaderInstance* instance = SKA_MEM_ALLOCATE(SkaShaderInstance); + SkaShaderInstance* instance = SKA_ALLOC(SkaShaderInstance); instance->shader = shader; instance->paramMap = ska_string_hash_map_create_default_capacity(); instance->paramsDirty = true; @@ -23,7 +25,7 @@ SkaShaderInstance* ska_shader_instance_create(const char* vertexSource, const ch SkaShaderInstance* ska_shader_instance_create_from_shader(SkaShader* shader) { SKA_ASSERT(shader != NULL); - SkaShaderInstance* instance = SKA_MEM_ALLOCATE(SkaShaderInstance); + SkaShaderInstance* instance = SKA_ALLOC(SkaShaderInstance); instance->shader = shader; instance->paramMap = ska_string_hash_map_create_default_capacity(); instance->paramsDirty = true; @@ -34,11 +36,11 @@ void ska_shader_instance_destroy(SkaShaderInstance* shaderInstance) { SKA_STRING_HASH_MAP_FOR_EACH(shaderInstance->paramMap, iter) { SkaStringHashMapNode* node = iter.pair; SkaShaderParam* param = (SkaShaderParam*)node->value; - SKA_MEM_FREE(param->name); + SKA_FREE(param->name); } ska_string_hash_map_destroy(shaderInstance->paramMap); ska_shader_destroy(shaderInstance->shader); - SKA_MEM_FREE(shaderInstance); + SKA_FREE(shaderInstance); } // Creation functions @@ -195,3 +197,5 @@ SkaVector4 ska_shader_instance_param_get_float4(SkaShaderInstance* shaderInstanc SKA_ASSERT(param->type == SkaShaderParamType_FLOAT4); return param->value.float4Value; } + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader_instance.h b/seika/rendering/shader/shader_instance.h index f0e023d..6ed2da8 100644 --- a/seika/rendering/shader/shader_instance.h +++ b/seika/rendering/shader/shader_instance.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + /* * Shader Instance * --------------------------------------------------------------------------------------------------------------------- @@ -70,3 +72,5 @@ f32 ska_shader_instance_param_get_float(SkaShaderInstance* shaderInstance, const SkaVector2 ska_shader_instance_param_get_float2(SkaShaderInstance* shaderInstance, const char* name); SkaVector3 ska_shader_instance_param_get_float3(SkaShaderInstance* shaderInstance, const char* name); SkaVector4 ska_shader_instance_param_get_float4(SkaShaderInstance* shaderInstance, const char* name); + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader_instance_minimal.h b/seika/rendering/shader/shader_instance_minimal.h index 6b426cd..a2c6cec 100644 --- a/seika/rendering/shader/shader_instance_minimal.h +++ b/seika/rendering/shader/shader_instance_minimal.h @@ -1,8 +1,12 @@ #pragma once +#if SKA_RENDERING + #include "seika/defines.h" #define SKA_SHADER_INSTANCE_MAX_INSTANCES 100 #define SKA_SHADER_INSTANCE_INVALID_ID (SKA_SHADER_INSTANCE_MAX_INSTANCES + 1) typedef uint32 SkaShaderInstanceId; + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/shader/shader_source.h b/seika/rendering/shader/shader_source.h index 9c9c8e0..545aeab 100644 --- a/seika/rendering/shader/shader_source.h +++ b/seika/rendering/shader/shader_source.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + static const char* SKA_OPENGL_SHADER_SOURCE_VERTEX_SPRITE = "#version 330 core\n" "\n" @@ -127,3 +129,5 @@ static const char* SKA_OPENGL_SHADER_SOURCE_FRAGMENT_SCREEN = " COLOR = texture(TEXTURE, UV);\n" " //@@fragment()\n" "}\n"; + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/texture.c b/seika/rendering/texture.c index 0e6d865..b57a275 100644 --- a/seika/rendering/texture.c +++ b/seika/rendering/texture.c @@ -1,3 +1,5 @@ +#if SKA_RENDERING + #include "texture.h" #include @@ -29,7 +31,7 @@ static inline bool ska_texture_is_texture_valid(const SkaTexture* texture) { } static inline SkaTexture* ska_texture_create_default_texture() { - SkaTexture* texture = SKA_MEM_ALLOCATE(SkaTexture); + SkaTexture* texture = SKA_ALLOC(SkaTexture); memcpy(texture, &DEFAULT_TEXTURE_REF, sizeof(SkaTexture)); return texture; } @@ -50,7 +52,7 @@ SkaTexture* ska_texture_create_texture2(const char* filePath, GLint wrapS, GLint SkaAssetFileImageData* fileImageData = ska_asset_file_loader_load_image_data(filePath); SKA_ASSERT_FMT(fileImageData != NULL, "Failed to load texture image at file path '%s'", filePath); const usize imageDataSize = strlen((char*) fileImageData->data); - texture->data = (unsigned char*) SKA_MEM_ALLOCATE_SIZE(imageDataSize); + texture->data = (unsigned char*) SKA_ALLOC_BYTES(imageDataSize); // memcpy(texture->data, fileImageData->data, imageDataSize); texture->data = fileImageData->data; // TODO: Fix texture->width = fileImageData->width; @@ -74,7 +76,7 @@ SkaTexture* ska_texture_create_texture_from_memory2(const void* buffer, usize bu texture->wrapS = wrapS; texture->wrapT = wrapT; texture->applyNearestNeighbor = applyNearestNeighbor; - texture->data = (unsigned char*) SKA_MEM_ALLOCATE_SIZE(bufferSize); + texture->data = (unsigned char*) SKA_ALLOC_BYTES(bufferSize); unsigned char* imageData = stbi_load_from_memory((unsigned char*)buffer, (int32)bufferSize, &texture->width, &texture->height, &texture->nrChannels, 0); SKA_ASSERT(imageData); // memcpy(texture->data, imageData, bufferSize); @@ -94,7 +96,7 @@ SkaTexture* ska_texture_create_solid_colored_texture(GLsizei width, GLsizei heig texture->height = height; const GLsizei dataSize = width * height * 4; - texture->data = (unsigned char*)SKA_MEM_ALLOCATE_SIZE(dataSize); + texture->data = (unsigned char*)SKA_ALLOC_BYTES(dataSize); for (GLsizei i = 0; i < dataSize; i++) { texture->data[i] = colorValue; } @@ -130,8 +132,8 @@ void ska_texture_generate(SkaTexture* texture) { } void ska_texture_delete(SkaTexture* texture) { - SKA_MEM_FREE(texture->fileName); - SKA_MEM_FREE(texture); + SKA_FREE(texture->fileName); + SKA_FREE(texture); } GLint ska_texture_wrap_string_to_int(const char* wrap) { @@ -150,3 +152,5 @@ const char* ska_texture_get_wrap_s_string(const SkaTexture* texture) { const char* ska_texture_get_wrap_t_string(const SkaTexture* texture) { return texture->wrapT == GL_REPEAT ? "repeat" : "clamp_to_border"; } + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/texture.h b/seika/rendering/texture.h index f21b428..f05a2e3 100644 --- a/seika/rendering/texture.h +++ b/seika/rendering/texture.h @@ -1,5 +1,7 @@ #pragma once +#if SKA_RENDERING + #ifdef __cplusplus extern "C" { #endif @@ -40,3 +42,5 @@ const char* ska_texture_get_wrap_t_string(const SkaTexture* texture); #ifdef __cplusplus } #endif + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/window.c b/seika/rendering/window.c new file mode 100644 index 0000000..f23dd2f --- /dev/null +++ b/seika/rendering/window.c @@ -0,0 +1,88 @@ +#if SKA_RENDERING + +#include "window.h" + +#include +#include + +#include "renderer.h" +#include "seika/assert.h" + +static SDL_Window* window = NULL; +static SDL_GLContext glContext; +static bool isWindowActive = false; + +bool ska_window_initialize(SkaWindowProperties props) { + SKA_ASSERT(isWindowActive == false); + + const bool isSDLInitialized = SDL_WasInit(0) != 0; + if (isSDLInitialized) { + if (SDL_InitSubSystem( SDL_INIT_VIDEO) != 0) { + return false; + } + } else { + if (SDL_Init( SDL_INIT_VIDEO) != 0) { + return false; + } + } + + // OpenGL attributes + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + + // Create window + const uint32 windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY; + window = SDL_CreateWindow( + props.title, + props.windowWidth, + props.windowHeight, + windowFlags + ); + if (!window) { + return false; + } + + // Create OpenGL Context + glContext = SDL_GL_CreateContext(window); + + // Initialize Glad + if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { + return false; + } + + // Initialize rendering + ska_renderer_initialize(props.windowWidth, props.windowHeight, props.resolutionWidth, props.resolutionHeight, props.maintainAspectRatio); + + isWindowActive = true; + return true; +} + +void ska_window_finalize() { + SKA_ASSERT(isWindowActive); + SDL_GL_DeleteContext(glContext); + SDL_DestroyWindow(window); + SDL_QuitSubSystem(SDL_INIT_VIDEO); + const bool subsystemsStillInitialized = SDL_WasInit(0) != 0; + if (!subsystemsStillInitialized) { + SDL_Quit(); + } + + window = NULL; +} + +void ska_window_render(const SkaColor* backgroundColor) { + SKA_ASSERT(isWindowActive); + ska_renderer_process_and_flush_batches(backgroundColor); + SDL_GL_SwapWindow(window); +} + +bool ska_window_set_vsync(bool enabled) { + return SDL_GL_SetSwapInterval((int)enabled) == 0; +} + +#endif // #if SKA_RENDERING diff --git a/seika/rendering/window.h b/seika/rendering/window.h new file mode 100644 index 0000000..5f24a94 --- /dev/null +++ b/seika/rendering/window.h @@ -0,0 +1,24 @@ +#pragma once + +#if SKA_RENDERING + +#include "seika/defines.h" + +struct SkaColor; + +typedef struct SkaWindowProperties { + const char* title; + int32 windowWidth; + int32 windowHeight; + int32 resolutionWidth; + int32 resolutionHeight; + bool maintainAspectRatio; +} SkaWindowProperties; + +bool ska_window_initialize(SkaWindowProperties props); +void ska_window_finalize(); +void ska_window_render(const struct SkaColor* backgroundColor); +bool ska_window_set_vsync(bool enabled); + +#endif // #if SKA_RENDERING + diff --git a/seika/seika.c b/seika/seika.c index f6b834d..064d844 100644 --- a/seika/seika.c +++ b/seika/seika.c @@ -1,250 +1 @@ #include "seika.h" - -#include - -#include -#include - -#include "flag_utils.h" -#include "logger.h" -#include "input/sdl_input.h" -#include "seika/assert.h" -#include "seika/rendering/renderer.h" -#include "seika/audio/audio_manager.h" -#include "seika/asset/asset_manager.h" - -#define SKA_AUDIO_SOURCE_DEFAULT_WAV_SAMPLE_RATE 44100 -#define SKA_WINDOW_DEFAULT_MAINTAIN_ASPECT_RATIO false - -typedef enum SkaSystemFlag { - SkaSystemFlag_NONE = 0, - SkaSystemFlag_CORE = 1 << 0, - SkaSystemFlag_WINDOW = 2 << 0, - SkaSystemFlag_INPUT = 3 << 0, - SkaSystemFlag_AUDIO = 4 << 0, - SkaSystemFlag_ALL = SkaSystemFlag_CORE | SkaSystemFlag_WINDOW | SkaSystemFlag_INPUT | SkaSystemFlag_AUDIO, -} SkaSystemFlag; - -typedef struct SkaState { - SkaSystemFlag runningSystems; - bool shutdownRequested; -} SkaState; - -static SkaState skaState = { .runningSystems = SkaSystemFlag_NONE, .shutdownRequested = false }; - -static SDL_Window* window = NULL; -static SDL_GLContext openGlContext = NULL; - -bool ska_init() { - if (SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)) { - return false; - } - - // Set random seed - srand((int)time(NULL)); - - if (SDL_Init(0) != 0) { - return false; - } - - SKA_ADD_FLAGS(skaState.runningSystems, SkaSystemFlag_CORE); - return true; -} - -void ska_shutdown() { - if (SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)) { - SDL_Quit(); - SKA_REMOVE_FLAGS(skaState.runningSystems, SkaSystemFlag_CORE); - } -} - -bool ska_init_all(const char* title, int32 windowWidth, int32 windowHeight, int32 resolutionWidth, int32 resolutionHeight) { - return ska_init_all2(title, windowWidth, windowHeight, resolutionWidth, resolutionHeight, SKA_AUDIO_SOURCE_DEFAULT_WAV_SAMPLE_RATE, SKA_WINDOW_DEFAULT_MAINTAIN_ASPECT_RATIO); -} - -bool ska_init_all2(const char* title, int32 windowWidth, int32 windowHeight, int32 resolutionWidth, int32 resolutionHeight, uint32 audioWavSampleRate, bool maintainAspectRatio) { - if (!ska_init()) { - return false; - } - - if (!ska_window_init2(title, windowWidth, windowHeight, resolutionWidth, resolutionHeight, maintainAspectRatio)) { - return false; - } - - if (!ska_input_init()) { - return false; - } - - if (!ska_audio_init2(audioWavSampleRate)) { - return false; - } - - ska_asset_manager_initialize(); - - return true; -} - - -void ska_shutdown_all() { - ska_window_shutdown(); - ska_input_shutdown(); - ska_audio_shutdown(); - ska_asset_manager_finalize(); - ska_shutdown(); -} - -void ska_update() { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)); - ska_input_new_frame(); - - SDL_Event event; - while (SDL_PollEvent(&event)) { - switch(event.type) { - case SDL_EVENT_QUIT: - skaState.shutdownRequested = true; - break; - case SDL_EVENT_WINDOW_RESIZED: { - const Sint32 windowWidth = event.window.data1; - const Sint32 windowHeight = event.window.data2; - ska_renderer_update_window_size(windowWidth, windowHeight); - break; - } - default: { - ska_sdl_process_event(event); - break; - } - } - } - ska_sdl_process_axis_events(); -} - -void ska_fixed_update(f32 deltaTime) { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)); - - static f32 globalTime = 0.0f; - globalTime += deltaTime; - ska_renderer_set_global_shader_param_time(globalTime); -} - -bool ska_is_running() { - return !skaState.shutdownRequested; -} - -uint32 ska_get_ticks() { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)); - return (uint32)SDL_GetTicks(); -} - -void ska_delay(uint32 timeToWait) { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)); - SDL_Delay(timeToWait); -} - -bool ska_set_vsync_enabled(bool enabled) { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)); - return SDL_GL_SetSwapInterval((int)enabled) == 0; -} - -bool ska_print_errors() { - return ska_logger_internal_print_queue(); -} - -bool ska_window_init(const char* title, int32 windowWidth, int32 windowHeight) { - return ska_window_init2(title, windowWidth, windowHeight, windowWidth, windowHeight, SKA_WINDOW_DEFAULT_MAINTAIN_ASPECT_RATIO); -} - -bool ska_window_init2(const char* title, int32 windowWidth, int32 windowHeight, int32 resolutionWidth, int32 resolutionHeight, bool maintainAspectRatio) { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)); - if (SKA_HAS_FLAG(SkaSystemFlag_WINDOW, skaState.runningSystems)) { - return false; - } - - if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) { - return false; - } - - // OpenGL attributes - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - - // Create window - const uint32 windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY; - window = SDL_CreateWindow( - title, - windowWidth, - windowHeight, - windowFlags - ); - if (!window) { - return false; - } - - // Create OpenGL Context - openGlContext = SDL_GL_CreateContext(window); - - // Initialize Glad - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { - return false; - } - - // Initialize rendering - ska_renderer_initialize(windowWidth, windowHeight, resolutionWidth, resolutionHeight, maintainAspectRatio); - - SKA_ADD_FLAGS(skaState.runningSystems, SkaSystemFlag_WINDOW); - return true; -} - -void ska_window_shutdown() { - if (SKA_HAS_FLAG(SkaSystemFlag_WINDOW, skaState.runningSystems)) { - SDL_GL_DeleteContext(openGlContext); - SDL_DestroyWindow(window); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - SKA_REMOVE_FLAGS(skaState.runningSystems, SkaSystemFlag_WINDOW); - } -} - -void ska_window_render(const SkaColor* windowBackgroundColor) { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_WINDOW, skaState.runningSystems)); - ska_renderer_process_and_flush_batches(windowBackgroundColor); - SDL_GL_SwapWindow(window); -} - -bool ska_input_init() { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)); - if (SDL_InitSubSystem( SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) != 0) { - return false; - } - - if (!ska_sdl_load_gamepad_mappings()) { - return false; - } - - return true; -} - -void ska_input_shutdown() { - if (SKA_HAS_FLAG(SkaSystemFlag_INPUT, skaState.runningSystems)) { - SKA_REMOVE_FLAGS(skaState.runningSystems, SkaSystemFlag_INPUT); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD); - } -} - -bool ska_audio_init() { - return ska_audio_init2(SKA_AUDIO_SOURCE_DEFAULT_WAV_SAMPLE_RATE); -} - -bool ska_audio_init2(uint32 audioWavSampleRate) { - SKA_ASSERT(SKA_HAS_FLAG(SkaSystemFlag_CORE, skaState.runningSystems)); - return ska_audio_manager_init(audioWavSampleRate); -} - -void ska_audio_shutdown() { - if (SKA_HAS_FLAG(SkaSystemFlag_AUDIO, skaState.runningSystems)) { - SKA_REMOVE_FLAGS(skaState.runningSystems, SkaSystemFlag_AUDIO); - } -} diff --git a/seika/seika.h b/seika/seika.h index 59031eb..6f70f09 100644 --- a/seika/seika.h +++ b/seika/seika.h @@ -1,38 +1 @@ #pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "defines.h" - -struct SkaColor; - -bool ska_init(); -void ska_shutdown(); -bool ska_init_all(const char* title, int32 windowWidth, int32 windowHeight, int32 resolutionWidth, int32 resolutionHeight); -bool ska_init_all2(const char* title, int32 windowWidth, int32 windowHeight, int32 resolutionWidth, int32 resolutionHeight, uint32 audioWavSampleRate, bool maintainAspectRatio); -void ska_shutdown_all(); -void ska_update(); -void ska_fixed_update(f32 deltaTime); -bool ska_is_running(); -uint32 ska_get_ticks(); -void ska_delay(uint32 timeToWait); -bool ska_set_vsync_enabled(bool enabled); -bool ska_print_errors(); - -bool ska_window_init(const char* title, int32 windowWidth, int32 windowHeight); -bool ska_window_init2(const char* title, int32 windowWidth, int32 windowHeight, int32 resolutionWidth, int32 resolutionHeight, bool maintainAspectRatio); -void ska_window_shutdown(); -void ska_window_render(const struct SkaColor* windowBackgroundColor); - -bool ska_input_init(); -void ska_input_shutdown(); - -bool ska_audio_init(); -bool ska_audio_init2(uint32 audioWavSampleRate); -void ska_audio_shutdown(); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/seika/string.c b/seika/string.c index 0675da8..562f5fe 100644 --- a/seika/string.c +++ b/seika/string.c @@ -1,6 +1,5 @@ #include "seika/string.h" -#include #include #include @@ -12,7 +11,7 @@ char* ska_strdup(const char* string) { const usize string_length = strlen(string) + 1; - char* new_string = (char*)SKA_MEM_ALLOCATE_SIZE(string_length); + char* new_string = (char*)SKA_ALLOC_BYTES(string_length); if (new_string == NULL) { return NULL; @@ -22,7 +21,7 @@ char* ska_strdup(const char* string) { } char* ska_strdup_from_memory(void* data, usize size) { - char* newString = (char*)SKA_MEM_ALLOCATE_SIZE(size + 1); + char* newString = (char*)SKA_ALLOC_BYTES(size + 1); memcpy(newString, data, size); newString[size] = '\0'; return newString; @@ -80,7 +79,7 @@ char* ska_str_to_lower_and_underscore_whitespace(char* str) { unsigned char* ska_str_convert_string_to_unsigned_char(const char* value, usize* outSize) { const usize stringLength = strlen(value); *outSize = stringLength + 1; - unsigned char* returnValue = (unsigned char*)SKA_MEM_ALLOCATE_SIZE(*outSize); + unsigned char* returnValue = (unsigned char*)SKA_ALLOC_BYTES(*outSize); for (usize i = 0; i < stringLength; i++) { returnValue[i] = (unsigned char)value[i]; } @@ -94,7 +93,7 @@ char* ska_str_trim(const char* value, char delimiter) { if (value == NULL) { return NULL; } - newStr = (char*)SKA_MEM_ALLOCATE_SIZE(strlen(value) + 1); + newStr = (char*)SKA_ALLOC_BYTES(strlen(value) + 1); if (newStr == NULL) { return NULL; } @@ -119,7 +118,7 @@ char* ska_str_trim_and_replace(const char* value, char delimiter, const char* re char pathBuffer[SE_TRIM_PATH_BUFFER]; strcpy(pathBuffer, newValue); strcat(pathBuffer, replacementValue); - SKA_MEM_FREE(newValue); + SKA_FREE(newValue); newValue = ska_strdup(pathBuffer); return newValue; #undef SE_TRIM_PATH_BUFFER @@ -147,7 +146,7 @@ char* get_project_archive_name(const char* startingPath) { char pathBuffer[256]; strcpy(pathBuffer, validPath); strcat(pathBuffer, ".zip"); - SKA_MEM_FREE(validPath); + SKA_FREE(validPath); validPath = ska_strdup(pathBuffer); return validPath; } diff --git a/seika/string.h b/seika/string.h index 99bcdf7..b872934 100644 --- a/seika/string.h +++ b/seika/string.h @@ -1,6 +1,6 @@ #pragma once -#include "defines.h" +#include "seika/defines.h" // Copies string and allocated new memory char* ska_strdup(const char* string); diff --git a/seika/thread/pthread.c b/seika/thread/pthread.c index 61964e1..69c998f 100644 --- a/seika/thread/pthread.c +++ b/seika/thread/pthread.c @@ -210,7 +210,7 @@ static DWORD WINAPI win_thread_start(void* arg) { void* (*start_routine)(void*) = data->start_routine; void* start_arg = data->start_arg; - SKA_MEM_FREE(data); + SKA_FREE(data); start_routine(start_arg); return 0; // ERROR_SUCCESS diff --git a/seika/thread/thread_pool.c b/seika/thread/thread_pool.c index dc975e3..8a193b4 100644 --- a/seika/thread/thread_pool.c +++ b/seika/thread/thread_pool.c @@ -10,7 +10,7 @@ static SkaThreadPoolWork* tpool_work_create(SkaThreadFunc func, void *arg) { return NULL; } - work = SKA_MEM_ALLOCATE_SIZE(sizeof(*work)); + work = SKA_ALLOC_BYTES(sizeof(*work)); work->func = func; work->arg = arg; work->next = NULL; @@ -21,7 +21,7 @@ static void tpool_work_destroy(SkaThreadPoolWork* work) { if (work == NULL) { return; } - SKA_MEM_FREE(work); + SKA_FREE(work); } @@ -95,7 +95,7 @@ SkaThreadPool* ska_tpool_create(usize num) { num = 2; } - tp = SKA_MEM_ALLOCATE_SIZE_ZERO(1, sizeof(*tp)); + tp = SKA_ALLOC_BYTES_ZEROED(sizeof(*tp)); tp->threadCount = num; pthread_mutex_init(&(tp->workMutex), NULL); @@ -137,7 +137,7 @@ void ska_tpool_destroy(SkaThreadPool* tp) { pthread_cond_destroy(&(tp->workCond)); pthread_cond_destroy(&(tp->workingCond)); - SKA_MEM_FREE(tp); + SKA_FREE(tp); } bool ska_tpool_add_work(SkaThreadPool* tp, SkaThreadFunc func, void* arg) { diff --git a/seika/time.c b/seika/time.c new file mode 100644 index 0000000..da06671 --- /dev/null +++ b/seika/time.c @@ -0,0 +1,15 @@ +#if SKA_INPUT || SKA_RENDERING + +#include "seika/time.h" + +#include + +uint32 ska_get_ticks() { + return (uint32)SDL_GetTicks(); +} + +void ska_delay(uint32 milliseconds) { + SDL_Delay(milliseconds); +} + +#endif // #if SKA_INPUT || SKA_RENDERING diff --git a/seika/time.h b/seika/time.h new file mode 100644 index 0000000..197641f --- /dev/null +++ b/seika/time.h @@ -0,0 +1,10 @@ +#pragma once + +#if SKA_INPUT || SKA_RENDERING + +#include "seika/defines.h" + +uint32 ska_get_ticks(); +void ska_delay(uint32 milliseconds); + +#endif // #if SKA_INPUT || SKA_RENDERING diff --git a/seika/version_info.h b/seika/version_info.h index 37e796d..e802b82 100644 --- a/seika/version_info.h +++ b/seika/version_info.h @@ -1,9 +1,9 @@ #pragma once -#include "macro_utils.h" +#include "seika/macro_utils.h" #define SKA_VERSION_MAJOR 0 -#define SKA_VERSION_MINOR 1 -#define SKA_VERSION_PATCH 6 +#define SKA_VERSION_MINOR 2 +#define SKA_VERSION_PATCH 0 #define SKA_VERSION (SKA_MACRO_TO_STRING(SKA_VERSION_MAJOR) "." SKA_MACRO_TO_STRING(SKA_VERSION_MINOR) "." SKA_MACRO_TO_STRING(SKA_VERSION_PATCH)) diff --git a/test/game/src/main.c b/test/game/src/main.c new file mode 100644 index 0000000..b7b6664 --- /dev/null +++ b/test/game/src/main.c @@ -0,0 +1,67 @@ +#include + +#include + +#include +#include +#include +#include +#include + +static void game_initialize() { + ska_window_initialize((SkaWindowProperties){ + .title = "Hello World!", + .windowWidth = 800, + .windowHeight = 600, + .resolutionWidth = 800, + .resolutionHeight = 600, + .maintainAspectRatio = true, + }); + ska_input_initialize(); +} + +static void game_finalize() { + ska_window_finalize(); + ska_input_finalize(); +} + +static void game_run() { + while (true) { + ska_input_new_frame(); + + bool shouldQuit = false; + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_EVENT_QUIT: { + shouldQuit = true; + break; + } + case SDL_EVENT_WINDOW_RESIZED: { + const Sint32 windowWidth = event.window.data1; + const Sint32 windowHeight = event.window.data2; + ska_renderer_update_window_size(windowWidth, windowHeight); + break; + } + default: { + ska_sdl_process_event(event); + break; + } + } + } + ska_sdl_process_axis_events(); + + if (shouldQuit || ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_ESCAPE, 0)) { + break; + } + ska_window_render(&(SkaColor){ 0.2f, 0.2f, 0.2f, 1.0f }); + SDL_Delay(10); + } +} + +int main(int argv, char** args) { + game_initialize(); + game_run(); + game_finalize(); + return EXIT_SUCCESS; +} diff --git a/test/test.c b/test/test.c index 2d09753..951ceb9 100644 --- a/test/test.c +++ b/test/test.c @@ -3,136 +3,136 @@ #include "seika/memory.h" #include "seika/event.h" -#include "seika/input/input.h" -#include "seika/data_structures/hash_map.h" -#include "seika/data_structures/spatial_hash_map.h" +#include "seika/asset/asset_file_loader.h" #include "seika/data_structures/array2d.h" -#include "seika/data_structures/linked_list.h" -#include "seika/ecs/ec_system.h" -#include "seika/ecs/ecs.h" +#include "seika/data_structures/array_list.h" +#include "seika/data_structures/id_queue.h" +#include "seika/data_structures/spatial_hash_map.h" #include "seika/math/curve_float.h" -#include "seika/asset/asset_file_loader.h" #include "seika/rendering/shader/shader_instance.h" #include "seika/rendering/shader/shader_file_parser.h" +#if SKA_ECS +#include "seika/ecs/ecs.h" +#include "seika/ecs/ec_system.h" +#endif + +#if SKA_INPUT +#include "seika/input/input.h" +#endif + #define RESOURCES_PATH "test/resources" #define RESOURCES_PACK_PATH "test/resources/test.pck" void setUp(void) {} void tearDown(void) {} -void seika_input_test(void); +void seika_mem_test(void); +void seika_array_list_test(void); void seika_hash_map_test(void); void seika_spatial_hash_map_test(void); -void seika_linked_list_test(void); void seika_array2d_test(void); +void seika_id_queue_test(void); void seika_asset_file_loader_test(void); void seika_observer_test(void); void seika_curve_float_test(void); void seika_shader_instance_test(void); void seika_shader_file_parser_test(void); + +#if SKA_ECS void seika_ecs_test(void); +#endif + +#if SKA_INPUT +void seika_input_test(void); +#endif int32 main(int32 argv, char** args) { UNITY_BEGIN(); - RUN_TEST(seika_input_test); + RUN_TEST(seika_mem_test); + RUN_TEST(seika_array_list_test); RUN_TEST(seika_hash_map_test); RUN_TEST(seika_spatial_hash_map_test); - RUN_TEST(seika_linked_list_test); RUN_TEST(seika_array2d_test); + RUN_TEST(seika_id_queue_test); RUN_TEST(seika_asset_file_loader_test); RUN_TEST(seika_observer_test); RUN_TEST(seika_curve_float_test); RUN_TEST(seika_shader_instance_test); RUN_TEST(seika_shader_file_parser_test); +#if SKA_ECS RUN_TEST(seika_ecs_test); +#endif +#if SKA_INPUT + RUN_TEST(seika_input_test); +#endif return UNITY_END(); } -void seika_input_test(void) { - TEST_MESSAGE("Testing 'for each' and checking input type"); - SKA_INPUT_KEY_GAMEPAD_FOR_EACH(key) { - TEST_ASSERT_TRUE(ska_input_is_gamepad_key(key)); - } - SKA_INPUT_KEY_KEYBOARD_FOR_EACH(key) { - TEST_ASSERT_TRUE(ska_input_is_keyboard_key(key)); - } - SKA_INPUT_KEY_MOUSE_FOR_EACH(key) { - TEST_ASSERT_TRUE(ska_input_is_mouse_key(key)); - } - - const char* backspaceKeyName = ska_input_key_to_string(SkaInputKey_KEYBOARD_BACKSPACE); - const SkaInputKey backSpaceKey = ska_input_string_to_key(backspaceKeyName); - TEST_ASSERT_EQUAL_STRING("Backspace", backspaceKeyName); - TEST_ASSERT_EQUAL_INT(SkaInputKey_KEYBOARD_BACKSPACE, backSpaceKey); - - TEST_MESSAGE("Testing events"); - ska_input_register_input_event3(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_BACKSPACE, SkaInputTriggerType_PRESSED); - TEST_ASSERT_TRUE(ska_input_is_key_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_TRUE(ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_FALSE(ska_input_is_key_just_released(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - - ska_input_register_input_event3(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_BACKSPACE, SkaInputTriggerType_PRESSED); - TEST_ASSERT_TRUE(ska_input_is_key_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_FALSE(ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_FALSE(ska_input_is_key_just_released(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - - ska_input_register_input_event3(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_BACKSPACE, SkaInputTriggerType_RELEASED); - TEST_ASSERT_FALSE(ska_input_is_key_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_FALSE(ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_TRUE(ska_input_is_key_just_released(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - - TEST_MESSAGE("Testing input get axis input"); - ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_Y, SkaInputTriggerType_AXIS_IN_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, -0.5f); - const SkaVector2 firstAxisInput = ska_input_get_axis_input(SkaInputAxis_LEFT, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); - TEST_ASSERT_EQUAL_FLOAT(0.0f, firstAxisInput.x); - TEST_ASSERT_EQUAL_FLOAT(-0.5f, firstAxisInput.y); +void seika_mem_test(void) { + int* testInt = SKA_ALLOC(int); + TEST_ASSERT_NOT_NULL(testInt); + *testInt = 5; + TEST_ASSERT_EQUAL_INT(5, *testInt); + TEST_ASSERT_TRUE(ska_mem_report_leaks()); + SKA_FREE(testInt); + TEST_ASSERT_FALSE(ska_mem_report_leaks()); +} - ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_X, SkaInputTriggerType_AXIS_IN_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.25f); - const SkaVector2 secondAxisInput = ska_input_get_axis_input(SkaInputAxis_LEFT, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); - TEST_ASSERT_EQUAL_FLOAT(0.25f, secondAxisInput.x); - TEST_ASSERT_EQUAL_FLOAT(-0.5f, secondAxisInput.y); +void seika_array_list_test(void) { + int listValues[] = { 8, 2, 3, 5 }; + SkaArrayList* arrayList = ska_array_list_create_default_capacity(sizeof(int)); + TEST_ASSERT_TRUE(ska_array_list_is_empty(arrayList)); - ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_X, SkaInputTriggerType_AXIS_STOPPED_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.25f); - ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_Y, SkaInputTriggerType_AXIS_STOPPED_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.25f); - const SkaVector2 thirdAxisInput = ska_input_get_axis_input(SkaInputAxis_LEFT, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); - TEST_ASSERT_EQUAL_FLOAT(0.0f, thirdAxisInput.x); - TEST_ASSERT_EQUAL_FLOAT(0.0f, thirdAxisInput.y); + for (int i = 0; i < 4; i++) { + ska_array_list_push_back(arrayList, &listValues[i]); + } + TEST_ASSERT_FALSE(ska_array_list_is_empty(arrayList)); + int index = 0; + SKA_ARRAY_LIST_FOR_EACH(arrayList, int, i) { + const int value = (int)*(int*)ska_array_list_get(arrayList, index); + TEST_ASSERT_EQUAL_INT(listValues[index], value); + index++; + } - ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_RIGHT_ANALOG_2D_AXIS_X, SkaInputTriggerType_AXIS_IN_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 1.0f); - const SkaVector2 fourthAxisInput = ska_input_get_axis_input(SkaInputAxis_RIGHT, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); - TEST_ASSERT_EQUAL_FLOAT(1.0f, fourthAxisInput.x); - TEST_ASSERT_EQUAL_FLOAT(0.0f, fourthAxisInput.y); + ska_array_list_remove_by_index(arrayList, 1); + int oneValue = (int)*(int*)ska_array_list_get(arrayList, 1); + TEST_ASSERT_EQUAL_INT(3, oneValue); - TEST_MESSAGE("Testing input actions"); - SkaInputActionHandle jumpActionHandle = ska_input_add_input_action( - "jump", - (SkaInputActionValue[]){ { .key = SkaInputKey_KEYBOARD_SPACE, .strengthThreshold = 0.5f }, { .key = SkaInputKey_KEYBOARD_RETURN, .strengthThreshold = 0.5f }, { SkaInputKey_INVALID } }, - SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX - ); - TEST_ASSERT_NOT_EQUAL_UINT32(SKA_INPUT_INVALID_INPUT_ACTION_HANDLE, jumpActionHandle); - jumpActionHandle = ska_input_find_input_action_handle("jump", SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); - TEST_ASSERT_NOT_EQUAL_UINT32(SKA_INPUT_INVALID_INPUT_ACTION_HANDLE, jumpActionHandle); + ska_array_list_remove(arrayList, &(int){3}); + oneValue = (int)*(int*)ska_array_list_get(arrayList, 1); + TEST_ASSERT_EQUAL_INT(5, oneValue); - ska_input_register_input_event(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_RETURN, SkaInputTriggerType_PRESSED, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.0f); - TEST_ASSERT_TRUE(ska_input_is_input_action_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_TRUE(ska_input_is_input_action_just_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_FALSE(ska_input_is_input_action_just_released(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_EQUAL_FLOAT(1.0f, ska_input_get_input_action_strength(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + ska_array_list_clear(arrayList); + TEST_ASSERT_TRUE(ska_array_list_is_empty(arrayList)); + ska_array_list_destroy(arrayList); +} - ska_input_new_frame(); - TEST_ASSERT_TRUE(ska_input_is_input_action_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_FALSE(ska_input_is_input_action_just_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_FALSE(ska_input_is_input_action_just_released(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); +void seika_id_queue_test(void) { + SkaIdQueue* idQueue = ska_id_queue_create(10); - ska_input_register_input_event(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_RETURN, SkaInputTriggerType_RELEASED, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.0f); - TEST_ASSERT_FALSE(ska_input_is_input_action_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_FALSE(ska_input_is_input_action_just_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); - TEST_ASSERT_TRUE(ska_input_is_input_action_just_released(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + uint32 value; + for (uint32 i = 0; i < 10; i++) { + ska_id_queue_dequeue(idQueue, &value); + TEST_ASSERT_EQUAL_UINT32(i, value); + } - ska_input_remove_input_action(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); - TEST_ASSERT_EQUAL_UINT32(SKA_INPUT_INVALID_INPUT_ACTION_HANDLE, ska_input_find_input_action_handle("jump", SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_TRUE(ska_id_queue_is_empty(idQueue)); + + ska_id_queue_enqueue(idQueue, 4); + ska_id_queue_enqueue(idQueue, 6); + ska_id_queue_enqueue(idQueue, 5); + ska_id_queue_dequeue(idQueue, &value); + TEST_ASSERT_EQUAL_UINT32(4, value); + ska_id_queue_dequeue(idQueue, &value); + TEST_ASSERT_EQUAL_UINT32(6, value); + ska_id_queue_dequeue(idQueue, &value); + TEST_ASSERT_EQUAL_UINT32(5, value); + + ska_id_queue_dequeue(idQueue, &value); + TEST_ASSERT_EQUAL_UINT32(10, value); + TEST_ASSERT_EQUAL_size_t(20, idQueue->capacity); } void seika_hash_map_test(void) { @@ -207,74 +207,6 @@ void seika_spatial_hash_map_test(void) { ska_spatial_hash_map_destroy(spatialHashMap); } -static bool linked_list_test_sort(void* a, void* b) { - int numA = (int) *(int*) a; - int numB = (int) *(int*) b; - return numA > numB; -} - -void seika_linked_list_test(void) { - SkaLinkedList* list = ska_linked_list_create(sizeof(int32)); - // Test prepend - int32 num1 = 9; - int32 num2 = 7; - ska_linked_list_prepend(list, &num1); - const int32 returnedNum = (int32) *(int32*) ska_linked_list_get_front(list); - TEST_ASSERT_EQUAL_INT(1, list->size); - TEST_ASSERT_EQUAL_INT(num1, returnedNum); - ska_linked_list_prepend(list, &num2); - TEST_ASSERT_EQUAL_INT(2, list->size); - ska_linked_list_remove(list, &num1); - TEST_ASSERT_EQUAL_INT(1, list->size); - int32* returnedNum2 = (int32*) ska_linked_list_pop_front(list); - TEST_ASSERT_EQUAL_INT(7, *returnedNum2); - TEST_ASSERT_TRUE(ska_linked_list_is_empty(list)); - SKA_MEM_FREE(returnedNum2); - - int32 numbers[5]; - for (int32 i = 0; i < 5; i++) { - numbers[i] = i; - ska_linked_list_append(list, &i); - } - TEST_ASSERT_EQUAL_INT(5, list->size); - - // For each loop test - SkaLinkedListNode* node = NULL; - int32 loopIndex = 0; - SKA_LINKED_LIST_FOR_EACH(list, node) { - const int32 indexNum = (int32)*(int32*)node->value; - TEST_ASSERT_EQUAL_INT(indexNum, numbers[loopIndex]); - loopIndex++; - } - - const int32 indexThreeNum = (int32)*(int32*)ska_linked_list_get(list, 3); - TEST_ASSERT_EQUAL_INT(3, indexThreeNum); - - // Insert Test - int32 insertNum1 = 10; - int32 insertNum2 = 20; - ska_linked_list_insert(list, &insertNum1, 3); - TEST_ASSERT_EQUAL_INT(6, list->size); - ska_linked_list_insert(list, &insertNum2, 1); - TEST_ASSERT_EQUAL_INT(7, list->size); - const int32 insertNumThree = (int32)*(int32*)ska_linked_list_get(list, 3); - TEST_ASSERT_EQUAL_INT(10, insertNumThree); - const int32 insertNumOne = (int32)*(int32*)ska_linked_list_get(list, 1); - TEST_ASSERT_EQUAL_INT(20, insertNumOne); - - ska_linked_list_sort(list, linked_list_test_sort); - const int32 smallestNum = (int32)*(int32*)ska_linked_list_get_front(list); - const int32 highestNum = (int32)*(int32*)ska_linked_list_get_back(list); - TEST_ASSERT_EQUAL_INT(0, smallestNum); - TEST_ASSERT_EQUAL_INT(20, highestNum); - - // Clear test - ska_linked_list_clear(list); - TEST_ASSERT_EQUAL_INT(0, list->size); - - ska_linked_list_destroy(list); -} - void seika_array2d_test(void) { typedef struct TestArrayStruct { int value; @@ -347,7 +279,8 @@ void seika_asset_file_loader_test(void) { ska_asset_file_loader_finalize(); } -// Observer Test +//--- Observer Test ---// + static bool hasObserved = false; void observer_func1(SkaSubjectNotifyPayload* payload) { @@ -425,7 +358,7 @@ void seika_shader_instance_test(void) { SKA_STRING_HASH_MAP_FOR_EACH(shaderInstance.paramMap, iter) { SkaStringHashMapNode* node = iter.pair; SkaShaderParam* param = (SkaShaderParam*) node->value; - SKA_MEM_FREE(param->name); + SKA_FREE(param->name); } ska_string_hash_map_destroy(shaderInstance.paramMap); } @@ -461,7 +394,7 @@ void seika_shader_file_parser_test(void) { ska_shader_file_parse_clear_parse_result(&result); } -// ECS TEST +#if SKA_ECS typedef struct TestValueComponent { int32 value; } TestValueComponent; @@ -556,3 +489,93 @@ void seika_ecs_test(void) { ska_ecs_finalize(); } +#endif + +#if SKA_INPUT + +void seika_input_test(void) { + TEST_MESSAGE("Testing 'for each' and checking input type"); + SKA_INPUT_KEY_GAMEPAD_FOR_EACH(key) { + TEST_ASSERT_TRUE(ska_input_is_gamepad_key(key)); + } + SKA_INPUT_KEY_KEYBOARD_FOR_EACH(key) { + TEST_ASSERT_TRUE(ska_input_is_keyboard_key(key)); + } + SKA_INPUT_KEY_MOUSE_FOR_EACH(key) { + TEST_ASSERT_TRUE(ska_input_is_mouse_key(key)); + } + + const char* backspaceKeyName = ska_input_key_to_string(SkaInputKey_KEYBOARD_BACKSPACE); + const SkaInputKey backSpaceKey = ska_input_string_to_key(backspaceKeyName); + TEST_ASSERT_EQUAL_STRING("Backspace", backspaceKeyName); + TEST_ASSERT_EQUAL_INT(SkaInputKey_KEYBOARD_BACKSPACE, backSpaceKey); + + TEST_MESSAGE("Testing events"); + ska_input_register_input_event3(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_BACKSPACE, SkaInputTriggerType_PRESSED); + TEST_ASSERT_TRUE(ska_input_is_key_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_TRUE(ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_FALSE(ska_input_is_key_just_released(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + + ska_input_register_input_event3(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_BACKSPACE, SkaInputTriggerType_PRESSED); + TEST_ASSERT_TRUE(ska_input_is_key_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_FALSE(ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_FALSE(ska_input_is_key_just_released(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + + ska_input_register_input_event3(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_BACKSPACE, SkaInputTriggerType_RELEASED); + TEST_ASSERT_FALSE(ska_input_is_key_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_FALSE(ska_input_is_key_just_pressed(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_TRUE(ska_input_is_key_just_released(SkaInputKey_KEYBOARD_BACKSPACE, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + + TEST_MESSAGE("Testing input get axis input"); + ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_Y, SkaInputTriggerType_AXIS_IN_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, -0.5f); + const SkaVector2 firstAxisInput = ska_input_get_axis_input(SkaInputAxis_LEFT, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); + TEST_ASSERT_EQUAL_FLOAT(0.0f, firstAxisInput.x); + TEST_ASSERT_EQUAL_FLOAT(-0.5f, firstAxisInput.y); + + ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_X, SkaInputTriggerType_AXIS_IN_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.25f); + const SkaVector2 secondAxisInput = ska_input_get_axis_input(SkaInputAxis_LEFT, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); + TEST_ASSERT_EQUAL_FLOAT(0.25f, secondAxisInput.x); + TEST_ASSERT_EQUAL_FLOAT(-0.5f, secondAxisInput.y); + + ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_X, SkaInputTriggerType_AXIS_STOPPED_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.25f); + ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_LEFT_ANALOG_2D_AXIS_Y, SkaInputTriggerType_AXIS_STOPPED_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.25f); + const SkaVector2 thirdAxisInput = ska_input_get_axis_input(SkaInputAxis_LEFT, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); + TEST_ASSERT_EQUAL_FLOAT(0.0f, thirdAxisInput.x); + TEST_ASSERT_EQUAL_FLOAT(0.0f, thirdAxisInput.y); + + ska_input_register_input_event(SkaInputSourceType_GAMEPAD, SkaInputKey_GAMEPAD_RIGHT_ANALOG_2D_AXIS_X, SkaInputTriggerType_AXIS_IN_MOTION, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 1.0f); + const SkaVector2 fourthAxisInput = ska_input_get_axis_input(SkaInputAxis_RIGHT, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); + TEST_ASSERT_EQUAL_FLOAT(1.0f, fourthAxisInput.x); + TEST_ASSERT_EQUAL_FLOAT(0.0f, fourthAxisInput.y); + + TEST_MESSAGE("Testing input actions"); + SkaInputActionHandle jumpActionHandle = ska_input_add_input_action( + "jump", + (SkaInputActionValue[]){ { .key = SkaInputKey_KEYBOARD_SPACE, .strengthThreshold = 0.5f }, { .key = SkaInputKey_KEYBOARD_RETURN, .strengthThreshold = 0.5f }, { SkaInputKey_INVALID } }, + SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX + ); + TEST_ASSERT_NOT_EQUAL_UINT32(SKA_INPUT_INVALID_INPUT_ACTION_HANDLE, jumpActionHandle); + jumpActionHandle = ska_input_find_input_action_handle("jump", SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); + TEST_ASSERT_NOT_EQUAL_UINT32(SKA_INPUT_INVALID_INPUT_ACTION_HANDLE, jumpActionHandle); + + ska_input_register_input_event(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_RETURN, SkaInputTriggerType_PRESSED, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.0f); + TEST_ASSERT_TRUE(ska_input_is_input_action_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_TRUE(ska_input_is_input_action_just_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_FALSE(ska_input_is_input_action_just_released(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_EQUAL_FLOAT(1.0f, ska_input_get_input_action_strength(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + + ska_input_new_frame(); + TEST_ASSERT_TRUE(ska_input_is_input_action_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_FALSE(ska_input_is_input_action_just_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_FALSE(ska_input_is_input_action_just_released(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + + ska_input_register_input_event(SkaInputSourceType_KEYBOARD, SkaInputKey_KEYBOARD_RETURN, SkaInputTriggerType_RELEASED, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX, 0.0f); + TEST_ASSERT_FALSE(ska_input_is_input_action_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_FALSE(ska_input_is_input_action_just_pressed(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + TEST_ASSERT_TRUE(ska_input_is_input_action_just_released(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); + + ska_input_remove_input_action(jumpActionHandle, SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX); + TEST_ASSERT_EQUAL_UINT32(SKA_INPUT_INVALID_INPUT_ACTION_HANDLE, ska_input_find_input_action_handle("jump", SKA_INPUT_FIRST_PLAYER_DEVICE_INDEX)); +} + +#endif // if SKA_INPUT