Solved Mouse Over Generator Object, no position info

I'm using a tooldata plugin and was originally trying to get the polygon data from a generator/objectdata object. That doesn't work because even though it's classed as a polygon object, no polygon data is available to grab from outside. Always returns as None. So I thought I'd just get the hit position and then reference that with the object itself. Only problem is, can't do that either. I can get pickobject to give me the generator object but no more info, no hit position, z-depth, nothing. GeRayCollider is the same story.

None of the ViewportSelect methods can get me this info either.
c4d.utils.ViewportSelect.PickObject() is supposed to return a Z value but doesn't.

Any ideas?


could you please follow our forum guidelines when posting a question, using tags and mark you thread as a questions can help us to answer your questions faster.

Generator are not polygon objects, they store virtual object in their cache. It is also explained on the python documentation

That's pretty logical to me that you can't have any information from the generator.

What kind of information are you trying to retrieve ?


MAXON SDK Specialist

MAXON Registered Developer

Ah apologies, I will make sure to follow the guidelines in future.
So I'm building a python objectdata plugin that will create geometry but I want to add more geometry to it with a tooldata plugin by brushing over the geometry that has already been created, the tooldata will just tell the objectdata to create the geometry though. The object data plugin will keep track of all geometry in order for other tooldata plugins to act on that geometry.
To put the new geo in the correct position though, I would need to know on what coordinate of the already generated geometry I would be hitting with the mouse, ideally I'd like access to the normal of the hitpoint too. Is there any way to detect a mouseover event on a virtual object?

As Manuel stated, you'll need to get the object's cache (baseObjectPtr->GetCache()). If you need the exact projected position of your mouse cursor on the polygon geometry, my first idea would be to use class GeRayCollider to shoot rays from your camera through the mouse cursor onto the geometry. Since you get a BaseDraw* in ToolData::MouseInput() you have all the necessary functions to transform mouse coordinates to world space.

Only asking personal code questions here.


using github example will help you to build your tool.

using the liquid paint plugin as a base, using the script example to iterate over caches where you can get the function DeformedPolygonCacheIterator


Int the function GetCursorInfo you have to retrieve the object the mouse is over, this can be done with the fuction c4d.utils.ViewportSelect.PickObject and GetPixelInfoPolygon

   def GetCursorInfo(self, doc, data, bd, x, y, bc):
        xPos = int(x)
        yPos = int(y)

        vpSelect = c4d.utils.ViewportSelect()
        rad = 20
        flags = c4d.VIEWPORT_PICK_FLAGS_NONE
        # Retrieve the object that are hovered by the mouse
        objectsList = c4d.utils.ViewportSelect.PickObject(bd, doc, xPos, yPos, rad, flags)

        # Retrieve the frame information, we need the height and width information to initialize the ViewportSelect object.
        frame = bd.GetFrame()   
        width = right - left + 1   
        height = bottom - top + 1   

        # Retrieve the object as PolygonObject
        polygonObjectList = list()
        for op in objectsList:
            for cache in self.DeformedPolygonCacheIterator(op):

        if len(polygonObjectList) < 1:
            return True

        # Init the viewportSelect object
        if not vpSelect.Init(width, height, bd, polygonObjectList, c4d.Mpolyedgepoint, True, c4d.VIEWPORTSELECTFLAGS_IGNORE_HIDDEN_SEL):
            return True

        # Retrieve the polygon information
        infopolygon = vpSelect.GetPixelInfoPolygon(xPos, yPos)
        if not infopolygon:
            return True

        i = infopolygon["i"]  # int
        op = infopolygon["op"]  # c4d.BaseObject
        z = infopolygon["z"]  # float

        # Build the array of the polygon vertices in world coordinates
        cpoly = op.GetPolygon(i)
        opmg = op.GetMg()
        self.pointList = list()
        if not cpoly.IsTriangle():
        # Transform the local coordinates to world coordinates.
        self.pointList = [opmg * p for p in self.pointList]
        # Update the view.
        c4d.DrawViews(c4d.DA_ONLY_ACTIVE_VIEW | c4d.DA_NO_THREAD | c4d.DA_NO_ANIMATION)
        # If the cursor has left a user area, simply return True
        if bc.GetId() == c4d.BFM_CURSORINFO_REMOVE:
            return True

        # Sets the BubbleHelp string and cursor.
        bc.SetInt32(c4d.RESULT_CURSOR, c4d.MOUSE_POINT_HAND)
        return True



MAXON SDK Specialist

MAXON Registered Developer

@m_magalhaes Manuel you hero! That was it! DeformedPolygonCacheIterator was the key! Thank you so much!