Thanks for contacting us.
While i understand your issue, this forum's scope is bound to Cinema4D's API use only. (c++ and Python)
For your issue, you need to contact our regular support and create a ticket there.
They have more information/knowledge with what could cause this issue. (hardware/software)
it's still a limitation.
Sorry for the late reply.
It's a matter of retrieving the right BaseContainer and Insert the data in the right spot.
If you want to change the order, you need to "copy" the existing data after adding the new ones first.
// react to this message to dynamically enhance the menu
// do this only if necessary - otherwise the user will end up with dozens of menus!
// This lambda will return the basecontainer of the menu if founded.
auto searchMenu = (const maxon::String& identifier) -> BaseContainer*
BaseContainer* bc = GetMenuResource(String("M_EDITOR"));
if (bc == nullptr)
BaseContainer* resContainer = nullptr;
while (browse.GetNext(&id, &dat))
if (id == MENURESOURCE_SUBMENU || id == MENURESOURCE_STRING)
BaseContainer* dc = dat->GetContainer();
if (dc && dc->GetString(MENURESOURCE_SUBTITLE) == identifier)
resContainer = dc;
// Retrieve the M_EDITOR container.
BaseContainer* bc = GetMenuResource(String("M_EDITOR"));
if (!bc) return true;
// Check if the menu is already added.
Bool alreadyExist = false;
BaseContainer *existingMenu = searchMenu("My menu"_s);
if (existingMenu == nullptr)
// Create a empty basecontainer to add our menu.
existingMenu = NewObjClear(BaseContainer);
alreadyExist = true;
// If the menu isn't created we need to add the string first
existingMenu->InsData(MENURESOURCE_STRING, String("My menu"));
existingMenu->InsData(MENURESOURCE_COMMAND, String("PLUGIN_CMD_1021433")); // character
// we need to insert the menu only if it doesn't exit.
// We want to insert the menu after the last one.
GeData* last = nullptr;
last = SearchPluginMenuResource();
bc->InsDataAfter(MENURESOURCE_STRING, *existingMenu, last);
else // user killed plugin menu - add as last overall entry
I did tried with R20 and it worked as expected. I'm reading a .txt file from a https link. (i did only tried on windows)
Could you send us an email with the link you are using ? (just to be sure I'm testing the same thing)
This is a bug and will be fix in a futur release.
Unfortunately, there's no workaround.
I did reproduced the issue, with the s22 we changed the viewport and many changes have been introduce.
I have contacted the devs to have some feedback about that.
doesn't look like a bug to me. With 32g it's doable but take some time and go up to 100% of the ram. (that could maybe be optimized)
Definitely can't go to 7 as the max point number per object is 500 millions.
@Cairyn hit the right numbers even if it's 1001006*4^6 polygons. (for each subdivision, you have 4 times the polygon count)
Add the fact that the subdivision need memory to calculate, it will eat a lot of ram. 6 subdivision is a lot, specially on a high polygon count object.
What kind of object are you creating ?
we are in the week of our summit 2021, answer may take longer :)
there's no really workaround expect tracking all the child object's state for the viewport/render mode and check by yourself if those have changes.
Depending on what you want to do it could even be worst than rebuilding your cache.
edit : this code have been there for more than 14 years.
That's because you are not in the main thread. So i would use maxon::ExecuteOnMainThread to open the GeDialog.
I don't have memory leak but maybe with a more complexe example you could end up with some. Be aware of that.
checkForUpdate.ObservableFinished().AddObserver([checkForUpdate]() -> maxon::Result<void>
// Get job's result. this works fine.
HttpResponse result = checkForUpdate.GetResult() iferr_return;
// This works:
if (GeOutString("hello"_s, GEMB::YESNO) == GEMB_R::V_YES)
}, false); // false here so we don't wait the dialog to be closed.
ApplicationOutput("thread is going away");
sorry for the delay, we have our internal summit and we have a bit less time this week to work on support cases.
it's a normal result, if you are changing the mesh, than the morph cannot convert the data.
You need to import all your mesh. combine them into one and optimize the mesh and than create your morph.
For that you need to track your points from what mesh they are coming from and what was the index on your morph.
To track the points, you can create and add a customDataTag that will store information for each points. (the orginal mesh name and the index from that mesh).
You can create one tag on each mesh part and when you combine all the parts, our core system will combine them. (you can implement the "add" function in your customDataTag to tell how you want to data to be combined)
You can read information about CustomDatTag in our manual
We also have examples in our sdk you can found them on github
I will try to test it myself.
there's no real "good practice" and your workflow isn't clear to give you an answer.
It sound normal that when your object is created in the main function, it's not alive in the function you call when pressing the button. The references is passed but the c++ object the reference is pointing to is not alive anymore.
If for example you want your generator to return a cube and add that cube in the scene when you click on a button you should have:
But without knowing what the button should do we can't help more.
technically, it is possible, but you will have to figure it out yourself and be prepare to do a lot lot work.
the answer is pretty no.
the preset will not be changed but the value for near and far clip are updated.
I will talked with the dev to see why the preset isn't set.
You can use the near and far values as a workaround.
auto PrintValue = (BaseDocument* doc)
Float n = udata.GetFloat();
Float f = udata.GetFloat();
printf("value are near : %f far %f \n\r", n, f);
BaseDocument* c4dDoc = cineware::BaseDocument::Alloc();
if (c4dDoc != nullptr)
cineware::Bool ret = c4dDoc->SetParameter(cineware::DOCUMENT_CLIPPING_PRESET, cineware::DOCUMENT_CLIPPING_PRESET_HUGE);
SetDirty(DIRTYFLAGS::MATRIX); is called when you change the editor or render mode.
I need to ask our tech team if somebody remember the reason for that.
yes it's done with the flag MOGENFLAG_CLONE_ON.
could you be more verbose about the kind of object you are using ? For example mograph's object are really special, almost always dirty.
Please also, take a loog at our guidelines to use the forum's functionalities (specially the tags)
I'm pretty sure you are talking about python, that information is useful.
Also, sharing some code (if you can) will help us to reproduce the issue.
Are you using a python generator or you are creating your own plugin and your own NodeData ?
you have to send the following message to the object so it will switch internally from regular falloff to fields.
The main should contain all the objects that all the takes are changing. Are you sure none of the take change a value of the "Null" object ?
regarding your question, this thread will help
We also have our documentation
You can also use GetTakeMode and enable the auto mode accordingly.
opClone = op.GetClone(c4d.COPYFLAGS_0)
op[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = c4d.OBJECT_OFF
op[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = c4d.OBJECT_OFF
# Gets the TakeData from the active document (holds all information about Takes)
takeData = doc.GetTakeData()
if takeData is None:
raise RuntimeError("Failed to retrieve the take data.")
# Adds a new Take
newTake = takeData.AddTake(op.GetName(), None, None)
if newTake is None:
raise RuntimeError("Failed to add a new take.")
# Defines the created Take as the active one
# Checks if there is some TakeData and the current mode is set to auto Take
if takeData and takeData.GetTakeMode() == c4d.TAKE_MODE_AUTO:
newTake.AutoTake(takeData, op, opClone)
# Pushes an update event to Cinema 4D
if __name__ == '__main__':