Navigation

    • Register
    • Login
    • Search
    1. Home
    2. y_puech
    3. Best
    • Profile
    • More
      • Following
      • Followers
      • Topics
      • Posts
      • Best
      • Groups

    Best posts made by y_puech

    RE: Print console logs in terminal

    Hi,

    There's a more convenient workaround than using GePrint().
    sys.__stdout__ original standard output stream can be used to redirect stdout and print to the terminal/console. Here's some code:

    # Stores the stdout redirected by Cinema 4D Python
    c4d_stdout = sys.stdout
    # Redirects to original stdout
    sys.stdout = sys.__stdout__
    
    # Prints something
    print("Some text to be printed to the terminal/console")
    
    # Restores Cinema 4D Python stdout redirection
    sys.stdout = c4d_stdout
    
    posted in Cinema 4D SDK •
    RE: Force InExclusionData update after remove object outside of In-/Exclusion User Data

    Hi,

    The InExcludeData object count does not always reflect the accurate number of valid objects depending on the scenarios.
    Additionally to calling GetObjectCount() the returned value from ObjectFromIndex() should be checked if it's not None.

    posted in Cinema 4D SDK •
    RE: R20 Startup script location - python_init.py

    Hi,

    Sorry for being late in the discussion here.

    In R20 python_init.py is no longer executed at startup of Cinema. Sorry this change was not documented.

    The __init__.py script in the preferences path python27/maxon_generated was not meant for this but it can be used as replacement.
    However, as Adam pointed out the difference in his last post here, the __init__.py script in R20 is executed after the plugins are registered. Pre-R20 python_init.py was executed before the plugins registration.
    This means a plugin cannot rely on operations done in python27/maxon_generated/__init__.py.

    Note the other Python files in the directory python27/maxon_generated (_configuration.py and _enums.py) must not be modified.

    posted in Cinema 4D SDK •
    RE: Force InExclusionData update after remove object outside of In-/Exclusion User Data

    Hi,

    Just a quick note on your code. A pythonic solution could be:

    count = inExData.GetObjectCount()
    for i in xrange(count):
        obj = inExData.ObjectFromIndex(doc, i)
        if obj is None:
            continue
    

    Why are you breaking out from the loop with the first invalid object in the InExcludeData?

    posted in Cinema 4D SDK •
    RE: How to use c4d.utils.PolygonReduction

    Hi,

    That's right, the error you're getting is related to the type of the passed object to be processed by the PolygonReduction.
    The sample code shouldn't try to process an object that isn't a PolygonObject because there's this check at the beginning:

    if not polyObject.IsInstanceOf(c4d.Opolygon):
        return
    

    To convert a BaseObject to a PolygonObject the Current State to Object modeling command can be used.
    The utility function below invokes the MCOMMAND_CURRENTSTATETOOBJECT:

    def CSTO(obj, doc, inheritance, keepAnimation, noGenerate):
        bc = c4d.BaseContainer()
        bc.SetBool(c4d.MDATA_CURRENTSTATETOOBJECT_INHERITANCE, inheritance)
        bc.SetBool(c4d.MDATA_CURRENTSTATETOOBJECT_KEEPANIMATION, keepAnimation)
        bc.SetBool(c4d.MDATA_CURRENTSTATETOOBJECT_NOGENERATE, noGenerate)
    
        res = c4d.utils.SendModelingCommand(c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[obj.GetClone()], bc=bc, doc=doc)
        if isinstance(res, list):
            return res[0]
        else:
            return None
    

    The CSTO() function can then be invoked like this:

    if not polyObject.IsInstanceOf(c4d.Opolygon):
        polyObject = CSTO(polyObject, doc, True, True, False)
        if polyObject is None:
            return
    

    I moved the topic to "CINEMA 4D DEVELOPMENT" category and I turned it into a question and answer (you can do this by yourself, see Q&A New Functionality).

    posted in Cinema 4D SDK •
    RE: How to use c4d.utils.PolygonReduction

    Hi,

    A BaseObject is the base type of every object in a document. A PointObject is an object that holds points. Then an object can be a PolygonObject if it has polygons.
    For instance if a generator object is made editable then it's transformed into a PolygonObject which is also a PointObject.
    The (reduced) object classes inheritance tree is as follows:

    • BaseObject
      • PointObject
        • SplineObject
        • PolygonObject
    posted in Cinema 4D SDK •
    RE: resource errors with SPLINE in R20

    Hi,

    Thanks for reporting the issue with GRIDSIZE.
    GRIDSIZE_H/GRIDSIZE_V were removed from the Definition list but not from Flags and Example in the SPLINE Description Resource page you linked.
    This will be fixed in the next update of the C++ API docs.

    Several flags for the Spline have been removed in R20 but its overall GUI behavior hasn't changed.
    The Changes in R20 page provides the information about the discarded Spline GUI flags in R20.

    Yes there's an issue with NO_FLOATING_WINDOW flag. The "Show in seperate Window.." button is still present in the GUI even if the flag is enabled. This will be reported.

    About the other elements in the Spline GUI there aren't flags to get rid of them but the GUI can be minimized/maximized with the arrow on the top left.

    PS: If you can't change the topic's title in edit mode then I can do it for you.

    posted in Cinema 4D SDK •
    RE: resource errors with SPLINE in R20

    Hi,

    Are you using the Spline GUI inside a dialog? It looks like so if there's no arrow.
    If that's the case you can call SetLayoutMode(c4d.LAYOUTMODE_MINIMIZED) on the Spline custom GUI to change its layout to the minimized/spline element only.

    posted in Cinema 4D SDK •
    RE: ParseTupleAndKeywords in R20

    Hi Victor,

    There's a logic error in the code you posted from the first post. The condition for R20 if (str.IsEmpty()!=false) returns false if the string has content.
    It makes more sense to call IsPopulated() for the R20 code instead of IsEmpty().

    posted in Cinema 4D SDK •
    RE: No fbx exporter in python library?

    Hi Rage,

    Unfortunately several importers and exporters do not have a constant for their ID. This is the case for FBX.
    The ID for the FBX exporter is 1026370.

    To find the ID of a specific exporter you can use the following code:

    import c4d
    
    saverPlugs = c4d.plugins.FilterPluginList(c4d.PLUGINTYPE_SCENESAVER, True)
    for plug in saverPlugs:
        print('{} : {}'.format(plug.GetName(), plug.GetID()))
    

    I turned the topic into a Q&A. Please remind to use this feature of the forum.

    posted in Cinema 4D SDK •
    RE: UserArea and EditText

    Hi,

    IMHO solution 2 is not the best because the user has to look below in the dialog to edit the text.
    I think solution 1 is the easiest and more convenient, you can simply call c4d.gui.InputDialog() to get the text.
    If you want the input dialog to be shown at the text's location in the user area then you can implement a GeDialog.

    posted in Cinema 4D SDK •
    RE: Add functions to python via C++ SDK [R20]

    Hi,

    You can add new functions with the C++ API using the Python library defined in frameworks/cinema.frameworksource/c4d_libs/lib_py.h
    This header is not documented but it allows to extend and embed Python.

    I already posted some code snippets and information in this topic.

    The posted code mostly compiles in R20 except the enumerations.

    Here's the code and corresponding files to add c4d.extendpyapi.HelloPython() Python function adapted for R20:

    extendpyapi.h

    #ifndef EXTENDPYAPI_H__
    #define EXTENDPYAPI_H__
    
    namespace extendpyapi
    {
    void InitExtendPython();
    void FreeExtendPython();
    }
    
    #endif
    

    extendpyapi.cpp

    #include "extendpyapi.h"
    
    #include "lib_py.h"
    
    namespace extendpyapi
    {
    
    // Global table of c4d.extendpyapi functions for PythonLibrary::InitModule()
    static maxon::BaseArray<PythonMethodData>* g_extendpyapi_functions = nullptr;
      
    // Prints "Hello from Python!" to the console
    static _PyObject *ExtendPyAPI_HelloPython(_PyObject *self)
    {
      PythonLibrary pylib;
      ApplicationOutput("Hello from Python!");
      return pylib.ReturnPyNone();
    }
    
    // Initializes c4d.extendpyapi module
    void InitExtendPyAPI()
    {
      PythonLibrary pylib;
    
      // Allocates c4d.extendpyapi module functions
      g_extendpyapi_functions = NewObjClear(maxon::BaseArray<PythonMethodData>);
      if (g_extendpyapi_functions == nullptr)
        return;
    
      // Initializes c4d.extendpyapi module functions
      g_extendpyapi_functions->Resize(2);
      PythonMethodData* moduleFunctions = g_extendpyapi_functions->GetFirst();
      moduleFunctions[0].Init("HelloPython", (PyFn)ExtendPyAPI_HelloPython, PYFN_FLAGS::NOARGS, "HelloPython() - Extend Python API");
      moduleFunctions[1].Init(String(), nullptr, PYFN_FLAGS::NONE, String()); // Last dummy element!
    
      // Initializes c4d.extendpyapi module
      if (pylib.InitModule("c4d.extendpyapi", moduleFunctions, "Extend Python API"))
        ApplicationOutput("\'c4d.extendpyapi\' module successfully initialized");
    }
    
    // Frees the module global function table
    void FreeExtendPyAPI()
    {
      DeleteObj(g_extendpyapi_functions);
    }
    
    }
    

    main.cpp

    #include "lib_py.h"
    
    #include "extendpyapi.h"
    
    ::Bool PluginStart()
    {
      return true;
    }
    
    void PluginEnd()
    {
    }
    
    ::Bool PluginMessage(::Int32 id, void* data)
    {
      switch (id)
      {
        case C4DPL_PYINITTYPES:
        {
          extendpyapi::InitExtendPyAPI();
          return true;
        }
    
        case C4DPL_PYFINALIZE:
        {
          extendpyapi::FreeExtendPyAPI();
          return true;
        }
    
        default: break;
      }
    
      return false;
    }
    

    Note ApplicationOutput() writes to the Default logger in the console and not the Python one.

    The use of the Python library defined in lib_py.h is not straightforward so do not hesitate to ask any question you may have.

    posted in Cinema 4D SDK •
    RE: Modify Sketch&Toon Rendersettings

    Hi,

    The Sketch and Toon render settings are stored in the related video post, not the render data.

    The video posts are stored in a list, the first element of that list can be obtained with GetFirstVideoPost() on the associated render data.
    Then loop trough all video posts simply with GetNext() and check the type of the current video post.

    Here is some code:

    rd = doc.GetActiveRenderData()
    if rd is None:
        return
    
    vpost = rd.GetFirstVideoPost()
    if vpost is None:
        return
    
    found = False
    while vpost:
        found = vpost.GetType() == 1011015
        if found:
            print "Found S&T VideoPost"
            break
    
        vpost = vpost.GetNext()
    
    if found:
        print vpost[c4d.OUTLINEMAT_SHADING_BACK]
        print vpost[c4d.OUTLINEMAT_SHADING_QUANTISE_LEVEL]
    
    posted in Cinema 4D SDK •
    RE: Add functions to python via C++ SDK [R20]

    Hi Víctor,

    To retrieve parameters a function must be initialized with PYFN_FLAGS::KEYWORDS. Then use pylib.ParseTupleAndKeywords() to get the value for each parameter.
    The following code shows the implementation of a function which expects a string, an integer and a float:

    static _PyObject *extendpyapi_PassParameters(_PyObject *self, _PyObject *args, _PyObject *keywords)
    {
    	PythonLibrary pylib;
    
    	String str;
    	Int32 integer = 0;
    	Float real = 0.0f;
    
    	const Char *kwlist[] = {"str", "integer", "real", nullptr};
    	if (!pylib.ParseTupleAndKeywords(args, keywords, "$if", kwlist, &str, &integer, &real))
    		return nullptr;
    
    	if (str.Content())
    		GePrint("Parameter str: " + str);
    
    	GePrint("Parameter integer: " + String::IntToString(integer));
    	GePrint("Parameter real: " + String::FloatToString(real));
    
    	return pylib.ReturnPyNone();
    }
    
    ...
    
    moduleFunctions[1].Init("PassParameters", (PyFn)extendpyapi_PassParameters, PYFN_FLAGS::KEYWORDS, "PassParameters() - Extend Python API");
    
    posted in Cinema 4D SDK •
    RE: c4dpy not working on OS x 10.12

    Note c4dpy does not work with a R20 free educational license. But c4dpy runs fine with a paid R20 student license.

    posted in Cinema 4D SDK •
    RE: Force InExclusionData update after remove object outside of In-/Exclusion User Data

    By the way, I wonder if there is a situation where the actual object counts are greater than GetObjectCount() returned?

    This should never happen.

    Thanks for marking the topic as solved. Note that you can mark a specific post as the correct answer or solution. See step 5 in Q&A New Functionality.

    posted in Cinema 4D SDK •
    RE: Print console logs in terminal

    Hi,

    Are you using Cinema 4D release 20 commandline.app/exe? There's a known bug under investigation.
    The workaround is to use c4d.GePrint() instead of print().

    Note I moved the topic to Cinema 4D Development category.
    I also turned it into a Q&A. Please make use of this in the future. For more information see Q&A New Functionality.

    posted in Cinema 4D SDK •
    RE: Content of PYTHONPATH not appended to sys.path

    Hi Heinrich,

    Welcome to the new forum 😀

    PYTHONPATH not added to sys.path is a known issue and has been already fixed for the R20 SP2 update.
    I don't see a better workaround then your with R20 SP1 currently.

    I turned this topic into a Q&A. Please use this functionality in the future. For more information see Q&A New Functionality.

    posted in Cinema 4D SDK •
    RE: C4D GUI Python Callback

    Hi,

    A string with format "PLUGIN_CMD_123456" is meant to be used with MENURESOURCE_COMMAND, not RegisterCommandPlugin().
    It tells Cinema the command ID and name for the menu item to be added.
    Note the sub-IDs returned from GetSubContainer() are specific to a command and aren't global to Cinema.

    Maybe CommandData isn't what you really need. Scripts from the user folder are automatically loaded and can be added to any menu using Customize Menus dialog.

    posted in Cinema 4D SDK •
    RE: Cinema 4D R20 (20026) GeDialog.SetLong, SetInt32 OverflowError

    Hi,

    The OverFlow error is thrown when SetInt32() is called from a SubDialog (used for Tool plugins settings).
    I'm afraid a regression was introduced in R20. It will be fixed in the next update.

    The workaround in R20 is to perform in Python what GeDialog::SetInt32() does in the C++ API (see cinema.framework/source/c4d_gui.cpp).

    import sys
    
    def StringToID(str):
      return int('0x'+hex(ord(str[0]))[2:4]+hex(ord(str[1]))[2:4]+hex(ord(str[2]))[2:4]+hex(ord(str[3]))[2:4], 16)
    
    CM_TYPE_INT = StringToID('vint')
    
    CM_VALUE_VAL = StringToID('valu')
    CM_VALUE_FORMAT = StringToID('frmt')
    CM_VALUE_MIN = StringToID('mini')
    CM_VALUE_MAX = StringToID('maxi')
    CM_VALUE_MIN2 = StringToID('min2')
    CM_VALUE_MAX2 = StringToID('max2')
    CM_VALUE_STEP = StringToID('step')
    CM_VALUE_TRISTATE = StringToID('tris')
    
    def SetInt32(dlg, id, value, min=-sys.maxint-1, max=sys.maxint, step=1, tristate=0, min2=-sys.maxint-1, max2=sys.maxint):
    
      msg = c4d.BaseContainer(CM_TYPE_INT)
      msg[CM_VALUE_VAL] = value
      msg[CM_VALUE_FORMAT] = c4d.FORMAT_INT
      msg[CM_VALUE_MIN] = min
      msg[CM_VALUE_MAX] = max
      msg[CM_VALUE_STEP] = step
      msg[CM_VALUE_TRISTATE] = tristate
      if min2 != -sys.maxint-1 or max2 != sys.maxint:
        msg[CM_VALUE_MIN2] = min2
        msg[CM_VALUE_MAX2] = max2
    
      return dlg.SendMessage(id, msg) != 0
    

    Call this SetInt32() from the subdialog to initialize any integer value.
    Note c4d.MINLONGl and c4d.MAXLONGl are no longer used internally. The documentation has to be updated.

    posted in General Talk •