Squashed commit of the following: [standardize_texture_handling]

closes #18

commit b114ec3085
Author: John McCardle <mccardle.john@gmail.com>
Date:   Thu Mar 21 22:22:35 2024 -0400

    cleaning up for merge

commit d7228172c4
Author: John McCardle <mccardle.john@gmail.com>
Date:   Thu Mar 21 21:39:15 2024 -0400

    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

commit 2cf8f94310
Author: John McCardle <mccardle.john@gmail.com>
Date:   Wed Mar 20 21:16:52 2024 -0400

    Radical new example pattern for exposing a C++ class to Python

commit 84a8886da2
Author: John McCardle <mccardle.john@gmail.com>
Date:   Sun Mar 17 16:29:33 2024 -0400

    Fixed render issue with UIGrid / PyTexture: wasn't positioning or scaling properly after fetching sprite

commit 20f80c4114
Author: John McCardle <mccardle.john@gmail.com>
Date:   Sun Mar 17 16:23:52 2024 -0400

    Fixed sprite indexing error in PyTexture; needs non-square sprite tests, but feeling confident!

commit afd4ff1925
Author: John McCardle <mccardle.john@gmail.com>
Date:   Sat Mar 16 21:53:24 2024 -0400

    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?)

commit bfd33102d1
Author: John McCardle <mccardle.john@gmail.com>
Date:   Sat Mar 16 14:52:35 2024 -0400

    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

commit 47d0e34a17
Author: John McCardle <mccardle.john@gmail.com>
Date:   Sat Mar 16 11:31:39 2024 -0400

    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);`
This commit is contained in:
John McCardle 2024-03-21 22:24:42 -04:00
commit 4ffe438d1b
8 changed files with 295 additions and 164 deletions

63
src/PyTexture.cpp Normal file
View file

@ -0,0 +1,63 @@
#include "PyTexture.h"
PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h)
: source(filename), sprite_width(sprite_w), sprite_height(sprite_h)
{
texture = sf::Texture();
texture.loadFromFile(source);
auto size = texture.getSize();
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;
}
}
sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s)
{
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);
sprite.setScale(s);
return sprite;
}
PyObject* PyTexture::pyObject()
{
PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyTextureType, 0);
try {
((PyTextureObject*)obj)->data = shared_from_this();
}
catch (std::bad_weak_ptr& e)
{
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
return obj;
}
Py_hash_t PyTexture::hash(PyObject* obj)
{
auto self = (PyTextureObject*)obj;
return reinterpret_cast<Py_hash_t>(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<char**>(keywords), &filename, &sprite_width, &sprite_height))
return -1;
self->data = std::make_shared<PyTexture>(filename, sprite_width, sprite_height);
return 0;
}
PyObject* PyTexture::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds)
{
return (PyObject*)type->tp_alloc(type, 0);
}