{"id":1292,"date":"2012-02-22T00:01:21","date_gmt":"2012-02-21T22:01:21","guid":{"rendered":"http:\/\/www.smart-page.net\/blog\/?p=1292"},"modified":"2012-02-22T01:39:52","modified_gmt":"2012-02-21T23:39:52","slug":"smart-hn-options-cinema-4d-python-commanddata-plugin-template","status":"publish","type":"post","link":"http:\/\/www.smart-page.net\/blog\/2012\/02\/22\/smart-hn-options-cinema-4d-python-commanddata-plugin-template\/","title":{"rendered":"Smart HN-Options &#8211; Cinema 4D Python CommandData Plugin Template"},"content":{"rendered":"<p>So far we already covered <a href=\"http:\/\/www.smart-page.net\/blog\/2011\/05\/09\/advanced-python-plugin-coding-for-cinema-4d\/\" target=\"_blank\">IDE-setup<\/a> and <a href=\"http:\/\/www.smart-page.net\/blog\/2011\/05\/29\/debugging-cinema-4d-python-plugins-with-pydev\/\" target=\"_blank\">debugging<\/a> &#8211; new let&#8217;s go and actually build something!<br \/>\n<br \/>\nThis is meant to be a simple template of the most common plugin type in Cinema 4D &#8211; the CommandData plugin.<\/p>\n<p>Smart HN-Options is a very simple tool that allows to globally change the parameters of every HyperNURBS object within the scene.<\/p>\n<p><a href=\"http:\/\/www.smart-page.net\/py4d\/SmartHNOptions.zip\">Grab the plugin and source! (Eclipse project files included)<\/a><\/p>\n<p><!--more--><br \/>\n<br \/>I had this lying around some time now and thought it would made for an excellent example since its small, <b>very<\/b> basic and couldn\u2019t have been a Script Manager script as it needs to ask the user for multiple parameters on each run.<\/p>\n<p>The code is commented and self-explanatory &#8211; i hope &#8211; but let\u2019s go through the abstract structure quickly:<br \/>\n<\/p>\n<h2>STEP 1: PYP-File and Package<\/h2>\n<p>As with each python plugin, we start by creating a sub-folder in <em>\/Plugins<\/em> and a *.pyp file within it &#8211; in this case the <em>SmartHNOptions.pyp<\/em>.<br \/>\nFirst we add the directory that file resides in to the python search path, so the interpreter will pick up our packages and modules:<\/p>\n<pre><span style=\"color: #ff6600;\"><code>import os\r\nimport sys\r\n\r\n# add this plugin to the python search path\r\nfolder = os.path.dirname(__file__)\r\nif folder not in sys.path:\r\n    sys.path.insert(0, folder)<\/code><\/span><\/pre>\n<p><\/p>\n<p>The <em>SmartHNOptions.pyp<\/em>\u00a0will also have to register our plugin with Cinema 4D, but let&#8217;s do that later and finish the general structure first.<\/p>\n<p>Your plugins should exist of at least one package which should be named after the plugin &#8211; try to come up with unique names here so you don&#8217;t collide with other plugins.<\/p>\n<p>I called it <em>smarthnoptions<\/em>\u00a0and placed an empty <em>__init__.py<\/em> file within the folder immediately &#8211; without that file the package will be ignored.<br \/>\n<\/p>\n<h2>STEP 2: RES-Folder<\/h2>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1293\" title=\"_\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2012\/02\/stripe2.jpg\" alt=\"\" width=\"683\" height=\"88\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2012\/02\/stripe2.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2012\/02\/stripe2-300x38.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>Then we create another subfolder next to the <em>smarthnoptions<\/em> package &#8211; the <em>res<\/em> folder.<\/p>\n<p>The <em>res<\/em> folder includes everything Cinema 4D will need to create and handle the GUI for your plugin &#8211; symbols, strings, the layout and images or other assets.<\/p>\n<p>You just have to follow conventions here &#8211; the <em>res<\/em> folder always includes the <em>c4d_symbols.h<\/em>\u00a0&#8211; the header file which includes an enumeration of symbols used to identify every GUI-object or string you use &#8211; and at least two folders:<br \/>\n<em>dialogs<\/em> and <em>strings_us<\/em> (only if your CommandData plugin actually has a dialog &#8211; otherwise you may skip the <em>dialog<\/em> folder(s)). <em>strings_us<\/em> also includes another <em>dialog<\/em> directory.<\/p>\n<p>For each dialog there is a <em>[dialog name].res<\/em> file within the <em>dialog<\/em> folder and a <em>[dialog name].str<\/em> within <em>strings_us\/dialog<\/em>.<br \/>\nThe *.res file describes the dialogs layout, the *.str file the strings used by those GUI-elements.<\/p>\n<p>Last but not least there is a <em>c4d_strings.str<\/em> file directly within the <em>strings_us<\/em> folder &#8211; this one is used for all strings you need to load on runtime (error-messages etc).<\/p>\n<p>As you might have already guessed, the <em>strings_us<\/em> folder has the &#8216;_us&#8217; extension because this is the default &#8211; but you can add a &#8216;strings_de&#8217; folder for example and localize your plugin to German &#8211; or French, Italian, Japanese&#8230;<br \/>\n<br \/>\nThis about covers the <em>res<\/em> folder &#8211; have a look at the provided files and I encourage you to read up on the topic in the documentation (misc\/pluginstructure.html).<br \/>\n<\/p>\n<h2>STEP 3: Hack away&#8230;<\/h2>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1295\" title=\"_\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2012\/02\/stripe1.jpg\" alt=\"\" width=\"683\" height=\"88\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2012\/02\/stripe1.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2012\/02\/stripe1-300x38.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>Let&#8217;s finish the boring part and lay out the python part of our plugin:<\/p>\n<p>We will need a convenient way to reference to GUI-elements by their correct symbol ID which was specified within the <em>c4d_symbols.h<\/em>.<\/p>\n<p>So I created a <em>ids.py<\/em>\u00a0file and basically copied the constants from the enum into it.<br \/>\nThus we can import that file and refer to GUI-elements by their constant name and don&#8217;t have to juggle a lot of abstract numbers.<\/p>\n<p>If you are building a huge plugin, you might want to consider parsing the <em>c4d_symbols.h<\/em>, but that\u2019s a future post&#8230;<\/p>\n<p>Then I created a <em>cmddata.py<\/em> &#8211; short for CommandData (avoid using names from the Cinema 4D API!).<\/p>\n<p><span style=\"color: #ff6600;\"><code># this class is the basic plugin<br \/>\nclass CMDData(c4d.plugins.CommandData):<\/span><\/code><br \/>\n<\/p>\n<p>It includes a class that derives from c4d.plugins.CommandData and is the plugin in itself &#8211; once executed (<em>Execute()<\/em>) it creates the dialog.<\/p>\n<p>The dialog however is another *.py file &#8211; <em>maindialog.py<\/em> which derives from c4d.gui.GeDialog &#8211; it will load it&#8217;s layout from the <em>maindialog.res<\/em> and start the actual script which I called <em>worker.py<\/em>.<\/p>\n<p>Now we head back to the <em>SmartHNOptions.pyp<\/em> and import the ids, cmddata and maindialog.<\/p>\n<p>Note this detail: the maindialog is injected the GeResource object <em>__res__<\/em> into its module scope, this will enable API functions such as <em>LoadDialogResource()<\/em> or <em>GeLoadString()<\/em>\u00a0to access the plugins resources.<br \/>\n<span style=\"color: #ff6600;\"><code><br \/>\n# make the GeResource object available to modules which need<br \/>\n#access to the *.res or *.str files<br \/>\nmaindialog.__res__ = __res__<\/code><\/span><br \/>\n<br \/>\nAnd finally &#8211; once the file is executed, we quickly load the icon and register the plugin with Cinema 4D.<\/p>\n<p><span style=\"color: #ff6600;\"><code># register the plugin<br \/>\nif __name__ == \"__main__\":<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0 \u00a0 # load an icon<\/span><br \/>\n<span style=\"color: #ff6600;\">\u00a0 \u00a0 icon = c4d.bitmaps.BaseBitmap()<\/span><br \/>\n<span style=\"color: #ff6600;\">\u00a0 \u00a0 icon.InitWith(os.path.join(os.path.dirname(__file__), \"res\", \"icon.tif\"))<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0 \u00a0 # get the plugin title from the string resource<\/span><br \/>\n<span style=\"color: #ff6600;\">\u00a0 \u00a0 title = c4d.plugins.GeLoadString(ids.STR_TITLE)<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0 \u00a0 c4d.plugins.RegisterCommandPlugin(ids.PLUGINID, title, 0, icon, title, cmddata.CMDData())<\/code><\/span><br \/>\n<br \/>\nFrom here on, things should be obvious from the source and comments &#8211; please let me know if you have any questions or suggestions.<br \/>\n<br \/>\nHappy plugin coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So far we already covered IDE-setup and debugging &#8211; new let&#8217;s go and actually build something! This is meant to be a simple template of the most common plugin type in Cinema 4D &#8211; the CommandData plugin. Smart HN-Options is a very simple tool that allows to globally change the parameters of every HyperNURBS object within the scene. Grab the plugin and source! (Eclipse project &hellip; <a href=\"http:\/\/www.smart-page.net\/blog\/2012\/02\/22\/smart-hn-options-cinema-4d-python-commanddata-plugin-template\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Smart HN-Options &#8211; Cinema 4D Python CommandData Plugin Template<\/span> <span class=\"meta-nav\">&raquo;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[52,53,1,88],"tags":[175,184,185],"_links":{"self":[{"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/posts\/1292"}],"collection":[{"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/comments?post=1292"}],"version-history":[{"count":62,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/posts\/1292\/revisions"}],"predecessor-version":[{"id":1358,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/posts\/1292\/revisions\/1358"}],"wp:attachment":[{"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/media?parent=1292"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/categories?post=1292"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/tags?post=1292"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}