Game / editor prototyping with Godot

Compare changes

Choose any two refs to compare.

+151 -13
+1
.gitignore
··· 1 1 # Godot 4+ specific ignores 2 2 .godot/ 3 3 /android/ 4 + qemu/
+28 -13
scenes/Editor.tscn
··· 1 - [gd_scene load_steps=2 format=3 uid="uid://dijojmon7te1k"] 1 + [gd_scene load_steps=4 format=3 uid="uid://dijojmon7te1k"] 2 2 3 + [ext_resource type="Script" uid="uid://djfeg1nlxsdad" path="res://scripts/editor.gd" id="1_3kl07"] 3 4 [ext_resource type="FontFile" uid="uid://cpj11tjx6ifqg" path="res://fonts/monogram.ttf" id="1_ndpqs"] 4 5 5 - [node name="Control" type="Control"] 6 + [sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_3kl07"] 7 + 8 + [node name="Control" type="Control" node_paths=PackedStringArray("run_button", "code_edit")] 6 9 layout_mode = 3 7 10 anchors_preset = 15 8 11 anchor_right = 1.0 9 12 anchor_bottom = 1.0 10 13 grow_horizontal = 2 11 14 grow_vertical = 2 15 + script = ExtResource("1_3kl07") 16 + run_button = NodePath("CodeEdit/FoldableContainer/VBoxContainer/Run") 17 + code_edit = NodePath("CodeEdit") 12 18 13 19 [node name="CodeEdit" type="CodeEdit" parent="."] 14 20 layout_mode = 1 ··· 20 26 theme_override_fonts/font = ExtResource("1_ndpqs") 21 27 theme_override_font_sizes/font_size = 24 22 28 scroll_smooth = true 29 + syntax_highlighter = SubResource("SyntaxHighlighter_3kl07") 23 30 gutters_draw_breakpoints_gutter = true 24 31 gutters_draw_executing_lines = true 25 32 gutters_draw_line_numbers = true 26 33 indent_size = 2 27 34 indent_use_spaces = true 28 35 29 - [node name="Step" type="Button" parent="CodeEdit"] 36 + [node name="FoldableContainer" type="FoldableContainer" parent="CodeEdit"] 30 37 layout_mode = 0 31 - offset_left = 1008.0 32 - offset_top = 592.0 38 + offset_left = 963.0 39 + offset_top = 12.0 33 40 offset_right = 1132.0 34 - offset_bottom = 631.0 41 + offset_bottom = 104.0 42 + title = "Commands" 43 + 44 + [node name="VBoxContainer" type="VBoxContainer" parent="CodeEdit/FoldableContainer"] 45 + layout_mode = 2 46 + 47 + [node name="Run" type="Button" parent="CodeEdit/FoldableContainer/VBoxContainer"] 48 + layout_mode = 2 35 49 theme_override_font_sizes/font_size = 24 36 - text = "Step" 50 + text = "Run" 37 51 38 - [node name="Stop" type="Button" parent="CodeEdit"] 39 - layout_mode = 0 40 - offset_left = 875.0 41 - offset_top = 592.0 42 - offset_right = 999.0 43 - offset_bottom = 631.0 52 + [node name="Stop" type="Button" parent="CodeEdit/FoldableContainer/VBoxContainer"] 53 + layout_mode = 2 44 54 theme_override_font_sizes/font_size = 24 45 55 text = "Stop 46 56 " 57 + 58 + [node name="Edit" type="Button" parent="CodeEdit/FoldableContainer/VBoxContainer"] 59 + layout_mode = 2 60 + theme_override_font_sizes/font_size = 24 61 + text = "Edit Flags"
+121
scripts/editor.gd
··· 1 + # QEMURunner.gd 2 + # Alpine Linux ARM64 QEMU Runner as a Node 3 + # Add to your scene and call run_vm() 4 + 5 + extends Node 6 + 7 + # Configuration 8 + const ALP_ARCH = "aarch64" 9 + const PORT = "2221" 10 + var DISK_NAME = "alpine.%s.qcow2" % ALP_ARCH 11 + 12 + # Working directory - qemu/ folder in project root 13 + var working_dir: String = "" 14 + 15 + @export var run_button: Button 16 + @export var code_edit: CodeEdit 17 + 18 + signal vm_started() 19 + signal vm_stopped(exit_code: int) 20 + signal vm_error(error_message: String) 21 + 22 + var qemu_pid: int = -1 23 + 24 + func handle_run(): 25 + print(code_edit.text) 26 + 27 + func _ready(): 28 + # Set working directory to PROJECT_ROOT/qemu/ 29 + working_dir = ProjectSettings.globalize_path("res://qemu/") 30 + print("QEMU working directory: %s" % working_dir) 31 + 32 + # Create qemu directory if it doesn't exist 33 + if not DirAccess.dir_exists_absolute(working_dir): 34 + DirAccess.make_dir_recursive_absolute(working_dir) 35 + print("Created qemu directory: %s" % working_dir) 36 + 37 + run_vm() 38 + 39 + run_button.button_up.connect(handle_run) 40 + 41 + func _exit_tree() -> void: 42 + stop_vm() 43 + 44 + func check_file_exists(filename: String) -> bool: 45 + """Check if required file exists in working directory""" 46 + var full_path = working_dir.path_join(filename) 47 + print(full_path) 48 + if not FileAccess.file_exists(full_path): 49 + print("Error: %s not found!" % full_path) 50 + return false 51 + return true 52 + 53 + func run_vm(): 54 + print("Alpine Linux ARM64 QEMU Runner") 55 + print() 56 + 57 + # Check required files 58 + var required_files = [ 59 + "AAVMF_CODE.fd", 60 + DISK_NAME 61 + ] 62 + 63 + var missing_files = [] 64 + for file in required_files: 65 + if not check_file_exists(file): 66 + missing_files.append(file) 67 + 68 + if not missing_files.is_empty(): 69 + print("\nMissing required files:") 70 + for file in missing_files: 71 + print(" - %s" % file) 72 + print("\nPlease run the setup script first to create these files.") 73 + vm_error.emit("Missing required files: " + str(missing_files)) 74 + return 75 + 76 + # Display connection info 77 + print("Starting Alpine Linux VM...") 78 + print("SSH Port: %s" % PORT) 79 + print("Connect with: ssh -p %s <username>@localhost" % PORT) 80 + print() 81 + print("To exit QEMU: Press Ctrl+A then X") 82 + print() 83 + 84 + # Build QEMU command 85 + var qemu_cmd = PackedStringArray([ 86 + "qemu-system-aarch64", 87 + "-accel", "tcg,thread=multi", 88 + "-machine", "virt", 89 + "-cpu", "cortex-a53", 90 + "-smp", "cores=1", 91 + "-m", "512", 92 + "-bios", working_dir.path_join("AAVMF_CODE.fd"), 93 + "-nographic", 94 + "-drive", "if=virtio,id=hd,format=qcow2,file=%s" % working_dir.path_join(DISK_NAME), 95 + "-nic", "user,hostfwd=tcp::%s-:22,model=virtio" % PORT, 96 + "-device", "virtio-rng-pci", 97 + "-rtc", "base=utc,clock=host", 98 + "-s" 99 + ]) 100 + 101 + # Run QEMU 102 + vm_started.emit() 103 + 104 + qemu_pid = OS.create_process(qemu_cmd[0], qemu_cmd.slice(1)) 105 + 106 + if qemu_pid == -1: 107 + print("\nError: qemu-system-aarch64 not found in PATH") 108 + print("Please install QEMU for Windows: https://qemu.weilnetz.de/w64/") 109 + print("Make sure qemu-system-aarch64 is in your system PATH") 110 + vm_error.emit("Failed to start QEMU process") 111 + return 112 + 113 + print("QEMU started with PID: %d" % qemu_pid) 114 + 115 + func stop_vm(): 116 + print("Attempting to kill QEMU") 117 + if qemu_pid != -1: 118 + OS.kill(qemu_pid) 119 + print("QEMU stopped") 120 + vm_stopped.emit(0) 121 + qemu_pid = -1
+1
scripts/editor.gd.uid
··· 1 + uid://djfeg1nlxsdad