2024-02-24 22:47:20 -05:00
# include "McRFPy_API.h"
# include "platform.h"
# include "GameEngine.h"
# include "Grid.h"
# include "UI.h"
# include "Resources.h"
// static class members...?
std : : map < std : : string , UIMenu * > McRFPy_API : : menus ;
std : : map < std : : string , Grid * > McRFPy_API : : grids ;
std : : map < std : : string , PyObject * > McRFPy_API : : callbacks ;
std : : list < Animation * > McRFPy_API : : animations ;
std : : vector < sf : : SoundBuffer > McRFPy_API : : soundbuffers ;
sf : : Music McRFPy_API : : music ;
sf : : Sound McRFPy_API : : sfx ;
std : : string McRFPy_API : : input_mode ;
int McRFPy_API : : turn_number ;
std : : string McRFPy_API : : active_grid ;
bool McRFPy_API : : do_camfollow ;
EntityManager McRFPy_API : : entities ;
static PyMethodDef mcrfpyMethods [ ] = {
{ " createMenu " , McRFPy_API : : _createMenu , METH_VARARGS ,
" Create a new uimenu (name_str, x, y, w, h) " } ,
{ " listMenus " , McRFPy_API : : _listMenus , METH_VARARGS ,
" return a list of existing menus " } ,
{ " modMenu " , McRFPy_API : : _modMenu , METH_VARARGS ,
" call with a UIMenu object to update all fields " } ,
{ " createCaption " , McRFPy_API : : _createCaption , METH_VARARGS ,
" Create a new text caption (menu_str, text_str, fontsize, r, g, b) " } ,
{ " createButton " , McRFPy_API : : _createButton , METH_VARARGS ,
" Create a new button (menu_str, x, y, w, h, (bg r, g, b), (text r, g, b), caption, action_code) " } ,
{ " createSprite " , McRFPy_API : : _createSprite , METH_VARARGS ,
" Create a new sprite (menu_str, texture_index, sprite_index, x, y, scale) " } ,
{ " createTexture " , McRFPy_API : : _createTexture , METH_VARARGS ,
" Create a new texture (filename_str, grid_size, width, height) - grid_size is in pixels (only square sprites for now), width and height are in tiles " } ,
{ " registerPyAction " , McRFPy_API : : _registerPyAction , METH_VARARGS ,
" Register a callable Python object to correspond to an action string. (actionstr, callable) " } ,
{ " registerInputAction " , McRFPy_API : : _registerInputAction , METH_VARARGS ,
" Register a SFML input code to correspond to an action string. (input_code, actionstr) " } ,
{ " createGrid " , McRFPy_API : : _createGrid , METH_VARARGS ,
" create a new grid (title, grid_x, grid_y, grid_size, x, y, w, h). grid_x and grid_y are the width and height in squares. grid_size is the pixel w/h of sprites on the grid. x,y are the grid's screen position. w,h are the grid's screen size " } ,
{ " listGrids " , McRFPy_API : : _listGrids , METH_VARARGS ,
" return grid objects and all points " } ,
{ " modGrid " , McRFPy_API : : _modGrid , METH_VARARGS ,
" call with a Grid object to update all fields " } ,
{ " createAnimation " , McRFPy_API : : _createAnimation , METH_VARARGS ,
" Create a new animation: \n "
" createAnimation(duration:float, parent:string, target_type:string, target_id:string or int, field:string, callback:function, loop:bool, frames:list) \n "
" duration: total animation time in seconds \n "
" parent: the name of a UI menu or grid \n "
" target_type: 'caption', 'button', 'sprite', or 'entity' \n "
" target_id: integer index of the caption or button, or string ID of entity \n "
" field: what to animate. 'position', 'size', 'bgcolor', 'textcolor' or 'sprite' \n "
" callback: called when the animation completes \n "
" loop: if True, animation repeats; if False, animation is deleted \n "
" frames: if animating a sprite, list the frames. For other data types, the value will change in discrete steps at a rate of duration/len(frames). \n " } ,
/*
static PyObject * _createSoundBuffer ( PyObject * , PyObject * ) ;
static PyObject * _loadMusic ( PyObject * , PyObject * ) ;
static PyObject * _setMusicVolume ( PyObject * , PyObject * ) ;
static PyObject * _setSoundVolume ( PyObject * , PyObject * ) ;
static PyObject * _playSound ( PyObject * , PyObject * ) ;
static PyObject * _getMusicVolume ( PyObject * , PyObject * ) ;
static PyObject * _getSoundVolume ( PyObject * , PyObject * ) ;
*/
{ " createSoundBuffer " , McRFPy_API : : _createSoundBuffer , METH_VARARGS , " (filename) " } ,
{ " loadMusic " , McRFPy_API : : _loadMusic , METH_VARARGS , " (filename) " } ,
{ " setMusicVolume " , McRFPy_API : : _setMusicVolume , METH_VARARGS , " (int) " } ,
{ " setSoundVolume " , McRFPy_API : : _setSoundVolume , METH_VARARGS , " (int) " } ,
{ " playSound " , McRFPy_API : : _playSound , METH_VARARGS , " (int) " } ,
{ " getMusicVolume " , McRFPy_API : : _getMusicVolume , METH_VARARGS , " " } ,
{ " getSoundVolume " , McRFPy_API : : _getSoundVolume , METH_VARARGS , " " } ,
{ " unlockPlayerInput " , McRFPy_API : : _unlockPlayerInput , METH_VARARGS , " " } ,
{ " lockPlayerInput " , McRFPy_API : : _lockPlayerInput , METH_VARARGS , " " } ,
{ " requestGridTarget " , McRFPy_API : : _requestGridTarget , METH_VARARGS , " " } ,
{ " activeGrid " , McRFPy_API : : _activeGrid , METH_VARARGS , " " } ,
{ " setActiveGrid " , McRFPy_API : : _setActiveGrid , METH_VARARGS , " " } ,
{ " inputMode " , McRFPy_API : : _inputMode , METH_VARARGS , " " } ,
{ " turnNumber " , McRFPy_API : : _turnNumber , METH_VARARGS , " " } ,
{ " createEntity " , McRFPy_API : : _createEntity , METH_VARARGS , " " } ,
//{"listEntities", McRFPy_API::_listEntities, METH_VARARGS, ""},
{ " refreshFov " , McRFPy_API : : _refreshFov , METH_VARARGS , " " } ,
{ " camFollow " , McRFPy_API : : _camFollow , METH_VARARGS , " " } ,
{ " sceneUI " , McRFPy_API : : _sceneUI , METH_VARARGS , " sceneUI(scene) - Returns a list of UI elements " } ,
{ NULL , NULL , 0 , NULL }
} ;
static PyModuleDef mcrfpyModule = {
PyModuleDef_HEAD_INIT , " mcrfpy " , NULL , - 1 , mcrfpyMethods ,
NULL , NULL , NULL , NULL
} ;
// Module initializer fn, passed to PyImport_AppendInittab
PyObject * PyInit_mcrfpy ( )
{
PyObject * m = PyModule_Create ( & mcrfpyModule ) ;
if ( m = = NULL )
{
return NULL ;
}
// This code runs, but Python segfaults when accessing the UIFrame type.
//std::cout << "Adding UIFrame object to module\n";
PyModule_AddType ( m , & mcrfpydef : : PyColorType ) ;
PyModule_AddType ( m , & mcrfpydef : : PyFontType ) ;
PyModule_AddType ( m , & mcrfpydef : : PyUICaptionType ) ;
PyModule_AddType ( m , & mcrfpydef : : PyTextureType ) ;
PyModule_AddType ( m , & mcrfpydef : : PyUISpriteType ) ;
if ( PyModule_AddType ( m , & mcrfpydef : : PyUIFrameType ) < 0 )
{
std : : cout < < " Error adding UIFrame type to module; aborting " < < std : : endl ;
Py_DECREF ( & mcrfpydef : : PyUIFrameType ) ;
return NULL ;
}
PyModule_AddType ( m , & mcrfpydef : : PyUICollectionType ) ;
PyModule_AddType ( m , & mcrfpydef : : PyUICollectionIterType ) ;
2024-03-04 23:12:08 -05:00
PyModule_AddType ( m , & mcrfpydef : : PyUIGridPointType ) ;
PyModule_AddType ( m , & mcrfpydef : : PyUIGridPointStateType ) ;
PyModule_AddType ( m , & mcrfpydef : : PyUIEntityType ) ;
2024-03-05 22:37:50 -05:00
PyModule_AddType ( m , & mcrfpydef : : PyUIEntityCollectionIterType ) ;
PyModule_AddType ( m , & mcrfpydef : : PyUIEntityCollectionType ) ;
2024-03-04 23:12:08 -05:00
PyModule_AddType ( m , & mcrfpydef : : PyUIGridType ) ;
2024-02-24 22:47:20 -05:00
return m ;
}
// init_python - configure interpreter details here
PyStatus init_python ( const char * program_name )
{
PyStatus status ;
//**preconfig to establish locale**
PyPreConfig preconfig ;
PyPreConfig_InitIsolatedConfig ( & preconfig ) ;
preconfig . utf8_mode = 1 ;
status = Py_PreInitialize ( & preconfig ) ;
if ( PyStatus_Exception ( status ) ) {
Py_ExitStatusException ( status ) ;
}
PyConfig config ;
PyConfig_InitIsolatedConfig ( & config ) ;
config . dev_mode = 0 ;
PyConfig_SetBytesString ( & config , & config . home ,
narrow_string ( executable_path ( ) + L " /lib/Python " ) . c_str ( ) ) ;
status = PyConfig_SetBytesString ( & config , & config . program_name ,
program_name ) ;
// under Windows, the search paths are correct; under Linux, they need manual insertion
# if __PLATFORM_SET_PYTHON_SEARCH_PATHS == 1
config . module_search_paths_set = 1 ;
// search paths for python libs/modules/scripts
const wchar_t * str_arr [ ] = {
L " /scripts " ,
L " /lib/Python/lib.linux-x86_64-3.12 " ,
L " /lib/Python " ,
L " /lib/Python/Lib " ,
L " /venv/lib/python3.12/site-packages "
} ;
for ( auto s : str_arr ) {
status = PyWideStringList_Append ( & config . module_search_paths , ( executable_path ( ) + s ) . c_str ( ) ) ;
if ( PyStatus_Exception ( status ) ) {
continue ;
}
}
# endif
status = Py_InitializeFromConfig ( & config ) ;
return status ;
}
void McRFPy_API : : setSpriteTexture ( int ti )
{
int tx = ti % texture_width , ty = ti / texture_width ;
sprite . setTextureRect ( sf : : IntRect (
tx * texture_size ,
ty * texture_size ,
texture_size , texture_size ) ) ;
}
// functionality
//void McRFPy_API::
void McRFPy_API : : api_init ( ) {
// build API exposure before python initialization
PyImport_AppendInittab ( " mcrfpy " , & PyInit_mcrfpy ) ;
// use full path version of argv[0] from OS to init python
init_python ( narrow_string ( executable_filename ( ) ) . c_str ( ) ) ;
/*
// Create Python translations of types
PyTypeObject * gridpoint_pytype = new PyTypeObject ;
gridpoint_pytype - > tp_name = " GridPoint " ;
gridpoint_pytype - > tp_basicsize = sizeof ( GridPoint ) ;
gridpoint_pytype - > tp_dealloc = [ ] ( PyObject * obj ) {
delete ( ( GridPoint * ) obj ) ;
} ;
gridpoint_pytype - > tp_flags = Py_TPFLAGS_DEFAULT ;
gridpoint_pytype - > tp_doc = " GridPoint " ;
gridpoint_pytype - > tp_new = [ ] ( PyTypeObject * type , PyObject * args , PyObject * kwds ) {
return ( PyObject * ) new GridPoint ( ) ;
} ;
PyType_Ready ( gridpoint_pytype ) ;
PyModule_AddObject (
PyImport_AddModule ( " __main__ " ) , " GridPoint " , ( PyObject * ) gridpoint_pytype ) ;
*/
texture . loadFromFile ( " ./assets/kenney_tinydungeon.png " ) ;
//texture_size = 16, texture_width = 12, texture_height= 11;
//texture_sprite_count = texture_width * texture_height;
texture . setSmooth ( false ) ;
sprite . setTexture ( texture ) ;
sprite . setScale ( sf : : Vector2f ( 4.0f , 4.0f ) ) ;
setSpriteTexture ( 0 ) ;
}
void McRFPy_API : : executeScript ( std : : string filename )
{
FILE * PScriptFile = fopen ( filename . c_str ( ) , " r " ) ;
if ( PScriptFile ) {
PyRun_SimpleFile ( PScriptFile , filename . c_str ( ) ) ;
fclose ( PScriptFile ) ;
}
}
void McRFPy_API : : api_shutdown ( )
{
Py_Finalize ( ) ;
}
void McRFPy_API : : executePyString ( std : : string pycode )
{
PyRun_SimpleString ( pycode . c_str ( ) ) ;
}
void McRFPy_API : : REPL ( )
{
PyRun_InteractiveLoop ( stdin , " <stdin> " ) ;
}
void McRFPy_API : : REPL_device ( FILE * fp , const char * filename )
{
PyRun_InteractiveLoop ( fp , filename ) ;
}
PyObject * McRFPy_API : : _createMenu ( PyObject * self , PyObject * args ) {
const char * title_cstr ;
int posx , posy , sizex , sizey ;
if ( ! PyArg_ParseTuple ( args , " siiii " , & title_cstr , & posx , & posy , & sizex , & sizey ) ) return NULL ;
std : : string title = title_cstr ;
//TODO (Bug 2) check for and free existing key before overwriting ptr
menus [ title ] = createMenu ( posx , posy , sizex , sizey ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _listMenus ( PyObject * , PyObject * ) {
// todo - get the (Py) classes UIMenu, Button, Caption, Sprite
// and call BuildValue (tuples) -> their constructors
PyObject * uimodule = PyImport_AddModule ( " UIMenu " ) ; //already imported
PyObject * uimenu_type = PyObject_GetAttrString ( uimodule , " UIMenu " ) ;
PyObject * btn_type = PyObject_GetAttrString ( uimodule , " Button " ) ;
PyObject * cap_type = PyObject_GetAttrString ( uimodule , " Caption " ) ;
PyObject * spr_type = PyObject_GetAttrString ( uimodule , " Sprite " ) ;
PyObject * menulist = PyList_New ( menus . size ( ) ) ;
std : : map < std : : string , UIMenu * > : : iterator it = menus . begin ( ) ;
//for (int i = 0; i < menus.size(); i++) {
int i = 0 ;
for ( auto it = menus . begin ( ) ; it ! = menus . end ( ) ; it + + ) {
std : : string title = it - > first ;
auto menu = it - > second ;
auto p = menu - > box . getPosition ( ) ;
auto s = menu - > box . getSize ( ) ;
auto g = menu - > box . getFillColor ( ) ;
PyObject * menu_args = Py_BuildValue ( " (siiii(iii)O) " ,
title . c_str ( ) ,
( int ) p . x , ( int ) p . y , ( int ) s . x , ( int ) s . y ,
( int ) g . r , ( int ) g . g , ( int ) g . b ,
menu - > visible ? Py_True : Py_False ) ;
menu - > visible ? Py_INCREF ( Py_True ) : Py_INCREF ( Py_False ) ;
PyObject * menuobj = PyObject_CallObject ( ( PyObject * ) uimenu_type , menu_args ) ;
// Loop: Convert Button objects to Python Objects
PyObject * button_list = PyObject_GetAttrString ( menuobj , " buttons " ) ;
for ( auto & b : menu - > buttons ) {
auto bp = b . rect . getPosition ( ) ;
auto bs = b . rect . getSize ( ) ;
auto bg = b . rect . getFillColor ( ) ;
auto bf = b . caption . getFillColor ( ) ;
PyObject * btn_args = Py_BuildValue ( " (iiii(iii)(iii)ss) " ,
( int ) bp . x , ( int ) bp . y , ( int ) bs . x , ( int ) bs . y ,
( int ) bg . r , ( int ) bg . g , ( int ) bg . b ,
( int ) bf . r , ( int ) bf . g , ( int ) bf . b ,
b . caption . getString ( ) . toAnsiString ( ) . c_str ( ) ,
b . action . c_str ( ) ) ;
PyObject * buttonobj = PyObject_CallObject ( ( PyObject * ) btn_type , btn_args ) ;
PyList_Append ( button_list , buttonobj ) ;
}
// Loop: Convert Caption objects to Python Objects
PyObject * caption_list = PyObject_GetAttrString ( menuobj , " captions " ) ;
for ( auto & c : menu - > captions ) {
auto cc = c . getFillColor ( ) ;
PyObject * cap_args = Py_BuildValue ( " si(iii) " ,
c . getString ( ) . toAnsiString ( ) . c_str ( ) ,
c . getCharacterSize ( ) ,
cc . r , cc . g , cc . b ) ;
PyObject * capobj = PyObject_CallObject ( ( PyObject * ) cap_type , cap_args ) ;
PyList_Append ( caption_list , capobj ) ;
}
// Loop: Convert Sprite objects to Python Objects
PyObject * sprite_list = PyObject_GetAttrString ( menuobj , " sprites " ) ;
for ( auto & s : menu - > sprites ) {
PyObject * spr_args = Py_BuildValue ( " (iiff) " ,
s . texture_index , s . sprite_index , s . x , s . y ) ;
PyObject * sprobj = PyObject_CallObject ( ( PyObject * ) spr_type , spr_args ) ;
PyList_Append ( sprite_list , sprobj ) ;
}
PyList_SET_ITEM ( menulist , i , menuobj ) ;
i + + ; // count iterator steps
}
return menulist ;
}
PyObject * McRFPy_API : : _modMenu ( PyObject * self , PyObject * args ) {
PyObject * o ;
if ( ! PyArg_ParseTuple ( args , " O " , & o ) ) return NULL ;
std : : string title = PyUnicode_AsUTF8 ( PyObject_GetAttrString ( o , " title " ) ) ;
int x = PyLong_AsLong ( PyObject_GetAttrString ( o , " x " ) ) ;
int y = PyLong_AsLong ( PyObject_GetAttrString ( o , " y " ) ) ;
int w = PyLong_AsLong ( PyObject_GetAttrString ( o , " w " ) ) ;
int h = PyLong_AsLong ( PyObject_GetAttrString ( o , " h " ) ) ;
PyObject * bgtuple = PyObject_GetAttrString ( o , " bgcolor " ) ;
auto bgcolor = sf : : Color (
PyLong_AsLong ( PyTuple_GetItem ( bgtuple , 0 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( bgtuple , 1 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( bgtuple , 2 ) )
) ;
bool visible = PyObject_IsTrue ( PyObject_GetAttrString ( o , " visible " ) ) ;
auto menu = menus [ title ] ;
if ( menu = = NULL ) return NULL ;
menu - > box . setPosition ( sf : : Vector2f ( x , y ) ) ;
menu - > box . setSize ( sf : : Vector2f ( w , h ) ) ;
menu - > box . setFillColor ( bgcolor ) ;
menu - > visible = visible ;
// jank, or dank? iterate over .captions, .buttons, .sprites to modify them
// captions
PyObject * captionlist = PyObject_GetAttrString ( o , " captions " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(captionlist)) << std::endl;
for ( int i = 0 ; i < menu - > captions . size ( ) ; i + + ) {
PyObject * captionobj = PyList_GetItem ( captionlist , i ) ;
menu - > captions [ i ] . setString (
PyUnicode_AsUTF8 ( PyObject_GetAttrString ( captionobj , " text " ) ) ) ;
//menu->captions[i].setCharacterSize(
// PyLong_AsLong(PyObject_GetAttrString(captionobj, "textsize")));
PyObject * fgtuple = PyObject_GetAttrString ( captionobj , " color " ) ;
menu - > captions [ i ] . setFillColor (
sf : : Color (
PyLong_AsLong ( PyTuple_GetItem ( fgtuple , 0 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( fgtuple , 1 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( fgtuple , 2 ) )
) ) ;
}
// buttons
PyObject * buttonlist = PyObject_GetAttrString ( o , " buttons " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(buttonlist)) << std::endl;
for ( int i = 0 ; i < menu - > buttons . size ( ) ; i + + ) {
PyObject * buttonobj = PyList_GetItem ( buttonlist , i ) ;
menu - > buttons [ i ] . setPosition ( sf : : Vector2f (
PyLong_AsLong ( PyObject_GetAttrString ( buttonobj , " x " ) ) ,
PyLong_AsLong ( PyObject_GetAttrString ( buttonobj , " y " ) )
) ) ;
auto sizevec = sf : : Vector2f (
PyLong_AsLong ( PyObject_GetAttrString ( buttonobj , " w " ) ) ,
PyLong_AsLong ( PyObject_GetAttrString ( buttonobj , " h " ) )
) ;
menu - > buttons [ i ] . setSize ( sizevec ) ;
PyObject * btncolor = PyObject_GetAttrString ( buttonobj , " bgcolor " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(btncolor)) << std::endl;
menu - > buttons [ i ] . setBackground (
sf : : Color (
PyLong_AsLong ( PyTuple_GetItem ( btncolor , 0 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( btncolor , 1 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( btncolor , 2 ) )
) ) ;
PyObject * btxtcolor = PyObject_GetAttrString ( buttonobj , " textcolor " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(btxtcolor)) << std::endl;
menu - > buttons [ i ] . setTextColor (
sf : : Color (
PyLong_AsLong ( PyTuple_GetItem ( btxtcolor , 0 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( btxtcolor , 1 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( btxtcolor , 2 ) )
) ) ;
//std::cout << PyObject_Repr(PyObject_GetAttrString(buttonobj, "text")) << std::endl;
menu - > buttons [ i ] . caption . setString (
PyUnicode_AsUTF8 ( PyObject_GetAttrString ( buttonobj , " text " ) ) ) ;
//std::cout << PyObject_Repr(PyObject_GetAttrString(buttonobj, "actioncode")) << std::endl;
menu - > buttons [ i ] . action =
PyUnicode_AsUTF8 ( PyObject_GetAttrString ( buttonobj , " actioncode " ) ) ;
}
// sprites
PyObject * spriteslist = PyObject_GetAttrString ( o , " sprites " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(spriteslist)) << std::endl;
for ( int i = 0 ; i < menu - > sprites . size ( ) ; i + + ) {
PyObject * spriteobj = PyList_GetItem ( spriteslist , i ) ;
menu - > sprites [ i ] . texture_index =
PyLong_AsLong ( PyObject_GetAttrString ( spriteobj , " tex_index " ) ) ;
menu - > sprites [ i ] . sprite_index =
PyLong_AsLong ( PyObject_GetAttrString ( spriteobj , " sprite_index " ) ) ;
menu - > sprites [ i ] . x =
PyFloat_AsDouble ( PyObject_GetAttrString ( spriteobj , " x " ) ) ;
menu - > sprites [ i ] . y =
PyFloat_AsDouble ( PyObject_GetAttrString ( spriteobj , " y " ) ) ;
}
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _createCaption ( PyObject * self , PyObject * args ) {
const char * menukey_cstr , * text_cstr ;
int fontsize , cr , cg , cb ;
if ( ! PyArg_ParseTuple ( args , " ssi(iii) " ,
& menukey_cstr , & text_cstr ,
& fontsize , & cr , & cg , & cb ) ) return NULL ;
createCaption ( std : : string ( menukey_cstr ) , std : : string ( text_cstr ) , fontsize , sf : : Color ( cr , cg , cb ) ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _createButton ( PyObject * self , PyObject * args ) {
const char * menukey_cstr , * caption_cstr , * action_cstr ;
int x , y , w , h , bgr , bgg , bgb , fgr , fgg , fgb ;
if ( ! PyArg_ParseTuple ( args , " siiii(iii)(iii)ss " ,
& menukey_cstr , & x , & y , & w , & h ,
& bgr , & bgg , & bgb , & fgr , & fgg , & fgb ,
& caption_cstr , & action_cstr
) ) return NULL ;
createButton ( std : : string ( menukey_cstr ) , x , y , w , h , sf : : Color ( bgr , bgg , bgb ) , sf : : Color ( fgr , fgg , fgb ) , std : : string ( caption_cstr ) , std : : string ( action_cstr ) ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _createTexture ( PyObject * self , PyObject * args ) {
const char * fn_cstr ;
int gs , gw , gh ;
if ( ! PyArg_ParseTuple ( args , " siii " , & fn_cstr , & gs , & gw , & gh ) ) return NULL ;
createTexture ( std : : string ( fn_cstr ) , gs , gw , gh ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _listTextures ( PyObject * , PyObject * ) {
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _createSprite ( PyObject * self , PyObject * args ) {
const char * menu_cstr ;
int ti , si ;
float x , y ;
float s ;
if ( ! PyArg_ParseTuple ( args , " siifff " , & menu_cstr , & ti , & si , & x , & y , & s ) ) return NULL ;
//std::cout << "Creating uisprite " << ti << " " << si << " " << x << " " << y << " " << s << " " << std::endl;
createSprite ( std : : string ( menu_cstr ) , ti , si , x , y , s ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
UIMenu * McRFPy_API : : createMenu ( int posx , int posy , int sizex , int sizey ) {
auto m = new UIMenu ( game - > getFont ( ) ) ;
m - > box . setPosition ( sf : : Vector2f ( posx , posy ) ) ;
m - > box . setSize ( sf : : Vector2f ( sizex , sizey ) ) ;
return m ;
}
void McRFPy_API : : createCaption ( std : : string menukey , std : : string text , int fontsize , sf : : Color textcolor ) {
auto menu = menus [ menukey ] ;
menu - > add_caption ( text . c_str ( ) , fontsize , textcolor ) ;
}
void McRFPy_API : : createButton ( std : : string menukey , int x , int y , int w , int h , sf : : Color bgcolor , sf : : Color textcolor , std : : string caption , std : : string action ) {
auto menu = menus [ menukey ] ;
auto b = Button ( x , y , w , h , bgcolor , textcolor , caption . c_str ( ) , game - > getFont ( ) , action . c_str ( ) ) ;
menu - > add_button ( b ) ;
}
void McRFPy_API : : createSprite ( std : : string menukey , int ti , int si , float x , float y , float scale ) {
auto menu = menus [ menukey ] ;
auto s = IndexSprite ( ti , si , x , y , scale ) ;
menu - > add_sprite ( s ) ;
//std::cout << "indexsprite just created has values x,y " << s.x << ", " << s.y << std::endl;
}
int McRFPy_API : : createTexture ( std : : string filename , int grid_size , int grid_width , int grid_height ) {
sf : : Texture t ;
t . loadFromFile ( filename . c_str ( ) ) ;
t . setSmooth ( false ) ;
auto indextex = IndexTexture ( t , grid_size , grid_width , grid_height ) ;
game - > textures . push_back ( indextex ) ;
return game - > textures . size ( ) - 1 ;
}
// python connection
PyObject * McRFPy_API : : _registerPyAction ( PyObject * self , PyObject * args )
{
PyObject * callable ;
const char * actionstr ;
if ( ! PyArg_ParseTuple ( args , " sO " , & actionstr , & callable ) ) return NULL ;
//TODO: if the string already exists in the callbacks map,
// decrease our reference count so it can potentially be garbage collected
callbacks [ std : : string ( actionstr ) ] = callable ;
Py_INCREF ( callable ) ;
// return None correctly
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _registerInputAction ( PyObject * self , PyObject * args )
{
int action_code ;
const char * actionstr ;
if ( ! PyArg_ParseTuple ( args , " iz " , & action_code , & actionstr ) ) return NULL ;
bool success ;
if ( actionstr = = NULL ) { // Action provided is None, i.e. unregister
std : : cout < < " Unregistering \n " ;
success = game - > currentScene ( ) - > unregisterActionInjected ( action_code , std : : string ( actionstr ) + " _py " ) ;
} else {
std : : cout < < " Registering " < < actionstr < < " _py to " < < action_code < < " \n " ;
success = game - > currentScene ( ) - > registerActionInjected ( action_code , std : : string ( actionstr ) + " _py " ) ;
}
success ? Py_INCREF ( Py_True ) : Py_INCREF ( Py_False ) ;
return success ? Py_True : Py_False ;
}
void McRFPy_API : : doAction ( std : : string actionstr ) {
// hard coded actions that require no registration
//std::cout << "Calling Python Action: " << actionstr;
if ( ! actionstr . compare ( " startrepl " ) ) return McRFPy_API : : REPL ( ) ;
if ( callbacks . find ( actionstr ) = = callbacks . end ( ) )
{
//std::cout << " (not found)" << std::endl;
return ;
}
//std::cout << " (" << PyUnicode_AsUTF8(PyObject_Repr(callbacks[actionstr])) << ")" << std::endl;
PyObject_Call ( callbacks [ actionstr ] , PyTuple_New ( 0 ) , NULL ) ;
}
PyObject * McRFPy_API : : _createGrid ( PyObject * self , PyObject * args ) {
const char * title_cstr ;
int gx , gy , gs , x , y , w , h ;
if ( ! PyArg_ParseTuple ( args , " siiiiiii " , & title_cstr , & gx , & gy , & gs , & x , & y , & w , & h ) ) return NULL ;
std : : string title = title_cstr ;
//TODO - (Bug 2) check for key existing, and free if overwriting
grids [ title ] = new Grid ( gx , gy , gs , x , y , w , h ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _listGrids ( PyObject * , PyObject * ) {
PyObject * gridmodule = PyImport_AddModule ( " Grid " ) ; //already imported
PyObject * grid_type = PyObject_GetAttrString ( gridmodule , " Grid " ) ;
PyObject * gridpoint_type = PyObject_GetAttrString ( gridmodule , " GridPoint " ) ;
PyObject * entity_type = PyObject_GetAttrString ( gridmodule , " Entity " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(gridmodule)) << std::endl;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(grid_type)) << std::endl;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(gridpoint_type)) << std::endl;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(entity_type)) << std::endl;
PyObject * gridlist = PyList_New ( grids . size ( ) ) ;
std : : map < std : : string , Grid * > : : iterator it = grids . begin ( ) ;
int i = 0 ;
for ( auto it = grids . begin ( ) ; it ! = grids . end ( ) ; it + + ) {
std : : string title = it - > first ;
auto grid = it - > second ;
auto p = grid - > box . getPosition ( ) ;
auto s = grid - > box . getSize ( ) ;
PyObject * grid_args = Py_BuildValue ( " (siiiiiiiO) " ,
title . c_str ( ) ,
( int ) grid - > grid_x , ( int ) grid - > grid_y , ( int ) grid - > grid_size ,
( int ) p . x , ( int ) p . y , ( int ) s . x , ( int ) s . y ,
grid - > visible ? Py_True : Py_False ) ;
grid - > visible ? Py_INCREF ( Py_True ) : Py_INCREF ( Py_False ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(grid_args)) << std::endl;
PyObject * gridobj = PyObject_CallObject ( ( PyObject * ) grid_type , grid_args ) ;
//std::cout << (long)gridobj << std::flush <<std::endl;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(gridobj)) << std::endl;
// Loop: Convert GridPoint objects to Python Objects
PyObject * gridp_list = PyObject_GetAttrString ( gridobj , " points " ) ;
for ( auto & p : grid - > points ) {
PyObject * gridp_args = Py_BuildValue ( " ((iii)OiOOO(iii)ii) " ,
( int ) p . color . r , ( int ) p . color . g , ( int ) p . color . b ,
p . walkable ? Py_True : Py_False ,
p . tilesprite ,
p . transparent ? Py_True : Py_False ,
p . visible ? Py_True : Py_False ,
p . discovered ? Py_True : Py_False ,
( int ) p . color_overlay . r , ( int ) p . color_overlay . g , ( int ) p . color_overlay . b ,
p . tile_overlay ,
p . uisprite ) ;
p . walkable ? Py_INCREF ( Py_True ) : Py_INCREF ( Py_False ) ;
p . transparent ? Py_INCREF ( Py_True ) : Py_INCREF ( Py_False ) ;
p . visible ? Py_INCREF ( Py_True ) : Py_INCREF ( Py_False ) ;
p . discovered ? Py_INCREF ( Py_True ) : Py_INCREF ( Py_False ) ;
PyObject * gridpobj = PyObject_CallObject ( ( PyObject * ) gridpoint_type , gridp_args ) ;
PyList_Append ( gridp_list , gridpobj ) ;
}
PyObject * ent_list = PyObject_GetAttrString ( gridobj , " entities " ) ;
for ( auto e : grid - > entities ) {
//def __init__(self, parent, tex_index, sprite_index, x, y, visible=True):
PyObject * ent_args = Py_BuildValue ( " siiiiO " ,
title . c_str ( ) ,
e - > cGrid - > indexsprite . texture_index ,
e - > cGrid - > indexsprite . sprite_index ,
e - > cGrid - > x ,
e - > cGrid - > y ,
e - > cGrid - > visible ? Py_True : Py_False ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(ent_args)) << std::endl;
e - > cGrid - > visible ? Py_INCREF ( Py_True ) : Py_INCREF ( Py_False ) ;
PyObject * entobj = PyObject_CallObject ( ( PyObject * ) entity_type , ent_args ) ;
PyList_Append ( ent_list , entobj ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(ent_list)) << std::endl;
}
PyList_SET_ITEM ( gridlist , i , gridobj ) ;
i + + ; // count iterator steps
}
return gridlist ;
}
PyObject * McRFPy_API : : _modGrid ( PyObject * self , PyObject * args ) {
PyObject * o ;
PyObject * bool_is_entityonly = Py_False ;
if ( ! PyArg_ParseTuple ( args , " O|O " , & o , & bool_is_entityonly ) ) return NULL ;
//std::cout << "EntOnly Flag: " << PyUnicode_AsUTF8(PyObject_Repr(bool_is_entityonly)) << std::endl;
std : : string title = PyUnicode_AsUTF8 ( PyObject_GetAttrString ( o , " title " ) ) ;
int grid_x = PyLong_AsLong ( PyObject_GetAttrString ( o , " grid_x " ) ) ;
int grid_y = PyLong_AsLong ( PyObject_GetAttrString ( o , " grid_y " ) ) ;
int grid_size = PyLong_AsLong ( PyObject_GetAttrString ( o , " grid_size " ) ) ;
int x = PyLong_AsLong ( PyObject_GetAttrString ( o , " x " ) ) ;
int y = PyLong_AsLong ( PyObject_GetAttrString ( o , " y " ) ) ;
int w = PyLong_AsLong ( PyObject_GetAttrString ( o , " w " ) ) ;
int h = PyLong_AsLong ( PyObject_GetAttrString ( o , " h " ) ) ;
bool visible = PyObject_IsTrue ( PyObject_GetAttrString ( o , " visible " ) ) ;
auto grid = grids [ title ] ;
if ( grid = = NULL ) return NULL ;
grid - > box . setPosition ( sf : : Vector2f ( x , y ) ) ;
grid - > box . setSize ( sf : : Vector2f ( w , h ) ) ;
grid - > visible = visible ;
//iterate over gridpoints
if ( ! PyObject_IsTrue ( bool_is_entityonly ) ) {
PyObject * gpointlist = PyObject_GetAttrString ( o , " points " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(gpointlist)) << std::endl;
for ( int i = 0 ; i < grid - > points . size ( ) ; i + + ) {
PyObject * gpointobj = PyList_GetItem ( gpointlist , i ) ;
PyObject * colortuple = PyObject_GetAttrString ( gpointobj , " color " ) ;
grid - > points [ i ] . color =
sf : : Color (
PyLong_AsLong ( PyTuple_GetItem ( colortuple , 0 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( colortuple , 1 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( colortuple , 2 ) )
) ;
grid - > points [ i ] . walkable = PyObject_IsTrue ( PyObject_GetAttrString ( gpointobj , " walkable " ) ) ;
grid - > points [ i ] . tilesprite = PyLong_AsLong ( PyObject_GetAttrString ( gpointobj , " tilesprite " ) ) ;
grid - > points [ i ] . transparent = PyObject_IsTrue ( PyObject_GetAttrString ( gpointobj , " transparent " ) ) ;
grid - > points [ i ] . visible = PyObject_IsTrue ( PyObject_GetAttrString ( gpointobj , " visible " ) ) ;
grid - > points [ i ] . discovered = PyObject_IsTrue ( PyObject_GetAttrString ( gpointobj , " discovered " ) ) ;
PyObject * overlaycolortuple = PyObject_GetAttrString ( gpointobj , " color_overlay " ) ;
grid - > points [ i ] . color_overlay =
sf : : Color (
PyLong_AsLong ( PyTuple_GetItem ( overlaycolortuple , 0 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( overlaycolortuple , 1 ) ) ,
PyLong_AsLong ( PyTuple_GetItem ( overlaycolortuple , 2 ) )
) ;
grid - > points [ i ] . tile_overlay = PyLong_AsLong ( PyObject_GetAttrString ( gpointobj , " tile_overlay " ) ) ;
grid - > points [ i ] . uisprite = PyLong_AsLong ( PyObject_GetAttrString ( gpointobj , " uisprite " ) ) ;
}
// update grid pathfinding & visibility
grid - > refreshTCODmap ( ) ;
for ( auto e : McRFPy_API : : entities . getEntities ( " player " ) ) {
grid - > refreshTCODsight ( e - > cGrid - > x , e - > cGrid - > y ) ;
}
}
PyObject * entlist = PyObject_GetAttrString ( o , " entities " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(entlist)) << std::endl;
for ( int i = 0 ; i < grid - > entities . size ( ) ; i + + ) {
PyObject * entobj = PyList_GetItem ( entlist , i ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(entobj)) << std::endl;
grid - > entities [ i ] - > cGrid - > x = PyLong_AsLong ( PyObject_GetAttrString ( entobj , " x " ) ) ;
grid - > entities [ i ] - > cGrid - > y = PyLong_AsLong ( PyObject_GetAttrString ( entobj , " y " ) ) ;
grid - > entities [ i ] - > cGrid - > indexsprite . texture_index = PyLong_AsLong ( PyObject_GetAttrString ( entobj , " tex_index " ) ) ;
grid - > entities [ i ] - > cGrid - > indexsprite . sprite_index = PyLong_AsLong ( PyObject_GetAttrString ( entobj , " sprite_index " ) ) ;
}
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _refreshFov ( PyObject * self , PyObject * args ) {
for ( auto e : McRFPy_API : : entities . getEntities ( " player " ) ) {
e - > cGrid - > grid - > refreshTCODsight ( e - > cGrid - > x , e - > cGrid - > y ) ;
}
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * _test_createAnimation ( PyObject * self , PyObject * args ) {
//LerpAnimation<T>::LerpAnimation(float _d, T _ev, T* _t, std::function<void()> _cb, std::function<void(T)> _w, bool _l)
std : : string menu_key = " demobox1 " ;
McRFPy_API : : animations . push_back (
new LerpAnimation < sf : : Vector2f > (
3.0 ,
sf : : Vector2f ( 100 , 100 ) ,
McRFPy_API : : menus [ menu_key ] - > box . getPosition ( ) ,
[ ] ( ) { McRFPy_API : : executePyString ( " print('animation callback') " ) ; } ,
[ = ] ( sf : : Vector2f v ) {
//std::cout << "write lambda!" << std::endl;
McRFPy_API : : menus [ menu_key ] - > box . setPosition ( v ) ;
//std::cout << "Position set to" << McRFPy_API::menus[menu_key]->box.getPosition().x
//<< ", " << McRFPy_API::menus[menu_key]->box.getPosition().y << std::endl;
} ,
false )
) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
# define CEQ(A, B) (std::string(A).compare(B) == 0)
PyObject * McRFPy_API : : _createAnimation ( PyObject * self , PyObject * args ) {
//std::cout << "Creating animation called..." << std::endl;
float duration ;
const char * parent ;
const char * target_type ;
PyObject * target_id_obj ;
const char * field ;
PyObject * callback ;
PyObject * loop_obj ;
PyObject * values_obj ;
PyObject * evdata ; // for decoding values_obj
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(args)) << std::endl;
if ( ! PyArg_ParseTuple ( args , " fssOsOOO " , & duration , & parent , & target_type , & target_id_obj , & field , & callback , & loop_obj , & values_obj ) ) { return NULL ; }
bool loop = PyObject_IsTrue ( loop_obj ) ;
int target_id = PyLong_AsLong ( target_id_obj ) ;
Py_INCREF ( callback ) ;
/*
std : : cout < < " Animation fields received: " < <
" \n duration: " < < duration < <
" \n parent: " < < parent < <
" \n target type: " < < target_type < <
" \n target id: " < < PyUnicode_AsUTF8 ( PyObject_Repr ( target_id_obj ) ) < <
" \n field: " < < field < <
" \n callback: " < < PyUnicode_AsUTF8 ( PyObject_Repr ( callback ) ) < <
" \n loop: " < < loop < <
" \n values: " < < PyUnicode_AsUTF8 ( PyObject_Repr ( values_obj ) ) < < std : : endl ;
*/
/* Jank alert:
* The following block is meant to raise an exception when index is missing from object animations that require one ,
* but accept the target_id_obj error ( and accept None as an index ) for menus / grids .
* Instead , I get a " latent " exception , not properly raised , when the index is None .
* That not - really - raised exception causes other scripts to silently fail to execute
* until I go into the REPL and run any code , and get a bizarre , botched traceback .
* So , Grid / Menu can just take an index of 0 in the scripts until this is dejankified
*/
if ( ! CEQ ( target_type , " menu " ) & & ! CEQ ( target_type , " grid " ) & & target_id = = - 1 ) {
PyErr_SetObject ( PyExc_TypeError , target_id_obj ) ;
PyErr_SetString ( PyExc_TypeError , " target_id (integer, index value) is required for targets other than 'menu' or 'grid' " ) ;
return NULL ;
}
// at this point, `values` needs to be decoded based on the `field` provided
// 3.0, # duration, seconds
// "demobox1", # parent: a UIMenu or Grid key
// "menu", # target type: 'menu', 'grid', 'caption', 'button', 'sprite', or 'entity'
// None, # target id: integer index for menu or grid objs; None for grid/menu
// "position", # field: 'position', 'size', 'bgcolor', 'textcolor', or 'sprite'
// lambda: self.animation_done("demobox1"), #callback: callable once animation is complete
// False, #loop: repeat indefinitely
// [100, 100] # values: iterable of frames for 'sprite', lerp target for others
//LerpAnimation<T>::LerpAnimation(float _d, T _ev, T _sv, std::function<void()> _cb, std::function<void(T)> _w, bool _l)
if ( CEQ ( target_type , " menu " ) ) {
auto obj = menus [ std : : string ( parent ) ] ;
if ( CEQ ( field , " position " ) ) {
if ( PyList_Check ( values_obj ) ) evdata = PyList_AsTuple ( values_obj ) ; else evdata = values_obj ;
auto end_value = sf : : Vector2f ( PyFloat_AsDouble ( PyTuple_GetItem ( evdata , 0 ) ) ,
PyFloat_AsDouble ( PyTuple_GetItem ( evdata , 1 ) ) ) ;
McRFPy_API : : animations . push_back ( new LerpAnimation < sf : : Vector2f > (
duration , end_value ,
obj - > box . getPosition ( ) ,
[ = ] ( ) { PyObject_Call ( callback , PyTuple_New ( 0 ) , NULL ) ; } ,
[ = ] ( sf : : Vector2f v ) { obj - > box . setPosition ( v ) ; } ,
loop )
) ;
}
else if ( CEQ ( field , " size " ) ) {
if ( PyList_Check ( values_obj ) ) evdata = PyList_AsTuple ( values_obj ) ; else evdata = values_obj ;
auto end_value = sf : : Vector2f ( PyFloat_AsDouble ( PyTuple_GetItem ( evdata , 0 ) ) ,
PyFloat_AsDouble ( PyTuple_GetItem ( evdata , 1 ) ) ) ;
McRFPy_API : : animations . push_back ( new LerpAnimation < sf : : Vector2f > (
duration , end_value ,
obj - > box . getSize ( ) ,
[ = ] ( ) { PyObject_Call ( callback , PyTuple_New ( 0 ) , NULL ) ; } ,
[ = ] ( sf : : Vector2f v ) { obj - > box . setSize ( v ) ; } ,
loop )
) ;
}
// else if (CEQ(field, "bgcolor")) { )
}
else if ( CEQ ( target_type , " sprite " ) ) {
if ( CEQ ( field , " position " ) ) {
auto obj = menus [ std : : string ( parent ) ] - > sprites [ target_id ] ;
PyObject * evdata ;
if ( PyList_Check ( values_obj ) ) evdata = PyList_AsTuple ( values_obj ) ; else evdata = values_obj ;
auto end_value = sf : : Vector2f ( PyFloat_AsDouble ( PyTuple_GetItem ( evdata , 0 ) ) ,
PyFloat_AsDouble ( PyTuple_GetItem ( evdata , 1 ) ) ) ;
McRFPy_API : : animations . push_back ( new LerpAnimation < sf : : Vector2f > ( duration , end_value ,
sf : : Vector2f ( obj . x , obj . y ) ,
[ = ] ( ) { PyObject_Call ( callback , PyTuple_New ( 0 ) , NULL ) ; } ,
[ & ] ( sf : : Vector2f v ) { obj . x = v . x ; obj . y = v . y ; } ,
loop )
) ;
}
else if ( CEQ ( field , " sprite " ) ) {
auto obj = menus [ std : : string ( parent ) ] ;
PyObject * evdata ;
if ( PyList_Check ( values_obj ) ) evdata = PyList_AsTuple ( values_obj ) ; else evdata = values_obj ;
std : : vector < int > frames ;
for ( int i = 0 ; i < PyTuple_Size ( evdata ) ; i + + ) {
frames . push_back ( PyLong_AsLong ( PyTuple_GetItem ( evdata , i ) ) ) ;
}
//DiscreteAnimation(float _d, std::vector<T> _v, std::function<void()> _cb, std::function<void(T)> _w, bool _l)
McRFPy_API : : animations . push_back ( new DiscreteAnimation < int > (
duration ,
frames ,
[ = ] ( ) { PyObject_Call ( callback , PyTuple_New ( 0 ) , NULL ) ; } ,
[ = ] ( int s ) { obj - > sprites [ target_id ] . sprite_index = s ; } ,
loop )
) ;
//std::cout << "Frame animation constructed, there are now " <<McRFPy_API::animations.size() << std::endl;
}
}
else if ( CEQ ( target_type , " entity " ) ) {
if ( CEQ ( field , " position " ) ) {
auto obj = grids [ std : : string ( parent ) ] - > entities [ target_id ] ;
PyObject * evdata ;
if ( PyList_Check ( values_obj ) ) evdata = PyList_AsTuple ( values_obj ) ; else evdata = values_obj ;
auto end_value = sf : : Vector2f ( PyFloat_AsDouble ( PyTuple_GetItem ( evdata , 0 ) ) ,
PyFloat_AsDouble ( PyTuple_GetItem ( evdata , 1 ) ) ) ;
McRFPy_API : : animations . push_back ( new LerpAnimation < sf : : Vector2f > ( duration , end_value ,
sf : : Vector2f ( obj - > cGrid - > indexsprite . x , obj - > cGrid - > indexsprite . y ) ,
[ = ] ( ) { PyObject_Call ( callback , PyTuple_New ( 0 ) , NULL ) ; } ,
[ = ] ( sf : : Vector2f v ) { obj - > cGrid - > indexsprite . x = v . x ; obj - > cGrid - > indexsprite . y = v . y ; } ,
loop )
) ;
}
else if ( CEQ ( field , " sprite " ) ) {
auto obj = grids [ std : : string ( parent ) ] ;
PyObject * evdata ;
if ( PyList_Check ( values_obj ) ) evdata = PyList_AsTuple ( values_obj ) ; else evdata = values_obj ;
std : : vector < int > frames ;
for ( int i = 0 ; i < PyTuple_Size ( evdata ) ; i + + ) {
frames . push_back ( PyLong_AsLong ( PyTuple_GetItem ( evdata , i ) ) ) ;
}
//DiscreteAnimation(float _d, std::vector<T> _v, std::function<void()> _cb, std::function<void(T)> _w, bool _l)
McRFPy_API : : animations . push_back ( new DiscreteAnimation < int > (
duration ,
frames ,
[ = ] ( ) { PyObject_Call ( callback , PyTuple_New ( 0 ) , NULL ) ; } ,
[ = ] ( int s ) { obj - > entities [ target_id ] - > cGrid - > indexsprite . sprite_index = s ; } ,
loop )
) ;
}
}
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _createSoundBuffer ( PyObject * self , PyObject * args ) {
const char * fn_cstr ;
if ( ! PyArg_ParseTuple ( args , " s " , & fn_cstr ) ) return NULL ;
auto b = sf : : SoundBuffer ( ) ;
b . loadFromFile ( fn_cstr ) ;
McRFPy_API : : soundbuffers . push_back ( b ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _loadMusic ( PyObject * self , PyObject * args ) {
const char * fn_cstr ;
PyObject * loop_obj ;
if ( ! PyArg_ParseTuple ( args , " s|O " , & fn_cstr , & loop_obj ) ) return NULL ;
McRFPy_API : : music . stop ( ) ;
// get params for sf::Music initialization
//sf::InputSoundFile file;
//file.openFromFile(fn_cstr);
McRFPy_API : : music . openFromFile ( fn_cstr ) ;
McRFPy_API : : music . setLoop ( PyObject_IsTrue ( loop_obj ) ) ;
//McRFPy_API::music.initialize(file.getChannelCount(), file.getSampleRate());
McRFPy_API : : music . play ( ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _setMusicVolume ( PyObject * self , PyObject * args ) {
int vol ;
if ( ! PyArg_ParseTuple ( args , " i " , & vol ) ) return NULL ;
McRFPy_API : : music . setVolume ( vol ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _setSoundVolume ( PyObject * self , PyObject * args ) {
float vol ;
if ( ! PyArg_ParseTuple ( args , " f " , & vol ) ) return NULL ;
McRFPy_API : : sfx . setVolume ( vol ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _playSound ( PyObject * self , PyObject * args ) {
float index ;
if ( ! PyArg_ParseTuple ( args , " f " , & index ) ) return NULL ;
if ( index > = McRFPy_API : : soundbuffers . size ( ) ) return NULL ;
McRFPy_API : : sfx . stop ( ) ;
McRFPy_API : : sfx . setBuffer ( McRFPy_API : : soundbuffers [ index ] ) ;
McRFPy_API : : sfx . play ( ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _getMusicVolume ( PyObject * self , PyObject * args ) {
return Py_BuildValue ( " f " , McRFPy_API : : music . getVolume ( ) ) ;
}
PyObject * McRFPy_API : : _getSoundVolume ( PyObject * self , PyObject * args ) {
return Py_BuildValue ( " f " , McRFPy_API : : sfx . getVolume ( ) ) ;
}
PyObject * McRFPy_API : : _unlockPlayerInput ( PyObject * self , PyObject * args ) {
McRFPy_API : : input_mode = " playerturn " ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _lockPlayerInput ( PyObject * self , PyObject * args ) {
McRFPy_API : : input_mode = " computerturnwait " ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _requestGridTarget ( PyObject * self , PyObject * args ) {
const char * requestmode ;
if ( ! PyArg_ParseTuple ( args , " s " , & requestmode ) ) return NULL ;
McRFPy_API : : input_mode = requestmode ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _activeGrid ( PyObject * self , PyObject * args ) {
return Py_BuildValue ( " s " , McRFPy_API : : active_grid . c_str ( ) ) ;
}
PyObject * McRFPy_API : : _setActiveGrid ( PyObject * self , PyObject * args ) {
const char * newactivegrid ;
if ( ! PyArg_ParseTuple ( args , " s " , & newactivegrid ) ) return NULL ;
McRFPy_API : : active_grid = newactivegrid ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
PyObject * McRFPy_API : : _inputMode ( PyObject * self , PyObject * args ) {
return Py_BuildValue ( " s " , McRFPy_API : : input_mode . c_str ( ) ) ;
}
PyObject * McRFPy_API : : _turnNumber ( PyObject * self , PyObject * args ) {
return Py_BuildValue ( " i " , McRFPy_API : : turn_number ) ;
}
PyObject * McRFPy_API : : _createEntity ( PyObject * self , PyObject * args ) {
const char * grid_cstr , * entity_tag ;
int ti , si , x , y ;
PyObject * behavior_obj ;
if ( ! PyArg_ParseTuple ( args , " ssiiii|O " , & grid_cstr , & entity_tag , & ti , & si , & x , & y , & behavior_obj ) ) return NULL ;
auto e = entities . addEntity ( std : : string ( entity_tag ) ) ;
Grid * grid_ptr = grids [ grid_cstr ] ;
grid_ptr - > entities . push_back ( e ) ;
e - > cGrid = std : : make_shared < CGrid > ( grid_ptr , ti , si , x , y , true ) ;
e - > cBehavior = std : : make_shared < CBehavior > ( behavior_obj ) ;
Py_INCREF ( behavior_obj ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
/*
PyObject * McRFPy_API : : _listEntities ( PyObject * self , PyObject * args ) {
Py_INCREF ( Py_None ) ;
return Py_None ;
}
*/
void McRFPy_API : : player_input ( int dx , int dy ) {
//std::cout << "# entities tagged 'player': " << McRFPy_API::entities.getEntities("player").size() << std::endl;
auto player_entity = McRFPy_API : : entities . getEntities ( " player " ) [ 0 ] ;
auto grid = player_entity - > cGrid - > grid ;
//std::cout << "Grid pointed to: " << (long)player_entity->cGrid->grid << std::endl;
if ( McRFPy_API : : input_mode . compare ( " playerturn " ) ! = 0 ) {
// no input accepted while computer moving
//std::cout << "Can't move while it's not player's turn." << std::endl;
return ;
}
// TODO: selection cursor via keyboard
// else if (!input_mode.compare("selectpoint") {}
// else if (!input_mode.compare("selectentity") {}
// grid bounds check
if ( player_entity - > cGrid - > x + dx < 0 | |
player_entity - > cGrid - > y + dy < 0 | |
player_entity - > cGrid - > x + dx > grid - > grid_x - 1 | |
player_entity - > cGrid - > y + dy > grid - > grid_y - 1 ) {
//std::cout << "(" << player_entity->cGrid->x << ", " << player_entity->cGrid->y <<
// ") + (" << dx << ", " << dy << ") is OOB." << std::endl;
return ;
}
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(player_entity->cBehavior->object)) << std::endl;
PyObject * move_fn = PyObject_GetAttrString ( player_entity - > cBehavior - > object , " move " ) ;
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(move_fn)) << std::endl;
if ( move_fn ) {
//std::cout << "Calling `move`" << std::endl;
PyObject * move_args = Py_BuildValue ( " (ii) " , dx , dy ) ;
PyObject_CallObject ( ( PyObject * ) move_fn , move_args ) ;
} else {
//std::cout << "player_input called on entity with no `move` method" << std::endl;
}
}
void McRFPy_API : : computerTurn ( ) {
McRFPy_API : : input_mode = " computerturnrunning " ;
for ( auto e : McRFPy_API : : grids [ McRFPy_API : : active_grid ] - > entities ) {
if ( e - > cBehavior ) {
PyObject_Call ( PyObject_GetAttrString ( e - > cBehavior - > object , " ai_act " ) , PyTuple_New ( 0 ) , NULL ) ;
}
}
}
void McRFPy_API : : playerTurn ( ) {
McRFPy_API : : input_mode = " playerturn " ;
for ( auto e : McRFPy_API : : entities . getEntities ( " player " ) ) {
if ( e - > cBehavior ) {
PyObject_Call ( PyObject_GetAttrString ( e - > cBehavior - > object , " player_act " ) , PyTuple_New ( 0 ) , NULL ) ;
}
}
}
void McRFPy_API : : camFollow ( ) {
if ( ! McRFPy_API : : do_camfollow ) return ;
auto & ag = McRFPy_API : : grids [ McRFPy_API : : active_grid ] ;
for ( auto e : McRFPy_API : : entities . getEntities ( " player " ) ) {
//std::cout << "grid center: " << ag->center_x << ", " << ag->center_y << std::endl <<
// "player grid pos: " << e->cGrid->x << ", " << e->cGrid->y << std::endl <<
// "player sprite pos: " << e->cGrid->indexsprite.x << ", " << e->cGrid->indexsprite.y << std::endl;
ag - > center_x = e - > cGrid - > indexsprite . x * ag - > grid_size + ag - > grid_size * 0.5 ;
ag - > center_y = e - > cGrid - > indexsprite . y * ag - > grid_size + ag - > grid_size * 0.5 ;
}
}
PyObject * McRFPy_API : : _camFollow ( PyObject * self , PyObject * args ) {
PyObject * set_camfollow = NULL ;
//std::cout << "camFollow Parse Args" << std::endl;
if ( ! PyArg_ParseTuple ( args , " |O " , & set_camfollow ) ) return NULL ;
//std::cout << "Parsed" << std::endl;
if ( set_camfollow = = NULL ) {
// return value
//std::cout << "null; Returning value " << McRFPy_API::do_camfollow << std::endl;
Py_INCREF ( McRFPy_API : : do_camfollow ? Py_True : Py_False ) ;
return McRFPy_API : : do_camfollow ? Py_True : Py_False ;
}
//std::cout << "non-null; setting value" << std::endl;
McRFPy_API : : do_camfollow = PyObject_IsTrue ( set_camfollow ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
//McRFPy_API::_sceneUI
PyObject * McRFPy_API : : _sceneUI ( PyObject * self , PyObject * args ) {
using namespace mcrfpydef ;
const char * scene_cstr ;
if ( ! PyArg_ParseTuple ( args , " s " , & scene_cstr ) ) return NULL ;
auto ui = Resources : : game - > scene_ui ( scene_cstr ) ;
if ( ! ui )
{
PyErr_SetString ( PyExc_RuntimeError , " No scene found by that name " ) ;
return NULL ;
}
//std::cout << "vector returned has size=" << ui->size() << std::endl;
//Py_INCREF(Py_None);
//return Py_None;
PyUICollectionObject * o = ( PyUICollectionObject * ) PyUICollectionType . tp_alloc ( & PyUICollectionType , 0 ) ;
if ( o )
o - > data = ui ;
return ( PyObject * ) o ;
}