0 votes

Trying to get the Color value out of a specific image's pixel given a LMB click. This script is attached to a basic Node (I prefer to use them as my scene roots):

func _process(delta):
if Input.is_action_just_pressed("lmb"):
    var data: Image = get_viewport().get_texture().get_data()
    data.lock()
    var world_click_pos: Vector2 = get_viewport().get_mouse_position()
    print("click at: %s" % world_click_pos)
    var color: Color = data.get_pixelv(world_click_pos);
    ColorNode.color = color # A ColorRect child, aliased out of scope of _process()
    print(str(color))
    data.unlock()

I fairly consistently get incorrect Color values out of this. The printed Vector4 is incorrect and the ColorRect displays the wrong color. It's almost like the position I'm feeding to get_pixelv() isn't right.
I've tried world_click_pos = get_global_mouse_pos() to no avail as well. (That I had to try in a script attached to the Sprite itself, since bare Node objects don't have access to that method).
I've tried it by keeping the Sprite at (0, 0) with offset = false, as well as setting the position programmatically to the center of the screen. Both give me false color readings. For clarification, here is the scene tree:
enter image description here

asked Jun 29 in Engine by DDoop (395 points)
retagged Jun 29 by DDoop

1 Answer

0 votes
Best answer

I solved it by using a radial rainbow gradient as the Sprite's image, which made it very clear that the coordinates needed to be "inverted" along the center X-axis of the Image.

answered Jun 29 by DDoop (395 points)
selected Jun 29 by DDoop

Source for the curious/frustrated:

func _process(delta):
if Input.is_action_just_pressed("lmb"):
    var data: Image = get_viewport().get_texture().get_data()
    data.lock()
    print(data.data["width"])
    print(data.data["height"])
    var click_pos: Vector2 = get_viewport().get_mouse_position()
    var adj_click_pos: Vector2 = invert_coordinates(click_pos)
    print("click at: %s" % click_pos)
    print("flipped pos: %s" % adj_click_pos)
    var color: Color = data.get_pixelv(adj_click_pos);
    ColorNode.color = color
    print(str(color))
    data.unlock()

func invert_coordinates(first_pos: Vector2) -> Vector2:
    var view_size = get_viewport().size
    var view_dim = Vector2(view_size.x, view_size.y)
    var adj_coords = Vector2(first_pos.x, view_size.y - first_pos.y)
    return adj_coords
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.