Navigation

    • Register
    • Login
        No matches found
    • Search
    1. Home
    2. jenandesign
    jenandesign

    jenandesign

    @jenandesign

    1
    Reputation
    17
    Posts
    135
    Profile views
    1
    Followers
    0
    Following
    Joined Last Online

    • Profile
    • More
      • Following
      • Followers
      • Topics
      • Posts
      • Best
      • Groups
    jenandesign Follow

    Best posts made by jenandesign

    RE: Issues with the C4D to Unity Import python plugin - missing some types of objects

    @m_adam Shoot, tried calling it 3X and still nothing on the cloner (spline mode) object.

    (failing) test file attached
    fbxtest_v04.c4d

    posted in Plugin Development with Cinema 4D •

    Latest posts made by jenandesign

    Generating a usable spline with a Python Generator

    This topic has been broached before over the years, but I think it should be mentioned again.

    There is no easy way to make a spline generated with a python generator that is usable in other parts of the program due to the internal hierarchy within c4d python and caching / generating "contours" as noted with the Python Generator object etc.

    The only solution available to generate procedural splines (usable in other generator objects) is that users are expected to make full ObjectData plugins.. which is unnecessarily time consuming, and places a much larger mountain to climb in front of new users of c4d python. I think this feature would be incredibly powerful and time saving if it was easier, even as someone who knows how to write ObjectData plugins.

    I hope you will please consider adding this functionality to return usable splines in the Python Generator in a future release or update to c4d python. Thanks for your consideration!

    posted in Plugin Development with Cinema 4D •
    Feature request: Quaternion Matrix Mix to XPresso "Mix" Node

    Hello, I would use it quite often if it could be added: a Quaternion rotation setting to the XPresso Mix node... much like there is in the c4d.BaseObject class as it is accessible through the GUI

    Attributes of a regular Null object showing Quaternion setting:
    Screen Shot 2020-11-17 at 11.07.11 AM.png

    Attributes of a Mix node in XPresso, where a boolean checkbox like above could live:
    Screen Shot 2020-11-17 at 11.08.59 AM.png

    I have constructed a Quaternion Matrix Mix using an XPresso Python node myself, but thought this would be a useful feature to be added in the default XPresso API for users who have not yet learned how to implement Quaternions in Python. Alternatively, perhaps other users will find the following code useful anyway 😁

    import c4d
    from c4d import utils
    #Welcome to the world of Python
    
    
    def main():
        global MatrixMix
    
        q1 = c4d.Quaternion()
        q1.SetMatrix(MatrixA)
    
        q2 = c4d.Quaternion()
        q2.SetMatrix(MatrixB)
    
        q = c4d.utils.QSlerp(q1, q2, Mix)
    
        MatrixMix = q.GetMatrix()
        MatrixMix.off = c4d.utils.MixVec(MatrixA.off, MatrixB.off, Mix)
    

    Screen Shot 2020-11-17 at 11.12.44 AM.png

    Cheers!
    -Leah

    Edit: also I am sorry if this is posted incorrectly. This seemed like the best place to put this post since there is usable Python code included 🙆

    posted in General Programming & Plugin Discussions •
    RE: Issues with the C4D to Unity Import python plugin - missing some types of objects

    Hi Maxime! Thanks for the suggestion, though I don't quite understand what you mean by your example... I don't see any use of SendCoreMessage in your snippet?

    SaveDocument is already present in the original code in the extended threading class "ExportThread" under definition Main(). How are you suggesting I change this?

    Thank you for the continued help ☺

    posted in Plugin Development with Cinema 4D •
    RE: Issues with the C4D to Unity Import python plugin - missing some types of objects

    I forgot to mention, Instances also fail to cache into Unity as well.

    I am thinking these are all related and to do with the cache being unavailable unless the script is being run within the C4D gui

    posted in Plugin Development with Cinema 4D •
    RE: Issues with the C4D to Unity Import python plugin - missing some types of objects

    @m_adam Then maybe the issue is that the command line fbx export is being executed from within Unity and not through C4D itself?

    Is there some kind of document referencing error that could happen if another program (other than C4D) were to call this script? Would caches behave differently?

    To answer your question, yes, I have FBXEXPORT_SPLINES set to True

    posted in Plugin Development with Cinema 4D •
    RE: Issues with the C4D to Unity Import python plugin - missing some types of objects

    Currently the Spline Deformer breaks other objects in the scene, while the Bevel Deformer and Cloner Object in Spline Object mode only break themselves.

    GetContour? SetOptimizeCache? Anything else worth investigating? Maybe this is happening because it's being called via Unity automatically?

    posted in Plugin Development with Cinema 4D •
    RE: Issues with the C4D to Unity Import python plugin - missing some types of objects

    @m_adam Shoot, tried calling it 3X and still nothing on the cloner (spline mode) object.

    (failing) test file attached
    fbxtest_v04.c4d

    posted in Plugin Development with Cinema 4D •
    RE: Issues with the C4D to Unity Import python plugin - missing some types of objects

    ExecutePasses worked for Polygon Reduction objects! That is a huge benefit to LOD versioning in Unity 👍 👍 👍

    Added here:

    #
    #SNIPPET FROM MAIN CODE
    #
    
    class ExportThread(threading.C4DThread):
    
        def __init__(self, doc, exportPath):
            self.doc = doc
            self.status = False
            self.exportPath = exportPath
            #ADDED THE LINE BELOW
            doc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_EXPORT)
    
        def Main(self):
            # Export document to FBX
            self.status = documents.SaveDocument(self.doc, self.exportPath, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, FBX_EXPORTER_ID)
    
        def GetStatus(self):
            return self.status
    
    #
    #SNIPPET FROM MAIN CODE
    #
    

    Cloners are still not working if they reference a spline. Any ideas why that is still giving us trouble?

    Leah

    posted in Plugin Development with Cinema 4D •
    RE: Issues with the C4D to Unity Import python plugin - missing some types of objects

    Hi Maxime! Thanks for the info about Poly Reduction and ideas with ExecutePasses 😄 I will try that immediately

    I am currently on the latest, R21.115. However I tested this same stuff happening on R20 as well.

    Cloners are usually okay as long as they don't reference a spline (which now makes sense knowing about the cache thing).

    However, I am right now getting a very strange thing where a cloner and a null with dynamics tag (applied to many children) go from importing normally to not.. depending on how many children are in the Fracture.1 null. But perhaps this is a separate issue. When testing with the manual FBX export, it takes some time.. I am assuming it has to animate the dynamics tag to it's current position before exporting... Perhaps unity does not know how to wait for this operation unless it is very fast. Perplexing why it would have anything to do with the cloner, though, as it is not in any way connected to the Fracture.1 null or the dynamics system. Removing one or the other object results in a successful import into unity. The attached scene fails import into unity unless you delete the cloner, the dynamics tag attached to the null, or at least 10-50 more children of the null.fbxtest_v03.c4d. This is different than the original issue I posted about, where the scene import does not fail, but merely comes in with missing objects.

    I will try the ExecutePasses thing now! Thanks again!

    Leah

    posted in Plugin Development with Cinema 4D •
    Issues with the C4D to Unity Import python plugin - missing some types of objects

    Hello, I am trying to figure out why the supplied C4D to Unity importer misses certain types of objects. The plugin itself is essentially just an FBX converter that Unity runs when a c4d file is within one of its Asset directories. It is written in Python and it is very easy for the end user to modify. I fixed SDS object import by adding a few lines of code, seen towards the end, but still cannot seem to get Polygon Reduction objects. Hoping that someone knows something about this, maybe they can shed some light.

    I found the definitions in the C++ documentation, which has been helpful, but I don't see anything that looks indicative of Polygon Reductions
    https://developers.maxon.net/docs/Cinema4DCPPSDK/html/_ffbxexport_8h.html

    """
    Unity C4D To FBX Converter
    Written for Cinema 4D R18.020
    
    """
    import platform
    import c4d
    import sys
    import os
    from c4d import documents, plugins, threading, utils, gui
    
    # Be sure to use a unique ID obtained from www.plugincafe.com
    PLUGIN_ID = 1038605
    FBX_EXPORTER_ID = 1026370
    
    FBXEXPORT_TEXTURES = True
    FBXEXPORT_EMBED_TEXTURES = False
    FBXEXPORT_SAVE_NORMALS = True
    FBXEXPORT_ASCII = False
    
    def win32_utf8_argv():                                                                                               
        """
        Adapted from http://code.activestate.com/recipes/572200-get-sysargv-with-unicode-characters-under-windows/
    
        Uses shell32.GetCommandLineArgvW to get sys.argv as a list of UTF-8
        strings.
    
        Versions 2.5 and older of Python don't support Unicode in sys.argv on
        Windows, with the underlying Windows API instead replacing multi-byte
        characters with '?'.
        """
    
        from ctypes import POINTER, byref, cdll, c_int, windll
        from ctypes.wintypes import LPCWSTR, LPWSTR
    
        GetCommandLineW = cdll.kernel32.GetCommandLineW
        GetCommandLineW.argtypes = []
        GetCommandLineW.restype = LPCWSTR
    
        CommandLineToArgvW = windll.shell32.CommandLineToArgvW
        CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)]
        CommandLineToArgvW.restype = POINTER(LPWSTR)
    
        cmd = GetCommandLineW()
        argc = c_int(0)
        argv = CommandLineToArgvW(cmd, byref(argc))
        if argc.value > 0:
            # Remove Python executable if present
            if argc.value - len(sys.argv) == 1:
                start = 1
            else:
                start = 0
            return [argv[i].encode('utf-8') for i in
                    xrange(start, argc.value)]
        else:
            return []
    
    class ExportThread(threading.C4DThread):
    
        def __init__(self, doc, exportPath):
            self.doc = doc
            self.status = False
            self.exportPath = exportPath
    
        def Main(self):
            # Export document to FBX
            self.status = documents.SaveDocument(self.doc, self.exportPath, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, FBX_EXPORTER_ID)
    
        def GetStatus(self):
            return self.status
    
    class MessageLogger():
    
        def __init__(self, logOutputPath=None):
            self.logString = ""
            if logOutputPath :
                self.logOutputFile = open(logOutputPath, 'w')
            else :
                self.logOutputFile = sys.stdout
    
        def appendMessage(self,message) :
            self.logString+= message + "\n"
    
        def writeLog(self, success) :
            if success :
                self.logOutputFile.write("SUCCESS\nframerate=" + str(documents.GetActiveDocument().GetFps()) + "\n")
            else :
                self.logOutputFile.write("FAILURE\n" + self.logString)
    
            if self.logOutputFile is not sys.stdout :
                self.logOutputFile.close()
            return success
    
    # get command line arguments
    def PluginMessage(id, data) :
        if id==c4d.C4DPL_COMMANDLINEARGS:
            if platform.system() == 'Windows':
                argv = win32_utf8_argv()
            else:
                argv = sys.argv
    
            if '-UnityC4DtoFBX' in argv :
                sourcePath = ""
                destinationPath = ""
                logOutputPath = ""
                textureSearchPath = ""
                # parse command line arguments
                for idx, arg in enumerate(argv):
                    if (arg == "-src" and len(argv) > idx) :
                        sourcePath = argv[idx+1]
                    if (arg == "-dst" and len(argv) > idx) :
                        destinationPath = argv[idx+1]
                    if (arg == "-out" and len(argv) > idx) :
                        logOutputPath = argv[idx+1]
                    if (arg == "-textureSearchPath" and len(argv) > idx) :
                        textureSearchPath = argv[idx+1]
    
                logger = MessageLogger(logOutputPath)
                
                if not sourcePath or not destinationPath :
                    logger.appendMessage("Invalid command line arguments")
                    return logger.writeLog(False)
                
                # C4D automatically opens any file which path is passed as an argument, 
                # to prevent that, the parameters omit file extensions.
                sourcePath+=".c4d"
                destinationPath+=".fbx"
    
                # load the c4d scene
                loadedDoc = documents.LoadFile(sourcePath)
                documents.GetActiveDocument().SetDocumentPath(textureSearchPath)
                if loadedDoc :    
                    logger.appendMessage("Succesfuly loaded " + sourcePath)
                else :
                    logger.appendMessage("Couldn't load " + sourcePath)
                    return logger.writeLog(False)
                # execute the conversion
                if ExecuteConversion(destinationPath, textureSearchPath, logger):
                    logger.appendMessage("FBX Exported at " + destinationPath)
                    return logger.writeLog(True)
                else :
                    logger.appendMessage("FBX Plugin failed to export\n")
                    return logger.writeLog(False)
            else :
                # command line argument not found. Do nothing.
                return False
    
    def ExecuteConversion(destinationPath, textureSearchPath, logger) :
        plug = plugins.FindPlugin(FBX_EXPORTER_ID, c4d.PLUGINTYPE_SCENESAVER)
        if plug is None:
            logger.appendMessage("FBX Export plugin not found")
            return False
    
        op = {}
        # Retrieve FBX Eporter settings object
        if plug.Message(c4d.MSG_RETRIEVEPRIVATEDATA, op) :
            if "imexporter" not in op:
                return False
    
            # BaseList2D object stored in "imexporter" key hold the settings
            fbxExport = op["imexporter"]
            if fbxExport is None :
                return False
    
            # Change export settings
            
            #THE FOLLOWING TWO LINES OF CODE WERE ADDED TO FIX SDS OBJECT IMPORT
            fbxExport[c4d.FBXEXPORT_SDS_SUBDIVISION] = True
            fbxExport[c4d.FBXEXPORT_SDS] = False
            fbxExport[c4d.FBXEXPORT_TEXTURES] = FBXEXPORT_TEXTURES
            fbxExport[c4d.FBXEXPORT_EMBED_TEXTURES] = FBXEXPORT_EMBED_TEXTURES
            fbxExport[c4d.FBXEXPORT_SAVE_NORMALS] = FBXEXPORT_SAVE_NORMALS
            fbxExport[c4d.FBXEXPORT_ASCII] = FBXEXPORT_ASCII
    
            c4d.SetGlobalTexturePath(9, documents.GetActiveDocument().GetDocumentPath())
            if textureSearchPath :
                c4d.SetGlobalTexturePath(8, textureSearchPath)
    
            thread = ExportThread(documents.GetActiveDocument(), destinationPath)
            thread.Start()       # Start thread
            thread.End()         # Then end it but wait until it finishes
    
            # Retrieve export status and return it
            status = thread.GetStatus()
            return status
        else :
            logger.appendMessage("Could not configure FBX plugin")
            return False
    
        documents.KillDocument(documents.GetActiveDocument())
    
    
    posted in Plugin Development with Cinema 4D •