Solved Problem on AddUndo and SendModellingCommand (Weld Tool)

Hi PluginCafe team!

I'm trying to create a script that weld selected points on the middle. For the scene, I just have the default cube made to an editable object.

It works as expected, but not with the AddUndo.

It gives me a dialog box error of
A problem with this project has been detected: Object "Cube" - Point selection out of bonds

Is there a way around this?

Here is the code so far

import c4d
from c4d import utils

settings = c4d.BaseContainer() 

res = utils.SendModelingCommand(command = c4d.ID_MODELING_WELD_TOOL,  
                                list = [op], 
                                mode = c4d.MODELINGCOMMANDMODE_POINTSELECTION, 
                                bc = settings,
                                doc = doc)
                                
doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
c4d.EventAdd()

Thank you for looking at the problem

P.S.
From what I understand, if you set the c4d.BaseContainer at empty, it will weld it on the middle by default which is what I want. But just wondering, is there a way to set-it explicitly?

I checked the parameters on the resource section which is follows:

{

	MDATA_WELD_POINT			    				     = 1100, //VECTOR
	MDATA_WELD_TOPOINT                     = 1101, //BOOL
	MDATA_WELD_POINTINDEX                  = 1102, //LONG
	MDATA_WELD_OBJECTINDEX                 = 1103, //LONG
	MDATA_WELD_VISIBLE			               = 1104, //BOOL
	MDATA_WELD_COLLAPSE                    = 1105, //BOOL
	MDATA_WELD_COLLAPSE_P1                 = 1106, //LONG
	MDATA_WELD_COLLAPSE_P2                 = 1107, //LONG
	MDATA_WELD_COLLAPSE_OBJ1               = 1108, //LINK
	MDATA_WELD_COLLAPSE_OBJ2               = 1109, //LINK
	MDATA_WELDPOINT_
};

But the documentation does not provide a description on such parameters. Or maybe I'm missing something out?

Hi @bentraje,

In order to support undo, you should encapsulate all your calls of BaseDocument.AddUndo with BaseDocument.StartUndo and BaseDocument.EndUndo
Moreover, take care depending on the operation you are doing, BaseDocument.AddUndo has to be called before or after your operation. Take a look at the documentation to know more.

Typically StartUndo, defines the state of the scene to be reverted when pressing undo. And EndUndo the state of the scene to be reverted when pressing re-do after an undo.
AddUndo then record all the changes that you want to store in this undoing.

Which will give us something like:

import c4d

# Main function
def main():
    # Create the BaseContainer to define the tool settings
    settings = c4d.BaseContainer()  
    
    # Explicitly say we will not use point, so the center will be used
    settings[c4d.MDATA_WELD_TOPOINT] = False
    
    doc.StartUndo()
	
    doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
    # Execute the SendModelingCommand
    res = c4d.utils.SendModelingCommand(command = c4d.ID_MODELING_WELD_TOOL,
                                    list = [op], 
                                    mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION, 
                                    bc = settings, 
                                    doc = doc)
                                    
    doc.EndUndo()
	
    # Update the scene
    c4d.EventAdd()

# Execute main()
if __name__=='__main__':
    main()

To find more information about how ID_MODELING_WELD_TOOL works, you can have a look at this topic.

If you have any question, please let me know.
Cheers,
Maxime.

Thanks @m_adam

Works as expected. Have a great day ahead!