Hi,
I'm trying to connect C4D with Tkinter (External Application) through sockets (first time using it).
You can see an illustration of the problem here:
https://www.dropbox.com/s/vz1ixu3jozeujum/c4d308_python_socket.mp4?dl=0
I expect that a Cube is made when I press the Cube button, but as you can see nothing happens.
Interestingly, the Tkinter doesn't error out so I guess there is some connection that was made.
Here is the code so far(Tkinter):
from tkinter import *
import socket
window = Tk()
data = bytes('', "utf-8")
def send_msg(msg):
data = bytes(msg, "utf-8")
b1 = Button (window, text="Cube", command=send_msg("cube"))
b1.grid(row=0, column=0)
b1 = Button (window, text="Sphere", command=send_msg("sphere"))
b1.grid(row=1, column=0)
b1 = Button (window, text="Plane", command=send_msg("plane"))
b1.grid(row=2, column=0)
window.mainloop()
host, port = '127.0.0.1', 12121
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((host, port))
while True:
socket.sendall(data)
Here is the .pyp file as plugin for C4D.
import c4d
import socket
from c4d.threading import C4DThread
thread_ = None
host, port = '127.0.0.1', 12121
pluginID = 131313
pluginIDCommandData = 141414
def create_primitive(primitive_type):
if primitive_type == 'cube':
doc.InsertObject(c4d.BaseObject(c4d.Ocube))
if primitive_type == 'sphere':
doc.InsertObject(c4d.BaseObject(c4d.Osphere))
if primitive_type == 'plane':
doc.InsertObject(c4d.BaseObject(c4d.Oplane))
c4d.EventAdd()
#Background_Server is driven from Thread class in order to make it run in the background.
class BGThread(C4DThread):
end = False
# Called by TestBreak to adds a custom condition to leave
def TestDBreak(self):
return bool(self.end)
#Start the thread to start listing to the port.
def Main(self):
self.socket_ = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket_.bind((host, port))
while True:
if self.TestBreak():
return
self.socket_.listen(5)
client, addr = self.socket_.accept()
data = ""
buffer_size = 4096*2
data = client.recv(buffer_size)
create_primitive(primitive_type=data)
class DialogSetting(c4d.gui.GeDialog):
def CreateLayout(self):
self.SetTitle("Primitive Plugin")
self.GroupBegin(id=1, flags=c4d.BFH_SCALEFIT, rows=3, title=("Primitive Plugin"), cols=1, initw = 500)
self.AddCheckbox(1001, c4d.BFH_CENTER, 300, 10, "Settings 1")
self.AddCheckbox(1002, c4d.BFH_CENTER, 300, 10, "Settings 2")
self.AddCheckbox(1003, c4d.BFH_CENTER, 300, 10, "Settings 3")
self.GroupEnd()
return True
class CommandDataDlg(c4d.plugins.CommandData):
dialog = None
def Execute(self, doc):
if self.dialog is None:
self.dialog = DialogSetting()
return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=pluginIDCommandData, xpos=-1, ypos=-1, defaultw=200, defaulth=150)
def RestoreLayout(self, sec_ref):
# manage the dialog
if self.dialog is None:
self.dialog = DialogSetting()
return self.dialog.Restore(pluginid=pluginIDCommandData, secret=sec_ref)
def PluginMessage(id, data):
global thread_
# At the start of Cinema 4D We lunch our thread
if id == c4d.C4DPL_PROGRAM_STARTED:
thread_ = BGThread()
thread_.Start()
def main():
c4d.plugins.RegisterCommandPlugin(id=pluginIDCommandData, str="Primitive Plugin", help="Primitive Plugin", info=0, dat=CommandDataDlg(),icon=None)
# Execute main()
if __name__=='__main__':
main()
P.S. Some of the lines for .pyp was copied from the megascans plug-in. If you want a reference of it, you can check it here: