You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
16 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "pyKey.h"
#include "pyDynamicText.h"
#include "pyEnum.h"
#include "pyColor.h"
#include "pyImage.h"
#include "plGImage/plDynamicTextMap.h"
#include <python.h>
// glue functions
PYTHON_CLASS_DEFINITION(ptDynamicMap, pyDynamicText);
PYTHON_DEFAULT_NEW_DEFINITION(ptDynamicMap, pyDynamicText)
PYTHON_DEFAULT_DEALLOC_DEFINITION(ptDynamicMap)
PYTHON_INIT_DEFINITION(ptDynamicMap, args, keywords)
{
PyObject* keyObj = NULL;
if (!PyArg_ParseTuple(args, "|O", &keyObj))
{
PyErr_SetString(PyExc_TypeError, "__init__ expects an optional ptKey");
PYTHON_RETURN_INIT_ERROR;
}
if (!keyObj)
PYTHON_RETURN_INIT_OK; // nothing to do
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "__init__ expects an optional ptKey");
PYTHON_RETURN_INIT_ERROR;
}
pyKey* key = pyKey::ConvertFrom(keyObj);
self->fThis->AddReceiver(*key);
PYTHON_RETURN_INIT_OK;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, sender, args)
{
PyObject* senderObj = NULL;
if (!PyArg_ParseTuple(args, "O", &senderObj))
{
PyErr_SetString(PyExc_TypeError, "sender expects a ptKey");
PYTHON_RETURN_ERROR;
}
if (!pyKey::Check(senderObj))
{
PyErr_SetString(PyExc_TypeError, "sender expects a ptKey");
PYTHON_RETURN_ERROR;
}
pyKey* sender = pyKey::ConvertFrom(senderObj);
self->fThis->SetSender(*sender);
PYTHON_RETURN_NONE;
}
PYTHON_BASIC_METHOD_DEFINITION(ptDynamicMap, clearKeys, ClearReceivers)
PYTHON_METHOD_DEFINITION(ptDynamicMap, addKey, args)
{
PyObject* keyObj = NULL;
if (!PyArg_ParseTuple(args, "O", &keyObj))
{
PyErr_SetString(PyExc_TypeError, "addKey expects a ptKey");
PYTHON_RETURN_ERROR;
}
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "addKey expects a ptKey");
PYTHON_RETURN_ERROR;
}
pyKey* key = pyKey::ConvertFrom(keyObj);
self->fThis->AddReceiver(*key);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, netPropagate, args)
{
char propagateFlag;
if (!PyArg_ParseTuple(args, "b", &propagateFlag))
{
PyErr_SetString(PyExc_TypeError, "netPropagate expects a boolean");
PYTHON_RETURN_ERROR;
}
self->fThis->SetNetPropagate(propagateFlag != 0);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, netForce, args)
{
char forceFlag;
if (!PyArg_ParseTuple(args, "b", &forceFlag))
{
PyErr_SetString(PyExc_TypeError, "netForce expects a boolean");
PYTHON_RETURN_ERROR;
}
self->fThis->SetNetForce(forceFlag != 0);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, clearToColor, args)
{
PyObject* colorObj = NULL;
if (!PyArg_ParseTuple(args, "O", &colorObj))
{
PyErr_SetString(PyExc_TypeError, "clearToColor expects a ptColor");
PYTHON_RETURN_ERROR;
}
if (!pyColor::Check(colorObj))
{
PyErr_SetString(PyExc_TypeError, "clearToColor expects a ptColor");
PYTHON_RETURN_ERROR;
}
pyColor* color = pyColor::ConvertFrom(colorObj);
self->fThis->ClearToColor(*color);
PYTHON_RETURN_NONE;
}
PYTHON_BASIC_METHOD_DEFINITION(ptDynamicMap, flush, Flush)
PYTHON_BASIC_METHOD_DEFINITION(ptDynamicMap, purgeImage, PurgeImage)
PYTHON_METHOD_DEFINITION(ptDynamicMap, setTextColor, args)
{
PyObject* colorObj = NULL;
char blockRGB = 0;
if (!PyArg_ParseTuple(args, "O|b", &colorObj, &blockRGB))
{
PyErr_SetString(PyExc_TypeError, "setTextColor expects a ptColor and an optional boolean");
PYTHON_RETURN_ERROR;
}
if (!pyColor::Check(colorObj))
{
PyErr_SetString(PyExc_TypeError, "setTextColor expects a ptColor and an optional boolean");
PYTHON_RETURN_ERROR;
}
pyColor* color = pyColor::ConvertFrom(colorObj);
self->fThis->SetTextColor2(*color, blockRGB != 0);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, setFont, args)
{
char* faceName;
short fontSize;
if (!PyArg_ParseTuple(args, "sh", &faceName, &fontSize))
{
PyErr_SetString(PyExc_TypeError, "setFont expects a string and a short int");
PYTHON_RETURN_ERROR;
}
self->fThis->SetFont(faceName, fontSize);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, fillRect, args)
{
unsigned short left, top, right, bottom;
PyObject* colorObj = NULL;
if (!PyArg_ParseTuple(args, "hhhhO", &left, &top, &right, &bottom, &colorObj))
{
PyErr_SetString(PyExc_TypeError, "fillRect expects four unsigned short ints and a ptColor");
PYTHON_RETURN_ERROR;
}
if (!pyColor::Check(colorObj))
{
PyErr_SetString(PyExc_TypeError, "fillRect expects four unsigned short ints and a ptColor");
PYTHON_RETURN_ERROR;
}
pyColor* color = pyColor::ConvertFrom(colorObj);
self->fThis->FillRect(left, top, right, bottom, *color);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, frameRect, args)
{
unsigned short left, top, right, bottom;
PyObject* colorObj = NULL;
if (!PyArg_ParseTuple(args, "hhhhO", &left, &top, &right, &bottom, &colorObj))
{
PyErr_SetString(PyExc_TypeError, "frameRect expects four unsigned short ints and a ptColor");
PYTHON_RETURN_ERROR;
}
if (!pyColor::Check(colorObj))
{
PyErr_SetString(PyExc_TypeError, "frameRect expects four unsigned short ints and a ptColor");
PYTHON_RETURN_ERROR;
}
pyColor* color = pyColor::ConvertFrom(colorObj);
self->fThis->FrameRect(left, top, right, bottom, *color);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, setClipping, args)
{
unsigned short left, top, right, bottom;
if (!PyArg_ParseTuple(args, "hhhh", &left, &top, &right, &bottom))
{
PyErr_SetString(PyExc_TypeError, "setClipping expects four unsigned short ints");
PYTHON_RETURN_ERROR;
}
self->fThis->SetClipping(left, top, right, bottom);
PYTHON_RETURN_NONE;
}
PYTHON_BASIC_METHOD_DEFINITION(ptDynamicMap, unsetClipping, UnsetClipping)
PYTHON_METHOD_DEFINITION(ptDynamicMap, setWrapping, args)
{
unsigned short wrapWidth, wrapHeight;
if (!PyArg_ParseTuple(args, "hh", &wrapWidth, &wrapHeight))
{
PyErr_SetString(PyExc_TypeError, "setWrapping expects two unsigned short ints");
PYTHON_RETURN_ERROR;
}
self->fThis->SetWrapping(wrapWidth, wrapHeight);
PYTHON_RETURN_NONE;
}
PYTHON_BASIC_METHOD_DEFINITION(ptDynamicMap, unsetWrapping, UnsetWrapping)
PYTHON_METHOD_DEFINITION(ptDynamicMap, drawText, args)
{
short x, y;
char* text;
if (!PyArg_ParseTuple(args, "hhs", &x, &y, &text))
{
PyErr_SetString(PyExc_TypeError, "drawText expects two short ints and a string");
PYTHON_RETURN_ERROR;
}
self->fThis->DrawText(x, y, text);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, drawTextW, args)
{
short x, y;
wchar_t* text;
if (!PyArg_ParseTuple(args, "hhu", &x, &y, &text))
{
PyErr_SetString(PyExc_TypeError, "drawTextW expects two short ints and a unicode string");
PYTHON_RETURN_ERROR;
}
self->fThis->DrawTextW(x, y, text);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, drawImage, args)
{
short x, y;
PyObject* imageObj = NULL;
char respectAlpha;
if (!PyArg_ParseTuple(args, "hhOb", &x, &y, &imageObj, &respectAlpha))
{
PyErr_SetString(PyExc_TypeError, "drawImage expects two shorts, a ptImage, and a boolean");
PYTHON_RETURN_ERROR;
}
if (!pyImage::Check(imageObj))
{
PyErr_SetString(PyExc_TypeError, "drawImage expects two shorts, a ptImage, and a boolean");
PYTHON_RETURN_ERROR;
}
pyImage* image = pyImage::ConvertFrom(imageObj);
self->fThis->DrawImage(x, y, *image, respectAlpha != 0);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, drawImageClipped, args)
{
unsigned short x, y;
PyObject* imageObj = NULL;
unsigned short cx, cy, cw, ch;
char respectAlpha;
if (!PyArg_ParseTuple(args, "hhOhhhhb", &x, &y, &imageObj, &cx, &cy, &cw, &ch, &respectAlpha))
{
PyErr_SetString(PyExc_TypeError, "drawImageClipped expects two shorts, a ptImage, four shorts, and a boolean");
PYTHON_RETURN_ERROR;
}
if (!pyImage::Check(imageObj))
{
PyErr_SetString(PyExc_TypeError, "drawImageClipped expects two shorts, a ptImage, four shorts, and a boolean");
PYTHON_RETURN_ERROR;
}
pyImage* image = pyImage::ConvertFrom(imageObj);
self->fThis->DrawImageClipped(x, y, *image, cx, cy, cw, ch, respectAlpha != 0);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION_NOARGS(ptDynamicMap, getWidth)
{
return PyInt_FromLong(self->fThis->GetWidth());
}
PYTHON_METHOD_DEFINITION_NOARGS(ptDynamicMap, getHeight)
{
return PyInt_FromLong(self->fThis->GetHeight());
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, calcTextExtents, args)
{
PyObject* textObj = NULL;
if (!PyArg_ParseTuple(args, "O", &textObj))
{
PyErr_SetString(PyExc_TypeError, "calcTextExtents expects a string");
PYTHON_RETURN_ERROR;
}
std::wstring wText;
if (PyUnicode_Check(textObj))
{
int strLen = PyUnicode_GetSize(textObj);
wchar_t* text = TRACKED_NEW wchar_t[strLen + 1];
PyUnicode_AsWideChar((PyUnicodeObject*)textObj, text, strLen);
text[strLen] = L'\0';
wText = text;
delete [] text;
}
else if (PyString_Check(textObj))
{
// we'll allow this, just in case something goes weird
char* text = PyString_AsString(textObj);
wchar_t* temp = hsStringToWString(text);
wText = temp;
delete [] temp;
}
else
{
PyErr_SetString(PyExc_TypeError, "calcTextExtents expects a string");
PYTHON_RETURN_ERROR;
}
unsigned height, width;
self->fThis->CalcTextExtents(wText, width, height);
PyObject* retVal = PyTuple_New(2);
PyTuple_SetItem(retVal, 0, PyInt_FromLong(width));
PyTuple_SetItem(retVal, 1, PyInt_FromLong(height));
return retVal;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, setJustify, args)
{
unsigned char justify;
if (!PyArg_ParseTuple(args, "b", &justify))
{
PyErr_SetString(PyExc_TypeError, "setJustify expects a unsigned 8-bit int");
PYTHON_RETURN_ERROR;
}
self->fThis->SetJustify(justify);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptDynamicMap, setLineSpacing, args)
{
short spacing;
if (!PyArg_ParseTuple(args, "h", &spacing))
{
PyErr_SetString(PyExc_TypeError, "setLineSpacing expects a short int");
PYTHON_RETURN_ERROR;
}
self->fThis->SetLineSpacing(spacing);
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION_NOARGS(ptDynamicMap, getImage)
{
return pyImage::New(self->fThis->GetImage());
}
PYTHON_START_METHODS_TABLE(ptDynamicMap)
PYTHON_METHOD(ptDynamicMap, sender, "Params: sender\nSet the sender of the message being sent to the DynamicMap"),
PYTHON_BASIC_METHOD(ptDynamicMap, clearKeys, "Clears the receiver list"),
PYTHON_METHOD(ptDynamicMap, addKey, "Params: key\nAdd a receiver... in other words a DynamicMap"),
PYTHON_METHOD(ptDynamicMap, netPropagate, "Params: propagateFlag\nSpecify whether this object needs to use messages that are sent on the network\n"
"- The default is for this to be false."),
PYTHON_METHOD(ptDynamicMap, netForce, "Params: forceFlag\nSpecify whether this object needs to use messages that are forced to the network\n"
"- This is to be used if your Python program is running on only one client\n"
"Such as a game master, only running on the client that owns a particular object\n"
"This only applies when NetPropagate is set to true"),
PYTHON_METHOD(ptDynamicMap, clearToColor, "Params: color\nClear the DynamicMap to the specified color\n"
"- 'color' is a ptColor object"),
PYTHON_BASIC_METHOD(ptDynamicMap, flush, "Flush all the commands that were issued since the last flush()"),
PYTHON_BASIC_METHOD(ptDynamicMap, purgeImage, "Purge the DynamicTextMap images"),
PYTHON_METHOD(ptDynamicMap, setTextColor, "Params: color, blockRGB=0\nSet the color of the text to be written\n"
"- 'color' is a ptColor object\n"
"- 'blockRGB' must be true if you're trying to render onto a transparent or semi-transparent color"),
PYTHON_METHOD(ptDynamicMap, setFont, "Params: facename,size\nSet the font of the text to be written\n"
"- 'facename' is a string with the name of the font\n"
"- 'size' is the point size of the font to use"),
PYTHON_METHOD(ptDynamicMap, fillRect, "Params: left,top,right,bottom,color\nFill in the specified rectangle with a color\n"
"- left,top,right,bottom define the rectangle\n"
"- 'color' is a ptColor object"),
PYTHON_METHOD(ptDynamicMap, frameRect, "Params: left,top,right,bottom,color\nFrame a rectangle with a specified color\n"
"- left,top,right,bottom define the rectangle\n"
"- 'color' is a ptColor object"),
PYTHON_METHOD(ptDynamicMap, setClipping, "Params: clipLeft,clipTop,clipRight,clipBottom\nSets the clipping rectangle\n"
"- All drawtext will be clipped to this until the\n"
"unsetClipping() is called"),
PYTHON_BASIC_METHOD(ptDynamicMap, unsetClipping, "Stop the clipping of text"),
PYTHON_METHOD(ptDynamicMap, setWrapping, "Params: wrapWidth,wrapHeight\nSet where text will be wrapped horizontally and vertically\n"
"- All drawtext commands will be wrapped until the\n"
"unsetWrapping() is called"),
PYTHON_BASIC_METHOD(ptDynamicMap, unsetWrapping, "Stop text wrapping"),
PYTHON_METHOD(ptDynamicMap, drawText, "Params: x,y,text\nDraw text at a specified location\n"
"- x,y is the point to start drawing the text\n"
"- 'text' is a string of the text to be drawn"),
PYTHON_METHOD(ptDynamicMap, drawTextW, "Params: x,y,text\nUnicode version of drawText"),
PYTHON_METHOD(ptDynamicMap, drawImage, "Params: x,y,image,respectAlphaFlag\nDraws a ptImage object on the dynamicTextmap starting at the location x,y"),
PYTHON_METHOD(ptDynamicMap, drawImageClipped, "Params: x,y,image,cx,cy,cw,ch,respectAlphaFlag\nDraws a ptImage object clipped to cx,cy with cw(width),ch(height)"),
PYTHON_METHOD_NOARGS(ptDynamicMap, getWidth, "Returns the width of the dynamicTextmap"),
PYTHON_METHOD_NOARGS(ptDynamicMap, getHeight, "Returns the height of the dynamicTextmap"),
PYTHON_METHOD(ptDynamicMap, calcTextExtents, "Params: text\nCalculates the extent of the specified text, returns it as a (width, height) tuple"),
PYTHON_METHOD(ptDynamicMap, setJustify, "Params: justify\nSets the justification of the text. (justify is a PtJustify)"),
PYTHON_METHOD(ptDynamicMap, setLineSpacing, "Params: spacing\nSets the line spacing (in pixels)"),
PYTHON_METHOD_NOARGS(ptDynamicMap, getImage, "Returns a pyImage associated with the dynamicTextmap"),
PYTHON_END_METHODS_TABLE;
// Type structure definition
PLASMA_DEFAULT_TYPE(ptDynamicMap, "Params: key=None\nCreates a ptDynamicMap object");
// required functions for PyObject interoperability
PYTHON_CLASS_NEW_IMPL(ptDynamicMap, pyDynamicText)
PyObject *pyDynamicText::New(pyKey& key)
{
ptDynamicMap *newObj = (ptDynamicMap*)ptDynamicMap_type.tp_new(&ptDynamicMap_type, NULL, NULL);
newObj->fThis->fReceivers.Append(key.getKey());
return (PyObject*)newObj;
}
PyObject *pyDynamicText::New(plKey key)
{
ptDynamicMap *newObj = (ptDynamicMap*)ptDynamicMap_type.tp_new(&ptDynamicMap_type, NULL, NULL);
newObj->fThis->fReceivers.Append(key);
return (PyObject*)newObj;
}
PYTHON_CLASS_CHECK_IMPL(ptDynamicMap, pyDynamicText)
PYTHON_CLASS_CONVERT_FROM_IMPL(ptDynamicMap, pyDynamicText)
///////////////////////////////////////////////////////////////////////////
//
// AddPlasmaClasses - the python module definitions
//
void pyDynamicText::AddPlasmaClasses(PyObject *m)
{
PYTHON_CLASS_IMPORT_START(m);
PYTHON_CLASS_IMPORT(m, ptDynamicMap);
PYTHON_CLASS_IMPORT_END(m);
}
void pyDynamicText::AddPlasmaConstantsClasses(PyObject *m)
{
PYTHON_ENUM_START(PtJustify);
PYTHON_ENUM_ELEMENT(PtJustify, kCenter, plDynamicTextMap::kCenter);
PYTHON_ENUM_ELEMENT(PtJustify, kLeftJustify, plDynamicTextMap::kLeftJustify);
PYTHON_ENUM_ELEMENT(PtJustify, kRightJustify, plDynamicTextMap::kRightJustify);
PYTHON_ENUM_END(m, PtJustify);
}