SOLVED Save Project As... new project name


I have a modifier plugin that generates a data file, at the same path and same project name.
When I use Save Project As..., I try to get the new project name in the Write(), to regenerate my data file, but what I get is actually the original project name.
Can I get the new project name in Write()?
Maybe I'm not accessing the correct document?

Bool SomeModifier::Write( GeListNode* /*node*/, HyperFile* hf )
	const auto sceneName = Get()->GetDocument()->GetDocumentPath() + Get()->GetDocument()->GetDocumentName();
	return true;

I understand that I can save anything with the project file, but for the moment we're using a separated file to keep compatibility with other hosts.


maybe I am overlooking or misunderstanding something here, but since NodeData::Write is called to write a node, i.e. is being called before the document has been saved, your general logic seems questionable to me. By getting the file path from the document your node is attached to at this point, you will always retrieve the old file path or - and that is probably even more critical - an empty path when the document has not been saved before.

Listening for MSG_DOCUMENTINFO_TYPE related messages, specifically the post save messages MSG_DOCUMENTINFO_TYPE_SAVE_AFTER and MSG_DOCUMENTINFO_TYPE_SAVEPROJECT_AFTER (and probably more [1]) and execute your save logic from there, seems to be a more reasonable approach to me.



@zipit Yes, my logic may be flawed. If I have more that one node in the scene, I'll save conflicting files.

I didn't know that Write() was called before the document is saved. If I'm saving the project with a new name, and while saving it calls Write(), I would expect the new project name to be available at that point. Is this saving processing order documented anywhere?


NodeData::Write is called when a document is about to be saved, to let you serialize any data that you cannot serialize into the data container of your NodeData node. The method passes you a pointer to a Hyperfile and expects you to serialize your data into that Hyperfile and Cinema then incorporates that data into the saved file. After the document has been saved, its in memory representation, including the file path, will be updated. The sister methods Read and CopyTo are expected to be implemented analogously.

I do not know what you are planning to do, but you said you have multiple nodes in your scene and there probably will be a user who thinks he really needs 500 of them. Which will lead to 500 save operations at the same time (which doesn't seem very graceful to me). So if you really want to save to (a) separate file(s), it would seem more graceful to at least move the save logic to a separate MessageData plugin and combine all of your nodes into one file.

I do not think that Maxon has fully exposed the saving process of Cinema, but you can get an idea of it by looking into the link I posted in my first post. They somewhat expect you to use the read/write logic related methods in NodeData. Circumventing these methods to save additional data does not seem advisable (unless you know exactly what you are doing), because it handles all the merging and copying (and other stuff that can happen) for you, which you would have to implement by hand if you would circumvent these methods.



you can use the Message function to catch the message sent before or after the document is saved.

the code below is in python but we have a c++ snippet in our documentation about BaseDocument
You will have to catch MSG_DOCUMENTINFO and check the DocumentInfoData structure you received.

    def Message(self, node,  type, data):
        if type == c4d.MSG_DOCUMENTINFO:
            if data['type'] == c4d.MSG_DOCUMENTINFO_TYPE_SAVE_BEFORE:
                print "save before",  data['filename']
            if data['type'] == c4d.MSG_DOCUMENTINFO_TYPE_SAVE_AFTER:
                print "save after", data['filename']
            if data['type'] == c4d.MSG_DOCUMENTINFO_TYPE_SAVEPROJECT_BEFORE:
                print "save project before", data['filename']
            if data['type'] == c4d.MSG_DOCUMENTINFO_TYPE_SAVEPROJECT_AFTER:
                print "save project", data['filename']
        return True

Maybe you can use "before" to warn the user that you are about to save something that could take time.
Note also the difference between save and saveProject.


Saving my project (or Saving As) does not call MSG_DOCUMENTINFO_TYPE_SAVEPROJECT_*, only MSG_DOCUMENTINFO_TYPE_SAVE_*.

And the document name is not updated on the AFTER message.
Do I need to enable something to call MSG_DOCUMENTINFO_TYPE_SAVEPROJECT_*?


with this code,
i first save my document,
press several time save
save as
save project with asset

save before C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\first_save.c4d
save after C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\first_save.c4d
save before C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\first_save.c4d
save after C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\first_save.c4d
save before C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\first_save.c4d
save after C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\first_save.c4d
save before C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\save_as.c4d
save after C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\save_as.c4d
save project before C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\save_project_with_asset\save_project_with_asset.c4d
save project C:\Users\Manuel Magalhaes\Desktop\temp\testin_saveasset\save_project_with_asset\save_project_with_asset.c4d

as in my code i forgot the save project AFTER the last line is really the after.
as you can see the project name is change before and after.

What result do you have ?


Got it! documentInfoData->doc->GetDocumentName() is outdated, but documentInfoData->filename has the new name. Good to detect it's changing.

If the SAVEPROJECT messages are only called for Save Project with Assets, MSG_DOCUMENTINFO_TYPE docs should explain it better, as all save options have Project in it.


sorry it wasn't clear enough.
yes sure, doing documentInfoData->doc->GetDocumentName() is the same as doc->GetDocumentName()

I've updated the documentation with Save Project with Assets to be a bit more clear.