== Python Space Handlers ==

- Old feature request: now space handlers can report release events, too. For that a new space handler type was added, here's the header for it:

# SPACEHANDLER.VIEW3D.EVENT.ALL

These scripts report both "presses and releases". For release events, Blender.eventValue is zero and Blender.link == Blender.SpaceHandlers.VIEW3D_EVENT_RELEASE. Check the API_related bpy doc for more info.

- Bug fix: left mouse clicks could be reported twice.

Important: for both the feature and the fix, to make the code nicer and to let space handlers become available in more situations, I moved the check for space handlers in space.c. Now it happens before checks for grease pencil, sculpt and left/right mouse button swapping. If this causes any problem (it shouldn't), please report.

PS: Thanks to Steven Truppe, who asked for this and even sent me a patch, but to preserve compatibility with existing event space handler scripts I did things in a different way.
This commit is contained in:
Willian Padovani Germano 2008-12-09 00:18:30 +00:00
parent 2746034295
commit caf58fe4b2
6 changed files with 73 additions and 38 deletions

@ -65,10 +65,12 @@ typedef struct ScriptLink {
/* these are special scriptlinks that can be assigned to
* a given space in a given ScrArea to:
* - (EVENT type) handle events sent to that space;
* - (DRAW type) draw on the space after its own drawing function finishes
* - (EVENT_ALL type): handle release events, too;
* - (DRAW type) draw on the space after its own drawing function finishes.
*/
#define SPACEHANDLER_VIEW3D_EVENT 1
#define SPACEHANDLER_VIEW3D_DRAW 2
#define SPACEHANDLER_VIEW3D_DRAW 1
#define SPACEHANDLER_VIEW3D_EVENT 2
#define SPACEHANDLER_VIEW3D_EVENT_ALL 3
#ifdef __cplusplus

@ -2403,7 +2403,7 @@ int BPY_is_spacehandler(Text *text, char spacetype)
char *line = tline->line;
/* Expected format: # SPACEHANDLER.SPACE.TYPE
* Ex: # SPACEHANDLER.VIEW3D.DRAW
* Exs: # SPACEHANDLER.VIEW3D.DRAW
* The actual checks are forgiving, so slight variations also work. */
if (line && line[0] == '#' && strstr(line, "HANDLER")) {
line++; /* skip '#' */
@ -2411,11 +2411,19 @@ int BPY_is_spacehandler(Text *text, char spacetype)
/* only done for 3D View right now, trivial to add for others: */
switch (spacetype) {
case SPACE_VIEW3D:
if (strstr(line, "3D")) { /* VIEW3D, 3DVIEW */
line = strstr(line, "3D"); /* VIEW3D, 3DVIEW */
if (line) {
if (strstr(line, "DRAW")) type = SPACEHANDLER_VIEW3D_DRAW;
else if (strstr(line, "EVENT")) type = SPACEHANDLER_VIEW3D_EVENT;
else {
line = strstr(line, "EVENT");
if (line) {
if (strstr(line, "ALL")) {
type = SPACEHANDLER_VIEW3D_EVENT_ALL;
} else { type = SPACEHANDLER_VIEW3D_EVENT; }
}
}
}
break;
break;
}
}
}
@ -2464,7 +2472,6 @@ int BPY_add_spacehandler(Text *text, ScrArea *sa, char spacetype)
if (handlertype) {
ScriptLink *slink = &sa->scriptlink;
void *stmp, *ftmp;
unsigned short space_event = SPACEHANDLER_VIEW3D_EVENT;
/* extend slink */
@ -2484,17 +2491,8 @@ int BPY_add_spacehandler(Text *text, ScrArea *sa, char spacetype)
MEM_freeN(ftmp);
}
switch (spacetype) {
case SPACE_VIEW3D:
if (handlertype == 1) space_event = SPACEHANDLER_VIEW3D_EVENT;
else space_event = SPACEHANDLER_VIEW3D_DRAW;
break;
default:
break;
}
slink->scripts[slink->totscript] = (ID *)text;
slink->flag[slink->totscript]= space_event;
slink->flag[slink->totscript]= handlertype;
slink->totscript++;
slink->actscript = slink->totscript;
@ -2508,6 +2506,7 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event,
{
ScriptLink *scriptlink;
int retval = 0;
short slink_event, spacehandlers_match;
PyGILState_STATE gilstate;
if (!sa || !(G.f & G_DOSCRIPTLINKS)) return 0;
@ -2549,7 +2548,16 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event,
EXPP_dict_set_item_str(g_blenderdict, "eventValue", PyInt_FromLong(eventValue));
/* now run all assigned space handlers for this space and space_event */
for( index = 0; index < scriptlink->totscript; index++ ) {
spacehandlers_match = 0;
slink_event = scriptlink->flag[index];
if( slink_event == space_event )
spacehandlers_match = 1;
else if( ( space_event == SPACEHANDLER_VIEW3D_EVENT ) &&
( slink_event == SPACEHANDLER_VIEW3D_EVENT_ALL ) )
spacehandlers_match = 1;
/* for DRAW handlers: */
if (event == 0) {
glPushAttrib(GL_ALL_ATTRIB_BITS);
@ -2558,8 +2566,8 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event,
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
}
if( ( scriptlink->flag[index] == space_event ) &&
if( spacehandlers_match &&
( scriptlink->scripts[index] != NULL ) ) {
dict = CreateGlobalDictionary();
ret = RunPython( ( Text * ) scriptlink->scripts[index], dict );

@ -1047,8 +1047,11 @@ void M_Blender_Init(void)
if (SpaceHandlers) {
BPy_constant *d = (BPy_constant *)SpaceHandlers;
PyConstant_Insert(d,"VIEW3D_EVENT",PyInt_FromLong(SPACEHANDLER_VIEW3D_EVENT));
/* EVENT_ALL are reported as EVENT on key presses
* and EVENT_RELEASE on key releases */
PyConstant_Insert(d,"VIEW3D_DRAW", PyInt_FromLong(SPACEHANDLER_VIEW3D_DRAW));
PyConstant_Insert(d,"VIEW3D_EVENT",PyInt_FromLong(SPACEHANDLER_VIEW3D_EVENT));
PyConstant_Insert(d,"VIEW3D_EVENT_RELEASE",PyInt_FromLong(SPACEHANDLER_VIEW3D_EVENT_ALL));
PyModule_AddObject(module, "SpaceHandlers", SpaceHandlers);
}

@ -184,11 +184,11 @@ Introduction:
Space Handler script links:
---------------------------
This is a new kind of script linked to spaces in a given window. Right now
only the 3D View has the necessary hooks, but the plan is to add access to
other types, too. Just to clarify naming conventions: in Blender, a screen
is partitioned in windows (also called areas) and each window can show any
space. Spaces are: 3D View, Text Editor, Scripts, Buttons, User Preferences,
These are scripts linked to spaces in a given window. Right now
only the 3D View has the necessary hooks. Just to clarify naming
conventions: in Blender, a screen is partitioned in windows (also
called areas) and each window can show any space.
Spaces are: 3D View, Text Editor, Scripts, Buttons, User Preferences,
Oops, etc.
Space handlers are texts in the Text Editor, like other script links, but they
@ -196,12 +196,16 @@ Introduction:
text file}} must inform:
1. that they are space handlers;
2. the space they belong to;
3. whether they are EVENT or DRAW handlers.
3. whether they are EVENT, EVENT_RELEASE (EVENT ones reporting key release events) or DRAW handlers.
Example header for a 3D View EVENT handler::
# SPACEHANDLER.VIEW3D.EVENT
Example header for a 3D View EVENT handler that also receives release events::
# SPACEHANDLER.VIEW3D.EVENT.ALL
Example header for a 3D View DRAW handler::
# SPACEHANDLER.VIEW3D.DRAW
@ -216,6 +220,10 @@ Introduction:
- process it (the script must set Blender.event to None then);
- ignore it.
EVENT ALL space handlers (header: # SPACEHANDLER.VIEW3D.EVENT.ALL) are executed
both for key presses (Blender.event = Blender.SpaceHandlers.VIEW3D_EVENT) and
for key releases (Blender.event = Blender.SpaceHandlers.VIEW3D_EVENT_RELEASE).
Setting C{Blender.event = None} tells Blender not to go on processing itself
the event, because it was grabbed by the script.
@ -248,7 +256,7 @@ Introduction:
- B{bylink} is the same: True if the script is running as a script link;
- B{link}: integer from the L{Blender}.SpaceHandlers constant dictionary,
tells what space this handler belongs to and the handler's type
(EVENT, DRAW);
(EVENT, EVENT_RELEASE, DRAW);
- B{event}:
- EVENT handlers: an input event (check keys and mouse events in
L{Draw}) to be processed or ignored;
@ -258,6 +266,7 @@ Introduction:
presses (since we don't pass releases) as 1 and mouse movements
(Draw.MOUSE.X and Draw.MOUSE.Y) as the current x or y coordinate,
for example;
- EVENT_RELEASE handlers (EVENT handlers executed during key release events): 0;
- DRAW handlers: 0 always.
B{Guidelines (important)}:

@ -517,6 +517,8 @@ static uiBlock *view3d_view_spacehandlers(void *arg_unused)
if (handlertype == SPACEHANDLER_VIEW3D_EVENT)
BLI_strncpy(menustr, "Event: ", 8);
else if (handlertype == SPACEHANDLER_VIEW3D_EVENT_ALL)
BLI_strncpy(menustr, "Event+: ", 8);
else
BLI_strncpy(menustr, "Draw: ", 8);
BLI_strncpy(menustr+7, text->id.name+2, 22);

@ -1247,18 +1247,19 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0;
if(event==UI_BUT_EVENT) do_butspace(val); /* temporal, view3d deserves own queue? */
#ifndef DISABLE_PYTHON
/* run any view3d event handler script links */
if(sa->scriptlink.totscript) {
if(BPY_do_spacehandlers(sa, event, val, SPACEHANDLER_VIEW3D_EVENT))
return; /* return if event was processed (swallowed) by handler(s) */
}
#endif
/* - we consider manipulator a button, defaulting to leftmouse
* - grease-pencil also defaults to leftmouse
*/
if(event==LEFTMOUSE) {
#ifndef DISABLE_PYTHON
/* run any view3d event handler script links */
if (sa->scriptlink.totscript) {
if (BPY_do_spacehandlers(sa, event, val, SPACEHANDLER_VIEW3D_EVENT))
return; /* return if event was processed (swallowed) by handler(s) */
}
#endif
if(gpencil_do_paint(sa, L_MOUSE)) return;
if(BIF_do_manipulator(sa)) return;
}
@ -2955,7 +2956,17 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
}
}
#ifndef DISABLE_PYTHON
else { /* val= 0 */
/* run any view3d release event handler script links */
if(sa->scriptlink.totscript) {
if(BPY_do_spacehandlers(sa, event, 0, SPACEHANDLER_VIEW3D_EVENT_ALL))
return; /* return if event was processed (swallowed) by handler(s) */
}
}
#endif
if(doredraw) {
scrarea_queue_winredraw(curarea);
scrarea_queue_headredraw(curarea);