godot-xterm/examples/menu/menu.gd
Leroy Hopson 2b3d4533c4
Change exit action for HTML5
Previously HTML5 exports would reload the page on exit. This commit
changes the behaviour to go back to the previous page (if any) or close
the tab and/or window if there is no previous page.
2024-03-29 19:35:14 +13:00

172 lines
4.5 KiB
GDScript

tool
extends Control
# This scene demonstrates how we can control the Terminal node directly by
# sending and receiving strings and ANSI escape sequences to the terminal
# directly.
# References:
# - https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
# - https://www.youtube.com/watch?v=jTSQlIK_92w
const TPut = preload("res://addons/godot_xterm/util/tput.gd")
# Title generated using command: toilet -f pagga GODOTXTERM
const TITLE = """
░█▀▀░█▀█░█▀▄░█▀█░▀█▀░█░█░▀█▀░█▀▀░█▀▄░█▄█\r
░█░█░█░█░█░█░█░█░░█░░▄▀▄░░█░░█▀▀░█▀▄░█░█\r
░▀▀▀░▀▀▀░▀▀░░▀▀▀░░▀░░▀░▀░░▀░░▀▀▀░▀░▀░▀░▀\r
"""
const TITLE_WIDTH = 42
var menu_items := [
{"name": "Asciicast", "scene": preload("../asciicast/asciicast.tscn")},
{
"name": "Terminal",
"scene":
(
preload("../web_console/web_console.tscn")
if OS.has_feature("JavaScript")
else preload("../terminal/terminal.tscn")
)
},
{"name": "Exit"}
]
var selected_index := 0
var row: int
var menu_start_row: int
var offset: int
onready var tput = TPut.new($Terminal)
func _ready():
if not $Terminal.is_connected("key_pressed", self, "_on_Terminal_key_pressed"):
# warning-ignore:return_value_discarded
$Terminal.connect("key_pressed", self, "_on_Terminal_key_pressed")
# warning-ignore:return_value_discarded
$Terminal.connect("size_changed", self, "draw_all")
$Terminal.grab_focus()
draw_all()
func draw_all(_size = Vector2.ZERO):
offset = int(floor(($Terminal.get_cols() / 2.0) - (TITLE_WIDTH / 2.0)))
tput.reset()
row = 5
tput.civis() # Hide the cursor.
draw_title()
draw_menu()
tput.sgr0()
row += 1
func draw_title():
tput.setaf(tput.ANSIColor.bright_yellow)
tput.cup(row, 0)
for line in TITLE.split("\r"):
row += 1
tput.cup(row, offset)
$Terminal.write(line)
tput.sgr0()
# Get the plugin version from the plugin's config file.
var config = ConfigFile.new()
var err = config.load("res://addons/godot_xterm/plugin.cfg")
if err == OK:
$Terminal.write("\n")
$Terminal.write("Version: %s" % config.get_value("plugin", "version", "unknown"))
row += 2
func draw_menu():
if not menu_start_row:
menu_start_row = row + 1
row = menu_start_row
var col_offset: int
for i in range(menu_items.size()):
row += 1
var item = menu_items[i]
if not col_offset:
col_offset = int(floor(($Terminal.get_cols() / 2) - (item.name.length() / 2)))
tput.cup(row, offset)
if selected_index == i:
tput.setab(tput.ANSIColor.red)
tput.setaf(tput.ANSIColor.black)
$Terminal.write("%s. %s" % [i + 1, item.name])
if selected_index == i:
tput.sgr0()
func _on_Terminal_key_pressed(data: String, event: InputEventKey) -> void:
match data:
tput.CURSOR_UP: # Up arrow key
selected_index = int(clamp(selected_index - 1, 0, menu_items.size() - 1))
draw_menu()
tput.CURSOR_DOWN: # Down arrow key
selected_index = int(clamp(selected_index + 1, 0, menu_items.size() - 1))
draw_menu()
"1":
selected_index = 0
draw_menu()
"2":
selected_index = 1
draw_menu()
"3":
selected_index = 2
draw_menu()
# We can also match against the raw InputEventKey.
if event.scancode == KEY_ENTER:
var item = menu_items[selected_index]
match item.name:
"Asciicast":
var scene = item.scene.instance()
var animation_player: AnimationPlayer = scene.get_node("AnimationPlayer")
scene.connect("key_pressed", self, "_on_Asciicast_key_pressed", [animation_player])
add_child(scene)
scene.grab_focus()
yield(animation_player, "animation_finished")
remove_child(scene)
$Terminal.grab_focus()
scene.queue_free()
"Terminal":
if OS.get_name() == "Windows":
return OS.call_deferred(
"alert",
(
"Psuedoterminal node currently"
+ " uses pty.h but needs to use either winpty or conpty"
+ " to work on Windows."
),
"Terminal not Supported on Windows"
)
var scene = item.scene.instance()
var pty = scene if OS.has_feature("JavaScript") else scene.get_node("PTY")
add_child(scene)
scene.grab_focus()
yield(pty, "exited")
$Terminal.grab_focus()
scene.queue_free()
"Exit":
if OS.has_feature("JavaScript"):
JavaScript.eval("window.history.back() || window.close()")
get_tree().quit()
func _on_Asciicast_key_pressed(
data: String, _event: InputEventKey, animation_player: AnimationPlayer
) -> void:
if data == "\u001b":
animation_player.emit_signal("animation_finished")