Testing some event stuff

This commit is contained in:
2023-11-17 22:40:08 -06:00
parent 0c46c328fa
commit 26b5ec2c7f
20 changed files with 260 additions and 30 deletions

View File

@ -3,10 +3,10 @@
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# target_sources(${DAWN_TARGET_NAME}
# PRIVATE
# Game.cpp
# )
target_sources(${DAWN_TARGET_NAME}
PRIVATE
SimpleComponent.cpp
)
# Subdirs
add_subdirectory(display)

View File

@ -0,0 +1,27 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "SimpleComponent.hpp"
using namespace Dawn;
void SimpleComponent::onInit() {
this->initMethod(*this, events);
}
void SimpleComponent::onDispose() {
for(auto &event : events) {
event();
}
}
std::shared_ptr<SimpleComponent> Dawn::addSimpleComponent(
std::shared_ptr<SceneItem> item,
std::function<void(SceneComponent&, std::vector<std::function<void()>>&)> init
) {
auto cmp = item->addComponent<SimpleComponent>();
cmp->initMethod = init;
return cmp;
}

View File

@ -0,0 +1,31 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "scene/Scene.hpp"
namespace Dawn {
class SimpleComponent final : public SceneComponent {
private:
std::vector<std::function<void()>> events;
public:
std::function<void(
SceneComponent&,
std::vector<std::function<void()>>&
)> initMethod;
void onInit() override;
void onDispose() override;
};
std::shared_ptr<SimpleComponent> addSimpleComponent(
std::shared_ptr<SceneItem> item,
std::function<void(
SceneComponent&,
std::vector<std::function<void()>>&
)> init
);
}

View File

@ -10,11 +10,11 @@
using namespace Dawn;
void Camera::onInit() {
if(renderTarget == nullptr) {
this->setRenderTarget(
getGame()->renderHost.backBufferRenderTarget
);
}
this->onResizeListener = this->getRenderTarget()->onResize.listen([&](
float_t width, float_t height
) {
this->onResize.emit(this->getRenderTarget(), width, height);
});
}
void Camera::onDispose() {
@ -22,7 +22,8 @@ void Camera::onDispose() {
}
std::shared_ptr<RenderTarget> Camera::getRenderTarget() {
return this->renderTarget;
if(this->renderTarget) return this->renderTarget;
return getGame()->renderHost.getBackBufferRenderTarget();
}
glm::mat4 Camera::getProjection() {
@ -52,13 +53,15 @@ glm::mat4 Camera::getProjection() {
float_t Camera::getAspect() {
auto rt = this->getRenderTarget();
if(rt == nullptr) rt = getGame()->renderHost.getBackBufferRenderTarget();
return rt->getWidth() / rt->getHeight();
}
void Camera::setRenderTarget(std::shared_ptr<RenderTarget> renderTarget) {
if(this->renderTarget != nullptr) {
}
onResizeListener();
this->renderTarget = renderTarget;
this->onResizeListener = this->getRenderTarget()->onResize.listen([&](
float_t width, float_t height
) {
this->onResize.emit(this->getRenderTarget(), width, height);
});
}

View File

@ -16,8 +16,10 @@ namespace Dawn {
class Camera final : public SceneComponent {
private:
std::shared_ptr<RenderTarget> renderTarget;
std::function<void()> onResizeListener;
public:
Event<std::shared_ptr<RenderTarget>, float_t, float_t> onResize;
float_t clipNear = 0.01f;
float_t clipFar = 1000.0f;
enum CameraType type = CameraType::PERSPECTIVE;

View File

@ -44,13 +44,13 @@ void RenderPipeline::renderScene(
for(auto camera : cameras) {
auto rt = camera->getRenderTarget();
// Is this camera the backbuffer camera?
if(rt == backBuffer || rt == nullptr) {
if(rt == backBuffer) {
backbufferCamera = camera;
continue;
}
// Render scene with this camera
renderSceneCamera(game, scene, camera, camera->getRenderTarget());
renderSceneCamera(game, scene, camera, rt);
}
if(backbufferCamera) {

View File

@ -4,7 +4,7 @@
// https://opensource.org/licenses/MIT
#pragma once
#include "dawnlibs.hpp"
#include "event/Event.hpp"
#define RENDER_TARGET_CLEAR_COLOR 1 << 0
#define RENDER_TARGET_CLEAR_DEPTH 1 << 1
@ -12,6 +12,8 @@
namespace Dawn {
class RenderTarget {
public:
Event<float_t, float_t> onResize;
/**
* Return the width of the render target.
*

View File

@ -11,13 +11,20 @@ namespace Dawn {
class Event {
private:
int32_t nextId = 0;
std::unordered_map<int32, std::function<void(A...)>> listeners;
std::map<int32_t, std::function<void(A...)>> listeners;
public:
/**
* Constructs a new Event.
*/
Event() {
}
/**
* Emits the event.
* @param args The arguments to pass to the listeners.
*/
void emit(A ...args) {
auto copy = listeners;
for(auto &pair : copy) {
@ -25,6 +32,11 @@ namespace Dawn {
}
}
/**
* Listens to the event.
* @param listener The listener to add.
* @returns A function that can be called to remove the listener.
*/
std::function<void()> listen(const std::function<void(A...)> listener) {
int32_t id = nextId++;
listeners[id] = listener;
@ -33,8 +45,12 @@ namespace Dawn {
};
}
/**
* Removes a listener from the event.
* @param id The id of the listener to remove.
*/
virtual ~Event() {
listeners.clear();
}
}
};
}

View File

@ -22,14 +22,15 @@ void Game::init() {
}
void Game::update() {
timeManager.update();
renderHost.update(shared_from_this());
if(nextFrameScene) {
nextFrameScene->stage();
currentScene = nextFrameScene;
nextFrameScene = nullptr;
}
timeManager.update();
if(currentScene) currentScene->update();
renderHost.update(shared_from_this());
}
bool_t Game::isCloseRequested() {

View File

@ -14,8 +14,8 @@ namespace Dawn {
class Game : public std::enable_shared_from_this<Game> {
private:
std::shared_ptr<Scene> currentScene;
std::shared_ptr<Scene> nextFrameScene;
std::shared_ptr<Scene> currentScene = nullptr;
std::shared_ptr<Scene> nextFrameScene = nullptr;
public:
RenderHost renderHost;

View File

@ -22,6 +22,22 @@ void Scene::stage() {
sceneInitializer(selfReference);
}
void Scene::update() {
if(!hasInitialized) {
hasInitialized = true;
for(auto &item : sceneItems) {
item->init();
}
}
float_t delta = getGame()->timeManager.delta;
if(paused) {
onPausedUpdate.emit(delta);
} else {
onUnpausedUpdate.emit(delta);
}
}
std::shared_ptr<Game> Scene::getGame() {
return game.lock();
}

View File

@ -13,8 +13,13 @@ namespace Dawn {
std::weak_ptr<Game> game;
const std::function<void(Scene&)> sceneInitializer;
std::vector<std::shared_ptr<SceneItem>> sceneItems;
bool_t paused = false;
bool_t hasInitialized = false;
public:
Event<float_t> onUnpausedUpdate;
Event<float_t> onPausedUpdate;
/**
* Constructs a scene object.
*
@ -30,6 +35,14 @@ namespace Dawn {
*/
void stage();
/**
* Called by the game every frame that the scene is set as the currently
* active scene. This may not be sequential, for example a scene can be
* active, then switched to a different scene temporarily, and then can be
* switched back to the active one.
*/
void update();
/**
* Returns a copy of the game instance that this scene belongs to.
*

View File

@ -23,6 +23,13 @@ std::shared_ptr<Scene> SceneItem::getScene() {
return scene.lock();
}
void SceneItem::init() {
auto sharedThis = shared_from_this();
for(auto &component : components) {
component->init(sharedThis);
}
}
SceneItem::~SceneItem() {
std::for_each(
components.begin(),

View File

@ -29,6 +29,12 @@ namespace Dawn {
*/
SceneItem(const std::weak_ptr<Scene> scene);
/**
* Called when the scene item is supposed to initialize. Should happen
* on the first frame that the scene item is staged.
*/
void init();
/**
* Returns the scene that this scene item belongs to.
*

View File

@ -43,9 +43,6 @@ namespace Dawn {
this->components.push_back(
static_pointer_cast<SceneComponent>(component)
);
// Init compoonent and return
component->init(sceneItemComponentsSelf());
return component;
}

View File

@ -64,6 +64,29 @@ void SceneItemTransform::updateWorldTransformFromParent() {
this->updateChildrenWorldTransforms();
}
void SceneItemTransform::updateLocalTransformFromLocalValues() {
this->transformLocal = glm::translate(
glm::mat4(1.0f),
this->localPosition
) * glm::mat4_cast(this->localRotation) * glm::scale(
glm::mat4(1.0f),
this->localScale
);
this->updateWorldTransformFromLocalTransform();
}
void SceneItemTransform::updateWorldTransformFromLocalTransform() {
auto parent = this->getParent();
if(!parent) {
this->transformWorld = this->transformLocal;
} else {
this->transformWorld = (
parent->transformWorld * this->transformLocal
);
}
this->updateChildrenWorldTransforms();
}
std::shared_ptr<SceneItem> SceneItemTransform::getParent() {
return parent.lock();
}
@ -88,12 +111,39 @@ glm::mat4 SceneItemTransform::getWorldTransform() {
return this->transformWorld;
}
glm::vec3 SceneItemTransform::getLocalPosition() {
return this->localPosition;
}
glm::vec3 SceneItemTransform::getLocalScale() {
return this->localScale;
}
glm::quat SceneItemTransform::getLocalRotation() {
return this->localRotation;
}
void SceneItemTransform::setWorldTransform(const glm::mat4 transform) {
this->transformWorld = transform;
this->updateLocalTransformFromWorldTransform();
this->updateChildrenWorldTransforms();
}
void SceneItemTransform::setLocalPosition(const glm::vec3 position) {
this->localPosition = position;
this->updateLocalTransformFromLocalValues();
}
void SceneItemTransform::setLocalScale(const glm::vec3 scale) {
this->localScale = scale;
this->updateLocalTransformFromLocalValues();
}
void SceneItemTransform::setLocalRotation(const glm::quat rotation) {
this->localRotation = rotation;
this->updateLocalTransformFromLocalValues();
}
bool_t SceneItemTransform::isChildOf(std::shared_ptr<SceneItem> item) {
assertNotNull(item, "Cannot check if child of null item.");
auto parent = this->getParent();

View File

@ -45,6 +45,16 @@ namespace Dawn {
*/
void updateWorldTransformFromParent();
/**
* Updates the local transform of this item from the local values.
*/
void updateLocalTransformFromLocalValues();
/**
* Updates the world transform from this items local transform.
*/
void updateWorldTransformFromLocalTransform();
public:
SceneItemTransform();
@ -75,6 +85,27 @@ namespace Dawn {
* @return World transform of this item.
*/
glm::mat4 getWorldTransform();
/**
* Gets the local position of this item (relative to its parent).
*
* @return Local position of this item.
*/
glm::vec3 getLocalPosition();
/**
* Local scale of this item (relative to its parent).
*
* @return Local scale of this item.
*/
glm::vec3 getLocalScale();
/**
* Local rotation of this item (relative to its parent).
*
* @return Local rotation of this item.
*/
glm::quat getLocalRotation();
/**
* Sets the transform of this item within world space (relative to scene
@ -84,6 +115,27 @@ namespace Dawn {
*/
void setWorldTransform(const glm::mat4 transform);
/**
* Sets the local position of this item (relative to its parent).
*
* @param position Local position of this item.
*/
void setLocalPosition(const glm::vec3 position);
/**
* Sets the local scale of this item (relative to its parent).
*
* @param scale Local scale of this item.
*/
void setLocalScale(const glm::vec3 scale);
/**
* Sets the local rotation of this item (relative to its parent).
*
* @param rotation Local rotation of this item.
*/
void setLocalRotation(const glm::quat rotation);
/**
* Returns whether or not this item is a child of the given item. This
* will traverse up the entire heirarchy to confirm.

View File

@ -82,8 +82,6 @@ void RenderHost::init(const std::shared_ptr<Game> game) {
}
void RenderHost::update(const std::shared_ptr<Game> game) {
// Prepare the initial values
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
assertNoGLError();

View File

@ -8,6 +8,7 @@
#include "component/display/MeshRenderer.hpp"
#include "component/display/material/SimpleTexturedMaterial.hpp"
#include "display/mesh/CubeMesh.hpp"
#include "component/SimpleComponent.hpp"
using namespace Dawn;
@ -26,4 +27,11 @@ void Dawn::helloWorldScene(Scene &s) {
auto cubeMeshRenderer = cubeItem->addComponent<MeshRenderer>();
cubeMeshRenderer->mesh = cubeMesh;
auto cubeMaterial = cubeItem->addComponent<SimpleTexturedMaterial>();
addSimpleComponent(cubeItem, [](auto &cmp, auto &events) {
events.push_back(cmp.getScene()->onUnpausedUpdate.listen([&](float_t delta) {
auto item = cmp.getItem();
item->setLocalRotation(item->getLocalRotation() * glm::quat(glm::vec3(1, 1, 0) * delta));
// item->setLocalScale(item->getLocalScale() + glm::vec3(1, 1, 1) * delta);
}));
});
}

View File

@ -36,7 +36,8 @@ void BackBufferRenderTarget::setSize(
// Fixes a new bug that it seems GLFW has introduced.
this->width = width == 0 ? 1 : width;
this->height = height == 0 ? 1 : height;
// this->eventRenderTargetResized.invoke(*this, width, height);
onResize.emit(this->width, this->height);
}
void BackBufferRenderTarget::setClearColor(const struct Color color) {