+4 votes

Hi,

I want the user to draw a mask on a Sprite. The sprite is initially invisible and as the user clicks on the sprite it reveal itself, like "painting" the Sprite.

I'm using the lightmask demo, my first attempt was to duplicate a light as long as the user clicks but it makes the game very slow.

I want to draw inside the Light2D's texture. Is that possible ? Is it possible to draw a texture programatically ?

I'm trying:

func _input(event):
if ( event.type == InputEvent.MOUSE_BUTTON ):
    var tex = get_texture()
    tex.draw(get_node("brushSprite").get_texture() , event.pos )
    set_texture(tex)
    update()

But this isn't working.
Any help will be greatly appreciated.

Cheers.

in Engine by (33 points)
retagged by

Well, I tried pretty much everything. I learnt that drawing on a CanvasItem is pretty easy, but couldn't convert that output on a working texture for my light.

The closer I got to is loading the image and painting Rect2 of 1 pixel size depending on mouse position.

I've seen there is a brush method in Image, but like the draw method on Texture, both are poorly documented, I tried using them with different parameters, no luck whatsover.

Ok, I'm getting closer:

var fondo
var fondoData
var brushData
var whiteData

func _ready():
    set_process_input(true)
    fondo = ResourceLoader.load("res://assets/empty.png")
    fondoData = fondo.get_data()
    whiteData = ResourceLoader.load("res://assets/white.png").get_data()
    brushData = ResourceLoader.load("res://assets/brush_bw.png").get_data()
func _input(event):
    if Input.is_mouse_button_pressed(1):
            var realPos = event.pos
            realPos.x -= brushData.get_width() / 2
            realPos.y -= brushData.get_height() / 2

            fondoData.brush_transfer( whiteData, brushData, realPos )
            get_node("cabeza/luces/luz").get_texture().set_data(fondoData)

fondoData.brush_transfer works like this:

  • fondoData is the background image.
  • whiteData is an image with same size that you want to put over fondoData
  • brushData is a grayscale image that will be used as brush
  • realPos is the position where you want to paint

pretty simple actually, and this is working, but still very slow (although faster that previous attempts).

Another way that works is not using lightmask and instead of whiteData use the image data. same bad performance tho

Maybe shaders its the answer...

2 Answers

+5 votes
Best answer

Using _process instead of _input and disabling mipmapping and filter did the trick

var fondo
var fondoData
var brushData
var whiteData

func _ready():
    set_process(true)
    whiteData = ResourceLoader.load("res://assets/cuerpo.png").get_data()
    brushData = ResourceLoader.load("res://assets/brush_bw.png").get_data()
func _process(event):
    if Input.is_mouse_button_pressed(1):
            var realPos = event.pos
            realPos.x -= brushData.get_width() / 2
            realPos.y -= brushData.get_height() / 2

            fondoData = get_node("TextureFrame").get_texture().get_data()
            fondoData.brush_transfer( whiteData, brushData, realPos )
            get_node("TextureFrame").get_texture().set_data(fondoData)
by (33 points)

Thank you so much for posting a solution to your problem. You're the hero this community needs :)

I still can't quite figure it out. Could you post an example scene?

Haha, thanks, you can download my source code here: https://macramole.itch.io/human-emotions

0 votes

I had a similar problem and found out you can use a Viewport with renderTexture enabled to generate masks from code.
See this question: https://godotengine.org/qa/9249/mask-a-sprite-with-a-dynamic-mask

by (121 points)
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.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.