73 lines
3.3 KiB
GDScript
73 lines
3.3 KiB
GDScript
extends RefCounted
|
|
## Compact translucent cards attached to objects in the world canvas.
|
|
static func panel_style(accent: Color) -> StyleBoxFlat:
|
|
var style := StyleBoxFlat.new()
|
|
style.bg_color = Color(0.018,0.041,0.063,0.48)
|
|
style.border_color = Color(accent,0.55)
|
|
style.set_border_width_all(1)
|
|
style.border_width_top = 2
|
|
style.set_corner_radius_all(7)
|
|
style.content_margin_left = 12
|
|
style.content_margin_right = 12
|
|
style.content_margin_top = 10
|
|
style.content_margin_bottom = 10
|
|
style.shadow_color = Color(0,0,0,0.28)
|
|
style.shadow_size = 7
|
|
style.shadow_offset = Vector2(0,3)
|
|
return style
|
|
|
|
static func compact_button(button: Button, accent: Color) -> void:
|
|
preload("res://scripts/ui/hud_button_style.gd").apply(button,accent)
|
|
button.custom_minimum_size.y = 30
|
|
button.add_theme_font_size_override("font_size",11)
|
|
for state in ["normal","hover","pressed","disabled"]:
|
|
var style := button.get_theme_stylebox(state).duplicate() as StyleBoxFlat
|
|
style.bg_color.a = 0.50
|
|
style.content_margin_top = 4
|
|
style.content_margin_bottom = 4
|
|
style.content_margin_left = 9
|
|
style.content_margin_right = 9
|
|
style.shadow_size = 0
|
|
style.set_corner_radius_all(4)
|
|
button.add_theme_stylebox_override(state,style)
|
|
|
|
static func hud_obstacles(hud: Node) -> Array[Rect2]:
|
|
var boxes: Array[Rect2] = []
|
|
if hud == null: return boxes
|
|
for name in ["CaptainPanel","CaptainEquipment","CaptainGearInventory","MissionObjectives","ShipDrawer","PassiveCaptainPanel","PassiveShipPanel"]:
|
|
var control := hud.get_node_or_null(NodePath(name)) as Control
|
|
if control != null and control.is_visible_in_tree(): boxes.append(control.get_global_rect().grow(6))
|
|
return boxes
|
|
|
|
static func beside(center: Vector2, radius: float, extent: Vector2, viewport: Vector2, obstacles: Array[Rect2] = [], prefer_right := true, vertical_radius := -1.0) -> Vector2:
|
|
var gap := 14.0
|
|
var vertical := radius if vertical_radius < 0 else vertical_radius
|
|
var right := center + Vector2(radius+gap,-extent.y*0.5)
|
|
var left := center - Vector2(radius+gap+extent.x,extent.y*0.5)
|
|
var candidates: Array[Vector2] = [right,left]
|
|
if not prefer_right: candidates.reverse()
|
|
candidates.append(center+Vector2(-extent.x*0.5,-vertical-gap-extent.y))
|
|
candidates.append(center+Vector2(-extent.x*0.5,vertical+gap))
|
|
# Additional lanes prevent two cards from clipping one another's headers.
|
|
for obstacle in obstacles:
|
|
candidates.append(Vector2(center.x-extent.x*0.5,obstacle.position.y-gap-extent.y))
|
|
candidates.append(Vector2(center.x-extent.x*0.5,obstacle.end.y+gap))
|
|
var chosen := Vector2.ZERO
|
|
var best := INF
|
|
var low := Vector2(10,88)
|
|
var high := Vector2(maxf(low.x,viewport.x-extent.x-10),maxf(low.y,viewport.y-extent.y-118))
|
|
for index in candidates.size():
|
|
var candidate := candidates[index]
|
|
var clamped := candidate.clamp(low,high)
|
|
var box := Rect2(clamped,extent)
|
|
var score := candidate.distance_to(clamped) + index*8.0
|
|
# Avoid covering the object if an edge forces the card to change sides.
|
|
var object_box := Rect2(center-Vector2(radius,vertical),Vector2(radius,vertical)*2)
|
|
if box.intersects(object_box): score += box.intersection(object_box).get_area()*0.1
|
|
for obstacle in obstacles:
|
|
if box.intersects(obstacle): score += box.intersection(obstacle).get_area()
|
|
if score < best:
|
|
best = score
|
|
chosen = clamped
|
|
return chosen
|