Controllo remoto con scripting
Questa pagina descrive come controllare l’applicazione in remoto per eseguire i comandi Javascript o Python.
Ciò richiede un argomento della riga di comando specifico, quindi un semplice script Python può eseguire qualsiasi comando disponibile dalle API Javascript e Python esistenti.
Avvio dell’applicazione
Per controllare in remoto l’applicazione, è necessario avviare Substance 3D Painter con la riga di comando seguente:
"Adobe Substance 3D painter.exe" --enable-remote-scripting
Script di controllo remoto
Il seguente script Python può fungere da libreria per comunicare con l’applicazione.
Salva lo script seguente in un file denominato lib_remote.py per far funzionare correttamente gli esempi riportati di seguito.
import sys
import json
import base64
import subprocess
if sys.version_info >= (3, 0):
import http.client as http
else:
import httplib as http
class RemotePainter() :
def __init__(self, port=60041, host='localhost'):
self._host = host
self._port = port
## Json server connection
self._PAINTER_ROUTE = '/run.json'
self._HEADERS = {'Content-type': 'application/json', 'Accept': 'application/json'}
## Execute a HTTP POST request to the Substance Painter server and send/receive JSON data
def _jsonPostRequest( self, route, body, type ) :
connection = http.HTTPConnection(self._host, self._port, timeout=3600)
connection.request('POST', route, body, self._HEADERS)
response = connection.getresponse()
data = response.read()
connection.close()
if type == "js" :
data = json.loads( data.decode('utf-8') )
if 'error' in data:
OutJson = json.loads( body.decode() )
print( base64.b64decode( OutJson["js"] ) )
raise ExecuteScriptError(data['error'])
else :
## Python can return nothing, so decoding can fail
try:
data = data.decode('utf-8').rstrip()
except:
pass
return data
def checkConnection(self):
connection = http.HTTPConnection(self._host, self._port)
connection.connect()
## Execute a command
def execScript( self, script, type ) :
Command = base64.b64encode( script.encode('utf-8') )
if type == "js" :
Command = '{{"js":"{0}"}}'.format( Command.decode('utf-8') )
else :
Command = '{{"python":"{0}"}}'.format( Command.decode('utf-8') )
Command = Command.encode( "utf-8" )
return self._jsonPostRequest( self._PAINTER_ROUTE, Command, type )
class PainterError(Exception):
def __init__(self, message):
super(PainterError, self).__init__(message)
class ExecuteScriptError(PainterError):
def __init__(self, data):
super(PainterError, self).__init__('An error occured when executing script: {0}'.format(data))
Esempi
Di seguito sono riportati due semplici esempi che mostrano come eseguire i comandi in entrambe le API supportate dall’applicazione:
Esecuzione dei comandi JavaScript
La maggior parte delle funzioni Javascript nell’API restituisce dati String o Json che li rendono facili da manipolare all’interno dello script Python. L’invio e la ricezione dei dati non dovrebbero comportare particolari problemi.
Crea un file di script python denominato example_js.py e aggiungi il codice seguente:
import lib_remote
Remote = lib_remote.RemotePainter()
Remote.checkConnection()
## Print the API version
Version = Remote.execScript( "alg.version.painter", "js" )
print( Version )
## Get a list of all the files in the default shelf/library:
Files = Remote.execScript( 'alg.resources.findResources("starter_assets", "*")', "js" )
for File in Files :
print( File )
Se l’applicazione è in esecuzione con la riga di comando, l’esecuzione di questo script consentirà l’esecuzione dei comandi e il recupero dei relativi risultati.
Esecuzione dei comandi Python
La maggior parte delle funzioni Python possono restituire oggetti che non possono essere passati nello script remoto, il che significa che per ricevere i dati devono essere esplicitamente convertiti in stringhe o dizionari Json.
Per semplificare le operazioni, è possibile creare uno script pitone personalizzato che viene caricato durante l’avvio dell’applicazione e chiamare le funzioni che gestiscono questo tipo di conversione senza dover fare affidamento sulle conversioni in linea.
Crea un file di script python denominato example_py.py e aggiungi il codice seguente:
import lib_remote
Remote = lib_remote.RemotePainter()
Remote.checkConnection()
## import the substance_painter module to make
## its API available to us
Remote.execScript( "import substance_painter", "python" )
## Print the API version
Version = Remote.execScript( "substance_painter.__version__", "python" )
print( Version )
## Get a list of all the files in the default shelf/library
## Because the search function return objects, we have to convert
## the information into a string within the same command (inline)
Command = 'substance_painter.resource.search( "p:starter_assets/" )'
Command = '"|||".join( [ x.identifier().url() for x in {0}] )'.format( Command )
Files = Remote.execScript( Command, "python" )
Files = Files.split( "|||" )
for File in Files :
print( File )
Se l’applicazione è in esecuzione con la riga di comando, l’esecuzione di questo script consentirà l’esecuzione dei comandi e il recupero dei relativi risultati.