In some tools, for example, “eyedropper” or “selection by color”, it is necessary to get the value of the texture pixel that is currently under the mouse cursor. To get pixels data we need to know its coordinates in the texture space.
In Blender, by handling the MOUSEMOVE event in a modal operator, we can get the coordinates that is under the mouse cursor in the current area space.
We can get the coordinate values in the area space from the following event properties:
- the x-coordinate – event.mouse_region_x
- the y-coordinate – event.mouse_region_y
However, we can see that the texture does not occupy the entire area of the Image Editor area. There may be free margins around it, or the texture can be scaled and go beyond the area.
To convert coordinates from area to texture coordinates, we can use the region_to_view function. This function allows us to convert area coordinates, which range from 0 to infinity, into linear texture coordinates, which range from 0 to 1.
Let’s define a modal operator that will track the MOUSEMOVE event and, when processing it, translate the mouse cursor coordinates into linear texture coordinates.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import bpy class CursorOperator(bpy.types.Operator): bl_idname = 'cursor.operator' bl_label = 'Cursor Operator' def modal(self, context, event): if event.type == 'MOUSEMOVE': print('area coordinates', 'x = ', event.mouse_region_x, 'y = ', event.mouse_region_y) texture_coordinates = context.region.view2d.region_to_view(event.mouse_region_x, event.mouse_region_y) print('texture coordinates', 'x = ', texture_coordinates[0], 'y = ', texture_coordinates[1]) if event.type in {'RIGHTMOUSE', 'ESC'}: return {'FINISHED'} return {'RUNNING_MODAL'} def invoke(self, context, event): print('start') context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} bpy.utils.register_class(CursorOperator) |
Let’s also define a panel in the Image Editor area with a button to execute this operator.
1 2 3 4 5 6 7 8 9 10 11 |
class CURSOR_PT_Panel(bpy.types.Panel): bl_idname = 'CURSOR_PT_Panel' bl_label = 'Cursor' bl_space_type = 'IMAGE_EDITOR' bl_region_type = 'UI' bl_category = 'Cursor' def draw(self, context): self.layout.operator('cursor.operator', icon='BLENDER', text='Start') bpy.utils.register_class(CURSOR_PT_Panel) |
Now, when we press the operator execution button in our panel in the Image Editor area, the current coordinates of the mouse cursor in the area space (from 0 to inf) and in the linear texture space (from 0 to 1) will be printed to the console.
If the resulting values are outside the range 0 – 1, it means that the mouse cursor has gone beyond the texture.
In order to get absolute texture coordinates, we can multiply getting values by the resolution of the texture: for x coordinate – by horizontal resolution in pixels, for y – by vertical.
To stop the operator, right-click or press the ESC key.