2
$\begingroup$

I am doing a POC using blender 2.77a and I am trying to display data continuously in 3DVIEW generated from python script.

When I try to modify the text object by editing it with the line command bpy.ops.object.editmode_toggle() I get an error "Context is incorrect".

I tried to launch the script from space bar but same error appeared. Which part of the context field is missing or wrong and how can I override the context to make it right for blender?

import bpy
import time
import numpy as np
from queue import Queue
from threading import Thread


def main(context):
    for ob in context.scene.objects:
        print(ob)


class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):

        # Produce data
         def producer(out_q):
            while True:
                data=np.random.rand(1)
                print(data)
                out_q.put(str(data))
                time.sleep(3)

         # get data
         def consumer(in_q):
            while True:

                data = in_q.get()
                print(data)

                #Replace the old text by "data" in 3DVIEW (Text object)
                bpy.context.scene.objects.active=bpy.data.objects["Text"]
                bpy.ops.object.editmode_toggle()
                bpy.ops.font.delete()
                newText=str(data)
                bpy.ops.font.text_insert(text=newText)
                bpy.ops.object.editmode_toggle()

         def start():

           # Create the shared queue and launch both threads
            q = Queue()
            t1 = Thread(target=consumer, args=(q,))
            t2 = Thread(target=producer, args=(q,))
            t1.start()
            t2.start()

         start()
         return {'FINISHED'}


def register():
    bpy.utils.register_class(SimpleOperator)


def unregister():
    bpy.utils.unregister_class(SimpleOperator)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.simple_operator()
$\endgroup$
1
  • $\begingroup$ Thanks. It works, both threading and modal timer operator. $\endgroup$
    – Hugh
    Commented May 1, 2016 at 21:59

1 Answer 1

2
$\begingroup$

Firstly threading isn't well supported. the context error would be from the threads not having a context. You may be able to pass the context from execute(self, context) to the threads and override the context when calling the operators.

I would suggest that a better option would be to use a modal operator. Based on the modal timer operator template included with blender -

import bpy
import numpy as np

class ModalTimerOperator(bpy.types.Operator):
    """Operator which runs its self from a timer"""
    bl_idname = "wm.modal_timer_operator"
    bl_label = "Modal Timer Operator"

    _timer = None

    def modal(self, context, event):
        if event.type in {'RIGHTMOUSE', 'ESC'}:
            self.cancel(context)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            txt = str(np.random.rand(1))
            context.scene.objects['Text'].data.body = txt

        return {'PASS_THROUGH'}

    def execute(self, context):
        wm = context.window_manager
        self._timer = wm.event_timer_add(3.0, context.window)
        wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def cancel(self, context):
        wm = context.window_manager
        wm.event_timer_remove(self._timer)


def register():
    bpy.utils.register_class(ModalTimerOperator)


def unregister():
    bpy.utils.unregister_class(ModalTimerOperator)


if __name__ == "__main__":
    register()
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .