Automatically adapting SoftSelection Radius



  • On 07/02/2013 at 03:38, xxxxxxxx wrote:

    Hi everyone, first post in this forum. I'm a long time programmer (C++, C#) but relatively new to Python in Cinema 4D and I'm trying to create a simple script that automatically enables soft selection for move, scale and rotate tools and sets the radius to the radius of the current selection. My question is (sorry if it's obviuos) : what modeling command should I call in the SendModelingCommand instruction to access Move, Rotate and Scale tools since I can't find them in the list of available commands?
    Thanks in advance,
    Michele



  • On 07/02/2013 at 05:10, xxxxxxxx wrote:

    the ids are ID_MODELING_MOVE, ...SCALE and ...ROTATE. but they are not modelling commands,
    but tools, so you should send them either with c4d.CallCommand or BaseDocument.SetActive .



  • On 07/02/2013 at 06:17, xxxxxxxx wrote:

    Thanks a lot for the answer. So how can I set parameters like Soft Selection Radius if I can't send the values in the c4d.BaseContainer like with any other modeling command?
    Thanks for your time and help!

    Michele



  • On 07/02/2013 at 06:18, xxxxxxxx wrote:

    You can't. You can try to use the SMC, but I don't know if it will work. It is however very easy to do the
    soft-offsetting manually. This would also give you more control.

    Edit: Oh wait, I think there was a method for getting the current tools
    container. Search for GetTool or something similar. I don't have the docs
    on m smartphone..



  • On 07/02/2013 at 07:32, xxxxxxxx wrote:

    soft selections are not part of the move,rotate and scale tools, they are a separate plugin.

        bp = c4d.plugins.FindPlugin(c4d.ID_MODELING_SOFTSELECTION)
        bp[c4d.MDATA_SOFT_ENABLE] = not bp[c4d.MDATA_SOFT_ENABLE]
      
        c4d.EventAdd()
    


  • On 07/02/2013 at 08:52, xxxxxxxx wrote:

    Thanks a lot ferdinand and NiklasR!



  • On 07/02/2013 at 09:39, xxxxxxxx wrote:

    Hi larsen,

    the following code has exactly the same effect as the soft-selection moving the points when using
    it with radius = 100, falloff = linear and offsetting the points about (0, 0, 100).

    Note that I used the c4dtools module for computing the midpoint. You can find the source-code
    for this function here: https://github.com/NiklasRo...

    import c4d
    import c4dtools
    import itertools
    import collections
      
    def soft_move(op, sel, offset, falloff, radius) :
        r"""
        Move the points in the selection *sel* of *op* about the *offset*
        with the falloff described by the callable object *falloff*.
        @param op c4d.PointObject instance
        @param sel c4d.BaseSelect instance
        @param offset c4d.Vector instance
        @param falloff Callable object accepting a floating-point value as
        sole argument (between 0 and 1, including) and returning a
        floating-point argument as multiplier.
        @param radius The radius for the soft selection.
        """
      
        if not isinstance(op, c4d.PointObject) :
            raise TypeError('expected c4d.PointObject for parameter `op`')
        if not isinstance(sel, c4d.BaseSelect) :
            raise TypeError('expected c4d.BaseSelect for parameter `sel`')
        if not isinstance(offset, c4d.Vector) :
            raise TypeError('expected c4d.Vector for parameter `offset`')
        if not isinstance(falloff, collections.Callable) :
            raise TypeError('expected callable object for parameter `falloff`')
      
        points = op.GetAllPoints()
        point_count = op.GetPointCount()
        sel_count = sel.GetCount()
      
        if point_count <= 0 or sel_count <= 0:
            return
      
        # Compute the mid-point of the selected points.
        midp = []
        for i, p in itertools.izip(xrange(point_count), points) :
            if sel.IsSelected(i) :
                midp.append(p)
        midp = c4dtools.utils.vbbmid(midp)
      
        # Offset all points.
        for i, p in itertools.izip(xrange(point_count), points) :
            distance = (midp - p).GetLength()
            if distance > radius:
                continue
      
            x = falloff(distance / radius)
            p = p + offset * x
            op.SetPoint(i, p)
      
    def main() :
        if not op or not op.CheckType(c4d.Opoint) :
            return
      
        offset = c4d.Vector(0, 0, 100)
        falloff = lambda x: (1-x)
        radius = 100
        doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
        soft_move(op, op.GetPointS(), offset, falloff, radius)
        op.Message(c4d.MSG_UPDATE)
        c4d.EventAdd()
      
    if __name__ == "__main__":
        main()
    

    Best,
    Niklas



  • On 07/02/2013 at 10:33, xxxxxxxx wrote:

    Niklas, thank you very much for taking the time to help me! Also your c4dtools module is great!
    THANKS!

    Kind regards,

    Michele


Log in to reply