1- import os
21from collections import namedtuple
32from contextlib import AbstractContextManager
43import json
54import socket
6- import sys
75import threading
86from queue import Queue , Empty
97
108import bpy
11- from bpy .types import Scene
129from bpy .props import BoolProperty
1310from bpy .props import FloatProperty
1411from bpy .props import IntProperty
1512
1613# --- Stores result of command. Created to make easier detecting result from lines of stdout
1714ResultContainer = namedtuple ("ResultContainer" , ["value" ])
15+ COMMAND_PORT = None
16+
17+ import sys
18+ sys .path .append (r"/home/pawel/git/tmp2" )
19+ import pydevd_pycharm
20+ pydevd_pycharm .settrace ('localhost' , port = 6666 , stdoutToServer = True , stderrToServer = True )
1821
1922
2023class OutputDuplicator (AbstractContextManager ):
@@ -122,60 +125,64 @@ class CommandPortOperator(bpy.types.Operator):
122125 bl_idname = "object.command_port"
123126 bl_label = "Blender Command Port"
124127 timer = None
128+ instance = None
129+ keep_command_port_running = False
125130
126131 # noinspection PyUnusedLocal
127132 def __init__ (self ):
128133 super (CommandPortOperator , self ).__init__ ()
129134 try :
130- self .command_port = CommandPort (queue_size = bpy .context .scene .bcp_queue_size ,
131- timeout = bpy .context .scene .bcp_timeout ,
132- port = bpy .context .scene .bcp_port ,
133- buffersize = bpy .context .scene .bcp_buffersize ,
134- max_connections = bpy .context .scene .bcp_max_connections ,
135- return_result = bpy .context .scene .bcp_return_result ,
136- result_as_json = bpy .context .scene .bcp_result_as_json ,
137- redirect_output = bpy .context .scene .bcp_redirect_output ,
138- share_environ = bpy .context .scene .bcp_share_environ )
135+ try :
136+ if not CommandPortOperator .instance .is_alive ():
137+ raise AttributeError # Hacky, but works
138+ self .command_port = CommandPortOperator .instance
139+ except AttributeError :
140+ self .command_port = CommandPort (queue_size = bpy .context .window_manager .bcp_queue_size ,
141+ timeout = bpy .context .window_manager .bcp_timeout ,
142+ port = bpy .context .window_manager .bcp_port ,
143+ buffersize = bpy .context .window_manager .bcp_buffersize ,
144+ max_connections = bpy .context .window_manager .bcp_max_connections ,
145+ return_result = bpy .context .window_manager .bcp_return_result ,
146+ result_as_json = bpy .context .window_manager .bcp_result_as_json ,
147+ redirect_output = bpy .context .window_manager .bcp_redirect_output ,
148+ share_environ = bpy .context .window_manager .bcp_share_environ )
149+ CommandPortOperator .instance = self .command_port
150+ self .command_port .start ()
139151 except AttributeError as e :
140152 try :
141153 # ---- Make sure that properties are not missing and did not cause this exception
142- queue_size = bpy .context .scene .bcp_queue_size ,
143- timeout = bpy .context .scene .bcp_timeout ,
144- port = bpy .context .scene .bcp_port ,
145- buffersize = bpy .context .scene .bcp_buffersize ,
146- max_connections = bpy .context .scene .bcp_max_connections ,
147- return_result = bpy .context .scene .bcp_return_result ,
148- result_as_json = bpy .context .scene .bcp_result_as_json ,
149- redirect_output = bpy .context .scene .bcp_redirect_output
150- bcp_share_environ = bpy .context .scene .bcp_share_environ
154+ queue_size = bpy .context .window_manager .bcp_queue_size ,
155+ timeout = bpy .context .window_manager .bcp_timeout ,
156+ port = bpy .context .window_manager .bcp_port ,
157+ buffersize = bpy .context .window_manager .bcp_buffersize ,
158+ max_connections = bpy .context .window_manager .bcp_max_connections ,
159+ return_result = bpy .context .window_manager .bcp_return_result ,
160+ result_as_json = bpy .context .window_manager .bcp_result_as_json ,
161+ redirect_output = bpy .context .window_manager .bcp_redirect_output
162+ bcp_share_environ = bpy .context .window_manager .bcp_share_environ
151163 except AttributeError :
152164 # ---- properties are missing
153165 raise AttributeError ("Properties are not registered. "
154166 "Run 'register_properties' function before opening the port" )
155167 # ---- If properties are working, then re-raise an exception
156168 raise e
157- self .command_port .start ()
158169 print ("Command port opened" )
159170
160- def __del__ (self ):
161- self .close_port ()
162- del bpy .context .window_manager .keep_command_port_running
163-
164171 def check_property (self ):
165- if not bpy . context . window_manager .keep_command_port_running :
172+ if not CommandPortOperator .keep_command_port_running :
166173 self .close_port ()
167174
168175 def close_port (self ):
169176 if self .timer is not None :
170177 bpy .context .window_manager .event_timer_remove (self .timer )
171178 print ("Waiting for command port thread to end...." )
172179 self .command_port .do_run = False
173- while self .command_port .isAlive ():
180+ while self .command_port .is_alive ():
174181 pass
175182 print ("Command port thread was stopped." )
176183
177184 def execute (self , context ):
178- if not self .command_port .isAlive ():
185+ if not self .command_port .is_alive ():
179186 return {'FINISHED' }
180187 try :
181188 command = self .command_port .commands_queue .get_nowait ()
@@ -210,23 +217,19 @@ def modal(self, context, event):
210217
211218 def invoke (self , context , event ):
212219 try :
213- bpy . context . window_manager .keep_command_port_running = True
220+ CommandPortOperator .keep_command_port_running = True
214221 except AttributeError :
215222 # --- Registering it here, because it has to run "check_property method
216223 bpy .types .WindowManager .keep_command_port_running = bpy .props .BoolProperty (
217224 name = "My Property" ,
218225 update = lambda o , c : self .check_property ()
219226 )
220- bpy . context . window_manager .keep_command_port_running = True
227+ CommandPortOperator .keep_command_port_running = True
221228 self .execute (context )
222229 context .window_manager .modal_handler_add (self )
223230 return {'RUNNING_MODAL' }
224231
225232
226- def open_command_port ():
227- bpy .ops .object .command_port ('INVOKE_DEFAULT' )
228-
229-
230233def register (queue_size = 0 , timeout = .1 , port = 5000 , buffersize = 4096 , max_connections = 5 ,
231234 return_result = True , result_as_json = False , redirect_output = True , share_environ = True ):
232235 """
@@ -252,34 +255,34 @@ def register(queue_size=0, timeout=.1, port=5000, buffersize=4096, max_connectio
252255 :param share_environ: Indicates if executed commands should operate on new dict instance, or os.environ of program
253256 :type share_environ: bool
254257 """
255- Scene .bcp_queue_size : IntProperty () = IntProperty (default = queue_size ,
258+ bpy . types . WindowManager .bcp_queue_size : IntProperty () = IntProperty (default = queue_size ,
256259 name = "Queue size" ,
257260 description = "Size of commands queue: max number of "
258261 "commands that are qaiting to be executed. "
259262 "0 == no limit" , )
260- Scene .bcp_timeout : FloatProperty () = FloatProperty (default = timeout ,
263+ bpy . types . WindowManager .bcp_timeout : FloatProperty () = FloatProperty (default = timeout ,
261264 name = "Timeout" ,
262265 description = "Maximum connection timeout, in seconds" )
263- Scene .bcp_port : IntProperty = IntProperty (default = port ,
266+ bpy . types . WindowManager .bcp_port : IntProperty = IntProperty (default = port ,
264267 name = "Port" ,
265268 description = "Port for the socket" )
266- Scene .bcp_buffersize : IntProperty = IntProperty (default = buffersize ,
269+ bpy . types . WindowManager .bcp_buffersize : IntProperty = IntProperty (default = buffersize ,
267270 name = "Buffersize" ,
268271 description = "Buffersize, in bytes, for socket" )
269- Scene .bcp_max_connections : IntProperty = IntProperty (default = max_connections ,
272+ bpy . types . WindowManager .bcp_max_connections : IntProperty = IntProperty (default = max_connections ,
270273 name = "Max connections" ,
271274 description = "\" backlog\" parameter of socket \" listen\" method" )
272- Scene .bcp_return_result : BoolProperty = BoolProperty (default = return_result ,
275+ bpy . types . WindowManager .bcp_return_result : BoolProperty = BoolProperty (default = return_result ,
273276 name = "Return result" ,
274277 description = "Indicates if result of command should be returned" )
275- Scene .bcp_result_as_json : BoolProperty = BoolProperty (default = result_as_json ,
278+ bpy . types . WindowManager .bcp_result_as_json : BoolProperty = BoolProperty (default = result_as_json ,
276279 name = "Result as json" ,
277280 description = "Indicates if result of command should be "
278281 "returned as a json string" )
279- Scene .bcp_redirect_output : BoolProperty = BoolProperty (default = redirect_output ,
282+ bpy . types . WindowManager .bcp_redirect_output : BoolProperty = BoolProperty (default = redirect_output ,
280283 name = "Redirect output" ,
281284 description = "Indicates if output should be copied and sent" )
282- Scene .bcp_share_environ : BoolProperty = BoolProperty (default = share_environ ,
285+ bpy . types . WindowManager .bcp_share_environ : BoolProperty = BoolProperty (default = share_environ ,
283286 name = "Share environment" ,
284287 description = "Indicates if current environment should share an "
285288 "application environment,\n "
@@ -291,17 +294,16 @@ def register(queue_size=0, timeout=.1, port=5000, buffersize=4096, max_connectio
291294 "and forcommands executed later." )
292295 bpy .utils .register_class (CommandPortOperator )
293296
294-
295297def unregister ():
296- del Scene .bcp_queue_size
297- del Scene .bcp_timeout
298- del Scene .bcp_port
299- del Scene .bcp_buffersize
300- del Scene .bcp_max_connections
301- del Scene .bcp_return_result
302- del Scene .bcp_result_as_json
303- del Scene .bcp_redirect_output
304- del Scene .bcp_share_environ
298+ del bpy . types . WindowManager .bcp_queue_size
299+ del bpy . types . WindowManager .bcp_timeout
300+ del bpy . types . WindowManager .bcp_port
301+ del bpy . types . WindowManager .bcp_buffersize
302+ del bpy . types . WindowManager .bcp_max_connections
303+ del bpy . types . WindowManager .bcp_return_result
304+ del bpy . types . WindowManager .bcp_result_as_json
305+ del bpy . types . WindowManager .bcp_redirect_output
306+ del bpy . types . WindowManager .bcp_share_environ
305307 bpy .utils .unregister_class (CommandPortOperator )
306308
307309
0 commit comments