Hi @merkvilson, to be honest, I completely overlooked the problem and thought op within ModifyObject would be a splineObject.
To clarify MCOMMAND_DELETE do not work on LineObject (which are the object for spline cache).
So in order to do so here a hacky solution.
Use the actual spline object from the scene, and then Apply the delete into this SplineObject (since there is no way to get a SplineObject from a LineObject).
class Oresplines(plugins.ObjectData):
# Get obj and all its Children into a list
def GetChildren(self, obj, next, modifiedObjs=None):
if modifiedObjs is None:
modifiedObjs = list()
while obj and obj != next:
modifiedObjs.append(obj)
self.GetChildren(obj.GetDown(), next, modifiedObjs)
obj = obj.GetNext()
return modifiedObjs
# Compare 2 line object and tell if it's the same one (based on the topology + space position of the object)
def compareOline(self, a, b):
if type(a) != type(b): return False
if not a.CheckType(c4d.Oline): return False
# Do different pass of checks from speedier to slower in order to leave as soon as possible if object does not match.
# Fast check, check for pt count
if a.GetPointCount() != b.GetPointCount():
return False
# Fast check
if a.GetMg() != b.GetMg():
return False
# slower check
if a.GetAllPoints() != b.GetAllPoints():
return False
tagA = a.GetTag(c4d.Tline)
tagB = b.GetTag(c4d.Tline)
if not tagA or not tagB:
return False
# Even slower
if tagA.GetAllHighlevelData() != tagB.GetAllHighlevelData():
return False
return True
def ModifyObject(self, mod, doc, op, op_mg, mod_mg, lod, flags, thread):
# Handle polygons
if not op.IsInstanceOf(c4d.Oline):
op.GetPointS().SelectAll(5)
res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_DELETE,
list = [op],
mode = 1,
doc = doc,
flags = 0)
return True
# First step is to get all objects modified by our modifier.
# Modifier works only if they are within another object. And all children of this hierarchy are modified.
parent = mod.GetUp()
isInGroup = bool(parent)
# Should never happen if we are not in a group, nothing is modified, so ModifyObject is never called.
if not isInGroup: return True
# Get all children of the parent (aka all objects modified by our modifier).
modifiedObjs = self.GetChildren(parent, mod.GetNext())
# Iterate over all modified objects, and check which LineObject is currently modified in the curent ModifyObject call.
spline = None
for obj in modifiedObjs:
cache = obj.GetCache()
if not cache:
continue
# Comparison of Oline might fail, C4D do not guarantee the execution order of ModifyObject.
# So if we get A and B identical e.g. 2 c4d.Osplinecircle with same parameters,
# ModifyObject may currently edit B before A, while the compare will return True to the first object matching the condition
# So it may return true on A while B was modified. But in the end, it does not really matter since both will be modified just order might get swapped.
if self.compareOline(cache, op):
spline = obj
break
# Check if our modified object is a spline and nothing else
if not spline or not spline.GetInfo()&c4d.OBJECT_ISSPLINE:
return True
# Then we get a copy of the SplineObject located in the scene
splineObj = spline.GetRealSpline().GetClone()
if not splineObj: return True
# Create a tempo document for our delete operation
workDoc = c4d.documents.BaseDocument()
workDoc.InsertObject(splineObj)
# Select and delet our points
splineObj.GetPointS().SelectAll(1)
res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_DELETE,
list = [splineObj],
mode = c4d.MODELINGCOMMANDMODE_POINTSELECTION,
doc = workDoc,
flags = 0)
if not res:
return True
# Build the cache, in order to generate a Oline object from the resulting SplineObject
workDoc.ExecutePasses(thread, False, False, True, c4d.BUILDFLAGS_INTERNALRENDERER)
# Get the Cache (Oline object) of our modified splineObject
oLineModified = splineObj.GetCache()
if not oLineModified: return True
# Copy our modified LineObject to the op LineObject
oLineModified.CopyTo(op, c4d.COPYFLAGS_NONE)
return True
If you have any question, please let me know. :smile:
Cheers,
Maxime.