From 278ac68ea68da16a53e0e4e77fb0c16a70b800db Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Sat, 23 Mar 2019 00:03:17 +0930 Subject: [PATCH] Add Remote IO protocol specification To enable Remote IO, run Dust3D with command line options: -remoteio See details: http://docs.dust3d.org/en/latest/remote_io_protocol.html --- docs/for_developers.rst | 1 + docs/remote_io_protocol.rst | 384 ++++++++++++++++++++++++++++++++++++ src/main.cpp | 17 +- src/remoteioconnection.cpp | 7 +- 4 files changed, 400 insertions(+), 9 deletions(-) create mode 100644 docs/remote_io_protocol.rst diff --git a/docs/for_developers.rst b/docs/for_developers.rst index d1b94523..6b85d9f2 100644 --- a/docs/for_developers.rst +++ b/docs/for_developers.rst @@ -7,4 +7,5 @@ For Developers :glob: builds + remote_io_protocol origin_and_future \ No newline at end of file diff --git a/docs/remote_io_protocol.rst b/docs/remote_io_protocol.rst new file mode 100644 index 00000000..9174ebb0 --- /dev/null +++ b/docs/remote_io_protocol.rst @@ -0,0 +1,384 @@ +Dust3D Remote IO Protocol Specification +--------------------------------------- +Introduction +=============== +| Dust3D Remote IO is an API based on a TCP/IP connection. It hosts on local TCP port 53309, and enables other software control the modeling progress of Dust3D by sending commands through the TCP connection. +| + +Protocol +============== +| Other software connect to tcp host 127.0.0.1:53309, send command, get reply and receive event from Dust3D. One command, or one response, consists of one packet, each packet encoded as hex string, and choose '\\0' as packet splitter. +| +| Each response start with a '+' or '-' when there is an error, the error message comes after the minus sign. + +Python Example +================= + +.. code-block:: python + + #!/usr/bin/env python + + # Run Dust3D with option: -remoteio to enable it + # e.g. + # $ open ./dust3d.app --args -remoteio + # $ ./dust3d -remoteio + + import socket + import binascii + + TCP_IP = '127.0.0.1' + TCP_PORT = 53309 + BUFFER_SIZE = 4096 + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((TCP_IP, TCP_PORT)) + s.send(binascii.hexlify("addnodewithid {3dc475f6-dcda-45b8-bb76-59948db39968} 0.51 0.51 1.01 0.08") + "\0") + s.send(binascii.hexlify("addnodewithid {3dc475f6-dcda-45b8-bb76-59948db39969} 0.51 0.51 1.51 0.08") + "\0") + s.send(binascii.hexlify("addedge {3dc475f6-dcda-45b8-bb76-59948db39968} {3dc475f6-dcda-45b8-bb76-59948db39969}") + "\0") + s.send(binascii.hexlify("savesnapshot") + "\0") + s.send(binascii.hexlify("exportAsObj") + "\0") + #s.send(binascii.hexlify("getNodePartId {3dc475f6-dcda-45b8-bb76-59948db39968}") + "\0") + response = bytes() + while True: + oneEnd = response.find(chr(0)) + if (-1 == oneEnd): + response += s.recv(BUFFER_SIZE) + continue + reply = response[:oneEnd] + response = response[oneEnd + 1:] + print binascii.unhexlify(reply) + s.close() + + +Commands +================== ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| Command | Examples | ++==============================================================+============================================================================================================================+ +| listWindow | | send> listwindow | +| | | +OK | +| | | {658cac48-4cc4-42bf-a561-dbd28330777e} Dust3D%201.0.0-beta.17%20* | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| selectWindow | | send> selectwindow {658cac48-4cc4-42bf-a561-dbd28330777e} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| undo | | send> undo | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| redo | | send> redo | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| paste | | send> paste | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| removeNode | | send> removeNode {3dc475f6-dcda-45b8-bb76-59948db39968} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| removeEdge | | send> removeEdge {a75f39ac-3c78-4754-b34a-dce70779832b} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| removePart | | send> removePart {79a15562-908c-4b74-a489-af604796b1a0} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| addNode | | send> addNode 0.51 0.51 1.01 0.08 | +| | | +OK | +| | | | +| | | send> addNode 0.51 0.51 1.01 0.08 {3dc475f6-dcda-45b8-bb76-59948db39968} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| addNodeWithId | | send> addNodeWithId {8d443cbf-fc73-4281-b3a1-268dd38b1c73} 0.51 0.51 1.01 0.08 | +| | | +OK | +| | | | +| | | send> addNodeWithId {8d443cbf-fc73-4281-b3a1-268dd38b1c73} 0.51 0.51 1.01 0.08 {3dc475f6-dcda-45b8-bb76-59948db39968} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| scaleNodeByAddRadius | | send> scaleNodeByAddRadius {8d443cbf-fc73-4281-b3a1-268dd38b1c73} 0.05 | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| moveNodeBy | | send> moveNodeBy {8d443cbf-fc73-4281-b3a1-268dd38b1c73} 0.05 0.05 0.05 | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setNodeOrigin | | send> setNodeOrigin {8d443cbf-fc73-4281-b3a1-268dd38b1c73} 0.51 0.51 1.01 | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setNodeRadius | | send> setNodeRadius {8d443cbf-fc73-4281-b3a1-268dd38b1c73} 0.08 | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setNodeBoneMark | | Available bone marks: Neck/Limb/Tail/Joint/None | +| | | | +| | | send> setNodeBoneMark {8d443cbf-fc73-4281-b3a1-268dd38b1c73} Neck | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| switchNodeXZ | | send> switchNodeXZ {8d443cbf-fc73-4281-b3a1-268dd38b1c73} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| moveOriginBy | | send> moveOriginBy 0.01, 0.02, 0.013 | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| addEdge | | send> addEdge {a75f39ac-3c78-4754-b34a-dce70779832b} {507328fd-9baf-41d1-9e05-850fb41fcbfa} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setPartLockState | | send> setPartLockState {79a15562-908c-4b74-a489-af604796b1a0} locked | +| | | +OK | +| | | | +| | | send> setPartLockState {79a15562-908c-4b74-a489-af604796b1a0} unlocked | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setPartVisibleState | | send> setPartVisibleState {79a15562-908c-4b74-a489-af604796b1a0} visible | +| | | +OK | +| | | | +| | | send> setPartVisibleState {79a15562-908c-4b74-a489-af604796b1a0} invisible | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setPartSubdivState | | send> setPartSubdivState {79a15562-908c-4b74-a489-af604796b1a0} subdived | +| | | +OK | +| | | | +| | | send> setPartSubdivState {79a15562-908c-4b74-a489-af604796b1a0} unsubdived | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setPartChamferState | | send> setPartChamferState {79a15562-908c-4b74-a489-af604796b1a0} chamfered | +| | | +OK | +| | | | +| | | send> setPartChamferState {79a15562-908c-4b74-a489-af604796b1a0} unchamfered | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setPartRoundState | | send> setPartRoundState {79a15562-908c-4b74-a489-af604796b1a0} rounded | +| | | +OK | +| | | | +| | | send> setPartRoundState {79a15562-908c-4b74-a489-af604796b1a0} unrounded | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setPartDisableState | | send> setPartDisableState {79a15562-908c-4b74-a489-af604796b1a0} disabled | +| | | +OK | +| | | | +| | | send> setPartDisableState {79a15562-908c-4b74-a489-af604796b1a0} undisabled | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setPartXmirrorState | | send> setPartXmirrorState {79a15562-908c-4b74-a489-af604796b1a0} mirrored | +| | | +OK | +| | | | +| | | send> setPartXmirrorState {79a15562-908c-4b74-a489-af604796b1a0} unmirrored | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| setPartColor | | send> setPartColor {79a15562-908c-4b74-a489-af604796b1a0} red | +| | | +OK | +| | | | +| | | send> setPartColor {79a15562-908c-4b74-a489-af604796b1a0} | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| getNodePartId | | send> getNodePartId {3dc475f6-dcda-45b8-bb76-59948db39968} | +| | | +OK | +| | | {b8f9ae53-999c-4851-9c2b-69a427fca10c} | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| saveSnapshot | | send> saveSnapshot | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| getSnapshot | | send> getSnapshot | +| | | +OK +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | +| | | | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| exportAsObj | | send> exportAsObj | +| | | +OK +| | | # DUST3D +| | | v -0.08 0.08 0.08 +| | | v -0.08 -0.08 0.08 +| | | v 0.08 -0.08 0.08 +| | | v 0.08 -0.08 -0.08 +| | | v -0.08 -0.08 -0.08 +| | | v -0.08 0.08 -0.08 +| | | v 0.08 0.08 -0.08 +| | | v 0.08 0.08 0.08 +| | | f 2 1 6 5 +| | | f 3 2 5 4 +| | | f 2 3 8 1 +| | | f 8 3 4 7 +| | | f 5 6 7 4 +| | | f 1 8 7 6 | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| new | | send> new | +| | | +OK | ++--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ + + +Events +============== ++--------------------------------------------------------------+ +| Event | ++==============================================================+ +| nodeadded | ++--------------------------------------------------------------+ +| partadded | ++--------------------------------------------------------------+ +| edgeadded | ++--------------------------------------------------------------+ +| partremoved | ++--------------------------------------------------------------+ +| componentnamechanged | ++--------------------------------------------------------------+ +| componentchildrenchanged | ++--------------------------------------------------------------+ +| componentremoved | ++--------------------------------------------------------------+ +| componentadded | ++--------------------------------------------------------------+ +| componentexpandstatechanged | ++--------------------------------------------------------------+ +| noderemoved | ++--------------------------------------------------------------+ +| edgeremoved | ++--------------------------------------------------------------+ +| noderadiuschanged | ++--------------------------------------------------------------+ +| nodebonemarkchanged | ++--------------------------------------------------------------+ +| nodeoriginchanged | ++--------------------------------------------------------------+ +| edgechanged | ++--------------------------------------------------------------+ +| partpreviewchanged | ++--------------------------------------------------------------+ +| resultmeshchanged | ++--------------------------------------------------------------+ +| turnaroundchanged | ++--------------------------------------------------------------+ +| editmodechanged | ++--------------------------------------------------------------+ +| skeletonchanged | ++--------------------------------------------------------------+ +| resulttexturechanged | ++--------------------------------------------------------------+ +| postprocessedresultchanged | ++--------------------------------------------------------------+ +| resultrigchanged | ++--------------------------------------------------------------+ +| rigchanged | ++--------------------------------------------------------------+ +| partlockstatechanged | ++--------------------------------------------------------------+ +| partvisiblestatechanged | ++--------------------------------------------------------------+ +| partsubdivstatechanged | ++--------------------------------------------------------------+ +| partdisablestatechanged | ++--------------------------------------------------------------+ +| partxmirrorstatechanged | ++--------------------------------------------------------------+ +| partdeformthicknesschanged | ++--------------------------------------------------------------+ +| partdeformwidthchanged | ++--------------------------------------------------------------+ +| partroundstatechanged | ++--------------------------------------------------------------+ +| partcolorstatechanged | ++--------------------------------------------------------------+ +| partcutrotationchanged | ++--------------------------------------------------------------+ +| partcuttemplatechanged | ++--------------------------------------------------------------+ +| partmaterialidchanged | ++--------------------------------------------------------------+ +| partchamferstatechanged | ++--------------------------------------------------------------+ +| componentcombinemodechanged | ++--------------------------------------------------------------+ +| cleanup | ++--------------------------------------------------------------+ +| originchanged | ++--------------------------------------------------------------+ +| xlockstatechanged | ++--------------------------------------------------------------+ +| ylockstatechanged | ++--------------------------------------------------------------+ +| zlockstatechanged | ++--------------------------------------------------------------+ +| radiuslockstatechanged | ++--------------------------------------------------------------+ +| checkpart | ++--------------------------------------------------------------+ +| checkedge | ++--------------------------------------------------------------+ +| optionschanged | ++--------------------------------------------------------------+ +| rigtypechanged | ++--------------------------------------------------------------+ +| poseschanged | ++--------------------------------------------------------------+ +| motionschanged | ++--------------------------------------------------------------+ +| poseadded | ++--------------------------------------------------------------+ +| poseremoved | ++--------------------------------------------------------------+ +| poselistchanged | ++--------------------------------------------------------------+ +| posenamechanged | ++--------------------------------------------------------------+ +| poseframeschanged | ++--------------------------------------------------------------+ +| poseturnaroundimageidchanged | ++--------------------------------------------------------------+ +| posepreviewchanged | ++--------------------------------------------------------------+ +| motionadded | ++--------------------------------------------------------------+ +| motionremoved | ++--------------------------------------------------------------+ +| motionlistchanged | ++--------------------------------------------------------------+ +| motionnamechanged | ++--------------------------------------------------------------+ +| motionclipschanged | ++--------------------------------------------------------------+ +| motionpreviewchanged | ++--------------------------------------------------------------+ +| motionresultchanged | ++--------------------------------------------------------------+ +| materialadded | ++--------------------------------------------------------------+ +| materialremoved | ++--------------------------------------------------------------+ +| materiallistchanged | ++--------------------------------------------------------------+ +| materialnamechanged | ++--------------------------------------------------------------+ +| materiallayerschanged | ++--------------------------------------------------------------+ +| materialpreviewchanged | ++--------------------------------------------------------------+ +| meshgenerating | ++--------------------------------------------------------------+ +| postprocessing | ++--------------------------------------------------------------+ +| texturegenerating | ++--------------------------------------------------------------+ +| texturechanged | ++--------------------------------------------------------------+ diff --git a/src/main.cpp b/src/main.cpp index 36204a46..6886d5a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,13 +54,16 @@ int main(int argc, char ** argv) DocumentWindow::createDocumentWindow(); - QSettings settings; - QVariant remoteIoListenPort = settings.value("RemoteIo/ListenPort"); - //if (remoteIoListenPort.isNull()) { - // settings.setValue("RemoteIo/ListenPort", "53309"); - //} - if (!remoteIoListenPort.isNull()) { - new RemoteIoServer(remoteIoListenPort.toInt()); + bool remoteIoEnabled = false; + for (int i = 1; i < argc; ++i) { + if ('-' == argv[i][0] && 0 == strcmp(argv[i], "-remoteio")) { + remoteIoEnabled = true; + break; + } + } + if (remoteIoEnabled) { + qDebug() << "Remote IO enabled"; + new RemoteIoServer(53309); } return app.exec(); diff --git a/src/remoteioconnection.cpp b/src/remoteioconnection.cpp index 37ced550..818c4f1a 100644 --- a/src/remoteioconnection.cpp +++ b/src/remoteioconnection.cpp @@ -140,7 +140,7 @@ QString RemoteIoConnection::nextParameter(const QByteArray ¶meters, int *off for (int i = *offset; i < parameters.size(); ++i) { if (isWhitespace(parameters[i])) { int parameterEnd = i; - auto parameter = parameters.mid(*offset, parameterEnd); + auto parameter = parameters.mid(*offset, (parameterEnd - *offset) + 1); while (i < parameters.size() && isWhitespace(parameters[i])) ++i; *offset = i; @@ -549,6 +549,8 @@ QByteArray RemoteIoConnection::commandRemovePart(const QByteArray ¶meters, Q { COMMAND_PRECHECK(); + // QUuid partId + if (parameters.isEmpty()) { *errorMessage = "Must specify part id"; return QByteArray(); @@ -1056,7 +1058,8 @@ QByteArray RemoteIoConnection::commandSetPartXmirrorState(const QByteArray ¶ *errorMessage = "Must specify xMirrorState parameter"; return QByteArray(); } - bool xMirrored = xMirrorString.toLower() == "xmirrored"; + xMirrorString = xMirrorString.toLower(); + bool xMirrored = xMirrorString == "mirrored" || xMirrorString == "xmirrored"; m_currentDocumentWindow->document()->setPartXmirrorState(partId, xMirrored); return QByteArray();