This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/python/api2_2x/Draw.c
Willian Padovani Germano 1e891f844a * Added submodule Window, including FileSelector and ImageSelector:
Most of the code comes from bpython/intern/opy_window.c, but two
    new functions were added, to access the file and image selector
    windows in Blender.

* Added submodules Draw (gui) and BGL (OpenGL wrapper):
    The code comes from bpython/intern/opy_draw.c, with minor changes
    to integrate it in the new implementation.

* Made changes to Camera, Lamp and Image submodules:
    The implementation was improved. These files should be good
    starting points for interested new coders to look at, now.

* Renamed interface.[ch] to EXPP_interface.[ch] to avoid conflict:
    There is another interface.h file in source/blender/include.
2003-05-08 03:06:46 +00:00

742 lines
18 KiB
C

/*
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* 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 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Willian P. Germano
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
/* This file is the Blender.Draw part of opy_draw.c, from the old
* bpython/intern dir, with minor changes to adapt it to the new Python
* implementation. Non-trivial original comments are marked with an
* @ symbol at their beginning. */
#include "Draw.h"
static void Button_dealloc(PyObject *self)
{
Button *but= (Button*) self;
if(but->type==3) MEM_freeN(but->val.asstr);
PyMem_DEL(self);
}
static PyObject *Button_getattr(PyObject *self, char *name)
{
Button *but= (Button*) self;
if(strcmp(name, "val") == 0) {
if (but->type==1)
return Py_BuildValue("i", but->val.asint);
else if (but->type==2)
return Py_BuildValue("f", but->val.asfloat);
else if (but->type==3)
return Py_BuildValue("s", but->val.asstr);
}
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
}
static int Button_setattr(PyObject *self, char *name, PyObject *v)
{
Button *but= (Button*) self;
if(strcmp(name, "val") == 0) {
if (but->type==1)
PyArg_Parse(v, "i", &but->val.asint);
else if (but->type==2)
PyArg_Parse(v, "f", &but->val.asfloat);
else if (but->type==3) {
char *newstr;
PyArg_Parse(v, "s", &newstr);
strncpy(but->val.asstr, newstr, but->slen);
}
} else {
PyErr_SetString(PyExc_AttributeError, name);
return -1;
}
return 0;
}
static PyObject *Button_repr(PyObject *self)
{
return PyObject_Repr(Button_getattr(self, "val"));
}
static Button *newbutton (void)
{
Button *but= (Button *) PyObject_NEW(Button, &Button_Type);
return but;
}
/* GUI interface routines */
static void exit_pydraw(SpaceText *st)
{
scrarea_queue_redraw(st->area);
if (st) {
Py_XDECREF((PyObject *) st->py_draw);
Py_XDECREF((PyObject *) st->py_event);
Py_XDECREF((PyObject *) st->py_button);
st->py_draw= st->py_event= st->py_button= NULL;
}
}
static void exec_callback(SpaceText *st, PyObject *callback, PyObject *args)
{
PyObject *result= PyEval_CallObject(callback, args);
if (result==NULL) {
st->text->compiled= NULL;
PyErr_Print();
exit_pydraw(st);
}
Py_XDECREF(result);
Py_DECREF(args);
}
/*@ the handler for drawing routines (see Register method) */
void EXPP_spacetext_do_pywin_draw(SpaceText *st)
{
uiBlock *block;
char butblock[20];
sprintf(butblock, "win %d", curarea->win);
block= uiNewBlock(&curarea->uiblocks, butblock, UI_EMBOSSX,
UI_HELV, curarea->win);
if (st->py_draw) {
glPushAttrib(GL_ALL_ATTRIB_BITS);
exec_callback(st, st->py_draw, Py_BuildValue("()"));
glPopAttrib();
} else {
glClearColor(0.4375, 0.4375, 0.4375, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
uiDrawBlock(block);
curarea->win_swap= WIN_BACK_OK;
}
/*@ the handler for button event routines (see Register method) */
static void spacetext_do_pywin_buttons(SpaceText *st, unsigned short event)
{
if (st->py_button) {
exec_callback(st, st->py_button, Py_BuildValue("(i)", event));
}
}
/*@ calls the generic event handling methods registered with Register */
void EXPP_spacetext_do_pywin_event(SpaceText *st, unsigned short event, short val)
{
if (event==QKEY && G.qual & (LR_ALTKEY|LR_CTRLKEY|LR_SHIFTKEY)) {
exit_pydraw(st);
return;
}
if (val) {
if (uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
if (event==UI_BUT_EVENT) {
spacetext_do_pywin_buttons(st, val);
}
}
if (st->py_event) {
exec_callback(st, st->py_event, Py_BuildValue("(ii)", event, val));
}
}
int EXPP_spacetext_is_pywin(SpaceText *st)
{
return (st->py_draw || st->py_event || st->py_button);
}
#define EXPP_TRY(x) if((!(x))) \
return EXPP_ReturnPyObjError(PyExc_AttributeError, "in module Blender.Draw")
static PyObject *Method_Exit (PyObject *self, PyObject *args)
{
SpaceText *st= curarea->spacedata.first;
#ifdef CLEAR_NAMESPACE
PyObject *d;
#endif
EXPP_TRY(PyArg_ParseTuple(args, ""));
exit_pydraw(st);
#ifdef CLEAR_NAMESPACE
d = st->py_globaldict; /* The current window's global namespace dictionary */
if (d) {
PyDict_Clear(d);
Py_DECREF(d); /* release dictionary */
}
#endif
return EXPP_incr_ret(Py_None);
}
static PyObject *Method_Register (PyObject *self, PyObject *args)
{
PyObject *newdrawc= NULL, *neweventc= NULL, *newbuttonc= NULL;
SpaceText *st= curarea->spacedata.first;
EXPP_TRY(PyArg_ParseTuple(args, "O|OO", &newdrawc,
&neweventc, &newbuttonc));
/*@This is a hack again:
* Every python script should actually do a global variable cleanup at
* the end of execution.
* For scripts registering GUI callbacks, this does not work, because
* the global namespace of the interpreter still needs to be accessed
* from the callback.
* Workaround: a text object has a flag which allows the global name
* space to be cleared at the end of the script. This flag should be
* normally set when executed with Alt-P. For a script registering with
* the GUI though, clear the flag and set it when the GUI mode is left
* (Method_Exit).
*/
/* EXPP_debug(("--- disable clear namespace")); */
st->flags &= ~ST_CLEAR_NAMESPACE;
if (!PyCallable_Check(newdrawc)) newdrawc= NULL;
if (!PyCallable_Check(neweventc)) neweventc= NULL;
if (!PyCallable_Check(newbuttonc)) newbuttonc= NULL;
if (!(newdrawc || neweventc || newbuttonc))
return EXPP_incr_ret(Py_None);
exit_pydraw(st);
Py_XINCREF(newdrawc);
Py_XINCREF(neweventc);
Py_XINCREF(newbuttonc);
st->py_draw= newdrawc;
st->py_event= neweventc;
st->py_button= newbuttonc;
scrarea_queue_redraw(st->area);
return EXPP_incr_ret(Py_None);
}
static PyObject *Method_Redraw (PyObject *self, PyObject *args)
{
int after= 0;
EXPP_TRY(PyArg_ParseTuple(args, "|i", &after));
if (after) addafterqueue(curarea->win, REDRAW, 1);
else scrarea_queue_winredraw(curarea);
return EXPP_incr_ret(Py_None);
}
static PyObject *Method_Draw (PyObject *self, PyObject *args)
{
/*@ If forced drawing is disable queue a redraw event instead */
if (EXPP_disable_force_draw) {
scrarea_queue_winredraw(curarea);
return EXPP_incr_ret(Py_None);
}
EXPP_TRY(PyArg_ParseTuple(args, ""));
scrarea_do_windraw(curarea);
screen_swapbuffers();
return EXPP_incr_ret(Py_None);
}
static PyObject *Method_Create (PyObject *self, PyObject *args)
{
Button *but;
PyObject *in;
EXPP_TRY(PyArg_ParseTuple(args, "O", &in));
but= newbutton();
if(PyFloat_Check(in)) {
but->type= 2;
but->val.asfloat= PyFloat_AsDouble(in);
} else if (PyInt_Check(in)) {
but->type= 1;
but->val.asint= PyInt_AsLong(in);
} else if (PyString_Check(in)) {
char *newstr= PyString_AsString(in);
but->type= 3;
but->slen= strlen(newstr);
but->val.asstr= MEM_mallocN(but->slen+1, "button string");
strcpy(but->val.asstr, newstr);
}
return (PyObject *) but;
}
static uiBlock *Get_uiBlock(void)
{
char butblock[32];
sprintf(butblock, "win %d", curarea->win);
return uiGetBlock(butblock, curarea);
}
static PyObject *Method_Button (PyObject *self, PyObject *args)
{
uiBlock *block;
char *name, *tip= NULL;
int event;
int x, y, w, h;
EXPP_TRY(PyArg_ParseTuple(args, "siiiii|s", &name, &event,
&x, &y, &w, &h, &tip));
block= Get_uiBlock();
if(block) uiDefBut(block, BUT, event, name, x, y, w, h,
0, 0, 0, 0, 0, tip);
return EXPP_incr_ret(Py_None);
}
static PyObject *Method_Menu (PyObject *self, PyObject *args)
{
uiBlock *block;
char *name, *tip= NULL;
int event, def;
int x, y, w, h;
Button *but;
EXPP_TRY(PyArg_ParseTuple(args, "siiiiii|s", &name, &event,
&x, &y, &w, &h, &def, &tip));
but= newbutton();
but->type= 1;
but->val.asint= def;
block= Get_uiBlock();
if(block) uiDefButI(block, MENU, event, name, x, y, w, h,
&but->val.asint, 0, 0, 0, 0, tip);
return (PyObject *) but;
}
static PyObject *Method_Toggle (PyObject *self, PyObject *args)
{
uiBlock *block;
char *name, *tip= NULL;
int event;
int x, y, w, h, def;
Button *but;
EXPP_TRY(PyArg_ParseTuple(args, "siiiiii|s", &name, &event,
&x, &y, &w, &h, &def, &tip));
but= newbutton();
but->type= 1;
but->val.asint= def;
block= Get_uiBlock();
if(block) uiDefButI(block, TOG, event, name, x, y, w, h,
&but->val.asint, 0, 0, 0, 0, tip);
return (PyObject *) but;
}
/*@DO NOT TOUCH THIS FUNCTION !
Redrawing a slider inside its own callback routine is actually forbidden
with the current toolkit architecture (button routines are not reentrant).
But it works anyway.
XXX This is condemned to be dinosource in future - it's a hack.
*/
static void py_slider_update(void *butv, void *data2_unused)
{
uiBut *but= butv;
EXPP_disable_force_draw= 1;
/*@
Disable forced drawing, otherwise the button object which
is still being used might be deleted
*/
/*@ UIfrontbuf = 0;
spacetext_do_pywin_buttons(curarea->spacedata.first, but->retval); */
g_window_redrawn = 0;
curarea->win_swap= WIN_BACK_OK;
UIfrontbuf = 1;
spacetext_do_pywin_buttons(curarea->spacedata.first, uiButGetRetVal(but));
UIfrontbuf = 0;
if (!g_window_redrawn) /*@ if Redraw already called */
M_Window_Redraw(0, Py_BuildValue("(i)", SPACE_VIEW3D));
EXPP_disable_force_draw= 0;
}
static PyObject *Method_Slider (PyObject *self, PyObject *args)
{
uiBlock *block;
char *name, *tip= NULL;
int event;
int x, y, w, h, realtime=1;
Button *but;
PyObject *mino, *maxo, *inio;
EXPP_TRY(PyArg_ParseTuple(args, "siiiiiOOO|is", &name, &event,
&x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip));
but= newbutton();
if (PyFloat_Check(inio)) {
float ini, min, max;
ini= PyFloat_AsDouble(inio);
min= PyFloat_AsDouble(mino);
max= PyFloat_AsDouble(maxo);
but->type= 2;
but->val.asfloat= ini;
block= Get_uiBlock();
if(block) {
uiBut *ubut;
ubut= uiDefButF(block, NUMSLI, event, name, x, y, w, h,
&but->val.asfloat, min, max, 0, 0, tip);
if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL);
}
}
else {
int ini, min, max;
ini= PyInt_AsLong(inio);
min= PyInt_AsLong(mino);
max= PyInt_AsLong(maxo);
but->type= 1;
but->val.asint= ini;
block= Get_uiBlock();
if(block) {
uiBut *ubut;
ubut= uiDefButI(block, NUMSLI, event, name, x, y, w, h,
&but->val.asint, min, max, 0, 0, tip);
if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL);
}
}
return (PyObject *) but;
}
static PyObject *Method_Scrollbar (PyObject *self, PyObject *args)
{
char *tip= NULL;
uiBlock *block;
int event;
int x, y, w, h, realtime=1;
Button *but;
PyObject *mino, *maxo, *inio;
float ini, min, max;
EXPP_TRY(PyArg_ParseTuple(args, "iiiiiOOO|is", &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip));
if (!PyNumber_Check(inio) || !PyNumber_Check(inio) || !PyNumber_Check(inio))
return EXPP_ReturnPyObjError (PyExc_AttributeError,
"expected numbers for initial, min, and max");
but= newbutton();
if (PyFloat_Check(inio)) but->type= 2;
else but->type= 1;
ini= PyFloat_AsDouble(inio);
min= PyFloat_AsDouble(mino);
max= PyFloat_AsDouble(maxo);
if (but->type==2) {
but->val.asfloat= ini;
block= Get_uiBlock();
if(block) {
uiBut *ubut;
ubut= uiDefButF(block, SCROLL, event, "", x, y, w, h,
&but->val.asfloat, min, max, 0, 0, tip);
if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL);
}
} else {
but->val.asint= ini;
block= Get_uiBlock();
if(block) {
uiBut *ubut;
ubut= uiDefButI(block, SCROLL, event, "", x, y, w, h,
&but->val.asint, min, max, 0, 0, tip);
if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL);
}
}
return (PyObject *) but;
}
static PyObject *Method_Number (PyObject *self, PyObject *args)
{
uiBlock *block;
char *name, *tip= NULL;
int event;
int x, y, w, h;
Button *but;
PyObject *mino, *maxo, *inio;
EXPP_TRY(PyArg_ParseTuple(args, "siiiiiOOO|s", &name, &event,
&x, &y, &w, &h, &inio, &mino, &maxo, &tip));
but= newbutton();
if (PyFloat_Check(inio)) {
float ini, min, max;
ini= PyFloat_AsDouble(inio);
min= PyFloat_AsDouble(mino);
max= PyFloat_AsDouble(maxo);
but->type= 2;
but->val.asfloat= ini;
block= Get_uiBlock();
if(block) uiDefButF(block, NUM, event, name, x, y, w, h,
&but->val.asfloat, min, max, 0, 0, tip);
} else {
int ini, min, max;
ini= PyInt_AsLong(inio);
min= PyInt_AsLong(mino);
max= PyInt_AsLong(maxo);
but->type= 1;
but->val.asint= ini;
block= Get_uiBlock();
if(block) uiDefButI(block, NUM, event, name, x, y, w, h,
&but->val.asint, min, max, 0, 0, tip);
}
return (PyObject *) but;
}
static PyObject *Method_String (PyObject *self, PyObject *args)
{
uiBlock *block;
char *name, *tip= NULL, *newstr;
int event;
int x, y, w, h, len;
Button *but;
EXPP_TRY(PyArg_ParseTuple(args, "siiiiisi|s", &name, &event,
&x, &y, &w, &h, &newstr, &len, &tip));
but= newbutton();
but->type= 3;
but->slen= len;
but->val.asstr= MEM_mallocN(len+1, "button string");
strncpy(but->val.asstr, newstr, len);
but->val.asstr[len]= 0;
block= Get_uiBlock();
if(block) uiDefBut(block, TEX, event, name, x, y, w, h,
but->val.asstr, 0, len, 0, 0, tip);
return (PyObject *) but;
}
static PyObject *Method_Text (PyObject *self, PyObject *args)
{
char *text;
EXPP_TRY(PyArg_ParseTuple(args, "s", &text));
BMF_DrawString(G.font, text);
return EXPP_incr_ret(Py_None);
}
PyObject *M_Draw_Init (void)
{
PyObject *submodule, *dict;
printf("In M_Draw_Init()\n");
submodule = Py_InitModule3("Blender.Draw", Draw_methods, Draw_doc);
dict= PyModule_GetDict(submodule);
#define EXPP_ADDCONST(x) \
PyDict_SetItemString(dict, #x, PyInt_FromLong(x))
/* So, for example:
* EXPP_ADDCONST(LEFTMOUSE) becomes
* PyDict_SetItemString(dict, "LEFTMOUSE", PyInt_FromLong(LEFTMOUSE)) */
EXPP_ADDCONST(LEFTMOUSE);
EXPP_ADDCONST(MIDDLEMOUSE);
EXPP_ADDCONST(RIGHTMOUSE);
EXPP_ADDCONST(MOUSEX);
EXPP_ADDCONST(MOUSEY);
EXPP_ADDCONST(TIMER0);
EXPP_ADDCONST(TIMER1);
EXPP_ADDCONST(TIMER2);
EXPP_ADDCONST(TIMER3);
EXPP_ADDCONST(KEYBD);
EXPP_ADDCONST(RAWKEYBD);
EXPP_ADDCONST(REDRAW);
EXPP_ADDCONST(INPUTCHANGE);
EXPP_ADDCONST(QFULL);
EXPP_ADDCONST(WINFREEZE);
EXPP_ADDCONST(WINTHAW);
EXPP_ADDCONST(WINCLOSE);
EXPP_ADDCONST(WINQUIT);
#ifndef IRISGL
EXPP_ADDCONST(Q_FIRSTTIME);
#endif
EXPP_ADDCONST(AKEY);
EXPP_ADDCONST(BKEY);
EXPP_ADDCONST(CKEY);
EXPP_ADDCONST(DKEY);
EXPP_ADDCONST(EKEY);
EXPP_ADDCONST(FKEY);
EXPP_ADDCONST(GKEY);
EXPP_ADDCONST(HKEY);
EXPP_ADDCONST(IKEY);
EXPP_ADDCONST(JKEY);
EXPP_ADDCONST(KKEY);
EXPP_ADDCONST(LKEY);
EXPP_ADDCONST(MKEY);
EXPP_ADDCONST(NKEY);
EXPP_ADDCONST(OKEY);
EXPP_ADDCONST(PKEY);
EXPP_ADDCONST(QKEY);
EXPP_ADDCONST(RKEY);
EXPP_ADDCONST(SKEY);
EXPP_ADDCONST(TKEY);
EXPP_ADDCONST(UKEY);
EXPP_ADDCONST(VKEY);
EXPP_ADDCONST(WKEY);
EXPP_ADDCONST(XKEY);
EXPP_ADDCONST(YKEY);
EXPP_ADDCONST(ZKEY);
EXPP_ADDCONST(ZEROKEY);
EXPP_ADDCONST(ONEKEY);
EXPP_ADDCONST(TWOKEY);
EXPP_ADDCONST(THREEKEY);
EXPP_ADDCONST(FOURKEY);
EXPP_ADDCONST(FIVEKEY);
EXPP_ADDCONST(SIXKEY);
EXPP_ADDCONST(SEVENKEY);
EXPP_ADDCONST(EIGHTKEY);
EXPP_ADDCONST(NINEKEY);
EXPP_ADDCONST(CAPSLOCKKEY);
EXPP_ADDCONST(LEFTCTRLKEY);
EXPP_ADDCONST(LEFTALTKEY);
EXPP_ADDCONST(RIGHTALTKEY);
EXPP_ADDCONST(RIGHTCTRLKEY);
EXPP_ADDCONST(RIGHTSHIFTKEY);
EXPP_ADDCONST(LEFTSHIFTKEY);
EXPP_ADDCONST(ESCKEY);
EXPP_ADDCONST(TABKEY);
EXPP_ADDCONST(RETKEY);
EXPP_ADDCONST(SPACEKEY);
EXPP_ADDCONST(LINEFEEDKEY);
EXPP_ADDCONST(BACKSPACEKEY);
EXPP_ADDCONST(DELKEY);
EXPP_ADDCONST(SEMICOLONKEY);
EXPP_ADDCONST(PERIODKEY);
EXPP_ADDCONST(COMMAKEY);
EXPP_ADDCONST(QUOTEKEY);
EXPP_ADDCONST(ACCENTGRAVEKEY);
EXPP_ADDCONST(MINUSKEY);
EXPP_ADDCONST(SLASHKEY);
EXPP_ADDCONST(BACKSLASHKEY);
EXPP_ADDCONST(EQUALKEY);
EXPP_ADDCONST(LEFTBRACKETKEY);
EXPP_ADDCONST(RIGHTBRACKETKEY);
EXPP_ADDCONST(LEFTARROWKEY);
EXPP_ADDCONST(DOWNARROWKEY);
EXPP_ADDCONST(RIGHTARROWKEY);
EXPP_ADDCONST(UPARROWKEY);
EXPP_ADDCONST(PAD2);
EXPP_ADDCONST(PAD4);
EXPP_ADDCONST(PAD6);
EXPP_ADDCONST(PAD8);
EXPP_ADDCONST(PAD1);
EXPP_ADDCONST(PAD3);
EXPP_ADDCONST(PAD5);
EXPP_ADDCONST(PAD7);
EXPP_ADDCONST(PAD9);
EXPP_ADDCONST(PADPERIOD);
EXPP_ADDCONST(PADSLASHKEY);
EXPP_ADDCONST(PADASTERKEY);
EXPP_ADDCONST(PAD0);
EXPP_ADDCONST(PADMINUS);
EXPP_ADDCONST(PADENTER);
EXPP_ADDCONST(PADPLUSKEY);
EXPP_ADDCONST(F1KEY);
EXPP_ADDCONST(F2KEY);
EXPP_ADDCONST(F3KEY);
EXPP_ADDCONST(F4KEY);
EXPP_ADDCONST(F5KEY);
EXPP_ADDCONST(F6KEY);
EXPP_ADDCONST(F7KEY);
EXPP_ADDCONST(F8KEY);
EXPP_ADDCONST(F9KEY);
EXPP_ADDCONST(F10KEY);
EXPP_ADDCONST(F11KEY);
EXPP_ADDCONST(F12KEY);
EXPP_ADDCONST(PAUSEKEY);
EXPP_ADDCONST(INSERTKEY);
EXPP_ADDCONST(HOMEKEY);
EXPP_ADDCONST(PAGEUPKEY);
EXPP_ADDCONST(PAGEDOWNKEY);
EXPP_ADDCONST(ENDKEY);
return submodule;
}