1
$\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$
  • $\begingroup$ Thanks. It works, both threading and modal timer operator. $\endgroup$ – Hugh May 1 '16 at 21:59
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$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.