64 lines
1.6 KiB
GDScript
64 lines
1.6 KiB
GDScript
@tool
|
|
extends Node2D
|
|
|
|
@export var watching_node: Node2D
|
|
@export var upside_down := false
|
|
@export var eye_texture: Texture2D:
|
|
set(val):
|
|
eye_texture = val
|
|
if is_node_ready():
|
|
eye_sprite.texture = eye_texture
|
|
@export_range(0.2, 2.0) var eye_scale := 1.0:
|
|
set(val):
|
|
eye_scale = val
|
|
if is_node_ready():
|
|
eye_sprite.scale = Vector2(eye_scale, eye_scale)
|
|
@export var radius := 30.0:
|
|
set(val):
|
|
radius = val
|
|
if is_node_ready():
|
|
_setup_eye_direction()
|
|
@export var angle_range := 0.9
|
|
@export var debug_real_time_update := false
|
|
|
|
@onready var eye_sprite := $眼睛 as Sprite2D
|
|
|
|
|
|
func _ready() -> void:
|
|
eye_sprite.texture = eye_texture
|
|
eye_sprite.scale = Vector2(eye_scale, eye_scale)
|
|
_setup_eye_direction()
|
|
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
if not watching_node or (Engine.is_editor_hint() and not debug_real_time_update):
|
|
return
|
|
_setup_eye_direction()
|
|
|
|
|
|
func _setup_eye_direction():
|
|
if not watching_node:
|
|
eye_sprite.position.y = radius
|
|
return
|
|
# set eye_sprite position at the arrow head from self's position to watching_node's position
|
|
var direction = watching_node.global_position - global_position
|
|
var min_range
|
|
var max_range
|
|
if upside_down:
|
|
# mirror x-axis
|
|
direction = Vector2(direction.x, -direction.y)
|
|
min_range = -PI + angle_range
|
|
max_range = -angle_range
|
|
else:
|
|
min_range = angle_range
|
|
max_range = PI - angle_range
|
|
var angle = direction.angle()
|
|
# fit in angle_range
|
|
if angle < min_range:
|
|
angle = min_range - angle
|
|
elif angle > max_range:
|
|
angle = max_range - angle
|
|
else:
|
|
angle = 0.0
|
|
eye_sprite.position = direction.normalized().rotated(angle) * radius
|