Files
Blockline/scripts/front_end.gd
T

181 lines
7.5 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 • 28", 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))