Hello @blastframe,
thank you for reaching out to us. No, there is no specific message for an object being moved. The closest message is EVMSG_CHANGE
, but that is a core message which is not being broadcasted to the NodeData
message stream, .e.g., the message()
function of a scripting object. One could also (ab)use some node messages in this scenario of yours, but it would not be my first choice.
I would simply store the data in the script module or use Cinema's dirty flags. For details see example below. I didn't bother with hitting your extremely specific requirements of reacting to translation and rotation transforms, but not scaling transforms, and instead just compare against the plain matrix. If you wanted to do this, you would have to compare against the normalized frame components of the matrix (v1, v2, v3) and its offset.
Edit: Eh, mistook this for a scripting object question. The answer remains the same, it is only that you then probably want to attach MATRIX_CACHE
to your NodeData
implementation and not some module. In a NodeData
environment you would also have to make sure that MATRIX_CACHE
is flushed with frame zero if you want it to be flushed and as it can be done by a Python Programming Tag.
Cheers,
Ferdinand
The file: move_cube.c4d
The result: 
The code:
"""Example for storing data in the module of a scripting object.
This approach can be sometimes not be sufficient, then one can do more or less
the same by storing data in the BaseContainer of an object. For that one will
need a Plugin ID to store that data collision free.
One could also take a more message oriented approach, but it seems a bit over
the top here. The strategy would be there to check for
IsDirty(DIRTYFLAGS_MATRIX).
As discussed in:
https://plugincafe.maxon.net/topic/13509/
"""
import c4d
MATRIX_CACHE = None
def main():
"""
"""
# Make the module attribute storing the last seen matrix locally visible,
# get the object attached to the tag and the global matrix of the that
# object.
global MATRIX_CACHE
obj = op.GetObject()
mg = obj.GetMg()
# Compare them and if they are not equal, then do stuff.
if mg != MATRIX_CACHE:
MATRIX_CACHE = mg
print (f"Global matrix of {obj.GetName()} has changed to: {mg}")
# We can also more or less do the same with DIRTYFLAGS_MATRIX. The problem
# with this approach is, that dirty flags can be consumed before one had
# a chance to react to them. It is more safe to use dirty counts, but
# there one will need some form of cache/look-up value again, since the
# dirty count only stores the total number of changes, not their purpose.
if obj.IsDirty(c4d.DIRTYFLAGS_MATRIX):
print (f"{obj.GetName()} is DIRTYFLAGS_MATRIX dirty.")