{"id":1215,"date":"2011-05-09T00:31:06","date_gmt":"2011-05-08T22:31:06","guid":{"rendered":"http:\/\/www.smart-page.net\/blog\/?p=1215"},"modified":"2012-11-04T03:57:31","modified_gmt":"2012-11-04T01:57:31","slug":"advanced-python-plugin-coding-for-cinema-4d","status":"publish","type":"post","link":"http:\/\/www.smart-page.net\/blog\/2011\/05\/09\/advanced-python-plugin-coding-for-cinema-4d\/","title":{"rendered":"Advanced Python plugin coding for Cinema 4D"},"content":{"rendered":"<p>It&#8217;s been a long time&#8230; how have you been?<\/p>\n<p>This is going to be another Python\/Cinema 4D related post.<\/p>\n<p>While python is great for quickly scripting workflow optimizing tools, prototype stuff or write generators and tags, is it suited for big, complex plugin development?<\/p>\n<p><!--more-->It is!<\/p>\n<p>You get &#8216;nearly&#8217; full access to the C++ API of Cinema 4D, don&#8217;t have to compile or worry much about platform dependencies, can easily find a ton of neat recipes and libraries out there&#8230;<\/p>\n<p>So it\u2019s not only possible to code full-fledged python plugins but it even has its advantages over classical C++ development.<\/p>\n<p>Imagine you wrote a nifty script, decided to make it a simple plugin, and now want to take it a step further &#8211; add more features, a complex GUI with some dialogs etc&#8230;<\/p>\n<p>If you are still working with the script editor by now, things will most likely start to get out of hand as you introduce more modules and classes, deal with more code and more functionality.<\/p>\n<p>This is the point where you might want to look out for a little help.<\/p>\n<p>We are going to set up an IDE (Integrated Development Environment), talk a bit about modules\/packages and finally I will try to give some general hints and tips.<br \/>\n<\/p>\n<h1>Coding Environment\/IDE:<\/h1>\n<h2>Prepare Cinema 4D:<\/h2>\n<p>You may skip this part, but I highly recommend it:<\/p>\n<ul>\n<li>Make a copy of your Cinema 4D installation &#8211; name it <em>&#8220;Cinema 4D R12 Dev&#8221;<\/em> for example.<\/li>\n<li>Get rid of all Cinema 4D plugins you don&#8217;t need for your development<\/li>\n<li>Place an empty text file named <em>&#8220;c4d_debug.txt&#8221;<\/em> into the root folder of your Cinema 4D copy.<\/li>\n<\/ul>\n<p>This will slow Cinema 4D down a bit, but enables you to monitor memory leaks.<\/p>\n<p>We will add some useful things on Cinema 4D-side later &#8211; for now let&#8217;s continue with the Eclipse setup&#8230;<br \/>\n<\/p>\n<h2>Python:<\/h2>\n<p>In order to get auto completion to work within PyDev, we are going to need a separate python interpreter &#8211; 2.6.4 to be exact.<br \/>\nJust download an install it from <a href=\"http:\/\/www.python.org\/download\/releases\/2.6.4\/\">here<\/a>.<br \/>\n<\/p>\n<h2>Eclipse:<\/h2>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1217\" title=\"eclipse\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/eclipse.jpg\" alt=\"\" width=\"683\" height=\"101\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/eclipse.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/eclipse-300x44.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>If you never used one, think of an IDE as your workshop, it\u2019s a collection of tools as well as the place where you do and organize your coding work.<\/p>\n<p>Eclipse is one of the most popular &#8211; its Java based, open source, free to use and most importantly has excellent support for python.<\/p>\n<p>So let&#8217;s start by downloading and installing Eclipse Classic from <a href=\"http:\/\/www.eclipse.org\/downloads\/\" target=\"_blank\">http:\/\/www.eclipse.org\/downloads\/<\/a><br \/>\nIf you don&#8217;t have the <a href=\"http:\/\/www.java.com\/de\/download\/\"  target=\"_blank\">Java Runtime Environment<\/a> installed jet, you need to do this first.<br \/>\n<\/p>\n<h2>PyDev:<\/h2>\n<p>As said before, Eclipse has excellent python support &#8211; but not out of the box, so we are going to install <a href=\"http:\/\/www.pydev.org\" target=\"_blank\">PyDev<\/a>.<\/p>\n<p>PyDev will help you coding by adding syntax highlighting, code completion and much more.<br \/>\nShould you encounter any trouble with the following steps, please refer to the PyDev <a href=\"http:\/\/pydev.org\/manual_101_install.html\" target=\"_blank\">installation manual<\/a>.<\/p>\n<ul>\n<li>After installation, startup Eclipse, click <em>&#8220;Help&#8221;, <\/em>and chose <em>&#8220;Install New Software&#8230;&#8221;.<\/em><\/li>\n<li>Next click the <em>&#8220;Add&#8230;&#8221;<\/em> button, type in <em>&#8220;PyDev&#8221;<\/em> as name and <em>&#8220;http:\/\/pydev.org\/updates&#8221; <\/em>as location &#8211; then confirm.<\/li>\n<li>Now enter <em>&#8220;PyDev&#8221;<\/em> in the <em>&#8220;Work with:&#8221;<\/em> field, you should see an entry<em> &#8220;PyDev for Eclipse&#8221; <\/em>&#8211; check it and click <em>&#8220;Next&#8221;.<\/em><\/li>\n<\/ul>\n<p>After confirming again and accepting the terms, it will download and install.<\/p>\n<ul>\n<li>Click <em>&#8220;Windows&#8221;<\/em> and open the <em>&#8220;Preferences&#8221;<\/em> dialog.<\/li>\n<li>Select PyDev and the child <em>&#8220;Interpreter &#8211; Python&#8221;<\/em><\/li>\n<li>Click <em>&#8220;New&#8230;&#8221;<\/em>, input <em>&#8220;Python Cinema 4D&#8221;<\/em> as name and browse to your interpreter installation.<\/li>\n<li>Select the <em>python.exe<\/em>.\n<li>Confirm your selection and the paths PyDev wants to add to your syspath.<\/li>\n<\/ul>\n<p>So much for the PyDev installation itself, now we have to associate the Cinema 4D Python plugin extension *.pyp with PyDev to enable syntax highlighting and code completion for those files as well:<\/p>\n<ul>\n<li>Open <em>&#8216;Window&#8217;<\/em> within the file-menu and click <em>&#8216;Preferences&#8217;<\/em><\/li>\n<li>Select <em>&#8216;General&#8217; -> &#8216;Content Types&#8217;<\/em> from the list on the left.<\/li>\n<li>In the <em>&#8216;Content types:&#8217;<\/em> view on the right, unfold <em>&#8216;Text&#8217;<\/em> and click <em>&#8216;Python File&#8217;<\/em><\/li>\n<li>Hit the <em>&#8216;Add&#8230;&#8217;<\/em> button of the <em>&#8216;File associations:&#8217;<\/em> list on the lower right, type <em>&#8220;*.pyp&#8221;<\/em> into the popup and confirm.<\/li>\n<\/ul>\n<ul>\n<li>Open <em>&#8216;Window&#8217;<\/em> and click <em>&#8216;Preferences&#8217;<\/em><\/li>\n<li>Select <em>&#8216;PyDev&#8217; -> &#8216;Editor&#8217; -> &#8216;Code Style&#8217; -> &#8216;File Types&#8217;<\/em> from the list on the left.<\/li>\n<li>In the field <em>&#8216;Valid source files (comma-separated):&#8217;<\/em> on the right, add <em>, pyp<\/em> and confirm.<\/li>\n<\/ul>\n<p>\nIts helpful to add a fake version of the Cinema 4D Python API\u2019s \u201cc4d\u201d package to the <em>\u2018\/Lib\/site-packages\/&#8217;<\/em> folder of the interpreter to enable auto-completion \u2013 <a href=\"http:\/\/www.smart-page.net\/python\/c4d_fake_package.zip\">grab it here<\/a>.<br \/>\n<br \/>\nThese are fake modules and they have their drawbacks &#8211; read more about them in <a href=\"http:\/\/www.smart-page.net\/blog\/2012\/11\/04\/python-cinema-4d-api-auto-completion-fake-modules\/\" target=\"_blank\">this blog post<\/a>.<br \/>\n<\/p>\n<h2>Project setup<\/h2>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1218\" title=\"construction\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/construction.jpg\" alt=\"\" width=\"683\" height=\"134\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/construction.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/construction-300x58.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>We take your IDE for a spin and create the first project:<\/p>\n<ul>\n<li>Click <em>&#8220;File&#8221; &#8211; &#8220;New&#8221;<\/em> and chose <em>&#8220;PyDev Project&#8221;<\/em><\/li>\n<li>Input a Name for your Project and uncheck the <em>&#8220;Use default&#8221; <\/em>box below.<\/li>\n<li>Browse to your Cinema 4D installations plugin folder, create a new directory with your plugins name and select it.<\/li>\n<li>Select<em> &#8220;2.6&#8221; <\/em>from the <em>&#8220;Grammar Version&#8221;- <\/em>dropdown and leave the Interpreter set to default.<\/li>\n<li>Last but not least uncheck the <em>&#8220;Create default &#8216;src&#8217; folder&#8230;&#8221; checkbox and hit &#8220;Finish&#8221;.<\/em><\/li>\n<\/ul>\n<p>To setup the needed folder structure, header- resource- and string files for your plugin, please read the Cinema 4D Python documentation <em>\u201cPlugin structure\u201d<\/em> &#8211; \u00a0especially <em>\u201cDirectory structure\u201d<\/em> &#8211; and take a look at the Python plugin examples within the documentation &#8211; or the experimental plugin from <a href=\"http:\/\/www.smart-page.net\/blog\/2010\/09\/10\/a-raytracer-in-python-for-cinema-4d\" target=\"_blank\">this post<\/a>:<\/p>\n<p>Just remember this part is vital, so do not rush through it &#8211; at least read the section mentioned above and take a good look at the SDK examples.<\/p>\n<p>Only if you have built C++ plugins before and are already familiar with the structure, you may&#8230;<br \/>\n<\/p>\n<h4>Hint:<\/h4>\n<p>You can also add your existing project files by just placing them within the plugin-directory we just created, or dragging them into the project-folder within Eclipse.<\/p>\n<p>When organizing the file structure within your project, you are working with your file system &#8211; changes you do here are reflected on your harddisk.<br \/>\nThis also works the other way round, move something on the file system and Eclipse will update those changes to your project &#8211; while not always instantly.<\/p>\n<p>You can press F5 within Eclipse to update a folder and its subfolders or the contents of a file.<\/p>\n<p>Don&#8217;t worry, if the project-view is out of sync with the file system &#8211; Eclipse will tell you.<br \/>\n<\/p>\n<h2>A coders Cinema 4D:<\/h2>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1219\" title=\"c4d\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/c4d.jpg\" alt=\"\" width=\"683\" height=\"112\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/c4d.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/c4d-300x49.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>We are all set with the IDE part &#8211; let&#8217;s tune the Cinema 4D installation a bit more to improve the workflow and finalize your coding environment.<\/p>\n<p>If you didn&#8217;t add\/import your existing code to the project we just created, write a simple hello world and fire up Cinema.<\/p>\n<p>It&#8217;s a good idea to setup a developer friendly layout, I like adding the console window to the tabs on the right, next to the object manager &#8211; or even better to a side monitor.<br \/>\nShould you be writing a CommandData Plugin, consider opening the Command Manager and dragging its icon into the layout, so you can quickly re-open it.<\/p>\n<p>You will be launching and closing Cinema 4D a lot during development &#8211; it&#8217;s helpful to have a strategy to quickly start and close it.<br \/>\nPlace a link to Cinema 4D on your taskbar\/dock, close it using <em>ALT+F4\/Command+Q<\/em> or create a little python script containing <em>&#8220;exit()&#8221; <\/em>and add it to the layout\/create a shortcut.<\/p>\n<p>Finally, open your Plugin as well as everything you need to test its functionality and save the layout as startup layout.<\/p>\n<p>If you have a test document that you need to check your plugin, press <em>CTRL+E<\/em>, click the &#8220;Open Preferences Folder&#8230;&#8221; button and place it as &#8220;default.c4d&#8221; within that folder so it will load on startup.<\/p>\n<p>You long got the idea &#8211; try to prepare everything so you don&#8217;t have to spend time doing recurring tasks on every unit-test you are going to make during development.<br \/>\n<\/p>\n<h2>Some additional tools:<\/h2>\n<p>It&#8217;s often helpful to keep an eye on memory consumption and or active threads so I always have the task manager\/activity monitor in reach when coding.<\/p>\n<p>And while not really necessary, it&#8217;s convenient to have a good, fast text editor with Python syntax highlighting so you are able to read a file or snippet without having to launch the IDE first.<br \/>\nI can recommend <a href=\"http:\/\/notepad-plus-plus.org\/\" target=\"_blank\">Notepad++<\/a> and <a href=\"http:\/\/macromates.com\/\" target=\"_blank\">TextMate <\/a>or <a href=\"http:\/\/www.gnu.org\/software\/emacs\/\" target=\"_blank\">Emacs <\/a>for this job.<br \/>\n<\/p>\n<h1>Working with eclipse:<\/h1>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1220\" title=\"prototype\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/prototype.jpg\" alt=\"\" width=\"683\" height=\"134\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/prototype.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/prototype-300x58.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>Eclipse in combination with PyDev is a mighty! tool &#8211; Aside from the obvious killer features &#8211; syntax highlighting and code completion, there is a ton of others.<\/p>\n<p>Often you will discover some that will make you feel bad for not having used them right from the start, so I&#8217;ll try to point out the most useful, while I encourage you to read up on Eclipse and PyDev.<br \/>\n<\/p>\n<h3>The Find\/Replace Dialog<\/h3>\n<p>Press CTRL+F for all your search and replace needs \u2013 just listing it to make you aware of the direction-, selection- and regex support.<br \/>\nIf you haven&#8217;t used regular expressions jet, you should directly head over to <a href=\"http:\/\/en.wikipedia.org\/wiki\/Regular_expression\" target=\"_blank\">Wikipedia <\/a>&#8211; you won&#8217;t regret it.<\/p>\n<p>Even more powerful is the&#8230;<br \/>\n<\/p>\n<h3>Search Dialog<\/h3>\n<p>CTRL+H opens the global or project wide search \u2013 here you can also replace over all files.<\/p>\n<p>Just keep in mind that the &#8220;PyDev Search&#8221; tab does only look within *.py files while the &#8220;File Search&#8221; tab by default searches over a *.* pattern.<br \/>\n<\/p>\n<h3>Compare feature and history<\/h3>\n<p>Just select two files, right click and chose <em>&#8220;Compare with&#8221; -&gt; &#8220;Each other&#8221;.<\/em><\/p>\n<p>You can also compare a file with an earlier state of itself by choosing <em>&#8220;Local history&#8221;.<\/em><\/p>\n<p>This is another huge plus of using an Eclipse &#8211; don&#8217;t worry anymore about changing huge sections of code or commenting it &#8211; just go ahead and delete it &#8211; you can always return to an earlier state using the &#8220;History&#8221;- tab.<\/p>\n<p>But use this with care, as it\u2019s possible to lose the history by moving or re-creating a project and it\u2019s not infinite.<br \/>\n<\/p>\n<h3>Tabbed views<\/h3>\n<p>You can drag a tab to one side of the code view until a small arrow appears &#8211; the tab will then snap to that side, splitting your view so you can work with multiple source files at the same time.<\/p>\n<p>This is very useful when working with the header-, resource- or string files of your project as you can code on the left and copy &#8216;n paste ID&#8217;s from the right for example.<br \/>\n<\/p>\n<h1>Coding python for Cinema 4D:<\/h1>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1221\" title=\"python\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/python.jpg\" alt=\"\" width=\"683\" height=\"126\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/python.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/python-300x55.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>We have setup the coding environment &#8211; how about doing some programming now?<\/p>\n<p>This will be a loose collection of tips that are all more or less Cinema 4D related, but mostly \u00a0good practice in general.<br \/>\n<\/p>\n<h3>Modules and namespace:<\/h3>\n<p>First &#8211; this is <a href=\"http:\/\/en.wikipedia.org\/wiki\/Object-oriented_programming\" target=\"_blank\">OOP <\/a>(Object Oriented Programming) and your project&#8217;s structure should reflect that.<\/p>\n<p>In general, classes and modules are a good thing, it&#8217;s a far more common fault to have less abstraction than too much.<\/p>\n<p>Packages\/Modules are also the key to keep your code organized, manageable &#8211; AND reusable.<\/p>\n<p>So if you are going to write something that you might want to use again later, consider spending the extra time to make it a bit more user\/coder-friendly and build a class or module.<\/p>\n<p>When working with python and modules you have to keep a close eye on naming and namespace, especially in context with the Cinema 4D SDK.<\/p>\n<p>Be creative and use unique module names &#8211; this will keep things easier when you are using other modules &#8211; and you will &#8211; at least the ones from the Cinema 4D API.<br \/>\nAlso be careful when importing from modules &#8211; it&#8217;s rarely a good idea to just import everything (<em>from foo import *<\/em>) &#8211; instead carefully select the members you really need and give everyone its own import line rather than stacking them with commas in one.<\/p>\n<p>It&#8217;s often better to just import the module into your namespace and reference the members via <em>module.foo<\/em> \u2013 you don\u2019t pollute your namespace and it\u2019s more readable.<\/p>\n<p>In any case you should avoid the API&#8217;s module AND member names like the plaque.<\/p>\n<p>For example if you extend the GeDialog Class and have a method <em>&#8220;def close(self):&#8221;<\/em> &#8211; but make the slight mistake to call it as <em>&#8220;Close()&#8221;<\/em>, you might end up with a similar behavior but wonder for minutes while your dialog just closes without saving it&#8217;s settings first (or whatever \u201c<em>close()\u201c<\/em> should have done).<\/p>\n<p>I know for some this is basic stuff &#8211; many have their own patterns for this and that\u2019s ok!<\/p>\n<p>Whatever you do &#8211; be consistent and aware of your namespace.<br \/>\n<\/p>\n<h3>Symbols:<\/h3>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1223\" title=\"symbols\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/symbols1.jpg\" alt=\"\" width=\"683\" height=\"112\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/symbols1.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/symbols1-300x49.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>As you need to keep track of the enums within the c4d_symbols.h, it is best to define every integer by yourself and not auto-enumerate them.<\/p>\n<p>Then mirror those symbols to a *.py file called <em>&#8220;ids.py&#8221;<\/em> and be careful to update both should you change them or introduce new ones.<\/p>\n<p>Instead of hardcoding ID&#8217;s, you should always use the symbol within the c4d-package.<br \/>\nShould you ever need to identify a symbol by it&#8217;s integer value (for example if you want to check for a certain flag that is returned) &#8211; this little script will help you out:<\/p>\n<pre>import c4d;\r\nfrom c4d import gui; \r\n\r\ndef main():\r\n    wanted = gui.RenameDialog(\"ID to search for...\")\r\n    outp = \"\"\r\n\r\n    for itm in dir(c4d):\r\n        s = getattr(c4d, itm)\r\n        if s == int(wanted):\r\n            outp += \"%s = %s\\n\" % (itm, s)\r\n\r\n    gui.MessageDialog(\"Sorry - none found...\" if outp == \"\" else outp)\r\n\r\nif __name__=='__main__':\r\n    main()<\/pre>\n<p><\/p>\n<h3>API calls \/ performance:<\/h3>\n<p>Don&#8217;t get me wrong &#8211; the Python API is blazing fast &#8211; so fast you often can&#8217;t tell the difference to C++ &#8211; but still, API calls take time.<br \/>\nWhen working with thousands of objects, this quickly adds up no matter how fast each individual call is.<\/p>\n<p>Try to limit those calls in sections of your code, where you really need performance &#8211; look for ways to keep states within your own plugin logic rather than querying them form Cinema 4D whenever possible.<\/p>\n<p>If you are looking for bottlenecks, be sure to check out <a href=\"http:\/\/docs.python.org\/library\/profile.html\" target=\"_blank\">cProfile <\/a>\u2013 it\u2019s great.<br \/>\n<\/p>\n<h3>Prototyping:<\/h3>\n<p>Using an IDE doesn&#8217;t forbid you to use Cinema 4D&#8217;s script editor and console to quickly whip up and test something &#8211; you can even write and directly execute a simple test script within eclipse if you are working on parts of your plugin that don&#8217;t need the Cinema SDK (some kind of parser for example) and take advantage of the PyDev debugger.<br \/>\n<\/p>\n<h3>Debugging:<\/h3>\n<p>The lack of a real debugger can be compensated by using the <a href='http:\/\/www.smart-page.net\/blog\/2011\/05\/29\/debugging-cinema-4d-python-plugins-with-pydev\/' target='_blank'>PyDev remote debugger<\/a>, pythons inspect module and the logging package.<\/p>\n<p>Remember that there is a limit to the amount of characters the Cinema 4D console can output for a single print command.<\/p>\n<p>Also take a look at <a href=\"http:\/\/docs.python.org\/library\/sys.html\" target=\"_blank\"><em>sys.exc_info()<\/em><\/a><br \/>\n<\/p>\n<h3>Garbage Collection:<\/h3>\n<p>When introducing <a href=\"http:\/\/en.wikipedia.org\/wiki\/Circular_reference\" target=\"_blank\">circular references<\/a> you should use <a href=\"http:\/\/docs.python.org\/library\/weakref.html\" target=\"_blank\">weak references<\/a> to give the garbage collector a hand.<br \/>\n<\/p>\n<h3>Compilation:<\/h3>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1226\" title=\"stuff\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/stuff.jpg\" alt=\"\" width=\"683\" height=\"112\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/stuff.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/stuff-300x49.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>How about shipping your plugin as precompiled byte code?<\/p>\n<p>This will make Cinema 4D start up faster &#8211; as the compilation of your plugin can be skipped, obfuse your source and still be platform interoperable.<\/p>\n<p>Just copy your plugin, open the console\/terminal and execute <em>&#8220;python.exe &#8211;<a href=\"http:\/\/docs.python.org\/library\/compileall.html\" target=\"_blank\">mcompileall <\/a>C:\\PathToMyPlugin&#8221;<\/em> and delete all *.py files afterwards.<\/p>\n<p>Note that this might not work in some cases, so be sure to test your plugins functionality again.<br \/>\n<\/p>\n<h3>Platform dependency:<\/h3>\n<p>While Python is platform-independent, there are still some things to keep in mind.<\/p>\n<p>Don&#8217;t use backslashes in paths but slashes &#8211; they are understood by windows AND mac OS.<\/p>\n<p>You can also use <a href=\"http:\/\/docs.python.org\/library\/platform.html\" target=\"_blank\"><em>platform.system()<\/em><\/a> to determine on what OS your plugin runs on and import modules after a conditional check &#8211; for example:<\/p>\n<pre>if platform.system().lower() == \"windows\":<\/pre>\n<pre>    import winsound\r\n    winsound.PlaySound(os.path.join(os.path.dirname(__file__), \"..\/res\/snd\", \"DingSound.wav\"),\r\nwinsound.SND_FILENAME)<\/pre>\n<p><\/p>\n<h3>GUI &#8211; Threading:<\/h3>\n<p>It&#8217;s the old story, if the GUI thread has to wait for your plugin, you lock up Cinema 4D &#8211; unacceptable for the user.<\/p>\n<p>Doing time intensive stuff within your own threads is the simple solution to this, but keep in mind that you can&#8217;t have them call the GUI thread &#8211; instead use messages and the GeDialog&#8217;s <em>SetTimer().<\/em><br \/>\n<\/p>\n<h3>Resource reference:<\/h3>\n<p>Classes that use the &#8220;plugins&#8221; module need a reference to the plugins resource pointer.<\/p>\n<p>This can be handled by importing those classes within the plugins *.pyp file and setting the class variable <em>&#8220;__res__&#8221;<\/em> or using a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Singleton_pattern\" target=\"_blank\">singleton <\/a>(see below).<br \/>\n<\/p>\n<h3>Singletons and invading Borgs:<\/h3>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-1224\" title=\"borg\" src=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/borg.jpg\" alt=\"\" width=\"683\" height=\"107\" srcset=\"http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/borg.jpg 683w, http:\/\/www.smart-page.net\/blog\/wp-content\/uploads\/2011\/05\/borg-300x46.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>This is something for the advanced developer &#8211; and kind of a hot topic too.<\/p>\n<p>The use of globally accessible objects or \u2018globals\u2019 is often considered bad practice but also unavoidable in some cases (logger) and python even somewhat encourages it.<\/p>\n<p>So if you know what you are doing and think about using a singleton, you might want to take a look at the &#8220;borg&#8221;-(anti)pattern &#8211; a monostate proxy with a twist.<\/p>\n<pre>class Borg:<\/pre>\n<pre>__we_are_one = {}<\/pre>\n<pre>    def __init__(self):\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n    self.__dict__ = self.__we_are_one<\/pre>\n<p><\/p>\n<h1>Still alive<\/h1>\n<p>This was a lot of compressed stuff to digest, I know, but please do me the favor and don\u2019t let any of this scare you off, it\u2019s easier and more fun than you would expect.<\/p>\n<p>I am sorry some topics where not covered in the depth they deserve &#8211;\u00a0 it wasn\u2019t easy to keep this a readable post rather than a book\u2026<\/p>\n<p>I hope this still was helpful to someone, if you have any questions, thoughts or would like me to write a more detailed post on a certain topic &#8211; let me know.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s been a long time&#8230; how have you been? This is going to be another Python\/Cinema 4D related post. While python is great for quickly scripting workflow optimizing tools, prototype stuff or write generators and tags, is it suited for big, complex plugin development?<\/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":[180,179,178,181,195,182],"_links":{"self":[{"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/posts\/1215"}],"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=1215"}],"version-history":[{"count":50,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/posts\/1215\/revisions"}],"predecessor-version":[{"id":1247,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/posts\/1215\/revisions\/1247"}],"wp:attachment":[{"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/media?parent=1215"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/categories?post=1215"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.smart-page.net\/blog\/wp-json\/wp\/v2\/tags?post=1215"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}