#include "UISprite.h" #include "GameEngine.h" UIDrawable* UISprite::click_at(sf::Vector2f point) { if (click_callable) { if(sprite.getGlobalBounds().contains(point)) return this; } return NULL; } UISprite::UISprite() {} 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)); } /* void UISprite::render(sf::Vector2f offset) { sprite.move(offset); Resources::game->getWindow().draw(sprite); sprite.move(-offset); } */ void UISprite::render(sf::Vector2f offset, sf::RenderTarget& target) { sprite.move(offset); target.draw(sprite); sprite.move(-offset); } void UISprite::setPosition(sf::Vector2f pos) { sprite.setPosition(pos); } void UISprite::setScale(sf::Vector2f s) { sprite.setScale(s); } 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()); } void UISprite::setSpriteIndex(int _sprite_index) { sprite_index = _sprite_index; sprite = ptex->sprite(sprite_index, sprite.getPosition(), sprite.getScale()); } sf::Vector2f UISprite::getScale() const { return sprite.getScale(); } sf::Vector2f UISprite::getPosition() { return sprite.getPosition(); } std::shared_ptr UISprite::getTexture() { return ptex; } int UISprite::getSpriteIndex() { return sprite_index; } PyObjectsEnum UISprite::derived_type() { return PyObjectsEnum::UISPRITE; } PyObject* UISprite::get_float_member(PyUISpriteObject* self, void* closure) { auto member_ptr = reinterpret_cast(closure); if (member_ptr == 0) return PyFloat_FromDouble(self->data->getPosition().x); else if (member_ptr == 1) return PyFloat_FromDouble(self->data->getPosition().y); else if (member_ptr == 2) return PyFloat_FromDouble(self->data->getScale().x); // scale X and Y are identical, presently else { PyErr_SetString(PyExc_AttributeError, "Invalid attribute"); return nullptr; } } int UISprite::set_float_member(PyUISpriteObject* self, PyObject* value, void* closure) { float val; auto member_ptr = reinterpret_cast(closure); if (PyFloat_Check(value)) { val = PyFloat_AsDouble(value); } else if (PyLong_Check(value)) { val = PyLong_AsLong(value); } else { PyErr_SetString(PyExc_TypeError, "Value must be a floating point number."); return -1; } if (member_ptr == 0) //x self->data->setPosition(sf::Vector2f(val, self->data->getPosition().y)); else if (member_ptr == 1) //y self->data->setPosition(sf::Vector2f(self->data->getPosition().x, val)); else if (member_ptr == 2) // scale self->data->setScale(sf::Vector2f(val, val)); return 0; } PyObject* UISprite::get_int_member(PyUISpriteObject* self, void* closure) { auto member_ptr = reinterpret_cast(closure); if (true) {} else { PyErr_SetString(PyExc_AttributeError, "Invalid attribute"); return nullptr; } return PyLong_FromDouble(self->data->getSpriteIndex()); } int UISprite::set_int_member(PyUISpriteObject* self, PyObject* value, void* closure) { int val; auto member_ptr = reinterpret_cast(closure); if (PyLong_Check(value)) { val = PyLong_AsLong(value); } else { PyErr_SetString(PyExc_TypeError, "Value must be an integer."); return -1; } // Validate sprite index is within texture bounds auto texture = self->data->getTexture(); if (texture) { int sprite_count = texture->getSpriteCount(); if (val < 0 || val >= sprite_count) { PyErr_Format(PyExc_ValueError, "Sprite index %d out of range. Texture has %d sprites (0-%d)", val, sprite_count, sprite_count - 1); return -1; } } self->data->setSpriteIndex(val); return 0; } PyObject* UISprite::get_texture(PyUISpriteObject* self, void* closure) { return self->data->getTexture()->pyObject(); } int UISprite::set_texture(PyUISpriteObject* self, PyObject* value, void* closure) { // Check if value is a Texture instance if (!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture"))) { PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance"); return -1; } // Get the texture from the Python object auto pytexture = (PyTextureObject*)value; if (!pytexture->data) { PyErr_SetString(PyExc_ValueError, "Invalid texture object"); return -1; } // Update the sprite's texture self->data->setTexture(pytexture->data); return 0; } 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}, {"scale", (getter)UISprite::get_float_member, (setter)UISprite::set_float_member, "Size factor", (void*)2}, {"sprite_number", (getter)UISprite::get_int_member, (setter)UISprite::set_int_member, "Which sprite on the texture is shown", NULL}, {"texture", (getter)UISprite::get_texture, (setter)UISprite::set_texture, "Texture object", NULL}, {"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}, {NULL} }; PyObject* UISprite::repr(PyUISpriteObject* self) { std::ostringstream ss; if (!self->data) ss << ""; else { //auto sprite = self->data->sprite; ss << ""; } std::string repr_str = ss.str(); return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); } int UISprite::init(PyUISpriteObject* self, PyObject* args, PyObject* kwds) { //std::cout << "Init called\n"; static const char* keywords[] = { "x", "y", "texture", "sprite_index", "scale", nullptr }; float x = 0.0f, y = 0.0f, scale = 1.0f; int sprite_index = 0; PyObject* texture = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ffOif", const_cast(keywords), &x, &y, &texture, &sprite_index, &scale)) { return -1; } // Handle texture - allow None or use default std::shared_ptr texture_ptr = nullptr; if (texture != NULL && texture != Py_None && !PyObject_IsInstance(texture, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture"))){ PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance or None"); return -1; } else if (texture != NULL && texture != Py_None) { auto pytexture = (PyTextureObject*)texture; texture_ptr = pytexture->data; } else { // Use default texture when None or not provided texture_ptr = McRFPy_API::default_texture; } if (!texture_ptr) { PyErr_SetString(PyExc_RuntimeError, "No texture provided and no default texture available"); return -1; } self->data = std::make_shared(texture_ptr, sprite_index, sf::Vector2f(x, y), scale); self->data->setPosition(sf::Vector2f(x, y)); return 0; } // 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)); return true; } else if (name == "y") { sprite.setPosition(sf::Vector2f(sprite.getPosition().x, value)); return true; } else if (name == "scale") { sprite.setScale(sf::Vector2f(value, value)); return true; } else if (name == "scale_x") { sprite.setScale(sf::Vector2f(value, sprite.getScale().y)); return true; } else if (name == "scale_y") { sprite.setScale(sf::Vector2f(sprite.getScale().x, value)); return true; } else if (name == "z_index") { z_index = static_cast(value); return true; } return false; } bool UISprite::setProperty(const std::string& name, int value) { if (name == "sprite_number") { setSpriteIndex(value); return true; } else if (name == "z_index") { z_index = value; return true; } return false; } bool UISprite::getProperty(const std::string& name, float& value) const { if (name == "x") { value = sprite.getPosition().x; return true; } else if (name == "y") { value = sprite.getPosition().y; return true; } else if (name == "scale") { value = sprite.getScale().x; // Assuming uniform scale return true; } else if (name == "scale_x") { value = sprite.getScale().x; return true; } else if (name == "scale_y") { value = sprite.getScale().y; return true; } else if (name == "z_index") { value = static_cast(z_index); return true; } return false; } bool UISprite::getProperty(const std::string& name, int& value) const { if (name == "sprite_number") { value = sprite_index; return true; } else if (name == "z_index") { value = z_index; return true; } return false; }