122 lines
5.0 KiB
GDScript
122 lines
5.0 KiB
GDScript
class_name ABGPartyLineTrack
|
|
extends Control
|
|
|
|
const INK := Color("#17252c")
|
|
const GOLD := Color("#d6ad5d")
|
|
const GOLD_LIGHT := Color("#f3d991")
|
|
const TEAL := Color("#4b8790")
|
|
const CORAL := Color("#d97964")
|
|
|
|
var actor_nodes: Array[Control] = []
|
|
var selected_recruit_id := ""
|
|
var locale := "zh_CN"
|
|
var draw_static_cord := true
|
|
enum RenderLayer { CORD, EFFECTS }
|
|
var render_layer := RenderLayer.CORD
|
|
|
|
func bind(nodes: Array[Control], selected_id: String, next_locale: String) -> void:
|
|
actor_nodes = nodes
|
|
selected_recruit_id = selected_id
|
|
locale = next_locale
|
|
queue_redraw()
|
|
|
|
func _process(_delta: float) -> void:
|
|
if not is_inside_tree():
|
|
return
|
|
queue_redraw()
|
|
|
|
func _exit_tree() -> void:
|
|
set_process(false)
|
|
actor_nodes.clear()
|
|
|
|
func _draw() -> void:
|
|
if actor_nodes.is_empty() or size.x <= 2.0 or size.y <= 2.0:
|
|
return
|
|
var centers: Array[Vector2] = []
|
|
for node in actor_nodes:
|
|
if not is_instance_valid(node):
|
|
continue
|
|
var rect := node.get_global_rect()
|
|
var track_rect := get_global_rect()
|
|
centers.append(Vector2(rect.get_center().x - track_rect.position.x, rect.position.y + rect.size.y * 0.68 - track_rect.position.y))
|
|
if centers.size() < 2:
|
|
return
|
|
var cord_y := centers[0].y
|
|
var left_x := maxf(18.0, centers[0].x - 92.0)
|
|
var right_x := minf(size.x - 18.0, centers[centers.size() - 1].x + 92.0)
|
|
if render_layer == RenderLayer.CORD:
|
|
if not draw_static_cord:
|
|
return
|
|
draw_line(Vector2(left_x, cord_y), Vector2(right_x, cord_y), Color(INK, 0.82), 8.0, true)
|
|
draw_line(Vector2(left_x, cord_y - 2.0), Vector2(right_x, cord_y - 2.0), GOLD, 2.0, true)
|
|
draw_line(Vector2(left_x, cord_y + 3.0), Vector2(right_x, cord_y + 3.0), Color(TEAL, 0.72), 1.0, true)
|
|
draw_circle(Vector2(left_x, cord_y), 9.0, Color(INK, 0.88))
|
|
draw_circle(Vector2(left_x, cord_y), 5.0, GOLD)
|
|
draw_circle(Vector2(right_x, cord_y), 9.0, Color(INK, 0.88))
|
|
draw_circle(Vector2(right_x, cord_y), 5.0, GOLD)
|
|
for index in range(centers.size() - 1):
|
|
var midpoint := centers[index].lerp(centers[index + 1], 0.5)
|
|
var diamond := PackedVector2Array([
|
|
midpoint + Vector2(0, -7), midpoint + Vector2(7, 0),
|
|
midpoint + Vector2(0, 7), midpoint + Vector2(-7, 0)
|
|
])
|
|
draw_colored_polygon(diamond, Color(INK, 0.90))
|
|
draw_polyline(diamond + PackedVector2Array([diamond[0]]), GOLD_LIGHT, 1.5, true)
|
|
return
|
|
var threat_target := Vector2(size.x * 0.94, size.y * 0.65)
|
|
draw_circle(threat_target, 8.0, Color(INK, 0.86))
|
|
draw_circle(threat_target, 5.0, Color(CORAL, 0.92))
|
|
draw_arc(threat_target, 12.0, 0.0, TAU, 28, Color(GOLD_LIGHT, 0.92), 2.0, true)
|
|
for index in range(centers.size()):
|
|
var point := centers[index]
|
|
var position := int(actor_nodes[index].get_meta("position", centers.size() - index - 1))
|
|
_draw_marker(point, position, position == 0)
|
|
var selected_index := -1
|
|
for index in range(actor_nodes.size()):
|
|
if is_instance_valid(actor_nodes[index]) and String(actor_nodes[index].get_meta("recruit_id", "")) == selected_recruit_id:
|
|
selected_index = index
|
|
break
|
|
if selected_index >= 0 and selected_index < centers.size():
|
|
var source := centers[selected_index]
|
|
draw_arc(source, 29.0, 0.0, TAU, 40, Color(GOLD_LIGHT, 0.92), 3.0, true)
|
|
draw_arc(source, 36.0, 0.2, 2.5, 40, Color(CORAL, 0.68), 2.0, true)
|
|
if threat_target.distance_to(source) > 20.0:
|
|
_draw_dashed_curve(source, threat_target)
|
|
for index in range(centers.size()):
|
|
if index == selected_index:
|
|
continue
|
|
var destination := centers[index] + Vector2(0, 18)
|
|
draw_arc(destination, 18.0, 0.0, TAU, 28, Color(GOLD_LIGHT, 0.75), 2.0, true)
|
|
draw_circle(destination, 4.0, Color(TEAL, 0.78))
|
|
|
|
func _draw_marker(point: Vector2, index: int, exposed: bool) -> void:
|
|
var center := point + Vector2(0, 18)
|
|
var fill := CORAL if exposed else TEAL
|
|
var shield := PackedVector2Array([
|
|
center + Vector2(-17, -11), center + Vector2(17, -11),
|
|
center + Vector2(13, 14), center + Vector2(0, 25),
|
|
center + Vector2(-13, 14)
|
|
])
|
|
draw_colored_polygon(shield, Color(INK, 0.92))
|
|
draw_polyline(shield + PackedVector2Array([shield[0]]), GOLD, 2.0, true)
|
|
draw_colored_polygon(PackedVector2Array([
|
|
center + Vector2(-12, -7), center + Vector2(12, -7),
|
|
center + Vector2(9, 10), center + Vector2(0, 18), center + Vector2(-9, 10)
|
|
]), Color(fill, 0.88))
|
|
draw_string(ThemeDB.fallback_font, center + Vector2(-4, 6), str(index), HORIZONTAL_ALIGNMENT_LEFT, -1, 14, GOLD_LIGHT)
|
|
|
|
func _draw_dashed_curve(start: Vector2, finish: Vector2) -> void:
|
|
var control := Vector2((start.x + finish.x) * 0.5, minf(size.y - 8.0, maxf(start.y, finish.y) + size.y * 0.26))
|
|
const SEGMENTS := 24
|
|
for index in range(SEGMENTS):
|
|
if index % 2 != 0:
|
|
continue
|
|
var t0 := float(index) / float(SEGMENTS)
|
|
var t1 := float(index + 1) / float(SEGMENTS)
|
|
draw_line(_quadratic_point(start, control, finish, t0), _quadratic_point(start, control, finish, t1), Color(GOLD_LIGHT, 0.92), 2.0, true)
|
|
|
|
|
|
func _quadratic_point(start: Vector2, control: Vector2, finish: Vector2, t: float) -> Vector2:
|
|
var inverse := 1.0 - t
|
|
return inverse * inverse * start + 2.0 * inverse * t * control + t * t * finish
|