extends Node2D ## Triggered when the "select" action occurs. Provide the value at the cursor position signal on_select(value : float) ## Progression type. Either looping or going back and forth. enum ProgressionType { LOOP_POSITIVE, LOOP_NEGATIVE, PING_PONG } ## Texture for the cursor @export var cursor_texture : Texture ## Size of the area @export var area_size : Vector2 : set(value) : area_size = value area_texture = ImageTexture.create_from_image(Image.create_empty(area_size.x, area_size.y, false, Image.FORMAT_RGBA8)) ## Shader material used for area rendering. ## Should have a sampler2D uniform called "values" that will accept a 1D-ish texture ## mapping the values. @export var area_material : ShaderMaterial ## Success values @export var area_values : Curve : set(value) : area_values = value if value != null: curve_texture = CurveTexture.new() var texture_size : int = int(ceil((area_values.bake_resolution * 4) / 512.) * 512) curve_texture.width = texture_size curve_texture.curve = area_values curve_texture.texture_mode = CurveTexture.TEXTURE_MODE_RED if area_material != null: area_material.set_shader_parameter("values", curve_texture) ## Type of progression @export var progression_type : ProgressionType = ProgressionType.PING_PONG : set(value) : progression_type = value _compute_phase() ## Progression speed in "area per second" (1 means "one area sprite length per seconds") @export var progression_speed : float ## Sprite offsetting (for debug purpose ...) @export var offset : Vector2 ## Shall we stop after a select ? @export var stop_at_select : bool = false # Cursor sprite @onready var cursor_sprite : Sprite2D = $Cursor as Sprite2D # Area sprite @onready var area_sprite : Sprite2D = $Area as Sprite2D # Progression phase (1. left to right, -1. right to left) @onready var phase : float = 1. var progression : float var curve_texture : CurveTexture var area_texture : Texture func _ready() -> void: deactivate() func activate() -> void: assert(cursor_texture != null and area_material != null and area_values != null ) progression = 0. cursor_sprite.texture = cursor_texture area_sprite.texture = area_texture area_sprite.position = offset area_sprite.material = area_material area_material.set_shader_parameter("values", curve_texture) area_sprite.material = area_material phase = -1. if progression_type == ProgressionType.LOOP_NEGATIVE else 1. set_process(true) set_process_input(true) func deactivate() -> void: set_process(false) set_process_input(false) func _process(delta : float) -> void: progression += delta * progression_speed if progression > 1.: progression -= 1. _compute_phase() cursor_sprite.position.x = area_sprite.position.x + phase * ((progression - 0.5) * area_size.x * area_sprite.scale.x) cursor_sprite.position.y = area_sprite.position.y # in case of area movement ... func _input(event : InputEvent) -> void: if event.is_action("ui_accept") and event.is_pressed() and (not event.is_echo()): var p : float = progression if phase > 0. else 1. - progression on_select.emit(area_values.sample_baked(p)) if stop_at_select: set_process(false) set_process_input(false) func _compute_phase() -> void: match progression_type: ProgressionType.PING_PONG: phase *= -1. ProgressionType.LOOP_POSITIVE: phase = 1. ProgressionType.LOOP_NEGATIVE: phase = -1.
or share this direct link: