Undo's and ObjectData

On 30/08/2016 at 09:04, xxxxxxxx wrote:

Hello all,

Got another little dumb question for you guys, if you don't mind:

One of my ObjectData plugins I made for our pipeline keeps track of a few other  objects' positions and behaves accordingly.  When I move one of these object's position and then undo it, my plugin refuses to acknowledge the change in position until the user clicks somewhere (anywhere) in C4D.

I've thrown in everything but the kitchen sink under the MSG_DOCUMENTINFO_TYPE_UNDO Message() type--that is, catching when the user makes an undo and trying to sync up and send update messages around--but it will forever and always return the old position until a click is made, even while python scripts (edit: tags, I mean) immediately print (for testing) the correct position post-undo.

I've tread twiddling with priorities, too, but nothing gives :\  Does anyone know the proper way to accomplish this in an ObjectData plugin?

As usual, thanks very much for any advice :heart:

On 31/08/2016 at 02:52, xxxxxxxx wrote:


the proper way to use an ObjectData generator (actually not sure you are working on a generator?) with other objects is via the OBJECT_INPUT flag using its child objects. Otherwise you can (actually will) run into all sorts of problems.

Maybe you can provide some more details on what you are actually trying to achieve? What kind of ObjectData you are currently using?

On 31/08/2016 at 12:20, xxxxxxxx wrote:

Oohh, right.  Yeah, some back-story on what I'm doing: we've been using a fairly ad hoc rig that, to date, has been a Python tag and a null with user data; the two of them drive a fairly complex rig of control objects and, ehh, stuff.  Occasionally we find a bug in the script or realize something needs tweaked, and I have to patch it and make sure everyone changes their python tag out for the latest version, so I'm porting the whole thing over to plugins and having them import the main code via modules that I can easily change in once place (and plugins are just cleaner in general).

Sorry, too much information--all that to say this ObjectData is replacing the null with user data in the original setup, and, correct, it's not actually working as a generator (or anything), it's just a glorified set of BaseContainers.  Though it does get input in the form of some objects' positions in the scene, so if that's a bad idea, I should change something.  I did read the blurbs in the Python and C++ docs about object plugins et al, but it wouldn't be the first or last time I miss something obvious from what I'm reading.

The output data is for the tag (or whatever's going to replace the tag) to use, and that will actually move objects around in the scene.  Without derailing this thread too much more: I was going to use a tag registered in the same plugin; I haven't gotten that far, but would that be ok to do, having one tag move a few dozen objects around?

Sorry for the novella of a post!  It's all just so I can get the right data out of my object post-Undo without clicking somewhere :slightly_smiling_face:  I *hate* having to click to make it update, especially if you want to keep the active object selected.

Thanks for the help!

On 01/09/2016 at 08:00, xxxxxxxx wrote:


don't worry about the length of the post, I rather have more details to work with, than less.

This is actually quite an ambitious project, as the lack of dependency tracking on arbitrary objects is currently one of the main issues in Cinema. No matter what you do, sooner or later in your case you will run into priority issues.

In an ObjectData plugin you can try to do something like you requested in Execute() and you could use 
AddToExecution() to minimize priority issues. Maybe you tried this already, as you mention "playing with priorities" in your first post. As said before, I'm not sure there's a perfect solution in this case.

In any case always make sure not to violate any of the threading rules, see threading information in the docs.

One other way we thought of, was the use of Xpresso. Basically setting up "Set Driver / Set Driven" connections by a CommandData or script. But unfortunately there's currently a bug pending, which makes it impossible to set up a Xpresso network via Python (it's currently not possible to add for example the dynamic ports to an object node). But also an Xpresso solution doesn't solve priority issues completely.

On your tag question: A tag should actually only modify the object it is attached to. But again, as long as you pay attention to the threading rules, you could get away with it in Execute().

On 01/09/2016 at 09:25, xxxxxxxx wrote:

Gotchya, gotchya--thanks for the info.

Yeah, changing the priority in AddToExecution() is what I was referring to in the first post, but thanks for the thought.  Maybe I'll approach it from a different angle...  If nothing else this whole operation has really de-mystified C4D plugins for me.

I'll report back when (if) I figure something out, but in the meantime you very much answered my question.  Thanks again, Andreas!

On 01/09/2016 at 13:21, xxxxxxxx wrote:

Wwwell, well, well, guess what desperate ploy actually pulled through in the end.  (Mind you, I have so much other, more important work to do, but this was really buggin' me.)  I just deselect and re-select the active object :slightly_smiling_face:  (or select None if None was selected)

if type==c4d.MSG_DOCUMENTINFO:
            if data['type']==c4d.MSG_DOCUMENTINFO_TYPE_UNDO: #Undo was done did
		obj = doc.GetActiveObject()
                if obj:

doc is defined further up, of course, and I have some other checks in there so that it doesn't do it *every* ctrl+z, but that's the idea.  Now updates are propagated (as far as the user can tell) immediately, albeit by the ugliest, jankiest way ever devised by mankind, but it still makes me happy.  I hope it's safe enough.