Commit fccdc78e authored by gerstrong@gmail.com's avatar gerstrong@gmail.com

More Python support, cleanups to some GUI elements

parent 43fa7fcb
......@@ -72,6 +72,151 @@ GsPythonModule::~GsPythonModule()
}
bool
GsPythonModule::
loadIntegerFunc(const std::string &pyMethodStr,
int &value)
{
// pFunc is a new reference
PyObject *pFunc = PyObject_GetAttrString(mpModule, pyMethodStr.c_str());
if (pFunc && PyCallable_Check(pFunc))
{
PyObject *pValue = PyObject_CallObject(pFunc, nullptr);
if (pValue != nullptr)
{
value = PyLong_AsLong(pValue);
Py_DECREF(pValue);
}
else
{
Py_DECREF(pFunc);
PyErr_Print();
gLogging.ftextOut("Call failed\n");
return false;
}
}
else
{
if (PyErr_Occurred())
{
PyErr_Print();
}
gLogging.ftextOut("Cannot find function \"init\"\n");
return false;
}
Py_XDECREF(pFunc);
return true;
}
bool
GsPythonModule::
loadIntegerFunc(const std::string &pyMethodStr,
int &value,
const int param1)
{
// pFunc is a new reference
PyObject *pFunc = PyObject_GetAttrString(mpModule, pyMethodStr.c_str());
PyObject *pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, PyLong_FromLong(param1));
if (pFunc && PyCallable_Check(pFunc))
{
PyObject *pValue = PyObject_CallObject(pFunc, pArgs);
if (pValue != nullptr)
{
value = PyLong_AsLong(pValue);
Py_DECREF(pValue);
}
else
{
Py_DECREF(pFunc);
PyErr_Print();
gLogging.ftextOut("Call failed\n");
return false;
}
}
else
{
if (PyErr_Occurred())
{
PyErr_Print();
}
gLogging.ftextOut("Cannot find function \"%s\"\n", pyMethodStr.c_str());
return false;
}
Py_XDECREF(pArgs);
Py_XDECREF(pFunc);
return true;
}
bool
GsPythonModule::
loadBooleanFunc(const std::string &pyMethodStr,
bool &value)
{
// pFunc is a new reference
PyObject *pFunc = PyObject_GetAttrString(mpModule, pyMethodStr.c_str());
if (pFunc && PyCallable_Check(pFunc))
{
PyObject *pValue = PyObject_CallObject(pFunc, nullptr);
if (pValue != nullptr)
{
auto isBool = PyBool_Check(pValue);
if(isBool)
{
if(pValue == Py_False)
{
value = false;
}
else if(pValue == Py_True)
{
value = true;
}
}
Py_DECREF(pValue);
}
else
{
Py_DECREF(pFunc);
PyErr_Print();
gLogging.ftextOut("Call failed\n");
return false;
}
}
else
{
if (PyErr_Occurred())
{
PyErr_Print();
}
gLogging.ftextOut("Cannot find function \"init\"\n");
return false;
}
Py_XDECREF(pFunc);
return true;
}
bool
GsPythonModule::
......@@ -118,9 +263,9 @@ load(GsPythonModule &module,
PyObject*
GsPythonFunc::call()
GsPythonFunc::call(PyObject* args)
{
PyObject *pValue = PyObject_CallObject(mpFunction, nullptr);
PyObject *pValue = PyObject_CallObject(mpFunction, args);
if (pValue == nullptr)
{
......@@ -152,7 +297,7 @@ PyObject *GsPython::loadModule(const std::string &scriptBaseName,
replaceSlashes(aidir);
duplicateBackslashes(aidir);
gLogging.ftextOut("calling Py_Initialize().\n", aiscriptPath.c_str() );
gLogging.ftextOut("calling Py_Initialize(): %s.\n", aiscriptPath.c_str() );
#ifdef ANDROID
......
......@@ -9,8 +9,45 @@
#define gPython GsPython::get()
/**
* @brief loadStrFunction Function that takes on integer and returns string
* @param pModule
* @param pyMethodStr
* @param value
* @param param1
* @return
*/
bool loadStrFunction(PyObject * pModule,
const std::string &pyMethodStr,
std::string &value,
const int param1);
bool loadStrFunction(PyObject * pModule,
const std::string &pyMethodStr,
std::string &value);
/**
* @brief loadIntegerGetter for a python function that has no arguments but returns an integer
* @param pModule
* @param pyMethodStr
* @param value
* @return
*/
bool loadIntegerFunc(PyObject * pModule,
const std::string &pyMethodStr,
int &value);
bool loadIntegerFunc(PyObject * pModule,
const std::string &pyMethodStr,
int &value,
const int param1);
bool loadBooleanFunc(PyObject * pModule,
const std::string &pyMethodStr,
bool &value);
class GsPythonModule
{
public:
......@@ -32,6 +69,17 @@ public:
}
bool loadIntegerFunc(const std::string &pyMethodStr,
int &value);
bool loadIntegerFunc(const std::string &pyMethodStr,
int &value,
const int param1);
bool loadBooleanFunc(const std::string &pyMethodStr,
bool &value);
private:
PyObject *mpModule = nullptr;
......@@ -54,7 +102,7 @@ public:
}
PyObject *call();
PyObject *call(PyObject *args = nullptr);
private:
PyObject *mpFunction = nullptr;
......@@ -89,44 +137,7 @@ public:
void fixNewLine(std::string& str);
/**
* @brief loadStrFunction Function that takes on integer and returns string
* @param pModule
* @param pyMethodStr
* @param value
* @param param1
* @return
*/
bool loadStrFunction(PyObject * pModule,
const std::string &pyMethodStr,
std::string &value,
const int param1);
bool loadStrFunction(PyObject * pModule,
const std::string &pyMethodStr,
std::string &value);
/**
* @brief loadIntegerGetter for a python function that has no arguments but returns an integer
* @param pModule
* @param pyMethodStr
* @param value
* @return
*/
bool loadIntegerFunc(PyObject * pModule,
const std::string &pyMethodStr,
int &value);
bool loadIntegerFunc(PyObject * pModule,
const std::string &pyMethodStr,
int &value,
const int param1);
bool loadBooleanFunc(PyObject * pModule,
const std::string &pyMethodStr,
bool &value);
#endif
......
......@@ -30,16 +30,6 @@ mBlue(blue)
{}
void GsButton::setupButtonSurface()
{
GsFont &Font = gGraphics.getFont(mFontID);
Font.createTextSurface(mTextDarkSfc, " " + mText, 38, 134, 38 );
Font.createTextSurface(mTextLightSfc, " " + mText, 84, 234, 84 );
Font.createTextSurface(mTextDisabledSfc, " " + mText, 123, 150, 123 );
}
bool GsButton::sendEvent(const InputCommand command)
{
if(command == IC_STATUS || command == IC_JUMP)
......@@ -154,6 +144,14 @@ void GsButton::setupButtonSurface(const std::string &text)
{
GsFont &Font = gGraphics.getFont(mFontID);
if(text.empty())
{
Font.createTextSurface(mTextDarkSfc, " " + mText, 38, 134, 38 );
Font.createTextSurface(mTextLightSfc, " " + mText, 84, 234, 84 );
Font.createTextSurface(mTextDisabledSfc, " " + mText, 123, 150, 123 );
return;
}
auto fontSfc = Font.SDLSurfacePtr();
auto palette = fontSfc->format->palette;
......
......@@ -28,8 +28,6 @@ public:
const float green = 0.875f,
const float blue = 1.0f);
void setupButtonSurface();
bool sendEvent(const InputCommand command);
void updateGraphics();
......@@ -66,7 +64,7 @@ public:
std::string getText()
{ return mText; }
virtual void setupButtonSurface(const std::string &text);
virtual void setupButtonSurface(const std::string &text = "");
protected:
......
......@@ -74,7 +74,7 @@ public:
mHovered = value;
}
virtual bool sendEvent(const InputCommand command) { return false; }
virtual bool sendEvent(const InputCommand) { return false; }
void drawTwirl( const SDL_Rect& lRect );
......
......@@ -147,6 +147,9 @@ void CGUIDialog::selectPrevItem()
void CGUIDialog::selectNextItem()
{
if(!mpCurrentCtrl)
return;
if(mpCurrentCtrl->isSelected())
{
mpCurrentCtrl->select(false);
......@@ -184,7 +187,7 @@ void CGUIDialog::selectNextItem()
}
void CGUIDialog::setSelection(const unsigned int sel)
void CGUIDialog::setSelection(const int sel)
{
const int steps = sel-mSelection;
......
......@@ -87,10 +87,10 @@ public:
std::list< std::shared_ptr<GsControl> >& getControlList()
{ return mControlList; }
const int Selection() const
int Selection() const
{ return mSelection; }
void setSelection(const unsigned int sel);
void setSelection(const int sel);
GsControl* CurrentControl()
{ return mpCurrentCtrl; }
......
......@@ -21,7 +21,7 @@ class CGUIText : public GsControl
public:
CGUIText(const std::string& text);
void setupButtonSurface(const std::string& text);
void setupButtonSurface(const std::string& text = "");
virtual void setText(const std::string& text);
......
......@@ -406,6 +406,7 @@ class CSpriteObject
GsPythonModule mModule;
GsPythonFunc mProcessFunc;
GsPythonFunc mUpdatePlayerCoord;
#endif
......
......@@ -34,7 +34,7 @@ CGUINumberControl(text, startValue, endValue,
}
void NumberControl::setupButtonSurface()
void NumberControl::setupButtonSurface(const std::string &text)
{
GsFont &Font = gGraphics.getFont(mFontID);
......
......@@ -15,13 +15,13 @@ public:
const bool slider,
const GsControl::Style style);
void setupButtonSurface();
void setupButtonSurface(const std::string &text = "") override;
void processLogic();
void processLogic() override;
void drawNoStyle(SDL_Rect& lRect);
void processRender(const GsRect<float> &RectDispCoordFloat);
void processRender(const GsRect<float> &RectDispCoordFloat) override;
};
#endif // NUMBERCONTROL_H
......@@ -40,13 +40,14 @@ m_HUD(Item.m_points, Item.m_lifes, Item.m_bullets,
#if USE_PYTHON3
auto pModule = gPython.loadModule( "constants", gKeenFiles.gameDir );
GsPythonModule module;
module.load("constants", gKeenFiles.gameDir);
if (pModule != nullptr)
if (module)
{
int startBullets = 0;
bool ok;
ok = loadIntegerFunc(pModule, "getStartWithNumBullets", startBullets);
ok = module.loadIntegerFunc("getStartWithNumBullets", startBullets);
if(ok)
{
Item.m_bullets = startBullets;
......@@ -54,7 +55,7 @@ m_HUD(Item.m_points, Item.m_lifes, Item.m_bullets,
bool usePogo;
ok = loadBooleanFunc(pModule, "mayUsePogo", usePogo);
ok = module.loadBooleanFunc("mayUsePogo", usePogo);
if(ok)
{
Item.m_special.mCanPogo = usePogo;
......@@ -63,8 +64,6 @@ m_HUD(Item.m_points, Item.m_lifes, Item.m_bullets,
}
#endif
m_HUD.sync();
}
......
......@@ -178,6 +178,8 @@ CPlayerBase(CMap *pmap,
mpMap->calcVisibleArea();
mpMap->refreshVisibleArea();
mModule.load("constants", gKeenFiles.gameDir);
}
......@@ -413,17 +415,16 @@ void CPlayerBase::processLevelMiscFlagsCheck()
}
#if USE_PYTHON3
auto pModule = gPython.loadModule( "constants", gKeenFiles.gameDir);
int value = 0;
if (pModule != nullptr)
if (mModule)
{
for( Uint32 i=21 ; i<=28 ; i++ )
{
if(hitdetectWithTilePropertyRect(i, l_x, l_y, l_w, l_h, 2<<STC))
{
loadIntegerFunc(pModule, "defineSlipperyTile",
value, int(i));
mModule.loadIntegerFunc("defineSlipperyTile", value, int(i));
if(value>0)
{
......
......@@ -110,12 +110,15 @@ void CSpriteItem::getTouchedBy(CSpriteObject &theObject)
// Enable pogo if some script would like that
#if USE_PYTHON3
auto pModule = gPython.loadModule( "constants", gKeenFiles.gameDir );
if (pModule != nullptr)
{
if(!mModule)
{
mModule.load("constants", gKeenFiles.gameDir);
}
else
{
int value = 0;
const auto ok = loadIntegerFunc(pModule, "enablePogo", value, m_basesprite);
const auto ok = mModule.loadIntegerFunc("enablePogo", value, m_basesprite);
if(ok)
{
if(value==1)
......@@ -123,7 +126,7 @@ void CSpriteItem::getTouchedBy(CSpriteObject &theObject)
Item.m_special.mCanPogo = true;
}
}
}
}
#endif
......
......@@ -74,6 +74,7 @@ bool CShikadi::loadPythonScripts(const std::string &scriptBaseName)
mp_processState = static_cast<GASOFctr>(&CShikadi::processPython);
mProcessFunc.load(mModule, "process");
mUpdatePlayerCoord.load(mModule, "updatePlayerCoord");
#endif
return true;
......@@ -82,12 +83,19 @@ bool CShikadi::loadPythonScripts(const std::string &scriptBaseName)
void CShikadi::processPython()
{
#if USE_PYTHON3
// TODO: Needs to be put into members of class. This part is yet too CPU heavy
// NOTE: My tests for using Pyton in CG. These will be forwared to a more common function
// The following will atempt to get a walk instruction from Python process.
// The following will atempt to get a walk instruction from Python process.
if (mProcessFunc)
{
PyObject *pDict = mProcessFunc.call();
// create arguments for the python function
auto args = PyTuple_New(2);
auto pValueX = PyLong_FromLong(getPosition().x);
auto pValueY = PyLong_FromLong(getPosition().y);
PyTuple_SetItem(args, 0, pValueX);
PyTuple_SetItem(args, 1, pValueY);
PyObject *pDict = mProcessFunc.call(args);
// Process return a dictionary of tasks to perform with some values
if (pDict != nullptr)
......@@ -104,20 +112,24 @@ void CShikadi::processPython()
const long iValue = PyLong_AsLong(value);
//gLogging.ftextOut("%s : %ld\n", bytes, iValue);
if(keyAsStr == "'walk'")
{
moveXDir(iValue);
}
if(keyAsStr == "'dir'")
{
xDirection = iValue;
}
Py_XDECREF(repr);
Py_XDECREF(str);
}
Py_DECREF(pDict);
Py_XDECREF(pDict);
Py_XDECREF(args);
}
}
#endif
}
......@@ -131,53 +143,53 @@ void CShikadi::processStanding()
void CShikadi::processWalking()
{
// Move normally in the direction
if( xDirection == RIGHT )
{
moveRight( WALK_SPEED );
}
else
{
moveLeft( WALK_SPEED );
}
if( blockedl )
{
xDirection = RIGHT;
}
else if(blockedr)
{
xDirection = LEFT;
}
mTimer++;
if( mTimer < TIME_UNTIL_STAND )
return;
mTimer = 0;
int newX = (xDirection == LEFT) ? getXLeftPos()+(4<<STC) : getXRightPos()-(4<<STC);
if(hitdetectWithTilePropertyVert(1, newX, getYUpPos(), getYDownPos(), (1<<STC) ))
{
if(getProbability(500))
{
newX = (newX>>CSF)<<CSF;
// Spawn a Enemyshot in form electrostatic charge which goes upwards
spawnObj( new CEnemyShot(mpMap, 0,
newX, getYUpPos(),
0x2E5A, 0, UP,
150, mSprVar, true) );
setAction(A_SHIKADI_POLE_ZAPS);
playSound(SOUND_POLEZAP);
return;
}
}
if(getProbability(300))
{
setAction(A_SHIKADI_STAND);
}
// Move normally in the direction
if( xDirection == RIGHT )
{
moveRight( WALK_SPEED );
}
else
{
moveLeft( WALK_SPEED );
}
if( blockedl )
{
xDirection = RIGHT;
}
else if(blockedr)
{
xDirection = LEFT;
}
mTimer++;
if( mTimer < TIME_UNTIL_STAND )
return;
mTimer = 0;
int newX = (xDirection == LEFT) ? getXLeftPos()+(4<<STC) : getXRightPos()-(4<<STC);
if(hitdetectWithTilePropertyVert(1, newX, getYUpPos(), getYDownPos(), (1<<STC) ))
{
if(getProbability(500))
{
newX = (newX>>CSF)<<CSF;
// Spawn a Enemyshot in form electrostatic charge which goes upwards
spawnObj( new CEnemyShot(mpMap, 0,
newX, getYUpPos(),
0x2E5A, 0, UP,
150, mSprVar, true) );
setAction(A_SHIKADI_POLE_ZAPS);
playSound(SOUND_POLEZAP);
return;
}
}
if(getProbability(300))
{
setAction(A_SHIKADI_STAND);
}
}
......@@ -192,16 +204,38 @@ void CShikadi::processPoleZaps()
bool CShikadi::isNearby(CSpriteObject &theObject)
{
if( !getProbability(10) )
return false;
return true;
#if USE_PYTHON3
if( CPlayerBase *player = dynamic_cast<CPlayerBase*>(&theObject) )
{
const int x = player->getPosition().x;
const int y = player->getPosition().y;
auto args = PyTuple_New(2);
auto pValueX = PyLong_FromLong(x);
auto pValueY = PyLong_FromLong(y);
PyTuple_SetItem(args, 0, pValueX);
PyTuple_SetItem(args, 1, pValueY);
mUpdatePlayerCoord.call(args);
Py_XDECREF(args);
}
#endif
if( !getProbability(10) )
return false;
return true;
}
void CShikadi::getTouchedBy(CSpriteObject &theObject)
{
if(mIsDead || theObject.mIsDead)
return;
if(mIsDead || theObject.mIsDead)
return;
CStunnable::getTouchedBy(theObject);
......@@ -222,31 +256,31 @@ void CShikadi::getTouchedBy(CSpriteObject &theObject)
}
}
if( CPlayerBase *player = dynamic_cast<CPlayerBase*>(&theObject) )
{
if( CPlayerBase *player = dynamic_cast<CPlayerBase*>(&theObject) )
{
player->kill(false);