From 47d0e34a17eb4aa86f781d0a022180d637cec602 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 16 Mar 2024 11:31:39 -0400 Subject: [PATCH 1/8] Initial PyTexture class no testing done. should enable rectangular (non-square) textures "sprite" method; let's just overwrite sprites with texture coords Hoping to replace awful code like: `self->data->sprite.sprite.setTextureRect(self->data->sprite.itex->spriteCoordinates(val));` with something like: `self->data->sprite = self->data->texture->sprite(val);` --- src/PyTexture.cpp | 20 ++++++++++++++++++++ src/PyTexture.h | 14 ++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/PyTexture.cpp create mode 100644 src/PyTexture.h diff --git a/src/PyTexture.cpp b/src/PyTexture.cpp new file mode 100644 index 0000000..0a16ed9 --- /dev/null +++ b/src/PyTexture.cpp @@ -0,0 +1,20 @@ +#include "PyTexture.h" + +PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) +: sprite_width(sprite_w), sprite_height(sprite_h) +{ + // TODO - get image resolution and get sheet width and height + sheet_width = 0; + sheet_height = 0; + source = filename; +} + +sf::Sprite PyTexture::sprite(int index, float x = 0.0, float y = 0.0, float s = 1.0) +{ + int tx = index % sprite_width, ty = index / sprite_height; + auto ir = sf::IntRect(tx * sprite_width, ty * sprite_height, sprite_width, sprite_height); + auto sprite = sf::Sprite(texture, ir); + sprite.setPosition(x, y); + sprite.setScale(s, s); + return sprite; +} diff --git a/src/PyTexture.h b/src/PyTexture.h new file mode 100644 index 0000000..288bbfb --- /dev/null +++ b/src/PyTexture.h @@ -0,0 +1,14 @@ +#pragma once +#include "Common.h" +#include "Python.h" + +class PyTexture +{ +private: + sf::Texture texture; + std::string source; + int sprite_width, sprite_height, sheet_width, sheet_height; +public: + PyTexture(std::string filename, int sprite_w, int sprite_h); + sf::Sprite sprite(int index, float x = 0.0, float y = 0.0, float s = 1.0); +}; From bfd33102d13072eb4624cb07dcf5a55a98e93aa0 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 16 Mar 2024 14:52:35 -0400 Subject: [PATCH 2/8] Squashed basically all the compile bugs in UISprite, but UIEntity and UIGrid use textures as well, so they need to be fixed too before the project will build again --- src/PyTexture.cpp | 18 ++++++---- src/PyTexture.h | 2 +- src/UI.cpp | 50 ++++++++++++++++++++++++++-- src/UI.h | 85 ++++++++++++++++++++++++++++------------------- 4 files changed, 111 insertions(+), 44 deletions(-) diff --git a/src/PyTexture.cpp b/src/PyTexture.cpp index 0a16ed9..d126e8b 100644 --- a/src/PyTexture.cpp +++ b/src/PyTexture.cpp @@ -3,18 +3,24 @@ PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) : sprite_width(sprite_w), sprite_height(sprite_h) { - // TODO - get image resolution and get sheet width and height - sheet_width = 0; - sheet_height = 0; + texture = sf::Texture(source); + auto size = texture.getSize(); + sheet_width = size.x; + sheet_height = size.y; source = filename; + if (sheet_width % sprite_width != 0 || sheet_height % sprite_height != 0) + { + std::cout << "Warning: Texture `" << source << "` is not an even number of sprite widths or heights across." << std::endl + << "Sprite size given was " << sprite_w << "x" << sprite_h << "px but the file has a resolution of " << sheet_width << "x" << sheet_height << "px." << std::endl; + } } -sf::Sprite PyTexture::sprite(int index, float x = 0.0, float y = 0.0, float s = 1.0) +sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)) { int tx = index % sprite_width, ty = index / sprite_height; auto ir = sf::IntRect(tx * sprite_width, ty * sprite_height, sprite_width, sprite_height); auto sprite = sf::Sprite(texture, ir); - sprite.setPosition(x, y); - sprite.setScale(s, s); + sprite.setPosition(pos); + sprite.setScale(s); return sprite; } diff --git a/src/PyTexture.h b/src/PyTexture.h index 288bbfb..208b84f 100644 --- a/src/PyTexture.h +++ b/src/PyTexture.h @@ -10,5 +10,5 @@ private: int sprite_width, sprite_height, sheet_width, sheet_height; public: PyTexture(std::string filename, int sprite_w, int sprite_h); - sf::Sprite sprite(int index, float x = 0.0, float y = 0.0, float s = 1.0); + sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)); }; diff --git a/src/UI.cpp b/src/UI.cpp index b2447cd..4a621a6 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -168,7 +168,8 @@ void UICaption::render(sf::Vector2f offset) } UISprite::UISprite() {} - +/* + // * tearing down the old IndexTexture way of life UISprite::UISprite(IndexTexture* _itex, int _sprite_index, float x = 0.0, float y = 0.0, float s = 1.0) : itex(_itex), sprite_index(_sprite_index) { @@ -186,6 +187,13 @@ UISprite::UISprite(IndexTexture* _itex, int _sprite_index, sf::Vector2f pos, flo sprite.setPosition(pos); sprite.setScale(sf::Vector2f(s, s)); } +*/ + +UISprite::UISprite(std::shared_ptr _ptex, int _sprite_index, sf::Vector2f _pos, float _scale) +: ptex(_ptex), sprite_index(_sprite_index) +{ + sprite = ptex(sprite_index, _pos, sf::Vector2f(_scale, _scale)); +} //void UISprite::update() //{ @@ -212,19 +220,55 @@ void UISprite::render(sf::Vector2f offset, sf::RenderTexture& target) sprite.move(-offset); } +/* void UISprite::setPosition(float x, float y) { setPosition(sf::Vector2f(x, y)); } +*/ void UISprite::setPosition(sf::Vector2f pos) { sprite.setPosition(pos); } -void UISprite::setScale(float s) +void UISprite::setScale(sf::Vector2f s) { - sprite.setScale(sf::Vector2f(s, s)); + sprite.setScale(s); +} + +void UISprite::setTexture(std::shared_ptr _ptex, int _sprite_index=-1) +{ + ptex = _ptex; + if (_sprite_index != -1) // if you are changing textures, there's a good chance you need a new index too + sprite_index = _sprite_index; + sprite = ptex->sprite(sprite_index, sprite.getPosition(), sprite.getScale()); +} + +void UISprite::setSpriteIndex(int _sprite_index) +{ + sprite_index = _sprite_index; + sprite = ptex->sprite(sprite_index, sprite.getPosition(), sprite.getScale()); +} + +sf::Vector2f UISprite::getScale() +{ + return sprite.getScale(); +} + +sf::Vector2f UISprite::getPosition() +{ + return sprite.getPosition(); +} + +std::shared_ptr UISprite::getTexture() +{ + return ptex; +} + +int UISprite::getSpriteIndex() +{ + return sprite_index; } PyObjectsEnum UICaption::derived_type() diff --git a/src/UI.h b/src/UI.h index 7df7861..cc88522 100644 --- a/src/UI.h +++ b/src/UI.h @@ -6,6 +6,7 @@ #include "Resources.h" #include #include "PyCallable.h" +#include "PyTexture.h" enum PyObjectsEnum : int { @@ -97,23 +98,36 @@ public: class UISprite: public UIDrawable { +private: + int sprite_index; + sf::Sprite sprite; +protected: + std::shared_ptr ptex; public: UISprite(); - UISprite(IndexTexture*, int, float, float, float); - UISprite(IndexTexture*, int, sf::Vector2f, float); + //UISprite(IndexTexture*, int, float, float, float); + //UISprite(IndexTexture*, int, sf::Vector2f, float); + UISprite(std::shared_ptr, int, sf::Vector2f, float); void update(); void render(sf::Vector2f) override final; virtual UIDrawable* click_at(sf::Vector2f point) override final; // 7DRL hack - TODO apply RenderTexture concept to all UIDrawables (via `sf::RenderTarget`) void render(sf::Vector2f, sf::RenderTexture&); - int /*texture_index,*/ sprite_index; - IndexTexture* itex; - //float x, y, scale; - sf::Sprite sprite; - void setPosition(float, float); + //IndexTexture* itex; + //sf::Vector2f pos; + //float scale; + //void setPosition(float, float); void setPosition(sf::Vector2f); - void setScale(float); + sf::Vector2f getPosition(); + void setScale(sf::Vector2f); + sf::Vector2f getScale(); + void setSpriteIndex(int); + int getSpriteIndex(); + + void setTexture(std::shared_ptr _ptex, int _sprite_index=-1); + std::shared_ptr getTexture(); + PyObjectsEnum derived_type() override final; // { return PyObjectsEnum::UISprite; }; }; @@ -155,6 +169,8 @@ public: class UIGrid: public UIDrawable { +private: + std::shared_ptr ptex; public: UIGrid(); UIGrid(int, int, IndexTexture*, float, float, float, float); @@ -170,7 +186,7 @@ public: //int grid_size; // grid sizes are implied by IndexTexture now sf::RectangleShape box; float center_x, center_y, zoom; - IndexTexture* itex; + //IndexTexture* itex; sf::Sprite sprite, output; sf::RenderTexture renderTexture; std::vector points; @@ -1071,7 +1087,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c typedef struct { PyObject_HEAD - std::shared_ptr data; + std::shared_ptr data; } PyTextureObject; static int PyTexture_init(PyTextureObject* self, PyObject* args, PyObject* kwds) @@ -1085,9 +1101,9 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c { return -1; } - sf::Texture t = sf::Texture(); - t.loadFromFile((std::string)filename); - self->data = std::make_shared(t, grid_size, grid_width, grid_height); + //sf::Texture t = sf::Texture(); + //t.loadFromFile((std::string)filename); + self->data = std::make_shared(filename, grid_size, grid_size); return 0; } @@ -1122,11 +1138,11 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c { auto member_ptr = reinterpret_cast(closure); if (member_ptr == 0) - return PyFloat_FromDouble(self->data->sprite.getPosition().x); + return PyFloat_FromDouble(self->data->getPosition().x); else if (member_ptr == 1) - return PyFloat_FromDouble(self->data->sprite.getPosition().y); + return PyFloat_FromDouble(self->data->getPosition().y); else if (member_ptr == 2) - return PyFloat_FromDouble(self->data->sprite.getScale().x); // scale X and Y are identical, presently + return PyFloat_FromDouble(self->data->getScale().x); // scale X and Y are identical, presently else { PyErr_SetString(PyExc_AttributeError, "Invalid attribute"); @@ -1153,11 +1169,11 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c return -1; } if (member_ptr == 0) //x - self->data->sprite.setPosition(val, self->data->sprite.getPosition().y); + self->data->setPosition(sf::Vector2f(val, self->data->getPosition().y)); else if (member_ptr == 1) //y - self->data->sprite.setPosition(self->data->sprite.getPosition().x, val); + self->data->setPosition(sf::Vector2f(self->data->getPosition().x, val)); else if (member_ptr == 2) // scale - self->data->sprite.setScale(sf::Vector2f(val, val)); + self->data->setScale(sf::Vector2f(val, val)); return 0; } @@ -1171,7 +1187,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c return nullptr; } - return PyLong_FromDouble(self->data->sprite_index); + return PyLong_FromDouble(self->data->getSpriteIndex()); } @@ -1188,8 +1204,9 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c PyErr_SetString(PyExc_TypeError, "Value must be an integer."); return -1; } - self->data->sprite_index = val; - self->data->sprite.setTextureRect(self->data->itex->spriteCoordinates(val)); + //self->data->sprite_index = val; + //self->data->sprite.setTextureRect(self->data->itex->spriteCoordinates(val)); + self->data->setSpriteIndex(val); return 0; } @@ -1218,10 +1235,10 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c std::ostringstream ss; if (!self->data) ss << ""; else { - auto sprite = self->data->sprite; - ss << ""; + //auto sprite = self->data->sprite; + ss << ""; } std::string repr_str = ss.str(); return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); @@ -1258,7 +1275,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c } auto pytexture = (PyTextureObject*)texture; self->data = std::make_shared(pytexture->data.get(), sprite_index, sf::Vector2f(x, y), scale); - self->data->sprite.setPosition(sf::Vector2f(x, y)); + self->data->setPosition(sf::Vector2f(x, y)); return 0; } @@ -1548,7 +1565,7 @@ static PyObject* PyUIEntity_get_gridstate(PyUIEntityObject* self, void* closure) } static PyObject* PyUIEntity_get_spritenumber(PyUIEntityObject* self, void* closure) { - return PyLong_FromDouble(self->data->sprite.sprite_index); + return PyLong_FromDouble(self->data->sprite.getSpriteIndex()); } static int PyUIEntity_set_spritenumber(PyUIEntityObject* self, PyObject* value, void* closure) { @@ -1560,8 +1577,8 @@ static int PyUIEntity_set_spritenumber(PyUIEntityObject* self, PyObject* value, PyErr_SetString(PyExc_TypeError, "Value must be an integer."); return -1; } - self->data->sprite.sprite_index = val; - self->data->sprite.sprite.setTextureRect(self->data->sprite.itex->spriteCoordinates(val)); // TODO - I don't like ".sprite.sprite" in this stack of UIEntity.UISprite.sf::Sprite + //self->data->sprite.sprite_index = val; + self->data->sprite.setSpriteIndex(val); // todone - I don't like ".sprite.sprite" in this stack of UIEntity.UISprite.sf::Sprite return 0; } @@ -1648,11 +1665,11 @@ static int PyUIGrid_init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { } PyTextureObject* pyTexture = reinterpret_cast(textureObj); // TODO (7DRL day 2, item 4.) use shared_ptr / PyTextureObject on UIGrid - IndexTexture* texture = pyTexture->data.get(); - + //IndexTexture* texture = pyTexture->data.get(); + // Initialize UIGrid //self->data = new UIGrid(grid_x, grid_y, texture, sf::Vector2f(box_x, box_y), sf::Vector2f(box_w, box_h)); - self->data = std::make_shared(grid_x, grid_y, texture, box_x, box_y, box_w, box_h); + self->data = std::make_shared(grid_x, grid_y, pyTexture->data, box_x, box_y, box_w, box_h); return 0; // Success } @@ -1913,7 +1930,7 @@ static int PyUIEntity_init(PyUIEntityObject* self, PyObject* args, PyObject* kwd self->data = std::make_shared(*((PyUIGridObject*)grid)->data); // TODO - PyTextureObjects and IndexTextures are a little bit of a mess with shared/unshared pointers - self->data->sprite = UISprite(pytexture->data.get(), sprite_index, sf::Vector2f(0,0), 1.0); + self->data->sprite = UISprite(pytexture->data, sprite_index, sf::Vector2f(0,0), 1.0); self->data->position = sf::Vector2f(x, y); if (grid != NULL) { PyUIGridObject* pygrid = (PyUIGridObject*)grid; From afd4ff1925382622abf79db132b6123ee33b946b Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 16 Mar 2024 21:53:24 -0400 Subject: [PATCH 3/8] good progress, we're building again. Issue with Grid (tile sprite) textures and I think the sprite indexes are being calculated wrong (x and y transposed?) --- src/PyTexture.cpp | 8 ++++---- src/PyTexture.h | 3 ++- src/UI.cpp | 49 ++++++++++++++++++++++++++------------------- src/UI.h | 27 +++++++++++++------------ src/UITestScene.cpp | 34 +++++++++++++++---------------- 5 files changed, 65 insertions(+), 56 deletions(-) diff --git a/src/PyTexture.cpp b/src/PyTexture.cpp index d126e8b..2fb8e7f 100644 --- a/src/PyTexture.cpp +++ b/src/PyTexture.cpp @@ -1,13 +1,13 @@ #include "PyTexture.h" PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) -: sprite_width(sprite_w), sprite_height(sprite_h) +: source(filename), sprite_width(sprite_w), sprite_height(sprite_h) { - texture = sf::Texture(source); + texture = sf::Texture(); + texture.loadFromFile(source); auto size = texture.getSize(); sheet_width = size.x; sheet_height = size.y; - source = filename; if (sheet_width % sprite_width != 0 || sheet_height % sprite_height != 0) { std::cout << "Warning: Texture `" << source << "` is not an even number of sprite widths or heights across." << std::endl @@ -15,7 +15,7 @@ PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) } } -sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)) +sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s) { int tx = index % sprite_width, ty = index / sprite_height; auto ir = sf::IntRect(tx * sprite_width, ty * sprite_height, sprite_width, sprite_height); diff --git a/src/PyTexture.h b/src/PyTexture.h index 208b84f..8f13139 100644 --- a/src/PyTexture.h +++ b/src/PyTexture.h @@ -7,8 +7,9 @@ class PyTexture private: sf::Texture texture; std::string source; - int sprite_width, sprite_height, sheet_width, sheet_height; + int sheet_width, sheet_height; public: + int sprite_width, sprite_height; // just use them read only, OK? PyTexture(std::string filename, int sprite_w, int sprite_h); sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)); }; diff --git a/src/UI.cpp b/src/UI.cpp index 4a621a6..05c8594 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -192,7 +192,7 @@ UISprite::UISprite(IndexTexture* _itex, int _sprite_index, sf::Vector2f pos, flo UISprite::UISprite(std::shared_ptr _ptex, int _sprite_index, sf::Vector2f _pos, float _scale) : ptex(_ptex), sprite_index(_sprite_index) { - sprite = ptex(sprite_index, _pos, sf::Vector2f(_scale, _scale)); + sprite = ptex->sprite(sprite_index, _pos, sf::Vector2f(_scale, _scale)); } //void UISprite::update() @@ -237,7 +237,7 @@ void UISprite::setScale(sf::Vector2f s) sprite.setScale(s); } -void UISprite::setTexture(std::shared_ptr _ptex, int _sprite_index=-1) +void UISprite::setTexture(std::shared_ptr _ptex, int _sprite_index) { ptex = _ptex; if (_sprite_index != -1) // if you are changing textures, there's a good chance you need a new index too @@ -302,9 +302,10 @@ UIGrid::UIGrid() { } -UIGrid::UIGrid(int gx, int gy, IndexTexture* _itex, float _x, float _y, float _w, float _h) +/* +UIGrid::UIGrid(int gx, int gy, std::shared_ptr _ptex, float _x, float _y, float _w, float _h) : grid_x(gx), grid_y(gy), - zoom(1.0f), center_x((gx/2) * _itex->grid_size), center_y((gy/2) * _itex->grid_size), + zoom(1.0f), center_x((gx/2) * _ptex->sheet_width), center_y((gy/2) * _ptex->sheet_height), itex(_itex), points(gx * gy) { // set up blank list of entities @@ -323,11 +324,12 @@ UIGrid::UIGrid(int gx, int gy, IndexTexture* _itex, float _x, float _y, float _w // textures are upside-down inside renderTexture output.setTexture(renderTexture.getTexture()); } +*/ -UIGrid::UIGrid(int gx, int gy, IndexTexture* _itex, sf::Vector2f _xy, sf::Vector2f _wh) +UIGrid::UIGrid(int gx, int gy, std::shared_ptr _ptex, sf::Vector2f _xy, sf::Vector2f _wh) : grid_x(gx), grid_y(gy), - zoom(1.0f), center_x((gx/2) * _itex->grid_size), center_y((gy/2) * _itex->grid_size), - itex(_itex), points(gx * gy) + zoom(1.0f), center_x((gx/2) * _ptex->sprite_width), center_y((gy/2) * _ptex->sprite_height), + ptex(_ptex), points(gx * gy) { // set up blank list of entities entities = std::make_shared>>(); @@ -340,7 +342,9 @@ UIGrid::UIGrid(int gx, int gy, IndexTexture* _itex, sf::Vector2f _xy, sf::Vector // create renderTexture with maximum theoretical size; sprite can resize to show whatever amount needs to be rendered renderTexture.create(1920, 1080); // TODO - renderTexture should be window size; above 1080p this will cause rendering errors - sprite.setTexture(_itex->texture); + //sprite.setTexture(_itex->texture); + sprite = ptex->sprite(0); + output.setTextureRect( sf::IntRect(0, 0, box.getSize().x, box.getSize().y)); @@ -354,11 +358,14 @@ void UIGrid::update() { } +/* void UIGrid::setSprite(int ti) { - int tx = ti % itex->grid_width, ty = ti / itex->grid_width; - sprite.setTextureRect(sf::IntRect(tx * itex->grid_size, ty * itex->grid_size, itex->grid_size, itex->grid_size)); + //int tx = ti % itex->grid_width, ty = ti / itex->grid_width; + // sprite.setTextureRect(sf::IntRect(tx * itex->grid_size, ty * itex->grid_size, itex->grid_size, itex->grid_size)); + sprite = ptex->sprite(ti); } +*/ void UIGrid::render(sf::Vector2f) { @@ -369,11 +376,11 @@ void UIGrid::render(sf::Vector2f) box.getSize().x, box.getSize().y)); renderTexture.clear(sf::Color(8, 8, 8, 255)); // TODO - UIGrid needs a "background color" field // sprites that are visible according to zoom, center_x, center_y, and box width - float center_x_sq = center_x / itex->grid_size; - float center_y_sq = center_y / itex->grid_size; + float center_x_sq = center_x / ptex->sprite_width; + float center_y_sq = center_y / ptex->sprite_height; - float width_sq = box.getSize().x / (itex->grid_size * zoom); - float height_sq = box.getSize().y / (itex->grid_size * zoom); + float width_sq = box.getSize().x / (ptex->sprite_width * zoom); + float height_sq = box.getSize().y / (ptex->sprite_height * zoom); float left_edge = center_x_sq - (width_sq / 2.0); float top_edge = center_y_sq - (height_sq / 2.0); @@ -382,7 +389,7 @@ void UIGrid::render(sf::Vector2f) sprite.setScale(sf::Vector2f(zoom, zoom)); sf::RectangleShape r; // for colors and overlays - r.setSize(sf::Vector2f(itex->grid_size * zoom, itex->grid_size * zoom)); + r.setSize(sf::Vector2f(ptex->sprite_width * zoom, ptex->sprite_height * zoom)); r.setOutlineThickness(0); int x_limit = left_edge + width_sq + 2; @@ -402,8 +409,8 @@ void UIGrid::render(sf::Vector2f) y+=1) { auto pixel_pos = sf::Vector2f( - (x*itex->grid_size - left_spritepixels) * zoom, - (y*itex->grid_size - top_spritepixels) * zoom ); + (x*ptex->sprite_width - left_spritepixels) * zoom, + (y*ptex->sprite_height - top_spritepixels) * zoom ); auto gridpoint = at(std::floor(x), std::floor(y)); @@ -417,7 +424,7 @@ void UIGrid::render(sf::Vector2f) // if discovered but not visible, set opacity to 90% // if not discovered... just don't draw it? if (gridpoint.tilesprite != -1) { - setSprite(gridpoint.tilesprite); + sprite = ptex->sprite(gridpoint.tilesprite); //setSprite(gridpoint.tilesprite); renderTexture.draw(sprite); } } @@ -430,10 +437,10 @@ void UIGrid::render(sf::Vector2f) //auto drawent = e->cGrid->indexsprite.drawable(); auto& drawent = e->sprite; //drawent.setScale(zoom, zoom); - drawent.setScale(zoom); + drawent.setScale(sf::Vector2f(zoom, zoom)); auto pixel_pos = sf::Vector2f( - (e->position.x*itex->grid_size - left_spritepixels) * zoom, - (e->position.y*itex->grid_size - top_spritepixels) * zoom ); + (e->position.x*ptex->sprite_width - left_spritepixels) * zoom, + (e->position.y*ptex->sprite_height - top_spritepixels) * zoom ); //drawent.setPosition(pixel_pos); //renderTexture.draw(drawent); drawent.render(pixel_pos, renderTexture); diff --git a/src/UI.h b/src/UI.h index cc88522..b732bfe 100644 --- a/src/UI.h +++ b/src/UI.h @@ -173,13 +173,13 @@ private: std::shared_ptr ptex; public: UIGrid(); - UIGrid(int, int, IndexTexture*, float, float, float, float); - UIGrid(int, int, IndexTexture*, sf::Vector2f, sf::Vector2f); + //UIGrid(int, int, IndexTexture*, float, float, float, float); + UIGrid(int, int, std::shared_ptr, sf::Vector2f, sf::Vector2f); void update(); void render(sf::Vector2f) override final; UIGridPoint& at(int, int); PyObjectsEnum derived_type() override final; - void setSprite(int); + //void setSprite(int); virtual UIDrawable* click_at(sf::Vector2f point) override final; int grid_x, grid_y; @@ -217,7 +217,7 @@ typedef struct { typedef struct { PyObject_HEAD std::shared_ptr data; - PyObject* texture; + //PyObject* texture; } PyUISpriteObject; typedef struct { @@ -241,13 +241,13 @@ typedef struct { typedef struct { PyObject_HEAD std::shared_ptr data; - PyObject* texture; + //PyObject* texture; } PyUIEntityObject; typedef struct { PyObject_HEAD std::shared_ptr data; - PyObject* texture; + //PyObject* texture; } PyUIGridObject; namespace mcrfpydef { @@ -1265,16 +1265,16 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c if (texture != NULL && !PyObject_IsInstance(texture, (PyObject*)&PyTextureType)){ PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance"); return -1; - } else if (texture != NULL) + } /*else if (texture != NULL) // to be removed: UIObjects don't manage texture references { self->texture = texture; Py_INCREF(texture); } else { // default tex? - } + }*/ auto pytexture = (PyTextureObject*)texture; - self->data = std::make_shared(pytexture->data.get(), sprite_index, sf::Vector2f(x, y), scale); + self->data = std::make_shared(pytexture->data, sprite_index, sf::Vector2f(x, y), scale); self->data->setPosition(sf::Vector2f(x, y)); return 0; @@ -1289,7 +1289,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c { PyUISpriteObject* obj = (PyUISpriteObject*)self; // release reference to font object - if (obj->texture) Py_DECREF(obj->texture); + //if (obj->texture) Py_DECREF(obj->texture); obj->data.reset(); Py_TYPE(self)->tp_free(self); }, @@ -1669,7 +1669,8 @@ static int PyUIGrid_init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { // Initialize UIGrid //self->data = new UIGrid(grid_x, grid_y, texture, sf::Vector2f(box_x, box_y), sf::Vector2f(box_w, box_h)); - self->data = std::make_shared(grid_x, grid_y, pyTexture->data, box_x, box_y, box_w, box_h); + self->data = std::make_shared(grid_x, grid_y, pyTexture->data, + sf::Vector2f(box_x, box_y), sf::Vector2f(box_w, box_h)); return 0; // Success } @@ -1909,14 +1910,14 @@ static int PyUIEntity_init(PyUIEntityObject* self, PyObject* args, PyObject* kwd if (texture != NULL && !PyObject_IsInstance(texture, (PyObject*)&PyTextureType)){ PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance"); return -1; - } else if (texture != NULL) + } /*else if (texture != NULL) // this section needs to go; texture isn't optional and isn't managed by the UI objects anymore { self->texture = texture; Py_INCREF(texture); } else { // default tex? - } + }*/ if (grid != NULL && !PyObject_IsInstance(grid, (PyObject*)&PyUIGridType)) { PyErr_SetString(PyExc_TypeError, "grid must be a mcrfpy.Grid instance"); diff --git a/src/UITestScene.cpp b/src/UITestScene.cpp index ff70c53..9250402 100644 --- a/src/UITestScene.cpp +++ b/src/UITestScene.cpp @@ -61,15 +61,15 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) //ui_elements.push_back(&e1); //ui_elements.push_back(&e2); - t.loadFromFile("./assets/kenney_tinydungeon.png"); - t.setSmooth(false); - auto* indextex = new IndexTexture(t, 16, 12, 11); - Resources::game->textures.push_back(*indextex); - + //t.loadFromFile("./assets/kenney_tinydungeon.png"); + //t.setSmooth(false); + //auto* indextex = new IndexTexture(t, 16, 12, 11); + //Resources::game->textures.push_back(*indextex); + auto ptex = std::make_shared("./assets/kenney_tinydungeon.png", 16, 16); //std::cout << Resources::game->textures.size() << " textures loaded.\n"; - auto e3 = std::make_shared(); + auto e3 = std::make_shared(ptex, 84, sf::Vector2f(10, 10), 4.0); // Make UISprite more like IndexSprite: this is bad //e3->x = 10; e3->y = 10; @@ -79,19 +79,19 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) //e3->update(); // This goes to show how inconvenient the default constructor is. It should be removed - e3->itex = &Resources::game->textures[0]; - e3->sprite.setTexture(e3->itex->texture); - e3->sprite_index = 84; - e3->sprite.setTextureRect(e3->itex->spriteCoordinates(e3->sprite_index)); - e3->setPosition(10, 10); - e3->setScale(4.0f); + //e3->itex = &Resources::game->textures[0]; + //e3->sprite.setTexture(e3->itex->texture); + //e3->sprite_index = 84; + //e3->sprite.setTextureRect(e3->itex->spriteCoordinates(e3->sprite_index)); + //e3->setPosition(10, 10); + //e3->setScale(4.0f); e1aa->children->push_back(e3); auto e4 = std::make_shared( - indextex, //&Resources::game->textures[0], + ptex, //indextex, //&Resources::game->textures[0], 85, sf::Vector2f(90, 10), 4.0); e1aa->children->push_back(e4); //std::cout << "UISprite built: " << e4->sprite.getPosition().x << " " << e4->sprite.getPosition().y << " " << e4->sprite.getScale().x << " " << @@ -104,9 +104,9 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) std::cout << "pointer to ui_elements now shows size=" << ui->size() << std::endl; */ - // UIGrid test: (in grid cells) (in screen pixels) - // constructor args: w h texture x y w h - auto e5 = std::make_shared(4, 4, indextex, 550, 150, 200, 200); + // UIGrid test: (in grid cells) ( in screen pixels ) + // constructor args: w h texture x y w h + auto e5 = std::make_shared(4, 4, ptex, sf::Vector2f(550, 150), sf::Vector2f(200, 200)); e5->zoom=2.0; e5->points[0].color = sf::Color(255, 0, 0); e5->points[1].tilesprite = 1; @@ -125,7 +125,7 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) e5a->grid = e5; //auto e5as = UISprite(indextex, 85, sf::Vector2f(0, 0), 1.0); //e5a->sprite = e5as; // will copy constructor even exist for UISprite...? - e5a->sprite = UISprite(indextex, 85, sf::Vector2f(0, 0), 1.0); + e5a->sprite = UISprite(ptex, 85, sf::Vector2f(0, 0), 1.0); e5a->position = sf::Vector2f(1, 0); e5->entities->push_back(e5a); From 20f80c4114fce029faf28a195ffdbb041181e484 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sun, 17 Mar 2024 16:23:52 -0400 Subject: [PATCH 4/8] Fixed sprite indexing error in PyTexture; needs non-square sprite tests, but feeling confident! --- src/PyTexture.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PyTexture.cpp b/src/PyTexture.cpp index 2fb8e7f..0f71f25 100644 --- a/src/PyTexture.cpp +++ b/src/PyTexture.cpp @@ -6,9 +6,9 @@ PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) texture = sf::Texture(); texture.loadFromFile(source); auto size = texture.getSize(); - sheet_width = size.x; - sheet_height = size.y; - if (sheet_width % sprite_width != 0 || sheet_height % sprite_height != 0) + sheet_width = (size.x / sprite_width); + sheet_height = (size.y / sprite_height); + if (size.x % sprite_width != 0 || size.y % sprite_height != 0) { std::cout << "Warning: Texture `" << source << "` is not an even number of sprite widths or heights across." << std::endl << "Sprite size given was " << sprite_w << "x" << sprite_h << "px but the file has a resolution of " << sheet_width << "x" << sheet_height << "px." << std::endl; @@ -17,7 +17,7 @@ PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s) { - int tx = index % sprite_width, ty = index / sprite_height; + int tx = index % sheet_width, ty = index / sheet_width; auto ir = sf::IntRect(tx * sprite_width, ty * sprite_height, sprite_width, sprite_height); auto sprite = sf::Sprite(texture, ir); sprite.setPosition(pos); From 84a8886da2570a8087f83141f0d41fef65073d99 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sun, 17 Mar 2024 16:29:33 -0400 Subject: [PATCH 5/8] Fixed render issue with UIGrid / PyTexture: wasn't positioning or scaling properly after fetching sprite --- src/UI.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/UI.cpp b/src/UI.cpp index 05c8594..b47fa1e 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -387,7 +387,7 @@ void UIGrid::render(sf::Vector2f) int left_spritepixels = center_x - (box.getSize().x / 2.0 / zoom); int top_spritepixels = center_y - (box.getSize().y / 2.0 / zoom); - sprite.setScale(sf::Vector2f(zoom, zoom)); + //sprite.setScale(sf::Vector2f(zoom, zoom)); sf::RectangleShape r; // for colors and overlays r.setSize(sf::Vector2f(ptex->sprite_width * zoom, ptex->sprite_height * zoom)); r.setOutlineThickness(0); @@ -414,7 +414,7 @@ void UIGrid::render(sf::Vector2f) auto gridpoint = at(std::floor(x), std::floor(y)); - sprite.setPosition(pixel_pos); + //sprite.setPosition(pixel_pos); r.setPosition(pixel_pos); r.setFillColor(gridpoint.color); @@ -424,7 +424,7 @@ void UIGrid::render(sf::Vector2f) // if discovered but not visible, set opacity to 90% // if not discovered... just don't draw it? if (gridpoint.tilesprite != -1) { - sprite = ptex->sprite(gridpoint.tilesprite); //setSprite(gridpoint.tilesprite); + sprite = ptex->sprite(gridpoint.tilesprite, pixel_pos, sf::Vector2f(zoom, zoom)); //setSprite(gridpoint.tilesprite);; renderTexture.draw(sprite); } } From 2cf8f9431025b3eecb67422e98ec95e3f2b4038f Mon Sep 17 00:00:00 2001 From: John McCardle Date: Wed, 20 Mar 2024 21:16:52 -0400 Subject: [PATCH 6/8] Radical new example pattern for exposing a C++ class to Python --- src/PyTexture.cpp | 23 +++++++++++++++++++ src/PyTexture.h | 49 +++++++++++++++++++++++++++++++++++++++++ src/UI.h | 3 +++ src/scripts/cos_play.py | 2 +- src/scripts/game.py | 8 +++---- 5 files changed, 80 insertions(+), 5 deletions(-) diff --git a/src/PyTexture.cpp b/src/PyTexture.cpp index 0f71f25..55e1c20 100644 --- a/src/PyTexture.cpp +++ b/src/PyTexture.cpp @@ -24,3 +24,26 @@ sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s) sprite.setScale(s); return sprite; } + +Py_hash_t PyTexture::hash(PyObject* obj) +{ + auto self = (PyTextureObject*)obj; + //return static_cast(reinterpret_cast(self->data)); + return reinterpret_cast(self->data.get()); +} + +int PyTexture::init(PyTextureObject* self, PyObject* args, PyObject* kwds) +{ + static const char* keywords[] = { "filename", "sprite_width", "sprite_height", nullptr }; + char* filename; + int sprite_width, sprite_height; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sii", const_cast(keywords), &filename, &sprite_width, &sprite_height)) + return -1; + self->data = std::make_shared(filename, sprite_width, sprite_height); + return 0; +} + +PyObject* PyTexture::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) +{ + return (PyObject*)type->tp_alloc(type, 0); +} diff --git a/src/PyTexture.h b/src/PyTexture.h index 8f13139..0cf56bc 100644 --- a/src/PyTexture.h +++ b/src/PyTexture.h @@ -2,14 +2,63 @@ #include "Common.h" #include "Python.h" +class PyTexture; + +typedef struct { + PyObject_HEAD + std::shared_ptr data; +} PyTextureObject; + class PyTexture { private: sf::Texture texture; std::string source; int sheet_width, sheet_height; +protected: + PyObject* self = 0; public: int sprite_width, sprite_height; // just use them read only, OK? PyTexture(std::string filename, int sprite_w, int sprite_h); sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)); + + PyObject* pyObject(); + static Py_hash_t hash(PyObject*); + static int init(PyTextureObject*, PyObject*, PyObject*); + static PyObject* pynew(PyTypeObject*, PyObject*, PyObject*); }; +/* +static int PyTexture_init(PyTextureObject* self, PyObject* args, PyObject* kwds) +{ + //std::cout << "Init called\n"; + static const char* keywords[] = { "filename", "grid_size", "grid_width", "grid_height", nullptr }; + char* filename; + int grid_size, grid_width, grid_height; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "siii", const_cast(keywords), &filename, &grid_size, &grid_width, &grid_height)) + { + return -1; + } + self->data = std::make_shared(filename, grid_size, grid_size); + return 0; +} +*/ +namespace mcrfpydef { + static PyTypeObject PyTextureType = { + .tp_name = "mcrfpy.Texture", + .tp_basicsize = sizeof(PyTextureObject), + .tp_itemsize = 0, + .tp_hash = PyTexture::hash, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = PyDoc_STR("SFML Texture Object"), + .tp_init = (initproc)PyTexture::init, + .tp_new = PyTexture::pynew, + /* + [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* + { + PyTextureObject* self = (PyTextureObject*)type->tp_alloc(type, 0); + return (PyObject*)self; + } + */ + }; +} diff --git a/src/UI.h b/src/UI.h index b732bfe..a90715b 100644 --- a/src/UI.h +++ b/src/UI.h @@ -1085,10 +1085,12 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c * */ + /* // Definition moved to PyTexture.h typedef struct { PyObject_HEAD std::shared_ptr data; } PyTextureObject; + static int PyTexture_init(PyTextureObject* self, PyObject* args, PyObject* kwds) { @@ -1121,6 +1123,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c return (PyObject*)self; } }; + */ /* * diff --git a/src/scripts/cos_play.py b/src/scripts/cos_play.py index fef09c1..5cc9ffd 100644 --- a/src/scripts/cos_play.py +++ b/src/scripts/cos_play.py @@ -1,7 +1,7 @@ import mcrfpy mcrfpy.createScene("play") ui = mcrfpy.sceneUI("play") -t = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 12, 11) +t = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) # 12, 11) font = mcrfpy.Font("assets/JetbrainsMono.ttf") frame_color = (64, 64, 128) diff --git a/src/scripts/game.py b/src/scripts/game.py index 18e46d0..c022aca 100644 --- a/src/scripts/game.py +++ b/src/scripts/game.py @@ -3,9 +3,9 @@ import mcrfpy import cos_play # Universal stuff font = mcrfpy.Font("assets/JetbrainsMono.ttf") -texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 12, 11) -texture_cold = mcrfpy.Texture("assets/kenney_ice.png", 16, 12, 11) -texture_hot = mcrfpy.Texture("assets/kenney_lava.png", 16, 12, 11) +texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) #12, 11) +texture_cold = mcrfpy.Texture("assets/kenney_ice.png", 16, 16) #12, 11) +texture_hot = mcrfpy.Texture("assets/kenney_lava.png", 16, 16) #12, 11) # Test stuff mcrfpy.createScene("boom") @@ -125,7 +125,7 @@ stress_test() mcrfpy.createScene("loading") ui = mcrfpy.sceneUI("loading") #mcrfpy.setScene("loading") -logo_texture = mcrfpy.Texture("assets/temp_logo.png", 1024, 1, 1) +logo_texture = mcrfpy.Texture("assets/temp_logo.png", 1024, 1024)#1, 1) logo_sprite = mcrfpy.Sprite(50, 50, logo_texture, 0, 0.5) ui.append(logo_sprite) logo_sprite.click = lambda *args: mcrfpy.setScene("menu") From d7228172c4d5455159cd91782b49304a971bb444 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Thu, 21 Mar 2024 21:39:15 -0400 Subject: [PATCH 7/8] Messy, but monumental: PyTexture::pyObject works this also coincidentally fixes a weird bug I encountered while (mis?)using tp_alloc: by using PyType_GenericAlloc, I avoid the segfault that tp_alloc sometimes causes. See the horrible UIDrawable retrieval macro that I use in UI.h for a workaround that can probably be replaced with this technique --- src/McRFPy_API.cpp | 23 ++++++++----- src/PyTexture.cpp | 35 ++++++++++++++++++++ src/PyTexture.h | 82 +++++++++++++++++++++++----------------------- src/UI.cpp | 7 ++++ src/UI.h | 14 ++++++-- 5 files changed, 110 insertions(+), 51 deletions(-) diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index 113c13a..9a65a61 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -55,30 +55,37 @@ PyObject* PyInit_mcrfpy() // This code runs, but Python segfaults when accessing the UIFrame type. //std::cout << "Adding UIFrame object to module\n"; + using namespace mcrfpydef; + PyTypeObject* pytypes[] = {&PyColorType, &PyFontType, &PyUICaptionType, &PyTextureType, &PyUISpriteType, &PyUIFrameType, &PyUICollectionType, + &PyUICollectionIterType, &PyUIGridPointType, &PyUIGridPointStateType, &PyUIEntityType, &PyUIEntityCollectionType, + &PyUIEntityCollectionIterType, &PyUIGridType, nullptr}; + int i = 0; + auto t = pytypes[i]; + while (t != nullptr) + { + PyType_Ready(t); + PyModule_AddType(m, t); + t = pytypes[i++]; + } + /* PyModule_AddType(m, &mcrfpydef::PyColorType); PyModule_AddType(m, &mcrfpydef::PyFontType); PyModule_AddType(m, &mcrfpydef::PyUICaptionType); PyModule_AddType(m, &mcrfpydef::PyTextureType); PyModule_AddType(m, &mcrfpydef::PyUISpriteType); - if (PyModule_AddType(m, &mcrfpydef::PyUIFrameType) < 0) - { - std::cout << "Error adding UIFrame type to module; aborting" << std::endl; - Py_DECREF(&mcrfpydef::PyUIFrameType); - return NULL; - } + PyModule_AddType(m, &mcrfpydef::PyUIFrameType); PyModule_AddType(m, &mcrfpydef::PyUICollectionType); PyModule_AddType(m, &mcrfpydef::PyUICollectionIterType); PyModule_AddType(m, &mcrfpydef::PyUIGridPointType); PyModule_AddType(m, &mcrfpydef::PyUIGridPointStateType); PyModule_AddType(m, &mcrfpydef::PyUIEntityType); - PyModule_AddType(m, &mcrfpydef::PyUIEntityCollectionIterType); PyModule_AddType(m, &mcrfpydef::PyUIEntityCollectionType); PyModule_AddType(m, &mcrfpydef::PyUIGridType); - + */ return m; diff --git a/src/PyTexture.cpp b/src/PyTexture.cpp index 55e1c20..f21311e 100644 --- a/src/PyTexture.cpp +++ b/src/PyTexture.cpp @@ -1,4 +1,6 @@ #include "PyTexture.h" +using namespace mcrfpydef; + PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) : source(filename), sprite_width(sprite_w), sprite_height(sprite_h) @@ -15,6 +17,17 @@ PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) } } +/* // bit misguided here: holding self might prevent the shared_ptr from ever being released. +PyTexture::~PyTexture() +{ + if (self != NULL) + { + (PyTextureObject*)self->data.reset(); + Py_DECREF(self); + } +} +*/ + sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s) { int tx = index % sheet_width, ty = index / sheet_width; @@ -25,6 +38,28 @@ sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s) return sprite; } +PyObject* PyTexture::pyObject() +{ + //PyTextureObject* self = (PyTextureObject*)pynew(&mcrfpydef::PyTextureType, NULL, NULL); + std::cout << "tp_alloc (GenericAlloc)" << std::endl; + //PyObject* obj = ((&PyTextureType)->tp_alloc(&PyTextureType, 0)); + //PyObject* obj = pynew(&PyTextureType); + PyObject* obj = PyType_GenericAlloc(&PyTextureType, 0); + std::cout << "alloc worked" << std::endl; + //Py_INCREF(self); + try { + std::cout << "assign data to self" << std::endl; + ((PyTextureObject*)obj)->data = shared_from_this(); + } + catch (std::bad_weak_ptr& e) + { + std::cout << "Bad weak ptr: shared_from_this() failed" << std::endl; + } + // TODO - shared_from_this will raise an exception if the object does not have a shared pointer. Constructor should be made private; write a factory function + std::cout << "returning PyObject" << std::endl; + return obj; +} + Py_hash_t PyTexture::hash(PyObject* obj) { auto self = (PyTextureObject*)obj; diff --git a/src/PyTexture.h b/src/PyTexture.h index 0cf56bc..9e7a7bc 100644 --- a/src/PyTexture.h +++ b/src/PyTexture.h @@ -2,48 +2,48 @@ #include "Common.h" #include "Python.h" -class PyTexture; - -typedef struct { - PyObject_HEAD - std::shared_ptr data; -} PyTextureObject; - -class PyTexture -{ -private: - sf::Texture texture; - std::string source; - int sheet_width, sheet_height; -protected: - PyObject* self = 0; -public: - int sprite_width, sprite_height; // just use them read only, OK? - PyTexture(std::string filename, int sprite_w, int sprite_h); - sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)); - - PyObject* pyObject(); - static Py_hash_t hash(PyObject*); - static int init(PyTextureObject*, PyObject*, PyObject*); - static PyObject* pynew(PyTypeObject*, PyObject*, PyObject*); -}; -/* -static int PyTexture_init(PyTextureObject* self, PyObject* args, PyObject* kwds) -{ - //std::cout << "Init called\n"; - static const char* keywords[] = { "filename", "grid_size", "grid_width", "grid_height", nullptr }; - char* filename; - int grid_size, grid_width, grid_height; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "siii", const_cast(keywords), &filename, &grid_size, &grid_width, &grid_height)) - { - return -1; - } - self->data = std::make_shared(filename, grid_size, grid_size); - return 0; -} -*/ namespace mcrfpydef { + class PyTexture; + + typedef struct { + PyObject_HEAD + std::shared_ptr data; + } PyTextureObject; + + class PyTexture : public std::enable_shared_from_this + { + private: + sf::Texture texture; + std::string source; + int sheet_width, sheet_height; + protected: + //PyObject* self = 0; + public: + int sprite_width, sprite_height; // just use them read only, OK? + PyTexture(std::string filename, int sprite_w, int sprite_h); + sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)); + + PyObject* pyObject(); + static Py_hash_t hash(PyObject*); + static int init(PyTextureObject*, PyObject*, PyObject*); + static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); + }; + /* + static int PyTexture_init(PyTextureObject* self, PyObject* args, PyObject* kwds) + { + //std::cout << "Init called\n"; + static const char* keywords[] = { "filename", "grid_size", "grid_width", "grid_height", nullptr }; + char* filename; + int grid_size, grid_width, grid_height; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "siii", const_cast(keywords), &filename, &grid_size, &grid_width, &grid_height)) + { + return -1; + } + self->data = std::make_shared(filename, grid_size, grid_size); + return 0; + } + */ static PyTypeObject PyTextureType = { .tp_name = "mcrfpy.Texture", .tp_basicsize = sizeof(PyTextureObject), diff --git a/src/UI.cpp b/src/UI.cpp index b47fa1e..116e6b4 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -2,6 +2,8 @@ #include "Resources.h" #include "GameEngine.h" +using namespace mcrfpydef; + /* //callability fields & methods PyObject* click_callable; virtual UIDrawable* click_at(sf::Vector2f point); @@ -520,3 +522,8 @@ PyObjectsEnum UIGrid::derived_type() { return PyObjectsEnum::UIGRID; } + +std::shared_ptr UIGrid::getTexture() +{ + return ptex; +} diff --git a/src/UI.h b/src/UI.h index a90715b..a803a32 100644 --- a/src/UI.h +++ b/src/UI.h @@ -8,6 +8,8 @@ #include "PyCallable.h" #include "PyTexture.h" +using namespace mcrfpydef; + enum PyObjectsEnum : int { UIFRAME = 1, @@ -187,6 +189,7 @@ public: sf::RectangleShape box; float center_x, center_y, zoom; //IndexTexture* itex; + std::shared_ptr getTexture(); sf::Sprite sprite, output; sf::RenderTexture renderTexture; std::vector points; @@ -1215,7 +1218,8 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c static PyObject* PyUISprite_get_texture(PyUISpriteObject* self, void* closure) { - return NULL; + std::cout << "Calling pyObject" << std::endl; + return self->data->getTexture()->pyObject(); } static int PyUISprite_set_texture(PyUISpriteObject* self, PyObject* value, void* closure) @@ -1791,6 +1795,12 @@ static PyObject* PyUIGrid_get_texture(PyUIGridObject* self, void* closure) { return self->texture; } */ +static PyObject* PyUIGrid_get_texture(PyUIGridObject* self, void* closure) { + //return self->data->getTexture()->pyObject(); + PyTextureObject* obj = (PyTextureObject*)((&PyTextureType)->tp_alloc(&PyTextureType, 0)); + obj->data = self->data->getTexture(); + return (PyObject*)obj; +} static PyObject* PyUIGrid_at(PyUIGridObject* self, PyObject* o) { @@ -1842,7 +1852,7 @@ static PyGetSetDef PyUIGrid_getsetters[] = { {"click", (getter)PyUIDrawable_get_click, (setter)PyUIDrawable_set_click, "Object called with (x, y, button) when clicked", (void*)PyObjectsEnum::UIGRID}, - //{"texture", (getter)PyUIGrid_get_texture, NULL, "Texture of the grid", NULL}, //TODO 7DRL-day2-item5 + {"texture", (getter)PyUIGrid_get_texture, NULL, "Texture of the grid", NULL}, //TODO 7DRL-day2-item5 {NULL} /* Sentinel */ }; From b114ec308518607fad5777c6c1b516381e2a78b9 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Thu, 21 Mar 2024 22:22:35 -0400 Subject: [PATCH 8/8] cleaning up for merge --- src/McRFPy_API.cpp | 39 +++++++++---------------- src/PyTexture.cpp | 25 ++-------------- src/PyTexture.h | 72 ++++++++++++++++------------------------------ src/UI.cpp | 2 -- src/UI.h | 55 ----------------------------------- 5 files changed, 40 insertions(+), 153 deletions(-) diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index 9a65a61..51bd3c7 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -53,12 +53,21 @@ PyObject* PyInit_mcrfpy() return NULL; } - // This code runs, but Python segfaults when accessing the UIFrame type. - //std::cout << "Adding UIFrame object to module\n"; using namespace mcrfpydef; - PyTypeObject* pytypes[] = {&PyColorType, &PyFontType, &PyUICaptionType, &PyTextureType, &PyUISpriteType, &PyUIFrameType, &PyUICollectionType, - &PyUICollectionIterType, &PyUIGridPointType, &PyUIGridPointStateType, &PyUIEntityType, &PyUIEntityCollectionType, - &PyUIEntityCollectionIterType, &PyUIGridType, nullptr}; + PyTypeObject* pytypes[] = { + /*SFML exposed types*/ + &PyColorType, &PyFontType, &PyTextureType, + + /*UI widgets*/ + &PyUICaptionType, &PyUISpriteType, &PyUIFrameType, &PyUIEntityType, &PyUIGridType, + + /*game map & perspective data*/ + &PyUIGridPointType, &PyUIGridPointStateType, + + /*collections & iterators*/ + &PyUICollectionType, &PyUICollectionIterType, + &PyUIEntityCollectionType, &PyUIEntityCollectionIterType, + nullptr}; int i = 0; auto t = pytypes[i]; while (t != nullptr) @@ -67,26 +76,6 @@ PyObject* PyInit_mcrfpy() PyModule_AddType(m, t); t = pytypes[i++]; } - /* - PyModule_AddType(m, &mcrfpydef::PyColorType); - PyModule_AddType(m, &mcrfpydef::PyFontType); - PyModule_AddType(m, &mcrfpydef::PyUICaptionType); - PyModule_AddType(m, &mcrfpydef::PyTextureType); - PyModule_AddType(m, &mcrfpydef::PyUISpriteType); - - PyModule_AddType(m, &mcrfpydef::PyUIFrameType); - PyModule_AddType(m, &mcrfpydef::PyUICollectionType); - PyModule_AddType(m, &mcrfpydef::PyUICollectionIterType); - - PyModule_AddType(m, &mcrfpydef::PyUIGridPointType); - PyModule_AddType(m, &mcrfpydef::PyUIGridPointStateType); - PyModule_AddType(m, &mcrfpydef::PyUIEntityType); - PyModule_AddType(m, &mcrfpydef::PyUIEntityCollectionIterType); - PyModule_AddType(m, &mcrfpydef::PyUIEntityCollectionType); - - PyModule_AddType(m, &mcrfpydef::PyUIGridType); - */ - return m; } diff --git a/src/PyTexture.cpp b/src/PyTexture.cpp index f21311e..7ce1b7b 100644 --- a/src/PyTexture.cpp +++ b/src/PyTexture.cpp @@ -1,5 +1,4 @@ #include "PyTexture.h" -using namespace mcrfpydef; PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) @@ -17,17 +16,6 @@ PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h) } } -/* // bit misguided here: holding self might prevent the shared_ptr from ever being released. -PyTexture::~PyTexture() -{ - if (self != NULL) - { - (PyTextureObject*)self->data.reset(); - Py_DECREF(self); - } -} -*/ - sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s) { int tx = index % sheet_width, ty = index / sheet_width; @@ -40,30 +28,21 @@ sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s) PyObject* PyTexture::pyObject() { - //PyTextureObject* self = (PyTextureObject*)pynew(&mcrfpydef::PyTextureType, NULL, NULL); - std::cout << "tp_alloc (GenericAlloc)" << std::endl; - //PyObject* obj = ((&PyTextureType)->tp_alloc(&PyTextureType, 0)); - //PyObject* obj = pynew(&PyTextureType); - PyObject* obj = PyType_GenericAlloc(&PyTextureType, 0); - std::cout << "alloc worked" << std::endl; - //Py_INCREF(self); + PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyTextureType, 0); try { - std::cout << "assign data to self" << std::endl; ((PyTextureObject*)obj)->data = shared_from_this(); } catch (std::bad_weak_ptr& e) { - std::cout << "Bad weak ptr: shared_from_this() failed" << std::endl; + std::cout << "Bad weak ptr: shared_from_this() failed in PyTexture::pyObject(); did you create a PyTexture outside of std::make_shared? enjoy your segfault, soon!" << std::endl; } // TODO - shared_from_this will raise an exception if the object does not have a shared pointer. Constructor should be made private; write a factory function - std::cout << "returning PyObject" << std::endl; return obj; } Py_hash_t PyTexture::hash(PyObject* obj) { auto self = (PyTextureObject*)obj; - //return static_cast(reinterpret_cast(self->data)); return reinterpret_cast(self->data.get()); } diff --git a/src/PyTexture.h b/src/PyTexture.h index 9e7a7bc..eea1838 100644 --- a/src/PyTexture.h +++ b/src/PyTexture.h @@ -2,48 +2,31 @@ #include "Common.h" #include "Python.h" +class PyTexture; + +typedef struct { + PyObject_HEAD + std::shared_ptr data; +} PyTextureObject; + +class PyTexture : public std::enable_shared_from_this +{ +private: + sf::Texture texture; + std::string source; + int sheet_width, sheet_height; +public: + int sprite_width, sprite_height; // just use them read only, OK? + PyTexture(std::string filename, int sprite_w, int sprite_h); + sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)); + + PyObject* pyObject(); + static Py_hash_t hash(PyObject*); + static int init(PyTextureObject*, PyObject*, PyObject*); + static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); +}; + namespace mcrfpydef { - class PyTexture; - - typedef struct { - PyObject_HEAD - std::shared_ptr data; - } PyTextureObject; - - class PyTexture : public std::enable_shared_from_this - { - private: - sf::Texture texture; - std::string source; - int sheet_width, sheet_height; - protected: - //PyObject* self = 0; - public: - int sprite_width, sprite_height; // just use them read only, OK? - PyTexture(std::string filename, int sprite_w, int sprite_h); - sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0)); - - PyObject* pyObject(); - static Py_hash_t hash(PyObject*); - static int init(PyTextureObject*, PyObject*, PyObject*); - static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); - }; - /* - static int PyTexture_init(PyTextureObject* self, PyObject* args, PyObject* kwds) - { - //std::cout << "Init called\n"; - static const char* keywords[] = { "filename", "grid_size", "grid_width", "grid_height", nullptr }; - char* filename; - int grid_size, grid_width, grid_height; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "siii", const_cast(keywords), &filename, &grid_size, &grid_width, &grid_height)) - { - return -1; - } - self->data = std::make_shared(filename, grid_size, grid_size); - return 0; - } - */ static PyTypeObject PyTextureType = { .tp_name = "mcrfpy.Texture", .tp_basicsize = sizeof(PyTextureObject), @@ -53,12 +36,5 @@ namespace mcrfpydef { .tp_doc = PyDoc_STR("SFML Texture Object"), .tp_init = (initproc)PyTexture::init, .tp_new = PyTexture::pynew, - /* - [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* - { - PyTextureObject* self = (PyTextureObject*)type->tp_alloc(type, 0); - return (PyObject*)self; - } - */ }; } diff --git a/src/UI.cpp b/src/UI.cpp index 116e6b4..5d43918 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -2,8 +2,6 @@ #include "Resources.h" #include "GameEngine.h" -using namespace mcrfpydef; - /* //callability fields & methods PyObject* click_callable; virtual UIDrawable* click_at(sf::Vector2f point); diff --git a/src/UI.h b/src/UI.h index a803a32..c45fe42 100644 --- a/src/UI.h +++ b/src/UI.h @@ -8,8 +8,6 @@ #include "PyCallable.h" #include "PyTexture.h" -using namespace mcrfpydef; - enum PyObjectsEnum : int { UIFRAME = 1, @@ -1082,58 +1080,6 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c * */ - /* - * - * Begin PyTextureType defs - * - */ - - /* // Definition moved to PyTexture.h - typedef struct { - PyObject_HEAD - std::shared_ptr data; - } PyTextureObject; - - - static int PyTexture_init(PyTextureObject* self, PyObject* args, PyObject* kwds) - { - //std::cout << "Init called\n"; - static const char* keywords[] = { "filename", "grid_size", "grid_width", "grid_height", nullptr }; - char* filename; - int grid_size, grid_width, grid_height; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "siii", const_cast(keywords), &filename, &grid_size, &grid_width, &grid_height)) - { - return -1; - } - //sf::Texture t = sf::Texture(); - //t.loadFromFile((std::string)filename); - self->data = std::make_shared(filename, grid_size, grid_size); - return 0; - } - - static PyTypeObject PyTextureType = { - //PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "mcrfpy.Texture", - .tp_basicsize = sizeof(PyTextureObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = PyDoc_STR("SFML Texture Object"), - .tp_init = (initproc)PyTexture_init, - .tp_new = [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* - { - PyTextureObject* self = (PyTextureObject*)type->tp_alloc(type, 0); - return (PyObject*)self; - } - }; - */ - - /* - * - * End PyTextureType defs - * - */ - /* * * Begin template generation for PyUISpriteType @@ -1218,7 +1164,6 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c static PyObject* PyUISprite_get_texture(PyUISpriteObject* self, void* closure) { - std::cout << "Calling pyObject" << std::endl; return self->data->getTexture()->pyObject(); }