tangled
alpha
login
or
join now
soda.bsky.social
/
editor
Game / editor prototyping with Godot
0
fork
atom
overview
issues
pulls
pipelines
Compare changes
Choose any two refs to compare.
base:
master
main
no tags found
compare:
master
main
no tags found
go
+151
-13
4 changed files
expand all
collapse all
unified
split
.gitignore
scenes
Editor.tscn
scripts
editor.gd
editor.gd.uid
+1
.gitignore
···
1
# Godot 4+ specific ignores
2
.godot/
3
/android/
0
···
1
# Godot 4+ specific ignores
2
.godot/
3
/android/
4
+
qemu/
+28
-13
scenes/Editor.tscn
···
1
-
[gd_scene load_steps=2 format=3 uid="uid://dijojmon7te1k"]
2
0
3
[ext_resource type="FontFile" uid="uid://cpj11tjx6ifqg" path="res://fonts/monogram.ttf" id="1_ndpqs"]
4
5
-
[node name="Control" type="Control"]
0
0
6
layout_mode = 3
7
anchors_preset = 15
8
anchor_right = 1.0
9
anchor_bottom = 1.0
10
grow_horizontal = 2
11
grow_vertical = 2
0
0
0
12
13
[node name="CodeEdit" type="CodeEdit" parent="."]
14
layout_mode = 1
···
20
theme_override_fonts/font = ExtResource("1_ndpqs")
21
theme_override_font_sizes/font_size = 24
22
scroll_smooth = true
0
23
gutters_draw_breakpoints_gutter = true
24
gutters_draw_executing_lines = true
25
gutters_draw_line_numbers = true
26
indent_size = 2
27
indent_use_spaces = true
28
29
-
[node name="Step" type="Button" parent="CodeEdit"]
30
layout_mode = 0
31
-
offset_left = 1008.0
32
-
offset_top = 592.0
33
offset_right = 1132.0
34
-
offset_bottom = 631.0
0
0
0
0
0
0
0
35
theme_override_font_sizes/font_size = 24
36
-
text = "Step"
37
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
44
theme_override_font_sizes/font_size = 24
45
text = "Stop
46
"
0
0
0
0
0
···
1
+
[gd_scene load_steps=4 format=3 uid="uid://dijojmon7te1k"]
2
3
+
[ext_resource type="Script" uid="uid://djfeg1nlxsdad" path="res://scripts/editor.gd" id="1_3kl07"]
4
[ext_resource type="FontFile" uid="uid://cpj11tjx6ifqg" path="res://fonts/monogram.ttf" id="1_ndpqs"]
5
6
+
[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_3kl07"]
7
+
8
+
[node name="Control" type="Control" node_paths=PackedStringArray("run_button", "code_edit")]
9
layout_mode = 3
10
anchors_preset = 15
11
anchor_right = 1.0
12
anchor_bottom = 1.0
13
grow_horizontal = 2
14
grow_vertical = 2
15
+
script = ExtResource("1_3kl07")
16
+
run_button = NodePath("CodeEdit/FoldableContainer/VBoxContainer/Run")
17
+
code_edit = NodePath("CodeEdit")
18
19
[node name="CodeEdit" type="CodeEdit" parent="."]
20
layout_mode = 1
···
26
theme_override_fonts/font = ExtResource("1_ndpqs")
27
theme_override_font_sizes/font_size = 24
28
scroll_smooth = true
29
+
syntax_highlighter = SubResource("SyntaxHighlighter_3kl07")
30
gutters_draw_breakpoints_gutter = true
31
gutters_draw_executing_lines = true
32
gutters_draw_line_numbers = true
33
indent_size = 2
34
indent_use_spaces = true
35
36
+
[node name="FoldableContainer" type="FoldableContainer" parent="CodeEdit"]
37
layout_mode = 0
38
+
offset_left = 963.0
39
+
offset_top = 12.0
40
offset_right = 1132.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
49
theme_override_font_sizes/font_size = 24
50
+
text = "Run"
51
52
+
[node name="Stop" type="Button" parent="CodeEdit/FoldableContainer/VBoxContainer"]
53
+
layout_mode = 2
0
0
0
0
54
theme_override_font_sizes/font_size = 24
55
text = "Stop
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
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
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
···
0
···
1
+
uid://djfeg1nlxsdad