Cursor gismow extension (gpu): how to keep a constant size with depth

well finally I have this. you can resize the gizmo pressing right mouse and going up or down
gizmo cursor

import bpy
import bgl
import gpu
from gpu_extras.batch import batch_for_shader
from bpy_extras import view3d_utils

vertex_shader = '''
uniform mat4 ModelViewProjectionMatrix;
in vec3 pos;
in vec4 color;
out vec4 finalColor;
void main()
{
    gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
    gl_Position.z -= 0.001;
    finalColor = color;
}
'''

fragment_shader = """
in vec4 finalColor;
in vec4 fragCoord;
out vec4 fragColor;
out float fragDepth;
void main()
{
    vec2 coord = gl_PointCoord - vec2(0.5, 0.5);
    fragColor = finalColor;
    fragDepth = 0;
}   
"""

def draw_callback_3d(self,context):
    curs = bpy.context.scene.cursor
    loc = curs.location
    
    def to2D(loc):
        region = context.region
        rv3d = context.region_data
        return view3d_utils.location_3d_to_region_2d(region, rv3d, loc) 
    
    offset = self.offset    
    coords = [loc, (loc[0]+offset, loc[1], loc[2]),
                loc, (loc[0], loc[1]+offset, loc[2]),  
                loc, (loc[0], loc[1], loc[2]+offset)] 

    colors = ((0.8, 0, 0, 0.9), (0.8, 0, 0, 0.9),    
            (0, 0.8, 0, 0.9), (0, 0.8, 0, 0.9),    
            (0, 0, 0.8, 0.9), (0, 0, 0.8, 0.9), )   
    shader = gpu.types.GPUShader(vertex_shader, fragment_shader) #simpler way?
    batch = batch_for_shader(shader, 'LINES', {"pos": coords, "color": colors})
    bgl.glEnable(bgl.GL_BLEND)           
    bgl.glEnable(bgl.GL_LINE_SMOOTH)
    bgl.glDisable(bgl.GL_DEPTH_TEST) #on top  
    bgl.glLineWidth(3)
    shader.bind()
    batch.draw(shader)    
    # restore opengl defaults
    bgl.glLineWidth(1)
    bgl.glDisable(bgl.GL_BLEND) 

class OT_draw_operator(bpy.types.Operator):
    bl_idname = "object.draw_op"
    bl_label = "Draw operator"

    def invoke(self, context, event):
        self.right_press = None
        self.right_release = None
        self.pos = None
        self.offset = 1
        self.up = None
        self.down = None
        args = (self, context)
        self.draw_handle_3d = bpy.types.SpaceView3D.draw_handler_add(draw_callback_3d, args, 'WINDOW', 'POST_VIEW')
        context.area.tag_redraw()
        context.window_manager.modal_handler_add(self)

        return {"RUNNING_MODAL"}
            
    def modal(self, context, event):
                           
        if event.type in {"ESC"} and event.value == "PRESS":
            bpy.types.SpaceView3D.draw_handler_remove(self.draw_handle_3d, 'WINDOW')
            context.area.tag_redraw()
            return {'FINISHED'}            

        if event.type == 'RIGHTMOUSE':
            self.right_press = event.value == 'PRESS'
            self.right_release = event.value == 'RELEASE'            
            self.pos = (event.mouse_region_x, event.mouse_region_y)

        if self.right_press and event.type == 'MOUSEMOVE': #WHEELUPMOUSE
            if event.mouse_region_y > self.pos[1]+5:
                self.up = True
                self.down = False
            elif event.mouse_region_y < self.pos[1]-5:
                self.down = True
                self.up = False
            else:
                self.down = False
                self.up = False  
                              
        if (self.up or self.down) and self.right_press and not self.right_release:
            if self.up:
                self.offset += 0.15
                context.area.tag_redraw()
                self.pos  = (event.mouse_region_x, event.mouse_region_y)
            elif self.down:
                if self.offset > 0.16:
                    self.offset -= 0.15 
                context.area.tag_redraw()
                self.pos  = (event.mouse_region_x, event.mouse_region_y)                                        
                   
        return {"RUNNING_MODAL"}
        
def register():
    bpy.utils.register_class(OT_draw_operator)

if __name__ == "__main__":
    register()
2 Likes