0
$\begingroup$

I'm trying to create a simulation using blender python.

Here's a sample template that creates a cube and bounces it back and forth on X axis:

import bpy


class ModalOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"
    
    x_pos=0
    x_limit=2
    direction_forward=True
    _timer=None

    def __init__(self):
        print("Start")

    def __del__(self):
        print("End")
        
    def cancel(self, context):
        wm = context.window_manager
        wm.event_timer_remove(self._timer)

    def execute(self, context):

        print(context.object.location.x)
        
        wm = context.window_manager        
        self._timer = wm.event_timer_add(0.1, window=context.window)
        wm.modal_handler_add(self)
        
        return {'FINISHED'}

    def modal(self, context, event):

        if event.type in {'RIGHTMOUSE', 'ESC'}:  # Cancel
            self.cancel(context)
            return {'CANCELLED'}
        elif event.type == 'TIMER':
            if self.direction_forward==True:
                self.x_pos=self.x_pos+0.1
                
                if self.x_pos>=self.x_limit:
                    self.direction_forward=False
            else:
                self.x_pos=self.x_pos-0.1
                
                if self.x_pos<=-self.x_limit:
                    self.direction_forward=True
                    
            print(self.x_pos)
            self.cube_object.location.x=self.x_pos

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        
        cube_name="simcube"
        
        # find object by name to reuse if possible
        self.cube_object = bpy.data.objects.get(cube_name)
        if self.cube_object is None:
        
            if self.cube_object==None:
                bpy.ops.mesh.primitive_cube_add(size=2.0, 
                    enter_editmode=False, 
                    location=( self.x_pos, 0, 0))
                                
            self.cube_object=bpy.context.view_layer.objects.active
            self.cube_object.name=cube_name

        self.execute(context)


        return {'RUNNING_MODAL'}


bpy.utils.register_class(ModalOperator)

# test call
bpy.ops.object.modal_operator('INVOKE_DEFAULT')

Everything works great - the cube moves back and forth and it responds to ESC keypress.

My problem is how do I make it so it's not timer based - when doing fluid or smoke baking the number of frames evaluated in the simulation is not based on a timer refresh rate - it's based on how fast your CPU can run the simulation data.

I would like my execute loop to be able to run a tight loop and respond to keypress events without a timer (higher simulation frame rate).

For example - each loop of the simulation it checks for keypress - not waiting for timer event.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.