Automatically add tags at last position on creation

Usually, when the user attaches a new tag to an object using the “Tags” menu in the Object Manager, the new tag is always added as first element to the object’s tag list.

For some tags, however, it would make sense to rather add them to the end of the object’s tag list. Especially if those tags should ‘layer’ their effects on top of each other (e.g. like multiple texture tags).

If you want your tag to be added to the end of the tag list automatically when it is being created, this article will tell you how.


Override your TagData’s Message function and catch the message type MSG_MENUPREPARE.

For that message type, you simply iterate over all existing tags (if there are any), remove the tag from the object it has just been attached to, and re-insert it after the last tag.


MyTagData::Message(GeListNode* node, LONG type, void* data);
  if (type == MSG_MENUPREPARE)
    // Get my own tag
    BaseTag *me = (BaseTag*)node;
    if (!me) return false;

    // Get the object
    BaseObject *op = me->GetObject();
    if (!op) return false;

    // Find the last tag
    BaseTag* last = op->GetFirstTag();
    if (last)
      // Iterate over tags to find the last one
      for (; ; )
        if (!last->GetNext())
        last = last->GetNext();

      // Remove tag from the 1st position

      // Re-insert tag after last tag
      op->InsertTag(me, last);

  return SUPER::Message(node, type, data);


def Message(self, node, type, data):
    if type == c4d.MSG_MENUPREPARE:
        # Get the object
        op = me.GetObject()
        if not op:
            return False

        # Find the last tag
        last = op.GetFirstTag()
        if last:
            # Iterate over tags to find the last one
            while True:
                if not last.GetNext():
                last = last.GetNext()

            # Remove tag from the 1st position

            # Re-insert tag after last tag
            op.InsertTag(me, last)

    return TagData.Message(node, type, data)

Frank Willeke

worked with computers since more than 20 years | got hooked on computer graphics back on the AMIGA | started programming at the age of 13 | relesed some successful plugins for cinema 4d | started working for maxon computer gmbh in 2009 | now contributing to cinema 4d as a senior developer making electronic music since 1993 | playing the electric guitar since 1995 age of 14 | first live gigs in 1997 | playing the bass guitar 2005 | playing keyboards and synths since 2012 experimenting with photography since 2003


  1. last = op.GetFirstTag()
    while last:
    next = last.GetNext()
    if not next:
    last = next

    Might be a little more performant. 🙂

  2. PS: Can we use any kind of formatting in the comments?

    And thanks for the post, good 2know we are actually allowed to do this in MSG_MENUPREPARE!

  3. Not really more performant, but a legitimate alternative. Depends on your personal programming style.

Comments are closed.