Updated more scene item coponents to state system

This commit is contained in:
2023-03-01 09:25:07 -08:00
parent 94d15b20cc
commit 2013600622
11 changed files with 256 additions and 360 deletions

View File

@ -34,7 +34,7 @@ void RenderPipeline::renderScene(Scene *scene) {
auto subSceneControllers = scene->findComponents<SubSceneController>(); auto subSceneControllers = scene->findComponents<SubSceneController>();
auto itSubScene = subSceneControllers.begin(); auto itSubScene = subSceneControllers.begin();
while(itSubScene != subSceneControllers.end()) { while(itSubScene != subSceneControllers.end()) {
auto subScene = (*itSubScene)->getSubScene(); Scene *subScene = (Scene *)((*itSubScene)->subScene);
if(subScene == nullptr) { if(subScene == nullptr) {
++itSubScene; ++itSubScene;
continue; continue;

View File

@ -19,24 +19,20 @@ SceneItem * ExampleSpin::create(Scene *scene) {
CubeMesh::buffer(mr->mesh, glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(1, 1, 1), 0, 0); CubeMesh::buffer(mr->mesh, glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(1, 1, 1), 0, 0);
auto mat = item->addComponent<SimpleTexturedMaterial>(); auto mat = item->addComponent<SimpleTexturedMaterial>();
item->addComponent<ExampleSpin>(); item->addComponent<ExampleSpin>();
return item; return item;
} }
ExampleSpin::ExampleSpin(SceneItem *item) : ExampleSpin::ExampleSpin(SceneItem *item) :
SceneItemComponent(item) SceneItemComponent(item)
{ {
getScene()->eventSceneUnpausedUpdate.addListener(this, &ExampleSpin::onUnpausedUpdate);
} }
void ExampleSpin::onUnpausedUpdate() { void ExampleSpin::onStart() {
auto quat = this->transform->getLocalRotation(); useEventLegacy([&]{
quat = glm::rotate(quat, getGame()->timeManager.delta, glm::vec3(0, 1, 0)); auto quat = this->transform->getLocalRotation();
quat = glm::rotate(quat, getGame()->timeManager.delta / 2.0f, glm::vec3(1, 0, 0)); quat = glm::rotate(quat, getGame()->timeManager.delta, glm::vec3(0, 1, 0));
quat = glm::rotate(quat, getGame()->timeManager.delta / 4.0f, glm::vec3(0, 0, 1)); quat = glm::rotate(quat, getGame()->timeManager.delta / 2.0f, glm::vec3(1, 0, 0));
this->transform->setLocalRotation(quat); quat = glm::rotate(quat, getGame()->timeManager.delta / 4.0f, glm::vec3(0, 0, 1));
} this->transform->setLocalRotation(quat);
}, getScene()->eventSceneUnpausedUpdate);
void ExampleSpin::onDispose() {
getScene()->eventSceneUnpausedUpdate.removeListener(this, &ExampleSpin::onUnpausedUpdate);
} }

View File

@ -1,19 +1,18 @@
// Copyright (c) 2022 Dominic Masters // Copyright (c) 2022 Dominic Masters
// //
// This software is released under the MIT License. // This software is released under the MIT License.
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#pragma once #pragma once
#include "scene/SceneItemComponent.hpp" #include "scene/SceneItemComponent.hpp"
#include "display/shader/Shader.hpp" #include "display/shader/Shader.hpp"
namespace Dawn { namespace Dawn {
class ExampleSpin : public SceneItemComponent { class ExampleSpin : public SceneItemComponent {
public: public:
static SceneItem * create(Scene *scene); static SceneItem * create(Scene *scene);
ExampleSpin(SceneItem *item); ExampleSpin(SceneItem *item);
void onUnpausedUpdate(); void onStart() override;
void onDispose() override; };
};
} }

View File

@ -7,18 +7,11 @@
using namespace Dawn; using namespace Dawn;
SubSceneCameraAlign::SubSceneCameraAlign(SceneItem *i) : SceneItemComponent(i) { SubSceneCameraAlign::SubSceneCameraAlign(SceneItem *i) :
SceneItemComponent(i),
} camera(nullptr),
renderTarget(nullptr)
void SubSceneCameraAlign::onRenderTargetResize( {
RenderTarget *target, float_t w, float_t h
) {
this->realign();
}
void SubSceneCameraAlign::onCameraResize(float_t w, float_t h) {
this->realign();
} }
void SubSceneCameraAlign::realign() { void SubSceneCameraAlign::realign() {
@ -27,7 +20,7 @@ void SubSceneCameraAlign::realign() {
if(this->renderTarget == nullptr) return; if(this->renderTarget == nullptr) return;
float_t ratio = this->renderTarget->getWidth() / this->renderTarget->getHeight(); float_t ratio = this->renderTarget->getWidth() / this->renderTarget->getHeight();
float_t myRatio = this->camera->getRenderTarget()->getWidth() / this->camera->getRenderTarget()->getHeight(); float_t myRatio = this->camera->getAspect();
this->camera->type = CAMERA_TYPE_ORTHONOGRAPHIC; this->camera->type = CAMERA_TYPE_ORTHONOGRAPHIC;
this->camera->transform->lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0)); this->camera->transform->lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0));
@ -49,57 +42,27 @@ void SubSceneCameraAlign::realign() {
} }
} }
void SubSceneCameraAlign::setRenderTarget(TextureRenderTarget *renderTarget) {
assertTrue(this->renderTarget != renderTarget);
if(this->renderTarget != nullptr) {
this->renderTarget->eventRenderTargetResized.removeListener(
this, &SubSceneCameraAlign::onRenderTargetResize
);
}
this->renderTarget = renderTarget;
this->realign();
if(this->renderTarget != nullptr) {
this->renderTarget->eventRenderTargetResized.addListener(
this, &SubSceneCameraAlign::onRenderTargetResize
);
}
}
void SubSceneCameraAlign::setCamera(Camera *camera) {
assertTrue(this->camera != camera);
if(this->camera != nullptr) {
this->camera->eventRenderTargetResized.removeListener(
this, &SubSceneCameraAlign::onCameraResize
);
}
this->camera = camera;
this->realign();
if(this->camera != nullptr) {
this->camera->eventRenderTargetResized.addListener(
this, &SubSceneCameraAlign::onCameraResize
);
}
}
void SubSceneCameraAlign::onStart() { void SubSceneCameraAlign::onStart() {
this->realign(); auto cameraEffect = useEffectWithTeardown([&]{
} if(camera == nullptr) return evtCameraResized = [&] {};
void SubSceneCameraAlign::onDispose() { this->realign();
if(this->renderTarget != nullptr) {
this->renderTarget->eventRenderTargetResized.removeListener( return evtCameraResized = useEvent([&](float_t w, float_t h){
this, &SubSceneCameraAlign::onRenderTargetResize this->realign();
); }, this->camera->event2RenderTargetResized);
} }, this->camera);
if(this->camera != nullptr) {
this->camera->eventRenderTargetResized.removeListener( auto renderEffect = useEffectWithTeardown([&]{
this, &SubSceneCameraAlign::onCameraResize if(renderTarget == nullptr) return evtRenderResized = [&]{};
);
} this->realign();
return evtRenderResized = useEventLegacy([&](RenderTarget *t, float_t w, float_t h) {
this->realign();
}, renderTarget->eventRenderTargetResized);
}, this->renderTarget);
cameraEffect();
renderEffect();
} }

View File

@ -11,11 +11,8 @@
namespace Dawn { namespace Dawn {
class SubSceneCameraAlign : public SceneItemComponent { class SubSceneCameraAlign : public SceneItemComponent {
protected: protected:
TextureRenderTarget *renderTarget = nullptr; std::function<void()> evtCameraResized;
Camera *camera = nullptr; std::function<void()> evtRenderResized;
void onRenderTargetResize(RenderTarget *target, float_t w, float_t h);
void onCameraResize(float_t w, float_t h);
/** /**
* Realigns the camera to match the render target quad. * Realigns the camera to match the render target quad.
@ -23,6 +20,9 @@ namespace Dawn {
void realign(); void realign();
public: public:
StateProperty<Camera*> camera;
StateProperty<TextureRenderTarget*> renderTarget;
/** /**
* Create the sub scene camera align component. This will align a camera * Create the sub scene camera align component. This will align a camera
* to match a render target quad (Refer SimpleRenderTargetQuad) * to match a render target quad (Refer SimpleRenderTargetQuad)
@ -31,21 +31,6 @@ namespace Dawn {
*/ */
SubSceneCameraAlign(SceneItem *item); SubSceneCameraAlign(SceneItem *item);
/**
* Set the render target for this alignment to use.
*
* @param renderTarget Render target to align to.
*/
void setRenderTarget(TextureRenderTarget *renderTarget);
/**
* Sets the camera that will be aligned.
*
* @param camera Camera to align.
*/
void setCamera(Camera *camera);
void onStart() override; void onStart() override;
void onDispose() override;
}; };
} }

View File

@ -1,45 +1,28 @@
// Copyright (c) 2023 Dominic Masters // Copyright (c) 2023 Dominic Masters
// //
// This software is released under the MIT License. // This software is released under the MIT License.
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#include "SubSceneController.hpp" #include "SubSceneController.hpp"
using namespace Dawn; using namespace Dawn;
SubSceneController::SubSceneController(SceneItem *i) : SceneItemComponent(i) { SubSceneController::SubSceneController(SceneItem *i) : SceneItemComponent(i) {
} }
void SubSceneController::onSceneUpdate() { void SubSceneController::onStart() {
if(this->onlyUpdateUnpaused) return; auto myScene = this->getScene();
if(this->subScene == nullptr) return;
this->subScene->update(); useEventLegacy([&]{
} if(!this->onlyUpdateUnpaused) return;
if(this->subScene == nullptr) return;
void SubSceneController::onSceneUnpausedUpdate() { this->subScene->update();
if(!this->onlyUpdateUnpaused) return; }, myScene->eventSceneUnpausedUpdate);
if(this->subScene == nullptr) return;
this->subScene->update(); useEventLegacy([&]{
} if(this->onlyUpdateUnpaused) return;
if(this->subScene == nullptr) return;
Scene * SubSceneController::getSubScene() { this->subScene->update();
return this->subScene; }, myScene->eventSceneUpdate);
}
void SubSceneController::setSubScene(Scene *scene) {
assertTrue(scene != this->subScene);
this->subScene = scene;
}
void SubSceneController::onStart() {
auto myScene = this->getScene();
myScene->eventSceneUnpausedUpdate.addListener(this, &SubSceneController::onSceneUnpausedUpdate);
myScene->eventSceneUpdate.addListener(this, &SubSceneController::onSceneUpdate);
}
void SubSceneController::onDispose() {
auto myScene = this->getScene();
myScene->eventSceneUnpausedUpdate.removeListener(this, &SubSceneController::onSceneUnpausedUpdate);
myScene->eventSceneUpdate.removeListener(this, &SubSceneController::onSceneUpdate);
} }

View File

@ -8,21 +8,12 @@
namespace Dawn { namespace Dawn {
class SubSceneController : public SceneItemComponent { class SubSceneController : public SceneItemComponent {
protected:
Scene *subScene = nullptr;
void onSceneUpdate();
void onSceneUnpausedUpdate();
public: public:
Scene *subScene = nullptr;
bool_t onlyUpdateUnpaused = false; bool_t onlyUpdateUnpaused = false;
SubSceneController(SceneItem *item); SubSceneController(SceneItem *item);
Scene * getSubScene();
void setSubScene(Scene *scene);
void onStart() override; void onStart() override;
void onDispose() override;
}; };
} }

View File

@ -15,39 +15,11 @@ UICanvas * UICanvas::create(Scene *scene) {
return item->addComponent<UICanvas>(); return item->addComponent<UICanvas>();
} }
UICanvas::UICanvas(SceneItem *item) : SceneItemComponent(item) { UICanvas::UICanvas(SceneItem *item) :
} SceneItemComponent(item),
camera(nullptr),
void UICanvas::onRenderTargetResize(float_t w, float_t h){ currentMenu(nullptr)
auto it = this->children.begin(); {
while(it != this->children.end()) {
(*it)->updatePositions();
++it;
}
}
void UICanvas::onSceneUpdate() {
if(this->currentMenu != nullptr) {
this->currentMenu->onTick();
}
}
void UICanvas::setCamera(Camera *camera) {
assertTrue(camera != this->camera);
if(this->camera != nullptr) {
this->camera->eventRenderTargetResized.removeListener(
this, &UICanvas::onRenderTargetResize
);
}
this->camera = camera;
if(this->camera != nullptr) {
this->camera->eventRenderTargetResized.addListener(
this, &UICanvas::onRenderTargetResize
);
}
} }
float_t UICanvas::getWidth() { float_t UICanvas::getWidth() {
@ -64,34 +36,47 @@ float_t UICanvas::getHeight() {
return this->camera->getRenderTarget()->getHeight(); return this->camera->getRenderTarget()->getHeight();
} }
struct UIMenu * UICanvas::getCurrentMenu() {
return this->currentMenu;
}
void UICanvas::setCurrentMenu(struct UIMenu *menu) { void UICanvas::setCurrentMenu(struct UIMenu *menu) {
if(this->currentMenu != nullptr) this->currentMenu->onInactive();
this->currentMenu = menu;
if(menu != nullptr) menu->onActive();
} }
void UICanvas::onStart() { void UICanvas::onStart() {
if(this->camera == nullptr) { useEffectWithTeardown([&]{
auto camera = this->getScene()->findComponent<Camera>(); if(this->camera == nullptr) return evtCamResize = [&]{};
this->setCamera(camera);
} auto it = this->children.begin();
while(it != this->children.end()) {
(*it)->updatePositions();
++it;
}
this->getScene()->eventSceneUpdate.addListener(this, &UICanvas::onSceneUpdate); return evtCamResize = useEvent([&](float_t w, float_t h){
auto it = this->children.begin();
while(it != this->children.end()) {
(*it)->updatePositions();
++it;
}
}, camera->event2RenderTargetResized);
}, camera);
useEffectWithTeardown([&]{
if(currentMenu != nullptr) currentMenu->onActive();
return [&] {
if(currentMenu == nullptr) currentMenu->onInactive();
};
}, this->currentMenu);
// Scene Update
useEventLegacy([&]{
if(this->currentMenu == nullptr) return;
this->currentMenu->onTick();
}, getScene()->eventSceneUpdate);
// Find Camera if we need to.
if(camera == nullptr) camera = this->getScene()->findComponent<Camera>();
} }
void UICanvas::onDispose() { void UICanvas::onDispose() {
if(this->camera != nullptr) {
this->camera->eventRenderTargetResized.removeListener(
this, &UICanvas::onRenderTargetResize
);
}
this->getScene()->eventSceneUpdate.removeListener(this, &UICanvas::onSceneUpdate);
auto it = this->children.begin(); auto it = this->children.begin();
while(it != this->children.end()) { while(it != this->children.end()) {
delete *it; delete *it;

View File

@ -20,13 +20,14 @@ namespace Dawn {
class UICanvas : public SceneItemComponent { class UICanvas : public SceneItemComponent {
protected: protected:
Camera *camera = nullptr; std::function<void()> evtCamResize;
struct UIMenu *currentMenu = nullptr;
void onRenderTargetResize(float_t w, float_t h); void onRenderTargetResize(float_t w, float_t h);
void onSceneUpdate();
public: public:
StateProperty<struct UIMenu*> currentMenu;
StateProperty<Camera*> camera;
/** /**
* Creates a UI Canvas Scene Item Element, and attaches it to the provided * Creates a UI Canvas Scene Item Element, and attaches it to the provided
* scene. * scene.
@ -47,13 +48,6 @@ namespace Dawn {
*/ */
UICanvas(SceneItem *item); UICanvas(SceneItem *item);
/**
* Sets the camera used by the UI canvas.
*
* @param camera Camera to set for the UI canvas.
*/
void setCamera(Camera *camera);
/** /**
* Construct and append a UI item to this UI Canvas. * Construct and append a UI item to this UI Canvas.
* *

View File

@ -18,8 +18,6 @@ namespace Dawn {
*/ */
void setInternal(V val) { void setInternal(V val) {
if(val == this->_realValue) return;// TODO: can I omit this? kinda bad tbh. if(val == this->_realValue) return;// TODO: can I omit this? kinda bad tbh.
this->previous = this->_realValue;
this->_realValue = val;
// Run the teardowns // Run the teardowns
auto itTeardown = this->_effectTeardowns.begin(); auto itTeardown = this->_effectTeardowns.begin();
@ -29,6 +27,10 @@ namespace Dawn {
} }
this->_effectTeardowns.clear(); this->_effectTeardowns.clear();
// Update the values
this->previous = this->_realValue;
this->_realValue = val;
// Notify the effect listeners // Notify the effect listeners
auto itEffect = this->_effectListners.begin(); auto itEffect = this->_effectListners.begin();
while(itEffect != this->_effectListners.end()) { while(itEffect != this->_effectListners.end()) {

View File

@ -1,127 +1,125 @@
// Copyright (c) 2023 Dominic Masters // Copyright (c) 2023 Dominic Masters
// //
// This software is released under the MIT License. // This software is released under the MIT License.
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#include "UIMenu.hpp" #include "UIMenu.hpp"
#include "game/DawnGame.hpp" #include "game/DawnGame.hpp"
using namespace Dawn; using namespace Dawn;
UIMenu::UIMenu(UICanvas *canvas, int32_t columns, int32_t rows) { UIMenu::UIMenu(UICanvas *canvas, int32_t columns, int32_t rows) {
assertNotNull(canvas); assertNotNull(canvas);
assertTrue(columns > 0); assertTrue(columns > 0);
assertTrue(rows > 0); assertTrue(rows > 0);
this->canvas = canvas; this->canvas = canvas;
this->rows = rows; this->rows = rows;
this->columns = columns; this->columns = columns;
this->items = (UIMenuItem**)memoryFillWithZero(sizeof(UIMenuItem*)*columns*rows); this->items = (UIMenuItem**)memoryFillWithZero(sizeof(UIMenuItem*)*columns*rows);
} }
void UIMenu::setSize(int32_t cols, int32_t rows) { void UIMenu::setSize(int32_t cols, int32_t rows) {
assertNotNull(this->items); assertNotNull(this->items);
assertTrue(columns > 0); assertTrue(columns > 0);
assertTrue(rows > 0); assertTrue(rows > 0);
assertTrue(columns != this->columns); assertTrue(columns != this->columns);
assertTrue(rows != this->rows); assertTrue(rows != this->rows);
memoryFree(this->items); memoryFree(this->items);
this->items = (UIMenuItem**)memoryFillWithZero(sizeof(UIMenuItem*)*columns*rows); this->items = (UIMenuItem**)memoryFillWithZero(sizeof(UIMenuItem*)*columns*rows);
} }
UIMenuItem * UIMenu::getItem(int32_t x, int32_t y) { UIMenuItem * UIMenu::getItem(int32_t x, int32_t y) {
return this->items[x * this->columns + y]; return this->items[x * this->columns + y];
} }
void UIMenu::setPosition(int32_t x, int32_t y) { void UIMenu::setPosition(int32_t x, int32_t y) {
assertTrue(x >= 0 && x < this->columns); assertTrue(x >= 0 && x < this->columns);
assertTrue(y >= 0 && y < this->rows); assertTrue(y >= 0 && y < this->rows);
UIMenuItem *item; UIMenuItem *item;
if(this->x != -1) { if(this->x != -1) {
assertTrue(this->y != -1); assertTrue(this->y != -1);
item = this->getItem(this->x, this->y); item = this->getItem(this->x, this->y);
if(item != nullptr) { if(item != nullptr) {
item->onItemOff(); item->onItemOff();
} }
} }
this->eventCursorChange.invoke(this->x, this->y, x, y); this->eventCursorChange.invoke(this->x, this->y, x, y);
this->x = x; this->x = x;
this->y = y; this->y = y;
item = this->getItem(x, y); item = this->getItem(x, y);
if(item != nullptr && item->canBeOvered()) { if(item != nullptr && item->canBeOvered()) {
item->onItemOver(); item->onItemOver();
} }
} }
void UIMenu::moveRelative(int32_t x, int32_t y) { void UIMenu::moveRelative(int32_t x, int32_t y) {
int32_t x2 = this->x + x; int32_t x2 = this->x + x;
if(x2 < 0 || x2 >= this->columns) return; if(x2 < 0 || x2 >= this->columns) return;
int32_t y2 = this->y + y; int32_t y2 = this->y + y;
if(y2 < 0 || y2 >= this->rows) return; if(y2 < 0 || y2 >= this->rows) return;
this->setPosition(x2, y2); this->setPosition(x2, y2);
} }
void UIMenu::setItem(int32_t x, int32_t y, UIMenuItem *item) { void UIMenu::setItem(int32_t x, int32_t y, UIMenuItem *item) {
assertTrue(x >= 0); assertTrue(x >= 0);
assertTrue(y >= 0); assertTrue(y >= 0);
assertTrue(x < this->columns); assertTrue(x < this->columns);
assertTrue(y < this->rows); assertTrue(y < this->rows);
assertNotNull(item); assertNotNull(item);
assertNotNull(this->items); assertNotNull(this->items);
assertNull(this->getItem(x, y)); assertNull(this->getItem(x, y));
this->items[x * this->columns + y] = item; this->items[x * this->columns + y] = item;
} }
void UIMenu::onInactive() { void UIMenu::onInactive() {
this->eventMenuInactive.invoke(); this->eventMenuInactive.invoke();
} }
void UIMenu::onActive() { void UIMenu::onActive() {
this->eventMenuActive.invoke(); this->eventMenuActive.invoke();
} }
void UIMenu::onTick() { void UIMenu::onTick() {
auto im = &this->canvas->getGame()->inputManager; auto im = &this->canvas->getGame()->inputManager;
if(im->isPressed(INPUT_BIND_ACCEPT)) { if(im->isPressed(INPUT_BIND_ACCEPT)) {
auto item = this->getItem(this->x, this->y); auto item = this->getItem(this->x, this->y);
if(item != nullptr && item->canBeSelected()) { if(item != nullptr && item->canBeSelected()) {
item->onItemSelected(); item->onItemSelected();
return; return;
} }
} }
if(im->isPressed(INPUT_BIND_NEGATIVE_Y)) { if(im->isPressed(INPUT_BIND_NEGATIVE_Y)) {
this->moveRelative(0, 1); this->moveRelative(0, 1);
return; return;
} }
if(im->isPressed(INPUT_BIND_POSITIVE_Y)) { if(im->isPressed(INPUT_BIND_POSITIVE_Y)) {
this->moveRelative(0, -1); this->moveRelative(0, -1);
return; return;
} }
if(im->isPressed(INPUT_BIND_NEGATIVE_X)) { if(im->isPressed(INPUT_BIND_NEGATIVE_X)) {
this->moveRelative(-1, 0); this->moveRelative(-1, 0);
return; return;
} }
if(im->isPressed(INPUT_BIND_POSITIVE_X)) { if(im->isPressed(INPUT_BIND_POSITIVE_X)) {
this->moveRelative(1, 0); this->moveRelative(1, 0);
return; return;
} }
// TODO: Support more modes and holding buttons to scroll. // TODO: Support more modes and holding buttons to scroll.
} }
UIMenu::~UIMenu() { UIMenu::~UIMenu() {
if(this->canvas->getCurrentMenu() == this) { if(this->canvas->currentMenu == this) this->canvas->currentMenu = nullptr;
this->canvas->setCurrentMenu(nullptr); memoryFree(this->items);
}
memoryFree(this->items);
} }