Hi!
How I can get 3D position cursor?
Welcome to BA
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')