@ferdinand Yes, you really understood the problem correctly, and I also knew the solution was unlikely to be simple. I was more interested in the possible options. Thank you for your analysis and recommendations.
Posts
-
RE: Reverse direction of multi-segment splines
-
RE: Reverse direction of multi-segment splines
Hi @ferdinand! I'm having trouble loading the site, so I'll leave the links. The reverse isn't the problem. I can't figure out how to automatically detect segments with "incorrect" direction, given their deformation, etc.
-
Reverse direction of multi-segment splines
Hi forum! When creating a spline with multiple segments (mostly text), the directions of some of the spline segments are inverted. I'd like to know if there's a simple and reliable way to fix this.I've tried several options, but they don't work correctly with deformed splines. Any advice would be greatly appreciated.spline_dir_problem.mp4
-
RE: Best way to hide a child and get best perfomance
Here's my prototype, if you are interested in my goal
Right now, everything works as expected, but only with these lines of code.
profile = GetCloneSpline(profile_orig) path = GetCloneSpline(path_orig)I'm happy with the current result. So, I'd love to get some additional advice on correctness and optimization. I think your previous answer was comprehensive enough, so I'll try to integrate some of it.
But I'd also be very grateful if you could take a look at my plugin and perhaps give me some more specific optimization tips. If that's not too much trouble, of course!


@ferdinand @ThomasB
Anyway, thanks for your replies and advices!
-
RE: Best way to hide a child and get best perfomance
Thanks for the answers! The method works great, but I ran into a problem when running the code further. My next part looks like this
spline = path.GetRealSpline() profile_spline = profile.GetRealSpline() if spline is None or profile_spline is None: return None points_profile = profile_spline.GetAllPoints() count_profile = len(points_profile) is_profile_closed = profile_spline.IsClosed() if count_profile < 2: return None sh = SplineHelp() if not sh.InitSplineWith( spline, c4d.SPLINEHELPFLAGS_GLOBALSPACE | c4d.SPLINEHELPFLAGS_USERDEFORMERS | c4d.SPLINEHELPFLAGS_CONTINUECURVE ): return NoneWith this approach, my path is no longer processed as GetRealSpline, while the profile is processed as expected.
I adjusted the code slightly, integrating the def GetCloneSpline function from this code.
Now I get this
profile_orig = op.GetDown() if profile_orig is None: return None path_orig = profile_orig.GetNext() if path_orig is None: return None dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTYFLAGS_ALL) profileData = op.GetAndCheckHierarchyClone( hh, profile_orig, c4d.HIERARCHYCLONEFLAGS_ASSPLINE, True) if not any([dirty, profileData["dirty"]]): return profileData["clone"] profile = GetCloneSpline(profile_orig) path = GetCloneSpline(path_orig)Maybe I have missed something important (let me know), but overall everything works like i want. But I have a few questions
-
Now I'm using CSTO as a quick fix for the GetRealSpline issue, but it seems incorrect. I'd like to know which way was better:
use CSTO outside of GVO (using a temporary document, as in the example) for improvement, or if I should try to find an alternative solution? -
I didn't fully understand this message: is it better to use caches instead of cloning, or should I use both in combination?
-
-
Best way to hide a child and get best perfomance
Hi, forum!
I'm working on a tool the principle of operation of which is similar like a "Sweep". It wraps one "profile" spline around a "path" spline. I want any geometric change to these splines to trigger an update. I think I've figured it out using this code.def GetVirtualObjects(self, op, hh): doc = op.GetDocument() path = op.GetDown() if path is None: return None profile = path.GetNext() if profile is None: return None dirty = op.CheckCache(hh)\ or op.IsDirty(c4d.DIRTY_DATA)\ or path.IsDirty(c4d.DIRTY_DATA)\ or path.IsDirty(c4d.DIRTY_MATRIX)\ or profile.IsDirty(c4d.DIRTY_DATA)\ or profile.IsDirty(c4d.DIRTY_MATRIX) if not dirty: return op.GetCache(hh) path = c4d.utils.SendModelingCommand( c4d.MCOMMAND_CURRENTSTATETOOBJECT, [path], c4d.MODELINGCOMMANDMODE_ALL, c4d.BaseContainer(), doc )[0] profile = c4d.utils.SendModelingCommand( c4d.MCOMMAND_CURRENTSTATETOOBJECT, [profile], c4d.MODELINGCOMMANDMODE_ALL, c4d.BaseContainer(), doc )[0]However, I'd like to hide the child elements, but I can't figure out how I can do it more correctly
I have try use c4d.BaseObject.Touch() and my child is hide, but I can't edit my path/profile dynamically. If I edit the path/profile, I need to refresh the viewport or op settings to see the changes.
I tried this code. Perhaps I didn't fully understand something and missed something.
path = op.GetDown() if path is None: return None profile = path.GetNext() if profile is None: return None path.Touch() profile.Touch() dirty = op.CheckCache(hh)\ or op.IsDirty(c4d.DIRTY_DATA)\ or path.IsDirty(c4d.DIRTY_DATA)\ or path.IsDirty(c4d.DIRTY_MATRIX)\ or profile.IsDirty(c4d.DIRTY_DATA)\ or profile.IsDirty(c4d.DIRTY_MATRIX) if not dirty: return op.GetCache(hh)Besides this, I tried using op.GetAndCheckHierarchyClone like it was in this thread https://developers.maxon.net/forum/topic/10491/13941_hide-child-of-object-plugin/3
path = op.GetDown() if path is None: return None profile = path.GetNext() if profile is None: return None ProfileClone = op.GetAndCheckHierarchyClone(hh, profile, c4d.HIERARCHYCLONEFLAGS_ASSPLINE, False) ProfileCloneDirty = ProfileClone["dirty"] ProfileCloneClone = ProfileClone["clone"] PathClone = op.GetAndCheckHierarchyClone(hh, path, c4d.HIERARCHYCLONEFLAGS_ASSPLINE, False) PathCloneDirty = PathClone["dirty"] PathCloneClone = PathClone["clone"] if not ProfileCloneDirty: return ProfileCloneClone if not PathCloneDirty: return PathCloneClone path_upd = c4d.utils.SendModelingCommand( c4d.MCOMMAND_CURRENTSTATETOOBJECT, [PathCloneClone], c4d.MODELINGCOMMANDMODE_ALL, c4d.BaseContainer(), doc )[0] profile_upd = c4d.utils.SendModelingCommand( c4d.MCOMMAND_CURRENTSTATETOOBJECT, [ProfileCloneClone], c4d.MODELINGCOMMANDMODE_ALL, c4d.BaseContainer(), doc )[0]However, this reduces performance compared to the code above. I would be very grateful if you could help me figure out how I can do this more correctly and optimized.
P.s I think my question will seem primitive, but I'm just learning the API, so don't judge me too harshly

-
Edge ring selection
Hi folks, I am actively trying to learn Python for Cinema 4D, and lately I have been struggling with edge selection, specifically the Loop and Ring functions.
I got the code working as expected in r21, but in r25 and 2024 it no longer works, I have been trying to figure out what the problem is, but alas, I have not been able to. I would really appreciate it if you could show me what I am missingimport c4d from c4d import utils def select_ring_edge(obj, edge_id): bc = c4d.BaseContainer() bc.SetData(c4d.MDATA_RING_EDGE, edge_id) bc.SetData(c4d.MDATA_RING_SELECTION, c4d.SELECTION_NEW) result = c4d.utils.SendModelingCommand( command=c4d.ID_MODELING_RING_TOOL, list=[obj], mode=c4d.MODELINGCOMMANDMODE_EDGESELECTION, bc=bc, doc=c4d.documents.GetActiveDocument(), flags=c4d.MODELINGCOMMANDFLAGS_CREATEUNDO ) c4d.EventAdd() return result def main(): doc = c4d.documents.GetActiveDocument() obj = doc.GetActiveObject() if obj is None: c4d.gui.MessageDialog("select obj.") return edge_index = 3 result = select_ring_edge(obj, edge_index) if result: print("DONE") else: print("ERROR") if __name__ == '__main__': main()