Hello @datamilch,
Thank you for reaching out to us. I am struggling with understanding the basic premise of your question when you say ' a commanddata plugin in combination with an objectdata plugin to store data in the document'. While I understand that statement in an abstract sense, it is unclear to me how these CommandData/GeDialog
to ObjectData/BaseObject
bindings come to pass concretely.
- You are correct about the undo system of
BaseDocument
only supporting scene elements.
- That is however the common approach, undo's usually only include the data layer of an application and not the interface layer. When you delete the file
foo.bar
in the Windows explorer, then change the view mode from List to Details, and finally press CTRL+Z
, it Windows will restore the file foo.bar
and not change the view mode of that Explorer window. Most applications, including Cinema 4D, handle it in that way.
With that being said, it is unclear to me for which entity you want to crate undo's. Manually creating undo's for scene elements, e.g., a BaseObject
instance of type Omyplugin
as the frontend of the class MyPluginData (ObjectData)
hook, is usually not necessary. Simply setting parameter values will create the necessary undo steps. Manual undo handling only becomes necessary when you want to consolidate multiple actions into one undo step.
You cannot create undo steps for anything that is not of type BaseList2D
, e.g., a CommandData
or GeDialog
instance. You would have to implement your own undo stack here. That is, however, not advisable as undo's for GUIs are a very odd thing to do.
"is it right, that I could create the undos in the commanddata OR the objectdata plugin?"
No, that is not correct. In all non-main thread NodeData
methods, e.g., Shaderdata.Output
, TagData.Execute
, or ObjectData.GetVirtualObjects
, creating undo's is strictly forbidden as lined out under the threading restrictions. Cinema 4D will definitely crash if you ignore this. In methods of NodeData
which often run on the main thread, e.g., NodeData.Message
, you can technically check for being on the main thread and then modify node
and create undo's for these modifications. This is however only something that one should do as a last ditch effort when one has no other option. In general, a node should not mess with its own undo steps.
So if I doundo, i could send a custom-message to the commanddata plugin to update the gui.
Sort of. My problem is here still that I do not know what you want to do. But to tie a dialog G to the state of an object O, one usually goes the other way around. G simply listens in its GeDialog.CoreMessage
for EVMSG_CHANGE
, and then checks the state of O.
But if I drag a slider in the command-gui, the message is sent multiple times before I release it at the final value.
If you want to consolidate multiple actions, you must that in your dialog. You could either only write what you consider to be the final value, or simply write all values but wrap them as one undo item. We recently talked about slider handling here.
I would recommend that you describe what you practically want to achieve and show code. Otherwise, I will have to do a lot guessing, which then leads to fuzzy answers such as this one here (my apologies).
Cheers,
Ferdinand