mirror of
https://github.com/ElHombreAlex/FTL-Faster-Than-Light-VR.git
synced 2026-10-06 01:00:06 +02:00
115 lines
4.1 KiB
GDScript
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)
|