Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hey folks,
I could need your help on building a Python Generator version of the Chamfer Tool. It's based on the Py-Parametric tools build by Andreas back in days. There were very helpful for setting up the generator. But here comes the issue: Using GetAndCheckHierarchyClone does not work well with the MCOMMAND_CURRENTSTATETOOBJECT (at least this is what I think). When I test the plugin and use a Cloner with Splines under a Connect Object, it only affects the first clone. When I make the Connect Object editable, it works on all objects. See images. When I bypass the dirty check and add replace "clone" by "op" in line 63 in the "GetVirtualObjects" method, than it works, but very badly.
I would appreciate any kind of help
import os import c4d from c4d import plugins, utils, bitmaps ############################################################################################################### #Based on the Py-Parametric Tools by Andreas Block ############################################################################################################### class ModelingCommandGeneratorModifier(plugins.ObjectData): _toolId = -1 _doSelection = False _selectId = -1 def InitCommon(self, toolId, doSelection, selectId): self._toolId = toolId self._doSelection = doSelection self._selectId = selectId def ExecModelingCommand(self, doc, opCtrl, op, parent): if op is None: return splineObjects = [] if op.GetDown().CheckType(c4d.Ospline) is False: splineObjects = utils.SendModelingCommand(command = c4d.MCOMMAND_CURRENTSTATETOOBJECT, list = [op.GetDown()], mode = c4d.MODELINGCOMMANDMODE_ALL, bc = c4d.BaseContainer(), doc = doc) else: splineObjects.append(op.GetDown()) if not splineObjects: return if splineObjects[0].CheckType(c4d.Ospline) is True: res = utils.SendModelingCommand(command = self._toolId, list = splineObjects, mode = c4d.MODELINGCOMMANDMODE_ALL, bc = opCtrl.GetDataInstance(), # settings, doc = doc) if res is True: splineObjects[0].InsertUnderLast(parent) def GetVirtualObjects(self, op, hh): doc = op.GetDocument() objInput = op.GetDown() if objInput is None: return None objRet = c4d.BaseObject(c4d.Onull) if doc is None or objRet is None: return None hierarchyClone = op.GetAndCheckHierarchyClone(hh, objInput, c4d.HIERARCHYCLONEFLAGS_NONE, True) if hierarchyClone["dirty"] is False: return hierarchyClone["clone"] clone = hierarchyClone["clone"] if clone is None: return objRet #When I replace "clone" to "op" and bypass the dirty checks, than it works but very sluggish self.ExecModelingCommand(doc, op, clone, objRet) return objRet class ChamferGen(ModelingCommandGeneratorModifier): def Init(self, op): ModelingCommandGeneratorModifier.InitCommon(self, c4d.ID_MODELING_SPLINE_CHAMFER_TOOL, False, -1) InitChamferDesc(self, op) return True def InitChamferDesc(inst, op): inst.InitAttr(op, bool, [c4d.MDATA_SPLINE_CHAMFERFLAT]) inst.InitAttr(op, float, [c4d.MDATA_SPLINE_CHAMFERRADIUS]) op[c4d.MDATA_SPLINE_CHAMFERRADIUS] = 5.0 ############################################################################################################### # Plugin Registration ############################################################################################################### PLUGIN_ID_GENERATOR = 9036026 def RegisterObjectData(id, name, bmpPath, objData, desc, flags): bmp = bitmaps.BaseBitmap() bmp.InitWith(os.path.join(bmpPath, "res", "icon.tif")) plugins.RegisterObjectPlugin(id=id, str=name, g=objData, description=desc, icon=bmp, info=flags) if __name__ == "__main__": path, fn = os.path.split(__file__) RegisterObjectData(PLUGIN_ID_GENERATOR, "ChamferGen", path, ChamferGen, "ochamfergen", c4d.OBJECT_GENERATOR | c4d.OBJECT_INPUT) print "ChamferGen 1.0 successfully initialized"
hello, please use our forum functionalities
as said in the documentation, Current State to Object should be use on a clone. And using a temporary document can help.
If you were not using a cloner, you could use HIERARCHYCLONEFLAGS_ASSPLINE. But with a cloner, the objects are returned as lineObject. And the chamfer only accept SplineObject (it checks for Ospline type).
HIERARCHYCLONEFLAGS_ASSPLINE
To avoid to run through the hierarchy, i've used a Join command and using the chamfer on the result.
def GetVirtualObjects(self, op, hh): objRet = c4d.BaseObject(c4d.Onull) doc = op.GetDocument() if doc is None: return objRet objInput = op.GetDown() if objInput is None: return objRet # If we set the flags to HIERARCHYCLONEFLAGS_ASSPLINE the result will be a lineObject and not a SplineObject. This will not pass the Chamfer tool. hierarchyClone = op.GetAndCheckHierarchyClone(hh, objInput, c4d.HIERARCHYCLONEFLAGS_NONE , True) if hierarchyClone["dirty"] is False: return hierarchyClone["clone"] # Retrieves the cloner cloner = op.GetDown() # Creates a temporary document. tempDoc = c4d.documents.BaseDocument() # Use a clone of the cloner so we can send it to a temporary document. cloned = cloner.GetClone(c4d.COPYFLAGS_NONE) # Insert the cloned object to the temporary document. tempDoc.InsertObject(cloned) # Retrieves the currect states. result = utils.SendModelingCommand(command = c4d.MCOMMAND_CURRENTSTATETOOBJECT, list = [cloned] , doc= tempDoc) spline = None if result: spline = result[0].GetDown() else: return objRet # Use the join command so we only have one spline object. (that help in case of a hierarchy) result = utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN, list = result , doc= tempDoc) # Champher the spline if result[0].IsInstanceOf(c4d.Ospline): bc = c4d.BaseContainer() bc[c4d.MDATA_SPLINE_CHAMFERFLAT] = True bc[c4d.MDATA_SPLINE_CHAMFERRADIUS] = 19.0 res = utils.SendModelingCommand(command = c4d.ID_MODELING_SPLINE_CHAMFER_TOOL, list = result, bc = bc) if res: return result[0] return objRet
Cheers, Manuel.
@m_magalhaes
Thank you for your help! It works. I really like the tip of the temporary document. Does it make sense to use c4d.documents.KillDocument(doc) after the process is complete to free up resources?
I also have another question. How should I change the setup to support multiple children? (see image) I tried to insert multiple objects in the tempDoc via a loop but nothing really worked.
hello,
you can retrieve the hierarchy clone "asis" with
hierarchyClone = op.GetAndCheckHierarchyClone(hh, objInput, c4d.HIERARCHYCLONEFLAGS_ASIS , True)
Than use Currentstate to object and join the result as with the cloner.
in my previous code you can just change this line to see the result.
cloner = hierarchyClone["clone"]
The problem is that if you have a polygon object, the join command will return a polygon object and a spline. One workaround would be to run through the hierarchy and remove the polygon objects.
Just an idea, have you tried a deformer instead of a generator ? (just like our bevel deformer for polygon object)
Cheers, Manuel
Hey Manuel,
I tried this method but I encountered another issue. The copy to another document does not work in a setup with a Mograph Effector. Therefore, I am inserting the object to the original document and try to remove the original. But that does not work. When I make ChamferGen editable, it creates the original Connect+Children objects as well as the editable Spline Object. I tried stuff like cloner.Remove() but that did not work. The setup is linked below.
funny i've learned something (once again)
I told that setting the flag to HIERARCHYCLONEFLAGS_ASSPLINE will return a LineObject and the chamfer tool want SplineObject. The fun fact is that the join command will transform that line object to a SplineObject.
So no need to use the CSTO to a temp document. Just use the Join command on the result of the GetAndCheckHierarchyClone
def GetVirtualObjects(self, op, hh): objRet = c4d.BaseObject(c4d.Onull) doc = op.GetDocument() if doc is None: return objRet objInput = op.GetDown() if objInput is None: return objRet # If we set the flags to HIERARCHYCLONEFLAGS_ASSPLINE the result will be a lineObject and not a SplineObject. This will not pass the Chamfer tool. hierarchyClone = op.GetAndCheckHierarchyClone(hh, objInput, c4d.HIERARCHYCLONEFLAGS_ASSPLINE , True) if hierarchyClone["dirty"] is False: print "return cache" return hierarchyClone["clone"] spline = hierarchyClone["clone"] # Use the join command so we only have one spline object. (that help in case of a hierarchy) result = utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN, list = [spline], doc= doc) res = None # Champher the spline if result[0].IsInstanceOf(c4d.Ospline): bc = c4d.BaseContainer() bc[c4d.MDATA_SPLINE_CHAMFERFLAT] = True bc[c4d.MDATA_SPLINE_CHAMFERRADIUS] = 19.0 res = utils.SendModelingCommand(command = c4d.ID_MODELING_SPLINE_CHAMFER_TOOL, list = result, bc = bc) print res if res: return result[0] return objRet
Amazing! Thank you Manuel! It works with multiple objects, Cloners etc. Without your help I would not make it