Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Hide Input Child Objects in GetContour[SOLVED]

    Scheduled Pinned Locked Moved PYTHON Development
    5 Posts 0 Posters 551 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H Offline
      Helper
      last edited by

      On 22/11/2016 at 15:32, xxxxxxxx wrote:

      Hi,

      1. How do I hide my child input objects? I'm using Touch() in GetContour() but it only works when I'm editing the child-objects.
      2. How do I ensure that grandchildren don't reappear when nested in another generator?

      I've created a simplified example plugin demonstrating my issues:
      BitBucket Snippet of ScaleSplineObject.pyp

      And, while harder to read, here's the full source embedded:

        
      """Scale Spline Object   
      Takes a child-spline as input and scaled it's point's down by 50%. Tangents are unaffected.   
        
      v0.0.1   
        
      by Donovan Keith <[email protected]>   
        
      Usage Instructions   
      ------------------   
      1. Save in a file called ScaleSplineObject.pyp   
      2. Place in C4D Plugins director   
      3. Restart C4D   
      4. Plugins > Scale Spline Object   
      5. Add an NSide spline   
      6. Make the NSide spline a child of the Scale Spline Object.   
        
      Outstanding Issues   
      -------------------   
        
      - [ ] Nested child objects aren't properly hidden. To recreate:   
              ScaleSpline   
              |   
              -- Scale Spline   
                  |   
                  -- NSide   
      - [ ] GetDirty() probably needs to be reimplemented.   
      """   
        
      # =====================================================================================================================#   
      #   Imports   
      # =====================================================================================================================#   
        
      import c4d   
        
        
      # =====================================================================================================================#   
      #   Class Definitions   
      # =====================================================================================================================#   
        
      class ScaleSplineObject(c4d.plugins.ObjectData) :   
          PLUGIN_ID = 1038342 # TODO: Replace with your own ID from PluginCafe.com   
        
          def __init__(self) :   
              self.last_child = None   
        
          def Init(self, op) :   
              return True   
        
          def ConversionCommand(self, op, command_id) :   
              """Allows you to easily perform a MakeEditable or CSTO on an object.   
              reference: https://developers.maxon.net/forum/topic/5237/5232_python-make-object-editable   
        
              Returns early if op is a Spline   
              """   
        
              if op is None:   
                  return   
        
              op_clone = op.GetClone()   
              if op_clone is None:   
                  return   
        
              # Is it a spline? No need to convert.   
              if op_clone.CheckType(c4d.Ospline) :   
                  return op_clone   
        
              # Perform the MakeEditable or CSTO in temporary document   
              temp_doc = c4d.documents.BaseDocument()   
              if not temp_doc:   
                  return   
        
              temp_doc.InsertObject(op_clone)   
              result_list = c4d.utils.SendModelingCommand(command=command_id,   
                                                          list=[op_clone],   
                                                          doc=temp_doc)   
        
              # Did anything go wrong? Bail   
              if not result_list:   
                  return   
        
              # Return the first object in the result list   
              return result_list[0]   
        
          def MakeEditable(self, op) :   
              """Returns a clone of `op` that's been made editable. Can return None."""   
              return self.ConversionCommand(op, command_id=c4d.MCOMMAND_MAKEEDITABLE)   
        
          def CurrentStateToObject(self, op) :   
              """Returns a clone of the current state of `op`. Can return None."""   
              return self.ConversionCommand(op, command_id=c4d.MCOMMAND_CURRENTSTATETOOBJECT)   
        
          def GetAsSpline(self, op) :   
              """Clones object as a c4d.Ospline - using the following priority   
              * Object if Spline   
              * Object Made Editable, if Spline   
              * Current State to Object, if Spline   
        
              Note: MakeEditable won't account for deformed splines, however, it will give you a spline   
              with fewer points which is preferable to CSTO for a lot of modeling operations.   
              """   
        
              if op is None:   
                  return   
        
              # Return op if it's a spline   
              if op.CheckType(c4d.Ospline) :   
                  return op.GetClone()   
        
              # Make it editable if it is.   
              made_editable = self.MakeEditable(op)   
              if made_editable is not None:   
                  if made_editable.CheckType(c4d.Ospline) :   
                     return made_editable   
        
              # Peform a CSTO if need be   
              # TODO: See if this ever actually executes, probably doesn't   
              current_state = self.CurrentStateToObject(op)   
              if current_state is not None:   
                  if current_state.CheckType(c4d.Ospline) :   
                     return current_state   
        
          def LocalizeSpline(self, op, spline) :   
              """Converts all of `spline`'s point to local space for `op`   
              This is necessary because GetContour assumes the spline is in the same   
              location as the object itself.   
              """   
        
              # Verify Inputs   
              if (op is None) or (spline is None) :   
                  return   
        
              # Get points   
              spline_points = spline.GetAllPoints()   
              if not spline_points:   
                  return   
        
              has_tangents = (spline.GetTangentCount() > 0)   
              spline_tangents = []   
        
              # Retrieve matrices for conversion math   
              spline_mg = spline.GetMg()   
              if not spline_mg:   
                  return   
        
              op_mg = op.GetMg()   
              if not op_mg:   
                  return   
        
              inverse_op_mg = ~op_mg   
        
              # Localize all points   
              for i, spline_point in enumerate(spline_points) :   
                  global_point = spline_point * spline_mg   
                  local_point = global_point * inverse_op_mg   
                  spline_points[i] = local_point   
        
                  # Calculate new tangent positions   
                  if has_tangents:   
                     # Get tangents for point   
                     tangent = spline.GetTangent(i)   
                     vl = tangent["vl"]   
                     vr = tangent["vr"]   
        
                     # Transform tangents into their global locales   
                     global_vl = (spline_point + vl) * spline_mg   
                     global_vr = (spline_point + vr) * spline_mg   
        
                     # Transform tangents from global points to point-local vectors.   
                     vl = (global_vl * inverse_op_mg) - local_point   
                     vr = (global_vr * inverse_op_mg) - local_point   
        
                     # Store the updated points & tangents.   
                     spline_tangents.append((vl, vr))   
                     spline.SetTangent(i, vl, vr)   
        
              # Neutralize spline's Matrix   
              spline.SetMg(op_mg)   
        
              # Restore spline to previous positions   
              spline.SetAllPoints(spline_points)   
        
              # Update tangent positions as well   
              for i, tangent in enumerate(spline_tangents) :   
                  vl, vr = tangent   
                  spline.SetTangent(i, vl, vr)   
        
          def CheckDirty(self, op, doc) :   
              """Marks the object as dirty if it's child object has been modified."""   
        
              if not op:   
                  return   
        
              # Is there a new or missing child object?   
              child = op.GetDown()   
              if child != self.last_child:   
                  # Dirty!   
                  self.last_child = child   
                  op.SetDirty(c4d.DIRTY_DATA)   
                  return   
        
              # Can't do anythng without a child object.   
              if child is None:   
                  return   
        
              # Has the child ben modified?   
              if child.IsDirty(c4d.DIRTYFLAGS_MATRIX |   
                               c4d.DIRTYFLAGS_DATA |   
                               c4d.DIRTYFLAGS_CHILDREN) :   
                  # Dirty!   
                  op.SetDirty(c4d.DIRTYFLAGS_DATA)   
        
          def ModifySpline(self, spline) :   
              """Scales all spline points down by 50%"""   
        
              point_scaling_factor = 0.5   
        
              if spline is None:   
                  return   
        
              spline_points = spline.GetAllPoints()   
              if spline_points is None:   
                  return   
        
              for i, spline_point in enumerate(spline_points) :   
                  spline_points[i] = spline_point * point_scaling_factor   
        
              spline.SetAllPoints(spline_points)   
        
          def GetContour(self, op, doc, lod, bt) :   
              """Return the result of the generator spline."""   
        
              # Create an Empty Spline   
              if not op:   
                  return   
        
              # Retrieve the child input object   
              child = op.GetDown()   
              if child is None:   
                  return   
        
              # Tell C4D the child is a generator input object and should be hidden.   
              child.Touch()   
        
              # Get the child input object as a spline clone we can modify.   
              result_spline = self.GetAsSpline(child)   
              if result_spline is None:   
                  return   
        
              # Scale down the spline points.   
              self.ModifySpline(result_spline)   
        
              # Ensure the spline points are localized to this generator's PSR.   
              self.LocalizeSpline(op, result_spline)   
        
              return result_spline   
        
        
      # =====================================================================================================================#   
      #   Registration   
      # =====================================================================================================================#   
        
      if __name__ == "__main__":   
          c4d.plugins.RegisterObjectPlugin(id=ScaleSplineObject.PLUGIN_ID,   
                                          str="ScaleSplineObject",   
                                          g=ScaleSplineObject,   
                                          description=None,   
                                          icon=None,   
                                          info=c4d.OBJECT_GENERATOR | c4d.OBJECT_INPUT | c4d.OBJECT_ISSPLINE)   
      

      Thanks!

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 22/11/2016 at 15:37, xxxxxxxx wrote:

        These posts seem to be related:

        - Object generator, GVO, cache and child objects - Plugin Cafe Forums
        Solution doesn't work because GetContour() doesn't have access to DependenceList() nor HierarchyHelp.

        - Touching Input object which in turn has input - Plugin Cafe Forums
        I think this is the same problem I'm having, no resolution was ever posted.

        - GetContour And op->Touch() - Plugin Cafe Forums
        Seems to indicate that Touch() doesn't work properly in GetContour(), and that without access to HierarchyHelp, these will be long-standing issues.

        ---

        Any thoughts? It seems like I have to choose between:

        1. Use GetVirtualObjects so I can easily hide children, but then create a spline that is incompatible with Hair, SketchAndToon, and any other plugins that use GetRealSpline() as a test to see if something is a spline.
        2. Use GetContour() and end up with flickering sub-objects and poor object hiding.

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          On 24/11/2016 at 02:51, xxxxxxxx wrote:

          Hi Donovan, thanks for writing us.

          with reference to your question, the solution proposed here should provide the functionality desired in terms of hiding child spline in generators.

          Best, Riccardo.

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            On 28/11/2016 at 21:24, xxxxxxxx wrote:

            Hi Riccardo,

            Unfortunately, the example you've posted:

            1. Does not hide child objects.
            2. Only works with SplineObjects instead of Spline Primitives (try to add a Circle as a child for example).

            Are you sure you posted the most recent version?

            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 15/12/2016 at 13:08, xxxxxxxx wrote:

              Hi Donovan,  thanks for writing us.

              i've provided a new answer here with updated code which should hide the child objects and work with procedural primitives as well.

              Best, Riccardo

              1 Reply Last reply Reply Quote 0
              • First post
                Last post