1111import os .path
1212import textwrap
1313import threading
14+ import traceback
1415
1516from telnetlib import Telnet
1617
@@ -228,6 +229,165 @@ def _py_str(s):
228229 return s
229230
230231
232+ def settings_obj ():
233+ return sublime .load_settings ("MayaSublime.sublime-settings" )
234+
235+
236+ def sync_settings ():
237+ so = settings_obj ()
238+
239+ _settings ['host' ] = so .get ('maya_hostname' )
240+ _settings ['py_port' ] = so .get ('python_command_port' )
241+ _settings ['mel_port' ] = so .get ('mel_command_port' )
242+ _settings ['strip_comments' ] = so .get ('strip_sending_comments' )
243+ _settings ['no_collisions' ] = so .get ('no_collisions' )
244+ _settings ['maya_output' ] = so .get ('receive_maya_output' )
245+ _settings ['undo' ] = so .get ('create_undo' )
246+
247+ MayaReader ._st2_remove_reader ()
248+
249+ if _settings ['maya_output' ] is not None :
250+ MayaReader .set_maya_output_enabled (_settings ["maya_output" ])
251+
252+
253+ # A template wrapper for sending Python source safely
254+ # over the socket.
255+ # Executes in a private namespace to avoid collisions
256+ # with the main environment in Maya.
257+ # Also handles catches and printing exceptions so that
258+ # they are not masked.
259+ PY_CMD_TEMPLATE = textwrap .dedent ('''
260+ import traceback
261+ import __main__
262+
263+ import maya.cmds
264+
265+ namespace = __main__.__dict__.get('_sublime_SendToMaya_plugin')
266+ if not namespace:
267+ namespace = __main__.__dict__.copy()
268+ __main__.__dict__['_sublime_SendToMaya_plugin'] = namespace
269+
270+ try:
271+ if {undo}:
272+ maya.cmds.undoInfo(openChunk=True, chunkName="MayaSublime Code")
273+
274+ if {ns}:
275+ namespace['__file__'] = {fp!r}
276+ {xtype}({cmd!r}, namespace, namespace)
277+ else:
278+ {xtype}({cmd!r})
279+ except:
280+ traceback.print_exc()
281+ finally:
282+ if {undo}:
283+ maya.cmds.undoInfo(closeChunk=True)
284+ ''' )
285+
286+
287+
288+ PY_MAYA_CALLBACK = textwrap .dedent (r'''
289+ import errno
290+ import socket
291+ import maya.OpenMaya
292+
293+ try:
294+ from cStringIO import StringIO
295+ except ImportError:
296+ from StringIO import StringIO
297+
298+ if '_MayaSublime_ScriptEditorOutput_CID' not in globals():
299+ _MayaSublime_ScriptEditorOutput_CID = None
300+
301+ if '_MayaSublime_SOCK' not in globals():
302+ _MayaSublime_SOCK = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
303+
304+ def _MayaSublime_streamScriptEditor(enable, host="127.0.0.1", port=5123, quiet=False):
305+ om = maya.OpenMaya
306+
307+ global _MayaSublime_ScriptEditorOutput_CID
308+ cid = _MayaSublime_ScriptEditorOutput_CID
309+
310+ # Only print if we are really changing state
311+ if enable and cid is None:
312+ sys.stdout.write("[MayaSublime] Enable Streaming ScriptEditor " \
313+ "({0}:{1})\n".format(host, port))
314+
315+ elif not enable and cid is not None:
316+ sys.stdout.write("[MayaSublime] Disable Streaming ScriptEditor\n")
317+
318+ if cid is not None:
319+ om.MMessage.removeCallback(cid)
320+ _MayaSublime_ScriptEditorOutput_CID = None
321+
322+ if not enable:
323+ return
324+
325+ buf = StringIO()
326+
327+ def _streamToMayaSublime(msg, msgType, *args):
328+ buf.seek(0)
329+ buf.truncate()
330+
331+ if msgType != om.MCommandMessage.kDisplay:
332+ buf.write('[MayaSublime] ')
333+
334+ if msgType == om.MCommandMessage.kWarning:
335+ buf.write('# Warning: ')
336+ buf.write(msg)
337+ buf.write(' #\n')
338+
339+ elif msgType == om.MCommandMessage.kError:
340+ buf.write('// Error: ')
341+ buf.write(msg)
342+ buf.write(' //\n')
343+
344+ elif msgType == om.MCommandMessage.kResult:
345+ buf.write('# Result: ')
346+ buf.write(msg)
347+ buf.write(' #\n')
348+
349+ else:
350+ buf.write(msg)
351+
352+ buf.seek(0)
353+
354+ # Start with trying to send 8kb packets
355+ bufsize = 8*1024
356+
357+ # Loop until the buffer is empty
358+ while True:
359+
360+ while bufsize > 0:
361+ # Save our position in case we error
362+ # and need to roll back
363+ pos = buf.tell()
364+
365+ part = buf.read(bufsize)
366+ if not part:
367+ # Buffer is empty. Nothing else to send
368+ return
369+
370+ try:
371+ _MayaSublime_SOCK.sendto(part, (host, port))
372+
373+ except Exception as e:
374+ if e.errno == errno.EMSGSIZE:
375+ # We have hit a message size limit.
376+ # Scale down and try the packet again
377+ bufsize /= 2
378+ buf.seek(pos)
379+ continue
380+ # Some other error
381+ raise
382+
383+ # Message sent without error
384+ break
385+
386+ cid = om.MCommandMessage.addCommandOutputCallback(_streamToMayaSublime)
387+ _MayaSublime_ScriptEditorOutput_CID = cid
388+ ''' )
389+
390+
231391class MayaReader (threading .Thread ):
232392 """
233393 A threaded reader that monitors for published ScriptEditor
@@ -242,9 +402,10 @@ class MayaReader(threading.Thread):
242402 # Signal to stop a receiving MayaReader
243403 STOP_MSG = _py_str ('MayaSublime::MayaReader::{0}' .format (uuid .uuid4 ()))
244404
245- # Stringified ScriptEditor callback code to install in Maya
246- PY_MAYA_CALLBACK = open (os .path .join (os .path .dirname (__file__ ),
247- "lib/pubScriptEditor.py" )).read ()
405+ # # Stringified ScriptEditor callback code to install in Maya
406+ # PY_MAYA_CALLBACK = open(os.path.join(os.path.dirname(__file__),
407+ # "lib/pubScriptEditor.py")).read()
408+ PY_MAYA_CALLBACK = PY_MAYA_CALLBACK
248409
249410 def __init__ (self , host = '127.0.0.1' , port = 0 ):
250411 super (MayaReader , self ).__init__ ()
@@ -391,60 +552,6 @@ def set_maya_output_enabled(cls, enable):
391552
392553 reader ._set_maya_callback_enabled (True , quiet )
393554
394- def settings_obj ():
395- return sublime .load_settings ("MayaSublime.sublime-settings" )
396-
397-
398- def sync_settings ():
399- so = settings_obj ()
400-
401- _settings ['host' ] = so .get ('maya_hostname' )
402- _settings ['py_port' ] = so .get ('python_command_port' )
403- _settings ['mel_port' ] = so .get ('mel_command_port' )
404- _settings ['strip_comments' ] = so .get ('strip_sending_comments' )
405- _settings ['no_collisions' ] = so .get ('no_collisions' )
406- _settings ['maya_output' ] = so .get ('receive_maya_output' )
407- _settings ['undo' ] = so .get ('create_undo' )
408-
409- MayaReader ._st2_remove_reader ()
410-
411- if _settings ['maya_output' ] is not None :
412- MayaReader .set_maya_output_enabled (_settings ["maya_output" ])
413-
414-
415- # A template wrapper for sending Python source safely
416- # over the socket.
417- # Executes in a private namespace to avoid collisions
418- # with the main environment in Maya.
419- # Also handles catches and printing exceptions so that
420- # they are not masked.
421- PY_CMD_TEMPLATE = textwrap .dedent ('''
422- import traceback
423- import __main__
424-
425- import maya.cmds
426-
427- namespace = __main__.__dict__.get('_sublime_SendToMaya_plugin')
428- if not namespace:
429- namespace = __main__.__dict__.copy()
430- __main__.__dict__['_sublime_SendToMaya_plugin'] = namespace
431-
432- try:
433- if {undo}:
434- maya.cmds.undoInfo(openChunk=True, chunkName="MayaSublime Code")
435-
436- if {ns}:
437- namespace['__file__'] = {fp!r}
438- {xtype}({cmd!r}, namespace, namespace)
439- else:
440- {xtype}({cmd!r})
441- except:
442- traceback.print_exc()
443- finally:
444- if {undo}:
445- maya.cmds.undoInfo(closeChunk=True)
446- ''' )
447-
448555
449556# Add callbacks for monitoring setting changes
450557settings_obj ().clear_on_change ("MayaSublime.settings" )
0 commit comments