Giter VIP home page Giter VIP logo

c4d-prototype-converter's Introduction

Cinema 4D Prototype Converter

This plugin aids you in converting your Cinema 4D Python plugin prototype to a plugin.

Script Converter

This tool converts a Cinema 4D Python Script to a CommandData plugin. Scripts you convert with this tool should have a main() function.

Features

  • The main() function will be automatically converted to a CommandData.Execute() method

Prototype Converter

This tool converts a Cinema 4D Python Generator or Expression Tag to a ObjectData or TagData plugin.

Features

  • Converts UserData to description resource files

  • Converts main() and message() functions in your Python code to the respective plugin member method (GetVirtualObjects(), Execute(), Message())

  • Replaces uses of op[c4d.ID_USERDATA,X] with the automatically generated resource symbols

FAQ

How to install the Plugin?

Downloading the source code from GitHub is not sufficient as it will not include Git submodules. Check the [Releases][] page to find the latest downloadable release or use a Git client to clone the repository recursively into your Cinema 4D plugins directory.

Where to find the Plugin in Cinema 4D?

After you have installed the plugin, you can find it in the Cinema 4D Script menu.

How does the code refactoring work?

We use the lib2to3 module from the Python standard library to parse and transform your code so that it (somewhat) matches the way it needs to be for Python plugins and to adjust the indentation.

Ideas for the Future

  • Report possible errors during conversion (eg. referencing the variables doc or op in global functions without previously declaring them)

Acknowledgements

This project is sponsored by Maxon US and was created for Cineversity.com's CV-Toolbox.

Changes

v1.2.0

  • Update third-party libraries (nr.c4d, nr.types, six)
  • Make Script Converter and Prototype Convert commands visible in Commander (Shift+C)
  • Fix #48 – DEFAULT property with UNIT PERCENT does NOT need to be multiplied by 100
  • Fix #49 – "Animatable" user data parameter - error when OFF

v1.1.0

  • Initial public release

Copyright © 2018 Niklas Rosenstein

c4d-prototype-converter's People

Contributors

niklasrosenstein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

c4d-prototype-converter's Issues

Add Support for Parameter Defaults

This is probably a non-trivial issue, but it would be great if parameters could be initialized with default values based on the Default Value setting in the UserData Editor.

IDEA: Add Line Break before Group IDs in `res()`

Current Behavior:

    CV_PS_RANGE_GROUP = 1045
    CV_PS_RANGE_GROUP1 = 1046
    CV_PS_FROM1 = 1047
    CV_PS_TO1 = 1048
    CV_PS_EVERY = 1049
    CV_PS_OFFSET1 = 1050
    CV_PS_BOUNDS_GROUP = 1051
    CV_PS_MINMAX_GROUP = 1052
    CV_PS_X = 1053
    CV_PS_X1 = 1054
    CV_PS_Y = 1055
    CV_PS_Y1 = 1056
    CV_PS_Z = 1057
    CV_PS_Z1 = 1058
    CV_PS_POLY_TYPE_GROUP = 1059
    CV_PS_POLY_TYPE_TRIANGLES = 1060
    CV_PS_POLY_TYPE_QUADRANGLES = 1061
    CV_PS_POLY_TYPE_NNGONS = 1062
    CV_PS_CIRCUMFERENCE_GROUP = 1063
    CV_PS_CIRCUMFERENCE_MIN = 1064
    CV_PS_CIRCUMFERENCE_MAX = 1065
    CV_PS_DISTANCE_GROUP = 1066
    CV_PS_DISTANCE_TARGETS = 1067
    CV_PS_DISTANCE_MAX_DISTANCE = 1068

Ideal Behavior:

    CV_PS_RANGE_GROUP = 1045

    CV_PS_RANGE_GROUP1 = 1046
    CV_PS_FROM1 = 1047
    CV_PS_TO1 = 1048
    CV_PS_EVERY = 1049
    CV_PS_OFFSET1 = 1050

    CV_PS_BOUNDS_GROUP = 1051

    CV_PS_MINMAX_GROUP = 1052
    CV_PS_X = 1053
    CV_PS_X1 = 1054
    CV_PS_Y = 1055
    CV_PS_Y1 = 1056
    CV_PS_Z = 1057
    CV_PS_Z1 = 1058

    CV_PS_POLY_TYPE_GROUP = 1059
    CV_PS_POLY_TYPE_TRIANGLES = 1060
    CV_PS_POLY_TYPE_QUADRANGLES = 1061
    CV_PS_POLY_TYPE_NNGONS = 1062

    CV_PS_CIRCUMFERENCE_GROUP = 1063
    CV_PS_CIRCUMFERENCE_MIN = 1064
    CV_PS_CIRCUMFERENCE_MAX = 1065

    CV_PS_DISTANCE_GROUP = 1066
    CV_PS_DISTANCE_TARGETS = 1067
    CV_PS_DISTANCE_MAX_DISTANCE = 1068

This would make it quite a bit easier to scan a big block of ids.

Selected Pre-Existing Icon Results in Error

image

Error
image

Traceback (most recent call last):
  File "D:\Donovan\MAXON\plugins\c4d-prototype-converter\c4d_prototype_converter\plugin_main.py", line 999, in Command
    self.do_create()
  File "D:\Donovan\MAXON\plugins\c4d-prototype-converter\c4d_prototype_converter\plugin_main.py", line 887, in do_create
    cnv.create()
  File "D:\Donovan\MAXON\plugins\c4d-prototype-converter\c4d_prototype_converter\plugin_main.py", line 483, in create
    shutil.copy(self.icon_file, files['icon'])
  File "D:\Donovan\MAXON\R19\resource\modules\python\Python.win64.framework\lib\shutil.py", line 119, in copy
    copyfile(src, dst)
  File "D:\Donovan\MAXON\R19\resource\modules\python\Python.win64.framework\lib\shutil.py", line 69, in copyfile
    raise Error("`%s` and `%s` are the same file" % (src, dst))
shutil.Error: `D:\Donovan\MAXON\plugins\cv-cube\res\icons\CV-Cube.tif` and `D:\Donovan\MAXON\plugins\cv-cube\res\icons\CV-Cube.tif` are the same file

To recreate:

  1. Create a plugin stub w/ this tool linking to the external icon.
  2. Re-run the plugin w/ Overwrite enabled, this time select the icon that was added to the icons directory.

BUG: Shutil is trying to a copy a file over itself and spits out an error.

Add Support for Icon IDs in Long Cycle Elements

If I want to include icons next to my drop-down menu types, I use code that looks like:

0;Hinge;180000011
1;Cardan;180000161
2;Ball and Socket;180000162
3;Ragdoll;180000163
4;Slider;180000164
5;Twist Slider;180000165
7;Planar;180000166
8;Box;180000167
9;Wheel Suspension;180000168
6;Fixed;180000169

in the UserData Cycle Option field.

So that I can generate something that looks like:

image

This doesn't survive the auto-conversion process.

image

Script Converter: `main` is not defined

Try to convert the script in this .zip file.

"""Name-US: CV-Hello World
Description-US: Simple plugin that opens a dialog.
"""

import c4d
from c4d import gui


def main():
    gui.MessageDialog('Hello World!')

if __name__=='__main__':
    main()

cv-hello-world.zip

You'll get this error:

Traceback (most recent call last):
  File "'cv-hello-world.pyp'", line 27, in <module>
NameError: name 'main' is not defined

It seems like the issue is this redundant main():

if __name__=='__main__':
    main()

IDEA: Set Default Plugin Directory

By default, place plugins in the User's AppData plugins folder. On Windows it's something that looks like: C:\Users\Donovan\AppData\Roaming\MAXON\R19_D9AA84E9. Typically accessible via Edit > Preferences > Open Preferences Folder

Default folder name should be the same as the hyphenated plugin name.

Accessing resource symbols in the Python Plugin Stub

@donovankeith

Using the c4d. module for resource symbols defined in description resources of your plugin is dangerous because of how easily Cinema 4D's symbol cache goes out of date. If you create the resource files for your plugin once, then add a parameter and update the resource files again, the newly added parameter is likely not in the symbol cache.

Personally, I prefer to use the c4ddev symbols command to generate Python code that contains all resource symbols. The automatic code generation makes it very easy to update the symbol information in the Plugin, just run the command again and copy&paste the output into the plugin source code.

I am not sure how easily this can be combined with the automatic plugin source code generator in the UserData to Description Resource Convert. One possibility would be to use res. instead of c4d. everywhere in the generated plugin stub, and add a note at the top of the stub

import c4d

# Note: It is not recommended to access your plugin's resource symbols via the c4d
# module due to how quickly the Cinema 4D symbol cache goes out of date. We
# recommend hard-coding your resource symbols in your source file. This code can
# be automatically generated with C4DDev (see https://github.com/NiklasRosenstein/c4ddev).
res = c4d

class MyPluginData(c4d.plugins.ObjectData):
  # ...
  def InitAttr(self, node):
    node[res.MY_PLUGIN_FOOBAR] = 42
    return True

This way, the user could easily drop in a replacement object with the name res and he/she will not need to modify the code further.

Set `Resource Symbols` default to `C4DDev`

image

# Note: It is NOT recommended to use the Cinema 4D module to access your
# plugin's resource symbols. The C4DDev project contains tools that can
# parse resource files and generate Python code with all the symbols.

If we're going to go to the trouble of writing this warning, might as well give them a default that avoids it in the first place.

Error with Linked Icon

Possibly related to Issue #10

Saved settings to object "Stagger Animation".
Traceback (most recent call last):
  File "D:\Donovan\MAXON\plugins\c4d-prototype-converter\c4d_prototype_converter\plugin_main.py", line 895, in Command
    self.do_create()
  File "D:\Donovan\MAXON\plugins\c4d-prototype-converter\c4d_prototype_converter\plugin_main.py", line 787, in do_create
    cnv.create()
  File "D:\Donovan\MAXON\plugins\c4d-prototype-converter\c4d_prototype_converter\plugin_main.py", line 433, in create
    shutil.copy(self.icon_file, files['icon'])
NameError: global name 'shutil' is not defined

I ran into this when trying to convert the Python Expression tag in the attached file.

DelayAnimationExpression.zip

BUG: Script Pulldown List Doesn't Search Sub-Directories

The scripts pulldown list only shows scripts in the root level of the /library/scripts/ directory. It should show all valid script files, including those in sub-directories.

If the script is in a sub-directory, it should perhaps be indented w/ the directory name, or show the sub-path.

Auto-replace `[c4d.ID_USERDATA,1]` with `[res.PLUGPREFIX_VALUE]`

If I have code like

cube[c4d.PRIM_CUBE_LEN] = op[c4d.ID_USERDATA,1]

I end up with the following error

Traceback (most recent call last):
  File "'cv-cube.pyp'", line 60, in GetVirtualObjects
AttributeError: parameter access failed

It should be auto-replaced with:

cube[c4d.PRIM_CUBE_LEN] = op[res.CV_CUBE_SIZE]

This way all of the UI Parameters will be linked to the appropriate container values.

You can test with:

CV-Cube.zip

IDEA: Auto-link to the Icon for the Script.

Many scripts have an icon associated with them. I'm not sure how easy this would be to grab, but if possible please copy the icon associated with the script into the new plugin.

Add a TODO List of Common Issues to Check to the Plugin Stub

There will inevitably be limits to this auto-conversion process. As much as possible, let's document the most common ones and include them as # TODO: items in the plugin template. Ideally close to the location where the change would need to occur.

I'm not sure what these are/should be, but I just wanted to start this issue to record and brainstorm.

"""
# TODO: Delete the old/redundant `__main__` check.
# TODO: Customize the icon for this plugin.
# TODO: Delete the original script so there aren't name conflicts when users search with The Commander (`shift + c`)
# TODO: Remove redundant imports
# TODO: Update Copyright information
# TODO: Add a README file
"""

Unable to Convert CV-Paint Fracture

I was unable to convert CV-Paint Fracture

This is the error message:

Traceback (most recent call last):
  File "/Users/donovankeith/Library/Preferences/MAXON/Cinema 4D R19_8DA1506D/plugins/c4d-prototype-converter/c4d_prototype_converter/main.py", line 1269, in Command
    self.do_create()
  File "/Users/donovankeith/Library/Preferences/MAXON/Cinema 4D R19_8DA1506D/plugins/c4d-prototype-converter/c4d_prototype_converter/main.py", line 1216, in do_create
    cnv.create()
  File "/Users/donovankeith/Library/Preferences/MAXON/Cinema 4D R19_8DA1506D/plugins/c4d-prototype-converter/c4d_prototype_converter/main.py", line 1118, in create
    code_parts = codeconv.refactor_command_script(fp.read(), indent='  ')
  File "/Users/donovankeith/Library/Preferences/MAXON/Cinema 4D R19_8DA1506D/plugins/c4d-prototype-converter/c4d_prototype_converter/codeconv.py", line 336, in refactor_command_script
    result['member_code'] = str(fixers[1].results[0])
AttributeError: 'FixStripDocstrings' object has no attribute 'results'

Unkown Customgui Printed to Console

Note: unknown customgui: Combine 200000180
Note: unknown customgui: Mode 200000180
Note: unknown customgui: From 15
Note: unknown customgui: To 15
Note: unknown customgui: Offset 15
Note: unknown customgui: Direction 200000180
Note: unknown customgui: Tolerance 19
Note: unknown customgui: From 15
Note: unknown customgui: To 15
Note: unknown customgui: Every 15
Note: unknown customgui: Offset 15
Note: unknown customgui: X 19
Note: unknown customgui: X 19
Note: unknown customgui: Y 19
Note: unknown customgui: Y 19
Note: unknown customgui: Z 19
Note: unknown customgui: Z 19
Note: unknown customgui: Min 19
Note: unknown customgui: Max 19
Note: unknown customgui: Max Distance 19
Note: unknown customgui: Orientation 200000180
Note: unknown customgui: Tolerance 19
Note: unknown customgui: Minimum Angle 19
Note: unknown customgui: Seed 15
Note: unknown customgui: Seed 15
Note: unknown customgui: Animation Speed 19
Note: unknown customgui: Scale 19
Note: unknown customgui: Max Angle 19
Note: unknown customgui: Tolerance 19
Note: unknown customgui: Iterations 15
Note: unknown customgui: Tolerance 19
Saved settings to object "CV-Parametric Selection v1.0.0".

This is Combine
image

This is Mode
image

This is From/To/Offset
image

And this is the Group that contains them
image

Maybe it has something to do w/ Sub-Groups? Or Columns?

File to test with:
CV-Parametric.zip

"Animatable" user data parameter - error when OFF

When the "Animatable" checkbox is unchecked in the user data manager properties menu, the TagData Plugin fails to load - the error message points to the .res file line wherever there's an ANIMATE OFF;

Leaving all parameters animatable fixes it, or removing all instances of "ANIMATE OFF;" in the res file... But I'd like to have several fields that can't be animated...

IDEA: Copy res() to Clipboard

It would be great if instead of generating a plugin there was a mode/command that would just generate the res() boilerplate and copy it to the clipboard.

class res(object):
    CV_PS_SELECT_GROUP = 1000

res = res()

I'm currently converting CV-Parametric Selection Tag and the toughest part of the process is changing all of my hard-coded IDs to match the ones that are auto-generated by c4d-prototype-converter. If I'd used a command like I'm proposing while developing, it would ensure a more seamless cross-over later.

Add Support for Scripts Located in ENV_VARIABLE Locations

I'm not sure how easy/challenging this would be to implement. Cinema 4D support Environment Variables that allow you to have a secondary location for plugins/scripts. I tend to keep most of my scripts in a dropbox folder so that I can share them between computers/c4d-versions.

image

When searching for Scripts to list in the Script List pulldown, it would be great if these locations were also included. As this is what my Scripts pulldown looks like:

image

And this is what I see when I use the converter:

image

Bad Token Error on Conversion

OSX 10.13.5
Cinema 4D Studio R19.053 (Build RB224935)
C4D Prototype Converter v1.2.0

I get an error when running the script converter, following the tutorial content:

   bad token: type=56, value='\r', context=(", (5, 3))

TagData Plugins Register but Don't Appear in Object Manager

  1. Convert a PythonExpression to a TagData plugin
  2. Restart C4D.
  3. Add a TagData Plugin
    image

The tag's settings appear in the AM
image

BUG: The tag isn't visible in the Objects Manager
image

Perhaps this is due to a lack of icon? Or perhaps a missing flag during registration?

AutoFill PluginName and Help with Docstring

image

Name-US: -> Plugin Name
Description-US: -> Plugin Help / status bar text.

It seems like this might already be implemented. If so, just ensure that the Plugin Name field updates to show the name from Name-US rather than the filename.

ISSUE: Pasted Plugin IDs Aren't Valid

If you copy/paste in a Plugin ID from Plugin Cafe it doesn't register as valid. I've run into this a couple times now. I suspect this is because instead of 12345 it's 12345 (<- with a space at the end). Perhaps run a string.strip() on new values?

Limit Min/Limit Max settings are ignored

Split from #13

image

Also, Limit Max isn't active, yet a value is being added to the Resource file:

Hm, there seems to be no (documented) symbols that describe the "Limit Min" or "Limit Max" checkboxes in the UserData settings. I'll have to find out how to read that checkbox value first.

BUG: Not possible to edit auto-set parameters

To reproduce:

image

  1. Drag a BaseList2D w/ UserData into the Source field.
    image

Notice that the Plugin Name ends in v1.0.0 (from the name of the tag)

  1. Try to select or edit the text in Plugin Name

image

BUG: You can't

Expected: Dragging something into the Link field will auto-fill the contents, however, you should be able to manually edit those auto-generated values after the fact.

Report Errors During Conversion

From the ReadMe

Report possible errors during conversion (eg. referencing the variables doc or op in global functions without previously declaring them)

`# Comments` Don't Get Proper Indent Level

Before Conversion:

        # Compose name in [0-30] or [17] format.
        range_name = "[" + str(start_frame)
        if end_frame != start_frame:
            range_name += "-" + str(end_frame)
        range_name += "]"
        
        range_render_data.SetName(range_name)
        
        range_render_data[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(start_frame, fps)
        range_render_data[c4d.RDATA_FRAMETO] = c4d.BaseTime(end_frame, fps)
        range_render_data.InsertUnder(render_data)
        
        doc.AddUndo(c4d.UNDOTYPE_NEW, range_render_data)
        
        # Add A take for this render setting
        range_take = take_data.AddTake(range_name, current_take, None)
        range_take.SetName(range_name)
        range_take.SetRenderData(take_data, range_render_data)
        range_take.SetChecked(True)

After Conversion:

          # Compose name in [0-30] or [17] format.
            range_name = "[" + str(start_frame)
            if end_frame != start_frame:
                range_name += "-" + str(end_frame)
            range_name += "]"

            range_render_data.SetName(range_name)

            range_render_data[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(start_frame, fps)
            range_render_data[c4d.RDATA_FRAMETO] = c4d.BaseTime(end_frame, fps)
            range_render_data.InsertUnder(render_data)

            doc.AddUndo(c4d.UNDOTYPE_NEW, range_render_data)

          # Add A take for this render setting
            range_take = take_data.AddTake(range_name, current_take, None)
            range_take.SetName(range_name)
            range_take.SetRenderData(take_data, range_render_data)
            range_take.SetChecked(True)

Auto-Open to the default Plugin Directory

Using the Prototype Converter it will pre-fill the Plugin Directory with a useful starting point:

image

However, if I click on the ... button, it shows me:

image

Ideally, it should open to the same directory as what's been proposed (if it exists), and if not, it should open to the plugins directory.

Duplicate / Conflicting IDs with "X+" "X-" Parameters

I hate to add special cases, but it seems that

  • X+
  • X-
  • Y+
  • Y-
  • Z+
  • Z-

Are fairly common cycle options. At the moment, they generate overlapping IDs:

UserData:

0;X+
3;X-
1;Y+
4;Y-
2;Z+
5;Z-

Ocvline.res

            CYCLE {
                CV_LINE_AXIS_X;
                CV_LINE_AXIS_X;
                CV_LINE_AXIS_Y;
                CV_LINE_AXIS_Y;
                CV_LINE_AXIS_Z;
                CV_LINE_AXIS_Z;
            }

cv-line spline.zip

Add Support for Sub-Ids

Not sure of the best way to implement this, but if I've got a Cycle pull-down with a bunch of options like:
image

It would be nice if these were automatically added as IDs to the res() object.

CV_LINE_SPLINE_AXIS = 10100,
CV_LINE_SPLINE_AXIS_XPLUS = 10101,
CV_LINE_SPLINE_AXIS_XMINUS = 10102,
CV_LINE_SPLINE_AXIS_YPLUS = 10103,
...

The attached .zip contains a .c4d file with a "CV-Line Spline" Generator Object you can use to test.
cv-line spline.zip

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.