Files
ElHombreAlex--FTL-Faster-Th…/scripts/shortcut_wheel.gd
T
ElHombreAlex 35cdf71054 V0.1
First publishable version of the mod
2026-10-03 12:59:33 +02:00

115 lines
4.1 KiB
GDScript

extends Node3D
# One FTL-styled radial surface. Choosing a sector redraws once; no animated
# viewport or per-label meshes are needed while the wheel is held open.
const UI = preload("res://scripts/ftl_ui_theme.gd")
const SIZE := Vector2(0.54,0.60)
const PIXELS := Vector2(720,800)
var selected := -1
var entries: Array = []
var heading := "ACTIONS"
var viewport: SubViewport
var canvas: Control
var content_revision := 0
func _ready() -> void:
viewport = SubViewport.new()
viewport.size = Vector2i(PIXELS)
viewport.transparent_bg = true
viewport.render_target_update_mode = SubViewport.UPDATE_ONCE
add_child(viewport)
canvas = WheelCanvas.new()
canvas.wheel = self
canvas.size = PIXELS
canvas.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
viewport.add_child(canvas)
var backing := MeshInstance3D.new()
var quad := QuadMesh.new()
quad.size = SIZE
backing.mesh = quad
backing.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
var material := StandardMaterial3D.new()
material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
material.no_depth_test = true
material.render_priority = 125
material.texture_filter = BaseMaterial3D.TEXTURE_FILTER_NEAREST
material.albedo_texture = viewport.get_texture()
backing.material_override = material
add_child(backing)
visible = false
func set_entries(value: Array, title: String) -> void:
if entries == value and heading == title:
return
entries = value.duplicate(true)
heading = title
_redraw()
func choose(stick: Vector2) -> void:
# Top = 1, clockwise through 8. Center releases without an action.
var next := -1 if stick.length() < 0.45 else posmod(roundi(atan2(stick.x,stick.y) / (TAU / 8.0)),8)
if next == selected:
return
selected = next
_redraw()
func _redraw() -> void:
content_revision += 1
if canvas != null:
canvas.queue_redraw()
viewport.render_target_update_mode = SubViewport.UPDATE_ONCE
class WheelCanvas extends Control:
var wheel: Node3D
const CENTER := Vector2(360,353)
func _sector(angle: float) -> PackedVector2Array:
var points := PackedVector2Array()
var half := TAU / 16.0 - .025
for j in range(13):
var a := angle - half + (half * 2) * j / 12.0
points.append(CENTER + Vector2(sin(a),-cos(a)) * 326)
for j in range(12,-1,-1):
var a := angle - half + (half * 2) * j / 12.0
points.append(CENTER + Vector2(sin(a),-cos(a)) * 129)
return points
func _draw() -> void:
for i in range(8):
var enabled: bool = i < wheel.entries.size() and bool(wheel.entries[i].get("enabled",true))
var active: bool = wheel.selected == i and enabled
var angle := i * TAU / 8.0
var outline := _sector(angle)
draw_colored_polygon(outline,UI.SELECTED if active else UI.PANEL if enabled else UI.DARK)
outline.append(outline[0])
draw_polyline(outline,UI.GOLD if active else UI.EDGE if enabled else UI.MUTED,1.5,false)
var center := CENTER + Vector2(sin(angle),-cos(angle)) * 225
UI.centered_text(self,str(i + 1),center + Vector2(0,-22),38,UI.GOLD if active else UI.GREEN if enabled else UI.MUTED,"header")
var label := str(wheel.entries[i].get("label","")) if i < wheel.entries.size() else "-"
var lines := label.replace("\n"," ").split(" ",false)
var current := ""
var wrapped: Array[String] = []
for word in lines:
if current.length() + word.length() + 1 > 12 and current != "":
wrapped.append(current)
current = ""
current = word if current == "" else current + " " + word
if current != "": wrapped.append(current)
for line in range(mini(3,wrapped.size())):
UI.centered_text(self,wrapped[line],center + Vector2(0,11 + line * 21),24,UI.INK if enabled else UI.MUTED)
UI.frame(self,Rect2(CENTER - Vector2(102,56),Vector2(204,112)),UI.DARK,UI.EDGE,17)
var titles := str(wheel.heading).split("\n")
for i in range(titles.size()):
UI.centered_text(self,titles[i],CENTER + Vector2(0,(i - (titles.size() - 1) * .5) * 29),25,UI.INK,"header")
UI.frame(self,Rect2(38,700,644,88),UI.DARK,UI.EDGE,12)
UI.centered_text(self,"STICK: CHOOSE RELEASE BUMPER: CONFIRM",Vector2(360,727),24,UI.INK)
UI.centered_text(self,"A: CATEGORY B / CENTER: CANCEL",Vector2(360,760),24,UI.MUTED)