Clicking "set" button of constraint tag from pyGen



  • On 13/04/2016 at 10:19, xxxxxxxx wrote:

    Hello, hello.

    I'm trying to attach generated splines to objects within my generator. I'm able to attach constraint and spline dynamics tags to my generated spline within the python generator, but the one step that I'm worried about is selecting a point on my spline and [clicking, setting True] the "set" button of the spline's constraint tag. I think what i'm looking for is something like

    tag[[c4d.HAIR_CONSTRAINTS_TAG_SET] = True

    but am unable to drag the buttons into the script editor like other parameters. Can anyone give me some pointers?

    I can do this manually, but for procedural reasons would prefer it to be done within the generator.

    PS.
    How can I select a point on a spline? Can't find it in the API at the moment but once I get this then I can start hacking away.

    Thanks in advance for any help.



  • On 14/04/2016 at 09:02, xxxxxxxx wrote:

    Hi,

    last things first. Selecting points on a spline (which is basically a PointObject) is just a matter of a point selection. Use GetPointS() to get the BaseSelect and you should be good to go.

    In order to find out button IDs you have several options. One would be to scan the resource files in <C4D program directory>/resource/modules. Another is to consult the C++ SDK documentation.
    So in your case it is HAIR_CONSTRAINTS_TAG_SET_ANCHOR.

    But you can't simply assign true to that ID to push the button. Instead you need to use CallButton(), like so:

    c4d.CallButton(hairConstraintTag, c4d.HAIR_CONSTRAINTS_TAG_SET_ANCHOR)
    


  • On 14/04/2016 at 09:35, xxxxxxxx wrote:

    Andreas, thank you yet again!

    CallButton and pulling stuff from the C++ SDK, this is a huge help. Thanks for adding that - very much appreciated :)



  • On 15/04/2016 at 07:56, xxxxxxxx wrote:

    Hey again,

    I'm having some difficulty with this. It seems like the GetPointS() solution above just return the points that are selected in my scene..? I'm trying to actually select the individual spline points from my generator to set constraints of all splines in my scene at once.

    I found this bit in the python api about selecting edges that uses SetSelectedEdges(). Since there's no SetSelectedPoints() function, am I donezo?

    def main() :
        nbr = utils.Neighbor()
        nbr.Init(op) # Initialize neighbor with a polygon object
    
        edges = c4d.BaseSelect()
        edges.SelectAll(nbr.GetEdgeCount()) # Select all edges in the range [0, nbr.GetEdgeCount()]
    
        op.SetSelectedEdges(nbr, edges, c4d.EDGESELECTIONTYPE_SELECTION) # Select edges from our edges selection
        c4d.EventAdd() # Update Cinema 4D
    


  • On 15/04/2016 at 11:58, xxxxxxxx wrote:

    Hi Tanzola,

    can you show me some of your GetPointS() code. I can't believe, it's returning all points selected in a scene.
    Also do not forget, that code in the Python Generator is like code in GetVirtualObjects(). So you will have to make sure you are not modifying the scene in any way.
    If unsure, rather post more code than less ;)



  • On 15/04/2016 at 12:21, xxxxxxxx wrote:

    I'd trust your instincts on this one, as I have no idea what I'm doing! This is what I was doing when I assumed points already selected were being returned - you could put it into an empty scene with a generator:

    import c4d
    def main() :
        
        try: doc.SearchObject("Spline").Remove()
        except: pass
        
        spline = c4d.SplineObject(2, c4d.SPLINETYPE_LINEAR)
        pts = [c4d.Vector(), c4d.Vector(0, 200, 0)]
        spline.SetAllPoints(pts)
        
        doc.InsertObject(spline)
        c4d.EventAdd()
        
        bs = doc.SearchObject("Spline").GetPointS()
        print bs.GetAll(2)
    

    I just get a list of [0, 0] in the console so I assumed it was saying [pt 0 is not selected, pt 1 is not selected].

    Were you saying that there is in fact a way to select pts from the generator?

    Also... I modify objects in my scene all the time! Point / object positions mostly. You're saying this is a no-no? As you can tell, I'm a big noob.

    Thanks for the help 🙂



  • On 15/04/2016 at 12:57, xxxxxxxx wrote:

    Yeah, that's what GetAll() on a base select is, a list of 0 if not selected and 1 if it is.

    Andreas, I think Tanz is looking for a way to *select*, like one would with the live selection tool, points so as to automate attaching them to other points via the Set button on a (presumably Hair) Constraint.



  • On 15/04/2016 at 14:10, xxxxxxxx wrote:

    That's exactly right - and with hair constraints, yes. Sorry if I was unclear.



  • On 18/04/2016 at 11:33, xxxxxxxx wrote:

    Hi Tanzola,

    I just want to double check, we are talking about the Python Generator here, right?

    The following explanations apply, if the answer is yes.

    In general the Python Generator is very much like an ObjectData plugin with the Python script running in GetVirtualObjects(). So, as mentioned before in this thread, all the constraints that apply to GVO are also true for the Python Generator. Most important, you are not allowed to do any changes to the scene. Instead you are generating an object (this may also be an object hierarchy), optionally based on (user data) parameters of your Python Generator, and this object will be returned in the end of your Python script. Cinema will take care of the insertion into the scene, so you neither have to, nor should you do this on your own (remember, no changes to the scene).

    Let's quickly walk through your code:

        try: doc.SearchObject("Spline").Remove()
        except: pass
    

    You are not allowed to do this, nor is there a need to do so. Cinema takes care of this, actually you are rebuilding the same object in your Python Generator script.

        spline = c4d.SplineObject(2, c4d.SPLINETYPE_LINEAR)
        pts = [c4d.Vector(), c4d.Vector(0, 200, 0)]
        spline.SetAllPoints(pts)
    

    Almost all fine and dandy, in the end you will return this spline.
    Be aware of the note on SetAllPoints() it needs to be followed by a MSG_UPDATE, like so:

        spline.Message(c4d.MSG_UPDATE)
    
        doc.InsertObject(spline)
        c4d.EventAdd()
    

    Again, you are not allowed to do this. Neither the object insertion, nor the EventAdd(). And you don't need it, either, as Cinema will take care of inserting your spline into the scene, when you are returning it at the end of your script.

        bs = doc.SearchObject("Spline").GetPointS()
        print bs.GetAll(2)
    

    No need to search for the spline, you just created it, so simply use it. You want to select a point, do it like this:

        bs = spline.GetPointS()
        bc.Select(1) # to select the second point in your spline
    

    And then in the end:

        return spline
    

    So your script should actually look like this:

    import c4d
      
    def main() :
        spline = c4d.SplineObject(3, c4d.SPLINETYPE_LINEAR)
        pts = [c4d.Vector(), c4d.Vector(0, 200, 0), c4d.Vector(200, 200, 0)]
        spline.SetAllPoints(pts)
        spline.Message(c4d.MSG_UPDATE)
        
        bs = spline.GetPointS()
        bs.Select(1) # select the second point
      
        return spline
    

    As said in the beginning, you can also generate object hierarchies and you can also add tags to the generated objects.

    I hope this helps a bit.



  • On 18/04/2016 at 11:37, xxxxxxxx wrote:

    Now, that I'm thinking about it (sorry, I should have come up with this earlier), I'm not really sure, it will work to press the "Set Anchor" button from within a Python Generator. You might run into a limitation there, as user interaction is also one of the things, that usually aren't happening in GVO.



  • On 18/04/2016 at 11:45, xxxxxxxx wrote:

    Thanks, Andreas.

    I figured that some things would need to be added to the doc because I'm using spline dynamics. I never thought about spline dynamics working with python generated splines each frame... I've run into some dead object errors in the past when I tried carrying objects over into the next frame via global lists, but nevertheless I'll have to give this a shot. Everything I've come here to ask about has just been answered, it seems, so I'll give this a go shortly and post about how it goes. Many thanks for the help and additional tips!


Log in to reply