Finish up clock implementation

This commit is contained in:
James Lambert 2023-06-29 21:10:58 -06:00
parent bcba882efd
commit 9ab44568d8
9 changed files with 159 additions and 2 deletions

View file

@ -843,7 +843,8 @@ materials:
clock_digits:
gDPSetTile:
filename: ./signage/clock_digits.png
siz: G_IM_SIZ_16b
siz: G_IM_SIZ_4b
twoTone: true
gDPSetCombineMode: G_CC_DECALRGBA
gDPSetCycleType: G_CYC_1CYCLE

Binary file not shown.

View file

@ -195,6 +195,15 @@ ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vecto
return result;
}
float soundClipDuration(int soundClipId, float pitch) {
if (soundClipId < 0 || soundClipId >= gSoundClipArray->soundCount) {
return 0.0f;
}
ALSound* alSound = gSoundClipArray->sounds[soundClipId];
return soundPlayerEstimateLength(alSound, pitch);
}
void soundPlayerUpdate() {
int index = 0;
int writeIndex = 0;
@ -321,6 +330,16 @@ int soundPlayerIsPlaying(ALSndId soundId) {
return activeSound->estimatedTimeLeft > 0.0f && alSndpGetState(&gSoundPlayer) != AL_STOPPED;
}
float soundPlayerTimeLeft(ALSndId soundId) {
struct ActiveSound* activeSound = soundPlayerFindActiveSound(soundId);
if (!activeSound) {
return 0.0f;
}
return activeSound->estimatedTimeLeft;
}
void soundListenerUpdate(struct Vector3* position, struct Quaternion* rotation, struct Vector3* velocity, int listenerIndex) {
gSoundListeners[listenerIndex].worldPos = *position;
gSoundListeners[listenerIndex].velocity = *velocity;

View file

@ -21,6 +21,7 @@ extern char _soundsTblSegmentRomEnd[];
void soundPlayerInit();
void soundPlayerUpdate();
ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vector3* at, struct Vector3* velocity);
float soundClipDuration(int soundClipId, float pitch);
void soundPlayerStop(ALSndId soundId);
void soundPlayerStopAll();
@ -31,6 +32,7 @@ void soundPlayerUpdatePosition(ALSndId soundId, struct Vector3* at, struct Vecto
void soundPlayerAdjustVolume(ALSndId soundId, float newVolume);
int soundPlayerIsPlaying(ALSndId soundId);
float soundPlayerTimeLeft(ALSndId soundId);
void soundListenerUpdate(struct Vector3* position, struct Quaternion* rotation, struct Vector3* velocity, int listenerIndex);
void soundListenerSetCount(int count);

View file

@ -7,6 +7,8 @@
#include "../util/memory.h"
#include "../savefile/checkpoint.h"
#include <math.h>
struct CutsceneRunner* gRunningCutscenes;
struct CutsceneRunner* gUnusedRunners;
u64 gTriggeredCutscenes;
@ -283,6 +285,32 @@ int cutsceneRunnerUpdateCurrentStep(struct CutsceneRunner* runner) {
}
}
float cutsceneSoundQueueTime(int channel);
float cutsceneStepEstimateTime(struct CutsceneStep* step, union CutsceneStepState* state) {
switch (step->type) {
case CutsceneStepTypePlaySound:
return state ? soundPlayerTimeLeft(state->playSound.soundId) : soundClipDuration(step->playSound.soundId, step->playSound.pitch * (1.0f / 64.0f));
case CutsceneStepTypeQueueSound:
return state ? soundPlayerTimeLeft(state->playSound.soundId) : soundClipDuration(step->queueSound.soundId, gCutsceneChannelPitch[step->queueSound.channel]);
case CutsceneStepTypeWaitForChannel:
{
return state ? cutsceneSoundQueueTime(step->waitForChannel.channel) : 0.0f;
}
case CutsceneStepTypeDelay:
return state ? state->delay : step->delay;
case CutsceneStepTypeWaitForSignal:
return 0.0f;
case CutsceneStepTypeWaitForCutscene:
return cutsceneEstimateTimeLeft(&gCurrentLevel->cutscenes[step->cutscene.cutsceneIndex]);
case CutsceneStepWaitForAnimation:
// Maybe todo
return 0.0f;
default:
return 0.0f;
}
}
void cutsceneRunnerRun(struct CutsceneRunner* runner, struct Cutscene* cutscene) {
runner->currentCutscene = cutscene;
runner->currentStep = 0;
@ -352,6 +380,23 @@ int cutsceneIsRunning(struct Cutscene* cutscene) {
return 0;
}
float cutsceneSoundQueueTime(int channel) {
float result = 0.0f;
if (soundPlayerIsPlaying(gCutsceneCurrentSound[channel])) {
result += soundPlayerTimeLeft(gCutsceneCurrentSound[channel]);
}
struct QueuedSound* curr = gCutsceneSoundQueues[channel];
while (curr) {
result += soundClipDuration(curr->soundId, gCutsceneChannelPitch[channel]);
curr = curr->next;
}
return result;
}
void cutscenesUpdateSounds() {
for (int i = 0; i < CH_COUNT; ++i) {
if (!soundPlayerIsPlaying(gCutsceneCurrentSound[i])) {
@ -397,6 +442,30 @@ void cutscenesUpdate() {
}
}
float cutsceneRunnerEstimateTimeLeft(struct CutsceneRunner* cutsceneRunner) {
float result = 0.0f;
for (int i = cutsceneRunner->currentStep; i < cutsceneRunner->currentCutscene->stepCount; ++i) {
result += cutsceneStepEstimateTime(&cutsceneRunner->currentCutscene->steps[i], i == cutsceneRunner->currentStep ? &cutsceneRunner->state : NULL);
}
return result;
}
float cutsceneEstimateTimeLeft(struct Cutscene* cutscene) {
struct CutsceneRunner* current = gRunningCutscenes;
while (current) {
if (current->currentCutscene == cutscene) {
return cutsceneRunnerEstimateTimeLeft(current);
}
current = current->nextRunner;
}
return 0.0f;
}
void cutsceneCheckTriggers(struct Vector3* playerPos) {
for (int i = 0; i < gCurrentLevel->triggerCount; ++i) {

View file

@ -32,6 +32,7 @@ void cutsceneStart(struct Cutscene* cutscene);
void cutsceneStop(struct Cutscene* cutscene);
int cutsceneIsRunning(struct Cutscene* cutscene);
void cutscenesUpdate();
float cutsceneEstimateTimeLeft(struct Cutscene* cutscene);
void cutsceneCheckTriggers(struct Vector3* playerPos);

View file

@ -3,11 +3,68 @@
#include "../scene/dynamic_scene.h"
#include "../defs.h"
#include "../levels/levels.h"
#include "../levels/cutscene_runner.h"
#include "../build/assets/models/signage/clock.h"
#include "../build/assets/models/signage/clock_digits.h"
#include "../../build/assets/materials/static.h"
#include <math.h>
#define DIGIT_WIDTH 512
u8 gCurrentClockDigits[5];
Vtx* gClockDigits[] = {
signage_clock_digits_clock_digits_minute_01_color,
signage_clock_digits_clock_digits_second_10_color,
signage_clock_digits_clock_digits_second_01_color,
signage_clock_digits_clock_digits_ms_10_color,
signage_clock_digits_clock_digits_ms_01_color,
};
void clockSetDigit(int digitIndex, int currDigit) {
int prevDigit = gCurrentClockDigits[digitIndex];
if (prevDigit == currDigit) {
return;
}
for (int i = 0; i < 4; ++i) {
gClockDigits[digitIndex][i].v.tc[0] += (currDigit - prevDigit) * DIGIT_WIDTH;
}
gCurrentClockDigits[digitIndex] = (u8)currDigit;
osWritebackDCache(gClockDigits[digitIndex], sizeof(Vtx) * 4);
}
void clockSetTime(float timeInSeconds) {
float minutes = floor(timeInSeconds * (1.0f / 60.0f));
clockSetDigit(0, (int)minutes);
timeInSeconds -= minutes *= 60.0f;
float tenSeconds = floor(timeInSeconds * 0.1f);
clockSetDigit(1, (int)tenSeconds);
timeInSeconds -= tenSeconds * 10.0f;
float seconds = floor(timeInSeconds);
clockSetDigit(2, (int)seconds);
timeInSeconds -= seconds;
float tenthsOfSecond = floor(timeInSeconds * 10.0f);
clockSetDigit(3, (int)tenthsOfSecond);
timeInSeconds -= tenthsOfSecond * 0.1f;
clockSetDigit(4, (int)floor(timeInSeconds * 100.0f));
}
void clockRenderRender(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState) {
struct Clock* clock = (struct Clock*)data;
@ -17,6 +74,14 @@ void clockRenderRender(void* data, struct DynamicRenderDataList* renderList, str
return;
}
float time = 0.0f;
if (clock->cutsceneIndex != -1) {
time = cutsceneEstimateTimeLeft(&gCurrentLevel->cutscenes[clock->cutsceneIndex]);
}
clockSetTime(time);
transformToMatrixL(&clock->transform, matrix, SCENE_SCALE);
dynamicRenderListAddData(
@ -30,7 +95,7 @@ void clockRenderRender(void* data, struct DynamicRenderDataList* renderList, str
dynamicRenderListAddData(
renderList,
signage_clock_model_gfx,
signage_clock_digits_model_gfx,
matrix,
CLOCK_DIGITS_INDEX,
&clock->transform.position,