== 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 /* these are special scriptlinks that can be assigned to
* a given space in a given ScrArea to: * a given space in a given ScrArea to:
* - (EVENT type) handle events sent to that space; * - (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 1
#define SPACEHANDLER_VIEW3D_DRAW 2 #define SPACEHANDLER_VIEW3D_EVENT 2
#define SPACEHANDLER_VIEW3D_EVENT_ALL 3
#ifdef __cplusplus #ifdef __cplusplus

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

@ -1047,8 +1047,11 @@ void M_Blender_Init(void)
if (SpaceHandlers) { if (SpaceHandlers) {
BPy_constant *d = (BPy_constant *)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_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); PyModule_AddObject(module, "SpaceHandlers", SpaceHandlers);
} }

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

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

@ -1248,10 +1248,6 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if(event==UI_BUT_EVENT) do_butspace(val); /* temporal, view3d deserves own queue? */ if(event==UI_BUT_EVENT) do_butspace(val); /* temporal, view3d deserves own queue? */
/* - we consider manipulator a button, defaulting to leftmouse
* - grease-pencil also defaults to leftmouse
*/
if(event==LEFTMOUSE) {
#ifndef DISABLE_PYTHON #ifndef DISABLE_PYTHON
/* run any view3d event handler script links */ /* run any view3d event handler script links */
if(sa->scriptlink.totscript) { if(sa->scriptlink.totscript) {
@ -1259,6 +1255,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
return; /* return if event was processed (swallowed) by handler(s) */ return; /* return if event was processed (swallowed) by handler(s) */
} }
#endif #endif
/* - we consider manipulator a button, defaulting to leftmouse
* - grease-pencil also defaults to leftmouse
*/
if(event==LEFTMOUSE) {
if(gpencil_do_paint(sa, L_MOUSE)) return; if(gpencil_do_paint(sa, L_MOUSE)) return;
if(BIF_do_manipulator(sa)) return; if(BIF_do_manipulator(sa)) return;
} }
@ -2956,6 +2957,16 @@ 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) { if(doredraw) {
scrarea_queue_winredraw(curarea); scrarea_queue_winredraw(curarea);
scrarea_queue_headredraw(curarea); scrarea_queue_headredraw(curarea);