Bug with GetLink/SetLink & Hyperfile



  • Hello,
    I think that I've found a bug. This is a variation of the same unsolved issue from this topic from a month ago. In the code example below, it is writing an object's CTrack (Position . X/Track) to a Hyperfile, so for it to work an object must have an animation track in position X and be selected. It prints correctly from the BaseContainer prior to saving. When loading the Hyperfile however, the link prints as None. As mentioned in the previous topic, CTracks are of type C4DAtom and I'm passing/retrieving it with the same ID, so it should be writing and reading correctly. If I use BaseContainer.SetString instead of BaseContainer.SetLink, it works.

    If there is a workaround storing a CTrack to a Hyperfile, I'd really appreciate the help. This is a very important part of my current project. Thank you.

    import c4d, os
    from c4d import documents, gui
    
    key = 12345
    OBJ_BC_ID = 90210
    
    desktopPath = c4d.storage.GeGetC4DPath(c4d.C4D_PATH_DESKTOP)
    defaultFilepath = os.path.join(desktopPath, "test.file")
    
    def load_hyperfile():
        global doc
        path = c4d.storage.LoadDialog(def_file=defaultFilepath)
    
        hf = c4d.storage.HyperFile()
        if not hf.Open(ident=key, filename=path, mode=c4d.FILEOPEN_READ,
                       error_dialog=c4d.FILEDIALOG_NONE):
            print "Could not read file."
            return False
        bc = hf.ReadContainer()
    
        for cid, value in bc[OBJ_BC_ID]:
            print cid, value
    
        hf.Close()
    
    
    def save_hyperfile(obj):
        path = c4d.storage.SaveDialog(title="Save your Hyperfile",force_suffix="file",def_file=defaultFilepath)
    
        bc = c4d.BaseContainer()
        objBc = c4d.BaseContainer()
        xPos = c4d.DescID(c4d.DescLevel(903, 23, 5155), c4d.DescLevel(1000, 19, 23))
        pxTrack = obj.FindCTrack(xPos)
        objBc.SetLink(OBJ_BC_ID,pxTrack)
        #objBc.SetString(OBJ_BC_ID,"Test String") # The Hyperfile works when using a String.
        bc.SetContainer(OBJ_BC_ID, objBc)
        print objBc[OBJ_BC_ID]
    
        hf = c4d.storage.HyperFile()
        if not hf.Open(ident=key, filename=path, mode=c4d.FILEOPEN_WRITE,
                       error_dialog=c4d.FILEDIALOG_ANY):
            print "Could not write file."
            return False
        else:
            print "Wrote file at %s"%path
    
        hf.WriteContainer(bc)
    
        for cid, value in bc[OBJ_BC_ID]:
            print cid, value
    
        hf.Close()
    
    class Dlg(gui.GeDialog):
        def __init__(self):
            global doc,obj
    
        def CreateLayout(self):
            self.SetTitle('Hyperfile')
            self.GroupBegin(1001, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 1, 2)
            self.AddButton(1002, c4d.BFH_CENTER | c4d.BFH_SCALE | c4d.BFV_TOP, initw=0, inith=20, name="Save Hyperfile")
            self.AddButton(1003, c4d.BFH_CENTER | c4d.BFH_SCALE | c4d.BFV_TOP, initw=0, inith=20, name="Load Hyperfile")
            self.GroupEnd()
            return True
    
        def Command(self, id, msg):
            if id == 1002:
                save_hyperfile(obj)
            elif id == 1003:
                load_hyperfile()
            return True
    
    def main():
        global doc,obj,dlg
        doc = documents.GetActiveDocument()
        obj = doc.GetActiveObject()
        if obj is None:
            gui.MessageDialog("Please select an object to save.")
            return
        dlg = Dlg()
        dlg.Open(c4d.DLG_TYPE_ASYNC, xpos=-2, ypos=-2, defaultw=200, defaulth=130)
    
    if __name__=='__main__':
        main()
    


  • hello,

    A BaseLink is like a shortcut or an alias. if you only save the shortcut you will have nothing. If i save my shortcut and send it to you, you will not be able to start the application.

    Instead what i suggest is

    • isolate the object (as in the previous post) in a temporary document. (or create a null, and copy the track on it)
    • create in the BaseContainer of the document a BaseLink that will point to your track.
    • save the temporary document.

    This way, when you open the file, you know where to get your BaseLink.
    You can also have different BaseLink pointing to different tracks of different objects.

    you can have a look at the BaseLink Manual

    Cheers,
    Manuel



  • hello,

    A BaseLink is like a shortcut or an alias. if you only save the shortcut you will have nothing. If i save my shortcut and send it to you, you will not be able to start the application.

    Instead what i suggest is

    • isolate the object (as in the previous post) in a temporary document. (or create a null, and copy the track on it)
    • create in the BaseContainer of the document a BaseLink that will point to your track.
    • save the temporary document.

    This way, when you open the file, you know where to get your BaseLink.
    You can also have different BaseLink pointing to different tracks of different objects.

    you can have a look at the BaseLink Manual

    Cheers,
    Manuel



  • My apologies: I didn't understand how BaseLink worked and this clarified things. Thank you!