== Python Space Handlers ==
authorWillian Padovani Germano <wpgermano@gmail.com>
Tue, 9 Dec 2008 00:18:30 +0000 (00:18 +0000)
committerWillian Padovani Germano <wpgermano@gmail.com>
Tue, 9 Dec 2008 00:18:30 +0000 (00:18 +0000)
- 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.

source/blender/makesdna/DNA_scriptlink_types.h
source/blender/python/BPY_interface.c
source/blender/python/api2_2x/Blender.c
source/blender/python/api2_2x/doc/API_related.py
source/blender/src/header_view3d.c
source/blender/src/space.c

index 95e20dd004d864984007d8bca0284b642e875dd0..9b50eb91a2060c2b77b1d8eee377c763cc852485 100644 (file)
@@ -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
index 331f72021f27fa2627f89bdacb85c1b90d44eed9..ec81de1f5e89c695c6369a09f74473dcc403261b 100644 (file)
@@ -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 );
index 47e7bcb2007c68f4a0c18971cf8dcf5f79add7fd..d09506f731b751329d3f4296cb863a346fc3e665 100644 (file)
@@ -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);
        }
index dcd2bdd1e603a92d4594a2a3e85af0a8ce1d2618..c5b0aafe9f0dd349606fe2486328cdb8c8de048b 100644 (file)
@@ -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)}:
index e2caf97df051342d8224b01d6a7e38a08a8c7dad..60c5854f1a5db8a49c75b5148b6c5061a5e282ee 100644 (file)
@@ -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);
index b6221c2f84b5926138c62db0b51b681836bb3fb7..e34624a25fecee7f03c4a14365d171a580a2979b 100644 (file)
@@ -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);