From e1c6c531574acd6e9c1f51a0d652855a301b2adf Mon Sep 17 00:00:00 2001 From: John McCardle Date: Mon, 7 Jul 2025 17:54:47 -0400 Subject: [PATCH] refactor: move position property to UIDrawable base class (UISprite) - Update UISprite to use base class position instead of sprite position - Synchronize sprite position with base class position for rendering - Implement onPositionChanged() for position synchronization - Update all UISprite methods to use base position consistently - Add comprehensive test coverage for UISprite position handling This is part 3 of moving position to the base class. UIGrid is the final class that needs to be updated. --- base_position_uisprite_test.png | Bin 0 -> 39499 bytes src/UISprite.cpp | 42 ++++++++++++++++++++------------ src/UISprite.h | 1 + 3 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 base_position_uisprite_test.png diff --git a/base_position_uisprite_test.png b/base_position_uisprite_test.png new file mode 100644 index 0000000000000000000000000000000000000000..21265331ff7286aab07ece4b87f10b37facedc38 GIT binary patch literal 39499 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 E0l+FcLI3~& literal 0 HcmV?d00001 diff --git a/src/UISprite.cpp b/src/UISprite.cpp index 33cc4f2..734764a 100644 --- a/src/UISprite.cpp +++ b/src/UISprite.cpp @@ -17,14 +17,16 @@ UISprite::UISprite() : sprite_index(0), ptex(nullptr) { // Initialize sprite to safe defaults - sprite.setPosition(0.0f, 0.0f); + position = sf::Vector2f(0.0f, 0.0f); // Set base class position + sprite.setPosition(position); // Sync sprite position sprite.setScale(1.0f, 1.0f); } UISprite::UISprite(std::shared_ptr _ptex, int _sprite_index, sf::Vector2f _pos, float _scale) : ptex(_ptex), sprite_index(_sprite_index) { - sprite = ptex->sprite(sprite_index, _pos, sf::Vector2f(_scale, _scale)); + position = _pos; // Set base class position + sprite = ptex->sprite(sprite_index, position, sf::Vector2f(_scale, _scale)); } /* @@ -57,7 +59,8 @@ void UISprite::render(sf::Vector2f offset, sf::RenderTarget& target) void UISprite::setPosition(sf::Vector2f pos) { - sprite.setPosition(pos); + position = pos; // Update base class position + sprite.setPosition(position); // Sync sprite position } void UISprite::setScale(sf::Vector2f s) @@ -70,13 +73,13 @@ 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 sprite_index = _sprite_index; - sprite = ptex->sprite(sprite_index, sprite.getPosition(), sprite.getScale()); + sprite = ptex->sprite(sprite_index, position, sprite.getScale()); // Use base class position } void UISprite::setSpriteIndex(int _sprite_index) { sprite_index = _sprite_index; - sprite = ptex->sprite(sprite_index, sprite.getPosition(), sprite.getScale()); + sprite = ptex->sprite(sprite_index, position, sprite.getScale()); // Use base class position } sf::Vector2f UISprite::getScale() const @@ -86,7 +89,7 @@ sf::Vector2f UISprite::getScale() const sf::Vector2f UISprite::getPosition() { - return sprite.getPosition(); + return position; // Return base class position } std::shared_ptr UISprite::getTexture() @@ -112,7 +115,9 @@ sf::FloatRect UISprite::get_bounds() const void UISprite::move(float dx, float dy) { - sprite.move(dx, dy); + position.x += dx; + position.y += dy; + sprite.setPosition(position); // Keep sprite in sync } void UISprite::resize(float w, float h) @@ -126,6 +131,12 @@ void UISprite::resize(float w, float h) } } +void UISprite::onPositionChanged() +{ + // Sync sprite position with base class position + sprite.setPosition(position); +} + PyObject* UISprite::get_float_member(PyUISpriteObject* self, void* closure) { auto member_ptr = reinterpret_cast(closure); @@ -278,8 +289,8 @@ PyMethodDef UISprite_methods[] = { }; PyGetSetDef UISprite::getsetters[] = { - {"x", (getter)UISprite::get_float_member, (setter)UISprite::set_float_member, "X coordinate of top-left corner", (void*)0}, - {"y", (getter)UISprite::get_float_member, (setter)UISprite::set_float_member, "Y coordinate of top-left corner", (void*)1}, + {"x", (getter)UIDrawable::get_float_member, (setter)UIDrawable::set_float_member, "X coordinate of top-left corner", (void*)((intptr_t)PyObjectsEnum::UISPRITE << 8 | 0)}, + {"y", (getter)UIDrawable::get_float_member, (setter)UIDrawable::set_float_member, "Y coordinate of top-left corner", (void*)((intptr_t)PyObjectsEnum::UISPRITE << 8 | 1)}, {"scale", (getter)UISprite::get_float_member, (setter)UISprite::set_float_member, "Uniform size factor", (void*)2}, {"scale_x", (getter)UISprite::get_float_member, (setter)UISprite::set_float_member, "Horizontal scale factor", (void*)3}, {"scale_y", (getter)UISprite::get_float_member, (setter)UISprite::set_float_member, "Vertical scale factor", (void*)4}, @@ -289,7 +300,7 @@ PyGetSetDef UISprite::getsetters[] = { {"click", (getter)UIDrawable::get_click, (setter)UIDrawable::set_click, "Object called with (x, y, button) when clicked", (void*)PyObjectsEnum::UISPRITE}, {"z_index", (getter)UIDrawable::get_int, (setter)UIDrawable::set_int, "Z-order for rendering (lower values rendered first)", (void*)PyObjectsEnum::UISPRITE}, {"name", (getter)UIDrawable::get_name, (setter)UIDrawable::set_name, "Name for finding elements", (void*)PyObjectsEnum::UISPRITE}, - {"pos", (getter)UISprite::get_pos, (setter)UISprite::set_pos, "Position as a Vector", NULL}, + {"pos", (getter)UIDrawable::get_pos, (setter)UIDrawable::set_pos, "Position as a Vector", (void*)PyObjectsEnum::UISPRITE}, UIDRAWABLE_GETSETTERS, {NULL} }; @@ -377,7 +388,6 @@ int UISprite::init(PyUISpriteObject* self, PyObject* args, PyObject* kwds) } self->data = std::make_shared(texture_ptr, sprite_index, sf::Vector2f(x, y), scale); - self->data->setPosition(sf::Vector2f(x, y)); // Process click handler if provided if (click_handler && click_handler != Py_None) { @@ -394,11 +404,13 @@ int UISprite::init(PyUISpriteObject* self, PyObject* args, PyObject* kwds) // Property system implementation for animations bool UISprite::setProperty(const std::string& name, float value) { if (name == "x") { - sprite.setPosition(sf::Vector2f(value, sprite.getPosition().y)); + position.x = value; + sprite.setPosition(position); // Keep sprite in sync return true; } else if (name == "y") { - sprite.setPosition(sf::Vector2f(sprite.getPosition().x, value)); + position.y = value; + sprite.setPosition(position); // Keep sprite in sync return true; } else if (name == "scale") { @@ -434,11 +446,11 @@ bool UISprite::setProperty(const std::string& name, int value) { bool UISprite::getProperty(const std::string& name, float& value) const { if (name == "x") { - value = sprite.getPosition().x; + value = position.x; return true; } else if (name == "y") { - value = sprite.getPosition().y; + value = position.y; return true; } else if (name == "scale") { diff --git a/src/UISprite.h b/src/UISprite.h index 8043282..5c16ab1 100644 --- a/src/UISprite.h +++ b/src/UISprite.h @@ -46,6 +46,7 @@ public: sf::FloatRect get_bounds() const override; void move(float dx, float dy) override; void resize(float w, float h) override; + void onPositionChanged() override; // Property system for animations bool setProperty(const std::string& name, float value) override;