3
$\begingroup$

Is there a way to use display options like "object info" or "view name" (in the viewport's preferences) to display other information like for example the lenth focal of the active camera and its position. And is there a way to move this information anywhere in the 3d window ? Like in this example:

enter image description here

So I found a script that allows me to display the focal point on the 3d window.

import bpy
import blf

dns = bpy.app.driver_namespace 
dc = dns.get("dc")
dc.remove_handle()

class DrawingClass:
    def __init__(self, context, prop):
        self.prop = prop
        self.handle = bpy.types.SpaceView3D.draw_handler_add(
                   self.draw_text_callback,(context,),
                   'WINDOW', 'POST_PIXEL')

    def draw_text_callback(self, context):
        font_id = 0  # XXX, need to find out how best to get this.

        # draw some text
        blf.position(font_id, 15, 350, 0)
        blf.size(font_id, 20, 72)
        blf.draw(font_id, "%s %s" % (context.scene.name, self.prop))

    def remove_handle(self):
         bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')

context = bpy.context             
dns = bpy.app.driver_namespace
dns["dc"] = DrawingClass(context, bpy.context.object.data.lens)

enter image description here

The first 3 line allows me to erase the preceding display. How can I prevent the scipte from reading the first 3 lines the first time the script is run? For now the script reads the focal once and writes it. How to make sure that the script is read every time the focal is changed?

$\endgroup$
2
  • 1
    $\begingroup$ For rendering or just to display the properties in the camera frame? $\endgroup$
    – brockmann
    Aug 17, 2020 at 14:08
  • $\begingroup$ Juste to diplay the properties in the camera frame $\endgroup$ Aug 17, 2020 at 14:21

1 Answer 1

3
$\begingroup$

AFAIK that's not possible by default and I guess there is no existing add-on which is able to display any kind of information in the camera frame.

However, you can draw the text using python's bgl module and create your own add-on. Following example code is based on our famous Operator Modal Draw template that comes with blender, extended by the answers from Coordinates of corners of camera view border and Multi-line Text in blf (with multi colour option) to get the ball rolling:

enter image description here

hud.py

import bpy
import blf
import bgl


# -> BASED ON: https://blender.stackexchange.com/a/14746/31447
def view3d_find(context):
    # returns first 3d view, normally we get from context
    for area in context.window.screen.areas:
        if area.type == 'VIEW_3D':
            v3d = area.spaces[0]
            rv3d = v3d.region_3d
            for region in area.regions:
                if region.type == 'WINDOW':
                    return region, rv3d
    return None, None

def view3d_camera_border(context):
    obj = context.scene.camera
    cam = obj.data

    frame = cam.view_frame(scene=context.scene)
    # move from object-space into world-space 
    frame = [obj.matrix_world @ v for v in frame]

    # move into pixelspace
    from bpy_extras.view3d_utils import location_3d_to_region_2d
    region, rv3d = view3d_find(context)
    frame_px = [location_3d_to_region_2d(region, rv3d, v) for v in frame]
    return frame_px

# -> BASED ON: https://blender.stackexchange.com/a/31799/31447
def draw_string(x, y, packed_strings):
    font_id = 0
    blf.size(font_id, 18, 72) 
    x_offset = 0
    y_offset = 0
    line_height = (blf.dimensions(font_id, "M")[1] * 1.45)
    for command in packed_strings:
        if len(command) == 2:
            pstr, pcol = command
            blf.color(font_id, pcol[0], pcol[1], pcol[2], pcol[3]) # #bgl.glColor4f(pcol)
            text_width, text_height = blf.dimensions(font_id, pstr)
            blf.position(font_id, (x + x_offset), (y + y_offset), 0)
            blf.draw(font_id, pstr)
            x_offset += text_width
        else:
            x_offset = 0
            y_offset -= line_height

def draw_callback_px(self, context):
    
    WHITE = (1, 1, 1, .7)
    CR = "Carriage Return"
    
    x, y = view3d_camera_border(context)[3]
    cam_ob = context.scene.camera
    
    if cam_ob is not None:
        ps = [
            ("{} {}mm".format(cam_ob.name, cam_ob.data.lens), WHITE), 
            CR,
            CR, 
            ("T: {:.2f}, {:.2f}, {:.2f}".format(
                cam_ob.location.x, 
                cam_ob.location.y, 
                cam_ob.location.z), WHITE),
            CR,
            ("R: {:.2f}, {:.2f}, {:.2f}".format(
                cam_ob.rotation_euler.x, 
                cam_ob.rotation_euler.y, 
                cam_ob.rotation_euler.z), WHITE),        
        ]
    
    draw_string(x+10, y-20, ps)
    # restore opengl defaults
    bgl.glLineWidth(1)
    bgl.glDisable(bgl.GL_BLEND)

# -> MODAL OPERATOR TEMPLATE
class ModalDrawOperator(bpy.types.Operator):
    """Draw a line with the mouse"""
    bl_idname = "view3d.modal_operator"
    bl_label = "Simple Modal View3D Operator"

    @classmethod
    def poll(cls, context):
        return context.area.type == 'VIEW_3D'
    
    def modal(self, context, event):
        context.area.tag_redraw()
        
        if event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}
        
        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        if context.space_data.region_3d.view_perspective == 'CAMERA':
            # the arguments we pass the the callback
            args = (self, context)
            # Add the region OpenGL drawing callback
            # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
            self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')

            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "Switch into Camera View")
            return {'CANCELLED'}



def register():
    bpy.utils.register_class(ModalDrawOperator)


def unregister():
    bpy.utils.unregister_class(ModalDrawOperator)


if __name__ == "__main__":
    register()

Copy and paste the script into the text editor, run it, move over to the in 3d View, press F3 and type "Simple Operator..." to execute. If you'd like to convert it into an Add-on, just add a python dictionary named "bl_info" at the top of your addon: https://wiki.blender.org/wiki/Process/Addons/Guidelines/metainfo


In order to make it work for 2.7x versions you would have to replace 2 lines due to changes in Matrix Multiplication and on how to set the text color using blf.color in newer versions:

# draw_string()
- blf.color(font_id, pcol[0], pcol[1], pcol[2], pcol[3]) # Blender 2.8x
+ bgl.glColor4f(*pcol) # Blender 2.7x

# view3d_camera_border()
- frame = [obj.matrix_world @ v for v in frame] # Blender 2.8x
+ frame = [obj.matrix_world * v for v in frame] # Blender 2.7x
$\endgroup$
7
  • $\begingroup$ It's awesome ! Thank you so much Any idea why its not working in 2.79 ? $\endgroup$ Aug 20, 2020 at 10:48
  • $\begingroup$ Sure, due to the viewport changes as of Blender 2.8x (eevee) there have been some changes to bgl as well: wiki.blender.org/wiki/Reference/Release_Notes/2.80/Python_API @LoickNizon Do you need it for 2.7x? If so, why the 2.8x screenshot in your question? How this site works: blender.stackexchange.com/tour $\endgroup$
    – brockmann
    Aug 20, 2020 at 10:53
  • $\begingroup$ Thank you for your answer. currently I would like to use this script for my personal project where I use 2.8 and for my boarder team which uses 2.79 $\endgroup$ Aug 20, 2020 at 11:36
  • $\begingroup$ If there is any good reason...? I can make it work for 2.79 but I don't have it around anymore, have to download and install it and such... @LoickNizon $\endgroup$
    – brockmann
    Aug 20, 2020 at 11:40
  • 2
    $\begingroup$ thank you so much ! you make my day! $\endgroup$ Aug 20, 2020 at 15:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .