From 0ef0a5d50622a1f3843feb21ea2126f46eb93036 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 2 Sep 2023 14:00:48 -0400 Subject: [PATCH] Switched UIFrame and Scene to store their UIDrawables in shared_ptr to vector, instead of directly to vector. Every object that can be exposed to Python has to be safely shareable so it doesn't become a segfault, and that includes the UIDrawable collections AND the UIDrawable members. So we get the terrifying type for collections of child elements: 'std::shared_ptr>>'. May I be forgiven for my sins --- src/GameEngine.cpp | 4 ++-- src/GameEngine.h | 2 +- src/Scene.cpp | 9 +++++++-- src/Scene.h | 2 +- src/UI.cpp | 5 ++++- src/UI.h | 4 ++-- src/UITestScene.cpp | 21 +++++++++++++++------ 7 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/GameEngine.cpp b/src/GameEngine.cpp index fea20a5..844e232 100644 --- a/src/GameEngine.cpp +++ b/src/GameEngine.cpp @@ -121,7 +121,7 @@ void GameEngine::sUserInput() } } -std::vector>* GameEngine::scene_ui(std::string target) +std::shared_ptr>> GameEngine::scene_ui(std::string target) { /* // facts about maps @@ -136,5 +136,5 @@ std::vector>* GameEngine::scene_ui(std::string targe std::cout << "scenes[target]: " << (long)(scenes[target]) << std::endl; */ if (scenes.count(target) == 0) return NULL; - return &scenes[target]->ui_elements; + return scenes[target]->ui_elements; } diff --git a/src/GameEngine.h b/src/GameEngine.h index 0090798..e8fe728 100644 --- a/src/GameEngine.h +++ b/src/GameEngine.h @@ -42,6 +42,6 @@ public: std::vector sfxbuffers; sf::Music music; sf::Sound sfx; - std::vector>* scene_ui(std::string scene); + std::shared_ptr>> scene_ui(std::string scene); }; diff --git a/src/Scene.cpp b/src/Scene.cpp index 61afda5..0fd308e 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -1,7 +1,12 @@ #include "Scene.h" +#include "UI.h" //Scene::Scene() { game = 0; std::cout << "WARN: default Scene constructor called. (game = " << game << ")" << std::endl;}; -Scene::Scene(GameEngine* g) { game = g; } +Scene::Scene(GameEngine* g) +{ + game = g; + ui_elements = std::make_shared>>(); +} void Scene::registerAction(int code, std::string name) { actions[code] = name; @@ -33,4 +38,4 @@ bool Scene::registerActionInjected(int code, std::string name) bool Scene::unregisterActionInjected(int code, std::string name) { return false; -} \ No newline at end of file +} diff --git a/src/Scene.h b/src/Scene.h index 8826946..c5a636e 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -39,6 +39,6 @@ public: virtual bool registerActionInjected(int, std::string); virtual bool unregisterActionInjected(int, std::string); - std::vector> ui_elements; + std::shared_ptr>> ui_elements; }; diff --git a/src/UI.cpp b/src/UI.cpp index 5874fde..81140dc 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -10,6 +10,7 @@ void UIDrawable::render() UIFrame::UIFrame(): x(0), y(0), w(0), h(0), outline(0) { + children = std::make_shared>>(); /* pyOutlineColor = NULL; pyFillColor = NULL; @@ -21,6 +22,7 @@ x(0), y(0), w(0), h(0), outline(0) UIFrame::UIFrame(float _x, float _y, float _w, float _h): x(_x), y(_y), w(_w), h(_h), outline(0) { + children = std::make_shared>>(); /* pyOutlineColor = NULL; pyFillColor = NULL; @@ -31,6 +33,7 @@ x(_x), y(_y), w(_w), h(_h), outline(0) UIFrame::~UIFrame() { + children.reset(); /* if (pyOutlineColor) Py_DECREF(pyOutlineColor); else if (_outlineColor) delete _outlineColor; @@ -64,7 +67,7 @@ void UIFrame::render(sf::Vector2f offset) //if (_outlineColor) { box.setOutlineColor(outlineColor()); } //box.setOutlineThickness(outline); //Resources::game->getWindow().draw(box); - for (auto drawable : children) { + for (auto drawable : *children) { drawable->render(offset + box.getPosition()); } } diff --git a/src/UI.h b/src/UI.h index a40a447..e00150a 100644 --- a/src/UI.h +++ b/src/UI.h @@ -38,7 +38,7 @@ public: //Simulate RectangleShape float x, y, w, h, outline; - std::vector> children; + std::shared_ptr>> children; void render(sf::Vector2f) override final; void move(sf::Vector2f); @@ -391,7 +391,7 @@ namespace mcrfpydef { "outline=" << box.getOutlineThickness() << ", " << "fill_color=(" << (int)fc.r << ", " << (int)fc.g << ", " << (int)fc.b << ", " << (int)fc.a <<"), " << "outlinecolor=(" << (int)oc.r << ", " << (int)oc.g << ", " << (int)oc.b << ", " << (int)oc.a <<"), " << - self->data->children.size() << " child" << (self->data->children.size() == 1 ? "" : "ren") << " objects" << + self->data->children->size() << " child objects" << ")>"; } std::string repr_str = ss.str(); diff --git a/src/UITestScene.cpp b/src/UITestScene.cpp index 2f4acd2..729b865 100644 --- a/src/UITestScene.cpp +++ b/src/UITestScene.cpp @@ -13,6 +13,9 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) //registerAction(ActionCode::KEY + sf::Keyboard::Up, "up"); //registerAction(ActionCode::KEY + sf::Keyboard::Down, "down"); + // note - you can't use the pointer to UI elements in constructor. + // The scene map is still being assigned to, so this object can't be looked up. + /* auto ui = Resources::game->scene_ui("uitest"); if (ui) { @@ -20,6 +23,7 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) } else { std::cout << "No UI vector was returned.\n"; } + */ // Create a UI element or three? auto e1 = std::make_shared(100,150,400,400); @@ -28,21 +32,21 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) e1->box.setFillColor(sf::Color(255, 0, 0)); //e1.fillColor(sf::Color(255,0,0)); //if (ui) ui->push_back(e1); - ui_elements.push_back(e1); + ui_elements->push_back(e1); auto e1a = std::make_shared(50,50,200,200); e1a->box.setPosition(50, 50); e1a->box.setSize(sf::Vector2f(200,200)); e1a->box.setFillColor(sf::Color(0, 255, 0)); //e1a.fillColor(sf::Color(0, 255, 0)); - e1->children.push_back(e1a); + e1->children->push_back(e1a); auto e1aa = std::make_shared(5,5,100,100); e1aa->box.setPosition(5, 5); e1aa->box.setSize(sf::Vector2f(100,100)); e1aa->box.setFillColor(sf::Color(0, 0, 255)); //e1aa.fillColor(sf::Color(0, 0, 255)); - e1a->children.push_back(e1aa); + e1a->children->push_back(e1aa); auto e2 = std::make_shared(); e2->text.setFont(game->getFont()); @@ -51,12 +55,16 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) e2->text.setPosition(50, 250); //if (ui) ui->push_back(e2); - ui_elements.push_back(e2); + ui_elements->push_back(e2); //ui_elements.push_back(&e1); //ui_elements.push_back(&e2); - + + /* + // note - you can't use the pointer to UI elements in constructor. + // The scene map is still being assigned to, so this object can't be looked up. if (ui) std::cout << "pointer to ui_elements now shows size=" << ui->size() << std::endl; + */ } void UITestScene::update() @@ -87,7 +95,8 @@ void UITestScene::sRender() //for (auto e: ui_elements) //auto ui = Resources::game->scene_ui("uitest"); //if (ui) - for (auto e: ui_elements) + auto vec = *ui_elements; + for (auto e: vec) { //std::cout << "Rendering element\n"; if (e)