Using HyperFiles to save data internally

On 08/01/2013 at 12:29, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   13 
Platform:   Windows  ;   
Language(s) :     C++  ;

It's become painfully obvious to me over the past few days that I simply don't understand how HyperFile works regarding to saving data to a scene file.
There's plenty of examples in the forums about using HF like a BaseFile. And saving things to HD files. But not for using HF for saving data into the scene itself.
There is only one example in the SDK that uses HF like this. The RoundedTube example.
However...It doesn't seem to actually use the HF data ("test") it reads and writes. So that's teaches me nothing.

Trying to learn how HF works. I wrote this very basic tag plugin example that overrides the Read() & Write() methods to save and read a variable called "text" into a HF. But I have no idea what to do next.

#include "c4d.h"  
#include "c4d_symbols.h"  
#include "tsimpletag.h"  
// be sure to use a unique ID obtained from  
#define PLUGIN_ID    1000010  
class SimpleTag : public TagData  
      String text;  
      virtual Bool Read(GeListNode *node, HyperFile *hf, LONG level);  
      virtual Bool Write(GeListNode *node, HyperFile *hf);  
      virtual Bool Message(GeListNode *node, LONG type, void *t_data);  
      virtual Bool Init(GeListNode *node);  
      virtual EXECUTIONRESULT Execute(BaseTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, EXECUTIONFLAGS flags);  
      static NodeData *Alloc(void) { return gNew SimpleTag; }  
Bool SimpleTag::Read(GeListNode *node, HyperFile *hf, LONG level)  
  return hf->ReadString(&text);  
Bool SimpleTag::Write(GeListNode *node, HyperFile *hf)  
  return hf->WriteString(text);  
Bool SimpleTag::Message(GeListNode *node, LONG type, void *data)  
  BaseTag *tag = (BaseTag* )node;                               //Get the tag and assign it to a variable  
  BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance();  //Get the container for the tag  
  switch (type)  
        DescriptionCommand *dc = (DescriptionCommand* )data;  // data contains the description ID of the button             
        LONG button = dc->id[0].id;                          // Get the ID of the button  
        switch (button)  
            case BUTTON1:  
                GePrint("Button1 was pushed");  
  tag->SetDirty(DIRTYFLAGS_DATA); //Used to update a Tag's AM GUI items  
  return TRUE;  
Bool SimpleTag::Init(GeListNode *node)  
  text = String("Hello");  
  return TRUE;  
EXECUTIONRESULT SimpleTag::Execute(BaseTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, EXECUTIONFLAGS flags)  
  BaseContainer *bc = tag->GetDataInstance();      
Bool RegisterSimpleTag(void)  
  String path = GeLoadString(IDS_SIMPLETAG); if (!path.Content()) return TRUE;  
  return RegisterTagPlugin(PLUGIN_ID,path,TAG_EXPRESSION|TAG_VISIBLE,SimpleTag::Alloc,"tsimpletag",AutoBitmap("myicon.tif"),0);  

I don't know how to access and use the string data that I've just written into the HF.
If I have written this correctly. I should have a string with the value of "Hello" somewhere saved in the default HF of the scene right?

When I look in the tag with: BaseContainer *tagdata = tag->GetDataInstance();
When I look in the doc with: BaseContainer *docdata = doc->GetDataInstance();
I can't find it. And since I did not allocate a HF, I don't know where to find the HF this data has supposedly been saved to.

I'm completely lost how we're supposed to use HF in this manner.


On 08/01/2013 at 15:34, xxxxxxxx wrote:


a plugin object has two locations where to store data. One is in the BaseContainer which you can access via tag->GetDataInstance(). All data you put in there will automatically be saved by C4D and if you open your scene your object has the saved data.

If you have data that does not fit in the BaseContainer or because of some other circumstances you can store your data in a member of your plugin object (in your example its 'text').

When you create an instance of SimpleTag then its initialized with "Hello". So far so good. Imagine you initialize your member with "Hello" and at a certain point you change that string to "World!". When the tag is saved to disk the word "World!" is saved to disk, and not "Hello". Therefore when you load the scene document again your plugin object reads the string again from the HyperFile and you can access the string with this->text in SimpleTag::Execute with the content "World!".

Hope that helped a little bit.

Cheers, Seb

On 08/01/2013 at 16:22, xxxxxxxx wrote:

I think I get it.

If I change the value of the class member variable after the tag has been added. By doing something like this: text = "World"  inside of my button code. And then save the file.
When I open the saved file. The variable will still have a value of "World".
So even though the tag's Init() method has code in it telling the text class variable to be "Hello".
The HyperFile methods Read()&Write() will basically take control of telling my class variable what value it should be?

Now I just have see if I can make it work with a BaseBitmap instead of a String variable.

Thanks Sebastien :beer: