11
$\begingroup$

I am considering writing a python script which, once run by the Blender internal interpreter, would stay in memory, listening to a socket and reacting to messages.

As an example I would use this to preview the currently edited object in an external engine, without having to export it to the filesystem then loading it in the engine.

How can I design a plugin to have such a behavior?

Note that this question :

  • Only targets the "staying in memory / listening to a socket" part with respect to Blender inner workings, not the scene crawling/exporting, messaging details etc.
  • Does not make reference to the "blender --background" mode of operation. To the contrary I would like this to work in the usual, UI-driven interface.

I am also aware of the Blender Command Port patch, but it does not seem like it has ever been merged (and I would like this to work with a "vanilla" Blender).

$\endgroup$
  • $\begingroup$ Could you define stay active more clearly? $\endgroup$ – ideasman42 Feb 8 '16 at 3:05
  • $\begingroup$ @ideasman42 of course. By "stay active" I mean a behavior similar to a unix daemon: "a long-running background process that answers requests for services" (source]. I'm not sure I can define this in Blender API terms since that's actually what I seek an answer for. $\endgroup$ – oparisy Feb 8 '16 at 7:00
  • $\begingroup$ I edited the question title for, I hope, more clarity. $\endgroup$ – oparisy Feb 8 '16 at 7:02
  • $\begingroup$ I found a related question afterwards: blender.stackexchange.com/questions/26284/…. This describes appending to bpy.app.handlers.frame_change_pre, and using threading to avoid freezing the GUI (see also blender.stackexchange.com/questions/2428/…). $\endgroup$ – oparisy Feb 8 '16 at 7:18
  • 2
    $\begingroup$ A modal operator seems to be the proper way to handle this robustly: blender.stackexchange.com/questions/442/… $\endgroup$ – oparisy Feb 9 '16 at 22:07
2
$\begingroup$

I've used the following for a quick and dirty solution using the update on animation trick:

import bpy, mathutils, socket

TCP_IP = '192.168.1.121'
TCP_PORT = 8888
BUFFER_SIZE = 1024

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))

def updateCubeFromSocket(args):
    data = s.recv(BUFFER_SIZE).decode('utf-8')
    #do stuff

bpy.app.handlers.frame_change_pre.append(updateCubeFromSocket)

Adding in threading isn't too much harder, something like this should work too:

import time, bpy, threading
def thread_update():
    TCP_IP = '192.168.1.121'
    TCP_PORT = 8888
    BUFFER_SIZE = 1024

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((TCP_IP, TCP_PORT))

    while(True):
        data = s.recv(BUFFER_SIZE).decode('utf-8')
        #do stuff
        time.sleep(0.1) #update rate in seconds

thread = threading.Thread(target=thread_update)
thread.start()
| improve this answer | |
$\endgroup$
3
$\begingroup$

Since neither Blender nor Python deal with threading very well.. one option is to use async-IO to handle the network socket, and hook bpy.app.handlers.scene_update_post to have your script called periodically.

When your handler is called, you would both process async events on the network sockets, and perform whatever operations were requested by the network. Each interation of your handler should run for a relatively short time, or you'll block the UI.

| improve this answer | |
$\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.