SOLVED Call plugin by python script with arguments

Hi all,
I'm trying to implement an additional no-gui version of a my plugin(python).
Normally as a command plugin it opens a dialog and require a click on ok button.
I would give the ability to call plugin via python script and pass options automatically as arguments.
CallCommand(xxx) is not able to do this.
does anyone think it is possible?
I also tried CallButton with no luck.
Thanks all in advance.

Hi,

you can't call a command with some default argument directly. You are talking about a no-gui version of your plugin, does that mean you want to run it with a command line argument? is it your plugin or c4d that should have no gui?

I think that what you are trying to achieve is to create a command plugin that can have some optional parameters, but the user does not have to define them every time he is using the command. When registering the commandData plugin, you can use the flag PLUGINFLAG_COMMAND_OPTION_DIALOG that will allow you to open a dialog box and retrieve some parameters from the user. This already exist on Cinema 4D, on some command you can see a cogwheel that will open the options for that command when you click on it. You must store those parameters in the class itself.
If you want to call the function from the command line, you must retrieve the argument when Cinema 4D is launched. You can do that in the PluginMessage function.

Once you retrieved the parameters, you can call a static function that will do the job you want.

import c4d
import sys


MAIN_CMD_PLUGIN_ID  = 1055692
subdivisionLevelID = 1000


class MYCOMMANDWITHDIALOG (c4d.plugins.CommandData):
	
	@staticmethod
	def External(doc, bc):
		# Create a static method that can be called from the command line or the from the execute command.
		subdivisionLevel = bc[subdivisionLevelID]
		print ("subdivision value is {}".format(subdivisionLevel))
		print ("default value 0")
		print ("value from option 3")
		print ("value from command line 5")
		if doc is None:
			doc = c4d.documents.GetActiveDocument()
		if doc is None:
			return
		

		cube = c4d.BaseObject(c4d.Ocube)
		cube[c4d.PRIM_CUBE_SUBX] = subdivisionLevel
		cube[c4d.PRIM_CUBE_SUBY] = subdivisionLevel
		cube[c4d.PRIM_CUBE_SUBZ] = subdivisionLevel
		doc.InsertObject(cube)
		c4d.EventAdd()

	def __init__(self):
		self.parameters = c4d.BaseContainer()
		self.parameters[subdivisionLevelID] = 1

	def Execute(self, doc):
		self.External(doc, self.parameters)

		return True

	
	def ExecuteOptionID(self, doc, plugid, subid):
		"""Opens the option dialog.
		"""
		print("Running {}.ExecuteOptionID() {}  {}".format(self, plugid, subid))
		# we should display a dialog box asking for parameters
		self.parameters[subdivisionLevelID] = 3
		


def PluginMessage(id, data):
	if id==c4d.C4DPL_COMMANDLINEARGS:
		for arg in reversed(sys.argv):
			if arg.startswith("-startMyPlugin_1055692"):
				bc = c4d.BaseContainer()
				# here we can define a default value when Cinema 4D is called with an argument
				# of we can also retrieve the next argument that will contain the values we want to use.
				bc[subdivisionLevelID] = 5
				MYCOMMANDWITHDIALOG.External(None, bc)
		return True
	return False


def main():

	c4d.plugins.RegisterCommandPlugin(id=MAIN_CMD_PLUGIN_ID,
								str  ="Command with sub id",
								info = c4d.PLUGINFLAG_COMMAND_OPTION_DIALOG,
								help ="Command with sub command or dialog option",
								dat = MYCOMMANDWITHDIALOG(),
								icon=None)
if __name__ == '__main__':
	main()

Cheers,
Manuel

Hi,

you can't call a command with some default argument directly. You are talking about a no-gui version of your plugin, does that mean you want to run it with a command line argument? is it your plugin or c4d that should have no gui?

I think that what you are trying to achieve is to create a command plugin that can have some optional parameters, but the user does not have to define them every time he is using the command. When registering the commandData plugin, you can use the flag PLUGINFLAG_COMMAND_OPTION_DIALOG that will allow you to open a dialog box and retrieve some parameters from the user. This already exist on Cinema 4D, on some command you can see a cogwheel that will open the options for that command when you click on it. You must store those parameters in the class itself.
If you want to call the function from the command line, you must retrieve the argument when Cinema 4D is launched. You can do that in the PluginMessage function.

Once you retrieved the parameters, you can call a static function that will do the job you want.

import c4d
import sys


MAIN_CMD_PLUGIN_ID  = 1055692
subdivisionLevelID = 1000


class MYCOMMANDWITHDIALOG (c4d.plugins.CommandData):
	
	@staticmethod
	def External(doc, bc):
		# Create a static method that can be called from the command line or the from the execute command.
		subdivisionLevel = bc[subdivisionLevelID]
		print ("subdivision value is {}".format(subdivisionLevel))
		print ("default value 0")
		print ("value from option 3")
		print ("value from command line 5")
		if doc is None:
			doc = c4d.documents.GetActiveDocument()
		if doc is None:
			return
		

		cube = c4d.BaseObject(c4d.Ocube)
		cube[c4d.PRIM_CUBE_SUBX] = subdivisionLevel
		cube[c4d.PRIM_CUBE_SUBY] = subdivisionLevel
		cube[c4d.PRIM_CUBE_SUBZ] = subdivisionLevel
		doc.InsertObject(cube)
		c4d.EventAdd()

	def __init__(self):
		self.parameters = c4d.BaseContainer()
		self.parameters[subdivisionLevelID] = 1

	def Execute(self, doc):
		self.External(doc, self.parameters)

		return True

	
	def ExecuteOptionID(self, doc, plugid, subid):
		"""Opens the option dialog.
		"""
		print("Running {}.ExecuteOptionID() {}  {}".format(self, plugid, subid))
		# we should display a dialog box asking for parameters
		self.parameters[subdivisionLevelID] = 3
		


def PluginMessage(id, data):
	if id==c4d.C4DPL_COMMANDLINEARGS:
		for arg in reversed(sys.argv):
			if arg.startswith("-startMyPlugin_1055692"):
				bc = c4d.BaseContainer()
				# here we can define a default value when Cinema 4D is called with an argument
				# of we can also retrieve the next argument that will contain the values we want to use.
				bc[subdivisionLevelID] = 5
				MYCOMMANDWITHDIALOG.External(None, bc)
		return True
	return False


def main():

	c4d.plugins.RegisterCommandPlugin(id=MAIN_CMD_PLUGIN_ID,
								str  ="Command with sub id",
								info = c4d.PLUGINFLAG_COMMAND_OPTION_DIALOG,
								help ="Command with sub command or dialog option",
								dat = MYCOMMANDWITHDIALOG(),
								icon=None)
if __name__ == '__main__':
	main()

Cheers,
Manuel

@m_magalhaes
Thank you very much for your reply.
Target was to let user run my plugin in pyton script without open its gui, but set options by some command.
Meanwhile I came to solution by implementing ExecuteOptionID method.
In this way user first sets options in gui and after can CallCommand anywhere he wants in scripts.
Again thank you for your time.