BaseDraw – DrawLine2D – Transparency?



  • Hellow,

    I'm currently seeking for a neat way to add an overlay to my camera that will show me a SplitScreen version of my 16:9 camera-layout... and in the end also an option for a 1:1 version.

    Cinema_4D_2020-11-05_14-19-29.png

    My current code looks like the following:

    import c4d
    
    def draw(bd):
        # Various exit conditions.
        if (not isinstance(bd, c4d.BaseDraw) or
            bd.GetDrawPass() != c4d.DRAWPASS_OBJECT):
            return False
    
        #works only on active Camera
        obj = op.GetMain()
        scene_cam = bd.GetSceneCamera(doc)
        if obj != scene_cam:
            return False
    
        res = bd.GetFrame()
        x, y = res['cr'], res['cb']
        # print(x, y)
    
        bd.SetPen(c4d.Vector(1,0,0))
    
        for i in range(x/2):
            p1 = c4d.Vector(i,0,0)
            p2 = c4d.Vector(i,y,0)
            bd.DrawLine2D(p1, p2)
    
    def main():
        pass
    

    Here's my scene-file: bddraw_safe-frame.c4d

    However, my questions are:

    1. Is it possible to add transparency to my current Pen, or do I have to use another method for approaching this? BaseDraw.DrawTexture for example?
    2. Is it possible to draw ABOVE the Safe Frames that can be activated via the Viewport HUD Menu?

    Thanks,
    Lasse



  • Hi @lasselauch,

    regarding your first question, you can set the transparency of the following drawing operations with BaseDraw.SetTransparency. So you could just add bd.SetTransparency(-125) to your script for example to draw everything with an alpha of 50%.
    For your second question about drawing on top of the safe frame indicators (I assume that was what you meant with drawing "above" them), there is no direct answer, since there is no draw pass which lets you draw on such a high level. But you can of course just turn of the built in safe frame indicators and draw your own. Below you will find a script and a scene file which deal with both your questions and go a bit more into the details. If possible, you should use the file, since the script does rely on some user data.

    Cheers,
    Ferdinand

    draw_camera_info.c4d

    """ Explores the overlay and safe frame questions as discussed in
        https://plugincafe.maxon.net/topic/12990/
    
        Draws a semi-transparent overlay with BaseDraw.DrawPolygon() and optionally replaces the indicator bars for the safe frame area.
    """
    
    import c4d
    
    
    def draw(bd):
        """Draws restriction indicators into a viewport.
        """
        # Get out when we are not in the object draw pass or when this tag is not
        # sitting on the currently active camera in the document. You could also
        # draw in other draw passes, depending on what you want to do with this
        # script.
        node = op.GetObject()
        if (not isinstance(bd, c4d.BaseDraw) or
            bd.GetDrawPass() != c4d.DRAWPASS_OBJECT or
                node != bd.GetSceneCamera(doc)):
            return
    
        # Set the drawing coordinate system to screen space.
        bd.SetMatrix_Screen()
        # The frame and safe-frame of the viewport.
        frame, safe_frame = bd.GetFrame(), bd.GetSafeFrame()
    
        # Variable for up to where the overlay should reach.
        ratio = .5
        # Set the transparency for the following drawing operations. See docs
        # for details on BaseDraw.SetTransparency().
        transparency = int(op[c4d.ID_USERDATA, 1] * 255)
        bd.SetTransparency(-transparency)
    
        # Draws the main overlay. We could also use lines like you did, but
        # just drawing a single polygon seems to be much more straight forward.
        points = [c4d.Vector(frame["cl"], frame["ct"], 0),
                  c4d.Vector(frame["cr"] * ratio, frame["ct"], 0),
                  c4d.Vector(frame["cr"] * ratio, frame["cb"], 0),
                  c4d.Vector(frame["cl"], frame["cb"], 0)]
        colors = [op[c4d.ID_USERDATA, 2]] * 4
        bd.DrawPolygon(points, colors)
    
        # We cannot draw on top of Cinema's safe frame indicators, but we can
        # turn them off and draw our own. This comes with the disadvantage that
        # the tag might leave a viewport with disabled safe frame overlays when
        # the tag is deleted or moved.
        # Which could be mitigated using messages, but should be done in a full
        # blown TagData plugin or otherwise we would have to jump through quite
        # a few hoops here.
    
        # User says we should use Cinema's default safe frame indicators.
        if op[c4d.ID_USERDATA, 3] == False:
            bd[c4d.BASEDRAW_DATA_SHOWSAFEFRAME] = True
        # User says we should use the custom safe frame indicators.
        elif op[c4d.ID_USERDATA, 3] == True:
            bd[c4d.BASEDRAW_DATA_SHOWSAFEFRAME] = False
            # Based on the transparency of the default safe frame indicator of
            # the viewport.
            transparency = bd[c4d.BASEDRAW_DATA_TINTBORDER_OPACITY] * 255
            # Otherwise the colors won't quite match up.
            transparency = min(int(transparency * 1.5), 255)
            bd.SetTransparency(-transparency)
    
            # First we have to figure out on which axis the viewport frame
            # differs from the render frame (a.k.a "safe frame"). The testing
            # could of course also be done on the vertical axis.
            frame_height = frame["cb"] - frame["ct"]
            safe_frame_height = safe_frame["cb"] - safe_frame["ct"]
            is_horizontal = frame_height > safe_frame_height
    
            # Since we draw with transparencies, we cannot just draw our overlay
            # area on top of the custom safe frame indicators, but have instead
            # to draw the safe frame indicators only there where we want them to
            # appear. E.g. in the horizontal case, we just draw "half a bar"
            # from the mid point.
    
            # We have to draw indicators on the top and bottom.
            if is_horizontal:
                mid_point = (frame["cr"] - frame["cl"]) * ratio
                top_bar = [c4d.Vector(mid_point, frame["ct"], 0),
                           c4d.Vector(frame["cr"], frame["ct"], 0),
                           c4d.Vector(frame["cr"], safe_frame["ct"], 0),
                           c4d.Vector(mid_point, safe_frame["ct"], 0)]
                bottom_bar = [c4d.Vector(mid_point, frame["cb"], 0),
                              c4d.Vector(frame["cr"], frame["cb"], 0),
                              c4d.Vector(frame["cr"], safe_frame["cb"], 0),
                              c4d.Vector(mid_point, safe_frame["cb"], 0)]
                polygons = [top_bar, bottom_bar]
            # We have to draw one indicator on the right (left one is covered).
            else:
                right_bar = [c4d.Vector(safe_frame["cr"], frame["ct"], 0),
                             c4d.Vector(frame["cr"], frame["ct"], 0),
                             c4d.Vector(frame["cr"], frame["cb"], 0),
                             c4d.Vector(safe_frame["cr"], frame["cb"], 0)]
                polygons = [right_bar]
    
            # Based on the color of the default safe frame indicator of
            # the viewport.
            colors = [bd[c4d.BASEDRAW_DATA_TINTBORDER_COLOR]] * 4
            for p in polygons:
                bd.DrawPolygon(p, colors)
    
    def main():
        pass
    


  • Hi @lasselauch,

    thanks for reaching out to us. We have seen and discussed your problem and I will tackle it on Monday. Have a nice weekend.

    Cheers,
    Ferdinand



  • Thanks for the reply, @zipit. Looking forward to it...

    In the meantime I created another little preset when working with takes, where I have the same problem when drawing ABOVE safe frames.

    https://github.com/lasselauch/c4d-presets#take-hud-helperc4d

    Thanks for looking into this.

    Cheers,
    Lasse



  • Hi @lasselauch,

    regarding your first question, you can set the transparency of the following drawing operations with BaseDraw.SetTransparency. So you could just add bd.SetTransparency(-125) to your script for example to draw everything with an alpha of 50%.
    For your second question about drawing on top of the safe frame indicators (I assume that was what you meant with drawing "above" them), there is no direct answer, since there is no draw pass which lets you draw on such a high level. But you can of course just turn of the built in safe frame indicators and draw your own. Below you will find a script and a scene file which deal with both your questions and go a bit more into the details. If possible, you should use the file, since the script does rely on some user data.

    Cheers,
    Ferdinand

    draw_camera_info.c4d

    """ Explores the overlay and safe frame questions as discussed in
        https://plugincafe.maxon.net/topic/12990/
    
        Draws a semi-transparent overlay with BaseDraw.DrawPolygon() and optionally replaces the indicator bars for the safe frame area.
    """
    
    import c4d
    
    
    def draw(bd):
        """Draws restriction indicators into a viewport.
        """
        # Get out when we are not in the object draw pass or when this tag is not
        # sitting on the currently active camera in the document. You could also
        # draw in other draw passes, depending on what you want to do with this
        # script.
        node = op.GetObject()
        if (not isinstance(bd, c4d.BaseDraw) or
            bd.GetDrawPass() != c4d.DRAWPASS_OBJECT or
                node != bd.GetSceneCamera(doc)):
            return
    
        # Set the drawing coordinate system to screen space.
        bd.SetMatrix_Screen()
        # The frame and safe-frame of the viewport.
        frame, safe_frame = bd.GetFrame(), bd.GetSafeFrame()
    
        # Variable for up to where the overlay should reach.
        ratio = .5
        # Set the transparency for the following drawing operations. See docs
        # for details on BaseDraw.SetTransparency().
        transparency = int(op[c4d.ID_USERDATA, 1] * 255)
        bd.SetTransparency(-transparency)
    
        # Draws the main overlay. We could also use lines like you did, but
        # just drawing a single polygon seems to be much more straight forward.
        points = [c4d.Vector(frame["cl"], frame["ct"], 0),
                  c4d.Vector(frame["cr"] * ratio, frame["ct"], 0),
                  c4d.Vector(frame["cr"] * ratio, frame["cb"], 0),
                  c4d.Vector(frame["cl"], frame["cb"], 0)]
        colors = [op[c4d.ID_USERDATA, 2]] * 4
        bd.DrawPolygon(points, colors)
    
        # We cannot draw on top of Cinema's safe frame indicators, but we can
        # turn them off and draw our own. This comes with the disadvantage that
        # the tag might leave a viewport with disabled safe frame overlays when
        # the tag is deleted or moved.
        # Which could be mitigated using messages, but should be done in a full
        # blown TagData plugin or otherwise we would have to jump through quite
        # a few hoops here.
    
        # User says we should use Cinema's default safe frame indicators.
        if op[c4d.ID_USERDATA, 3] == False:
            bd[c4d.BASEDRAW_DATA_SHOWSAFEFRAME] = True
        # User says we should use the custom safe frame indicators.
        elif op[c4d.ID_USERDATA, 3] == True:
            bd[c4d.BASEDRAW_DATA_SHOWSAFEFRAME] = False
            # Based on the transparency of the default safe frame indicator of
            # the viewport.
            transparency = bd[c4d.BASEDRAW_DATA_TINTBORDER_OPACITY] * 255
            # Otherwise the colors won't quite match up.
            transparency = min(int(transparency * 1.5), 255)
            bd.SetTransparency(-transparency)
    
            # First we have to figure out on which axis the viewport frame
            # differs from the render frame (a.k.a "safe frame"). The testing
            # could of course also be done on the vertical axis.
            frame_height = frame["cb"] - frame["ct"]
            safe_frame_height = safe_frame["cb"] - safe_frame["ct"]
            is_horizontal = frame_height > safe_frame_height
    
            # Since we draw with transparencies, we cannot just draw our overlay
            # area on top of the custom safe frame indicators, but have instead
            # to draw the safe frame indicators only there where we want them to
            # appear. E.g. in the horizontal case, we just draw "half a bar"
            # from the mid point.
    
            # We have to draw indicators on the top and bottom.
            if is_horizontal:
                mid_point = (frame["cr"] - frame["cl"]) * ratio
                top_bar = [c4d.Vector(mid_point, frame["ct"], 0),
                           c4d.Vector(frame["cr"], frame["ct"], 0),
                           c4d.Vector(frame["cr"], safe_frame["ct"], 0),
                           c4d.Vector(mid_point, safe_frame["ct"], 0)]
                bottom_bar = [c4d.Vector(mid_point, frame["cb"], 0),
                              c4d.Vector(frame["cr"], frame["cb"], 0),
                              c4d.Vector(frame["cr"], safe_frame["cb"], 0),
                              c4d.Vector(mid_point, safe_frame["cb"], 0)]
                polygons = [top_bar, bottom_bar]
            # We have to draw one indicator on the right (left one is covered).
            else:
                right_bar = [c4d.Vector(safe_frame["cr"], frame["ct"], 0),
                             c4d.Vector(frame["cr"], frame["ct"], 0),
                             c4d.Vector(frame["cr"], frame["cb"], 0),
                             c4d.Vector(safe_frame["cr"], frame["cb"], 0)]
                polygons = [right_bar]
    
            # Based on the color of the default safe frame indicator of
            # the viewport.
            colors = [bd[c4d.BASEDRAW_DATA_TINTBORDER_COLOR]] * 4
            for p in polygons:
                bd.DrawPolygon(p, colors)
    
    def main():
        pass
    


  • Hi,

    without further feedback, we will consider this thread as solved by tomorrow and flag it accordingly.

    Cheers,
    Ferdinand