Get 3D position cursor

Hi!
How I can get 3D position cursor?

Welcome to BA :slight_smile:
Use bpy.context.scene.cursor_location

It’s not work, it’s all return <Vector (0.0000, 0.0000, 0.0000)>

Try bpy.data.scenes[“Scene”].cursor.location - works for me

It’s too return <Vector (0.0000, 0.0000, 0.0000)>
It’s my code

class ModalOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"


    def modal(self, context, event):
        if event.type == 'MOUSEMOVE':                    
            
            print(bpy.data.scenes["Scene"].cursor.location )

        elif event.type == 'LEFTMOUSE':
            scene = context.scene
            region = context.region
            rv3d = context.region_data
            
            coord = (event.mouse_region_x, event.mouse_region_y)
            depthLocation = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
            self.ViewVector = depthLocation
            loc = view3d_utils.region_2d_to_location_3d(region, rv3d, coord, depthLocation)
            
       return {'FINISHED'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}
        


def menu_func(self, context): # for ModalOperator
    self.layout.operator(ModalOperator.bl_idname, text=ModalOperator.bl_label)


def register():
    bpy.utils.register_class(ModalOperator)
    bpy.types.VIEW3D_MT_object.append(menu_func)


def unregister():
    bpy.utils.unregister_class(ModalOperator)
    bpy.types.VIEW3D_MT_object.remove(menu_func)



if __name__ == "__main__":
    register()
    
    bpy.ops.object.modal_operator('INVOKE_DEFAULT')

If you want to return the 3D cursor location, my code works as written:

It is work for tool shift+rightMouse, but how dinamic get this signal or use event pressd shift+rightMouse?

Normally you use the msgbus but it only works of accesing location from GUI or from programming. Not from operators.

Now you can use a previous-next value comparison that runs all the time. Though I have never seen this used widely, perhaps it might not be the best approach.

import bpy
from math import floor


class ModalTimerOperator(bpy.types.Operator):
    bl_idname = "wm.modal_timer_operator"
    bl_label = "Modal Timer Operator"
    
    _timer = None
    prev = []
    
    def modal(self, context, event):
        # now cancel with ESC
        if event.type in {'ESC'}:
            self.cancel(context)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            # convert to list to not mess with object references
            c = list(context.scene.cursor.location)
            if self.prev != c:
                self.prev = c
                print('cursor changed', c)

        return {'PASS_THROUGH'}

    def execute(self, context):
        wm = context.window_manager
        self._timer = wm.event_timer_add(0.1, window=context.window)
        wm.modal_handler_add(self)
        print('operator started')
        return {'RUNNING_MODAL'}

    def cancel(self, context):
        print('operator cancelled')        
        wm = context.window_manager
        wm.event_timer_remove(self._timer)

bpy.utils.register_class(ModalTimerOperator)
bpy.ops.wm.modal_timer_operator()

It is work on clicked rightMouse

import copy
import bpy
from bpy.props import IntProperty, FloatProperty


class ModalOperator(bpy.types.Operator):
    """Move an object with the mouse, example"""
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"
    
    last_position_cursor_3d = copy.deepcopy(bpy.context.scene.cursor.location)

    def modal(self, context, event):               
        if event.type == 'LEFTMOUSE':
            pass
            
        elif event.type == 'RIGHTMOUSE': 
            if self.last_position_cursor_3d != bpy.context.scene.cursor.location:
                self.last_position_cursor_3d = copy.deepcopy(bpy.context.scene.cursor.location)
                print(self.last_position_cursor_3d)
            #return {'CANCELLED'}

        elif event.type == 'ESC':
            return {'CANCELLED'}

        return {'PASS_THROUGH'}
        #return {'RUNNING_MODAL'}
        

    def invoke(self, context, event):
        if context.object:

            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "No active object, could not finish")
            return {'CANCELLED'}


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


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


if __name__ == "__main__":
    print("---------------")
    register()

    # test call
    bpy.ops.object.modal_operator('INVOKE_DEFAULT')