How can I use Plane Cut in Python
-
Hi!
How can I use the Plane Cut Tool with Python in Cinema4D. I tried the following code but it always fails and returns false as a result. Also: is it possible to specify coordinates by using a vertex (e.g. c4d.Vector(0,0,0) to specify the cut location?obj = doc.GetActiveObject() settings = c4d.BaseContainer() # Settings settings[c4d.MDATA_KNIFEPLANE_MODE] = c4d.MDATA_KNIFEPLANE_MODE_REGION_A settings[c4d.MDATA_KNIFEPLANE_PLANE_MODE] = c4d.MDATA_KNIFEPLANE_PLANE_MODE_LOCAL settings[c4d.MDATA_KNIFEPLANE_PLANE] = c4d.MDATA_KNIFEPLANE_PLANE_XZ result = c4d.utils.SendModelingCommand( command=c4d.ID_MODELING_KNIFE_PLANE, # Use the ID of the modeling command for the cut tool list=[obj], mode=c4d.MODELINGCOMMANDMODE_POLYGONSELECTION, bc=settings, doc=doc, )
-
Hello @Christian-0,
Welcome to the Plugin Café forum and the Cinema 4D development community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our Forum and Support Guidelines, as they line out details about the Maxon SDK Group support procedures. Of special importance are:
- Support Procedures: Scope of Support: Lines out the things we will do and what we will not do.
- Support Procedures: Confidential Data: Most questions should be accompanied by code but code cannot always be shared publicly. This section explains how to share code confidentially with Maxon.
- Forum Structure and Features: Lines out how the forum works.
- Structure of a Question: Lines out how to ask a good technical question. It is not mandatory to follow this exactly, but you should follow the idea of keeping things short and mentioning your primary question in a clear manner.
About your First Question
You got most things right in your script, but probably missed our resource documentation. There is also the problem that Cinema 4D relies these days on the new modelling core which has not been documented too well for
SendModelingCommand
yet. Find below my answer as a script.Cheers,
FerdinandResult:
Code:
"""Demonstrates how to use the plane cut tool with SendModelingCommand (SMC). Must be run with an editable polygonal geometry selected. For details about SMC see [1]. Tools are documented in the resources of the docs, the plane cut tool is for example documented here [2]. The problem is that most SMC (I think all) commands are these days wrapped by the new modelling core which reimplements most of the modelling operations of Cinema 4D. In case of the plane cut tool this means for example that MDATA_KNIFEPLANE_PIVOT_POSITION and MDATA_KNIFEPLANE_PIVOT_ROTATION are not in use anymore, being replaced by MDATA_KNIFEPLANE_MATRIX. This means a few things: * You cannot mimic each aspect of a tool with SMC. That has always been the case. You alternatively can manipulate the tool container of the tool and invoke `CallCommand` as shown here [3] but there you will probably run into problems with the mouse inputs. * The new modelling core re-imagines things and ignores a good portion of the settings you can see in the UI and adds a new field, MDATA_KNIFEPLANE_MATRIX. These are the fields that are evaluated by the new modelling core: mcd.bc->GetMatrix(MDATA_KNIFEPLANE_MATRIX) mcd.bc->GetInt32(MDATA_KNIFEPLANE_CONUT) mcd.bc->GetFloat(MDATA_KNIFEPLANE_OFFSET) mcd.bc->GetFloat(MDATA_KNIFEPLANE_DIST) mcd.bc->GetBool(MDATA_KNIFEPLANE_SELECTED) mcd.bc->GetBool(MDATA_KNIFEPLANE_SELECT_CUT) mcd.bc->GetBool(MDATA_KNIFEPLANE_CUTPOLYS) mcd.bc->GetInt32(MDATA_KNIFEPLANE_MODE) mcd.bc->GetBool(MDATA_KNIFEPLANE_NGON_CURVATURE) mcd.bc->GetBool(MDATA_KNIFEPLANE_REGULARSLICE) References: [1]: https://github.com/PluginCafe/cinema4d_py_sdk_extended/tree/master/scripts/04_3d_concepts/modeling/modeling_commands [2]: https://developers.maxon.net/docs/py/2023_2/classic_resource/tool/toolknifeplane.html [3]: https://developers.maxon.net/forum/topic/12298/toggle-knife-cut-planes/ """ import c4d op: c4d.BaseObject # The active object. doc: c4d.documents.BaseDocument # The currently active document. def main() -> None: """Runs the example. """ # Sort out a non polygon object being selected. if not isinstance(op, c4d.PolygonObject): raise TypeError(f"{op = }") # The settings container for the plane cut we will carry out. bc: c4d.BaseContainer = c4d.BaseContainer(c4d.ID_MODELING_KNIFE_PLANE) # The modelling core uses a matrix to define the cut instead of the two vectors of the classic # API tool. We define here a cutting plane +100 units on the y axis which is rotated by 45° ccw # on the x-axis. bc[c4d.MDATA_KNIFEPLANE_MATRIX] = (c4d.utils.MatrixRotX(c4d.utils.DegToRad(45.)) * c4d.utils.MatrixMove(c4d.Vector(0, 100, 0))) bc[c4d.MDATA_KNIFEPLANE_CONUT] = 4 # We want to make four cuts. bc[c4d.MDATA_KNIFEPLANE_DIST] = 25. # Which are 25 units apart each. bc[c4d.MDATA_KNIFEPLANE_CUTPOLYS] = True # This has to be true, the tool will fail otherwise. # Don't ask me why :) # Add an undo item for the plane cut we are going to carry out. doc.StartUndo() doc.AddUndo(c4d.UNDOTYPE_CHANGE, op) # Carry out the command. if not c4d.utils.SendModelingCommand(c4d.ID_MODELING_KNIFE_PLANE, [op], c4d.MODELINGCOMMANDMODE_ALL, bc, doc): print (f"Failed to run plane cut tool in the modelling core on {op}.") # CLose the undo and push an update event to the core of Cinema 4D. doc.EndUndo() c4d.EventAdd() if __name__ == "__main__": main()
-
Thank you very much! Now it is working.