0
$\begingroup$

I'm trying to draw text in 3d space, but it draws in wrong coordinates and not directed at the screen. As from here Text in 3D view linked to an object. It work correctly with modal, but did not with this class. How it look: enter image description here

How it needed:

enter image description here

import bpy
import blf

from mathutils import Vector
from bpy_extras.view3d_utils import location_3d_to_region_2d

def view3d_find( return_area = False ):
    for area in bpy.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':
                    if return_area: return region, rv3d, v3d, area
                    return region, rv3d, v3d
    return None, None

class DrawingClass:
    def __init__(self):
        self.handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_text, (), 'WINDOW', 'POST_VIEW')
    
    def draw_text(self):
        font_id = 0    
      
        obj = bpy.context.active_object
#        v3d = bpy.context.space_data
#        rv3d = v3d.region_3d
#        region = bpy.context.region

        region, rv3d, v3d = view3d_find()
        
        pos = location_3d_to_region_2d(region, rv3d, obj.location)
        pos_x = pos[0]
        pos_y = pos[1]   
        
        # draw function
        blf.position(font_id, pos_x, pos_y, 0)
        blf.size(font_id, 20)
        blf.draw(font_id, obj.name)

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

# to draw           
dns = bpy.app.driver_namespace
dns["dc"] = DrawingClass()

# to remove
dns = bpy.app.driver_namespace
dc = dns.get("dc")
dc.remove_handle()
$\endgroup$
7
  • $\begingroup$ The text is drawn in 3D space, not 2D. You can use pos = obj.location I think $\endgroup$
    – Gorgious
    Commented Feb 14, 2023 at 11:37
  • $\begingroup$ Hello, it did not help. It draws text near the object but did not turned to the screen $\endgroup$
    – APEC
    Commented Feb 14, 2023 at 12:13
  • 1
    $\begingroup$ blf.position(font_id, pos_x, pos_y, 0) change to blf.position(font_id, *obj.location) and blf.size(font_id, 20) change to blf.size(font_id, 20, 72). If you want display 2D, 'POST_VIEW' change to 'POST_PIXEL' $\endgroup$
    – X Y
    Commented Feb 14, 2023 at 12:22
  • $\begingroup$ X Y, did not help also. dpi 72 is deprecated now. $\endgroup$
    – APEC
    Commented Feb 14, 2023 at 12:28
  • $\begingroup$ You might want to rephrase your question a bit (to add you want to draw in 2D instead of 3D) and add a schema of how you'd like it to look like. $\endgroup$
    – Gorgious
    Commented Feb 14, 2023 at 12:29

1 Answer 1

2
$\begingroup$

Thanks to X Y, all I had to do was replace 'POST_VIEW' to 'POST_PIXEL'. Updated code:

import bpy
import blf

from bpy_extras.view3d_utils import location_3d_to_region_2d

class DrawingClass:
    def __init__(self):
        self.handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_text, (), 'WINDOW', 'POST_PIXEL')
    
    def draw_text(self):
        font_id = 0    
      
        obj = bpy.context.active_object
        v3d = bpy.context.space_data
        rv3d = v3d.region_3d
        region = bpy.context.region
        
        pos = location_3d_to_region_2d(region, rv3d, obj.location)
        pos_x = pos[0]
        pos_y = pos[1]   
        
        # draw function
        blf.position(font_id, pos_x, pos_y, 0)
        blf.size(font_id, 20)
        blf.draw(font_id, obj.name)

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

# to draw           
dns = bpy.app.driver_namespace
dns["dc"] = DrawingClass()

# to remove
dns = bpy.app.driver_namespace
dc = dns.get("dc")
dc.remove_handle()
$\endgroup$

You must log in to answer this question.

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