2024-02-25 03:47:20 +00:00
# pragma once
# include "Common.h"
# include "Python.h"
# include "structmember.h"
# include "IndexTexture.h"
2024-03-02 05:42:21 +00:00
# include <list>
2024-02-25 03:47:20 +00:00
2024-03-07 02:12:26 +00:00
enum PyObjectsEnum : int
2024-02-25 03:47:20 +00:00
{
UIFRAME = 1 ,
UICAPTION ,
UISPRITE ,
UIGRID
} ;
class UIDrawable
{
public :
2024-03-02 05:42:21 +00:00
//UIDrawable* parent;
2024-02-25 03:47:20 +00:00
void render ( ) ;
virtual void render ( sf : : Vector2f ) = 0 ;
//virtual sf::Rect<int> aabb(); // not sure I care about this yet
//virtual sf::Vector2i position();
2024-03-07 02:12:26 +00:00
//bool handle_event(/* ??? click, scroll, keystroke*/);
//std::string action;
2024-02-25 03:47:20 +00:00
virtual PyObjectsEnum derived_type ( ) = 0 ;
2024-03-07 02:12:26 +00:00
// Mouse input handling - callable object, methods to find event's destination
PyObject * click_callable ;
virtual UIDrawable * click_at ( sf : : Vector2f point ) = 0 ;
void click_register ( PyObject * ) ;
void click_unregister ( ) ;
UIDrawable ( ) ;
2024-02-25 03:47:20 +00:00
} ;
//Python object types & forward declarations
/*
typedef struct {
PyObject_HEAD
sf : : Color color ;
} PyColorObject ;
*/
typedef struct {
PyObject_HEAD
std : : shared_ptr < sf : : Color > data ;
} PyColorObject ;
class UIFrame : public UIDrawable
{
public :
UIFrame ( float , float , float , float ) ;
UIFrame ( ) ;
~ UIFrame ( ) ;
sf : : RectangleShape box ;
2024-03-07 02:12:26 +00:00
// todone: why does UIFrame have x,y,w,h AND a box? Which one should be used for bounds checks? (floats removed)
2024-02-25 03:47:20 +00:00
//Simulate RectangleShape
2024-03-07 02:12:26 +00:00
//float x, y, w, h,
float outline ;
2024-02-25 03:47:20 +00:00
std : : shared_ptr < std : : vector < std : : shared_ptr < UIDrawable > > > children ;
void render ( sf : : Vector2f ) override final ;
void move ( sf : : Vector2f ) ;
PyObjectsEnum derived_type ( ) override final ; // { return PyObjectsEnum::UIFrame; };
2024-03-07 02:12:26 +00:00
virtual UIDrawable * click_at ( sf : : Vector2f point ) override final ;
2024-02-25 03:47:20 +00:00
/*
sf : : Color fillColor ( ) ; // getter
void fillColor ( sf : : Color c ) ; // C++ setter
void fillColor ( PyColorObject * pyColor ) ; // Python setter
sf : : Color outlineColor ( ) ; // getter
void outlineColor ( sf : : Color c ) ; // C++ setter
void outlineColor ( PyColorObject * pyColor ) ; // Python setter
*/
private :
//std::shared_ptr<sf::Color> fillColor, outlineColor;
/*
sf : : Color * _fillColor , * _outlineColor ;
PyColorObject * pyFillColor , * pyOutlineColor ;
*/
} ;
class UICaption : public UIDrawable
{
public :
sf : : Text text ;
void render ( sf : : Vector2f ) override final ;
PyObjectsEnum derived_type ( ) override final ; // { return PyObjectsEnum::UICaption; };
2024-03-07 02:12:26 +00:00
virtual UIDrawable * click_at ( sf : : Vector2f point ) override final ;
2024-02-25 03:47:20 +00:00
} ;
class UISprite : public UIDrawable
{
public :
UISprite ( ) ;
UISprite ( IndexTexture * , int , float , float , float ) ;
UISprite ( IndexTexture * , int , sf : : Vector2f , float ) ;
void update ( ) ;
void render ( sf : : Vector2f ) override final ;
2024-03-07 02:12:26 +00:00
virtual UIDrawable * click_at ( sf : : Vector2f point ) override final ;
2024-03-05 04:12:08 +00:00
// 7DRL hack - TODO apply RenderTexture concept to all UIDrawables (via `sf::RenderTarget`)
void render ( sf : : Vector2f , sf : : RenderTexture & ) ;
2024-02-25 03:47:20 +00:00
int /*texture_index,*/ sprite_index ;
IndexTexture * itex ;
//float x, y, scale;
sf : : Sprite sprite ;
void setPosition ( float , float ) ;
void setPosition ( sf : : Vector2f ) ;
void setScale ( float ) ;
PyObjectsEnum derived_type ( ) override final ; // { return PyObjectsEnum::UISprite; };
} ;
2024-03-02 05:42:21 +00:00
// UIGridPoint - revised grid data for each point
class UIGridPoint
{
public :
sf : : Color color , color_overlay ;
bool walkable , transparent ;
int tilesprite , tile_overlay , uisprite ;
UIGridPoint ( ) ;
} ;
// UIGridPointState - entity-specific info for each cell
class UIGridPointState
{
public :
bool visible , discovered ;
} ;
class UIGrid ;
2024-03-05 04:12:08 +00:00
// TODO: make UIEntity a drawable(?) Maybe just rely on UISprite/UIGrid to
// somehow properly render the thing? Poorly designed interface
class UIEntity //: public UIDrawable
2024-03-02 05:42:21 +00:00
{
public :
//PyObject* self;
std : : shared_ptr < UIGrid > grid ;
std : : vector < UIGridPointState > gridstate ;
UISprite sprite ;
2024-03-05 04:12:08 +00:00
sf : : Vector2f position ; //(x,y) in grid coordinates; float for animation
void render ( sf : : Vector2f ) ; //override final;
2024-03-06 03:37:50 +00:00
UIEntity ( ) ;
UIEntity ( UIGrid & ) ;
2024-03-02 05:42:21 +00:00
} ;
class UIGrid : public UIDrawable
{
public :
UIGrid ( ) ;
UIGrid ( int , int , IndexTexture * , float , float , float , float ) ;
UIGrid ( int , int , IndexTexture * , sf : : Vector2f , sf : : Vector2f ) ;
void update ( ) ;
void render ( sf : : Vector2f ) override final ;
UIGridPoint & at ( int , int ) ;
PyObjectsEnum derived_type ( ) override final ;
void setSprite ( int ) ;
2024-03-07 02:12:26 +00:00
virtual UIDrawable * click_at ( sf : : Vector2f point ) override final ;
2024-03-02 05:42:21 +00:00
int grid_x , grid_y ;
//int grid_size; // grid sizes are implied by IndexTexture now
sf : : RectangleShape box ;
float center_x , center_y , zoom ;
IndexTexture * itex ;
sf : : Sprite sprite , output ;
sf : : RenderTexture renderTexture ;
std : : vector < UIGridPoint > points ;
2024-03-05 04:12:08 +00:00
std : : shared_ptr < std : : list < std : : shared_ptr < UIEntity > > > entities ;
2024-03-02 05:42:21 +00:00
} ;
2024-02-25 03:47:20 +00:00
/*
template < typename T >
struct CPythonSharedObject {
PyObject_HEAD
std : : shared_ptr < T > data ;
} ;
typedef CPythonSharedObject < UIFrame > PyUIFrameObject ;
*/
typedef struct {
PyObject_HEAD
std : : shared_ptr < UIFrame > data ;
} PyUIFrameObject ;
typedef struct {
PyObject_HEAD
std : : shared_ptr < UICaption > data ;
PyObject * font ;
} PyUICaptionObject ;
typedef struct {
PyObject_HEAD
std : : shared_ptr < UISprite > data ;
PyObject * texture ;
} PyUISpriteObject ;
2024-03-05 12:42:49 +00:00
typedef struct {
PyObject_HEAD
std : : shared_ptr < std : : vector < std : : shared_ptr < UIDrawable > > > data ;
} PyUICollectionObject ;
2024-03-05 04:12:08 +00:00
typedef struct {
PyObject_HEAD
2024-03-06 03:37:50 +00:00
UIGridPoint * data ;
std : : shared_ptr < UIGrid > grid ;
2024-03-05 04:12:08 +00:00
} PyUIGridPointObject ;
typedef struct {
PyObject_HEAD
2024-03-06 03:37:50 +00:00
UIGridPointState * data ;
std : : shared_ptr < UIGrid > grid ;
std : : shared_ptr < UIEntity > entity ;
2024-03-05 04:12:08 +00:00
} PyUIGridPointStateObject ;
typedef struct {
PyObject_HEAD
std : : shared_ptr < UIEntity > data ;
2024-03-06 03:37:50 +00:00
PyObject * texture ;
2024-03-05 04:12:08 +00:00
} PyUIEntityObject ;
typedef struct {
PyObject_HEAD
std : : shared_ptr < UIGrid > data ;
PyObject * texture ;
} PyUIGridObject ;
2024-02-25 03:47:20 +00:00
namespace mcrfpydef {
//PyObject* py_instance(std::shared_ptr<UIDrawable> source);
// This function segfaults on tp_alloc for an unknown reason, but works inline with mcrfpydef:: methods.
# define RET_PY_INSTANCE(target) { \
switch ( target - > derived_type ( ) ) \
{ \
case PyObjectsEnum : : UIFRAME : \
{ \
PyUIFrameObject * o = ( PyUIFrameObject * ) ( ( & PyUIFrameType ) - > tp_alloc ( & PyUIFrameType , 0 ) ) ; \
if ( o ) \
{ \
auto p = std : : static_pointer_cast < UIFrame > ( target ) ; \
o - > data = p ; \
auto utarget = o - > data ; \
} \
return ( PyObject * ) o ; \
} \
case PyObjectsEnum : : UICAPTION : \
{ \
PyUICaptionObject * o = ( PyUICaptionObject * ) ( ( & PyUICaptionType ) - > tp_alloc ( & PyUICaptionType , 0 ) ) ; \
if ( o ) \
{ \
auto p = std : : static_pointer_cast < UICaption > ( target ) ; \
o - > data = p ; \
auto utarget = o - > data ; \
} \
return ( PyObject * ) o ; \
} \
case PyObjectsEnum : : UISPRITE : \
{ \
PyUISpriteObject * o = ( PyUISpriteObject * ) ( ( & PyUISpriteType ) - > tp_alloc ( & PyUISpriteType , 0 ) ) ; \
if ( o ) \
{ \
auto p = std : : static_pointer_cast < UISprite > ( target ) ; \
o - > data = p ; \
auto utarget = o - > data ; \
} \
return ( PyObject * ) o ; \
} \
case PyObjectsEnum : : UIGRID : \
{ \
2024-03-05 12:42:49 +00:00
PyUIGridObject * o = ( PyUIGridObject * ) ( ( & PyUIGridType ) - > tp_alloc ( & PyUIGridType , 0 ) ) ; \
2024-02-25 03:47:20 +00:00
if ( o ) \
{ \
2024-03-05 12:42:49 +00:00
auto p = std : : static_pointer_cast < UIGrid > ( target ) ; \
2024-02-25 03:47:20 +00:00
o - > data = p ; \
auto utarget = o - > data ; \
} \
return ( PyObject * ) o ; \
} \
} \
}
// end macro definition
// Color Definitions
// struct, members, new, set_member, PyTypeObject
/* for reference: the structs to implement
typedef struct {
PyObject_HEAD
std : : shared_ptr < sf : : Color > data ;
} PyColorObject ;
typedef struct {
PyObject_HEAD
std : : shared_ptr < UIFrame > data ;
} PyUIFrameObject ;
typedef struct {
PyObject_HEAD
std : : shared_ptr < UICaption > data ;
} PyUICaptionObject ;
typedef struct {
PyObject_HEAD
std : : shared_ptr < UISprite > data ;
} PyUISpriteObject ;
*/
2024-03-07 02:12:26 +00:00
//
// Clickable / Callable Object Assignment
//
static PyObject * PyUIDrawable_get_click ( PyUIGridObject * self , void * closure ) {
PyObjectsEnum objtype = static_cast < PyObjectsEnum > ( reinterpret_cast < long > ( closure ) ) ; // trust me bro, it's an Enum
PyObject * ptr ;
switch ( objtype )
{
case PyObjectsEnum : : UIFRAME :
ptr = ( ( PyUIFrameObject * ) self ) - > data - > click_callable ;
break ;
case PyObjectsEnum : : UICAPTION :
ptr = ( ( PyUICaptionObject * ) self ) - > data - > click_callable ;
break ;
case PyObjectsEnum : : UISPRITE :
ptr = ( ( PyUISpriteObject * ) self ) - > data - > click_callable ;
break ;
case PyObjectsEnum : : UIGRID :
ptr = ( ( PyUIGridObject * ) self ) - > data - > click_callable ;
break ;
default :
PyErr_SetString ( PyExc_TypeError , " no idea how you did that; invalid UIDrawable derived instance for _get_click " ) ;
return NULL ;
}
if ( ptr & & ptr ! = Py_None )
return ptr ;
else
return Py_None ;
}
static int PyUIDrawable_set_click ( PyUIGridObject * self , PyObject * value , void * closure ) {
PyObjectsEnum objtype = static_cast < PyObjectsEnum > ( reinterpret_cast < long > ( closure ) ) ; // trust me bro, it's an Enum
UIDrawable * target ;
switch ( objtype )
{
case PyObjectsEnum : : UIFRAME :
target = ( ( ( PyUIFrameObject * ) self ) - > data . get ( ) ) ;
break ;
case PyObjectsEnum : : UICAPTION :
target = ( ( ( PyUICaptionObject * ) self ) - > data . get ( ) ) ;
break ;
case PyObjectsEnum : : UISPRITE :
target = ( ( ( PyUISpriteObject * ) self ) - > data . get ( ) ) ;
break ;
case PyObjectsEnum : : UIGRID :
target = ( ( ( PyUIGridObject * ) self ) - > data . get ( ) ) ;
break ;
default :
PyErr_SetString ( PyExc_TypeError , " no idea how you did that; invalid UIDrawable derived instance for _set_click " ) ;
return - 1 ;
}
if ( value = = Py_None )
{
target - > click_unregister ( ) ;
} else {
target - > click_register ( value ) ;
}
return 0 ;
}
// End Clickability implementation
2024-02-25 03:47:20 +00:00
/*
*
* Begin PyFontType defs
*
*/
typedef struct {
PyObject_HEAD
std : : shared_ptr < sf : : Font > data ;
} PyFontObject ;
static int PyFont_init ( PyFontObject * self , PyObject * args , PyObject * kwds )
{
//std::cout << "Init called\n";
static const char * keywords [ ] = { " filename " , nullptr } ;
char * filename ;
if ( ! PyArg_ParseTupleAndKeywords ( args , kwds , " s " , const_cast < char * * > ( keywords ) , & filename ) )
{
return - 1 ;
}
self - > data - > loadFromFile ( ( std : : string ) filename ) ;
return 0 ;
}
static PyTypeObject PyFontType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.Font " ,
. tp_basicsize = sizeof ( PyFontObject ) ,
. tp_itemsize = 0 ,
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " SFML Font Object " ) ,
. tp_init = ( initproc ) PyFont_init ,
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
PyFontObject * self = ( PyFontObject * ) type - > tp_alloc ( type , 0 ) ;
self - > data = std : : make_shared < sf : : Font > ( ) ;
return ( PyObject * ) self ;
}
} ;
/*
*
* End PyFontType defs
*
*/
static PyObject * PyColor_get_member ( PyColorObject * self , void * closure )
{
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( member_ptr = = 0 )
return PyLong_FromLong ( self - > data - > r ) ;
else if ( member_ptr = = 1 )
return PyLong_FromLong ( self - > data - > g ) ;
else if ( member_ptr = = 2 )
return PyLong_FromLong ( self - > data - > b ) ;
else if ( member_ptr = = 3 )
return PyLong_FromLong ( self - > data - > a ) ;
else
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return nullptr ;
}
}
static int PyColor_set_member ( PyColorObject * self , PyObject * value , void * closure )
{
if ( PyLong_Check ( value ) )
{
long int_val = PyLong_AsLong ( value ) ;
if ( int_val < 0 )
int_val = 0 ;
else if ( int_val > 255 )
int_val = 255 ;
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( member_ptr = = 0 )
self - > data - > r = static_cast < sf : : Uint8 > ( int_val ) ;
else if ( member_ptr = = 1 )
self - > data - > g = static_cast < sf : : Uint8 > ( int_val ) ;
else if ( member_ptr = = 2 )
self - > data - > b = static_cast < sf : : Uint8 > ( int_val ) ;
else if ( member_ptr = = 3 )
self - > data - > a = static_cast < sf : : Uint8 > ( int_val ) ;
}
else
{
PyErr_SetString ( PyExc_TypeError , " Value must be an integer. " ) ;
return - 1 ;
}
return 0 ;
}
static PyGetSetDef PyColor_getsetters [ ] = {
{ " r " , ( getter ) PyColor_get_member , ( setter ) PyColor_set_member , " Red component " , ( void * ) 0 } ,
{ " g " , ( getter ) PyColor_get_member , ( setter ) PyColor_set_member , " Green component " , ( void * ) 1 } ,
{ " b " , ( getter ) PyColor_get_member , ( setter ) PyColor_set_member , " Blue component " , ( void * ) 2 } ,
{ " a " , ( getter ) PyColor_get_member , ( setter ) PyColor_set_member , " Alpha component " , ( void * ) 3 } ,
{ NULL }
} ;
static PyTypeObject PyColorType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.Color " ,
. tp_basicsize = sizeof ( PyColorObject ) ,
. tp_itemsize = 0 ,
. tp_dealloc = ( destructor ) [ ] ( PyObject * self )
{
PyColorObject * obj = ( PyColorObject * ) self ;
obj - > data . reset ( ) ;
Py_TYPE ( self ) - > tp_free ( self ) ;
} ,
//.tp_repr = (reprfunc)PyUIFrame_repr,
//.tp_hash = NULL,
//.tp_iter
//.tp_iternext
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " SFML Color object (RGBA) " ) ,
//.tp_methods = PyUIFrame_methods,
//.tp_members = PyColor_members,
. tp_getset = PyColor_getsetters ,
//.tp_base = NULL,
//.tp_init = (initproc)PyUIFrame_init,
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
PyColorObject * self = ( PyColorObject * ) type - > tp_alloc ( type , 0 ) ;
if ( self ) self - > data = std : : make_shared < sf : : Color > ( ) ;
return ( PyObject * ) self ;
}
} ;
/*
*
* Begin template generation for PyUICaptionType
*
*/
static PyObject * PyUICaption_get_float_member ( PyUICaptionObject * self , void * closure )
{
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( member_ptr = = 0 )
return PyFloat_FromDouble ( self - > data - > text . getPosition ( ) . x ) ;
else if ( member_ptr = = 1 )
return PyFloat_FromDouble ( self - > data - > text . getPosition ( ) . y ) ;
else if ( member_ptr = = 4 )
return PyFloat_FromDouble ( self - > data - > text . getOutlineThickness ( ) ) ;
else if ( member_ptr = = 5 )
return PyLong_FromLong ( self - > data - > text . getCharacterSize ( ) ) ;
else
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return nullptr ;
}
}
static int PyUICaption_set_float_member ( PyUICaptionObject * self , PyObject * value , void * closure )
{
float val ;
auto member_ptr = reinterpret_cast < long > ( 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 an integer. " ) ;
return - 1 ;
}
if ( member_ptr = = 0 ) //x
self - > data - > text . setPosition ( val , self - > data - > text . getPosition ( ) . y ) ;
else if ( member_ptr = = 1 ) //y
self - > data - > text . setPosition ( self - > data - > text . getPosition ( ) . x , val ) ;
else if ( member_ptr = = 4 ) //outline
self - > data - > text . setOutlineThickness ( val ) ;
else if ( member_ptr = = 5 ) // character size
self - > data - > text . setCharacterSize ( val ) ;
return 0 ;
}
static PyObject * PyUICaption_get_color_member ( PyUICaptionObject * self , void * closure )
{
// validate closure (should be impossible to be wrong, but it's thorough)
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( member_ptr ! = 0 & & member_ptr ! = 1 )
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return nullptr ;
}
2024-03-05 04:12:08 +00:00
// TODO: manually calling tp_alloc to create a PyColorObject seems like an antipattern
2024-02-25 03:47:20 +00:00
PyTypeObject * colorType = & PyColorType ;
PyObject * pyColor = colorType - > tp_alloc ( colorType , 0 ) ;
if ( pyColor = = NULL )
{
std : : cout < < " failure to allocate mcrfpy.Color / PyColorType " < < std : : endl ;
return NULL ;
}
PyColorObject * pyColorObj = reinterpret_cast < PyColorObject * > ( pyColor ) ;
// fetch correct member data
sf : : Color color ;
if ( member_ptr = = 0 )
{
color = self - > data - > text . getFillColor ( ) ;
//return Py_BuildValue("(iii)", color.r, color.g, color.b);
}
else if ( member_ptr = = 1 )
{
color = self - > data - > text . getOutlineColor ( ) ;
//return Py_BuildValue("(iii)", color.r, color.g, color.b);
}
// initialize new mcrfpy.Color instance
pyColorObj - > data = std : : make_shared < sf : : Color > ( color ) ;
return pyColor ;
}
static int PyUICaption_set_color_member ( PyUICaptionObject * self , PyObject * value , void * closure )
{
auto member_ptr = reinterpret_cast < long > ( closure ) ;
2024-03-05 04:12:08 +00:00
//TODO: this logic of (PyColor instance OR tuple -> sf::color) should be encapsulated for reuse
2024-02-25 03:47:20 +00:00
int r , g , b , a ;
if ( PyObject_IsInstance ( value , ( PyObject * ) & PyColorType ) )
{
// get value from mcrfpy.Color instance
PyColorObject * color = reinterpret_cast < PyColorObject * > ( value ) ;
r = color - > data - > r ;
g = color - > data - > g ;
b = color - > data - > b ;
a = color - > data - > a ;
}
else if ( ! PyTuple_Check ( value ) | | PyTuple_Size ( value ) < 3 | | PyTuple_Size ( value ) > 4 )
{
// reject non-Color, non-tuple value
PyErr_SetString ( PyExc_TypeError , " Value must be a tuple of 3 or 4 integers or an mcrfpy.Color object. " ) ;
return - 1 ;
}
else // get value from tuples
{
r = PyLong_AsLong ( PyTuple_GetItem ( value , 0 ) ) ;
g = PyLong_AsLong ( PyTuple_GetItem ( value , 1 ) ) ;
b = PyLong_AsLong ( PyTuple_GetItem ( value , 2 ) ) ;
a = 255 ;
if ( PyTuple_Size ( value ) = = 4 )
{
a = PyLong_AsLong ( PyTuple_GetItem ( value , 3 ) ) ;
}
}
if ( r < 0 | | r > 255 | | g < 0 | | g > 255 | | b < 0 | | b > 255 | | a < 0 | | a > 255 )
{
PyErr_SetString ( PyExc_ValueError , " Color values must be between 0 and 255. " ) ;
return - 1 ;
}
if ( member_ptr = = 0 )
{
self - > data - > text . setFillColor ( sf : : Color ( r , g , b , a ) ) ;
}
else if ( member_ptr = = 1 )
{
self - > data - > text . setOutlineColor ( sf : : Color ( r , g , b , a ) ) ;
}
else
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return - 1 ;
}
return 0 ;
}
static PyObject * PyUICaption_get_text ( PyUICaptionObject * self , void * closure )
{
return PyUnicode_FromString ( " Test String, Please Ignore " ) ;
}
static int PyUICaption_set_text ( PyUICaptionObject * self , PyObject * value , void * closure )
{
// asdf
return 0 ;
}
static PyGetSetDef PyUICaption_getsetters [ ] = {
{ " x " , ( getter ) PyUICaption_get_float_member , ( setter ) PyUICaption_set_float_member , " X coordinate of top-left corner " , ( void * ) 0 } ,
{ " y " , ( getter ) PyUICaption_get_float_member , ( setter ) PyUICaption_set_float_member , " Y coordinate of top-left corner " , ( void * ) 1 } ,
//{"w", (getter)PyUIFrame_get_float_member, (setter)PyUIFrame_set_float_member, "width of the rectangle", (void*)2},
//{"h", (getter)PyUIFrame_get_float_member, (setter)PyUIFrame_set_float_member, "height of the rectangle", (void*)3},
{ " outline " , ( getter ) PyUICaption_get_float_member , ( setter ) PyUICaption_set_float_member , " Thickness of the border " , ( void * ) 4 } ,
{ " fill_color " , ( getter ) PyUICaption_get_color_member , ( setter ) PyUICaption_set_color_member , " Fill color of the text " , ( void * ) 0 } ,
{ " outline_color " , ( getter ) PyUICaption_get_color_member , ( setter ) PyUICaption_set_color_member , " Outline color of the text " , ( void * ) 1 } ,
//{"children", (getter)PyUIFrame_get_children, NULL, "UICollection of objects on top of this one", NULL},
{ " text " , ( getter ) PyUICaption_get_text , ( setter ) PyUICaption_set_text , " The text displayed " , NULL } ,
{ " size " , ( getter ) PyUICaption_get_float_member , ( setter ) PyUICaption_set_float_member , " Text size (integer) in points " , ( void * ) 5 } ,
2024-03-07 02:12:26 +00:00
{ " click " , ( getter ) PyUIDrawable_get_click , ( setter ) PyUIDrawable_set_click , " Object called with (x, y, button) when clicked " , ( void * ) PyObjectsEnum : : UICAPTION } ,
2024-02-25 03:47:20 +00:00
{ NULL }
} ;
static PyObject * PyUICaption_repr ( PyUICaptionObject * self )
{
std : : ostringstream ss ;
if ( ! self - > data ) ss < < " <Frame (invalid internal object)> " ;
else {
auto text = self - > data - > text ;
auto fc = text . getFillColor ( ) ;
auto oc = text . getOutlineColor ( ) ;
ss < < " <Caption (x= " < < text . getPosition ( ) . x < < " , y= " < < text . getPosition ( ) . y < < " , " < <
" text=' " < < ( std : : string ) text . getString ( ) < < " ', " < <
" outline= " < < text . 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 < < " ), " < <
" )> " ;
}
std : : string repr_str = ss . str ( ) ;
return PyUnicode_DecodeUTF8 ( repr_str . c_str ( ) , repr_str . size ( ) , " replace " ) ;
}
static int PyUICaption_init ( PyUICaptionObject * self , PyObject * args , PyObject * kwds )
{
//std::cout << "Init called\n";
static const char * keywords [ ] = { " x " , " y " , " text " , " font " , " fill_color " , " outline_color " , nullptr } ;
float x = 0.0f , y = 0.0f ;
char * text ;
PyObject * font , fill_color , outline_color ;
if ( ! PyArg_ParseTupleAndKeywords ( args , kwds , " |ffzOOO " ,
const_cast < char * * > ( keywords ) , & x , & y , & text , & font , & fill_color , & outline_color ) )
{
return - 1 ;
}
// check types for font, fill_color, outline_color
//
// Set Font
//
if ( font ! = NULL & & ! PyObject_IsInstance ( font , ( PyObject * ) & PyFontType ) ) {
PyErr_SetString ( PyExc_TypeError , " font must be a mcrfpy.Font instance " ) ;
return - 1 ;
} else if ( font ! = NULL )
{
auto font_obj = ( PyFontObject * ) font ;
self - > data - > text . setFont ( * font_obj - > data ) ;
self - > font = font ;
Py_INCREF ( font ) ;
} else
{
// default font
//self->data->text.setFont(Resources::game->getFont());
}
//
// Set Color
//
self - > data - > text . setPosition ( sf : : Vector2f ( x , y ) ) ;
self - > data - > text . setString ( ( std : : string ) text ) ;
self - > data - > text . setFillColor ( sf : : Color ( 0 , 0 , 0 , 255 ) ) ;
self - > data - > text . setOutlineColor ( sf : : Color ( 128 , 128 , 128 , 255 ) ) ;
return 0 ;
}
static PyTypeObject PyUICaptionType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.Caption " ,
. tp_basicsize = sizeof ( PyUICaptionObject ) ,
. tp_itemsize = 0 ,
. tp_dealloc = ( destructor ) [ ] ( PyObject * self )
{
PyUICaptionObject * obj = ( PyUICaptionObject * ) self ;
// release reference to font object
if ( obj - > font ) Py_DECREF ( obj - > font ) ;
obj - > data . reset ( ) ;
Py_TYPE ( self ) - > tp_free ( self ) ;
} ,
. tp_repr = ( reprfunc ) PyUICaption_repr ,
//.tp_hash = NULL,
//.tp_iter
//.tp_iternext
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " docstring " ) ,
//.tp_methods = PyUIFrame_methods,
//.tp_members = PyUIFrame_members,
. tp_getset = PyUICaption_getsetters ,
//.tp_base = NULL,
. tp_init = ( initproc ) PyUICaption_init ,
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
PyUICaptionObject * self = ( PyUICaptionObject * ) type - > tp_alloc ( type , 0 ) ;
if ( self ) self - > data = std : : make_shared < UICaption > ( ) ;
return ( PyObject * ) self ;
}
} ;
/*
*
* End PyUICaptionType generation
*
*/
/*
*
* Begin template generation for PyUIFrameType
*
*/
static PyObject * PyUIFrame_get_float_member ( PyUIFrameObject * self , void * closure )
{
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( member_ptr = = 0 )
return PyFloat_FromDouble ( self - > data - > box . getPosition ( ) . x ) ;
else if ( member_ptr = = 1 )
return PyFloat_FromDouble ( self - > data - > box . getPosition ( ) . y ) ;
else if ( member_ptr = = 2 )
return PyFloat_FromDouble ( self - > data - > box . getSize ( ) . x ) ;
else if ( member_ptr = = 3 )
return PyFloat_FromDouble ( self - > data - > box . getSize ( ) . y ) ;
else if ( member_ptr = = 4 )
return PyFloat_FromDouble ( self - > data - > box . getOutlineThickness ( ) ) ;
else
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return nullptr ;
}
}
static int PyUIFrame_set_float_member ( PyUIFrameObject * self , PyObject * value , void * closure )
{
float val ;
auto member_ptr = reinterpret_cast < long > ( 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 an integer. " ) ;
return - 1 ;
}
if ( member_ptr = = 0 ) //x
self - > data - > box . setPosition ( val , self - > data - > box . getPosition ( ) . y ) ;
else if ( member_ptr = = 1 ) //y
self - > data - > box . setPosition ( self - > data - > box . getPosition ( ) . x , val ) ;
else if ( member_ptr = = 2 ) //w
self - > data - > box . setSize ( sf : : Vector2f ( val , self - > data - > box . getSize ( ) . y ) ) ;
else if ( member_ptr = = 3 ) //h
self - > data - > box . setSize ( sf : : Vector2f ( self - > data - > box . getSize ( ) . x , val ) ) ;
else if ( member_ptr = = 4 ) //outline
self - > data - > box . setOutlineThickness ( val ) ;
return 0 ;
}
static PyObject * PyUIFrame_get_color_member ( PyUIFrameObject * self , void * closure )
{
// validate closure (should be impossible to be wrong, but it's thorough)
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( member_ptr ! = 0 & & member_ptr ! = 1 )
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return nullptr ;
}
PyTypeObject * colorType = & PyColorType ;
PyObject * pyColor = colorType - > tp_alloc ( colorType , 0 ) ;
if ( pyColor = = NULL )
{
std : : cout < < " failure to allocate mcrfpy.Color / PyColorType " < < std : : endl ;
return NULL ;
}
PyColorObject * pyColorObj = reinterpret_cast < PyColorObject * > ( pyColor ) ;
// fetch correct member data
sf : : Color color ;
if ( member_ptr = = 0 )
{
color = self - > data - > box . getFillColor ( ) ;
//return Py_BuildValue("(iii)", color.r, color.g, color.b);
}
else if ( member_ptr = = 1 )
{
color = self - > data - > box . getOutlineColor ( ) ;
//return Py_BuildValue("(iii)", color.r, color.g, color.b);
}
// initialize new mcrfpy.Color instance
pyColorObj - > data = std : : make_shared < sf : : Color > ( color ) ;
return pyColor ;
}
static int PyUIFrame_set_color_member ( PyUIFrameObject * self , PyObject * value , void * closure )
{
2024-03-05 04:12:08 +00:00
//TODO: this logic of (PyColor instance OR tuple -> sf::color) should be encapsulated for reuse
2024-02-25 03:47:20 +00:00
auto member_ptr = reinterpret_cast < long > ( closure ) ;
int r , g , b , a ;
if ( PyObject_IsInstance ( value , ( PyObject * ) & PyColorType ) )
{
// get value from mcrfpy.Color instance
PyColorObject * color = reinterpret_cast < PyColorObject * > ( value ) ;
r = color - > data - > r ;
g = color - > data - > g ;
b = color - > data - > b ;
a = color - > data - > a ;
std : : cout < < " using color: " < < r < < " " < < g < < " " < < b < < " " < < a < < std : : endl ;
}
else if ( ! PyTuple_Check ( value ) | | PyTuple_Size ( value ) < 3 | | PyTuple_Size ( value ) > 4 )
{
// reject non-Color, non-tuple value
PyErr_SetString ( PyExc_TypeError , " Value must be a tuple of 3 or 4 integers or an mcrfpy.Color object. " ) ;
return - 1 ;
}
else // get value from tuples
{
r = PyLong_AsLong ( PyTuple_GetItem ( value , 0 ) ) ;
g = PyLong_AsLong ( PyTuple_GetItem ( value , 1 ) ) ;
b = PyLong_AsLong ( PyTuple_GetItem ( value , 2 ) ) ;
a = 255 ;
if ( PyTuple_Size ( value ) = = 4 )
{
a = PyLong_AsLong ( PyTuple_GetItem ( value , 3 ) ) ;
}
}
if ( r < 0 | | r > 255 | | g < 0 | | g > 255 | | b < 0 | | b > 255 | | a < 0 | | a > 255 )
{
PyErr_SetString ( PyExc_ValueError , " Color values must be between 0 and 255. " ) ;
return - 1 ;
}
if ( member_ptr = = 0 )
{
self - > data - > box . setFillColor ( sf : : Color ( r , g , b , a ) ) ;
}
else if ( member_ptr = = 1 )
{
self - > data - > box . setOutlineColor ( sf : : Color ( r , g , b , a ) ) ;
}
else
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return - 1 ;
}
return 0 ;
}
static PyObject * PyUIFrame_get_children ( PyUIFrameObject * , void * ) ;
// implementation after the PyUICollectionType definition
static PyGetSetDef PyUIFrame_getsetters [ ] = {
{ " x " , ( getter ) PyUIFrame_get_float_member , ( setter ) PyUIFrame_set_float_member , " X coordinate of top-left corner " , ( void * ) 0 } ,
{ " y " , ( getter ) PyUIFrame_get_float_member , ( setter ) PyUIFrame_set_float_member , " Y coordinate of top-left corner " , ( void * ) 1 } ,
{ " w " , ( getter ) PyUIFrame_get_float_member , ( setter ) PyUIFrame_set_float_member , " width of the rectangle " , ( void * ) 2 } ,
{ " h " , ( getter ) PyUIFrame_get_float_member , ( setter ) PyUIFrame_set_float_member , " height of the rectangle " , ( void * ) 3 } ,
{ " outline " , ( getter ) PyUIFrame_get_float_member , ( setter ) PyUIFrame_set_float_member , " Thickness of the border " , ( void * ) 4 } ,
{ " fill_color " , ( getter ) PyUIFrame_get_color_member , ( setter ) PyUIFrame_set_color_member , " Fill color of the rectangle " , ( void * ) 0 } ,
{ " outline_color " , ( getter ) PyUIFrame_get_color_member , ( setter ) PyUIFrame_set_color_member , " Outline color of the rectangle " , ( void * ) 1 } ,
{ " children " , ( getter ) PyUIFrame_get_children , NULL , " UICollection of objects on top of this one " , NULL } ,
2024-03-07 02:12:26 +00:00
{ " click " , ( getter ) PyUIDrawable_get_click , ( setter ) PyUIDrawable_set_click , " Object called with (x, y, button) when clicked " , ( void * ) PyObjectsEnum : : UIFRAME } ,
2024-02-25 03:47:20 +00:00
{ NULL }
} ;
static PyObject * PyUIFrame_repr ( PyUIFrameObject * self )
{
std : : ostringstream ss ;
if ( ! self - > data ) ss < < " <Frame (invalid internal object)> " ;
else {
auto box = self - > data - > box ;
auto fc = box . getFillColor ( ) ;
auto oc = box . getOutlineColor ( ) ;
ss < < " <Frame (x= " < < box . getPosition ( ) . x < < " , y= " < < box . getPosition ( ) . y < < " , x= " < <
box . getSize ( ) . x < < " , w= " < < box . getSize ( ) . y < < " , " < <
" 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 objects " < <
" )> " ;
}
std : : string repr_str = ss . str ( ) ;
return PyUnicode_DecodeUTF8 ( repr_str . c_str ( ) , repr_str . size ( ) , " replace " ) ;
}
static int PyUIFrame_init ( PyUIFrameObject * self , PyObject * args , PyObject * kwds )
{
//std::cout << "Init called\n";
static const char * keywords [ ] = { " x " , " y " , nullptr } ;
float x = 0.0f , y = 0.0f ;
if ( ! PyArg_ParseTupleAndKeywords ( args , kwds , " |ff " , const_cast < char * * > ( keywords ) , & x , & y ) )
{
return - 1 ;
}
//self->data->x = x;
//self->data->y = y;
self - > data - > box . setFillColor ( sf : : Color ( 0 , 0 , 0 , 255 ) ) ;
self - > data - > box . setOutlineColor ( sf : : Color ( 128 , 128 , 128 , 255 ) ) ;
return 0 ;
}
static PyTypeObject PyUIFrameType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.Frame " ,
. tp_basicsize = sizeof ( PyUIFrameObject ) ,
. tp_itemsize = 0 ,
. tp_dealloc = ( destructor ) [ ] ( PyObject * self )
{
PyUIFrameObject * obj = ( PyUIFrameObject * ) self ;
obj - > data . reset ( ) ;
Py_TYPE ( self ) - > tp_free ( self ) ;
} ,
. tp_repr = ( reprfunc ) PyUIFrame_repr ,
//.tp_hash = NULL,
//.tp_iter
//.tp_iternext
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " docstring " ) ,
//.tp_methods = PyUIFrame_methods,
//.tp_members = PyUIFrame_members,
. tp_getset = PyUIFrame_getsetters ,
//.tp_base = NULL,
. tp_init = ( initproc ) PyUIFrame_init ,
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
PyUIFrameObject * self = ( PyUIFrameObject * ) type - > tp_alloc ( type , 0 ) ;
if ( self ) self - > data = std : : make_shared < UIFrame > ( ) ;
return ( PyObject * ) self ;
}
} ;
/*
*
* End auto - generated PyUIFrameType generation
*
*/
/*
*
* Begin Python Class Instantiator ( iterator helper )
*
*/
/* // definition can't go in the header file
PyObject * py_instance ( UIDrawable * obj )
{
}
*/
/*
*
* End Python Class Instantitator ( iterator helper )
*
*/
/*
*
* Begin PyTextureType defs
*
*/
typedef struct {
PyObject_HEAD
std : : shared_ptr < IndexTexture > 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 < char * * > ( 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 < IndexTexture > ( t , grid_size , grid_width , grid_height ) ;
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
*
*/
static PyObject * PyUISprite_get_float_member ( PyUISpriteObject * self , void * closure )
{
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( member_ptr = = 0 )
return PyFloat_FromDouble ( self - > data - > sprite . getPosition ( ) . x ) ;
else if ( member_ptr = = 1 )
return PyFloat_FromDouble ( self - > data - > sprite . getPosition ( ) . y ) ;
else if ( member_ptr = = 2 )
return PyFloat_FromDouble ( self - > data - > sprite . getScale ( ) . x ) ; // scale X and Y are identical, presently
else
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return nullptr ;
}
}
static int PyUISprite_set_float_member ( PyUISpriteObject * self , PyObject * value , void * closure )
{
float val ;
auto member_ptr = reinterpret_cast < long > ( 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 - > sprite . setPosition ( val , self - > data - > sprite . getPosition ( ) . y ) ;
else if ( member_ptr = = 1 ) //y
self - > data - > sprite . setPosition ( self - > data - > sprite . getPosition ( ) . x , val ) ;
else if ( member_ptr = = 2 ) // scale
self - > data - > sprite . setScale ( sf : : Vector2f ( val , val ) ) ;
return 0 ;
}
static PyObject * PyUISprite_get_int_member ( PyUISpriteObject * self , void * closure )
{
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( true ) { }
else
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return nullptr ;
}
return PyLong_FromDouble ( self - > data - > sprite_index ) ;
}
static int PyUISprite_set_int_member ( PyUISpriteObject * self , PyObject * value , void * closure )
{
int val ;
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( PyLong_Check ( value ) )
{
val = PyLong_AsLong ( value ) ;
}
else
{
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 ) ) ;
return 0 ;
}
static PyObject * PyUISprite_get_texture ( PyUISpriteObject * self , void * closure )
{
return NULL ;
}
static int PyUISprite_set_texture ( PyUISpriteObject * self , PyObject * value , void * closure )
{
return - 1 ;
}
static PyGetSetDef PyUISprite_getsetters [ ] = {
{ " x " , ( getter ) PyUISprite_get_float_member , ( setter ) PyUISprite_set_float_member , " X coordinate of top-left corner " , ( void * ) 0 } ,
{ " y " , ( getter ) PyUISprite_get_float_member , ( setter ) PyUISprite_set_float_member , " Y coordinate of top-left corner " , ( void * ) 1 } ,
{ " scale " , ( getter ) PyUISprite_get_float_member , ( setter ) PyUISprite_set_float_member , " Size factor " , ( void * ) 2 } ,
{ " sprite_number " , ( getter ) PyUISprite_get_int_member , ( setter ) PyUISprite_set_int_member , " Which sprite on the texture is shown " , NULL } ,
{ " texture " , ( getter ) PyUISprite_get_texture , ( setter ) PyUISprite_set_texture , " Texture object " , NULL } ,
2024-03-07 02:12:26 +00:00
{ " click " , ( getter ) PyUIDrawable_get_click , ( setter ) PyUIDrawable_set_click , " Object called with (x, y, button) when clicked " , ( void * ) PyObjectsEnum : : UISPRITE } ,
2024-02-25 03:47:20 +00:00
{ NULL }
} ;
static PyObject * PyUISprite_repr ( PyUISpriteObject * self )
{
std : : ostringstream ss ;
if ( ! self - > data ) ss < < " <Sprite (invalid internal object)> " ;
else {
auto sprite = self - > data - > sprite ;
ss < < " <Sprite (x= " < < sprite . getPosition ( ) . x < < " , y= " < < sprite . getPosition ( ) . y < < " , " < <
" scale= " < < sprite . getScale ( ) . x < < " , " < <
" sprite_number= " < < self - > data - > sprite_index < < " )> " ;
}
std : : string repr_str = ss . str ( ) ;
return PyUnicode_DecodeUTF8 ( repr_str . c_str ( ) , repr_str . size ( ) , " replace " ) ;
}
static int PyUISprite_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 ;
PyObject * texture ;
if ( ! PyArg_ParseTupleAndKeywords ( args , kwds , " |ffOif " ,
const_cast < char * * > ( keywords ) , & x , & y , & texture , & sprite_index , & scale ) )
{
return - 1 ;
}
// check types for texture
//
// Set Texture
//
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 )
{
self - > texture = texture ;
Py_INCREF ( texture ) ;
} else
{
// default tex?
}
auto pytexture = ( PyTextureObject * ) texture ;
self - > data = std : : make_shared < UISprite > ( pytexture - > data . get ( ) , sprite_index , sf : : Vector2f ( x , y ) , scale ) ;
self - > data - > sprite . setPosition ( sf : : Vector2f ( x , y ) ) ;
return 0 ;
}
static PyTypeObject PyUISpriteType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.Sprite " ,
. tp_basicsize = sizeof ( PyUISpriteObject ) ,
. tp_itemsize = 0 ,
. tp_dealloc = ( destructor ) [ ] ( PyObject * self )
{
PyUISpriteObject * obj = ( PyUISpriteObject * ) self ;
// release reference to font object
if ( obj - > texture ) Py_DECREF ( obj - > texture ) ;
obj - > data . reset ( ) ;
Py_TYPE ( self ) - > tp_free ( self ) ;
} ,
. tp_repr = ( reprfunc ) PyUISprite_repr ,
//.tp_hash = NULL,
//.tp_iter
//.tp_iternext
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " docstring " ) ,
//.tp_methods = PyUIFrame_methods,
//.tp_members = PyUIFrame_members,
. tp_getset = PyUISprite_getsetters ,
//.tp_base = NULL,
. tp_init = ( initproc ) PyUISprite_init ,
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
PyUISpriteObject * self = ( PyUISpriteObject * ) type - > tp_alloc ( type , 0 ) ;
//if (self) self->data = std::make_shared<UICaption>();
return ( PyObject * ) self ;
}
} ;
/*
*
* End template for PyUISpriteType
*
*/
2024-03-05 12:42:49 +00:00
2024-02-25 03:47:20 +00:00
/*
*
2024-03-05 12:42:49 +00:00
* PyUIGridPoint defs
2024-02-25 03:47:20 +00:00
*
*/
2024-03-05 12:42:49 +00:00
// TODO: question: are sfColor_to_PyObject and PyObject_to_sfColor duplicitive? How does UIFrame get/set colors?
// Utility function to convert sf::Color to PyObject*
static PyObject * sfColor_to_PyObject ( sf : : Color color ) {
return Py_BuildValue ( " (iiii) " , color.r, color.g, color.b, color.a) ;
}
// Utility function to convert PyObject* to sf::Color
static sf : : Color PyObject_to_sfColor ( PyObject * obj ) {
int r , g , b , a = 255 ; // Default alpha to fully opaque if not specified
if ( ! PyArg_ParseTuple ( obj , " iii|i " , & r , & g , & b , & a ) ) {
return sf : : Color ( ) ; // Return default color on parse error
2024-02-25 03:47:20 +00:00
}
2024-03-05 12:42:49 +00:00
return sf : : Color ( r , g , b , a ) ;
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
static PyObject * PyUIGridPoint_get_color ( PyUIGridPointObject * self , void * closure ) {
if ( reinterpret_cast < long > ( closure ) = = 0 ) { // color
return sfColor_to_PyObject ( self - > data - > color ) ;
} else { // color_overlay
return sfColor_to_PyObject ( self - > data - > color_overlay ) ;
}
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
static int PyUIGridPoint_set_color ( PyUIGridPointObject * self , PyObject * value , void * closure ) {
sf : : Color color = PyObject_to_sfColor ( value ) ;
if ( reinterpret_cast < long > ( closure ) = = 0 ) { // color
self - > data - > color = color ;
} else { // color_overlay
self - > data - > color_overlay = color ;
}
return 0 ;
}
static PyObject * PyUIGridPoint_get_bool_member ( PyUIGridPointObject * self , void * closure ) {
if ( reinterpret_cast < long > ( closure ) = = 0 ) { // walkable
return PyBool_FromLong ( self - > data - > walkable ) ;
} else { // transparent
return PyBool_FromLong ( self - > data - > transparent ) ;
}
}
static int PyUIGridPoint_set_bool_member ( PyUIGridPointObject * self , PyObject * value , void * closure ) {
if ( value = = Py_True ) {
if ( reinterpret_cast < long > ( closure ) = = 0 ) { // walkable
self - > data - > walkable = true ;
} else { // transparent
self - > data - > transparent = true ;
2024-02-25 03:47:20 +00:00
}
2024-03-05 12:42:49 +00:00
} else if ( value = = Py_False ) {
if ( reinterpret_cast < long > ( closure ) = = 0 ) { // walkable
self - > data - > walkable = false ;
} else { // transparent
self - > data - > transparent = false ;
2024-02-25 03:47:20 +00:00
}
2024-03-05 12:42:49 +00:00
} else {
PyErr_SetString ( PyExc_ValueError , " Expected a boolean value " ) ;
return - 1 ;
2024-02-25 03:47:20 +00:00
}
2024-03-05 12:42:49 +00:00
return 0 ;
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
static PyObject * PyUIGridPoint_get_int_member ( PyUIGridPointObject * self , void * closure ) {
switch ( reinterpret_cast < long > ( closure ) ) {
case 0 : return PyLong_FromLong ( self - > data - > tilesprite ) ;
case 1 : return PyLong_FromLong ( self - > data - > tile_overlay ) ;
case 2 : return PyLong_FromLong ( self - > data - > uisprite ) ;
default : PyErr_SetString ( PyExc_RuntimeError , " Invalid closure " ) ; return nullptr ;
}
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
static int PyUIGridPoint_set_int_member ( PyUIGridPointObject * self , PyObject * value , void * closure ) {
long val = PyLong_AsLong ( value ) ;
if ( PyErr_Occurred ( ) ) return - 1 ;
switch ( reinterpret_cast < long > ( closure ) ) {
case 0 : self - > data - > tilesprite = val ; break ;
case 1 : self - > data - > tile_overlay = val ; break ;
case 2 : self - > data - > uisprite = val ; break ;
default : PyErr_SetString ( PyExc_RuntimeError , " Invalid closure " ) ; return - 1 ;
}
return 0 ;
}
static PyGetSetDef PyUIGridPoint_getsetters [ ] = {
{ " color " , ( getter ) PyUIGridPoint_get_color , ( setter ) PyUIGridPoint_set_color , " GridPoint color " , ( void * ) 0 } ,
{ " color_overlay " , ( getter ) PyUIGridPoint_get_color , ( setter ) PyUIGridPoint_set_color , " GridPoint color overlay " , ( void * ) 1 } ,
{ " walkable " , ( getter ) PyUIGridPoint_get_bool_member , ( setter ) PyUIGridPoint_set_bool_member , " Is the GridPoint walkable " , ( void * ) 0 } ,
{ " transparent " , ( getter ) PyUIGridPoint_get_bool_member , ( setter ) PyUIGridPoint_set_bool_member , " Is the GridPoint transparent " , ( void * ) 1 } ,
{ " tilesprite " , ( getter ) PyUIGridPoint_get_int_member , ( setter ) PyUIGridPoint_set_int_member , " Tile sprite index " , ( void * ) 0 } ,
{ " tile_overlay " , ( getter ) PyUIGridPoint_get_int_member , ( setter ) PyUIGridPoint_set_int_member , " Tile overlay sprite index " , ( void * ) 1 } ,
{ " uisprite " , ( getter ) PyUIGridPoint_get_int_member , ( setter ) PyUIGridPoint_set_int_member , " UI sprite index " , ( void * ) 2 } ,
{ NULL } /* Sentinel */
} ;
static PyTypeObject PyUIGridPointType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.GridPoint " ,
. tp_basicsize = sizeof ( PyUIGridPointObject ) ,
. tp_itemsize = 0 ,
// Methods omitted for brevity
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = " UIGridPoint objects " ,
. tp_getset = PyUIGridPoint_getsetters ,
//.tp_init = (initproc)PyUIGridPoint_init, // TODO Define the init function
. tp_new = PyType_GenericNew ,
} ;
2024-02-25 03:47:20 +00:00
/*
*
2024-03-05 12:42:49 +00:00
* end PyUIGridPoint defs
2024-02-25 03:47:20 +00:00
*
*/
/*
2024-03-05 12:42:49 +00:00
*
* PyUIGridPointState defs
*
*/
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
static PyObject * PyUIGridPointState_get_bool_member ( PyUIGridPointStateObject * self , void * closure ) {
if ( reinterpret_cast < long > ( closure ) = = 0 ) { // visible
return PyBool_FromLong ( self - > data - > visible ) ;
} else { // discovered
return PyBool_FromLong ( self - > data - > discovered ) ;
}
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
static int PyUIGridPointState_set_bool_member ( PyUIGridPointStateObject * self , PyObject * value , void * closure ) {
if ( ! PyBool_Check ( value ) ) {
PyErr_SetString ( PyExc_TypeError , " Value must be a boolean " ) ;
return - 1 ;
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
int truthValue = PyObject_IsTrue ( value ) ;
if ( truthValue < 0 ) {
return - 1 ; // PyObject_IsTrue returns -1 on error
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
if ( reinterpret_cast < long > ( closure ) = = 0 ) { // visible
self - > data - > visible = truthValue ;
} else { // discovered
self - > data - > discovered = truthValue ;
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
return 0 ;
}
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
static PyGetSetDef PyUIGridPointState_getsetters [ ] = {
{ " visible " , ( getter ) PyUIGridPointState_get_bool_member , ( setter ) PyUIGridPointState_set_bool_member , " Is the GridPointState visible " , ( void * ) 0 } ,
{ " discovered " , ( getter ) PyUIGridPointState_get_bool_member , ( setter ) PyUIGridPointState_set_bool_member , " Has the GridPointState been discovered " , ( void * ) 1 } ,
{ NULL } /* Sentinel */
} ;
2024-02-25 03:47:20 +00:00
2024-03-05 12:42:49 +00:00
static PyTypeObject PyUIGridPointStateType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.GridPointState " ,
. tp_basicsize = sizeof ( PyUIGridPointStateObject ) ,
. tp_itemsize = 0 ,
// Methods omitted for brevity
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = " UIGridPointState objects " , // TODO: Add PyUIGridPointState tp_init
. tp_getset = PyUIGridPointState_getsetters ,
. tp_new = PyType_GenericNew ,
} ;
2024-03-05 04:12:08 +00:00
/*
*
* end PyUIGridPointState defs
*
*/
/*
*
* PyUIEntity defs
*
*/
// TODO: sf::Vector2f convenience functions here might benefit from a PyVectorObject much like PyColorObject
// Utility function to convert sf::Vector2f to PyObject*
static PyObject * sfVector2f_to_PyObject ( sf : : Vector2f vector ) {
return Py_BuildValue ( " (ff) " , vector.x, vector.y) ;
}
// Utility function to convert PyObject* to sf::Vector2f
static sf : : Vector2f PyObject_to_sfVector2f ( PyObject * obj ) {
float x , y ;
if ( ! PyArg_ParseTuple ( obj , " ff " , & x , & y ) ) {
return sf : : Vector2f ( ) ; // TODO / reconsider this default: Return default vector on parse error
}
return sf : : Vector2f ( x , y ) ;
}
// Utility function to convert UIGridPointState to PyObject*
static PyObject * UIGridPointState_to_PyObject ( const UIGridPointState & state ) {
PyObject * obj = PyObject_New ( PyObject , & PyUIGridPointStateType ) ;
if ( ! obj ) return PyErr_NoMemory ( ) ;
// Assuming PyUIGridPointStateObject structure has a UIGridPointState* member called 'data'
//((PyUIGridPointStateObject*)obj)->data = new UIGridPointState(state); // Copy constructor // TODO / BUGFIX - don't use new, get shared_ptr working
return obj ;
}
// Function to convert std::vector<UIGridPointState> to a Python list TODO need a PyUICollection style iterable
static PyObject * UIGridPointStateVector_to_PyList ( const std : : vector < UIGridPointState > & vec ) {
PyObject * list = PyList_New ( vec . size ( ) ) ;
if ( ! list ) return PyErr_NoMemory ( ) ;
for ( size_t i = 0 ; i < vec . size ( ) ; + + i ) {
PyObject * obj = UIGridPointState_to_PyObject ( vec [ i ] ) ;
if ( ! obj ) { // Cleanup on failure
Py_DECREF ( list ) ;
return NULL ;
}
PyList_SET_ITEM ( list , i , obj ) ; // This steals a reference to obj
}
return list ;
}
static PyObject * PyUIEntity_get_position ( PyUIEntityObject * self , void * closure ) {
return sfVector2f_to_PyObject ( self - > data - > position ) ;
}
static int PyUIEntity_set_position ( PyUIEntityObject * self , PyObject * value , void * closure ) {
self - > data - > position = PyObject_to_sfVector2f ( value ) ;
return 0 ;
}
static PyObject * PyUIEntity_get_gridstate ( PyUIEntityObject * self , void * closure ) {
// Assuming a function to convert std::vector<UIGridPointState> to PyObject* list
return UIGridPointStateVector_to_PyList ( self - > data - > gridstate ) ;
}
2024-03-06 03:37:50 +00:00
static PyObject * PyUIEntity_get_spritenumber ( PyUIEntityObject * self , void * closure ) {
return PyLong_FromDouble ( self - > data - > sprite . sprite_index ) ;
}
static int PyUIEntity_set_spritenumber ( PyUIEntityObject * self , PyObject * value , void * closure ) {
int val ;
if ( PyLong_Check ( value ) )
val = PyLong_AsLong ( value ) ;
else
{
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
return 0 ;
}
static PyObject * PyUIEntity_at ( PyUIEntityObject * self , PyObject * o )
{
int x , y ;
if ( ! PyArg_ParseTuple ( o , " ii " , & x , & y ) ) {
PyErr_SetString ( PyExc_TypeError , " UIEntity.at requires two integer arguments: (x, y) " ) ;
return NULL ;
}
if ( self - > data - > grid = = NULL ) {
PyErr_SetString ( PyExc_ValueError , " Entity cannot access surroundings because it is not associated with a grid " ) ;
return NULL ;
}
PyUIGridPointStateObject * obj = ( PyUIGridPointStateObject * ) ( ( & PyUIGridPointStateType ) - > tp_alloc ( & PyUIGridPointStateType , 0 ) ) ;
//auto target = std::static_pointer_cast<UIEntity>(target);
obj - > data = & ( self - > data - > gridstate [ y + self - > data - > grid - > grid_x * x ] ) ;
obj - > grid = self - > data - > grid ;
obj - > entity = self - > data ;
return ( PyObject * ) obj ;
}
static PyMethodDef PyUIEntity_methods [ ] = {
{ " at " , ( PyCFunction ) PyUIEntity_at , METH_O } ,
{ NULL , NULL , 0 , NULL }
} ;
2024-03-05 04:12:08 +00:00
// Define getters and setters
static PyGetSetDef PyUIEntity_getsetters [ ] = {
{ " position " , ( getter ) PyUIEntity_get_position , ( setter ) PyUIEntity_set_position , " Entity position " , NULL } ,
{ " gridstate " , ( getter ) PyUIEntity_get_gridstate , NULL , " Grid point states for the entity " , NULL } ,
2024-03-06 03:37:50 +00:00
{ " sprite_number " , ( getter ) PyUIEntity_get_spritenumber , ( setter ) PyUIEntity_set_spritenumber , " Sprite number (index) on the texture on the display " , NULL } ,
2024-03-05 04:12:08 +00:00
{ NULL } /* Sentinel */
} ;
2024-03-06 03:37:50 +00:00
static int PyUIEntity_init ( PyUIEntityObject * , PyObject * , PyObject * ) ; // forward declare
2024-03-05 04:12:08 +00:00
// Define the PyTypeObject for UIEntity
static PyTypeObject PyUIEntityType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.Entity " ,
. tp_basicsize = sizeof ( PyUIEntityObject ) ,
. tp_itemsize = 0 ,
// Methods omitted for brevity
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = " UIEntity objects " ,
2024-03-06 03:37:50 +00:00
. tp_methods = PyUIEntity_methods ,
2024-03-05 04:12:08 +00:00
. tp_getset = PyUIEntity_getsetters ,
. tp_init = ( initproc ) PyUIEntity_init ,
. tp_new = PyType_GenericNew ,
} ;
/*
*
* end PyUIEntity defs
*
*/
/*
*
* PyUIGrid defs
*
*/
static int PyUIGrid_init ( PyUIGridObject * self , PyObject * args , PyObject * kwds ) {
int grid_x , grid_y ;
PyObject * textureObj ;
float box_x , box_y , box_w , box_h ;
2024-03-05 12:42:49 +00:00
if ( ! PyArg_ParseTuple ( args , " iiOffff " , & grid_x , & grid_y , & textureObj , & box_x , & box_y , & box_w , & box_h ) ) {
return - 1 ; // If parsing fails, return an error
}
// Convert PyObject texture to IndexTexture*
// This requires the texture object to have been initialized similar to UISprite's texture handling
if ( ! PyObject_IsInstance ( textureObj , ( PyObject * ) & PyTextureType ) ) {
PyErr_SetString ( PyExc_TypeError , " texture must be a mcrfpy.Texture instance " ) ;
return - 1 ;
}
PyTextureObject * pyTexture = reinterpret_cast < PyTextureObject * > ( textureObj ) ;
// TODO (7DRL day 2, item 4.) use shared_ptr / PyTextureObject on UIGrid
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 < UIGrid > ( grid_x , grid_y , texture , box_x , box_y , box_w , box_h ) ;
return 0 ; // Success
}
static PyObject * PyUIGrid_get_grid_size ( PyUIGridObject * self , void * closure ) {
return Py_BuildValue ( " (ii) " , self->data->grid_x, self->data->grid_y) ;
}
static PyObject * PyUIGrid_get_position ( PyUIGridObject * self , void * closure ) {
auto & box = self - > data - > box ;
return Py_BuildValue ( " (ff) " , box.getPosition().x, box.getPosition().y) ;
}
static int PyUIGrid_set_position ( PyUIGridObject * self , PyObject * value , void * closure ) {
float x , y ;
if ( ! PyArg_ParseTuple ( value , " ff " , & x , & y ) ) {
PyErr_SetString ( PyExc_ValueError , " Position must be a tuple of two floats " ) ;
return - 1 ;
}
self - > data - > box . setPosition ( x , y ) ;
return 0 ;
}
static PyObject * PyUIGrid_get_size ( PyUIGridObject * self , void * closure ) {
auto & box = self - > data - > box ;
return Py_BuildValue ( " (ff) " , box.getSize().x, box.getSize().y) ;
}
static int PyUIGrid_set_size ( PyUIGridObject * self , PyObject * value , void * closure ) {
float w , h ;
if ( ! PyArg_ParseTuple ( value , " ff " , & w , & h ) ) {
PyErr_SetString ( PyExc_ValueError , " Size must be a tuple of two floats " ) ;
return - 1 ;
}
self - > data - > box . setSize ( sf : : Vector2f ( w , h ) ) ;
return 0 ;
}
2024-03-06 03:37:50 +00:00
static PyObject * PyUIGrid_get_center ( PyUIGridObject * self , void * closure ) {
return Py_BuildValue ( " (ff) " , self->data->center_x, self->data->center_y) ;
}
static int PyUIGrid_set_center ( PyUIGridObject * self , PyObject * value , void * closure ) {
float x , y ;
if ( ! PyArg_ParseTuple ( value , " ff " , & x , & y ) ) {
PyErr_SetString ( PyExc_ValueError , " Size must be a tuple of two floats " ) ;
return - 1 ;
}
self - > data - > center_x = x ;
self - > data - > center_y = y ;
return 0 ;
}
static PyObject * PyUIGrid_get_float_member ( PyUIGridObject * self , void * closure )
{
auto member_ptr = reinterpret_cast < long > ( closure ) ;
if ( member_ptr = = 0 ) // x
return PyFloat_FromDouble ( self - > data - > box . getPosition ( ) . x ) ;
else if ( member_ptr = = 1 ) // y
return PyFloat_FromDouble ( self - > data - > box . getPosition ( ) . y ) ;
else if ( member_ptr = = 2 ) // w
return PyFloat_FromDouble ( self - > data - > box . getSize ( ) . x ) ;
else if ( member_ptr = = 3 ) // h
return PyFloat_FromDouble ( self - > data - > box . getSize ( ) . y ) ;
else if ( member_ptr = = 4 ) // center_x
return PyFloat_FromDouble ( self - > data - > center_x ) ;
else if ( member_ptr = = 5 ) // center_y
return PyFloat_FromDouble ( self - > data - > center_y ) ;
else if ( member_ptr = = 6 ) // zoom
return PyFloat_FromDouble ( self - > data - > zoom ) ;
else
{
PyErr_SetString ( PyExc_AttributeError , " Invalid attribute " ) ;
return nullptr ;
}
}
static int PyUIGrid_set_float_member ( PyUIGridObject * self , PyObject * value , void * closure )
{
float val ;
auto member_ptr = reinterpret_cast < long > ( 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 - > box . setPosition ( val , self - > data - > box . getPosition ( ) . y ) ;
else if ( member_ptr = = 1 ) // y
self - > data - > box . setPosition ( self - > data - > box . getPosition ( ) . x , val ) ;
else if ( member_ptr = = 2 ) // w
self - > data - > box . setSize ( sf : : Vector2f ( val , self - > data - > box . getSize ( ) . y ) ) ;
else if ( member_ptr = = 3 ) // h
self - > data - > box . setSize ( sf : : Vector2f ( self - > data - > box . getSize ( ) . x , val ) ) ;
else if ( member_ptr = = 4 ) // center_x
self - > data - > center_x = val ;
else if ( member_ptr = = 5 ) // center_y
self - > data - > center_y = val ;
else if ( member_ptr = = 6 ) // zoom
self - > data - > zoom = val ;
return 0 ;
}
2024-03-05 12:42:49 +00:00
// TODO (7DRL Day 2, item 5.) return Texture object
/*
static PyObject * PyUIGrid_get_texture ( PyUIGridObject * self , void * closure ) {
Py_INCREF ( self - > texture ) ;
return self - > texture ;
}
*/
2024-03-06 03:37:50 +00:00
static PyObject * PyUIGrid_at ( PyUIGridObject * self , PyObject * o )
{
int x , y ;
if ( ! PyArg_ParseTuple ( o , " ii " , & x , & y ) ) {
PyErr_SetString ( PyExc_TypeError , " UIGrid.at requires two integer arguments: (x, y) " ) ;
return NULL ;
}
PyUIGridPointObject * obj = ( PyUIGridPointObject * ) ( ( & PyUIGridPointType ) - > tp_alloc ( & PyUIGridPointType , 0 ) ) ;
//auto target = std::static_pointer_cast<UIEntity>(target);
obj - > data = & ( self - > data - > points [ y + self - > data - > grid_x * x ] ) ;
obj - > grid = self - > data ;
return ( PyObject * ) obj ;
}
static PyMethodDef PyUIGrid_methods [ ] = {
{ " at " , ( PyCFunction ) PyUIGrid_at , METH_O } ,
{ NULL , NULL , 0 , NULL }
} ;
2024-03-05 12:42:49 +00:00
static PyObject * PyUIGrid_get_children ( PyUIGridObject * self , void * closure ) ; // forward declare
static PyGetSetDef PyUIGrid_getsetters [ ] = {
2024-03-06 03:37:50 +00:00
// TODO - refactor into get_vector_member with field identifier values `(void*)n`
2024-03-05 12:42:49 +00:00
{ " grid_size " , ( getter ) PyUIGrid_get_grid_size , NULL , " Grid dimensions (grid_x, grid_y) " , NULL } ,
{ " position " , ( getter ) PyUIGrid_get_position , ( setter ) PyUIGrid_set_position , " Position of the grid (x, y) " , NULL } ,
{ " size " , ( getter ) PyUIGrid_get_size , ( setter ) PyUIGrid_set_size , " Size of the grid (width, height) " , NULL } ,
2024-03-06 03:37:50 +00:00
{ " center " , ( getter ) PyUIGrid_get_center , ( setter ) PyUIGrid_set_center , " Grid coordinate at the center of the Grid's view (pan) " , NULL } ,
// TODO / BUGFIX - everything about Entity collection
2024-03-05 12:42:49 +00:00
{ " entities " , ( getter ) PyUIGrid_get_children , NULL , " EntityCollection of entities on this grid " , NULL } ,
2024-03-06 03:37:50 +00:00
{ " x " , ( getter ) PyUIGrid_get_float_member , ( setter ) PyUIGrid_set_float_member , " top-left corner X-coordinate " , ( void * ) 0 } ,
{ " y " , ( getter ) PyUIGrid_get_float_member , ( setter ) PyUIGrid_set_float_member , " top-left corner Y-coordinate " , ( void * ) 1 } ,
{ " w " , ( getter ) PyUIGrid_get_float_member , ( setter ) PyUIGrid_set_float_member , " visible widget width " , ( void * ) 2 } ,
{ " h " , ( getter ) PyUIGrid_get_float_member , ( setter ) PyUIGrid_set_float_member , " visible widget height " , ( void * ) 3 } ,
{ " center_x " , ( getter ) PyUIGrid_get_float_member , ( setter ) PyUIGrid_set_float_member , " center of the view X-coordinate " , ( void * ) 4 } ,
{ " center_y " , ( getter ) PyUIGrid_get_float_member , ( setter ) PyUIGrid_set_float_member , " center of the view Y-coordinate " , ( void * ) 5 } ,
{ " zoom " , ( getter ) PyUIGrid_get_float_member , ( setter ) PyUIGrid_set_float_member , " zoom factor for displaying the Grid " , ( void * ) 6 } ,
2024-03-07 02:12:26 +00:00
{ " click " , ( getter ) PyUIDrawable_get_click , ( setter ) PyUIDrawable_set_click , " Object called with (x, y, button) when clicked " , ( void * ) PyObjectsEnum : : UIGRID } ,
2024-03-05 12:42:49 +00:00
//{"texture", (getter)PyUIGrid_get_texture, NULL, "Texture of the grid", NULL}, //TODO 7DRL-day2-item5
{ NULL } /* Sentinel */
} ;
/* // TODO standard pointer would need deleted, but I opted for a shared pointer. tp_dealloc currently not even defined in the PyTypeObject
static void PyUIGrid_dealloc ( PyUIGridObject * self ) {
delete self - > data ; // Clean up the allocated UIGrid object
Py_TYPE ( self ) - > tp_free ( ( PyObject * ) self ) ;
}
*/
static PyTypeObject PyUIGridType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.Grid " ,
. tp_basicsize = sizeof ( PyUIGridObject ) ,
. tp_itemsize = 0 ,
//.tp_dealloc = (destructor)[](PyObject* self)
//{
// PyUIGridObject* obj = (PyUIGridObject*)self;
// obj->data.reset();
// Py_TYPE(self)->tp_free(self);
//},
//TODO - PyUIGrid REPR def:
// .tp_repr = (reprfunc)PyUIGrid_repr,
//.tp_hash = NULL,
//.tp_iter
//.tp_iternext
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " docstring " ) ,
2024-03-06 03:37:50 +00:00
. tp_methods = PyUIGrid_methods ,
2024-03-05 12:42:49 +00:00
//.tp_members = PyUIGrid_members,
. tp_getset = PyUIGrid_getsetters ,
//.tp_base = NULL,
. tp_init = ( initproc ) PyUIGrid_init ,
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
PyUIGridObject * self = ( PyUIGridObject * ) type - > tp_alloc ( type , 0 ) ;
if ( self ) self - > data = std : : make_shared < UIGrid > ( ) ;
return ( PyObject * ) self ;
}
} ;
/*
*
* end PyUIGrid defs
*
*/
2024-03-06 03:37:50 +00:00
// PyUIEntity_init defined here because it depends on the PyUIGridType (to accept grid optional keyword argument)
static int PyUIEntity_init ( PyUIEntityObject * self , PyObject * args , PyObject * kwds ) {
static const char * keywords [ ] = { " x " , " y " , " texture " , " sprite_index " , " grid " , nullptr } ;
float x = 0.0f , y = 0.0f , scale = 1.0f ;
int sprite_index = - 1 ;
PyObject * texture = NULL ;
PyObject * grid = NULL ;
if ( ! PyArg_ParseTupleAndKeywords ( args , kwds , " ffOi|O " ,
const_cast < char * * > ( keywords ) , & x , & y , & texture , & sprite_index , & grid ) )
{
return - 1 ;
}
// check types for texture
//
// Set Texture
//
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 )
{
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 " ) ;
return - 1 ;
}
auto pytexture = ( PyTextureObject * ) texture ;
if ( grid = = NULL )
self - > data = std : : make_shared < UIEntity > ( ) ;
else
self - > data = std : : make_shared < UIEntity > ( * ( ( 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 - > position = sf : : Vector2f ( x , y ) ;
if ( grid ! = NULL ) {
PyUIGridObject * pygrid = ( PyUIGridObject * ) grid ;
self - > data - > grid = pygrid - > data ;
// todone - on creation of Entity with Grid assignment, also append it to the entity list
pygrid - > data - > entities - > push_back ( self - > data ) ;
}
return 0 ;
}
2024-03-05 12:42:49 +00:00
/*
*
* Begin PyUIEntityCollectionIter defs
*
*/
typedef struct {
PyObject_HEAD
std : : shared_ptr < std : : list < std : : shared_ptr < UIEntity > > > data ;
int index ;
int start_size ;
} PyUIEntityCollectionIterObject ;
static int PyUIEntityCollectionIter_init ( PyUIEntityCollectionIterObject * self , PyObject * args , PyObject * kwds )
{
PyErr_SetString ( PyExc_TypeError , " UICollection cannot be instantiated: a C++ data source is required. " ) ;
return - 1 ;
}
static PyObject * PyUIEntityCollectionIter_next ( PyUIEntityCollectionIterObject * self )
{
if ( self - > data - > size ( ) ! = self - > start_size )
{
PyErr_SetString ( PyExc_RuntimeError , " collection changed size during iteration " ) ;
return NULL ;
}
if ( self - > index > self - > start_size - 1 )
{
PyErr_SetNone ( PyExc_StopIteration ) ;
return NULL ;
}
self - > index + + ;
auto vec = self - > data . get ( ) ;
if ( ! vec )
{
PyErr_SetString ( PyExc_RuntimeError , " the collection store returned a null pointer " ) ;
return NULL ;
}
// Advance list iterator since Entities are not stored in a vector (if this code even worked)
// vectors only: //auto target = (*vec)[self->index-1];
//auto l_front = (*vec).begin();
//std::advance(l_front, self->index-1);
// TODO build PyObject* of the correct UIDrawable subclass to return
//return py_instance(target);
return NULL ;
}
static PyObject * PyUIEntityCollectionIter_repr ( PyUIEntityCollectionIterObject * self )
{
std : : ostringstream ss ;
if ( ! self - > data ) ss < < " <UICollectionIter (invalid internal object)> " ;
else {
ss < < " <UICollectionIter ( " < < self - > data - > size ( ) < < " child objects, @ index " < < self - > index < < " )> " ;
}
std : : string repr_str = ss . str ( ) ;
return PyUnicode_DecodeUTF8 ( repr_str . c_str ( ) , repr_str . size ( ) , " replace " ) ;
}
static PyTypeObject PyUIEntityCollectionIterType = {
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.UICollectionIter " ,
. tp_basicsize = sizeof ( PyUIEntityCollectionIterObject ) ,
. tp_itemsize = 0 ,
. tp_dealloc = ( destructor ) [ ] ( PyObject * self )
{
PyUIEntityCollectionIterObject * obj = ( PyUIEntityCollectionIterObject * ) self ;
obj - > data . reset ( ) ;
Py_TYPE ( self ) - > tp_free ( self ) ;
} ,
. tp_repr = ( reprfunc ) PyUIEntityCollectionIter_repr ,
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " Iterator for a collection of UI objects " ) ,
. tp_iternext = ( iternextfunc ) PyUIEntityCollectionIter_next ,
//.tp_getset = PyUIEntityCollection_getset,
. tp_init = ( initproc ) PyUIEntityCollectionIter_init , // just raise an exception
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
PyErr_SetString ( PyExc_TypeError , " UICollection cannot be instantiated: a C++ data source is required. " ) ;
return NULL ;
}
} ;
/*
*
* End PyUIEntityCollectionIter defs
*
*/
/*
*
* Begin PyUIEntityCollection defs
*
*/
typedef struct {
PyObject_HEAD
std : : shared_ptr < std : : list < std : : shared_ptr < UIEntity > > > data ;
2024-03-06 03:37:50 +00:00
std : : shared_ptr < UIGrid > grid ;
2024-03-05 12:42:49 +00:00
} PyUIEntityCollectionObject ;
static Py_ssize_t PyUIEntityCollection_len ( PyUIEntityCollectionObject * self ) {
return self - > data - > size ( ) ;
}
static PyObject * PyUIEntityCollection_getitem ( PyUIEntityCollectionObject * self , Py_ssize_t index ) {
// build a Python version of item at self->data[index]
// Copy pasted::
auto vec = self - > data . get ( ) ;
if ( ! vec )
{
PyErr_SetString ( PyExc_RuntimeError , " the collection store returned a null pointer " ) ;
return NULL ;
}
while ( index < 0 ) index + = self - > data - > size ( ) ;
if ( index > self - > data - > size ( ) - 1 )
{
PyErr_SetString ( PyExc_IndexError , " EntityCollection index out of range " ) ;
return NULL ;
}
auto l_begin = ( * vec ) . begin ( ) ;
std : : advance ( l_begin , index ) ;
auto target = * l_begin ; //auto target = (*vec)[index];
//RET_PY_INSTANCE(target);
// construct and return an entity object that points directly into the UIGrid's entity vector
PyUIEntityObject * o = ( PyUIEntityObject * ) ( ( & PyUIEntityType ) - > tp_alloc ( & PyUIEntityType , 0 ) ) ;
auto p = std : : static_pointer_cast < UIEntity > ( target ) ;
o - > data = p ;
return ( PyObject * ) o ;
return NULL ;
2024-03-05 04:12:08 +00:00
}
2024-03-05 12:42:49 +00:00
static PySequenceMethods PyUIEntityCollection_sqmethods = {
. sq_length = ( lenfunc ) PyUIEntityCollection_len ,
. sq_item = ( ssizeargfunc ) PyUIEntityCollection_getitem ,
//.sq_item_by_index = PyUIEntityCollection_getitem
//.sq_slice - return a subset of the iterable
//.sq_ass_item - called when `o[x] = y` is executed (x is any object type)
//.sq_ass_slice - cool; no thanks, for now
//.sq_contains - called when `x in o` is executed
//.sq_ass_item_by_index - called when `o[x] = y` is executed (x is explictly an integer)
} ;
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static PyObject * PyUIEntityCollection_append ( PyUIEntityCollectionObject * self , PyObject * o )
{
// if not UIDrawable subclass, reject it
// self->data->push_back( c++ object inside o );
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
// this would be a great use case for .tp_base
if ( ! PyObject_IsInstance ( o , ( PyObject * ) & PyUIEntityType ) )
{
PyErr_SetString ( PyExc_TypeError , " Only Entity objects can be added to EntityCollection " ) ;
return NULL ;
}
PyUIEntityObject * entity = ( PyUIEntityObject * ) o ;
self - > data - > push_back ( entity - > data ) ;
2024-03-06 03:37:50 +00:00
entity - > data - > grid = self - > grid ;
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
Py_INCREF ( Py_None ) ;
return Py_None ;
2024-03-05 04:12:08 +00:00
}
2024-03-05 12:42:49 +00:00
static PyObject * PyUIEntityCollection_remove ( PyUIEntityCollectionObject * self , PyObject * o )
{
if ( ! PyLong_Check ( o ) )
{
PyErr_SetString ( PyExc_TypeError , " UICollection.remove requires an integer index to remove " ) ;
return NULL ;
}
long index = PyLong_AsLong ( o ) ;
if ( index > = self - > data - > size ( ) )
{
PyErr_SetString ( PyExc_ValueError , " Index out of range " ) ;
return NULL ;
}
else if ( index < 0 )
{
PyErr_SetString ( PyExc_NotImplementedError , " reverse indexing is not implemented. " ) ;
return NULL ;
}
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
// release the shared pointer at self->data[index];
//self->data->erase(self->data->begin() + index);
// (Advance list to position)
2024-03-06 03:37:50 +00:00
//auto l_front = self->data->begin();
//std::advance(l_front, index);
2024-03-05 12:42:49 +00:00
//self->data->erase(std::remove(l_front, std::next(l_front)); // TODO / BUGFIX - ???
2024-03-06 03:37:50 +00:00
self - > data - > erase ( std : : next ( self - > data - > begin ( ) , index ) ) ;
2024-03-05 12:42:49 +00:00
Py_INCREF ( Py_None ) ;
return Py_None ;
2024-03-05 04:12:08 +00:00
}
2024-03-05 12:42:49 +00:00
static PyMethodDef PyUIEntityCollection_methods [ ] = {
{ " append " , ( PyCFunction ) PyUIEntityCollection_append , METH_O } ,
//{"extend", (PyCFunction)PyUIEntityCollection_extend, METH_O}, // TODO
{ " remove " , ( PyCFunction ) PyUIEntityCollection_remove , METH_O } ,
{ NULL , NULL , 0 , NULL }
} ;
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static PyObject * PyUIEntityCollection_repr ( PyUIEntityCollectionObject * self )
{
std : : ostringstream ss ;
if ( ! self - > data ) ss < < " <UICollection (invalid internal object)> " ;
else {
ss < < " <UICollection ( " < < self - > data - > size ( ) < < " child objects)> " ;
}
std : : string repr_str = ss . str ( ) ;
return PyUnicode_DecodeUTF8 ( repr_str . c_str ( ) , repr_str . size ( ) , " replace " ) ;
}
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static int PyUIEntityCollection_init ( PyUIEntityCollectionObject * self , PyObject * args , PyObject * kwds )
{
PyErr_SetString ( PyExc_TypeError , " EntityCollection cannot be instantiated: a C++ data source is required. " ) ;
return - 1 ;
}
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static PyObject * PyUIEntityCollection_iter ( PyUIEntityCollectionObject * self )
{
PyUIEntityCollectionIterObject * iterObj ;
iterObj = ( PyUIEntityCollectionIterObject * ) PyUIEntityCollectionIterType . tp_alloc ( & PyUIEntityCollectionIterType , 0 ) ;
if ( iterObj = = NULL ) {
return NULL ; // Failed to allocate memory for the iterator object
}
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
iterObj - > data = self - > data ; // TODO / BUGFIX - mismatch between the Iter Type and Collection Type Data members
iterObj - > index = 0 ;
iterObj - > start_size = self - > data - > size ( ) ;
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
return ( PyObject * ) iterObj ;
}
static PyTypeObject PyUIEntityCollectionType = {
//PyVarObject_/HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.EntityCollection " ,
. tp_basicsize = sizeof ( PyUIEntityCollectionObject ) ,
2024-03-05 04:12:08 +00:00
. tp_itemsize = 0 ,
2024-03-05 12:42:49 +00:00
. tp_dealloc = ( destructor ) [ ] ( PyObject * self )
{
PyUIEntityCollectionObject * obj = ( PyUIEntityCollectionObject * ) self ;
obj - > data . reset ( ) ;
Py_TYPE ( self ) - > tp_free ( self ) ;
} ,
. tp_repr = ( reprfunc ) PyUIEntityCollection_repr ,
. tp_as_sequence = & PyUIEntityCollection_sqmethods ,
2024-03-05 04:12:08 +00:00
. tp_flags = Py_TPFLAGS_DEFAULT ,
2024-03-05 12:42:49 +00:00
. tp_doc = PyDoc_STR ( " Iterable, indexable collection of Entities " ) ,
. tp_iter = ( getiterfunc ) PyUIEntityCollection_iter ,
. tp_methods = PyUIEntityCollection_methods , // append, remove
//.tp_getset = PyUIEntityCollection_getset,
. tp_init = ( initproc ) PyUIEntityCollection_init , // just raise an exception
2024-03-05 04:12:08 +00:00
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
2024-03-05 12:42:49 +00:00
// Does PyUIEntityCollectionType need __new__ if it's not supposed to be instantiable by the user?
// Should I just raise an exception? Or is the uninitialized shared_ptr enough of a blocker?
PyErr_SetString ( PyExc_TypeError , " EntityCollection cannot be instantiated: a C++ data source is required. " ) ;
return NULL ;
2024-03-05 04:12:08 +00:00
}
} ;
2024-03-05 12:42:49 +00:00
// Grid's get_children def must follow the EntityCollection def
static PyObject * PyUIGrid_get_children ( PyUIGridObject * self , void * closure )
{
// create PyUICollection instance pointing to self->data->children
PyUIEntityCollectionObject * o = ( PyUIEntityCollectionObject * ) PyUIEntityCollectionType . tp_alloc ( & PyUIEntityCollectionType , 0 ) ;
2024-03-06 03:37:50 +00:00
if ( o ) {
o - > data = self - > data - > entities ; // todone. / BUGFIX - entities isn't a shared pointer on UIGrid, what to do? -- I made it a sp<list<sp<UIEntity>>>
o - > grid = self - > data ;
}
2024-03-05 12:42:49 +00:00
return ( PyObject * ) o ;
}
2024-03-05 04:12:08 +00:00
/*
*
2024-03-05 12:42:49 +00:00
* End PyUIEntityCollection defs
2024-03-05 04:12:08 +00:00
*
*/
2024-03-05 12:42:49 +00:00
/*
2024-03-05 04:12:08 +00:00
*
2024-03-05 12:42:49 +00:00
* Begin PyUICollectionIter defs
2024-03-05 04:12:08 +00:00
*
*/
typedef struct {
PyObject_HEAD
2024-03-05 12:42:49 +00:00
std : : shared_ptr < std : : vector < std : : shared_ptr < UIDrawable > > > data ;
2024-03-05 04:12:08 +00:00
int index ;
int start_size ;
2024-03-05 12:42:49 +00:00
} PyUICollectionIterObject ;
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static int PyUICollectionIter_init ( PyUICollectionIterObject * self , PyObject * args , PyObject * kwds )
2024-03-05 04:12:08 +00:00
{
PyErr_SetString ( PyExc_TypeError , " UICollection cannot be instantiated: a C++ data source is required. " ) ;
return - 1 ;
}
2024-03-05 12:42:49 +00:00
static PyObject * PyUICollectionIter_next ( PyUICollectionIterObject * self )
2024-03-05 04:12:08 +00:00
{
if ( self - > data - > size ( ) ! = self - > start_size )
{
PyErr_SetString ( PyExc_RuntimeError , " collection changed size during iteration " ) ;
return NULL ;
}
if ( self - > index > self - > start_size - 1 )
{
PyErr_SetNone ( PyExc_StopIteration ) ;
return NULL ;
}
2024-03-05 12:42:49 +00:00
self - > index + + ;
2024-03-05 04:12:08 +00:00
auto vec = self - > data . get ( ) ;
if ( ! vec )
{
PyErr_SetString ( PyExc_RuntimeError , " the collection store returned a null pointer " ) ;
return NULL ;
}
2024-03-05 12:42:49 +00:00
auto target = ( * vec ) [ self - > index - 1 ] ;
2024-03-05 04:12:08 +00:00
// TODO build PyObject* of the correct UIDrawable subclass to return
//return py_instance(target);
return NULL ;
}
2024-03-05 12:42:49 +00:00
static PyObject * PyUICollectionIter_repr ( PyUICollectionIterObject * self )
{
std : : ostringstream ss ;
if ( ! self - > data ) ss < < " <UICollectionIter (invalid internal object)> " ;
else {
ss < < " <UICollectionIter ( " < < self - > data - > size ( ) < < " child objects, @ index " < < self - > index < < " )> " ;
}
std : : string repr_str = ss . str ( ) ;
return PyUnicode_DecodeUTF8 ( repr_str . c_str ( ) , repr_str . size ( ) , " replace " ) ;
}
static PyTypeObject PyUICollectionIterType = {
2024-03-05 04:12:08 +00:00
//PyVarObject_HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.UICollectionIter " ,
2024-03-05 12:42:49 +00:00
. tp_basicsize = sizeof ( PyUICollectionIterObject ) ,
2024-03-05 04:12:08 +00:00
. tp_itemsize = 0 ,
. tp_dealloc = ( destructor ) [ ] ( PyObject * self )
{
2024-03-05 12:42:49 +00:00
PyUICollectionIterObject * obj = ( PyUICollectionIterObject * ) self ;
2024-03-05 04:12:08 +00:00
obj - > data . reset ( ) ;
Py_TYPE ( self ) - > tp_free ( self ) ;
} ,
2024-03-05 12:42:49 +00:00
. tp_repr = ( reprfunc ) PyUICollectionIter_repr ,
2024-03-05 04:12:08 +00:00
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " Iterator for a collection of UI objects " ) ,
2024-03-05 12:42:49 +00:00
. tp_iternext = ( iternextfunc ) PyUICollectionIter_next ,
//.tp_getset = PyUICollection_getset,
. tp_init = ( initproc ) PyUICollectionIter_init , // just raise an exception
2024-03-05 04:12:08 +00:00
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
PyErr_SetString ( PyExc_TypeError , " UICollection cannot be instantiated: a C++ data source is required. " ) ;
return NULL ;
}
} ;
/*
*
2024-03-05 12:42:49 +00:00
* End PyUICollectionIter defs
2024-03-05 04:12:08 +00:00
*
*/
2024-03-05 12:42:49 +00:00
/*
*
* Begin PyUICollection defs
*
*/
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static Py_ssize_t PyUICollection_len ( PyUICollectionObject * self ) {
return self - > data - > size ( ) ;
}
static PyObject * PyUICollection_getitem ( PyUICollectionObject * self , Py_ssize_t index ) {
// build a Python version of item at self->data[index]
2024-03-05 04:12:08 +00:00
// Copy pasted::
auto vec = self - > data . get ( ) ;
if ( ! vec )
{
PyErr_SetString ( PyExc_RuntimeError , " the collection store returned a null pointer " ) ;
return NULL ;
}
while ( index < 0 ) index + = self - > data - > size ( ) ;
if ( index > self - > data - > size ( ) - 1 )
{
2024-03-05 12:42:49 +00:00
PyErr_SetString ( PyExc_IndexError , " UICollection index out of range " ) ;
2024-03-05 04:12:08 +00:00
return NULL ;
}
2024-03-05 12:42:49 +00:00
auto target = ( * vec ) [ index ] ;
RET_PY_INSTANCE ( target ) ;
2024-03-05 04:12:08 +00:00
return NULL ;
2024-03-05 12:42:49 +00:00
}
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static PySequenceMethods PyUICollection_sqmethods = {
. sq_length = ( lenfunc ) PyUICollection_len ,
. sq_item = ( ssizeargfunc ) PyUICollection_getitem ,
//.sq_item_by_index = PyUICollection_getitem
//.sq_slice - return a subset of the iterable
//.sq_ass_item - called when `o[x] = y` is executed (x is any object type)
//.sq_ass_slice - cool; no thanks, for now
//.sq_contains - called when `x in o` is executed
//.sq_ass_item_by_index - called when `o[x] = y` is executed (x is explictly an integer)
} ;
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static PyObject * PyUICollection_append ( PyUICollectionObject * self , PyObject * o )
{
// if not UIDrawable subclass, reject it
// self->data->push_back( c++ object inside o );
2024-03-05 04:12:08 +00:00
// this would be a great use case for .tp_base
2024-03-05 12:42:49 +00:00
if ( ! PyObject_IsInstance ( o , ( PyObject * ) & PyUIFrameType ) & &
! PyObject_IsInstance ( o , ( PyObject * ) & PyUISpriteType ) & &
! PyObject_IsInstance ( o , ( PyObject * ) & PyUICaptionType ) & &
! PyObject_IsInstance ( o , ( PyObject * ) & PyUIGridType )
)
2024-03-05 04:12:08 +00:00
{
2024-03-05 12:42:49 +00:00
PyErr_SetString ( PyExc_TypeError , " Only Frame, Caption, Sprite, and Grid objects can be added to UICollection " ) ;
2024-03-05 04:12:08 +00:00
return NULL ;
}
2024-03-05 12:42:49 +00:00
if ( PyObject_IsInstance ( o , ( PyObject * ) & PyUIFrameType ) )
{
PyUIFrameObject * frame = ( PyUIFrameObject * ) o ;
self - > data - > push_back ( frame - > data ) ;
}
if ( PyObject_IsInstance ( o , ( PyObject * ) & PyUICaptionType ) )
{
PyUICaptionObject * caption = ( PyUICaptionObject * ) o ;
self - > data - > push_back ( caption - > data ) ;
}
if ( PyObject_IsInstance ( o , ( PyObject * ) & PyUISpriteType ) )
{
PyUISpriteObject * sprite = ( PyUISpriteObject * ) o ;
self - > data - > push_back ( sprite - > data ) ;
}
if ( PyObject_IsInstance ( o , ( PyObject * ) & PyUIGridType ) )
{
PyUIGridObject * grid = ( PyUIGridObject * ) o ;
self - > data - > push_back ( grid - > data ) ;
}
2024-03-05 04:12:08 +00:00
Py_INCREF ( Py_None ) ;
return Py_None ;
2024-03-05 12:42:49 +00:00
}
static PyObject * PyUICollection_remove ( PyUICollectionObject * self , PyObject * o )
{
if ( ! PyLong_Check ( o ) )
2024-03-05 04:12:08 +00:00
{
PyErr_SetString ( PyExc_TypeError , " UICollection.remove requires an integer index to remove " ) ;
return NULL ;
}
2024-03-05 12:42:49 +00:00
long index = PyLong_AsLong ( o ) ;
if ( index > = self - > data - > size ( ) )
2024-03-05 04:12:08 +00:00
{
PyErr_SetString ( PyExc_ValueError , " Index out of range " ) ;
return NULL ;
}
else if ( index < 0 )
{
PyErr_SetString ( PyExc_NotImplementedError , " reverse indexing is not implemented. " ) ;
return NULL ;
}
2024-03-05 12:42:49 +00:00
// release the shared pointer at self->data[index];
self - > data - > erase ( self - > data - > begin ( ) + index ) ;
2024-03-05 04:12:08 +00:00
Py_INCREF ( Py_None ) ;
return Py_None ;
2024-03-05 12:42:49 +00:00
}
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static PyMethodDef PyUICollection_methods [ ] = {
{ " append " , ( PyCFunction ) PyUICollection_append , METH_O } ,
//{"extend", (PyCFunction)PyUICollection_extend, METH_O}, // TODO
{ " remove " , ( PyCFunction ) PyUICollection_remove , METH_O } ,
{ NULL , NULL , 0 , NULL }
} ;
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static PyObject * PyUICollection_repr ( PyUICollectionObject * self )
{
std : : ostringstream ss ;
if ( ! self - > data ) ss < < " <UICollection (invalid internal object)> " ;
else {
ss < < " <UICollection ( " < < self - > data - > size ( ) < < " child objects)> " ;
}
std : : string repr_str = ss . str ( ) ;
return PyUnicode_DecodeUTF8 ( repr_str . c_str ( ) , repr_str . size ( ) , " replace " ) ;
}
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static int PyUICollection_init ( PyUICollectionObject * self , PyObject * args , PyObject * kwds )
2024-03-05 04:12:08 +00:00
{
2024-03-05 12:42:49 +00:00
PyErr_SetString ( PyExc_TypeError , " UICollection cannot be instantiated: a C++ data source is required. " ) ;
2024-03-05 04:12:08 +00:00
return - 1 ;
}
2024-03-05 12:42:49 +00:00
static PyObject * PyUICollection_iter ( PyUICollectionObject * self )
2024-03-05 04:12:08 +00:00
{
2024-03-05 12:42:49 +00:00
PyUICollectionIterObject * iterObj ;
iterObj = ( PyUICollectionIterObject * ) PyUICollectionIterType . tp_alloc ( & PyUICollectionIterType , 0 ) ;
2024-03-05 04:12:08 +00:00
if ( iterObj = = NULL ) {
return NULL ; // Failed to allocate memory for the iterator object
}
2024-03-05 12:42:49 +00:00
iterObj - > data = self - > data ;
2024-03-05 04:12:08 +00:00
iterObj - > index = 0 ;
iterObj - > start_size = self - > data - > size ( ) ;
return ( PyObject * ) iterObj ;
}
2024-03-05 12:42:49 +00:00
/*
static PyGetSetDef PyUICollection_getsetters [ ] = {
{ NULL }
2024-03-05 04:12:08 +00:00
} ;
2024-03-05 12:42:49 +00:00
*/
2024-03-05 04:12:08 +00:00
2024-03-05 12:42:49 +00:00
static PyTypeObject PyUICollectionType = {
//PyVarObject_/HEAD_INIT(NULL, 0)
. tp_name = " mcrfpy.UICollection " ,
. tp_basicsize = sizeof ( PyUICollectionObject ) ,
. tp_itemsize = 0 ,
. tp_dealloc = ( destructor ) [ ] ( PyObject * self )
{
PyUICollectionObject * obj = ( PyUICollectionObject * ) self ;
obj - > data . reset ( ) ;
Py_TYPE ( self ) - > tp_free ( self ) ;
} ,
. tp_repr = ( reprfunc ) PyUICollection_repr ,
. tp_as_sequence = & PyUICollection_sqmethods ,
. tp_flags = Py_TPFLAGS_DEFAULT ,
. tp_doc = PyDoc_STR ( " Iterable, indexable collection of UI objects " ) ,
. tp_iter = ( getiterfunc ) PyUICollection_iter ,
. tp_methods = PyUICollection_methods , // append, remove
//.tp_getset = PyUICollection_getset,
. tp_init = ( initproc ) PyUICollection_init , // just raise an exception
. tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) - > PyObject *
{
// Does PyUICollectionType need __new__ if it's not supposed to be instantiable by the user?
// Should I just raise an exception? Or is the uninitialized shared_ptr enough of a blocker?
PyErr_SetString ( PyExc_TypeError , " UICollection cannot be instantiated: a C++ data source is required. " ) ;
return NULL ;
}
} ;
/*
*
* End PyUICollection defs
*
*/
static PyObject * PyUIFrame_get_children ( PyUIFrameObject * self , void * closure )
2024-03-05 04:12:08 +00:00
{
// create PyUICollection instance pointing to self->data->children
2024-03-05 12:42:49 +00:00
PyUICollectionObject * o = ( PyUICollectionObject * ) PyUICollectionType . tp_alloc ( & PyUICollectionType , 0 ) ;
2024-03-05 04:12:08 +00:00
if ( o )
2024-03-05 12:42:49 +00:00
o - > data = self - > data - > children ;
2024-03-05 04:12:08 +00:00
return ( PyObject * ) o ;
}
2024-02-25 03:47:20 +00:00
} // namespace mcrfpydef