From ad0577dc455760b8b8f8a5d8068c8c8ab325c03d Mon Sep 17 00:00:00 2001 From: westonCoder Date: Thu, 12 Oct 2023 13:17:46 -0500 Subject: [PATCH] added all captions option, implemented all current sfx captions --- src/levels/cutscene_runner.c | 2 +- src/menu/audio_options.c | 37 +++++++++-- src/menu/audio_options.h | 2 + src/menu/controls.c | 9 ++- src/menu/controls.h | 3 +- src/player/player.c | 5 ++ src/savefile/savefile.h | 1 + src/scene/ball.c | 2 + src/scene/box_dropper.c | 3 + src/scene/button.c | 4 ++ src/scene/door.c | 3 + src/scene/elevator.c | 2 + src/scene/hud.c | 117 +++++++++++++++++++++++++++-------- src/scene/hud.h | 20 ++++-- src/scene/pedestal.c | 4 ++ src/scene/scene.c | 8 +++ src/scene/scene_animator.c | 6 +- src/scene/switch.c | 5 ++ 18 files changed, 188 insertions(+), 45 deletions(-) diff --git a/src/levels/cutscene_runner.c b/src/levels/cutscene_runner.c index 3f8c3c0..8222005 100644 --- a/src/levels/cutscene_runner.c +++ b/src/levels/cutscene_runner.c @@ -398,7 +398,7 @@ void cutscenesUpdateSounds() { struct QueuedSound* curr = gCutsceneSoundQueues[i]; gCutsceneCurrentSound[i] = soundPlayerPlay(curr->soundId, curr->volume, gCutsceneChannelPitch[i], NULL, NULL, SoundTypeAll); - hudShowSubtitle(&gScene.hud, curr->subtitleId); + hudShowSubtitle(&gScene.hud, curr->subtitleId, SubtitleTypeCloseCaption); gCutsceneSoundQueues[i] = curr->next; diff --git a/src/menu/audio_options.c b/src/menu/audio_options.c index ed3196b..e35f86c 100644 --- a/src/menu/audio_options.c +++ b/src/menu/audio_options.c @@ -53,7 +53,7 @@ void audioOptionsHandleSlider(unsigned short* settingValue, float* sliderValue) void audioOptionsInit(struct AudioOptions* audioOptions) { audioOptions->selectedItem = AudioOptionGameVolume; - audioOptions->gameVolumeText = menuBuildText(&gDejaVuSansFont, "Master Volume", GAMEPLAY_X + 8, GAMEPLAY_Y + 8); + audioOptions->gameVolumeText = menuBuildText(&gDejaVuSansFont, "Game Volume", GAMEPLAY_X + 8, GAMEPLAY_Y + 8); audioOptions->gameVolume = menuBuildSlider(GAMEPLAY_X + 120, GAMEPLAY_Y + 8, 120, SCROLL_TICKS); audioOptions->gameVolume.value = gSaveData.audio.soundVolume/0xFFFF; @@ -64,10 +64,13 @@ void audioOptionsInit(struct AudioOptions* audioOptions) { audioOptions->subtitlesEnabled = menuBuildCheckbox(&gDejaVuSansFont, "Closed Captions", GAMEPLAY_X + 8, GAMEPLAY_Y + 48); audioOptions->subtitlesEnabled.checked = (gSaveData.controls.flags & ControlSaveSubtitlesEnabled) != 0; - audioOptions->subtitlesLanguageText = menuBuildText(&gDejaVuSansFont, "Captions Language: ", GAMEPLAY_X + 8, GAMEPLAY_Y + 68); - audioOptions->subtitlesLanguageDynamicText = menuBuildText(&gDejaVuSansFont, SubtitleLanguages[gSaveData.controls.subtitleLanguage], GAMEPLAY_X + 125, GAMEPLAY_Y + 68); + audioOptions->allSubtitlesEnabled = menuBuildCheckbox(&gDejaVuSansFont, "All Captions", GAMEPLAY_X + 8, GAMEPLAY_Y + 68); + audioOptions->allSubtitlesEnabled.checked = (gSaveData.controls.flags & ControlSaveAllSubtitlesEnabled) != 0; - audioOptions->subtitlesLanguage= menuBuildSlider(GAMEPLAY_X + 8, GAMEPLAY_Y + 88, 200, NUM_SUBTITLE_LANGUAGES); + audioOptions->subtitlesLanguageText = menuBuildText(&gDejaVuSansFont, "Captions Language: ", GAMEPLAY_X + 8, GAMEPLAY_Y + 88); + audioOptions->subtitlesLanguageDynamicText = menuBuildText(&gDejaVuSansFont, SubtitleLanguages[gSaveData.controls.subtitleLanguage], GAMEPLAY_X + 125, GAMEPLAY_Y + 88); + + audioOptions->subtitlesLanguage= menuBuildSlider(GAMEPLAY_X + 8, GAMEPLAY_Y + 108, 200, NUM_SUBTITLE_LANGUAGES); audioOptions->subtitles_language_temp = (0xFFFF/NUM_SUBTITLE_LANGUAGES)* gSaveData.controls.subtitleLanguage; audioOptions->subtitlesLanguage.value = (int)gSaveData.controls.subtitleLanguage * (0xFFFF/NUM_SUBTITLE_LANGUAGES); } @@ -111,17 +114,33 @@ enum MenuDirection audioOptionsUpdate(struct AudioOptions* audioOptions) { if (audioOptions->subtitlesEnabled.checked) { gSaveData.controls.flags |= ControlSaveSubtitlesEnabled; + gSaveData.controls.flags &= ~ControlSaveAllSubtitlesEnabled; + audioOptions->allSubtitlesEnabled.checked = 0; } else { gSaveData.controls.flags &= ~ControlSaveSubtitlesEnabled; } } break; + case AudioOptionAllSubtitlesEnabled: + if (controllerGetButtonDown(0, A_BUTTON)) { + audioOptions->allSubtitlesEnabled.checked = !audioOptions->allSubtitlesEnabled.checked; + soundPlayerPlay(SOUNDS_BUTTONCLICKRELEASE, 1.0f, 0.5f, NULL, NULL, SoundTypeAll); + + if (audioOptions->allSubtitlesEnabled.checked) { + gSaveData.controls.flags |= ControlSaveAllSubtitlesEnabled; + gSaveData.controls.flags &= ~ControlSaveSubtitlesEnabled; + audioOptions->subtitlesEnabled.checked = 0; + } else { + gSaveData.controls.flags &= ~ControlSaveAllSubtitlesEnabled; + } + } + break; case AudioOptionSubtitlesLanguage: audioOptionsHandleSlider(&audioOptions->subtitles_language_temp, &audioOptions->subtitlesLanguage.value); int temp = (int)((audioOptions->subtitles_language_temp * (1.0f/0xFFFF) * NUM_SUBTITLE_LANGUAGES)); temp = (int)minf(maxf(0.0, temp), NUM_SUBTITLE_LANGUAGES-1); gSaveData.controls.subtitleLanguage = temp; - audioOptions->subtitlesLanguageDynamicText = menuBuildText(&gDejaVuSansFont, SubtitleLanguages[gSaveData.controls.subtitleLanguage], GAMEPLAY_X + 125, GAMEPLAY_Y + 68); + audioOptions->subtitlesLanguageDynamicText = menuBuildText(&gDejaVuSansFont, SubtitleLanguages[gSaveData.controls.subtitleLanguage], GAMEPLAY_X + 125, GAMEPLAY_Y + 88); break; } @@ -161,6 +180,9 @@ void audioOptionsRender(struct AudioOptions* audioOptions, struct RenderState* r gSPDisplayList(renderState->dl++, audioOptions->subtitlesEnabled.outline); renderState->dl = menuCheckboxRender(&audioOptions->subtitlesEnabled, renderState->dl); + gSPDisplayList(renderState->dl++, audioOptions->allSubtitlesEnabled.outline); + renderState->dl = menuCheckboxRender(&audioOptions->allSubtitlesEnabled, renderState->dl); + gSPDisplayList(renderState->dl++, audioOptions->subtitlesLanguage.back); renderState->dl = menuSliderRender(&audioOptions->subtitlesLanguage, renderState->dl); @@ -177,11 +199,14 @@ void audioOptionsRender(struct AudioOptions* audioOptions, struct RenderState* r menuSetRenderColor(renderState, audioOptions->selectedItem == AudioOptionMusicVolume, &gSelectionGray, &gColorWhite); gSPDisplayList(renderState->dl++, audioOptions->musicVolumeText); - gDPPipeSync(renderState->dl++); menuSetRenderColor(renderState, audioOptions->selectedItem == AudioOptionSubtitlesEnabled, &gSelectionGray, &gColorWhite); gSPDisplayList(renderState->dl++, audioOptions->subtitlesEnabled.text); + gDPPipeSync(renderState->dl++); + menuSetRenderColor(renderState, audioOptions->selectedItem == AudioOptionAllSubtitlesEnabled, &gSelectionGray, &gColorWhite); + gSPDisplayList(renderState->dl++, audioOptions->allSubtitlesEnabled.text); + gDPPipeSync(renderState->dl++); menuSetRenderColor(renderState, audioOptions->selectedItem == AudioOptionSubtitlesLanguage, &gSelectionGray, &gColorWhite); gSPDisplayList(renderState->dl++, audioOptions->subtitlesLanguageText); diff --git a/src/menu/audio_options.h b/src/menu/audio_options.h index baa164f..6e3f2fd 100644 --- a/src/menu/audio_options.h +++ b/src/menu/audio_options.h @@ -8,6 +8,7 @@ enum AudioOption { AudioOptionGameVolume, AudioOptionMusicVolume, AudioOptionSubtitlesEnabled, + AudioOptionAllSubtitlesEnabled, AudioOptionSubtitlesLanguage, AudioOptionCount, @@ -17,6 +18,7 @@ struct AudioOptions { struct MenuSlider gameVolume; struct MenuSlider musicVolume; struct MenuCheckbox subtitlesEnabled; + struct MenuCheckbox allSubtitlesEnabled; struct MenuSlider subtitlesLanguage; Gfx* gameVolumeText; Gfx* musicVolumeText; diff --git a/src/menu/controls.c b/src/menu/controls.c index bff78a9..aeafb08 100644 --- a/src/menu/controls.c +++ b/src/menu/controls.c @@ -510,7 +510,7 @@ void controlsRenderPrompt(enum ControllerAction action, char* message, float opa gSPDisplayList(renderState->dl++, ui_material_revert_list[BUTTON_ICONS_INDEX]); } -void controlsRenderSubtitle(char* message, float textOpacity, float backgroundOpacity, struct RenderState* renderState) { +void controlsRenderSubtitle(char* message, float textOpacity, float backgroundOpacity, struct RenderState* renderState, enum SubtitleType subtitleType) { struct Vector2s16 size = fontMeasure(&gDejaVuSansFont, message); int textOpacityAsInt = (int)(255 * textOpacity); @@ -544,7 +544,12 @@ void controlsRenderSubtitle(char* message, float textOpacity, float backgroundOp gSPDisplayList(renderState->dl++, ui_material_revert_list[SOLID_TRANSPARENT_OVERLAY_INDEX]); gSPDisplayList(renderState->dl++, ui_material_list[DEJAVU_SANS_INDEX]); - gDPSetEnvColor(renderState->dl++, 255, 140, 155, textOpacityAsInt); + if (subtitleType == SubtitleTypeCloseCaption){ + gDPSetEnvColor(renderState->dl++, 255, 140, 155, textOpacityAsInt); + } else if (subtitleType == SubtitleTypeCaption){ + gDPSetEnvColor(renderState->dl++, 255, 255, 255, textOpacityAsInt); + } + renderState->dl = fontRender( &gDejaVuSansFont, message, diff --git a/src/menu/controls.h b/src/menu/controls.h index 2d5119a..ef64a28 100644 --- a/src/menu/controls.h +++ b/src/menu/controls.h @@ -4,6 +4,7 @@ #include "./menu.h" #include "../controls/controller_actions.h" #include "../graphics/graphics.h" +#include "../scene/hud.h" #define MAX_SOURCES_PER_ACTION 4 #define MAX_CONTROLS_SECTIONS 4 @@ -42,6 +43,6 @@ enum MenuDirection controlsMenuUpdate(struct ControlsMenu* controlsMenu); void controlsMenuRender(struct ControlsMenu* controlsMenu, struct RenderState* renderState, struct GraphicsTask* task); void controlsRenderPrompt(enum ControllerAction action, char* message, float opacity, struct RenderState* renderState); -void controlsRenderSubtitle(char* message, float textOpacity, float backgroundOpacity, struct RenderState* renderState); +void controlsRenderSubtitle(char* message, float textOpacity, float backgroundOpacity, struct RenderState* renderState, enum SubtitleType subtitleType); #endif \ No newline at end of file diff --git a/src/player/player.c b/src/player/player.c index 577ecab..ee5cb3a 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -427,6 +427,9 @@ void playerUpdateSpeedSound(struct Player* player) { soundPlayerVolume = sqrtf(vector3MagSqrd(&player->body.velocity))*(0.6f / MAX_PORTAL_SPEED); soundPlayerVolume = clampf(soundPlayerVolume, 0.0, 1.0f); soundPlayerAdjustVolume(player->flyingSoundLoopId, soundPlayerVolume); + if (soundPlayerVolume >= 0.75){ + hudShowSubtitle(&gScene.hud, PORTALPLAYER_WOOSH, SubtitleTypeCaption); + } } void playerKill(struct Player* player, int isUnderwater) { @@ -742,7 +745,9 @@ void playerUpdate(struct Player* player) { if (didPassThroughPortal) { soundPlayerPlay(soundsPortalEnter[didPassThroughPortal - 1], 0.75f, 1.0f, NULL, NULL, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTALPLAYER_ENTERPORTAL, SubtitleTypeCaption); soundPlayerPlay(soundsPortalExit[2 - didPassThroughPortal], 0.75f, 1.0f, NULL, NULL, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTALPLAYER_EXITPORTAL, SubtitleTypeCaption); gPlayerCollider.extendDownward = 0.0f; } else { gPlayerCollider.extendDownward = mathfMoveTowards(gPlayerCollider.extendDownward, TARGET_CAPSULE_EXTEND_HEIGHT, STAND_SPEED * FIXED_DELTA_TIME); diff --git a/src/savefile/savefile.h b/src/savefile/savefile.h index aa3aa0a..6da593f 100755 --- a/src/savefile/savefile.h +++ b/src/savefile/savefile.h @@ -39,6 +39,7 @@ enum ControlSaveFlags { ControlSaveTankControls = (1 << 2), ControlSaveSubtitlesEnabled = (1 << 5), + ControlSaveAllSubtitlesEnabled = (1 << 6), ControlSaveMoveablePortals = (1 << 8), ControlSaveWideScreen = (1 << 9), diff --git a/src/scene/ball.c b/src/scene/ball.c index fec2c85..6c17bf6 100644 --- a/src/scene/ball.c +++ b/src/scene/ball.c @@ -139,6 +139,7 @@ void ballInitBurn(struct Ball* ball, struct ContactManifold* manifold) { transformPoint(&manifold->shapeA->body->transform, &position, &position); } soundPlayerPlay(soundsBallBounce, 1.5f, 1.0f, &position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, ENERGYBALL_IMPACT, SubtitleTypeCaption); ball->flags |= BallJustBounced; } @@ -210,6 +211,7 @@ void ballUpdate(struct Ball* ball) { dynamicSceneRemove(ball->dynamicId); soundPlayerStop(ball->soundLoopId); soundPlayerPlay(soundsBallExplode, 2.0f, 1.0f, &ball->rigidBody.transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, ENERGYBALL_EXPLOSION, SubtitleTypeCaption); effectsSplashPlay(&gScene.effects, &gBallBurst, &ball->rigidBody.transform.position, &gUp); ball->soundLoopId = SOUND_ID_NONE; } diff --git a/src/scene/box_dropper.c b/src/scene/box_dropper.c index 9b9ea52..84016d3 100644 --- a/src/scene/box_dropper.c +++ b/src/scene/box_dropper.c @@ -12,6 +12,8 @@ #include "../../build/assets/models/props/box_dropper.h" #include "../../build/assets/models/dynamic_model_list.h" #include "../../build/assets/models/dynamic_animated_model_list.h" +#include "hud.h" +#include "scene.h" #define DROOPER_RELOAD_TIME 2.0f #define DROPPER_DROP_TIME 0.5f @@ -151,6 +153,7 @@ void boxDropperUpdate(struct BoxDropper* dropper) { decorObjectInit(&dropper->activeCube, decorObjectDefinitionForId(DECOR_TYPE_CUBE_UNIMPORTANT), &pendingCubePos, dropper->roomIndex); skAnimatorRunClip(&dropper->animator, dynamicAssetClip(PROPS_BOX_DROPPER_DYNAMIC_ANIMATED_MODEL, PROPS_BOX_DROPPER_ARMATURE_DROPCUBE_CLIP_INDEX), 0.0f, 0); soundPlayerPlay(soundsReleaseCube, 5.0f, 0.5f, &dropper->activeCube.rigidBody.transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, ESCAPE_CAKE_RIDE_1, SubtitleTypeCaption); dropper->flags &= ~BoxDropperFlagsCubeRequested; dropper->flags |= BoxDropperFlagsCubeIsActive; diff --git a/src/scene/button.c b/src/scene/button.c index c2d639d..3a69cfa 100644 --- a/src/scene/button.c +++ b/src/scene/button.c @@ -12,6 +12,8 @@ #include "../../build/assets/models/dynamic_animated_model_list.h" #include "../build/assets/materials/static.h" #include "../../build/assets/models/props/button.h" +#include "../scene/hud.h" +#include "../scene/scene.h" struct Vector2 gButtonCylinderEdgeVectors[] = { {0.0f, 1.0f}, @@ -142,6 +144,7 @@ void buttonUpdate(struct Button* button) { if (shouldPress){ if (!(button->flags & ButtonFlagsBeingPressed)){ soundPlayerPlay(soundsButton, 2.5f, 0.5f, &button->rigidBody.transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_BUTTON_DOWN, SubtitleTypeCaption); } button->flags |= ButtonFlagsBeingPressed; } @@ -149,6 +152,7 @@ void buttonUpdate(struct Button* button) { else{ if ((button->flags & ButtonFlagsBeingPressed)){ soundPlayerPlay(soundsButtonRelease, 2.5f, 0.4f, &button->rigidBody.transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_BUTTON_UP, SubtitleTypeCaption); } button->flags &= ~ButtonFlagsBeingPressed; } diff --git a/src/scene/door.c b/src/scene/door.c index 39553e0..1315fd7 100644 --- a/src/scene/door.c +++ b/src/scene/door.c @@ -9,6 +9,8 @@ #include "../physics/collision_box.h" #include "../physics/collision_scene.h" #include "../util/dynamic_asset_loader.h" +#include "hud.h" +#include "scene.h" #include "../build/assets/materials/static.h" #include "../../build/assets/models/dynamic_animated_model_list.h" @@ -132,6 +134,7 @@ void doorUpdate(struct Door* door) { } soundPlayerPlay(soundsDoor, 3.0f, 0.5f, &door->rigidBody.transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_DOORCLOSE, SubtitleTypeCaption); if (signal) { door->flags |= DoorFlagsIsOpen; diff --git a/src/scene/elevator.c b/src/scene/elevator.c index 3926f34..6b9e859 100644 --- a/src/scene/elevator.c +++ b/src/scene/elevator.c @@ -186,6 +186,7 @@ int elevatorUpdate(struct Elevator* elevator, struct Player* player) { soundPlayerPlay(soundsElevatorDoor, 1.0f, 0.5f, &elevator->rigidBody.transform.position, &gZeroVec, SoundTypeAll); if ((elevator->openAmount == 0.0f && shouldBeOpen) && (elevator->flags & ElevatorFlagsHasHadPlayer)){ soundPlayerPlay(soundsElevatorChime, 1.5f, 0.5f, &elevator->rigidBody.transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_ELEVATOR_CHIME, SubtitleTypeCaption); } } @@ -196,6 +197,7 @@ int elevatorUpdate(struct Elevator* elevator, struct Player* player) { if ((elevator->flags & ElevatorFlagsIsLocked) && (elevator->openAmount == 0.0f) && !(elevator->flags & ElevatorFlagsMovingSoundPlayed) && (elevator->movingTimer <= 0.0f) && inside){ soundPlayerPlay(soundsElevatorMoving, 1.25f, 0.5f, &elevator->rigidBody.transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_ELEVATOR_START, SubtitleTypeCaption); player->shakeTimer = SHAKE_DURATION; elevator->flags |= ElevatorFlagsMovingSoundPlayed; } diff --git a/src/scene/hud.c b/src/scene/hud.c index 7641ffd..d1f3d5e 100644 --- a/src/scene/hud.c +++ b/src/scene/hud.c @@ -1,7 +1,6 @@ #include "hud.h" #include "../../build/assets/materials/hud.h" -#include "../../build/src/audio/subtitles.h" #include "../menu/controls.h" #include "../graphics/graphics.h" #include "../util/time.h" @@ -32,15 +31,23 @@ #define RETICLE_WIDTH 16 #define RETICLE_HEIGHT 16 -#define PROMPT_FADE_TIME 2.0f -#define SUBTITLE_FADE_TIME 0.75f +#define PROMPT_FADE_TIME 2.0f +#define SUBTITLE_SLOW_FADE_TIME 0.75f +#define SUBTITLE_FAST_FADE_TIME 0.25f +#define CAPTION_EXPIRE_TIME 1.5f + + void hudInit(struct Hud* hud) { hud->promptType = CutscenePromptTypeNone; + hud->subtitleKey = SubtitleKeyNone; + hud->queuedSubtitleKey = SubtitleKeyNone; + hud->subtitleType = SubtitleTypeNone; + hud->queuedSubtitleType = SubtitleTypeNone; hud->promptOpacity = 0.0f; hud->subtitleOpacity = 0.0f; hud->backgroundOpacity = 0.0f; - hud->subtitleFadeTime = 0.75; + hud->subtitleFadeTime = SUBTITLE_SLOW_FADE_TIME; hud->chosenLanguage = gSaveData.controls.subtitleLanguage; hud->flags = 0; hud->resolvedPrompts = 0; @@ -63,11 +70,19 @@ void hudUpdate(struct Hud* hud) { } } + if (hud->subtitleExpireTimer > 0.0f) { + hud->subtitleExpireTimer -= FIXED_DELTA_TIME; + + if (hud->subtitleExpireTimer < 0.0f) { + hud->subtitleExpireTimer = 0.0f; + } + } + hud->chosenLanguage = gSaveData.controls.subtitleLanguage; float targetPromptOpacity = (hud->flags & HudFlagsShowingPrompt) ? 1.0 : 0.0f; - float targetSubtitleOpacity = ((hud->flags & HudFlagsShowingSubtitle) && !(hud->flags & HudFlagsSubtitleQueued)) ? 0.85: 0.0f; - float targetBackgroundOpacity = (hud->flags & HudFlagsShowingSubtitle && !(hud->flags & HudFlagsSubtitleQueued)) ? 0.45: 0.0f; + float targetSubtitleOpacity = ((hud->flags & HudFlagsShowingSubtitle) && (!(hud->flags & HudFlagsSubtitleQueued) || (hud->subtitleExpireTimer > 0.0f))) ? 0.85: 0.0f; + float targetBackgroundOpacity = (hud->flags & HudFlagsShowingSubtitle && (!(hud->flags & HudFlagsSubtitleQueued) || (hud->subtitleExpireTimer > 0.0f))) ? 0.45: 0.0f; if (targetPromptOpacity != hud->promptOpacity) { hud->promptOpacity = mathfMoveTowards(hud->promptOpacity, targetPromptOpacity, FIXED_DELTA_TIME / PROMPT_FADE_TIME); @@ -77,10 +92,22 @@ void hudUpdate(struct Hud* hud) { hud->subtitleOpacity = mathfMoveTowards(hud->subtitleOpacity, targetSubtitleOpacity, FIXED_DELTA_TIME / hud->subtitleFadeTime); } - if ((hud->subtitleOpacity == 0.0f) && (hud->flags & HudFlagsSubtitleQueued)){ - hud->flags &= ~HudFlagsSubtitleQueued; - hud->subtitleType = hud->queuedSubtitleType; - hud->queuedSubtitleType = SubtitleKeyNone; + if ((hud->subtitleOpacity <= 0.0f) && (hud->flags & HudFlagsSubtitleQueued)){ + if (!((hud->subtitleType == SubtitleTypeCaption) && (hud->queuedSubtitleType == SubtitleTypeCaption) && (hud->subtitleExpireTimer > 0.0))){ + hud->flags &= ~HudFlagsSubtitleQueued; + hud->flags |= HudFlagsShowingSubtitle; + hud->subtitleKey = hud->queuedSubtitleKey; + hud->subtitleType= hud->queuedSubtitleType; + hud->queuedSubtitleKey = SubtitleKeyNone; + hud->queuedSubtitleType = SubtitleTypeNone; + if (hud->subtitleType == SubtitleTypeCaption){ + hud->subtitleExpireTimer = CAPTION_EXPIRE_TIME; + } + } + } + + if (hud->subtitleExpireTimer <= 0.0f && hud->subtitleType == SubtitleTypeCaption){ + hudResolveSubtitle(&gScene.hud); } if (targetBackgroundOpacity != hud->backgroundOpacity) { @@ -152,30 +179,64 @@ void hudShowActionPrompt(struct Hud* hud, enum CutscenePromptType promptType) { hud->promptType = promptType; } -void hudShowSubtitle(struct Hud* hud, enum SubtitleKey subtitleType) { - if (subtitleType == hud->subtitleType){ +void hudShowSubtitle(struct Hud* hud, enum SubtitleKey subtitleKey, enum SubtitleType subtitleType) { + if (!(gSaveData.controls.flags & ControlSaveSubtitlesEnabled || gSaveData.controls.flags & ControlSaveAllSubtitlesEnabled)){ + return; + } + if (subtitleKey == hud->subtitleKey){ return; } - if (subtitleType == SubtitleKeyNone) { + if (subtitleType == SubtitleTypeNone) { hud->flags &= ~HudFlagsShowingSubtitle; hud->flags &= ~HudFlagsSubtitleQueued; - hud->subtitleFadeTime = 0.75; + hud->queuedSubtitleType = SubtitleTypeNone; + hud->queuedSubtitleKey = SubtitleKeyNone; + hud->subtitleFadeTime = SUBTITLE_SLOW_FADE_TIME; return; } - if (hud->flags & HudFlagsShowingSubtitle){ - hud->flags |= HudFlagsSubtitleQueued; - hud->queuedSubtitleType = subtitleType; - hud->subtitleFadeTime = 0.3; + else if (subtitleType == SubtitleTypeCaption) { + if (!(gSaveData.controls.flags & ControlSaveAllSubtitlesEnabled)){ + return; + } + if ((hud->flags & HudFlagsShowingSubtitle) && ((hud->subtitleType > subtitleType) || (hud->queuedSubtitleType > subtitleType))){ + return; // dont push off screen a higher importance subtitle + } + else if ((hud->flags & HudFlagsShowingSubtitle) && (hud->subtitleType <= subtitleType)){ + hud->flags |= HudFlagsSubtitleQueued; + hud->queuedSubtitleKey = subtitleKey; + hud->queuedSubtitleType = subtitleType; + hud->subtitleFadeTime = SUBTITLE_FAST_FADE_TIME; + } + else{ + hud->flags |= HudFlagsShowingSubtitle; + hud->subtitleKey = subtitleKey; + hud->subtitleType = subtitleType; + hud->queuedSubtitleType = SubtitleTypeNone; + hud->queuedSubtitleKey = SubtitleKeyNone; + hud->subtitleFadeTime = SUBTITLE_SLOW_FADE_TIME; + hud->subtitleExpireTimer = CAPTION_EXPIRE_TIME; + } + return; } - else{ - hud->flags |= HudFlagsShowingSubtitle; - hud->subtitleType = subtitleType; - hud->subtitleFadeTime = 0.75; + else if (subtitleType == SubtitleTypeCloseCaption) { + if (hud->flags & HudFlagsShowingSubtitle){ + hud->flags |= HudFlagsSubtitleQueued; + hud->queuedSubtitleKey = subtitleKey; + hud->queuedSubtitleType = subtitleType; + hud->subtitleFadeTime = SUBTITLE_FAST_FADE_TIME; + } + else{ + hud->flags |= HudFlagsShowingSubtitle; + hud->flags &= ~HudFlagsSubtitleQueued; + hud->subtitleKey = subtitleKey; + hud->subtitleType = subtitleType; + hud->queuedSubtitleType = SubtitleTypeNone; + hud->queuedSubtitleKey = SubtitleKeyNone; + hud->subtitleFadeTime = SUBTITLE_SLOW_FADE_TIME; + } + return; } - - - } void hudResolvePrompt(struct Hud* hud, enum CutscenePromptType promptType) { @@ -183,7 +244,9 @@ void hudResolvePrompt(struct Hud* hud, enum CutscenePromptType promptType) { } void hudResolveSubtitle(struct Hud* hud) { + hud->flags &= ~HudFlagsShowingSubtitle; + hud->subtitleFadeTime = SUBTITLE_SLOW_FADE_TIME; } void hudRender(struct Hud* hud, struct Player* player, struct RenderState* renderState) { @@ -301,7 +364,7 @@ void hudRender(struct Hud* hud, struct Player* player, struct RenderState* rende controlsRenderPrompt(gPromptActions[hud->promptType], gPromptText[hud->promptType], hud->promptOpacity, renderState); } - if (hud->subtitleOpacity > 0.0f && gSaveData.controls.flags & ControlSaveSubtitlesEnabled) { - controlsRenderSubtitle(SubtitleLanguageValues[hud->chosenLanguage][hud->subtitleType], hud->subtitleOpacity, hud->backgroundOpacity, renderState); + if (hud->subtitleOpacity > 0.0f && (gSaveData.controls.flags & ControlSaveSubtitlesEnabled || gSaveData.controls.flags & ControlSaveAllSubtitlesEnabled) && hud->subtitleKey != SubtitleKeyNone) { + controlsRenderSubtitle(SubtitleLanguageValues[hud->chosenLanguage][hud->subtitleKey], hud->subtitleOpacity, hud->backgroundOpacity, renderState, hud->subtitleType); } } \ No newline at end of file diff --git a/src/scene/hud.h b/src/scene/hud.h index e827f97..1cac6f8 100644 --- a/src/scene/hud.h +++ b/src/scene/hud.h @@ -4,29 +4,39 @@ #include "../graphics/renderstate.h" #include "../player/player.h" #include "../controls/controller_actions.h" +#include "../../build/src/audio/subtitles.h" #define INTRO_BLACK_TIME 3.0f #define INTRO_FADE_TIME 1.0f #define INTRO_TOTAL_TIME (INTRO_BLACK_TIME + INTRO_FADE_TIME) +enum SubtitleType { + SubtitleTypeNone, + SubtitleTypeCaption, + SubtitleTypeCloseCaption, +}; + enum HudFlags { HudFlagsLookedPortalable0 = (1 << 0), HudFlagsLookedPortalable1 = (1 << 1), HudFlagsShowingPrompt = (1 << 2), - HudFlagsShowingSubtitle= (1 << 3), - HudFlagsSubtitleQueued= (1 << 4), + HudFlagsShowingSubtitle = (1 << 3), + HudFlagsSubtitleQueued = (1 << 4), }; struct Hud { int chosenLanguage; enum CutscenePromptType promptType; - enum SubtitleKey subtitleType; - enum SubtitleKey queuedSubtitleType; + enum SubtitleKey subtitleKey; + enum SubtitleKey queuedSubtitleKey; + enum SubtitleType subtitleType; + enum SubtitleType queuedSubtitleType; float promptOpacity; float subtitleOpacity; float backgroundOpacity; float subtitleFadeTime; + float subtitleExpireTimer; float fadeInTimer; u16 flags; @@ -43,7 +53,7 @@ void hudUpdatePortalIndicators(struct Hud* hud, struct Ray* raycastRay, struct void hudPortalFired(struct Hud* hud, int index); void hudShowActionPrompt(struct Hud* hud, enum CutscenePromptType promptType); void hudResolvePrompt(struct Hud* hud, enum CutscenePromptType promptType); -void hudShowSubtitle(struct Hud* hud, enum SubtitleKey subtitleType); +void hudShowSubtitle(struct Hud* hud, enum SubtitleKey subtitleKey, enum SubtitleType subtitleType); void hudResolveSubtitle(struct Hud* hud); void hudRender(struct Hud* hud, struct Player* player, struct RenderState* renderState); diff --git a/src/scene/pedestal.c b/src/scene/pedestal.c index 9e20a1e..14fd767 100644 --- a/src/scene/pedestal.c +++ b/src/scene/pedestal.c @@ -9,6 +9,8 @@ #include "../build/assets/models/pedestal.h" #include "../../build/assets/models/dynamic_animated_model_list.h" #include "../../build/assets/models/portal_gun/w_portalgun.h" +#include "../scene/hud.h" +#include "../scene/scene.h" struct Vector2 gMaxPedistalRotation; #define MAX_PEDISTAL_ROTATION_DEGREES_PER_SEC (M_PI / 3.0f) @@ -102,6 +104,7 @@ void pedestalUpdate(struct Pedestal* pedestal) { else{ if (!(pedestal->flags & PedestalFlagsAlreadyMoving) && !(pedestal->flags & PedestalFlagsDown)){ soundPlayerPlay(soundsPedestalMoving, 5.0f, 0.5f, &pedestal->transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTALGUN_PEDESTAL_ROTATE, SubtitleTypeCaption); pedestal->flags |= PedestalFlagsAlreadyMoving; } } @@ -116,6 +119,7 @@ void pedestalUpdate(struct Pedestal* pedestal) { void pedestalHide(struct Pedestal* pedestal) { soundPlayerPlay(soundsReleaseCube, 3.0f, 0.5f, &pedestal->transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, WEAPON_PORTALGUN_POWERUP, SubtitleTypeCaption); pedestal->flags |= PedestalFlagsDown; skAnimatorRunClip(&pedestal->animator, dynamicAssetClip(PEDESTAL_DYNAMIC_ANIMATED_MODEL, PEDESTAL_ARMATURE_HIDE_CLIP_INDEX), 0.0f, 0); } diff --git a/src/scene/scene.c b/src/scene/scene.c index 649c334..32be4f3 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -361,6 +361,7 @@ void sceneCheckPortals(struct Scene* scene) { scene->player.flags |= PlayerJustShotPortalGun; hudPortalFired(&scene->hud, 0); soundPlayerPlay(soundsPortalgunShoot[0], 1.0f, 1.0f, NULL, NULL, SoundTypeAll); + hudShowSubtitle(&gScene.hud, WEAPON_PORTALGUN_FIRE_RED, SubtitleTypeCaption); rumblePakClipPlay(&gFireGunRumbleWave); } @@ -369,6 +370,7 @@ void sceneCheckPortals(struct Scene* scene) { scene->player.flags |= PlayerJustShotPortalGun; hudPortalFired(&scene->hud, 1); soundPlayerPlay(soundsPortalgunShoot[1], 1.0f, 1.0f, NULL, NULL, SoundTypeAll); + hudShowSubtitle(&gScene.hud, WEAPON_PORTALGUN_FIRE_BLUE, SubtitleTypeCaption); rumblePakClipPlay(&gFireGunRumbleWave); } @@ -799,6 +801,11 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformInde collisionObjectUpdateBB(&portal->collisionObject); soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &portal->rigidBody.transform.position, &gZeroVec, SoundTypeAll); + if (portalIndex == 0){ + hudShowSubtitle(&gScene.hud, PORTAL_OPEN_RED, SubtitleTypeCaption); + } else { + hudShowSubtitle(&gScene.hud, PORTAL_OPEN_BLUE, SubtitleTypeCaption); + } if (fromPlayer) { portal->flags |= PortalFlagsPlayerPortal; @@ -972,6 +979,7 @@ int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* player void sceneClosePortal(struct Scene* scene, int portalIndex) { if (gCollisionScene.portalTransforms[portalIndex]) { soundPlayerPlay(soundsPortalFizzle, 1.0f, 1.0f, &gCollisionScene.portalTransforms[portalIndex]->position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_FIZZLE_MOVED, SubtitleTypeCaption); gCollisionScene.portalTransforms[portalIndex] = NULL; gCollisionScene.portalColliderIndex[portalIndex] = -1; scene->portals[portalIndex].portalSurfaceIndex = -1; diff --git a/src/scene/scene_animator.c b/src/scene/scene_animator.c index a14dedc..b08e984 100644 --- a/src/scene/scene_animator.c +++ b/src/scene/scene_animator.c @@ -60,7 +60,7 @@ void sceneAnimatorUpdate(struct SceneAnimator* sceneAnimator) { if (audioInfo->loopSoundId != SOUND_ID_NONE) { if (isMoving && state->soundId == SOUND_ID_NONE) { - state->soundId = soundPlayerPlay(audioInfo->loopSoundId, 1.0f, audioInfo->pitch, ¤tPos, &gZeroVec); + state->soundId = soundPlayerPlay(audioInfo->loopSoundId, 1.0f, audioInfo->pitch, ¤tPos, &gZeroVec, SoundTypeAll); } else if (isMoving && state->soundId != SOUND_ID_NONE) { soundPlayerUpdatePosition(state->soundId, ¤tPos, &gZeroVec); } else if (!isMoving && state->soundId != SOUND_ID_NONE) { @@ -70,11 +70,11 @@ void sceneAnimatorUpdate(struct SceneAnimator* sceneAnimator) { } if (isMoving && !wasMoving && audioInfo->startSoundId != SOUND_ID_NONE) { - soundPlayerPlay(audioInfo->startSoundId, 1.0f, audioInfo->pitch, ¤tPos, &gZeroVec); + soundPlayerPlay(audioInfo->startSoundId, 1.0f, audioInfo->pitch, ¤tPos, &gZeroVec, SoundTypeAll); } if (!wasMoving && isMoving && audioInfo->endSoundId != SOUND_ID_NONE) { - soundPlayerPlay(audioInfo->endSoundId, 1.0f, audioInfo->pitch, ¤tPos, &gZeroVec); + soundPlayerPlay(audioInfo->endSoundId, 1.0f, audioInfo->pitch, ¤tPos, &gZeroVec, SoundTypeAll); } state->lastPosition = currentPos; diff --git a/src/scene/switch.c b/src/scene/switch.c index 683ac68..e4b6e48 100644 --- a/src/scene/switch.c +++ b/src/scene/switch.c @@ -11,6 +11,8 @@ #include "../../build/assets/models/dynamic_animated_model_list.h" #include "../util/time.h" +#include "../scene/hud.h" +#include "../scene/scene.h" #define COLLIDER_HEIGHT 0.7f #define TICKTOCK_PAUSE_LENGTH 0.25f @@ -105,7 +107,9 @@ void switchActivate(struct Switch* switchObj) { return; } soundPlayerPlay(soundsButton, 1.0f, 0.5f, &switchObj->rigidBody.transform.position, &gZeroVec, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_BUTTON_DOWN, SubtitleTypeCaption); switchObj->ticktockSoundLoopId = soundPlayerPlay(soundsTickTock, 1.0f, 0.5f, NULL, NULL, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_ROOM1_TICKTOCK, SubtitleTypeCaption); switchObj->flags |= SwitchFlagsDepressed; switchObj->timeLeft = switchObj->duration; signalsSend(switchObj->signalIndex); @@ -144,6 +148,7 @@ void switchUpdate(struct Switch* switchObj) { }else{ switchObj->ticktockPauseTimer = 0; switchObj->ticktockSoundLoopId = soundPlayerPlay(soundsTickTock, 1.0f, 0.5f, NULL, NULL, SoundTypeAll); + hudShowSubtitle(&gScene.hud, PORTAL_ROOM1_TICKTOCK, SubtitleTypeCaption); } }else{ switchObj->ticktockPauseTimer = 0;