Compare commits

..

2 Commits

Author SHA1 Message Date
b4438c1510 tely: Fix DLL build using wrong DLL nameg 2023-10-29 15:14:16 +11:00
989b0d30cc fp: Upgrade TELY and simplify build 2023-10-29 15:14:16 +11:00
12 changed files with 318 additions and 462 deletions

2
External/tely vendored

@ -1 +1 @@
Subproject commit a1e15e336b6d9eac5538392d2c473c7b740364d5
Subproject commit d82244653e856bbf4f83c6338207405aa4595e46

View File

@ -38,7 +38,7 @@ static void FP_EmitParticle(FP_Game *game, FP_ParticleDescriptor descriptor, Dqn
}
}
static TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform, TELY_Assets *assets, Dqn_Arena *arena, Dqn_Str8 sheet_name)
static TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_OS *os, TELY_Assets *assets, Dqn_Arena *arena, Dqn_Str8 sheet_name)
{
TELY_AssetSpriteSheet result = {};
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(arena);
@ -47,7 +47,7 @@ static TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform,
// NOTE: Load the sprite meta file =========================================================
Dqn_Str8 sprite_spec_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.txt", DQN_STR_FMT(assets->textures_dir), DQN_STR_FMT(sheet_name));
Dqn_Str8 sprite_spec_buffer = platform->func_load_file(scratch.arena, sprite_spec_path);
Dqn_Str8 sprite_spec_buffer = os->funcs.load_file(scratch.arena, sprite_spec_path);
Dqn_Str8SplitAllocResult lines = Dqn_Str8_SplitAlloc(scratch.allocator, sprite_spec_buffer, DQN_STR8("\n"));
Dqn_usize sprite_rect_index = 0;
Dqn_usize sprite_anim_index = 0;
@ -62,7 +62,7 @@ static TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform,
// NOTE: Sprite sheet path
Dqn_Str8 sprite_sheet_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STR_FMT(assets->textures_dir), DQN_STR_FMT(line_splits.data[1]));
result.tex_handle = platform->func_load_texture(assets, sheet_name, sprite_sheet_path);
result.tex_handle = os->funcs.load_texture(assets, sheet_name, sprite_sheet_path);
DQN_ASSERTF(Dqn_Fs_Exists(sprite_sheet_path), "Required file does not exist '%.*s'", DQN_STR_FMT(sprite_sheet_path));
// NOTE: Total sprite frame count
@ -127,18 +127,18 @@ static TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform,
static void FP_SetDefaultGamepadBindings(FP_GameControls *controls)
{
// NOTE: Note up/down/left/right uses analog sticks, non-negotiable.
controls->attack.gamepad_key = TELY_PlatformInputGamepadKey_X;
controls->range_attack.gamepad_key = TELY_PlatformInputGamepadKey_Y;
controls->build_mode.gamepad_key = TELY_PlatformInputGamepadKey_L3;
controls->strafe.gamepad_key = TELY_PlatformInputGamepadKey_B;
controls->dash.gamepad_key = TELY_PlatformInputGamepadKey_A;
controls->buy_building.gamepad_key = TELY_PlatformInputGamepadKey_LeftBumper;
controls->buy_upgrade.gamepad_key = TELY_PlatformInputGamepadKey_RightBumper;
controls->move_building_ui_cursor_left.gamepad_key = TELY_PlatformInputGamepadKey_DLeft;
controls->move_building_ui_cursor_right.gamepad_key = TELY_PlatformInputGamepadKey_DRight;
controls->attack.gamepad_key = TELY_OSInputGamepadKey_X;
controls->range_attack.gamepad_key = TELY_OSInputGamepadKey_Y;
controls->build_mode.gamepad_key = TELY_OSInputGamepadKey_L3;
controls->strafe.gamepad_key = TELY_OSInputGamepadKey_B;
controls->dash.gamepad_key = TELY_OSInputGamepadKey_A;
controls->buy_building.gamepad_key = TELY_OSInputGamepadKey_LeftBumper;
controls->buy_upgrade.gamepad_key = TELY_OSInputGamepadKey_RightBumper;
controls->move_building_ui_cursor_left.gamepad_key = TELY_OSInputGamepadKey_DLeft;
controls->move_building_ui_cursor_right.gamepad_key = TELY_OSInputGamepadKey_DRight;
}
static bool FP_ListenForNewPlayer(TELY_PlatformInput *input, FP_Game *game)
static bool FP_ListenForNewPlayer(TELY_OSInput *input, FP_Game *game)
{
bool result = false;
if (game->play.players.size == 2)
@ -159,8 +159,8 @@ static bool FP_ListenForNewPlayer(TELY_PlatformInput *input, FP_Game *game)
}
}
bool keyboard_pressed = !keyboard_already_allocated && TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_B);
bool gamepad_pressed = TELY_Platform_InputGamepadKeyIsPressed(input, gamepad_index, TELY_PlatformInputGamepadKey_Start);
bool keyboard_pressed = !keyboard_already_allocated && TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_B);
bool gamepad_pressed = TELY_OSInput_GamepadKeyIsPressed(input, gamepad_index, TELY_OSInputGamepadKey_Start);
if (keyboard_pressed || gamepad_pressed) {
FP_GameEntityHandle terry_handle = {};
@ -178,19 +178,19 @@ static bool FP_ListenForNewPlayer(TELY_PlatformInput *input, FP_Game *game)
FP_GameControls *controls = &terry->controls;
if (keyboard_pressed) {
controls->mode = FP_GameControlMode_Keyboard;
controls->up.scan_code = TELY_PlatformInputScanCode_W;
controls->down.scan_code = TELY_PlatformInputScanCode_S;
controls->left.scan_code = TELY_PlatformInputScanCode_A;
controls->right.scan_code = TELY_PlatformInputScanCode_D;
controls->attack.scan_code = TELY_PlatformInputScanCode_J;
controls->range_attack.scan_code = TELY_PlatformInputScanCode_K;
controls->build_mode.scan_code = TELY_PlatformInputScanCode_H;
controls->strafe.scan_code = TELY_PlatformInputScanCode_L;
controls->dash.scan_code = TELY_PlatformInputScanCode_N;
controls->buy_building.scan_code = TELY_PlatformInputScanCode_U;
controls->buy_upgrade.scan_code = TELY_PlatformInputScanCode_I;
controls->move_building_ui_cursor_left.scan_code = TELY_PlatformInputScanCode_Q;
controls->move_building_ui_cursor_right.scan_code = TELY_PlatformInputScanCode_E;
controls->up.scan_key = TELY_OSInputScanKey_W;
controls->down.scan_key = TELY_OSInputScanKey_S;
controls->left.scan_key = TELY_OSInputScanKey_A;
controls->right.scan_key = TELY_OSInputScanKey_D;
controls->attack.scan_key = TELY_OSInputScanKey_J;
controls->range_attack.scan_key = TELY_OSInputScanKey_K;
controls->build_mode.scan_key = TELY_OSInputScanKey_H;
controls->strafe.scan_key = TELY_OSInputScanKey_L;
controls->dash.scan_key = TELY_OSInputScanKey_N;
controls->buy_building.scan_key = TELY_OSInputScanKey_U;
controls->buy_upgrade.scan_key = TELY_OSInputScanKey_I;
controls->move_building_ui_cursor_left.scan_key = TELY_OSInputScanKey_Q;
controls->move_building_ui_cursor_right.scan_key = TELY_OSInputScanKey_E;
} else {
controls->mode = FP_GameControlMode_Gamepad;
controls->gamepad_index = gamepad_index;
@ -202,7 +202,7 @@ static bool FP_ListenForNewPlayer(TELY_PlatformInput *input, FP_Game *game)
return result;
}
static void FP_PlayReset(FP_Game *game, TELY_Platform *platform)
static void FP_PlayReset(FP_Game *game, TELY_OS *os)
{
FP_GamePlay *play = &game->play;
if (game->play.root_entity)
@ -211,7 +211,7 @@ static void FP_PlayReset(FP_Game *game, TELY_Platform *platform)
Dqn_VArray<FP_GameEntity> shallow_entities_copy = play->entities;
DQN_MEMSET(play, 0, sizeof(*play));
play->chunk_pool = &platform->chunk_pool;
play->chunk_pool = &os->chunk_pool;
play->meters_to_pixels = 65.416f;
play->entities = shallow_entities_copy;
@ -223,7 +223,7 @@ static void FP_PlayReset(FP_Game *game, TELY_Platform *platform)
play->root_entity = Dqn_VArray_Make(&play->entities, Dqn_ZeroMem_No);
Dqn_FArray_Add(&play->parent_entity_stack, play->root_entity->handle);
Dqn_PCG32_Seed(&play->rng, platform->core.epoch_time);
Dqn_PCG32_Seed(&play->rng, os->core.epoch_time);
// NOTE: Map ===================================================================================
{
@ -393,61 +393,55 @@ static void FP_PlayReset(FP_Game *game, TELY_Platform *platform)
play->camera.size = FP_TARGET_VIEWPORT_SIZE;
}
#if defined(DQN_OS_WIN32)
#define FP_DLL_FUNCTION extern "C" __declspec(dllexport)
#else
#define FP_DLL_FUNCTION
#endif
FP_DLL_FUNCTION
void TELY_DLL_Reload(void *user_data)
TELY_OS_DLL_FUNCTION
void TELY_OS_DLLReload(TELY_OS *os)
{
TELY_Platform *platform = DQN_CAST(TELY_Platform *)user_data;
Dqn_Library_SetPointer(platform->core.dqn_lib);
platform->func_set_window_title(DQN_STR8("Terry Cherry"));
Dqn_Library_SetPointer(os->core.dqn_lib);
g_tely = os->funcs;
os->funcs.set_window_title(DQN_STR8("Terry Cherry"));
}
FP_DLL_FUNCTION
void TELY_DLL_Init(void *user_data)
TELY_OS_DLL_FUNCTION
void TELY_OS_DLLInit(TELY_OS *os)
{
TELY_Platform *platform = DQN_CAST(TELY_Platform *)user_data;
TELY_DLL_Reload(user_data);
FP_UnitTests(platform);
TELY_OS_DLLReload(os);
FP_UnitTests(os);
// NOTE: TELY Game =============================================================================
TELY_Assets *assets = &platform->assets;
FP_Game *game = Dqn_Arena_New(&platform->arena, FP_Game, Dqn_ZeroMem_Yes);
TELY_Assets *assets = &os->assets;
FP_Game *game = Dqn_Arena_New(&os->arena, FP_Game, Dqn_ZeroMem_Yes);
Dqn_f32 font_scalar = FP_TARGET_VIEWPORT_SIZE.w / DQN_CAST(Dqn_f32)platform->core.window_size.x;
uint16_t font_size = DQN_CAST(uint16_t)(18 * font_scalar);
game->inter_regular_font_large = platform->func_load_font(assets, DQN_STR8("Inter (Regular)"), DQN_STR8("Data/Fonts/Inter-Regular.otf"), DQN_CAST(uint16_t)(font_size * 5.f));
game->inter_regular_font = platform->func_load_font(assets, DQN_STR8("Inter (Regular)"), DQN_STR8("Data/Fonts/Inter-Regular.otf"), DQN_CAST(uint16_t)(font_size));
game->inter_italic_font = platform->func_load_font(assets, DQN_STR8("Inter (Italic)"), DQN_STR8("Data/Fonts/Inter-Italic.otf"), font_size);
game->jetbrains_mono_font = platform->func_load_font(assets, DQN_STR8("JetBrains Mono NL (Regular)"), DQN_STR8("Data/Fonts/JetBrainsMonoNL-Regular.ttf"), font_size);
game->talkco_font = platform->func_load_font(assets, DQN_STR8("Talkco"), DQN_STR8("Data/Fonts/Talkco.otf"), font_size);
game->talkco_font_large = platform->func_load_font(assets, DQN_STR8("Talkco"), DQN_STR8("Data/Fonts/Talkco.otf"), DQN_CAST(uint16_t)(font_size * 1.5f));
game->talkco_font_xlarge = platform->func_load_font(assets, DQN_STR8("Talkco"), DQN_STR8("Data/Fonts/Talkco.otf"), DQN_CAST(uint16_t)(font_size * 2.f));
game->audio[FP_GameAudio_TerryHit] = platform->func_load_audio(assets, DQN_STR8("Terry Hit"), DQN_STR8("Data/Audio/terry_hit.ogg"));
game->audio[FP_GameAudio_Ching] = platform->func_load_audio(assets, DQN_STR8("Ching"), DQN_STR8("Data/Audio/ching.ogg"));
game->audio[FP_GameAudio_Church] = platform->func_load_audio(assets, DQN_STR8("Church"), DQN_STR8("Data/Audio/church.ogg"));
game->audio[FP_GameAudio_Club] = platform->func_load_audio(assets, DQN_STR8("Club"), DQN_STR8("Data/Audio/club_terry.ogg"));
game->audio[FP_GameAudio_Dog] = platform->func_load_audio(assets, DQN_STR8("Dog"), DQN_STR8("Data/Audio/dog.ogg"));
game->audio[FP_GameAudio_MerchantGhost] = platform->func_load_audio(assets, DQN_STR8("Ghost"), DQN_STR8("Data/Audio/merchant_ghost.ogg"));
game->audio[FP_GameAudio_MerchantGym] = platform->func_load_audio(assets, DQN_STR8("Gym"), DQN_STR8("Data/Audio/merchant_gym.ogg"));
game->audio[FP_GameAudio_MerchantPhone] = platform->func_load_audio(assets, DQN_STR8("Phone"), DQN_STR8("Data/Audio/merchant_tech.ogg"));
game->audio[FP_GameAudio_MerchantTerry] = platform->func_load_audio(assets, DQN_STR8("Door"), DQN_STR8("Data/Audio/merchant_terry.ogg"));
game->audio[FP_GameAudio_Message] = platform->func_load_audio(assets, DQN_STR8("Message"), DQN_STR8("Data/Audio/message.ogg"));
game->audio[FP_GameAudio_Monkey] = platform->func_load_audio(assets, DQN_STR8("Monkey"), DQN_STR8("Data/Audio/monkey.ogg"));
game->audio[FP_GameAudio_Plane] = platform->func_load_audio(assets, DQN_STR8("Plane"), DQN_STR8("Data/Audio/airport.ogg"));
game->audio[FP_GameAudio_PortalDestroy] = platform->func_load_audio(assets, DQN_STR8("Portal Destroy"), DQN_STR8("Data/Audio/portal_destroy.ogg"));
game->audio[FP_GameAudio_Smooch] = platform->func_load_audio(assets, DQN_STR8("Smooch"), DQN_STR8("Data/Audio/smooch.ogg"));
game->audio[FP_GameAudio_Woosh] = platform->func_load_audio(assets, DQN_STR8("Woosh"), DQN_STR8("Data/Audio/woosh.ogg"));
Dqn_f32 font_scalar = FP_TARGET_VIEWPORT_SIZE.w / DQN_CAST(Dqn_f32)os->core.window_size.x;
game->font_size = DQN_CAST(uint16_t)(18 * font_scalar);
game->large_font_size = DQN_CAST(uint16_t)(game->font_size * .5f);
game->large_talkco_font_size = DQN_CAST(uint16_t)(game->font_size * 1.5f);
game->xlarge_talkco_font_size = DQN_CAST(uint16_t)(game->font_size * 2.f);
game->inter_regular_font = TELY_Asset_LoadFont(assets, DQN_STR8("Inter (Regular)"), DQN_STR8("Data/Fonts/Inter-Regular.otf"));
game->inter_italic_font = TELY_Asset_LoadFont(assets, DQN_STR8("Inter (Italic)"), DQN_STR8("Data/Fonts/Inter-Italic.otf"));
game->jetbrains_mono_font = TELY_Asset_LoadFont(assets, DQN_STR8("JetBrains Mono NL (Regular)"), DQN_STR8("Data/Fonts/JetBrainsMonoNL-Regular.ttf"));
game->talkco_font = TELY_Asset_LoadFont(assets, DQN_STR8("Talkco"), DQN_STR8("Data/Fonts/Talkco.otf"));
game->audio[FP_GameAudio_TerryHit] = os->funcs.load_audio(assets, DQN_STR8("Terry Hit"), DQN_STR8("Data/Audio/terry_hit.ogg"));
game->audio[FP_GameAudio_Ching] = os->funcs.load_audio(assets, DQN_STR8("Ching"), DQN_STR8("Data/Audio/ching.ogg"));
game->audio[FP_GameAudio_Church] = os->funcs.load_audio(assets, DQN_STR8("Church"), DQN_STR8("Data/Audio/church.ogg"));
game->audio[FP_GameAudio_Club] = os->funcs.load_audio(assets, DQN_STR8("Club"), DQN_STR8("Data/Audio/club_terry.ogg"));
game->audio[FP_GameAudio_Dog] = os->funcs.load_audio(assets, DQN_STR8("Dog"), DQN_STR8("Data/Audio/dog.ogg"));
game->audio[FP_GameAudio_MerchantGhost] = os->funcs.load_audio(assets, DQN_STR8("Ghost"), DQN_STR8("Data/Audio/merchant_ghost.ogg"));
game->audio[FP_GameAudio_MerchantGym] = os->funcs.load_audio(assets, DQN_STR8("Gym"), DQN_STR8("Data/Audio/merchant_gym.ogg"));
game->audio[FP_GameAudio_MerchantPhone] = os->funcs.load_audio(assets, DQN_STR8("Phone"), DQN_STR8("Data/Audio/merchant_tech.ogg"));
game->audio[FP_GameAudio_MerchantTerry] = os->funcs.load_audio(assets, DQN_STR8("Door"), DQN_STR8("Data/Audio/merchant_terry.ogg"));
game->audio[FP_GameAudio_Message] = os->funcs.load_audio(assets, DQN_STR8("Message"), DQN_STR8("Data/Audio/message.ogg"));
game->audio[FP_GameAudio_Monkey] = os->funcs.load_audio(assets, DQN_STR8("Monkey"), DQN_STR8("Data/Audio/monkey.ogg"));
game->audio[FP_GameAudio_Plane] = os->funcs.load_audio(assets, DQN_STR8("Plane"), DQN_STR8("Data/Audio/airport.ogg"));
game->audio[FP_GameAudio_PortalDestroy] = os->funcs.load_audio(assets, DQN_STR8("Portal Destroy"), DQN_STR8("Data/Audio/portal_destroy.ogg"));
game->audio[FP_GameAudio_Smooch] = os->funcs.load_audio(assets, DQN_STR8("Smooch"), DQN_STR8("Data/Audio/smooch.ogg"));
game->audio[FP_GameAudio_Woosh] = os->funcs.load_audio(assets, DQN_STR8("Woosh"), DQN_STR8("Data/Audio/woosh.ogg"));
// NOTE: Load sprite sheets ====================================================================
platform->user_data = game;
game->atlas_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STR8("atlas"));
FP_PlayReset(game, platform);
os->user_data = game;
game->atlas_sprite_sheet = FP_LoadSpriteSheetFromSpec(os, assets, &os->arena, DQN_STR8("atlas"));
FP_PlayReset(game, os);
}
@ -508,7 +502,7 @@ static void FP_AppendMobSpawnerWaypoints(FP_Game *game, FP_GameEntityHandle src_
}
}
static void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_PlatformInput *input, FP_GameEntity *entity, Dqn_V2 *acceleration_meters_per_s)
static void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_OSInput *input, FP_GameEntity *entity, Dqn_V2 *acceleration_meters_per_s)
{
TELY_AssetSpriteSheet *sheet = &game->atlas_sprite_sheet;
FP_GameEntityAction *action = &entity->action;
@ -1301,25 +1295,25 @@ static void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_P
}
}
static void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input, TELY_Audio *audio)
static void FP_Update(TELY_OS *os, FP_Game *game, TELY_OSInput *input, TELY_Audio *audio)
{
Dqn_Profiler_ZoneScopeWithIndex("FP_Update", FP_ProfileZone_FPUpdate);
game->play.update_counter++;
Dqn_ProfilerZone update_zone = Dqn_Profiler_BeginZoneWithIndex(DQN_STR8("FP_Update: Entity loop"), FP_ProfileZone_FPUpdate_EntityLoop);
if (game->play.state == FP_GameState_Play && game->play.perry_joined != FP_GamePerryJoins_Enters) {
game->play.clock_ms = DQN_CAST(uint64_t)(platform->input.timer_s * 1000.f);
game->play.clock_ms = DQN_CAST(uint64_t)(os->input.timer_s * 1000.f);
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4127) // Conditional expression is constant 'FP_DEVELOPER_MODE'
if (FP_DEVELOPER_MODE && TELY_Platform_InputKeyIsReleased(input->mouse_left))
if (FP_DEVELOPER_MODE && TELY_OSInput_KeyIsReleased(input->mouse_left))
game->play.clicked_entity = game->play.prev_active_entity;
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Escape))
if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_Escape))
game->play.state = FP_GameState_Pause;
if (FP_DEVELOPER_MODE && game->play.clicked_entity.id) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Delete))
if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_Delete))
FP_Game_DeleteEntity(game, game->play.clicked_entity);
}
DQN_MSVC_WARNING_POP
@ -1347,8 +1341,8 @@ static void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput
// NOTE: Gamepad movement input
if (controls->mode == FP_GameControlMode_Gamepad) {
dir_vector.x += input->left_stick[controls->gamepad_index].x;
dir_vector.y += input->left_stick[controls->gamepad_index].y;
TELY_OSInputGamepad *gamepad = input->gamepads + controls->gamepad_index;
dir_vector += gamepad->left_stick;
}
// TODO(doyle): Some bug, diagonal is still faster
@ -1945,7 +1939,7 @@ static void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput
// NOTE: Tick the state machine
// NOTE: This can delete the entity! Take caution
FP_GameEntityHandle entity_handle = entity->handle;
FP_EntityActionStateMachine(game, &platform->audio, input, entity, &acceleration_meters_per_s);
FP_EntityActionStateMachine(game, &os->audio, input, entity, &acceleration_meters_per_s);
// NOTE: Limit the entity to within bounds of the camera only in multiplayer ===========
bool entity_is_oob_with_camera = false;
@ -2304,7 +2298,7 @@ static void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput
// NOTE: Clamp camera to map bounds ============================================================
{
Dqn_V2 window_size = Dqn_V2_InitV2I(platform->core.window_size);
Dqn_V2 window_size = Dqn_V2_InitV2I(os->core.window_size);
camera->scale = window_size / camera->size;
Dqn_V2 camera_size_screen = camera->size * camera->scale;
@ -2323,27 +2317,27 @@ static void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput
Dqn_Profiler_EndZone(update_zone);
}
static Dqn_Str8 FP_ScanCodeToLabel(Dqn_Arena *arena, TELY_PlatformInputScanCode scan_code)
static Dqn_Str8 FP_ScanKeyToLabel(Dqn_Arena *arena, TELY_OSInputScanKey scan_key)
{
Dqn_Str8 result = {};
Dqn_Allocator allocator = Dqn_Arena_Allocator(arena);
if (scan_code >= TELY_PlatformInputScanCode_A && scan_code <= TELY_PlatformInputScanCode_Z) {
char scan_code_ch = DQN_CAST(char)('A' + (scan_code - TELY_PlatformInputScanCode_A));
result = Dqn_Str8_InitF(allocator, "[%c]", scan_code_ch);
if (scan_key >= TELY_OSInputScanKey_A && scan_key <= TELY_OSInputScanKey_Z) {
char scan_key_ch = DQN_CAST(char)('A' + (scan_key - TELY_OSInputScanKey_A));
result = Dqn_Str8_InitF(allocator, "[%c]", scan_key_ch);
} else {
if (scan_code == TELY_PlatformInputScanCode_Up) {
if (scan_key == TELY_OSInputScanKey_Up) {
result = Dqn_Str8_InitF(allocator, "[Up]");
} else if (scan_code == TELY_PlatformInputScanCode_Down) {
} else if (scan_key == TELY_OSInputScanKey_Down) {
result = Dqn_Str8_InitF(allocator, "[Down]");
} else if (scan_code == TELY_PlatformInputScanCode_Left) {
} else if (scan_key == TELY_OSInputScanKey_Left) {
result = Dqn_Str8_InitF(allocator, "[Left]");
} else if (scan_code == TELY_PlatformInputScanCode_Right) {
} else if (scan_key == TELY_OSInputScanKey_Right) {
result = Dqn_Str8_InitF(allocator, "[Right]");
} else if (scan_code == TELY_PlatformInputScanCode_Semicolon) {
} else if (scan_key == TELY_OSInputScanKey_Semicolon) {
result = Dqn_Str8_InitF(allocator, "[;]");
} else if (scan_code == TELY_PlatformInputScanCode_Apostrophe) {
} else if (scan_key == TELY_OSInputScanKey_Apostrophe) {
result = Dqn_Str8_InitF(allocator, "[']");
} else if (scan_code == TELY_PlatformInputScanCode_Backslash) {
} else if (scan_key == TELY_OSInputScanKey_Backslash) {
result = Dqn_Str8_InitF(allocator, "[/]");
}
}
@ -2366,20 +2360,20 @@ static void FP_DrawBillboardKeyBindHint(TELY_Renderer *renderer,
if (mode == FP_GameControlMode_Gamepad) {
Dqn_Str8 tex_name = {};
if (key_bind.gamepad_key == TELY_PlatformInputGamepadKey_A)
if (key_bind.gamepad_key == TELY_OSInputGamepadKey_A)
tex_name = g_anim_names.merchant_button_a;
else if (key_bind.gamepad_key == TELY_PlatformInputGamepadKey_B)
else if (key_bind.gamepad_key == TELY_OSInputGamepadKey_B)
tex_name = g_anim_names.merchant_button_b;
else if (key_bind.gamepad_key == TELY_PlatformInputGamepadKey_X)
else if (key_bind.gamepad_key == TELY_OSInputGamepadKey_X)
tex_name = g_anim_names.merchant_button_x;
else if (key_bind.gamepad_key == TELY_PlatformInputGamepadKey_Y)
else if (key_bind.gamepad_key == TELY_OSInputGamepadKey_Y)
tex_name = g_anim_names.merchant_button_y;
if (tex_name.size) {
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, tex_name);
Dqn_Rect button_rect = game->atlas_sprite_sheet.rects.data[anim->index];
Dqn_V2 text_size = TELY_Asset_MeasureText(TELY_Render_Font(renderer, assets), player_prefix);
Dqn_V2 text_size = TELY_Asset_MeasureText(assets, TELY_Render_ActiveFont(renderer), player_prefix);
TELY_Render_Text(renderer, draw_p, Dqn_V2_InitNx2(0, +1.f), player_prefix);
Dqn_Rect gamepad_btn_rect = {};
@ -2395,22 +2389,22 @@ static void FP_DrawBillboardKeyBindHint(TELY_Renderer *renderer,
TELY_COLOUR_WHITE_V4);
}
} else {
Dqn_Str8 key_bind_label = FP_ScanCodeToLabel(scratch.arena, key_bind.scan_code);
Dqn_Str8 key_bind_label = FP_ScanKeyToLabel(scratch.arena, key_bind.scan_key);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_InitNx2(0, +1.f), "%.*s%.*s", DQN_STR_FMT(player_prefix), DQN_STR_FMT(key_bind_label));
}
}
static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer, TELY_Audio *audio)
static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_Audio *audio)
{
Dqn_Profiler_ZoneScopeWithIndex("FP_Render", FP_ProfileZone_FPRender);
TELY_PlatformInput *input = &platform->input;
TELY_OSInput *input = &os->input;
TELY_RFui *rfui = &game->rfui;
TELY_Assets *assets = &platform->assets;
TELY_Assets *assets = &os->assets;
TELY_Render_ClearColourV3(renderer, TELY_COLOUR_BLACK_MIDNIGHT_V4.rgb);
TELY_Render_PushFont(renderer, game->jetbrains_mono_font);
TELY_RFui_FrameSetup(rfui, &platform->frame_arena);
TELY_RFui_PushFont(rfui, game->jetbrains_mono_font);
TELY_Render_PushFontSize(renderer, game->jetbrains_mono_font, game->font_size);
TELY_RFui_FrameSetup(rfui, &os->frame_arena);
TELY_RFui_PushFontSize(rfui, game->jetbrains_mono_font, game->font_size);
FP_GameCamera shake_camera = game->play.camera;
{
@ -2441,18 +2435,18 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
Dqn_V2 world_mouse_p = Dqn_M2x3_MulV2(camera_xforms.view_model, input->mouse_p);
// NOTE: Draw tiles ============================================================================
Dqn_usize tile_count_x = DQN_CAST(Dqn_usize)(platform->core.window_size.w / game->play.tile_size);
Dqn_usize tile_count_y = DQN_CAST(Dqn_usize)(platform->core.window_size.h / game->play.tile_size);
Dqn_usize tile_count_x = DQN_CAST(Dqn_usize)(os->core.window_size.w / game->play.tile_size);
Dqn_usize tile_count_y = DQN_CAST(Dqn_usize)(os->core.window_size.h / game->play.tile_size);
for (Dqn_usize x = 0; x < tile_count_x; x++) {
Dqn_V2 start = Dqn_V2_InitNx2((x + 1) * game->play.tile_size, 0);
Dqn_V2 end = Dqn_V2_InitNx2(start.x, platform->core.window_size.h);
Dqn_V2 end = Dqn_V2_InitNx2(start.x, os->core.window_size.h);
TELY_Render_LineColourV4(renderer, start, end, TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, .25f), 1.f);
}
for (Dqn_usize y = 0; y < tile_count_y; y++) {
Dqn_V2 start = Dqn_V2_InitNx2(0, (y + 1) * game->play.tile_size);
Dqn_V2 end = Dqn_V2_InitNx2(platform->core.window_size.w, start.y);
Dqn_V2 end = Dqn_V2_InitNx2(os->core.window_size.w, start.y);
TELY_Render_LineColourV4(renderer, start, end, TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, .25f), 1.f);
}
@ -2798,7 +2792,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
if (game->play.hot_entity == entity->handle) {
if (entity->name.size) {
Dqn_V2I player_tile = Dqn_V2I_InitNx2(world_pos.x / game->play.tile_size, world_pos.y / game->play.tile_size);
Dqn_f32 line_height = TELY_Render_FontHeight(renderer, &platform->assets);
Dqn_f32 line_height = TELY_Render_FontSize(renderer) * os->core.dpi_scale;
Dqn_V2 draw_p = world_mouse_p;
TELY_Render_TextF(renderer, draw_p, Dqn_V2_InitNx2(0.f, 1), "%.*s", DQN_STR_FMT(entity->name)); draw_p.y += line_height;
TELY_Render_TextF(renderer, draw_p, Dqn_V2_InitNx2(0.f, 1), "World Pos: (%.1f, %.1f)", world_pos.x, world_pos.y); draw_p.y += line_height;
@ -2818,7 +2812,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
if (entity->type == FP_EntityType_Billboard) {
TELY_Render_PushFont(renderer, game->talkco_font);
TELY_Render_PushFontSize(renderer, game->talkco_font, game->font_size);
DQN_DEFER { TELY_Render_PopFont(renderer); };
DQN_FOR_UINDEX (player_index, game->play.players.size) {
FP_GameEntityHandle player_handle = game->play.players.data[player_index];
@ -2828,7 +2822,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
switch (state) {
case FP_EntityBillboardState_Attack: {
Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.6f, 0.2f));
draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index;
draw_p.y += TELY_Render_FontSize(renderer) * player_index * os->core.dpi_scale;
TELY_Render_PushColourV4(renderer, colour_accent_yellow);
FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->attack, draw_p, true /*draw_player_prefix*/);
TELY_Render_PopColourV4(renderer);
@ -2836,7 +2830,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
case FP_EntityBillboardState_Dash: {
Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.505f, -0.08f));
draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index;
draw_p.y += TELY_Render_FontSize(renderer) * player_index * os->core.dpi_scale;
TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0xFFE726));
FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->dash, draw_p, true /*draw_player_prefix*/);
TELY_Render_PopColourV4(renderer);
@ -2847,7 +2841,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
case FP_EntityBillboardState_RangeAttack: {
Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.20f, -0.13f));
draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index;
draw_p.y += TELY_Render_FontSize(renderer) * player_index * os->core.dpi_scale;
TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0x364659));
FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->range_attack, draw_p, true /*draw_player_prefix*/);
TELY_Render_PopColourV4(renderer);
@ -2855,7 +2849,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
case FP_EntityBillboardState_Strafe: {
Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.36f, -0.15f));
draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index;
draw_p.y += TELY_Render_FontSize(renderer) * player_index * os->core.dpi_scale;
TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0xFF68A8));
FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->strafe, draw_p, true /*draw_player_prefix*/);
TELY_Render_PopColourV4(renderer);
@ -2863,25 +2857,25 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
case FP_EntityBillboardState_Build: {
Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.065f, 0.2f));
draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index;
draw_p.y += TELY_Render_FontSize(renderer) * player_index * os->core.dpi_scale;
TELY_Render_PushColourV4(renderer, colour_accent_yellow);
FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->build_mode, draw_p, true /*draw_player_prefix*/);
TELY_Render_PopColourV4(renderer);
draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.35f, 0.2f));
draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index;
draw_p.y += TELY_Render_FontSize(renderer) * player_index * os->core.dpi_scale;
TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0xFF68A8));
FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->move_building_ui_cursor_left, draw_p, true /*draw_player_prefix*/);
TELY_Render_PopColourV4(renderer);
draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.44f, 0.2f));
draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index;
draw_p.y += TELY_Render_FontSize(renderer) * player_index * os->core.dpi_scale;
TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0xFF68A8));
FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->move_building_ui_cursor_right, draw_p, false /*draw_player_prefix*/);
TELY_Render_PopColourV4(renderer);
draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.665f, 0.2f));
draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index;
draw_p.y += TELY_Render_FontSize(renderer) * player_index * os->core.dpi_scale;
TELY_Render_PushColourV4(renderer, TELY_COLOUR_BLACK_V4);
FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->attack, draw_p, true /*draw_player_prefix*/);
TELY_Render_PopColourV4(renderer);
@ -2899,7 +2893,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
// NOTE: Shake the world ===================================================================
Dqn_Rect window_rect = {};
window_rect.size = Dqn_V2_InitV2I(platform->core.window_size);
window_rect.size = Dqn_V2_InitV2I(os->core.window_size);
Dqn_f32 tex_scalar = {};
{
@ -3007,7 +3001,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
Dqn_V2 const player_avatar_base_pos[] = {
Dqn_V2_InitNx1(32.f),
Dqn_V2_InitNx2(platform->core.window_size.x - 320.f, 32.f),
Dqn_V2_InitNx2(os->core.window_size.x - 320.f, 32.f),
};
DQN_ASSERT(game->play.players.size <= DQN_ARRAY_UCOUNT(player_avatar_base_pos));
@ -3015,7 +3009,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
if (game->play.players.size == 1) {
// NOTE: We show the Press <BTN> to join for the remaining 2nd player
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
TELY_Render_PushFont(renderer, game->talkco_font);
TELY_Render_PushFontSize(renderer, game->talkco_font, game->font_size);
DQN_DEFER {
TELY_Render_PopFont(renderer);
TELY_Render_PopTransform(renderer);
@ -3028,7 +3022,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
else
join_game_key = DQN_STR8("<Gamepad: B>");
Dqn_f32 font_height = TELY_Render_FontHeight(renderer, assets);
Dqn_f32 font_height = TELY_Render_FontSize(renderer) * os->core.dpi_scale;
Dqn_V2 base_p = player_avatar_base_pos[game->play.players.size];
TELY_Render_TextF(renderer, base_p, Dqn_V2_Zero, "Press %.*s", DQN_STR_FMT(join_game_key)); base_p.y += font_height;
FP_ListenForNewPlayer(input, game);
@ -3144,7 +3138,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
TELY_Render_PushColourV4(renderer, TELY_COLOUR_BLACK_V4);
TELY_Render_PushFont(renderer, game->talkco_font_large);
TELY_Render_PushFontSize(renderer, game->talkco_font, game->large_talkco_font_size);
DQN_DEFER {
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
@ -3180,10 +3174,10 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
0.f /*rotation*/,
tex_mod_colour);
} else {
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
TELY_AssetFont const *font = TELY_Render_Font(renderer, assets);
Dqn_Str8 key_bind_label = FP_ScanCodeToLabel(scratch.arena, key_bind.scan_code);
interact_btn_rect.size = TELY_Asset_MeasureText(font, key_bind_label);
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
TELY_AssetFontSizeHandle font_size = TELY_Render_ActiveFont(renderer);
Dqn_Str8 key_bind_label = FP_ScanKeyToLabel(scratch.arena, key_bind.scan_key);
interact_btn_rect.size = TELY_Asset_MeasureText(assets, font_size, key_bind_label);
Dqn_Rect key_bind_rect = interact_btn_rect;
key_bind_rect.pos.y += interact_btn_rect.size.y * .3f;
@ -3204,13 +3198,13 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
bool trigger_buy_anim = false;
if (have_enough_coins) {
if (TELY_Platform_InputScanCodeIsPressed(input, key_bind.scan_code)) {
if (TELY_OSInput_ScanKeyIsPressed(input, key_bind.scan_key)) {
game->play.player_trigger_purchase_building_timestamp = game->play.clock_ms + buy_duration_ms;
} else if (TELY_Platform_InputScanCodeIsDown(input, key_bind.scan_code)) {
} else if (TELY_OSInput_ScanKeyIsDown(input, key_bind.scan_key)) {
trigger_buy_anim = true;
if (game->play.clock_ms > game->play.player_trigger_purchase_building_timestamp)
game->play.player_trigger_purchase_building_timestamp = game->play.clock_ms;
} else if (TELY_Platform_InputScanCodeIsReleased(input, key_bind.scan_code)) {
} else if (TELY_OSInput_ScanKeyIsReleased(input, key_bind.scan_key)) {
if (game->play.clock_ms > game->play.player_trigger_purchase_building_timestamp) {
if (mapping.inventory_count) {
player->coins -= *mapping.building_base_price;
@ -3295,13 +3289,13 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
0.f /*rotation*/,
tex_mod_colour);
} else {
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
TELY_AssetFont const *font = TELY_Render_Font(renderer, assets);
Dqn_Str8 key_bind_label = FP_ScanCodeToLabel(scratch.arena, key_bind.scan_code);
interact_btn_rect.size = TELY_Asset_MeasureText(font, key_bind_label);
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
TELY_AssetFontSizeHandle font_size = TELY_Render_ActiveFont(renderer);
Dqn_Str8 key_bind_label = FP_ScanKeyToLabel(scratch.arena, key_bind.scan_key);
interact_btn_rect.size = TELY_Asset_MeasureText(assets, font_size, key_bind_label);
Dqn_Rect key_bind_rect = interact_btn_rect;
key_bind_rect.pos.y += interact_btn_rect.size.y * .3f;
Dqn_Rect key_bind_rect = interact_btn_rect;
key_bind_rect.pos.y += interact_btn_rect.size.y * .3f;
TELY_Render_RectColourV4(renderer, Dqn_Rect_Expand(key_bind_rect, 2.f), TELY_RenderShapeMode_Fill, TELY_Colour_V4Alpha(keybind_btn_shadow_colour, tex_mod_colour.a));
TELY_Render_PushColourV4(renderer, TELY_Colour_V4Alpha(colour_accent_yellow, tex_mod_colour.a));
@ -3336,13 +3330,13 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
bool trigger_buy_anim = false;
if (have_enough_coins) {
if (TELY_Platform_InputScanCodeIsPressed(input, key_bind.scan_code)) {
if (TELY_OSInput_ScanKeyIsPressed(input, key_bind.scan_key)) {
game->play.player_trigger_purchase_upgrade_timestamp = game->play.clock_ms + buy_duration_ms;
} else if (TELY_Platform_InputScanCodeIsDown(input, key_bind.scan_code)) {
} else if (TELY_OSInput_ScanKeyIsDown(input, key_bind.scan_key)) {
trigger_buy_anim = true;
if (game->play.clock_ms > game->play.player_trigger_purchase_upgrade_timestamp)
game->play.player_trigger_purchase_upgrade_timestamp = game->play.clock_ms;
} else if (TELY_Platform_InputScanCodeIsReleased(input, key_bind.scan_code)) {
} else if (TELY_OSInput_ScanKeyIsReleased(input, key_bind.scan_key)) {
if (game->play.clock_ms > game->play.player_trigger_purchase_upgrade_timestamp) {
player->coins -= *mapping.upgrade_base_price;
*mapping.upgrade_base_price *= 1;
@ -3411,11 +3405,11 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
0.f,
TELY_COLOUR_WHITE_V4);
TELY_Render_PushFont(renderer, game->talkco_font);
TELY_Render_PushFontSize(renderer, game->talkco_font, game->font_size);
DQN_DEFER { TELY_Render_PopFont(renderer); };
next_pos = Dqn_Rect_InterpolatedPoint(player_avatar_rect, Dqn_V2_InitNx2(1.f, 0));
Dqn_f32 font_height = TELY_Render_FontHeight(renderer, &platform->assets);
Dqn_f32 font_height = TELY_Render_FontSize(renderer) * os->core.dpi_scale;
// NOTE: Health bar ====================================================
Dqn_f32 bar_height = font_height * .75f;
@ -3677,7 +3671,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
else if (building.type == FP_EntityType_ChurchTerry)
building_count = player->inventory.churchs;
TELY_Render_PushFont(renderer, game->talkco_font);
TELY_Render_PushFontSize(renderer, game->talkco_font, game->font_size);
DQN_DEFER { TELY_Render_PopFont(renderer); };
Dqn_V2 label_p = Dqn_Rect_InterpolatedPoint(rect, Dqn_V2_InitNx2(0.5f, 1.25f));
@ -3694,7 +3688,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
TELY_Render_PushFont(renderer, game->talkco_font_large);
TELY_Render_PushFontSize(renderer, game->talkco_font, game->large_talkco_font_size);
DQN_DEFER { TELY_Render_PopFont(renderer); };
uint64_t time_until_next_wave_ms = 0;
@ -3704,7 +3698,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
}
Dqn_f32 mid_x = platform->core.window_size.x * .5f;
Dqn_f32 mid_x = os->core.window_size.x * .5f;
if (time_until_next_wave_ms) {
TELY_Render_TextF(renderer,
Dqn_V2_InitNx2(mid_x, first_player_avatar_rect.pos.y),
@ -3721,13 +3715,13 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
Dqn_f32 font_height = TELY_Render_FontHeight(renderer, assets);
Dqn_f32 bar_height = font_height * 1.25f;
Dqn_f32 font_height = TELY_Render_FontSize(renderer) * os->core.dpi_scale;
Dqn_f32 bar_height = font_height * 1.25f;
{
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.heart);
FP_GameEntity *heart = FP_Game_GetEntity(game, game->play.heart);
Dqn_f32 max_width = platform->core.window_size.x * .5f;
Dqn_V2 draw_p = Dqn_V2_InitNx2(platform->core.window_size.x * .25f, first_player_avatar_rect.pos.y + bar_height);
Dqn_f32 max_width = os->core.window_size.x * .5f;
Dqn_V2 draw_p = Dqn_V2_InitNx2(os->core.window_size.x * .25f, first_player_avatar_rect.pos.y + bar_height);
Dqn_f32 health_t = heart->hp / DQN_CAST(Dqn_f32)heart->hp_cap;
Dqn_Rect health_rect = Dqn_Rect_InitNx4(draw_p.x, draw_p.y, max_width, bar_height);
Dqn_Rect curr_health_rect = Dqn_Rect_InitNx4(draw_p.x, draw_p.y, max_width * health_t, bar_height);
@ -3755,7 +3749,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
0.f /*rotation*/,
TELY_COLOUR_WHITE_V4);
TELY_Render_PushFont(renderer, game->talkco_font_large);
TELY_Render_PushFontSize(renderer, game->talkco_font, game->large_talkco_font_size);
DQN_DEFER { TELY_Render_PopFont(renderer); };
TELY_Render_TextF(renderer, Dqn_Rect_InterpolatedPoint(heart_icon_rect, Dqn_V2_InitNx2(1.f, 0.65f)), Dqn_V2_Zero, "Terry's Heart");
}
@ -3772,7 +3766,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
// NOTE: Add scanlines into the game for A E S T H E T I C S ===================================
if (game->play.state == FP_GameState_Play) {
Dqn_V2 screen_size = Dqn_V2_InitNx2(platform->core.window_size.w, platform->core.window_size.h);
Dqn_V2 screen_size = Dqn_V2_InitNx2(os->core.window_size.w, os->core.window_size.h);
Dqn_f32 scanline_gap = 4.0f;
Dqn_f32 scanline_thickness = 3.0f;
FP_GameRenderScanlines(renderer, scanline_gap, scanline_thickness, screen_size);
@ -3784,7 +3778,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
Dqn_V2I inset = platform->core.window_size * .05f;
Dqn_V2I inset = os->core.window_size * .05f;
Dqn_f32 min_inset = DQN_CAST(Dqn_f32)DQN_MIN(inset.x, inset.y);
Dqn_V2 draw_p = Dqn_V2_InitNx2(min_inset, min_inset);
@ -3793,11 +3787,11 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
Dqn_V4 bg_colour = TELY_Colour_V4InitRGBAU32(0x301010FF); // NOTE: Maroon
TELY_Render_RectColourV4(
renderer,
Dqn_Rect_InitNx4(0, 0, DQN_CAST(Dqn_f32)platform->core.window_size.x, DQN_CAST(Dqn_f32)platform->core.window_size.y),
Dqn_Rect_InitNx4(0, 0, DQN_CAST(Dqn_f32)os->core.window_size.x, DQN_CAST(Dqn_f32)os->core.window_size.y),
TELY_RenderShapeMode_Fill,
bg_colour);
Dqn_Rect window_rect = Dqn_Rect_InitNx4(0, 0, DQN_CAST(Dqn_f32)platform->core.window_size.w, DQN_CAST(Dqn_f32)platform->core.window_size.h);
Dqn_Rect window_rect = Dqn_Rect_InitNx4(0, 0, DQN_CAST(Dqn_f32)os->core.window_size.w, DQN_CAST(Dqn_f32)os->core.window_size.h);
if (game->play.state == FP_GameState_IntroScreen || game->play.state == FP_GameState_LoseGame) {
Dqn_f32 tex_scalar = 0.f;
{
@ -3892,7 +3886,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
TELY_COLOUR_WHITE_V4);
}
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_PushFontSize(renderer, game->inter_regular_font, game->font_size);
Dqn_f32 t = (DQN_SINF(DQN_CAST(Dqn_f32)input->timer_s * 5.f) + 1.f) / 2.f;
TELY_Render_PushColourV4(renderer, TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, t));
TELY_Render_TextF(renderer, Dqn_Rect_InterpolatedPoint(window_rect, Dqn_V2_InitNx2(0.5f, 0.925f)), Dqn_V2_InitNx1(0.5f), "Press <B> or <Gamepad: Start> to %s", game->play.state == FP_GameState_IntroScreen ? "start" : "restart");
@ -3901,37 +3895,37 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
TELY_Render_PopFont(renderer);
if (game->play.state == FP_GameState_LoseGame)
FP_PlayReset(game, platform);
FP_PlayReset(game, os);
if (FP_ListenForNewPlayer(input, game))
game->play.state = FP_GameState_Play;
} else if (game->play.state == FP_GameState_Pause) {
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Paused"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PushFontSize(renderer, game->inter_regular_font, game->large_font_size);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Paused"); draw_p.y += TELY_Render_FontSize(renderer) * os->core.dpi_scale;
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to resume"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PushFontSize(renderer, game->inter_regular_font, game->font_size);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to resume"); draw_p.y += TELY_Render_FontSize(renderer) * os->core.dpi_scale;
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_Return))
game->play.state = FP_GameState_Play;
} else {
DQN_ASSERT(game->play.state == FP_GameState_WinGame);
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Terry has been saved"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "from his terrible calamity"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PushFontSize(renderer, game->inter_regular_font, game->large_font_size);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Terry has been saved"); draw_p.y += TELY_Render_FontSize(renderer) * os->core.dpi_scale;
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "from his terrible calamity"); draw_p.y += TELY_Render_FontSize(renderer) * os->core.dpi_scale;
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "He lives for yet another day and another love"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to restart"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PushFontSize(renderer, game->inter_regular_font, game->font_size);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "He lives for yet another day and another love"); draw_p.y += TELY_Render_FontSize(renderer) * os->core.dpi_scale;
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to restart"); draw_p.y += TELY_Render_FontSize(renderer) * os->core.dpi_scale;
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
FP_PlayReset(game, platform);
if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_Return))
FP_PlayReset(game, os);
}
Dqn_f32 scanline_gap = 4.0f;
@ -3978,7 +3972,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
// NOTE: Debug UI ==============================================================================
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F1))
if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F1))
game->play.debug_ui = !game->play.debug_ui;
DQN_MSVC_WARNING_PUSH
@ -4009,7 +4003,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
info_column.widget->semantic_position[TELY_RFuiAxis_X].kind = TELY_RFuiPositionKind_Absolute;
info_column.widget->semantic_position[TELY_RFuiAxis_X].value = next_y;
info_column.widget->semantic_position[TELY_RFuiAxis_Y].kind = TELY_RFuiPositionKind_Absolute;
info_column.widget->semantic_position[TELY_RFuiAxis_Y].value = platform->core.window_size.h - TELY_Render_FontHeight(renderer, assets);
info_column.widget->semantic_position[TELY_RFuiAxis_Y].value = os->core.window_size.h - TELY_Render_FontSize(renderer) * os->core.dpi_scale;
{
TELY_RFuiResult row = TELY_RFui_Row(rfui, DQN_STR8("Info Bar"));
@ -4021,19 +4015,19 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
builder.allocator = scratch.allocator;
Dqn_Str8Builder_AppendF(&builder, "TELY");
if (Dqn_Str8_IsValid(platform->core.os_name)) {
Dqn_Str8Builder_AppendF(&builder, " | %.*s", DQN_STR_FMT(platform->core.os_name));
if (Dqn_Str8_IsValid(os->core.os_name)) {
Dqn_Str8Builder_AppendF(&builder, " | %.*s", DQN_STR_FMT(os->core.os_name));
}
Dqn_Str8Builder_AppendF(&builder,
" | %dx%d %.1fHz | TSC %.1f GHz",
platform->core.window_size.w,
platform->core.window_size.h,
platform->core.display.refresh_rate,
platform->core.tsc_per_second / 1'000'000'000.0);
os->core.window_size.w,
os->core.window_size.h,
os->core.display.refresh_rate,
os->core.tsc_per_second / 1'000'000'000.0);
if (platform->core.ram_mb)
Dqn_Str8Builder_AppendF(&builder, " | RAM %.1fGB", platform->core.ram_mb / 1024.0);
if (os->core.ram_mb)
Dqn_Str8Builder_AppendF(&builder, " | RAM %.1fGB", os->core.ram_mb / 1024.0);
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(6272 6271)
@ -4059,23 +4053,23 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
if (TELY_RFui_ButtonF(rfui, "F1 Debug info").clicked)
game->play.debug_ui = !game->play.debug_ui;
if (TELY_RFui_ButtonF(rfui, "F2 Add coins x10,000").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F2)) {
if (TELY_RFui_ButtonF(rfui, "F2 Add coins x10,000").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F2)) {
for (FP_GameEntityHandle player_handle : game->play.players) {
FP_GameEntity *player = FP_Game_GetEntity(game, player_handle);
player->coins += 10'000;
}
}
if (TELY_RFui_ButtonF(rfui, "F3 Win game").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F3))
if (TELY_RFui_ButtonF(rfui, "F3 Win game").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F3))
game->play.state = FP_GameState_WinGame;
if (TELY_RFui_ButtonF(rfui, "F4 Lose game").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F4))
if (TELY_RFui_ButtonF(rfui, "F4 Lose game").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F4))
game->play.state = FP_GameState_LoseGame;
if (TELY_RFui_ButtonF(rfui, "F5 Reset game").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F5))
FP_PlayReset(game, platform);
if (TELY_RFui_ButtonF(rfui, "F5 Reset game").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F5))
FP_PlayReset(game, os);
if (TELY_RFui_ButtonF(rfui, "F6 Increase health").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F6)) {
if (TELY_RFui_ButtonF(rfui, "F6 Increase health").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F6)) {
for (FP_GameEntityHandle player_handle : game->play.players) {
FP_GameEntity *player = FP_Game_GetEntity(game, player_handle);
player->hp_cap += FP_DEFAULT_DAMAGE;
@ -4083,7 +4077,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
}
if (TELY_RFui_ButtonF(rfui, "F7 Increase stamina").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F7)) {
if (TELY_RFui_ButtonF(rfui, "F7 Increase stamina").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F7)) {
for (FP_GameEntityHandle player_handle : game->play.players) {
FP_GameEntity *player = FP_Game_GetEntity(game, player_handle);
player->stamina_cap += DQN_CAST(uint16_t)(FP_TERRY_DASH_STAMINA_COST * .5f);
@ -4091,7 +4085,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
}
if (TELY_RFui_ButtonF(rfui, "F8 Increase mobile data").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F8)) {
if (TELY_RFui_ButtonF(rfui, "F8 Increase mobile data").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F8)) {
for (FP_GameEntityHandle player_handle : game->play.players) {
FP_GameEntity *player = FP_Game_GetEntity(game, player_handle);
player->terry_mobile_data_plan_cap += DQN_KILOBYTES(1);
@ -4099,10 +4093,10 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
}
if (TELY_RFui_ButtonF(rfui, "F9 %s god mode", game->play.god_mode ? "Disable" : "Enable").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F9))
if (TELY_RFui_ButtonF(rfui, "F9 %s god mode", game->play.god_mode ? "Disable" : "Enable").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F9))
game->play.god_mode = !game->play.god_mode;
if (TELY_RFui_ButtonF(rfui, "F11 Building inventory +1").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F11)) {
if (TELY_RFui_ButtonF(rfui, "F11 Building inventory +1").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F11)) {
for (FP_GameEntityHandle player_handle : game->play.players) {
FP_GameEntity *player = FP_Game_GetEntity(game, player_handle);
player->inventory.clubs += 1;
@ -4112,7 +4106,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
}
if (TELY_RFui_ButtonF(rfui, "1 %s HUD", game->play.debug_hide_hud ? "Show" : "Hide").clicked || TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_1))
if (TELY_RFui_ButtonF(rfui, "1 %s HUD", game->play.debug_hide_hud ? "Show" : "Hide").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_1))
game->play.debug_hide_hud = !game->play.debug_hide_hud;
if (TELY_RFui_ButtonF(rfui, "%s bounding rects", game->play.debug_hide_bounding_rectangles ? "Show" : "Hide").clicked)
@ -4123,7 +4117,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
if (0) {
next_y += TELY_Asset_GetFont(assets, TELY_RFui_ActiveFont(rfui))->pixel_height;
next_y += TELY_RFui_ActiveFont(rfui).size;
TELY_RFuiResult bar = TELY_RFui_Column(rfui, DQN_STR8("Memory bar"));
bar.widget->semantic_position[TELY_RFuiAxis_X].kind = TELY_RFuiPositionKind_Absolute;
bar.widget->semantic_position[TELY_RFuiAxis_X].value = 10.f;
@ -4134,23 +4128,23 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
DQN_DEFER { TELY_RFui_PopParent(rfui); };
{
Dqn_ArenaInfo arena_info = Dqn_Arena_Info(&platform->arena);
Dqn_ArenaInfo arena_info = Dqn_Arena_Info(&os->arena);
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(6271) // warning C6271: Extra argument passed to 'TELY_RFui_TextF'.
TELY_RFui_TextF(rfui,
"Platform Arena[%I64u]: %_$$d/%_$$d (HWM %_$$d, COMMIT %_$$d)",
platform->arena.blocks,
os->arena.blocks,
arena_info.used,
arena_info.capacity,
arena_info.used_hwm,
arena_info.commit);
DQN_MSVC_WARNING_POP
next_y += TELY_Asset_GetFont(assets, TELY_RFui_ActiveFont(rfui))->pixel_height;
next_y += TELY_RFui_ActiveFont(rfui).size;
}
for (Dqn_ArenaCatalogItem *item = g_dqn_library->arena_catalog.sentinel.next; item != &g_dqn_library->arena_catalog.sentinel; item = item->next) {
if (item != g_dqn_library->arena_catalog.sentinel.next)
next_y += TELY_Asset_GetFont(assets, TELY_RFui_ActiveFont(rfui))->pixel_height;
next_y += TELY_RFui_ActiveFont(rfui).size;
Dqn_Arena *arena = item->arena;
Dqn_ArenaInfo arena_info = Dqn_Arena_Info(arena);
@ -4170,7 +4164,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
// NOTE: Profiler
if (0) {
next_y += TELY_Asset_GetFont(assets, TELY_RFui_ActiveFont(rfui))->pixel_height;
next_y += TELY_RFui_ActiveFont(rfui).size;
TELY_RFuiResult profiler_layout = TELY_RFui_Column(rfui, DQN_STR8("Profiler Bar"));
profiler_layout.widget->semantic_position[TELY_RFuiAxis_X].kind = TELY_RFuiPositionKind_Absolute;
profiler_layout.widget->semantic_position[TELY_RFuiAxis_X].value = 10.f;
@ -4181,9 +4175,9 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
DQN_DEFER { TELY_RFui_PopParent(rfui); };
// TODO(doyle): On emscripten we need to use Dqn_OS_PerfCounterNow() however those
// require OS functions which need to be exposed into the platform layer.
// require OS functions which need to be exposed into the os layer.
#if 0
Dqn_f64 const tsc_frequency = DQN_CAST(Dqn_f64)TELY_Platform_PerfCounterFrequency(&platform->core);
Dqn_f64 const tsc_frequency = DQN_CAST(Dqn_f64)TELY_OS_PerfCounterFrequency(&os->core);
Dqn_ProfilerAnchor *anchors = Dqn_Profiler_AnchorBuffer(Dqn_ProfilerAnchorBuffer_Back);
for (size_t anchor_index = 1; anchor_index < DQN_PROFILER_ANCHOR_BUFFER_SIZE; anchor_index++) {
Dqn_ProfilerAnchor const *anchor = anchors + anchor_index;
@ -4216,14 +4210,13 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren
}
}
FP_DLL_FUNCTION
void TELY_DLL_FrameUpdate(void *user_data)
TELY_OS_DLL_FUNCTION
void TELY_OS_DLLFrameUpdate(TELY_OS *os)
{
TELY_Platform *platform = DQN_CAST(TELY_Platform *) user_data;
TELY_PlatformInput *input = &platform->input;
TELY_Assets *assets = &platform->assets;
TELY_Renderer *renderer = &platform->renderer;
FP_Game *game = DQN_CAST(FP_Game *) platform->user_data;
TELY_OSInput *input = &os->input;
TELY_Assets *assets = &os->assets;
TELY_Renderer *renderer = &os->renderer;
FP_Game *game = DQN_CAST(FP_Game *) os->user_data;
// =============================================================================================
@ -4237,7 +4230,7 @@ void TELY_DLL_FrameUpdate(void *user_data)
// =============================================================================================
TELY_Audio *audio = &platform->audio;
TELY_Audio *audio = &os->audio;
#if 0
if (audio->playback_size == 0) {
@ -4248,7 +4241,7 @@ void TELY_DLL_FrameUpdate(void *user_data)
// =============================================================================================
if (game->play.state == FP_GameState_Play) {
if (TELY_Platform_InputKeyWasDown(input->mouse_left) && TELY_Platform_InputKeyIsDown(input->mouse_left)) {
if (TELY_OSInput_KeyWasDown(input->mouse_left) && TELY_OSInput_KeyIsDown(input->mouse_left)) {
if (game->play.prev_active_entity.id)
game->play.active_entity = game->play.prev_active_entity;
} else {
@ -4268,7 +4261,7 @@ void TELY_DLL_FrameUpdate(void *user_data)
continue;
game->play.hot_entity = entity->handle;
if (TELY_Platform_InputKeyIsPressed(input->mouse_left)) {
if (TELY_OSInput_KeyIsPressed(input->mouse_left)) {
game->play.active_entity = entity->handle;
game->play.clicked_entity = entity->handle;
}
@ -4279,10 +4272,10 @@ void TELY_DLL_FrameUpdate(void *user_data)
for (game->play.delta_s_accumulator += DQN_CAST(Dqn_f32)input->delta_s;
game->play.delta_s_accumulator > FP_GAME_PHYSICS_STEP;
game->play.delta_s_accumulator -= FP_GAME_PHYSICS_STEP) {
FP_Update(platform, game, input, audio);
FP_Update(os, game, input, audio);
}
FP_Render(game, platform, renderer, audio);
FP_Render(game, os, renderer, audio);
TELY_Audio_MixPlaybackSamples(audio, assets);
}

View File

@ -97,7 +97,7 @@ int main(int argc, char const **argv)
dry_run = true;
} else if (arg == DQN_STR8("--web")) {
target_web = true;
} else if (arg == DQN_STR8("--dev-fast-build")) {
} else if (arg == DQN_STR8("--fast-dev-build")) {
dev_fast_build = true;
} else {
PRINT_HELP;
@ -302,14 +302,21 @@ int main(int argc, char const **argv)
DQN_DEFER { feely_pona_no_dll_timings[1] = Dqn_OS_PerfCounterNow(); };
Dqn_CPPBuildCompileFile build_file = {};
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity_nodll.h", DQN_STR_FMT(code_dir));
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir));
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry");
build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STR8("/Tp")});
Dqn_List<Dqn_Str8> compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 16, common_compile_flags);
Dqn_List_AddCArray(&compile_flags, {
DQN_STR8("/D TELY_WITH_PLATFORM"),
DQN_STR8("/D FEELY_PONA_IMPLEMENTATION"),
});
Dqn_CPPBuildContext feely_pona_no_dll_build_context = {};
feely_pona_no_dll_build_context.compiler = Dqn_CPPBuildCompiler_MSVC;
feely_pona_no_dll_build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {build_file});
feely_pona_no_dll_build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, {raylib_dir});
feely_pona_no_dll_build_context.compile_flags = common_compile_flags;
feely_pona_no_dll_build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena);
feely_pona_no_dll_build_context.build_dir = build_dir;
feely_pona_no_dll_build_context.link_flags = feely_pona_platform_link_flags;
@ -329,12 +336,14 @@ int main(int argc, char const **argv)
Dqn_CPPBuildCompileFile build_file = {};
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir));
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "tely_dll_msvc", DQN_STR_FMT(code_dir));
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry_dev_dll");
build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STR8("/Tp")});
Dqn_List<Dqn_Str8> compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 128, common_compile_flags);
Dqn_List_Add(&compile_flags, DQN_STR8("/LD"));
Dqn_List_Add(&compile_flags, DQN_STR8("/Fetely_dll_msvc"));
Dqn_List<Dqn_Str8> compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 16, common_compile_flags);
Dqn_List_AddCArray(&compile_flags, {
DQN_STR8("/LD"),
DQN_STR8("/D FEELY_PONA_IMPLEMENTATION"),
});
if (!dev_fast_build)
Dqn_List_Add(&compile_flags, DQN_STR8("/analyze"));
@ -361,12 +370,15 @@ int main(int argc, char const **argv)
DQN_DEFER { feely_pona_platform_timings[1] = Dqn_OS_PerfCounterNow(); };
Dqn_CPPBuildCompileFile build_file = {};
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/tely_platform_raylib_unity.h", DQN_STR_FMT(tely_dir));
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "feely_pona_msvc", DQN_STR_FMT(code_dir));
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir));
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry_dev", DQN_STR_FMT(code_dir));
build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STR8("/Tp")});
Dqn_List<Dqn_Str8> compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 128, common_compile_flags);
Dqn_List_Add(&compile_flags, DQN_STR8("/Fefeely_pona_msvc"));
Dqn_List_AddCArray(&compile_flags, {
DQN_STR8("/D TELY_WITH_PLATFORM"),
DQN_STR8("/D TELY_WITH_PLATFORM_DLL"),
});
Dqn_CPPBuildContext build_context = {};
build_context.compiler = Dqn_CPPBuildCompiler_MSVC;
@ -380,7 +392,7 @@ int main(int argc, char const **argv)
Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd));
} else {
Dqn_Str8 exe_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_msvc.exe", DQN_STR_FMT(build_dir));
Dqn_Str8 exe_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/terry_cherry_dev_msvc.exe", DQN_STR_FMT(build_dir));
bool exe_is_locked = false;
if (Dqn_Fs_Exists(exe_path)) {
Dqn_FsFile exe_file = Dqn_Fs_OpenFile(exe_path, Dqn_FsFileOpen_OpenIfExist, Dqn_FsFileAccess_Read | Dqn_FsFileAccess_Write);
@ -528,10 +540,10 @@ int main(int argc, char const **argv)
Dqn_CPPBuildContext build_context = {};
build_context.compile_file_obj_suffix = DQN_CPP_BUILD_OBJ_SUFFIX_O;
build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {
Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity_nodll.cpp", DQN_STR_FMT(code_dir)) },
Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.cpp", DQN_STR_FMT(code_dir)) },
});
Dqn_Str8 output_name = DQN_STR8("Terry_Cherry");
Dqn_Str8 output_name = DQN_STR8("Terry_Cherry_Emscripten");
Dqn_List<Dqn_Str8> compile_flags = Dqn_List_InitCArrayCopy(scratch.arena, 32, {
DQN_STR8("cmd"), DQN_STR8("/C"), DQN_STR8("emcc.bat"),
DQN_STR8("-o"), Dqn_Str8_InitF(scratch.allocator, "%.*s.html", DQN_STR_FMT(output_name)),
@ -545,6 +557,8 @@ int main(int argc, char const **argv)
DQN_STR8("--preload-file"), DQN_STR8("Data"),
DQN_STR8("-msimd128"),
DQN_STR8("-msse2"),
DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"),
DQN_STR8("-D"), DQN_STR8("FEELY_PONA_IMPLEMENTATION"),
});
Dqn_List_AddList(&compile_flags, build_specific_compile_flags);
@ -559,7 +573,7 @@ int main(int argc, char const **argv)
}
// NOTE: Move the files to a directory
Dqn_Str8 folder_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s_Emscripten", DQN_STR_FMT(build_dir), DQN_STR_FMT(output_name));
Dqn_Str8 folder_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(output_name));
if (!Dqn_Fs_DirExists(folder_path)) {
Dqn_Str8 mkdir_cmd = Dqn_Str8_InitF(scratch.allocator, "mkdir %.*s", DQN_STR_FMT(folder_path));
Dqn_OS_ExecOrAbort(mkdir_cmd, {});
@ -574,7 +588,7 @@ int main(int argc, char const **argv)
for (Dqn_Str8 file_ext : generated_file_extension) {
Dqn_Str8 src_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(output_name), DQN_STR_FMT(file_ext));
Dqn_Str8 dest_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.%.*s", DQN_STR_FMT(folder_path), DQN_STR_FMT(output_name), DQN_STR_FMT(file_ext));
Dqn_Str8 dest_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Terry_Cherry.%.*s", DQN_STR_FMT(folder_path), DQN_STR_FMT(file_ext));
Dqn_Str8 cmd = Dqn_Str8_InitF(scratch.allocator, "cmd /C move /Y %.*s %.*s", DQN_STR_FMT(src_path), DQN_STR_FMT(dest_path));
if (dry_run) {
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd));

View File

@ -3,24 +3,24 @@
#include "feely_pona_unity.h"
#endif
static bool FP_Game_KeyBindIsPressed(TELY_PlatformInput const *input, FP_GameControls const *controls, FP_GameKeyBind key_bind)
static bool FP_Game_KeyBindIsPressed(TELY_OSInput const *input, FP_GameControls const *controls, FP_GameKeyBind key_bind)
{
bool result = false;
if (controls->mode == FP_GameControlMode_Keyboard) {
result = TELY_Platform_InputScanCodeIsPressed(input, key_bind.scan_code);
result = TELY_OSInput_ScanKeyIsPressed(input, key_bind.scan_key);
} else {
result = TELY_Platform_InputGamepadKeyIsPressed(input, controls->gamepad_index, key_bind.gamepad_key);
result = TELY_OSInput_GamepadKeyIsPressed(input, controls->gamepad_index, key_bind.gamepad_key);
}
return result;
}
static bool FP_Game_KeyBindIsDown(TELY_PlatformInput const *input, FP_GameControls const *controls, FP_GameKeyBind key_bind)
static bool FP_Game_KeyBindIsDown(TELY_OSInput const *input, FP_GameControls const *controls, FP_GameKeyBind key_bind)
{
bool result = false;
if (controls->mode == FP_GameControlMode_Keyboard) {
result = TELY_Platform_InputScanCodeIsDown(input, key_bind.scan_code);
result = TELY_OSInput_ScanKeyIsDown(input, key_bind.scan_key);
} else {
result = TELY_Platform_InputGamepadKeyIsDown(input, controls->gamepad_index, key_bind.gamepad_key);
result = TELY_OSInput_GamepadKeyIsDown(input, controls->gamepad_index, key_bind.gamepad_key);
}
return result;
}

View File

@ -168,8 +168,8 @@ enum FP_GameInGameMenu
struct FP_GameKeyBind
{
TELY_PlatformInputScanCode scan_code;
TELY_PlatformInputGamepadKey gamepad_key;
TELY_OSInputScanKey scan_key;
TELY_OSInputGamepadKey gamepad_key;
};
enum FP_GameControlMode
@ -433,18 +433,20 @@ struct FP_GamePlay
struct FP_Game
{
TELY_AssetFontHandle inter_regular_font_large;
TELY_AssetFontHandle inter_regular_font;
TELY_AssetFontHandle inter_italic_font;
TELY_AssetFontHandle jetbrains_mono_font;
TELY_AssetFontHandle talkco_font;
TELY_AssetFontHandle talkco_font_large;
TELY_AssetFontHandle talkco_font_xlarge;
TELY_AssetAudioHandle audio[FP_GameAudio_Count];
TELY_AssetSpriteSheet atlas_sprite_sheet;
TELY_RFui rfui;
FP_GamePlay play;
Dqn_Arena *frame_arena;
uint16_t font_size;
uint16_t large_font_size;
uint16_t large_talkco_font_size;
uint16_t xlarge_talkco_font_size;
};
struct FP_GameAStarNode

View File

@ -3,7 +3,7 @@
#include "feely_pona_unity.h"
#endif
void FP_UnitTests(TELY_Platform *platform)
void FP_UnitTests(TELY_OS *os)
{
{
uint32_t array[] = {1};
@ -318,9 +318,9 @@ void FP_UnitTests(TELY_Platform *platform)
}
{
Dqn_Arena_TempMemoryScope(&platform->arena);
Dqn_Arena_TempMemoryScope(&os->arena);
TELY_ChunkPool pool = {};
pool.arena = &platform->arena;
pool.arena = &os->arena;
void *bytes16 = TELY_ChunkPool_Alloc(&pool, 16);
TELY_ChunkPool_Dealloc(&pool, bytes16);
@ -346,13 +346,13 @@ void FP_UnitTests(TELY_Platform *platform)
}
// NOTE: Unit test DFS pre-order and post-order walk
Dqn_Arena_TempMemoryScope(&platform->arena);
Dqn_Arena_TempMemoryScope(&os->arena);
TELY_ChunkPool chunk_pool = {};
chunk_pool.arena = &platform->arena;
chunk_pool.arena = &os->arena;
FP_Game *game = Dqn_Arena_New(&platform->arena, FP_Game, Dqn_ZeroMem_Yes);
FP_Game *game = Dqn_Arena_New(&os->arena, FP_Game, Dqn_ZeroMem_Yes);
game->play.chunk_pool = &chunk_pool;
game->play.entities = Dqn_VArray_Init<FP_GameEntity>(&platform->arena, 1024 * 8);
game->play.entities = Dqn_VArray_Init<FP_GameEntity>(&os->arena, 1024 * 8);
game->play.root_entity = Dqn_VArray_Make(&game->play.entities, Dqn_ZeroMem_No);
Dqn_FArray_Add(&game->play.parent_entity_stack, game->play.root_entity->handle);

View File

@ -37,17 +37,17 @@ struct SpriteSpecification
uint16_t frames_per_second;
};
static Dqn_String8 SpriteAnimNameFromFilePath(Dqn_String8 path)
static Dqn_Str8 SpriteAnimNameFromFilePath(Dqn_Str8 path)
{
// NOTE: Enumerate the number of frames for this animation =================================
Dqn_String8 file_name = Dqn_String8_FileNameFromPath(path);
Dqn_String8 file_name_without_extension = Dqn_String8_BinarySplit(file_name, DQN_STRING8(".")).lhs;
Dqn_Str8 file_name = Dqn_Str8_FileNameFromPath(path);
Dqn_Str8 file_name_without_extension = Dqn_Str8_BinarySplit(file_name, DQN_STR8(".")).lhs;
// NOTE: If the sprite is a standalone sprite without any frame suffix (e.g. "_1.png") then
// we accept the entry as the name of the sprite as is.
Dqn_String8 result = {};
Dqn_Str8 result = {};
if (Dqn_Char_IsDigit(file_name_without_extension.data[file_name_without_extension.size - 1])) {
Dqn_String8BinarySplitResult split = Dqn_String8_BinarySplitReverse(file_name_without_extension, DQN_STRING8("_"));
Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplitReverse(file_name_without_extension, DQN_STR8("_"));
result = split.lhs;
} else {
result = file_name_without_extension;
@ -67,26 +67,26 @@ int main(int argc, char const *argv[])
}
// NOTE: Verify some arguments =================================================================
Dqn_String8 atlas_dimensions = Dqn_String8_InitCString8(argv[1]);
Dqn_String8 sprite_spec_path = Dqn_String8_InitCString8(argv[2]);
Dqn_String8 dir = Dqn_String8_InitCString8(argv[3]);
Dqn_Str8 atlas_dimensions = Dqn_Str8_InitCStr8(argv[1]);
Dqn_Str8 sprite_spec_path = Dqn_Str8_InitCStr8(argv[2]);
Dqn_Str8 dir = Dqn_Str8_InitCStr8(argv[3]);
if (!Dqn_Fs_Exists(sprite_spec_path)) {
Dqn_Log_ErrorF("Sprite specification file does not exist, we tried to find \"%.*s\" but it does not exist", DQN_STRING_FMT(sprite_spec_path));
Dqn_Log_ErrorF("Sprite specification file does not exist, we tried to find \"%.*s\" but it does not exist", DQN_STR_FMT(sprite_spec_path));
return -1;
}
if (!Dqn_Fs_DirExists(dir)) {
Dqn_Log_ErrorF("Directory to load sprites from does not exist, we tried to find \"%.*s\" but it does not exist", DQN_STRING_FMT(dir));
Dqn_Log_ErrorF("Directory to load sprites from does not exist, we tried to find \"%.*s\" but it does not exist", DQN_STR_FMT(dir));
return -1;
}
// NOTE: Parse the atlas size ==================================================================
Dqn_V2I atlas_size = {};
{
Dqn_String8BinarySplitResult atlas_dimensions_split = Dqn_String8_BinarySplit(atlas_dimensions, DQN_STRING8("x"));
Dqn_String8ToU64Result width = Dqn_String8_ToU64(atlas_dimensions_split.lhs, 0);
Dqn_String8ToU64Result height = Dqn_String8_ToU64(atlas_dimensions_split.rhs, 0);
Dqn_Str8BinarySplitResult atlas_dimensions_split = Dqn_Str8_BinarySplit(atlas_dimensions, DQN_STR8("x"));
Dqn_Str8ToU64Result width = Dqn_Str8_ToU64(atlas_dimensions_split.lhs, 0);
Dqn_Str8ToU64Result height = Dqn_Str8_ToU64(atlas_dimensions_split.rhs, 0);
if (!width.success || width.value == 0) {
Dqn_Log_ErrorF("Width for the sprite atlas was not a number > 0");
@ -106,51 +106,51 @@ int main(int argc, char const *argv[])
Dqn_DSMap<SpriteSpecification> sprite_spec_table = Dqn_DSMap_Init<SpriteSpecification>(1024);
{
Dqn_ThreadScratch inner_scratch = Dqn_Thread_GetScratch(scratch.arena);
Dqn_String8 sprite_spec_buffer = Dqn_Fs_Read(sprite_spec_path, inner_scratch.allocator);
Dqn_String8SplitAllocResult sprite_spec_lines = Dqn_String8_SplitAlloc(inner_scratch.allocator, sprite_spec_buffer, DQN_STRING8("\n"));
Dqn_Str8 sprite_spec_buffer = Dqn_Fs_Read(sprite_spec_path, inner_scratch.allocator);
Dqn_Str8SplitAllocResult sprite_spec_lines = Dqn_Str8_SplitAlloc(inner_scratch.allocator, sprite_spec_buffer, DQN_STR8("\n"));
DQN_FOR_UINDEX(line_index, sprite_spec_lines.size) {
Dqn_String8 line = Dqn_String8_TrimWhitespaceAround(sprite_spec_lines.data[line_index]);
Dqn_Str8 line = Dqn_Str8_TrimWhitespaceAround(sprite_spec_lines.data[line_index]);
if (line.size == 0) // NOTE: Support empty lines, just ignore them
continue;
Dqn_String8SplitAllocResult line_parts = Dqn_String8_SplitAlloc(inner_scratch.allocator, line, DQN_STRING8(";"));
Dqn_Str8SplitAllocResult line_parts = Dqn_Str8_SplitAlloc(inner_scratch.allocator, line, DQN_STR8(";"));
DQN_ASSERTF(line_parts.size == 2, "Line must have 2 parts in the sprite specification\n"
"\n"
"<animation name>;<frames per second>\\n\n"
"\n"
"Line was '%.*s' loaded from '%.*s'", DQN_STRING_FMT(line), DQN_STRING_FMT(sprite_spec_path));
"Line was '%.*s' loaded from '%.*s'", DQN_STR_FMT(line), DQN_STR_FMT(sprite_spec_path));
Dqn_String8 anim_name = line_parts.data[0];
Dqn_String8ToU64Result frames_per_second = Dqn_String8_ToU64(line_parts.data[1], 0);
Dqn_Str8 anim_name = line_parts.data[0];
Dqn_Str8ToU64Result frames_per_second = Dqn_Str8_ToU64(line_parts.data[1], 0);
DQN_ASSERTF(frames_per_second.success, "Frames per second was not a convertible number, line was '%.*s'", line);
Dqn_DSMapResult<SpriteSpecification> slot = Dqn_DSMap_MakeKeyString8Copy(&sprite_spec_table, scratch.allocator, anim_name);
Dqn_DSMapResult<SpriteSpecification> slot = Dqn_DSMap_MakeKeyStr8Copy(&sprite_spec_table, scratch.allocator, anim_name);
slot.value->frames_per_second = DQN_CAST(uint16_t)frames_per_second.value;
}
}
// NOTE: Get the list of files =================================================================
Dqn_List<Dqn_String8> file_list_raw = Dqn_List_Init<Dqn_String8>(scratch.arena, 128);
Dqn_List<Dqn_Str8> file_list_raw = Dqn_List_Init<Dqn_Str8>(scratch.arena, 128);
for (Dqn_Win_FolderIterator it = {}; Dqn_Win_FolderIterate(dir, &it); ) {
if (Dqn_String8_EndsWithInsensitive(it.file_name, DQN_STRING8(".png"))) {
Dqn_String8 *item = Dqn_List_Make(&file_list_raw, Dqn_ZeroMem_Yes);
*item = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STRING_FMT(dir), DQN_STRING_FMT(it.file_name));
if (Dqn_Str8_EndsWithInsensitive(it.file_name, DQN_STR8(".png"))) {
Dqn_Str8 *item = Dqn_List_Make(&file_list_raw, Dqn_ZeroMem_Yes);
*item = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STR_FMT(dir), DQN_STR_FMT(it.file_name));
}
}
// NOTE: Sort the list of files ================================================================
if (file_list_raw.count == 0) {
Dqn_Log_InfoF("There are no '.png' files in the directory '%.*s' to create an atlas from, exiting", DQN_STRING_FMT(dir));
Dqn_Log_InfoF("There are no '.png' files in the directory '%.*s' to create an atlas from, exiting", DQN_STR_FMT(dir));
return 0;
}
// NOTE: Bubble sort the file list naturally ===================================================
Dqn_Slice<Dqn_String8> file_list = Dqn_List_ToSliceCopy(&file_list_raw, scratch.arena);
Dqn_Slice<Dqn_Str8> file_list = Dqn_List_ToSliceCopy(&file_list_raw, scratch.arena);
for (bool swapped = true; swapped; ) {
swapped = false;
for (Dqn_usize list_index = 0; list_index < file_list.size - 1; list_index++) {
Dqn_String8 left = file_list.data[list_index + 0];
Dqn_String8 right = file_list.data[list_index + 1];
Dqn_Str8 left = file_list.data[list_index + 0];
Dqn_Str8 right = file_list.data[list_index + 1];
if (strnatcmp(left.data, right.data) > 0) {
DQN_SWAP(file_list.data[list_index + 0], file_list.data[list_index + 1]);
swapped = true;
@ -165,7 +165,7 @@ int main(int argc, char const *argv[])
// NOTE: Load the sprites to determine their dimensions for rect packing =======================
Dqn_SArray<stbrp_rect> rects = Dqn_SArray_Init<stbrp_rect>(scratch.arena, file_list.size, Dqn_ZeroMem_Yes);
for (Dqn_String8 it : file_list) {
for (Dqn_Str8 it : file_list) {
int x = 0, y = 0, channels_in_file = 0;
stbi_uc *pixels = stbi_load(it.data, &x, &y, &channels_in_file, 4 /*desired_channels*/);
DQN_ASSERT(pixels);
@ -177,16 +177,16 @@ int main(int argc, char const *argv[])
rect->h = y;
// NOTE: Enumerate the number of frames for this animation =================================
Dqn_String8 anim_prefix = SpriteAnimNameFromFilePath(it);
Dqn_String8 file_name = Dqn_String8_FileNameFromPath(it);
DQN_ASSERTF(!Dqn_String8_HasChar(file_name, ';'),
Dqn_Str8 anim_prefix = SpriteAnimNameFromFilePath(it);
Dqn_Str8 file_name = Dqn_Str8_FileNameFromPath(it);
DQN_ASSERTF(!Dqn_Str8_HasChar(file_name, ';'),
"\n\nSprite frame loaded from file\n"
" '%.*s'\n"
"\n"
"however the file name has a semicolon which is not supported because we use a semicolon to delimit our sprite specification",
DQN_STRING_FMT(file_name));
DQN_STR_FMT(file_name));
Dqn_DSMapResult<SpriteSpecification> slot = Dqn_DSMap_FindKeyString8(&sprite_spec_table, anim_prefix);
Dqn_DSMapResult<SpriteSpecification> slot = Dqn_DSMap_FindKeyStr8(&sprite_spec_table, anim_prefix);
DQN_ASSERTF(slot.found,
"\n\nSprite frame loaded from file\n"
" '%.*s'\n"
@ -196,12 +196,12 @@ int main(int argc, char const *argv[])
"\n"
"Add a line in format of <animation name>;<frames_per_second> to the file, e.g.\n"
" %.*s;8\n",
DQN_STRING_FMT(it),
DQN_STRING_FMT(sprite_spec_path),
DQN_STRING_FMT(anim_prefix));
DQN_STR_FMT(it),
DQN_STR_FMT(sprite_spec_path),
DQN_STR_FMT(anim_prefix));
slot.value->frame_count++;
Dqn_Log_InfoF("Packing sprite: %.*s", DQN_STRING_FMT(it));
Dqn_Log_InfoF("Packing sprite: %.*s", DQN_STR_FMT(it));
}
// NOTE: Pack the rects ========================================================================
@ -217,7 +217,7 @@ int main(int argc, char const *argv[])
int final_bpp = 4;
int final_image_stride = atlas_size.w * final_bpp;
char *final_image = Dqn_Arena_NewArray(scratch.arena, char, atlas_size.h * final_image_stride, Dqn_ZeroMem_Yes);
Dqn_String8 atlas_path = Dqn_String8_InitF(scratch.allocator, "%.*s.png", DQN_STRING_FMT(dir));
Dqn_Str8 atlas_path = Dqn_Str8_InitF(scratch.allocator, "%.*s.png", DQN_STR_FMT(dir));
// NOTE: Generate the meta file ================================================================
// NOTE: Count the number of animations we loaded frames fore
@ -231,18 +231,18 @@ int main(int argc, char const *argv[])
}
}
Dqn_String8 meta_path = Dqn_String8_InitF(scratch.allocator, "%.*s.txt", DQN_STRING_FMT(dir));
Dqn_Str8 meta_path = Dqn_Str8_InitF(scratch.allocator, "%.*s.txt", DQN_STR_FMT(dir));
Dqn_FsFile meta_file = Dqn_Fs_OpenFile(meta_path, Dqn_FsFileOpen_CreateAlways, Dqn_FsFileAccess_Write);
Dqn_Fs_WriteFileF(&meta_file,
"@file;%.*s;%d;%d\n",
DQN_STRING_FMT(Dqn_String8_FileNameFromPath(atlas_path)),
DQN_STR_FMT(Dqn_Str8_FileNameFromPath(atlas_path)),
DQN_CAST(int) num_anim_rects,
DQN_CAST(int) num_anims);
Dqn_Log_InfoF("Generating meta file: %.*s", DQN_STRING_FMT(meta_path));
Dqn_String8 active_anim_prefix = {};
Dqn_Log_InfoF("Generating meta file: %.*s", DQN_STR_FMT(meta_path));
Dqn_Str8 active_anim_prefix = {};
DQN_FOR_UINDEX (file_list_index, file_list.size) {
Dqn_String8 it = file_list.data[file_list_index];
Dqn_Str8 it = file_list.data[file_list_index];
int w, h, channels_in_file;
stbi_uc *loaded_image = stbi_load(it.data, &w, &h, &channels_in_file, 4 /*desired_channels*/);
@ -263,22 +263,22 @@ int main(int argc, char const *argv[])
stbi_image_free(loaded_image);
// NOTE: Detect what animation we are currently processing =================================
Dqn_String8 anim_prefix = SpriteAnimNameFromFilePath(it);
Dqn_Str8 anim_prefix = SpriteAnimNameFromFilePath(it);
if (active_anim_prefix.size == 0 || active_anim_prefix != anim_prefix) {
// NOTE: Anim prefix is different, we are starting a new animation- mark it accordingly
active_anim_prefix = anim_prefix;
Dqn_DSMapResult<SpriteSpecification> slot = Dqn_DSMap_FindKeyString8(&sprite_spec_table, active_anim_prefix);
Dqn_Fs_WriteFileF(&meta_file, "@anim;%.*s;%u;%u\n", DQN_STRING_FMT(active_anim_prefix), slot.value->frames_per_second, slot.value->frame_count);
Dqn_DSMapResult<SpriteSpecification> slot = Dqn_DSMap_FindKeyStr8(&sprite_spec_table, active_anim_prefix);
Dqn_Fs_WriteFileF(&meta_file, "@anim;%.*s;%u;%u\n", DQN_STR_FMT(active_anim_prefix), slot.value->frames_per_second, slot.value->frame_count);
}
// NOTE: Write the sprite rectangles in ====================================================
Dqn_String8 file_name = Dqn_String8_FileNameFromPath(it);
Dqn_Fs_WriteFileF(&meta_file, "%d;%d;%d;%d;%.*s", packed_rect.x, packed_rect.y, packed_rect.w, packed_rect.h, DQN_STRING_FMT(file_name));
Dqn_Str8 file_name = Dqn_Str8_FileNameFromPath(it);
Dqn_Fs_WriteFileF(&meta_file, "%d;%d;%d;%d;%.*s", packed_rect.x, packed_rect.y, packed_rect.w, packed_rect.h, DQN_STR_FMT(file_name));
if (file_list_index != (file_list.size - 1))
Dqn_Fs_WriteFileF(&meta_file, "\n");
}
Dqn_Log_InfoF("Generating atlas: %.*s", DQN_STRING_FMT(atlas_path));
Dqn_Log_InfoF("Generating atlas: %.*s", DQN_STR_FMT(atlas_path));
stbi_write_png(atlas_path.data, atlas_size.w, atlas_size.h, 4, final_image, final_image_stride);
return 0;
}

1
feely_pona_unity.cpp Normal file
View File

@ -0,0 +1 @@
#include "feely_pona_unity.h"

View File

@ -1,65 +1,13 @@
// =================================================================================================
// NOTE: feely_pona ================================================================================
// Unity build header to compile the entire application as a single translation unit
// NOTE(doyle): Work-around for clangd to correctly resolve symbols in unity
// builds by providing symbol definition and prototypes by including this
// mega-header in all files and using the "#pragma once" directive to
// avoid multiple defined symbols when compiling the unity build itself.
//
// See: https://www.frogtoss.com/labs/clangd-with-unity-builds.html
#pragma once
// NOTE: DQN =======================================================================================
// NOTE: C-strings declared in a ternary cause global-buffer-overflow in
// MSVC2022.
// stb_sprintf assumes c-string literals are 4 byte aligned which is always
// true, however, reading past the end of a string whose size is not a multiple
// of 4 is UB causing ASAN to complain.
#if defined(_MSC_VER) && !defined(__clang__)
#define STBSP__ASAN __declspec(no_sanitize_address)
#endif
#define DQN_ASAN_POISON 0
#define DQN_ASAN_VET_POISON 1
#define DQN_ONLY_RECT
#define DQN_ONLY_V2
#define DQN_ONLY_V3
#define DQN_ONLY_V4
#define DQN_ONLY_WIN
#define DQN_ONLY_FARRAY
#define DQN_ONLY_PROFILER
#define DQN_ONLY_SLICE
#define DQN_ONLY_LIST
#define DQN_ONLY_VARRAY
#define DQN_ONLY_DSMAP
#define DQN_ONLY_FS
#define _CRT_SECURE_NO_WARNINGS
#define DQN_IMPLEMENTATION
#include "External/tely/External/dqn/dqn.h"
// NOTE: TELY ======================================================================================
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: unreferenced function with internal linkage has been removed
#include "External/tely/tely_profile.h"
#include "External/tely/tely_platform_input.h"
#include "External/tely/tely_tools.h"
#include "External/tely/tely_asset.h"
#include "External/tely/tely_colour.h"
#include "External/tely/tely_render.h"
#include "External/tely/tely_audio.h"
#include "External/tely/tely_platform.h"
#include "External/tely/tely_rfui.h"
#include "External/tely/tely_tools.cpp"
#include "External/tely/tely_asset.cpp"
#include "External/tely/tely_audio.cpp"
#include "External/tely/tely_render.cpp"
#include "External/tely/tely_platform_input.cpp"
#include "External/tely/tely_rfui.cpp"
#define TELY_PLATFORM_DLL_FILE_NAME "terry_cherry_dev_dll"
#include "External/tely/tely_os_raylib_unity.h"
// NOTE: feely_pona ================================================================================
#if defined(_CLANGD) || defined(FEELY_PONA_IMPLEMENTATION)
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: unreferenced function with internal linkage has been removed
#include "feely_pona.h"
#include "feely_pona_stdlib.h"
#include "feely_pona_entity.h"
@ -71,3 +19,4 @@ DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: unreferenced function with inte
#include "feely_pona_misc.cpp"
#include "feely_pona.cpp"
DQN_MSVC_WARNING_POP
#endif

View File

@ -1 +0,0 @@
#include "feely_pona_unity_nodll.h"

View File

@ -1,102 +0,0 @@
// =================================================================================================
// NOTE(doyle): Work-around for clangd to correctly resolve symbols in unity
// builds by providing symbol definition and prototypes by including this
// mega-header in all files and using the "#pragma once" directive to
// avoid multiple defined symbols when compiling the unity build itself.
//
// See: https://www.frogtoss.com/labs/clangd-with-unity-builds.html
#pragma once
// NOTE: DQN =======================================================================================
// NOTE: C-strings declared in a ternary cause global-buffer-overflow in
// MSVC2022.
// stb_sprintf assumes c-string literals are 4 byte aligned which is always
// true, however, reading past the end of a string whose size is not a multiple
// of 4 is UB causing ASAN to complain.
#if defined(_MSC_VER) && !defined(__clang__)
#define STBSP__ASAN __declspec(no_sanitize_address)
#endif
#define DQN_ASAN_POISON 0
#define DQN_ASAN_VET_POISON 1
#define DQN_ONLY_RECT
#define DQN_ONLY_V2
#define DQN_ONLY_V3
#define DQN_ONLY_V4
#define DQN_ONLY_WIN
#define DQN_ONLY_FARRAY
#define DQN_ONLY_PROFILER
#define DQN_ONLY_SLICE
#define DQN_ONLY_LIST
#define DQN_ONLY_VARRAY
#define DQN_ONLY_DSMAP
#define DQN_ONLY_FS
#define _CRT_SECURE_NO_WARNINGS
#define DQN_IMPLEMENTATION
#include "External/tely/External/dqn/dqn.h"
// NOTE: STB Headers ===============================================================================
DQN_GCC_WARNING_PUSH
DQN_GCC_WARNING_DISABLE(-Wunused-function)
#include "External/tely/External/stb/stb_image.h"
DQN_GCC_WARNING_POP
// =================================================================================================
#include "External/tely/External/raylib/raylib.h"
#include "External/tely/External/raylib/rlgl.h"
#include "External/tely/External/raylib/external/glfw/include/GLFW/glfw3.h"
// NOTE: TELY ======================================================================================
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: unreferenced function with internal linkage has been removed
DQN_GCC_WARNING_PUSH
DQN_GCC_WARNING_DISABLE(-Wunused-function)
#include "External/tely/tely_profile.h"
#include "External/tely/tely_platform_input.h"
#include "External/tely/tely_tools.h"
#include "External/tely/tely_asset.h"
#include "External/tely/tely_colour.h"
#include "External/tely/tely_render.h"
#include "External/tely/tely_audio.h"
#include "External/tely/tely_platform.h"
#include "External/tely/tely_rfui.h"
#include "External/tely/tely_tools.cpp"
#include "External/tely/tely_asset.cpp"
#include "External/tely/tely_audio.cpp"
#include "External/tely/tely_render.cpp"
#include "External/tely/tely_platform_input.cpp"
#include "External/tely/tely_rfui.cpp"
// NOTE: feely_pona ================================================================================
#include "feely_pona.h"
#include "feely_pona_stdlib.h"
#include "feely_pona_entity.h"
#include "feely_pona_game.h"
#include "feely_pona_entity.cpp"
#include "feely_pona_game.cpp"
#include "feely_pona_entity_create.cpp"
#include "feely_pona_misc.cpp"
#include "feely_pona.cpp"
DQN_MSVC_WARNING_POP
DQN_GCC_WARNING_POP
#if defined(DQN_PLATFORM_EMSCRIPTEN)
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#endif
// NOTE: TELY_Platform =============================================================================
#define TELY_PLATFORM_NO_DLL
#include "External/tely/tely_platform.cpp"
#include "External/tely/tely_platform_raylib.cpp"

Binary file not shown.