181 lines
7.5 KiB
GDScript
181 lines
7.5 KiB
GDScript
class_name FrontEnd
|
||
extends Control
|
||
|
||
const ORANGE := Color("f18b28")
|
||
var ui: GameUI
|
||
var loading := false
|
||
var status: Label
|
||
var progress: ProgressBar
|
||
var preview: SubViewport
|
||
var actor: ImportedOperator
|
||
var elapsed := 0.0
|
||
|
||
func caption(value: String, at: Vector2, font_size: int, color: Color = Color("cfcbc3")) -> Label:
|
||
var item := Label.new()
|
||
item.text = value
|
||
item.position = at
|
||
item.add_theme_font_size_override("font_size", font_size)
|
||
item.add_theme_color_override("font_color", color)
|
||
add_child(item)
|
||
return item
|
||
|
||
func _ready() -> void:
|
||
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
if DisplayServer.get_name() == "headless":
|
||
set_process(false)
|
||
return
|
||
mouse_filter = Control.MOUSE_FILTER_STOP
|
||
resized.connect(queue_redraw)
|
||
var backdrop := SubViewportContainer.new()
|
||
backdrop.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
backdrop.stretch = true
|
||
backdrop.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
add_child(backdrop)
|
||
var viewport := SubViewport.new()
|
||
preview = viewport
|
||
viewport.own_world_3d = true
|
||
viewport.msaa_3d = get_viewport().msaa_3d
|
||
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
||
backdrop.add_child(viewport)
|
||
var environment := WorldEnvironment.new()
|
||
var env := Environment.new()
|
||
env.background_mode = Environment.BG_COLOR
|
||
env.background_color = Color("090807")
|
||
env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
|
||
env.ambient_light_color = Color("7c858e")
|
||
env.ambient_light_energy = 0.16
|
||
env.tonemap_mode = Environment.TONE_MAPPER_FILMIC
|
||
environment.environment = env
|
||
viewport.add_child(environment)
|
||
var camera := Camera3D.new()
|
||
viewport.add_child(camera)
|
||
camera.position = Vector3(0, 1.38, -1.65)
|
||
camera.look_at(Vector3(0.18, 1.35, 0))
|
||
camera.fov = 43
|
||
camera.current = true
|
||
actor = ImportedOperator.new()
|
||
viewport.add_child(actor)
|
||
actor.setup("gas_mask")
|
||
actor.rotation.y = -0.17
|
||
actor.preview("pro_rifle__idle", 0.2)
|
||
actor.weapon_mount.add_child(WeaponModels.build(0))
|
||
for index in 2:
|
||
var light := OmniLight3D.new()
|
||
light.position = Vector3(-0.7, 2.7, -0.4) if index == 0 else Vector3(1.1, 1.9, 0.7)
|
||
light.light_color = Color("ffbe70") if index == 0 else Color("b67b3d")
|
||
light.light_energy = 4.0 if index == 0 else 3.0
|
||
light.omni_range = 5
|
||
viewport.add_child(light)
|
||
var veil := TextureRect.new()
|
||
var gradient := Gradient.new()
|
||
gradient.offsets = PackedFloat32Array([0, 0.25, 0.48, 0.75, 1])
|
||
gradient.colors = PackedColorArray([Color(0,0,0,0.88), Color(0,0,0,0.55), Color(0,0,0,0), Color(0,0,0,0.1), Color(0,0,0,0.65)])
|
||
var texture := GradientTexture2D.new()
|
||
texture.gradient = gradient
|
||
texture.fill_from = Vector2(0, 0)
|
||
texture.fill_to = Vector2(1, 0)
|
||
veil.texture = texture
|
||
veil.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
add_child(veil)
|
||
veil.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
var haze := ColorRect.new()
|
||
haze.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
var shader := Shader.new()
|
||
shader.code = """shader_type canvas_item;
|
||
float noise(vec2 p) { return fract(sin(dot(p,vec2(12.9898,78.233))) * 43758.5453); }
|
||
void fragment() {
|
||
vec2 p=UV*vec2(20.,12.);
|
||
float mist=sin(p.x*.7+TIME*.13)*sin(p.y*.6-TIME*.1);
|
||
float glow=exp(-length((UV-vec2(.7,.4))*vec2(2.,1.))*3.);
|
||
vec2 sparks=UV*vec2(150.,80.)+vec2(TIME*.6,TIME*1.2);
|
||
float dotlight=step(.994,noise(floor(sparks)))*(1.-smoothstep(.02,.13,length(fract(sparks)-.5)));
|
||
COLOR=vec4(vec3(.52,.28,.10)+vec3(dotlight),glow*(.06+mist*.025)+dotlight*.65);
|
||
}"""
|
||
var haze_material := ShaderMaterial.new()
|
||
haze_material.shader = shader
|
||
haze.material = haze_material
|
||
add_child(haze)
|
||
haze.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
var layout := Control.new()
|
||
layout.name = "Layout"
|
||
layout.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
add_child(layout)
|
||
# Design coordinates remain proportional on every window size.
|
||
resized.connect(func(): layout.scale = size / Vector2(1600, 900))
|
||
layout.scale = size / Vector2(1600, 900)
|
||
var logo := caption("BLOCKLINE", Vector2(60, 264), 48, Color("eeeae2"))
|
||
logo.reparent(layout, false)
|
||
var bars := caption("III", Vector2(348, 259), 58, ORANGE)
|
||
bars.reparent(layout, false)
|
||
var subtitle := caption("RELAY DISTRICT / LOCAL OPERATIONS", Vector2(62, 322), 12)
|
||
subtitle.reparent(layout, false)
|
||
var strip := ColorRect.new()
|
||
strip.color = Color("a9ada6")
|
||
strip.position = Vector2(1106, 57)
|
||
strip.size = Vector2(420, 24)
|
||
layout.add_child(strip)
|
||
var roster := caption("1 SPIELER / 8 MAX.", Vector2(1114, 58), 15, Color("181917"))
|
||
roster.reparent(layout, false)
|
||
var nameplate := caption((str(ui.game.nickname) if ui != null else "OPERATOR") + "\n\nLOKALES NETZWERK", Vector2(1130, 97), 17, ORANGE)
|
||
nameplate.reparent(layout, false)
|
||
if loading:
|
||
status = Label.new()
|
||
progress = ProgressBar.new()
|
||
var heading := caption("EINSATZ WIRD VORBEREITET", Vector2(62, 420), 22, ORANGE)
|
||
heading.reparent(layout, false)
|
||
layout.add_child(status)
|
||
status.position = Vector2(62, 465)
|
||
status.size = Vector2(480, 90)
|
||
status.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||
status.add_theme_font_size_override("font_size", 17)
|
||
layout.add_child(progress)
|
||
progress.position = Vector2(62, 575)
|
||
progress.size = Vector2(430, 6)
|
||
progress.show_percentage = false
|
||
var fill := StyleBoxFlat.new()
|
||
fill.bg_color = ORANGE
|
||
progress.add_theme_stylebox_override("fill", fill)
|
||
var track := StyleBoxFlat.new()
|
||
track.bg_color = Color("34302a")
|
||
progress.add_theme_stylebox_override("background", track)
|
||
var count := caption("0 %", Vector2(62, 595), 14, ORANGE)
|
||
count.reparent(layout, false)
|
||
progress.value_changed.connect(func(value: float): count.text = "%02d %% / %d VON %d SCHRITTEN" % [int(progress.ratio * 100), int(value), int(progress.max_value)])
|
||
else:
|
||
var names := ["PLAY", "MULTIPLAYER", "LOADOUT", "OPERATOR", "SETTINGS", "QUIT"]
|
||
var actions: Array[Callable] = [ui.play_menu, ui.multiplayer_menu, ui.loadout_menu, ui.operator_menu, ui.settings_menu, func(): get_tree().quit()]
|
||
for index in names.size():
|
||
var button := Button.new()
|
||
button.text = names[index]
|
||
button.position = Vector2(62, 397 + index * 35)
|
||
button.size = Vector2(240, 32)
|
||
button.alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||
button.add_theme_font_size_override("font_size", 20)
|
||
for state: String in ["normal", "hover", "pressed", "focus"]:
|
||
var style := StyleBoxFlat.new()
|
||
style.bg_color = Color(0,0,0,0) if state == "normal" else ORANGE
|
||
style.content_margin_left = 9
|
||
button.add_theme_stylebox_override(state, style)
|
||
button.add_theme_color_override("font_hover_color", Color.BLACK)
|
||
button.add_theme_color_override("font_focus_color", Color.BLACK)
|
||
button.pressed.connect(actions[index])
|
||
button.mouse_entered.connect(button.grab_focus)
|
||
layout.add_child(button)
|
||
if index == 0: button.grab_focus()
|
||
var footer := caption("RESSOURCEN LADEN / BITTE WARTEN" if loading else "ENTER AUSWÄHLEN / MAUS NAVIGATION", Vector2(62, 854), 13)
|
||
footer.reparent(layout, false)
|
||
var party := caption("LOKALER EINSATZ\nPARTY: OFFEN", Vector2(62, 736), 15)
|
||
party.reparent(layout, false)
|
||
var build := caption("BLOCKLINE / RELAY DISTRICT LAN • 2–8", Vector2(1070, 854), 12)
|
||
build.reparent(layout, false)
|
||
|
||
func _process(dt: float) -> void:
|
||
preview.render_target_update_mode = SubViewport.UPDATE_ALWAYS if is_visible_in_tree() else SubViewport.UPDATE_DISABLED
|
||
if not is_visible_in_tree(): return
|
||
elapsed += dt
|
||
if is_instance_valid(actor): actor.preview("pro_rifle__idle", elapsed)
|
||
queue_redraw()
|
||
|
||
func _draw() -> void:
|
||
draw_line(Vector2(0, size.y * 0.93), Vector2(size.x, size.y * 0.93), Color(0.6,0.5,0.35,0.28))
|