Solved S22: c4d.MCOMMAND_SPLIT returns a Bool instead of a List, while it returned a list in R21 and earlier versions

Hey guys, i have a script which uses the c4d.utils.SendModelingCommand until recently this returned a list to me. https://developers.MAXON.net/docs/Cinema4DPythonSDK/html/modules/c4d.utils/index.html#c4d.utils.SendModelingCommand

This function either returns a boolean, or a list. Up until R21 the following code returned a list to me. But as of S22 i get returned the bool true, which signifies it ran succesfully, but i cant seem to retrieve the list.

Any help on how i can get the list ( by passing a parameter or anything else ) would be appreciated.

Heres the related snippet of my code

selId = []
    sel = op.GetPolygonS()
    for index, selected in enumerate(sel.GetAll(polyCnt)):
        if not selected: continue
        selId.append(index)
    allPolys = [n for n in allPolys if n not in selId]
    settings = c4d.BaseContainer()
    res = utils.SendModelingCommand(command = c4d.MCOMMAND_SPLIT,
                                list = [op],
                                mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                                bc = settings,
                                doc = doc)

after running this script, res is now true instead of a List

many thanks in advance.

Thanks for the complete code, the issue is not located in the MCOMMAND_SPLIT but in the ID_MODELING_FILL_SELECTION_TOOL, within the S22 development cycle, parameters IDs changed but the new ones were not exposed to Python (I've created a bug report) so you need to hardcode them, like so

startPolyID = c4d.MDATA_FILLSEL_START_POLY if c4d.GetC4DVersion() < 21600 else 1100 # MDATA_FILL_POLYGON_INDEX in C++
selectionTypeID = c4d.MDATA_FILLSEL_SELECTION if c4d.GetC4DVersion() < 21600 else 1110 # MDATA_FILL_SELECTION_TYPE in C++

And here your code adapted to work

import c4d
from c4d import gui,utils

def main():
    if op.GetType() != c4d.Opolygon : return
    sel = op.GetPolygonS()
    polyCnt = op.GetPolygonCount()
    allPolys = range(polyCnt)
    doc.StartUndo()
    null = c4d.BaseObject(c4d.Onull)
    null[c4d.ID_BASELIST_NAME] = op[c4d.ID_BASELIST_NAME]+"_Segments"
    null.SetMg(op.GetMg())
    cntr = 0
    while allPolys:
        settings = c4d.BaseContainer()
        startPolyID = c4d.MDATA_FILLSEL_START_POLY if c4d.GetC4DVersion() < 21600 else 1100 # MDATA_FILL_POLYGON_INDEX in C++
        selectionTypeID = c4d.MDATA_FILLSEL_SELECTION if c4d.GetC4DVersion() < 21600 else 1110 # MDATA_FILL_SELECTION_TYPE in C++
        
        settings[startPolyID] = allPolys[0]
        settings[selectionTypeID] = c4d.SELECTION_NEW # Or SELECTION_ADD or SELECTION_SUB

        utils.SendModelingCommand(command = c4d.ID_MODELING_FILL_SELECTION_TOOL,
                                    list = [op],
                                    mode = c4d.MODELINGCOMMANDMODE_EDGESELECTION,
                                    bc = settings,
                                    doc = doc)
        selId = []
        sel = op.GetPolygonS()
        for index, selected in enumerate(sel.GetAll(polyCnt)):
            if not selected: continue
            selId.append(index)
            
        allPolys = [n for n in allPolys if n not in selId]
        settings = c4d.BaseContainer()
        res = utils.SendModelingCommand(command = c4d.MCOMMAND_SPLIT,
                                    list = [op],
                                    mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                                    bc = settings,
                                    doc = doc)
        
        res[0][c4d.ID_BASELIST_NAME] = op[c4d.ID_BASELIST_NAME]
        res[0].InsertUnderLast(null)
        res[0].SetMg(op.GetMg())
        sel.DeselectAll()
        cntr += 1
    doc.InsertObject(null)
    doc.AddUndo(c4d.UNDOTYPE_NEW, null)
    doc.EndUndo()
    c4d.EventAdd()


if __name__=='__main__':
    main()

Cheers,
Maxime.

Hi @Awesuus first of all welcome in the plugincafe community 🙂

Unfortunately, I wasn't able to reproduce your result in S22 and we correctly had a list returned.
So what's your exact Cinema 4D Version? ( I tested on S22.118).
Could you upload the Cinema 4D file where you are experiencing this issue?

Thanks in advance,
Cheers,
Maxime.

Hi Maxime,
Thank you so much for your reply. I also work in S22.118.

Here's the whole script that I'm trying to get to work:

import c4d
from c4d import gui,utils

def main():
    if op.GetType() != c4d.Opolygon : return
    sel = op.GetPolygonS()
    polyCnt = op.GetPolygonCount()
    allPolys = range(polyCnt)
    doc.StartUndo()
    null = c4d.BaseObject(c4d.Onull)
    null[c4d.ID_BASELIST_NAME] = op[c4d.ID_BASELIST_NAME]+"_Segments"
    null.SetMg(op.GetMg())
    cntr = 0
    while allPolys:
        settings = c4d.BaseContainer()
        settings[c4d.MDATA_FILLSEL_START_POLY] = allPolys[0]
        utils.SendModelingCommand(command = c4d.ID_MODELING_FILL_SELECTION_TOOL,
                                    list = [op],
                                    mode = c4d.MODELINGCOMMANDMODE_EDGESELECTION,
                                    bc = settings,
                                    doc = doc)
        selId = []
        sel = op.GetPolygonS()
        for index, selected in enumerate(sel.GetAll(polyCnt)):
            if not selected: continue
            selId.append(index)
        allPolys = [n for n in allPolys if n not in selId]
        settings = c4d.BaseContainer()
        res = utils.SendModelingCommand(command = c4d.MCOMMAND_SPLIT,
                                    list = [op],
                                    mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                                    bc = settings,
                                    doc = doc)
        
        res[0][c4d.ID_BASELIST_NAME] = op[c4d.ID_BASELIST_NAME]
        res[0].InsertUnderLast(null)
        res[0].SetMg(op.GetMg())
        sel.DeselectAll()
        cntr += 1
    doc.InsertObject(null)
    doc.AddUndo(c4d.UNDOTYPE_NEW, null)
    doc.EndUndo()
    c4d.EventAdd()


if __name__=='__main__':
    main()

What I'm trying to get it to do is explode the mesh by edge selection, so that it creates a new null with the separate objects. The c4d file below is just a scene with a sphere with edge selections.

test.c4d

Thanks for the complete code, the issue is not located in the MCOMMAND_SPLIT but in the ID_MODELING_FILL_SELECTION_TOOL, within the S22 development cycle, parameters IDs changed but the new ones were not exposed to Python (I've created a bug report) so you need to hardcode them, like so

startPolyID = c4d.MDATA_FILLSEL_START_POLY if c4d.GetC4DVersion() < 21600 else 1100 # MDATA_FILL_POLYGON_INDEX in C++
selectionTypeID = c4d.MDATA_FILLSEL_SELECTION if c4d.GetC4DVersion() < 21600 else 1110 # MDATA_FILL_SELECTION_TYPE in C++

And here your code adapted to work

import c4d
from c4d import gui,utils

def main():
    if op.GetType() != c4d.Opolygon : return
    sel = op.GetPolygonS()
    polyCnt = op.GetPolygonCount()
    allPolys = range(polyCnt)
    doc.StartUndo()
    null = c4d.BaseObject(c4d.Onull)
    null[c4d.ID_BASELIST_NAME] = op[c4d.ID_BASELIST_NAME]+"_Segments"
    null.SetMg(op.GetMg())
    cntr = 0
    while allPolys:
        settings = c4d.BaseContainer()
        startPolyID = c4d.MDATA_FILLSEL_START_POLY if c4d.GetC4DVersion() < 21600 else 1100 # MDATA_FILL_POLYGON_INDEX in C++
        selectionTypeID = c4d.MDATA_FILLSEL_SELECTION if c4d.GetC4DVersion() < 21600 else 1110 # MDATA_FILL_SELECTION_TYPE in C++
        
        settings[startPolyID] = allPolys[0]
        settings[selectionTypeID] = c4d.SELECTION_NEW # Or SELECTION_ADD or SELECTION_SUB

        utils.SendModelingCommand(command = c4d.ID_MODELING_FILL_SELECTION_TOOL,
                                    list = [op],
                                    mode = c4d.MODELINGCOMMANDMODE_EDGESELECTION,
                                    bc = settings,
                                    doc = doc)
        selId = []
        sel = op.GetPolygonS()
        for index, selected in enumerate(sel.GetAll(polyCnt)):
            if not selected: continue
            selId.append(index)
            
        allPolys = [n for n in allPolys if n not in selId]
        settings = c4d.BaseContainer()
        res = utils.SendModelingCommand(command = c4d.MCOMMAND_SPLIT,
                                    list = [op],
                                    mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                                    bc = settings,
                                    doc = doc)
        
        res[0][c4d.ID_BASELIST_NAME] = op[c4d.ID_BASELIST_NAME]
        res[0].InsertUnderLast(null)
        res[0].SetMg(op.GetMg())
        sel.DeselectAll()
        cntr += 1
    doc.InsertObject(null)
    doc.AddUndo(c4d.UNDOTYPE_NEW, null)
    doc.EndUndo()
    c4d.EventAdd()


if __name__=='__main__':
    main()

Cheers,
Maxime.

Thank you so much, this works like a charm!!!