Switched scene update to state event

This commit is contained in:
2023-03-01 09:40:57 -08:00
parent 6aa7d317d1
commit 1061cda666
10 changed files with 438 additions and 473 deletions

View File

@ -36,8 +36,8 @@ void Scene::update() {
// TODO: Cleanup old scene items // TODO: Cleanup old scene items
// TODO: Tick scene items(?) // TODO: Tick scene items(?)
this->eventSceneUpdate.invoke(); this->eventSceneUpdate.invoke(game->timeManager.delta);
if(!this->game->timeManager.isPaused) this->eventSceneUnpausedUpdate.invoke(); if(!this->game->timeManager.isPaused) this->eventSceneUnpausedUpdate.invoke(game->timeManager.delta);
} }
SceneItem * Scene::createSceneItem() { SceneItem * Scene::createSceneItem() {

View File

@ -21,7 +21,7 @@ namespace Dawn {
template<class T> template<class T>
T * _sceneForwardGetComponent(SceneItem *item); T * _sceneForwardGetComponent(SceneItem *item);
class Scene : public StateOwner { class Scene {
private: private:
sceneitemid_t nextId; sceneitemid_t nextId;
std::map<sceneitemid_t, SceneItem*> items; std::map<sceneitemid_t, SceneItem*> items;
@ -30,8 +30,8 @@ namespace Dawn {
public: public:
DawnGame *game; DawnGame *game;
ScenePhysicsManager *physics; ScenePhysicsManager *physics;
Event<> eventSceneUpdate; StateEvent<float_t> eventSceneUpdate;
Event<> eventSceneUnpausedUpdate; StateEvent<float_t> eventSceneUnpausedUpdate;
/** /**
* Construct a new Scene instance. * Construct a new Scene instance.

View File

@ -22,10 +22,10 @@ void AnimationController::addAnimation(Animation *animation) {
void AnimationController::onStart() { void AnimationController::onStart() {
SceneItemComponent::onStart(); SceneItemComponent::onStart();
useEventLegacy([&]{ useEvent([&](float_t delta){
auto it = this->animations.begin(); auto it = this->animations.begin();
while(it != this->animations.end()) { while(it != this->animations.end()) {
(*it)->tick(this->getGame()->timeManager.delta); (*it)->tick(delta);
++it; ++it;
} }
}, getScene()->eventSceneUnpausedUpdate); }, getScene()->eventSceneUnpausedUpdate);

View File

@ -28,11 +28,11 @@ ExampleSpin::ExampleSpin(SceneItem *item) :
} }
void ExampleSpin::onStart() { void ExampleSpin::onStart() {
useEventLegacy([&]{ useEvent([&](float_t delta){
auto quat = this->transform->getLocalRotation(); auto quat = this->transform->getLocalRotation();
quat = glm::rotate(quat, getGame()->timeManager.delta, glm::vec3(0, 1, 0)); quat = glm::rotate(quat, delta, glm::vec3(0, 1, 0));
quat = glm::rotate(quat, getGame()->timeManager.delta / 2.0f, glm::vec3(1, 0, 0)); quat = glm::rotate(quat, delta / 2.0f, glm::vec3(1, 0, 0));
quat = glm::rotate(quat, getGame()->timeManager.delta / 4.0f, glm::vec3(0, 0, 1)); quat = glm::rotate(quat, delta / 4.0f, glm::vec3(0, 0, 1));
this->transform->setLocalRotation(quat); this->transform->setLocalRotation(quat);
}, getScene()->eventSceneUnpausedUpdate); }, getScene()->eventSceneUnpausedUpdate);
} }

View File

@ -14,13 +14,13 @@ SubSceneController::SubSceneController(SceneItem *i) : SceneItemComponent(i) {
void SubSceneController::onStart() { void SubSceneController::onStart() {
auto myScene = this->getScene(); auto myScene = this->getScene();
useEventLegacy([&]{ useEvent([&](float_t d){
if(!this->onlyUpdateUnpaused) return; if(!this->onlyUpdateUnpaused) return;
if(this->subScene == nullptr) return; if(this->subScene == nullptr) return;
this->subScene->update(); this->subScene->update();
}, myScene->eventSceneUnpausedUpdate); }, myScene->eventSceneUnpausedUpdate);
useEventLegacy([&]{ useEvent([&](float_t d){
if(this->onlyUpdateUnpaused) return; if(this->onlyUpdateUnpaused) return;
if(this->subScene == nullptr) return; if(this->subScene == nullptr) return;
this->subScene->update(); this->subScene->update();

View File

@ -67,7 +67,7 @@ void UICanvas::onStart() {
}, this->currentMenu); }, this->currentMenu);
// Scene Update // Scene Update
useEventLegacy([&]{ useEvent([&](float_t delta){
if(this->currentMenu == nullptr) return; if(this->currentMenu == nullptr) return;
this->currentMenu->onTick(); this->currentMenu->onTick();
}, getScene()->eventSceneUpdate); }, getScene()->eventSceneUpdate);

View File

@ -8,7 +8,10 @@
using namespace Dawn; using namespace Dawn;
AudioSource::AudioSource(SceneItem *i) : SceneItemComponent(i) { AudioSource::AudioSource(SceneItem *i) :
SceneItemComponent(i),
playMode(AUDIO_PLAY_MODE_UNPAUSED)
{
} }
@ -107,8 +110,113 @@ void AudioSource::onStart() {
this->ready = true; this->ready = true;
// Listen for events // Listen for events
this->transform->eventTransformUpdated.addListener(this, &AudioSource::onTransformUpdate); useEventLegacy([&]{
this->getScene()->eventSceneUpdate.addListener(this, &AudioSource::onSceneUpdate); glm::vec3 position = this->transform->getWorldPosition();
alSource3f(this->source, AL_POSITION, position.x, position.y, position.z);
}, this->transform->eventTransformUpdated);
useEvent([&](float_t delta){
ALuint bufferId;
ALint buffersProcessed;
assertTrue(this->ready);
// What is the user trying to do?
if(this->state == AUDIO_SOURCE_STATE_PLAYING) {
assertTrue(this->data != nullptr);
assertTrue(this->data->loaded);
// Handle the special game-paused music-paused state.
if(this->playMode == AUDIO_PLAY_MODE_UNPAUSED && this->getGame()->timeManager.isPaused) {
if(this->internalState == AUDIO_SOURCE_STATE_PLAYING) {
// Functionally, this is the same as pausing
alSourcePause(this->source);
this->internalState = AUDIO_SOURCE_STATE_PAUSED;
}
return;// Do nothing else, at all.
}
// They are trying to play. We need to check if we are already playing
if(this->internalState == AUDIO_SOURCE_STATE_PLAYING) {
// We are good to continue buffering audio data.
buffersProcessed = 0;
alGetSourcei(this->source, AL_BUFFERS_PROCESSED, &buffersProcessed);
while(buffersProcessed > 0) {
alSourceUnqueueBuffers(this->source, 1, &bufferId);
this->fillBuffer(bufferId);
alSourceQueueBuffers(this->source, 1, &bufferId);
buffersProcessed--;
// Now, before we go to the next buffer let's see if we need to
// update the internal state
if(this->bufferPosition != 0) continue;
// We reached the end of the buffer whilst filling. What to do now?
if(this->loop) {
// We're looping so it's fine
this->eventLooped.invoke();
continue;
}
// We are NOT looping, so we need to finish here.
this->state = AUDIO_SOURCE_STATE_STOPPED;
this->eventFinished.invoke();
this->bufferPosition = 0;
buffersProcessed = 0;
}
} else if(this->internalState == AUDIO_SOURCE_STATE_STOPPED) {
// Not yet playing. First thing we need to do is fill the buffers.
for(int32_t i = 0; i < AUDIO_SOURCE_BUFFER_COUNT; i++) {
this->fillBuffer(this->buffers[i]);
}
// Now attach the buffers
this->attachBuffers();
// And begin playing
alSourcePlay(this->source);
this->internalState = AUDIO_SOURCE_STATE_PLAYING;
this->eventPlaying.invoke();
} else if(AUDIO_SOURCE_STATE_PAUSED) {
// Request to resume
alSourcePlay(this->source);
this->eventResumed.invoke();
this->internalState = AUDIO_SOURCE_STATE_PLAYING;
} else {
assertUnreachable();
}
} else if(this->state == AUDIO_SOURCE_STATE_PAUSED) {
assertTrue(this->data != nullptr);
assertTrue(this->data->loaded);
// Pause has been requested.
if(this->internalState != AUDIO_SOURCE_STATE_PLAYING) return;
// We are playing something, pause it
alSourcePause(this->source);
this->internalState = AUDIO_SOURCE_STATE_PAUSED;
this->eventPaused.invoke();
} else if(this->state == AUDIO_SOURCE_STATE_STOPPED) {
if(this->internalState == AUDIO_SOURCE_STATE_STOPPED) return;
assertTrue(this->data != nullptr);
assertTrue(this->data->loaded);
// Release the buffers
alSourceStop(this->source);
this->detatchBuffers();
this->internalState = AUDIO_SOURCE_STATE_STOPPED;
this->eventStopped.invoke();
this->bufferPosition = 0;
} else {
assertUnreachable();
}
}, getScene()->eventSceneUpdate);
} }
AudioSourceState AudioSource::getRealState() { AudioSourceState AudioSource::getRealState() {
@ -128,14 +236,6 @@ void AudioSource::setAudioData(AudioAsset *data) {
this->rewind(); this->rewind();
} }
enum AudioSourcePlayMode AudioSource::getPlayMode() {
return this->playMode;
}
void AudioSource::setPlayMode(enum AudioSourcePlayMode playMode) {
this->playMode = playMode;
}
void AudioSource::stop() { void AudioSource::stop() {
this->state = AUDIO_SOURCE_STATE_STOPPED; this->state = AUDIO_SOURCE_STATE_STOPPED;
} }
@ -152,117 +252,6 @@ void AudioSource::onDispose() {
assertTrue(this->ready); assertTrue(this->ready);
this->ready = false; this->ready = false;
this->getScene()->eventSceneUpdate.removeListener(this, &AudioSource::onSceneUpdate);
this->transform->eventTransformUpdated.removeListener(this, &AudioSource::onTransformUpdate);
alDeleteSources((ALuint)1, &this->source); alDeleteSources((ALuint)1, &this->source);
alDeleteBuffers((ALuint)AUDIO_SOURCE_BUFFER_COUNT, this->buffers); alDeleteBuffers((ALuint)AUDIO_SOURCE_BUFFER_COUNT, this->buffers);
} }
void AudioSource::onSceneUpdate() {
ALuint bufferId;
ALint buffersProcessed;
assertTrue(this->ready);
// What is the user trying to do?
if(this->state == AUDIO_SOURCE_STATE_PLAYING) {
assertTrue(this->data != nullptr);
assertTrue(this->data->loaded);
// Handle the special game-paused music-paused state.
if(this->playMode == AUDIO_PLAY_MODE_UNPAUSED && this->getGame()->timeManager.isPaused) {
if(this->internalState == AUDIO_SOURCE_STATE_PLAYING) {
// Functionally, this is the same as pausing
alSourcePause(this->source);
this->internalState = AUDIO_SOURCE_STATE_PAUSED;
}
return;// Do nothing else, at all.
}
// They are trying to play. We need to check if we are already playing
if(this->internalState == AUDIO_SOURCE_STATE_PLAYING) {
// We are good to continue buffering audio data.
buffersProcessed = 0;
alGetSourcei(this->source, AL_BUFFERS_PROCESSED, &buffersProcessed);
while(buffersProcessed > 0) {
alSourceUnqueueBuffers(this->source, 1, &bufferId);
this->fillBuffer(bufferId);
alSourceQueueBuffers(this->source, 1, &bufferId);
buffersProcessed--;
// Now, before we go to the next buffer let's see if we need to
// update the internal state
if(this->bufferPosition != 0) continue;
// We reached the end of the buffer whilst filling. What to do now?
if(this->loop) {
// We're looping so it's fine
this->eventLooped.invoke();
continue;
}
// We are NOT looping, so we need to finish here.
this->state = AUDIO_SOURCE_STATE_STOPPED;
this->eventFinished.invoke();
this->bufferPosition = 0;
buffersProcessed = 0;
}
} else if(this->internalState == AUDIO_SOURCE_STATE_STOPPED) {
// Not yet playing. First thing we need to do is fill the buffers.
for(int32_t i = 0; i < AUDIO_SOURCE_BUFFER_COUNT; i++) {
this->fillBuffer(this->buffers[i]);
}
// Now attach the buffers
this->attachBuffers();
// And begin playing
alSourcePlay(this->source);
this->internalState = AUDIO_SOURCE_STATE_PLAYING;
this->eventPlaying.invoke();
} else if(AUDIO_SOURCE_STATE_PAUSED) {
// Request to resume
alSourcePlay(this->source);
this->eventResumed.invoke();
this->internalState = AUDIO_SOURCE_STATE_PLAYING;
} else {
assertUnreachable();
}
} else if(this->state == AUDIO_SOURCE_STATE_PAUSED) {
assertTrue(this->data != nullptr);
assertTrue(this->data->loaded);
// Pause has been requested.
if(this->internalState != AUDIO_SOURCE_STATE_PLAYING) return;
// We are playing something, pause it
alSourcePause(this->source);
this->internalState = AUDIO_SOURCE_STATE_PAUSED;
this->eventPaused.invoke();
} else if(this->state == AUDIO_SOURCE_STATE_STOPPED) {
if(this->internalState == AUDIO_SOURCE_STATE_STOPPED) return;
assertTrue(this->data != nullptr);
assertTrue(this->data->loaded);
// Release the buffers
alSourceStop(this->source);
this->detatchBuffers();
this->internalState = AUDIO_SOURCE_STATE_STOPPED;
this->eventStopped.invoke();
this->bufferPosition = 0;
} else {
assertUnreachable();
}
}
void AudioSource::onTransformUpdate() {
glm::vec3 position = this->transform->getWorldPosition();
alSource3f(this->source, AL_POSITION, position.x, position.y, position.z);
}

View File

@ -34,7 +34,6 @@ namespace Dawn {
enum AudioSourceState internalState = AUDIO_SOURCE_STATE_STOPPED; enum AudioSourceState internalState = AUDIO_SOURCE_STATE_STOPPED;
int32_t layer = 0; int32_t layer = 0;
AudioAsset *data = nullptr; AudioAsset *data = nullptr;
AudioSourcePlayMode playMode = AUDIO_PLAY_MODE_UNPAUSED;
/** /**
* Internally update the audio's state based on the current settings. * Internally update the audio's state based on the current settings.
@ -47,11 +46,11 @@ namespace Dawn {
// Events // Events
void onSceneUpdate(); void onSceneUpdate();
void onTransformUpdate();
public: public:
bool_t loop = false; bool_t loop = false;
enum AudioSourceState state = AUDIO_SOURCE_STATE_STOPPED; enum AudioSourceState state = AUDIO_SOURCE_STATE_STOPPED;
AudioSourcePlayMode playMode;
Event<> eventPlaying; Event<> eventPlaying;
Event<> eventResumed; Event<> eventResumed;
@ -98,20 +97,6 @@ namespace Dawn {
*/ */
void setAudioData(AudioAsset *data); void setAudioData(AudioAsset *data);
/**
* Returns the play mode for the source.
*
* @return Current play mode.
*/
enum AudioSourcePlayMode getPlayMode();
/**
* Sets the play mode for the source.
*
* @param mode Play Mode to use.
*/
void setPlayMode(enum AudioSourcePlayMode mode);
/** /**
* Stop playing this audio source. Shorthand for setting the state. * Stop playing this audio source. Shorthand for setting the state.
*/ */

View File

@ -14,73 +14,67 @@ TicTacToeGame::TicTacToeGame(SceneItem *item) : SceneItemComponent(item) {}
void TicTacToeGame::onStart() { void TicTacToeGame::onStart() {
// Map tiles by tile number = tile // Map tiles by tile number = tile
auto tiles = getScene()->findComponents<TicTacToeTile>(); auto ts = getScene()->findComponents<TicTacToeTile>();
auto itTiles = tiles.begin(); auto itTiles = ts.begin();
while(itTiles != tiles.end()) { while(itTiles != ts.end()) {
this->tiles[(*itTiles)->tile] = *itTiles; this->tiles[(*itTiles)->tile] = *itTiles;
++itTiles; ++itTiles;
} }
// Listen // Listen
getScene()->eventSceneUpdate.addListener(this, &TicTacToeGame::onSceneUpdate); useEvent([&](float_t delta) {
} // Get mouse in screen space.
auto mouse = getGame()->inputManager.getAxis2D(INPUT_BIND_MOUSE_X, INPUT_BIND_MOUSE_Y);
mouse *= 2.0f;
mouse -= glm::vec2(1, 1);
void TicTacToeGame::onDispose() { Camera *camera = getScene()->findComponent<Camera>();
getScene()->eventSceneUpdate.removeListener(this, &TicTacToeGame::onSceneUpdate); if(camera == nullptr) return;
}
void TicTacToeGame::onSceneUpdate() { struct Ray3D ray;
// Get mouse in screen space. ray.origin = camera->transform->getWorldPosition();
auto mouse = getGame()->inputManager.getAxis2D(INPUT_BIND_MOUSE_X, INPUT_BIND_MOUSE_Y); ray.direction = camera->getRayDirectionFromScreenSpace(mouse);
mouse *= 2.0f;
mouse -= glm::vec2(1, 1);
Camera *camera = getScene()->findComponent<Camera>();
if(camera == nullptr) return;
struct Ray3D ray;
ray.origin = camera->transform->getWorldPosition();
ray.direction = camera->getRayDirectionFromScreenSpace(mouse);
// Find the hovered tile (if any) // Find the hovered tile (if any)
TicTacToeTile *hovered = nullptr; TicTacToeTile *hovered = nullptr;
auto results = getPhysics()->raycast3DAll(ray); auto results = getPhysics()->raycast3DAll(ray);
auto itResult = results.begin(); auto itResult = results.begin();
while(itResult != results.end()) { while(itResult != results.end()) {
auto result = *itResult; auto result = *itResult;
auto tile = result.collider->item->getComponent<TicTacToeTile>(); auto tile = result.collider->item->getComponent<TicTacToeTile>();
if(tile == nullptr) { if(tile == nullptr) {
++itResult; ++itResult;
continue; continue;
}
hovered = tile;
break;
}
// Now update the state of each tile, also get the state while we are at it
std::map<uint8_t, enum TicTacToeTileState> tileMap;
auto itTiles = tiles.begin();
while(itTiles != tiles.end()) {
auto t = itTiles->second;
if(t == hovered) {
if(t->tileState == TIC_TAC_TOE_EMPTY && getGame()->inputManager.isPressed(INPUT_BIND_MOUSE_CLICK)) {
t->tileState = nextMove;
nextMove = nextMove == TIC_TAC_TOE_NOUGHT ? TIC_TAC_TOE_CROSS : TIC_TAC_TOE_NOUGHT;
} else if(t->tileState == TIC_TAC_TOE_EMPTY) {
t->hovered = true;
} }
} else {
t->hovered = false;
}
tileMap[itTiles->second->tile] = itTiles->second->tileState;
++itTiles;
}
// Determine winner hovered = tile;
std::vector<uint8_t> winningCombo; break;
auto winner = ticTacToeDetermineWinner(tileMap, &winningCombo); }
// Now update the state of each tile, also get the state while we are at it
std::map<uint8_t, enum TicTacToeTileState> tileMap;
auto itTiles = tiles.begin();
while(itTiles != tiles.end()) {
auto t = itTiles->second;
if(t == hovered) {
if(t->tileState == TIC_TAC_TOE_EMPTY && getGame()->inputManager.isPressed(INPUT_BIND_MOUSE_CLICK)) {
t->tileState = nextMove;
nextMove = nextMove == TIC_TAC_TOE_NOUGHT ? TIC_TAC_TOE_CROSS : TIC_TAC_TOE_NOUGHT;
} else if(t->tileState == TIC_TAC_TOE_EMPTY) {
t->hovered = true;
}
} else {
t->hovered = false;
}
tileMap[itTiles->second->tile] = itTiles->second->tileState;
++itTiles;
}
// Determine winner
std::vector<uint8_t> winningCombo;
auto winner = ticTacToeDetermineWinner(tileMap, &winningCombo);
}, getScene()->eventSceneUpdate);
} }

View File

@ -17,8 +17,5 @@ namespace Dawn {
TicTacToeGame(SceneItem *item); TicTacToeGame(SceneItem *item);
void onStart() override; void onStart() override;
void onDispose() override;
void onSceneUpdate();
}; };
} }