I just made C++ God and it's scary

This commit is contained in:
2023-02-26 21:56:39 -08:00
parent 451b5b067e
commit cd0a5a2155
15 changed files with 221 additions and 96 deletions

View File

@ -33,6 +33,7 @@ add_subdirectory(physics)
add_subdirectory(prefab)
add_subdirectory(save)
add_subdirectory(scene)
add_subdirectory(state)
add_subdirectory(time)
add_subdirectory(ui)

View File

@ -45,6 +45,10 @@ void SceneItemComponent::onDispose() {
}
void SceneItemComponent::onStateUpdate() {
}
SceneItemComponent::~SceneItemComponent() {
}

View File

@ -7,11 +7,12 @@
#include "dawnlibs.hpp"
#include "display/Transform.hpp"
#include "scene/SceneItem.hpp"
#include "state/State.hpp"
namespace Dawn {
class DawnGame;
class SceneItemComponent {
class SceneItemComponent : public StateOwner {
public:
SceneItem *item;
Transform *transform;
@ -70,6 +71,7 @@ namespace Dawn {
*/
virtual void onDispose();
virtual void onStateUpdate();
/**
* Cleanup the SceneItemComponent.

View File

@ -0,0 +1,11 @@
# Copyright (c) 2023 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
StateOwner.cpp
StateProperty.cpp
)

9
src/dawn/state/State.hpp Normal file
View File

@ -0,0 +1,9 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "StateOwner.hpp"
#include "StateProperty.hpp"

View File

@ -0,0 +1,8 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "State.hpp"
using namespace Dawn;

View File

@ -0,0 +1,73 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "assert/assert.hpp"
namespace Dawn {
template<class V>
class StateProperty;
class StateOwner {
private:
std::map<void*, std::vector<std::function<void()>>> effects;
public:
/**
* Invoked event listener for the subclass that listens for all changes
* to any part of this state updated.
*/
virtual void onStateUpdate() = 0;
/**
* Creates a new state property and listens for its change.
*
* @tparam V The type of the state that is held.
* @param initial The initial value of this state.
* @return The state that can then be listened for.
*/
template<class V>
StateProperty<V> useState(V initial) {
auto property = StateProperty<V>();
property.value = initial;
property.owner = this;
return property;
}
/**
* Listen for changees to a state property and involke the provided func
* when the value is changed.
*
* @tparam V The type of the state property.
* @param property Property to listen for affect changees to.
* @param fn The callback to be invoked when the state value changes.
*/
template<class V>
void useEffect(StateProperty<V> &property, const std::function<void()> &fn) {
this->effects[(void*)&property].push_back(fn);
}
/**
* Internal method (that has to be exposed) to listen for changes for when
* a state property that belongs to this state owner is updated.
*
* @tparam V The value type of the state property.
* @param prop The property that has its value changed in question.
* @param n The new, current value of the property.
* @param o The old, previous value of the property.
*/
template<class V>
void onStatePropertyUpdated(StateProperty<V> *prop, V n, V o) {
this->onStateUpdate();
auto eff = &this->effects[prop];
auto itEff = eff->begin();
while(itEff != eff->end()) {
(*itEff)();
++itEff;
}
}
};
}

View File

@ -0,0 +1,8 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "State.hpp"
using namespace Dawn;

View File

@ -0,0 +1,49 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "StateOwner.hpp"
namespace Dawn {
template<class V>
class StateProperty {
private:
StateOwner *owner;
V value;
void setInternal(V val) {
if(val == this->value) return;// TODO: can I omit this? kinda bad tbh.
assertNotNull(this->owner);
auto old = this->value;
this->value = val;
this->owner->onStatePropertyUpdated(this, val, old);
}
public:
const StateProperty& operator += (const V &value) {
this->setInternal(this->value + value);
return *this;
}
const bool_t operator != (const V &value) {
return value != this->value;
}
const bool_t operator == (const V &value) {
return value == this->value;
}
const StateProperty& operator = (const V &val) {
this->setInternal(val);
return *this;
}
operator V() const {
return this->value;
}
friend class StateOwner;
};
}

View File

@ -30,4 +30,5 @@ extern "C" {
#include <memory>
#include <algorithm>
#include <sstream>
#include <string>
#include <string>
#include <functional>

View File

@ -67,16 +67,16 @@ void TicTacToeGame::onSceneUpdate() {
auto t = itTiles->second;
if(t == hovered) {
if(t->state == TIC_TAC_TOE_EMPTY && getGame()->inputManager.isPressed(INPUT_BIND_MOUSE_CLICK)) {
t->setState(nextMove);
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->state == TIC_TAC_TOE_EMPTY) {
} else if(t->tileState == TIC_TAC_TOE_EMPTY) {
t->hovered = true;
}
} else {
t->hovered = false;
}
tileMap[itTiles->second->tile] = itTiles->second->getState();
tileMap[itTiles->second->tile] = itTiles->second->tileState;
++itTiles;
}

View File

@ -12,17 +12,19 @@ TicTacToeTile::TicTacToeTile(SceneItem *item) : SceneItemComponent(item) {
}
void TicTacToeTile::onStart() {
this->setState(TIC_TAC_TOE_EMPTY);
}
tileState = useState(TIC_TAC_TOE_EMPTY);
hovered = useState(false);
enum TicTacToeTileState TicTacToeTile::getState() {
return this->state;
}
auto cb = [&]{
auto sprite = this->item->getComponent<TiledSprite>();
if(this->hovered) {
sprite->setTile(0x03);
} else {
sprite->setTile(tileState);
}
};
void TicTacToeTile::setState(enum TicTacToeTileState state) {
auto ts = this->item->getComponent<TiledSprite>();
ts->setTile(state);
this->state = state;
useEffect(tileState, cb);
useEffect(hovered, cb);
cb();
}

View File

@ -11,16 +11,12 @@
namespace Dawn {
class TicTacToeTile : public SceneItemComponent {
public:
enum TicTacToeTileState state = TIC_TAC_TOE_EMPTY;
bool_t hovered = false;
StateProperty<enum TicTacToeTileState> tileState;
StateProperty<bool_t> hovered;
uint8_t tile;
TicTacToeTile(SceneItem *item);
void onStart() override;
enum TicTacToeTileState getState();
void setState(enum TicTacToeTileState state);
};
}

View File

@ -10,8 +10,11 @@
#include "display/mesh/TriangleMesh.hpp"
#include "components/TicTacToeGame.hpp"
#include "state/State.hpp"
namespace Dawn {
class TicTacToeScene : public Scene {
class TicTacToeScene : public Scene, public StateOwner {
protected:
Camera *camera;
@ -39,6 +42,10 @@ namespace Dawn {
}
}
}
void onStateUpdate() override {
std::cout << "State Update Invoked" << std::endl;
}
std::vector<Asset*> getRequiredAssets() override {
auto assMan = &this->game->assetManager;