script events : a versatile modal and a logger for your scripts/addons

this addon can be useful for script that need some real time features. it can logs keyboard and mouse events, frame change during animation renders (timer event), it can change the speed of it while running (there’s a trick), it cares about instance multiplication (only one running at a time even if you try to start it again and again).

there’s also some code to use a script event logger. and a popup that appear whatever the context is (can be called from global, the console or a function for example).

http://wiki.blender.org/uploads/9/9d/Script_events3.png

WIKI

bpy.ops.wm.modal_start()
bpy.ops.wm.modal_stop()
bpy.context.window_manager.modal.status = True
bpy.context.window_manager.modal.timer = True
bpy.context.window_manager.modal.timer_refresh = 0.2
bpy.context.window_manager.modal.hud = False
bpy.context.window_manager.modal.func = ‘myModalFunc(self,context,spam)’
(…)
all realtime and no crash (aha just kidding : no crashes when your script is properly connected with it :slight_smile: )

http://wiki.blender.org/uploads/2/26/Script_events2.png

below are some info to use it from your own scripts/addons :

the modal function to call must be available in bpy, so it should resides in a bpy class.
maybe there’s a way with global namespace but I don’t know, if so please let me know.


import blf
import time

class myPanel(bpt.types.panel) :
    [...]
    draw(self,context) :
        [...]
        row.operator('<b>wm.modal_start</b>', icon = 'GHOST_ENABLED')
        row.operator('<b>wm.modal_stop</b>', icon = 'GHOST_ENABLED')
        row.operator('<b>wm.modal'</b>, text = 'toggle')

class myClass(bpy.types.PropertyGroup) :
    
    myClassValue = bpy.props.StringProperty()

    # my modal function that will be called from the modal
    def <b>modalAction</b>(self,self_modal,context,event) :
        print(event.type)

    # my hud
    def <b>hud</b>(self, <b>self_modal</b>, context) :

        x = self.myClassValue

        if type(<b>self_modal.event</b>) != str :

            # event fields are available
            <b>evt = self_modal.event</b>
            #if evt.type......

def myScriptInit() :

    modal = bpy.context.window_manager.modal
    modal.status = False

    # FUNCTION CALLS
<b>    modal.func = 'bpy.context.scene.myclass.modalAction(self,context,event)'
    modal.hudfunc = 'bpy.context.scene.myclass.hud'</b>

    modal.timer = True
    modal.timer_refresh = 0.33
    gvar = bpy.context.window_manager.global_var
    gvar.popupreport.loglevel = 0
    gvar.popupreport.loglevel = 0

def register() :
    bpy.utils.register_class(myClass)  
    bpy.types.Scene.myclass = bpy.props.PointerProperty(type=myClass)
    myScriptInit()

also you can hook a function that resides in another operator :
bpy.types.OBJECT_PT_hello.modalAction(self,context,event)

also in the addon init file you can have a look to the default_hud() and the modal_example() functions that are called by default by the addon.

hope this can help. beware the hud function call, the punishment is immediate if you write something wrong :slight_smile:

hope this can help. i’ll publish a real example soon.

updated :
no crash anymore when the addon was enabled by default,
no crash anymore when selecting ‘load default factory’
test with 2.5.8a

http://projects.blender.org/tracker/download.php/153/467/28022/17150/script_events_v02.zip

Nice … I putted

import script_events
into init.py of blended_cities

==> only one addon has to be activated the city :wink:

@ATOM
I used “Blend Cities” where Vector*Matrix is reversed and Vector *= Matrix replaced by Vector = Matrix * Vector …
(it just build 3 high objects out of planes … yet)

Do you have a working BLEND file example using the frameChange event?

sorry for the delay Atom :confused:
the blended cities draft uses it from the BlendedCIties class, in the core/main file
also the chess addon io_pgn.

your function needs to reside in a class that is registered somewhere in bpy :

class MyClass( propertygrouptype )
    [..]
    def frameChange(self,context,event,verbose=1):
        frameCurrent = context.scene.frame_current
        print (str(frameCurrent))

register() :
    [..]
    bpy.type.Scene.myclass = bpy.pointerproperty(type=MyClass)

(mispelled code but you get the idea)

so you can configure

bpy.context.scene.myclass.frameChange(self,context,event,verbose=1)

as the ‘called’ function.

I just tried this code you posted and I get errors in traceback.py which is not even part of my script.


import bpy

class MyClass( propertygrouptype ):
    def frameChange(self,context,event,verbose=1):
        frameCurrent = context.scene.frame_current
        print (str(frameCurrent))

def register() :
    bpy.type.Scene.MyClass = bpy.pointerproperty(type=MyClass)

Can you post the code working without spelling errors? I am still interested to see if this version of a framechange can hold up to the task of animation for external render systems like Yafaray and so on.

I wrote this code in a text block starting from the post above :

import bpy

class MyClass(bpy.types.PropertyGroup):
    def frameChange(self,context,event,verbose=1):
        frameCurrent = context.scene.frame_current
        print (str(frameCurrent))

def register() :
    bpy.utils.register_class(MyClass)
    bpy.types.Scene.MyClass = bpy.props.PointerProperty(type=MyClass)
    
register()

alt-P then :

http://thumbnails29.imagebam.com/14991/a97401149902005.jpg

watch out, you need to remove self from arguments :
so :
frameChange(self,context,event,verbose=1)
gives :
frameChange(context,event,verbose=1) in the tool

and if you hook your class to:
bpy.types.Scene.MyClass = bpy.props.PointerProperty(type=MyClass)
using context path it gives :
bpy.context.scene.MyClass

so :

bpy.context.scene.MyClass.frameChange(context, event, verbose=1)
or
bpy.context.scene.MyClass.frameChange(context, event)

works.
and if not… please let me know… maybe I mismatch release version… (mine is 0.2)

watch out, you need to remove self from arguments :
so :
frameChange(self,context,event,verbose=1)
gives :
frameChange(context,event,verbose=1) in the tool


or you need to
class MyClass(bpy.types.PropertyGroup):
def frameChange(self,selfmodal,context,event,verbose=1):
[…]

and type :
bpy.context.scene.MyClass.frameChange(self,selfmodal,context, event)
in the tool or in bpy.context.window_manager.modal.func

it’s a bit tricky… I’ll try to make it more simple in next version. also I replaced “your function is buggy” by “wrong path or buggy function.”… :wink: