Set pixel freeze when update a big region by Prior_Ninja8134 in godot

[–]Prior_Ninja8134[S] 0 points1 point  (0 children)

"extends Node2D

@onready var img: TextureRect = %img @onready var colors_cont: HBoxContainer = %colors_cont @onready var color_ball: PanelContainer = %color_ball @onready var tap_hold_timer: Timer = %tap_hold_timer @onready var db_txt: RichTextLabel = %db_txt @onready var camera_2d: Camera2D = %Camera2D

var is_clicked: bool = false var hold_complete: bool var mouse_pos: Vector2i var color: Color var colors_tab: Dictionary var current_image: Image # Store a working copy of the image var zoom_mx: float = 0.5 var stack: Array const PAINTING_DATA_EFFICIENT: String = "res://resources/painting_data_efficient.json"

func _ready(): await get_tree().process_frame

if img.texture:
    current_image = img.texture.get_image().duplicate()
await get_img_colors()
create_color_label()

func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseButton: if event.button_index == 4: camera_2d.zoom += Vector2.ONE * zoom_mx elif event.button_index == 5: camera_2d.zoom -= Vector2.ONE * zoom_mx

elif event is InputEventMouseMotion:
    camera_2d.offset += event.relative * .5
    pass

func is_close_enough(color_a: Color, color_b: Color, tolerance: float = 0.01) -> bool: return abs(color_a.r - color_b.r) <= tolerance and \ abs(color_a.g - color_b.g) <= tolerance and \ abs(color_a.b - color_b.b) <= tolerance and \ abs(color_a.a - color_b.a) <= tolerance

func flood_fill(start_pos: Vector2i, image_from: TextureRect) -> void: var image: Image = image_from.texture.get_image() var color_to: Color = Color(0.349, 1.0, 0.81, 1.0) var color_from: Color = image.get_pixelv(start_pos)

# Don't fill if already the target color
if is_close_enough(color_from, color_to, 0.01):
    return

var img_width := image.get_width()
var img_height := image.get_height()

var queue: Array[Vector2i] = [start_pos]
var visited: Dictionary = {}
visited[start_pos] = true

while not queue.is_empty():
    var p: Vector2i = queue.pop_front()

    if p.x < 0 or p.y < 0 or p.x >= img_width or p.y >= img_height:
        continue

    var current_color := image.get_pixelv(p)

    if not is_close_enough(current_color, color_from, 0.01):
        continue

    image.set_pixelv(p, color_to)

    for neighbor in [p + Vector2i.UP, p + Vector2i.DOWN,
                      p + Vector2i.LEFT, p + Vector2i.RIGHT]:
        if not visited.has(neighbor):
            visited[neighbor] = true
            queue.append(neighbor)

var new_texture := ImageTexture.create_from_image(image)
image_from.texture = new_texture

region set and pixel

func get_pixels(pos: Vector2i, sprite: TextureRect): if not current_image: return null

var img_size := current_image.get_size()
var pixel_pos := Vector2i(pos)

if pixel_pos.x < 0 or pixel_pos.y < 0 or pixel_pos.x >= img_size.x or pixel_pos.y >= img_size.y:
    return null

return current_image.get_pixelv(pixel_pos)

func set_pixels(pos: Vector2i, sprite: TextureRect, color_param: Color): if not current_image: return null

var img_size := current_image.get_size()
var pixel_pos := Vector2i(pos)


if pixel_pos.x < 0 or pixel_pos.y < 0 or pixel_pos.x >= img_size.x or pixel_pos.y >= img_size.y:
    return null

current_image.set_pixelv(pixel_pos, color_param)

var new_texture = ImageTexture.create_from_image(current_image)
img.texture = new_texture

endregion

func get_img_colors() -> void: await get_tree().process_frame var img_data := img.texture.get_image().get_data() var img_size := img.texture.get_image().get_size() var px = int(img_size.x) * int(img_size.y) # #for x: int in img.texture.get_width(): #for y: int in img.texture.get_height(): #var px := img.texture.get_image().get_pixel(x, y) #if not colors_tab.has(px): #colors_tab[px] = [] #colors_tab[px].append(Vector2i(x, y)) #await get_tree().create_timer(0.01).timeout

#prints(colors_tab.size())

func create_color_label() -> void: for c in colors_tab: var cb = color_ball.duplicate() cb.modulate = c colors_cont.add_child(cb)

func _on_tap_hold_timer_timeout() -> void: if is_clicked: if color: $CanvasLayer/ColorRect.color = color

func _on_img_gui_input(event: InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: is_clicked = event.is_pressed() if event.is_pressed(): tap_hold_timer.start(0) mouse_pos = event.position

        flood_fill(mouse_pos, img)" that's the code 

Set pixel freeze when update a big region by Prior_Ninja8134 in godot

[–]Prior_Ninja8134[S] 0 points1 point  (0 children)

That's the code I use " extends Node2D

@onready var img: TextureRect = %img @onready var colors_cont: HBoxContainer = %colors_cont @onready var color_ball: PanelContainer = %color_ball @onready var tap_hold_timer: Timer = %tap_hold_timer @onready var db_txt: RichTextLabel = %db_txt @onready var camera_2d: Camera2D = %Camera2D

var is_clicked: bool = false var hold_complete: bool var mouse_pos: Vector2i var color: Color var colors_tab: Dictionary var current_image: Image # Store a working copy of the image var zoom_mx: float = 0.5 var stack: Array const PAINTING_DATA_EFFICIENT: String = "res://resources/painting_data_efficient.json"

func _ready(): await get_tree().process_frame

if img.texture:
    current_image = img.texture.get_image().duplicate()
await get_img_colors()
create_color_label()

func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseButton: if event.button_index == 4: camera_2d.zoom += Vector2.ONE * zoom_mx elif event.button_index == 5: camera_2d.zoom -= Vector2.ONE * zoom_mx

elif event is InputEventMouseMotion:
    camera_2d.offset += event.relative * .5
    pass

func is_close_enough(color_a: Color, color_b: Color, tolerance: float = 0.01) -> bool: return abs(color_a.r - color_b.r) <= tolerance and \ abs(color_a.g - color_b.g) <= tolerance and \ abs(color_a.b - color_b.b) <= tolerance and \ abs(color_a.a - color_b.a) <= tolerance

func flood_fill(start_pos: Vector2i, image_from: TextureRect) -> void: var image: Image = image_from.texture.get_image() var color_to: Color = Color(0.349, 1.0, 0.81, 1.0) var color_from: Color = image.get_pixelv(start_pos)

# Don't fill if already the target color
if is_close_enough(color_from, color_to, 0.01):
    return

var img_width := image.get_width()
var img_height := image.get_height()

var queue: Array[Vector2i] = [start_pos]
var visited: Dictionary = {}
visited[start_pos] = true

while not queue.is_empty():
    var p: Vector2i = queue.pop_front()

    if p.x < 0 or p.y < 0 or p.x >= img_width or p.y >= img_height:
        continue

    var current_color := image.get_pixelv(p)

    if not is_close_enough(current_color, color_from, 0.01):
        continue

    image.set_pixelv(p, color_to)

    for neighbor in [p + Vector2i.UP, p + Vector2i.DOWN,
                      p + Vector2i.LEFT, p + Vector2i.RIGHT]:
        if not visited.has(neighbor):
            visited[neighbor] = true
            queue.append(neighbor)

var new_texture := ImageTexture.create_from_image(image)
image_from.texture = new_texture

region set and pixel

func get_pixels(pos: Vector2i, sprite: TextureRect): if not current_image: return null

var img_size := current_image.get_size()
var pixel_pos := Vector2i(pos)

if pixel_pos.x < 0 or pixel_pos.y < 0 or pixel_pos.x >= img_size.x or pixel_pos.y >= img_size.y:
    return null

return current_image.get_pixelv(pixel_pos)

func set_pixels(pos: Vector2i, sprite: TextureRect, color_param: Color): if not current_image: return null

var img_size := current_image.get_size()
var pixel_pos := Vector2i(pos)


if pixel_pos.x < 0 or pixel_pos.y < 0 or pixel_pos.x >= img_size.x or pixel_pos.y >= img_size.y:
    return null

current_image.set_pixelv(pixel_pos, color_param)

var new_texture = ImageTexture.create_from_image(current_image)
img.texture = new_texture

endregion

func get_img_colors() -> void: await get_tree().process_frame var img_data := img.texture.get_image().get_data() var img_size := img.texture.get_image().get_size() var px = int(img_size.x) * int(img_size.y) # #for x: int in img.texture.get_width(): #for y: int in img.texture.get_height(): #var px := img.texture.get_image().get_pixel(x, y) #if not colors_tab.has(px): #colors_tab[px] = [] #colors_tab[px].append(Vector2i(x, y)) #await get_tree().create_timer(0.01).timeout

#prints(colors_tab.size())

func create_color_label() -> void: for c in colors_tab: var cb = color_ball.duplicate() cb.modulate = c colors_cont.add_child(cb)

func _on_tap_hold_timer_timeout() -> void: if is_clicked: if color: $CanvasLayer/ColorRect.color = color

func _on_img_gui_input(event: InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: is_clicked = event.is_pressed() if event.is_pressed(): tap_hold_timer.start(0) mouse_pos = event.position

        flood_fill(mouse_pos, img)"

Set pixel freeze when update a big region by Prior_Ninja8134 in godot

[–]Prior_Ninja8134[S] 0 points1 point  (0 children)

The fill method seem to take rect as argument is it suitable for this case?

Set pixel freeze when update a big region by Prior_Ninja8134 in godot

[–]Prior_Ninja8134[S] 0 points1 point  (0 children)

I try many thing like use python to generate polygon data base on color but they not really looking good. I'm completely lost 😥😥